| 1 | /* |
| 2 | * |
| 3 | * Copyright (c) 2015 Linaro Limited |
| 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify it |
| 6 | * under the terms and conditions of the GNU General Public License, |
| 7 | * version 2 or later, as published by the Free Software Foundation. |
| 8 | * |
| 9 | * This program is distributed in the hope it will be useful, but WITHOUT |
| 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| 12 | * more details. |
| 13 | * |
| 14 | * You should have received a copy of the GNU General Public License along with |
| 15 | * this program. If not, see <http://www.gnu.org/licenses/>. |
| 16 | * |
| 17 | * Emulate a virtual board which works by passing Linux all the information |
| 18 | * it needs about what devices are present via the device tree. |
| 19 | * There are some restrictions about what we can do here: |
| 20 | * + we can only present devices whose Linux drivers will work based |
| 21 | * purely on the device tree with no platform data at all |
| 22 | * + we want to present a very stripped-down minimalist platform, |
| 23 | * both because this reduces the security attack surface from the guest |
| 24 | * and also because it reduces our exposure to being broken when |
| 25 | * the kernel updates its device tree bindings and requires further |
| 26 | * information in a device binding that we aren't providing. |
| 27 | * This is essentially the same approach kvmtool uses. |
| 28 | */ |
| 29 | |
| 30 | #ifndef QEMU_ARM_VIRT_H |
| 31 | #define QEMU_ARM_VIRT_H |
| 32 | |
| 33 | #include "exec/hwaddr.h" |
| 34 | #include "qemu/notify.h" |
| 35 | #include "hw/core/boards.h" |
| 36 | #include "hw/acpi/ghes.h" |
| 37 | #include "hw/arm/boot.h" |
| 38 | #include "hw/arm/bsa.h" |
| 39 | #include "hw/block/flash.h" |
| 40 | #include "hw/cxl/cxl.h" |
| 41 | #include "system/kvm.h" |
| 42 | #include "hw/intc/arm_gicv3_common.h" |
| 43 | #include "qom/object.h" |
| 44 | #include "hw/core/cpu.h" |
| 45 | |
| 46 | #define NUM_GICV2M_SPIS 64 |
| 47 | #define NUM_VIRTIO_TRANSPORTS 32 |
| 48 | #define NUM_SMMU_IRQS 4 |
| 49 | |
| 50 | /* See Linux kernel arch/arm64/include/asm/pvclock-abi.h */ |
| 51 | #define PVTIME_SIZE_PER_CPU 64 |
| 52 | |
| 53 | /* GPIO pins */ |
| 54 | #define GPIO_PIN_POWER_BUTTON 3 |
| 55 | |
| 56 | #define CPU_MAX_CACHES 16 |
| 57 | |
| 58 | enum { |
| 59 | VIRT_FLASH, |
| 60 | VIRT_MEM, |
| 61 | VIRT_CPUPERIPHS, |
| 62 | VIRT_GIC_DIST, |
| 63 | VIRT_GIC_CPU, |
| 64 | VIRT_GIC_V2M, |
| 65 | VIRT_GIC_HYP, |
| 66 | VIRT_GIC_VCPU, |
| 67 | VIRT_GIC_ITS, |
| 68 | VIRT_GIC_REDIST, |
| 69 | VIRT_GICV5_IRS_S, |
| 70 | VIRT_GICV5_IRS_NS, |
| 71 | VIRT_GICV5_IRS_EL3, |
| 72 | VIRT_GICV5_IRS_REALM, |
| 73 | VIRT_GICV5_ITS_S, |
| 74 | VIRT_GICV5_ITS_NS, |
| 75 | VIRT_GICV5_ITS_EL3, |
| 76 | VIRT_GICV5_ITS_REALM, |
| 77 | VIRT_GICV5_ITS_TR_S, |
| 78 | VIRT_GICV5_ITS_TR_NS, |
| 79 | VIRT_GICV5_ITS_TR_EL3, |
| 80 | VIRT_GICV5_ITS_TR_REALM, |
| 81 | VIRT_SMMU, |
| 82 | VIRT_UART0, |
| 83 | VIRT_MMIO, |
| 84 | VIRT_RTC, |
| 85 | VIRT_FW_CFG, |
| 86 | VIRT_PCIE, |
| 87 | VIRT_PCIE_MMIO, |
| 88 | VIRT_PCIE_PIO, |
| 89 | VIRT_PCIE_ECAM, |
| 90 | VIRT_PLATFORM_BUS, |
| 91 | VIRT_GPIO, |
| 92 | VIRT_UART1, |
| 93 | VIRT_SECURE_MEM, |
| 94 | VIRT_SECURE_GPIO, |
| 95 | VIRT_PCDIMM_ACPI, |
| 96 | VIRT_ACPI_GED, |
| 97 | VIRT_NVDIMM_ACPI, |
| 98 | VIRT_PVTIME, |
| 99 | VIRT_ACPI_PCIHP, |
| 100 | VIRT_GWDT_WS0, |
| 101 | VIRT_GWDT_REFRESH, |
| 102 | VIRT_GWDT_CONTROL, |
| 103 | VIRT_LOWMEMMAP_LAST, |
| 104 | }; |
| 105 | |
| 106 | /* indices of IO regions located after the RAM */ |
| 107 | enum { |
| 108 | VIRT_HIGH_GIC_REDIST2 = VIRT_LOWMEMMAP_LAST, |
| 109 | VIRT_CXL_HOST, |
| 110 | VIRT_HIGH_PCIE_ECAM, |
| 111 | VIRT_HIGH_PCIE_MMIO, |
| 112 | }; |
| 113 | |
| 114 | typedef enum VirtIOMMUType { |
| 115 | VIRT_IOMMU_NONE, |
| 116 | VIRT_IOMMU_SMMUV3, |
| 117 | VIRT_IOMMU_VIRTIO, |
| 118 | } VirtIOMMUType; |
| 119 | |
| 120 | typedef enum VirtMSIControllerType { |
| 121 | VIRT_MSI_CTRL_NONE, |
| 122 | /* This value is overridden at runtime.*/ |
| 123 | VIRT_MSI_CTRL_AUTO, |
| 124 | /* Legacy option: its=off provides a GICv2m when using GICv2 */ |
| 125 | VIRT_MSI_LEGACY_OPT_ITS_OFF, |
| 126 | VIRT_MSI_CTRL_GICV2M, |
| 127 | VIRT_MSI_CTRL_ITS, |
| 128 | } VirtMSIControllerType; |
| 129 | |
| 130 | typedef enum VirtGICType { |
| 131 | VIRT_GIC_VERSION_MAX = 0, |
| 132 | VIRT_GIC_VERSION_HOST = 1, |
| 133 | /* The concrete GIC values have to match the GIC version number */ |
| 134 | VIRT_GIC_VERSION_2 = 2, |
| 135 | VIRT_GIC_VERSION_3 = 3, |
| 136 | VIRT_GIC_VERSION_4 = 4, |
| 137 | VIRT_GIC_VERSION_5 = 5, |
| 138 | VIRT_GIC_VERSION_NOSEL, |
| 139 | } VirtGICType; |
| 140 | |
| 141 | #define VIRT_GIC_VERSION_2_MASK BIT(VIRT_GIC_VERSION_2) |
| 142 | #define VIRT_GIC_VERSION_3_MASK BIT(VIRT_GIC_VERSION_3) |
| 143 | #define VIRT_GIC_VERSION_4_MASK BIT(VIRT_GIC_VERSION_4) |
| 144 | #define VIRT_GIC_VERSION_5_MASK BIT(VIRT_GIC_VERSION_5) |
| 145 | |
| 146 | struct VirtMachineClass { |
| 147 | MachineClass parent; |
| 148 | bool no_tcg_its; |
| 149 | bool no_highmem_compact; |
| 150 | bool no_kvm_steal_time; |
| 151 | bool acpi_expose_flash; |
| 152 | bool no_secure_gpio; |
| 153 | /* Machines < 6.2 have no support for describing cpu topology to guest */ |
| 154 | bool no_cpu_topology; |
| 155 | bool no_tcg_lpa2; |
| 156 | bool no_ns_el2_virt_timer_irq; |
| 157 | bool no_nested_smmu; |
| 158 | /* HVF specific: support for kernel-irqchip=on introduced in QEMU 11.1 */ |
| 159 | bool hvf_no_kernel_irqchip_default; |
| 160 | }; |
| 161 | |
| 162 | struct VirtMachineState { |
| 163 | MachineState parent; |
| 164 | Notifier machine_done; |
| 165 | DeviceState *platform_bus_dev; |
| 166 | FWCfgState *fw_cfg; |
| 167 | PFlashCFI01 *flash[2]; |
| 168 | bool secure; |
| 169 | bool highmem; |
| 170 | bool highmem_compact; |
| 171 | bool highmem_cxl; |
| 172 | bool highmem_ecam; |
| 173 | bool highmem_mmio; |
| 174 | bool highmem_redists; |
| 175 | bool tcg_its; |
| 176 | bool virt; |
| 177 | bool ras; |
| 178 | bool mte; |
| 179 | bool dtb_randomness; |
| 180 | bool second_ns_uart_present; |
| 181 | OnOffAuto acpi; |
| 182 | VirtGICType gic_version; |
| 183 | VirtIOMMUType iommu; |
| 184 | bool default_bus_bypass_iommu; |
| 185 | VirtMSIControllerType msi_controller; |
| 186 | uint16_t virtio_iommu_bdf; |
| 187 | struct arm_boot_info bootinfo; |
| 188 | MemMapEntry *memmap; |
| 189 | char *pciehb_nodename; |
| 190 | const int *irqmap; |
| 191 | int fdt_size; |
| 192 | uint32_t clock_phandle; |
| 193 | uint32_t gic_phandle; |
| 194 | uint32_t msi_phandle; |
| 195 | uint32_t iommu_phandle; |
| 196 | uint32_t *cpu_phandles; |
| 197 | int psci_conduit; |
| 198 | uint8_t virtio_transports; |
| 199 | hwaddr highest_gpa; |
| 200 | DeviceState *gic; |
| 201 | DeviceState *acpi_dev; |
| 202 | Notifier powerdown_notifier; |
| 203 | Notifier generic_error_notifier; |
| 204 | PCIBus *bus; |
| 205 | char *oem_id; |
| 206 | char *oem_table_id; |
| 207 | bool ns_el2_virt_timer_irq; |
| 208 | CXLState cxl_devices_state; |
| 209 | bool legacy_smmuv3_present; |
| 210 | MemoryRegion *sysmem; |
| 211 | MemoryRegion *secure_sysmem; |
| 212 | bool pci_preserve_config; |
| 213 | GPtrArray *smmuv3_devices; |
| 214 | }; |
| 215 | |
| 216 | #define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : VIRT_PCIE_ECAM) |
| 217 | |
| 218 | #define TYPE_VIRT_MACHINE MACHINE_TYPE_NAME("virt") |
| 219 | OBJECT_DECLARE_TYPE(VirtMachineState, VirtMachineClass, VIRT_MACHINE) |
| 220 | |
| 221 | void virt_acpi_setup(VirtMachineState *vms); |
| 222 | bool virt_is_acpi_enabled(const VirtMachineState *vms); |
| 223 | |
| 224 | #define CLIDR_CTYPE_NO_CACHE 0x00 |
| 225 | #define CLIDR_CTYPE_I_CACHE 0x01 |
| 226 | #define CLIDR_CTYPE_D_CACHE 0x02 |
| 227 | #define CLIDR_CTYPE_SEPARATE_I_D_CACHES 0x03 |
| 228 | #define CLIDR_CTYPE_UNIFIED_CACHE 0x04 |
| 229 | #define CLIDR_CTYPE_MAX_CACHE_LEVEL 7 |
| 230 | |
| 231 | unsigned int virt_get_caches(const VirtMachineState *vms, |
| 232 | CPUCoreCaches *caches); |
| 233 | void set_cpu_cache(CPUCoreCaches *cpu_cache, enum CacheType cache_type, |
| 234 | int cache_level, bool is_i_cache); |
| 235 | |
| 236 | /* Return number of redistributors that fit in the specified region */ |
| 237 | static uint32_t virt_redist_capacity(VirtMachineState *vms, int region) |
| 238 | { |
| 239 | uint32_t redist_size; |
| 240 | |
| 241 | if (vms->gic_version == VIRT_GIC_VERSION_3) { |
| 242 | redist_size = GICV3_REDIST_SIZE; |
| 243 | } else { |
| 244 | redist_size = GICV4_REDIST_SIZE; |
| 245 | } |
| 246 | return vms->memmap[region].size / redist_size; |
| 247 | } |
| 248 | |
| 249 | /* Return the number of used redistributor regions */ |
| 250 | static inline int virt_gicv3_redist_region_count(VirtMachineState *vms) |
| 251 | { |
| 252 | uint32_t redist0_capacity = virt_redist_capacity(vms, VIRT_GIC_REDIST); |
| 253 | |
| 254 | assert(vms->gic_version != VIRT_GIC_VERSION_2); |
| 255 | |
| 256 | return (MACHINE(vms)->smp.cpus > redist0_capacity && |
| 257 | vms->highmem_redists) ? 2 : 1; |
| 258 | } |
| 259 | |
| 260 | #endif /* QEMU_ARM_VIRT_H */ |