summaryrefslogtreecommitdiffstats
path: root/hw/arm/virt.c
diff options
context:
space:
mode:
authorPeter Maydell2018-06-22 17:03:31 +0200
committerPeter Maydell2018-06-22 17:03:31 +0200
commit5fce31220003bbe1b4c7faa0dbf92d131b0a413b (patch)
tree2a7aff159e9ce1f120b691a17d8a9f8a25ab1441 /hw/arm/virt.c
parentMerge remote-tracking branch 'remotes/dgibson/tags/ppc-for-3.0-20180622' into... (diff)
parentxen: Don't use memory_region_init_ram_nomigrate() in pci_assign_dev_load_opti... (diff)
downloadqemu-5fce31220003bbe1b4c7faa0dbf92d131b0a413b.tar.gz
qemu-5fce31220003bbe1b4c7faa0dbf92d131b0a413b.tar.xz
qemu-5fce31220003bbe1b4c7faa0dbf92d131b0a413b.zip
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20180622' into staging
target-arm queue: * hw/intc/arm_gicv3: fix wrong values when reading IPRIORITYR * target/arm: fix read of freed memory in kvm_arm_machine_init_done() * virt: support up to 512 CPUs * virt: support 256MB ECAM PCI region (for more PCI devices) * xlnx-zynqmp: Use Cortex-R5F, not Cortex-R5 * mps2-tz: Implement and use the TrustZone Memory Protection Controller * target/arm: enforce alignment checking for v6M cores * xen: Don't use memory_region_init_ram_nomigrate() in pci_assign_dev_load_option_rom() * vl.c: Don't zero-initialize statics for serial_hds # gpg: Signature made Fri 22 Jun 2018 13:56:00 BST # gpg: using RSA key 3C2525ED14360CDE # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" # gpg: aka "Peter Maydell <pmaydell@gmail.com>" # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * remotes/pmaydell/tags/pull-target-arm-20180622: (28 commits) xen: Don't use memory_region_init_ram_nomigrate() in pci_assign_dev_load_option_rom() vl.c: Don't zero-initialize statics for serial_hds target/arm: Strict alignment for ARMv6-M and ARMv8-M Baseline target/arm: Introduce ARM_FEATURE_M_MAIN hw/arm/mps2-tz.c: Instantiate MPCs hw/arm/iotkit: Wire up MPC interrupt lines hw/arm/iotkit: Instantiate MPC hw/misc/iotkit-secctl.c: Implement SECMPCINTSTATUS hw/misc/tz_mpc.c: Honour the BLK_LUT settings in translate hw/misc/tz-mpc.c: Implement correct blocked-access behaviour hw/misc/tz-mpc.c: Implement registers hw/misc/tz-mpc.c: Implement the Arm TrustZone Memory Protection Controller xlnx-zynqmp: Swap Cortex-R5 for Cortex-R5F target-arm: Add the Cortex-R5F hw/arm/virt: Increase max_cpus to 512 hw/arm/virt: Use 256MB ECAM region by default hw/arm/virt: Add virt-3.0 machine type hw/arm/virt: Add a new 256MB ECAM region hw/arm/virt: Register two redistributor regions when necessary hw/arm/virt-acpi-build: Advertise one or two GICR structures ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/arm/virt.c')
-rw-r--r--hw/arm/virt.c100
1 files changed, 85 insertions, 15 deletions
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 98b99cf236..742f68afca 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -149,6 +149,9 @@ static const MemMapEntry a15memmap[] = {
[VIRT_PCIE_PIO] = { 0x3eff0000, 0x00010000 },
[VIRT_PCIE_ECAM] = { 0x3f000000, 0x01000000 },
[VIRT_MEM] = { 0x40000000, RAMLIMIT_BYTES },
+ /* Additional 64 MB redist region (can contain up to 512 redistributors) */
+ [VIRT_GIC_REDIST2] = { 0x4000000000ULL, 0x4000000 },
+ [VIRT_PCIE_ECAM_HIGH] = { 0x4010000000ULL, 0x10000000 },
/* Second PCIe window, 512GB wide at the 512GB boundary */
[VIRT_PCIE_MMIO_HIGH] = { 0x8000000000ULL, 0x8000000000ULL },
};
@@ -402,13 +405,30 @@ static void fdt_add_gic_node(VirtMachineState *vms)
qemu_fdt_setprop_cell(vms->fdt, "/intc", "#size-cells", 0x2);
qemu_fdt_setprop(vms->fdt, "/intc", "ranges", NULL, 0);
if (vms->gic_version == 3) {
+ int nb_redist_regions = virt_gicv3_redist_region_count(vms);
+
qemu_fdt_setprop_string(vms->fdt, "/intc", "compatible",
"arm,gic-v3");
- qemu_fdt_setprop_sized_cells(vms->fdt, "/intc", "reg",
- 2, vms->memmap[VIRT_GIC_DIST].base,
- 2, vms->memmap[VIRT_GIC_DIST].size,
- 2, vms->memmap[VIRT_GIC_REDIST].base,
- 2, vms->memmap[VIRT_GIC_REDIST].size);
+
+ qemu_fdt_setprop_cell(vms->fdt, "/intc",
+ "#redistributor-regions", nb_redist_regions);
+
+ if (nb_redist_regions == 1) {
+ qemu_fdt_setprop_sized_cells(vms->fdt, "/intc", "reg",
+ 2, vms->memmap[VIRT_GIC_DIST].base,
+ 2, vms->memmap[VIRT_GIC_DIST].size,
+ 2, vms->memmap[VIRT_GIC_REDIST].base,
+ 2, vms->memmap[VIRT_GIC_REDIST].size);
+ } else {
+ qemu_fdt_setprop_sized_cells(vms->fdt, "/intc", "reg",
+ 2, vms->memmap[VIRT_GIC_DIST].base,
+ 2, vms->memmap[VIRT_GIC_DIST].size,
+ 2, vms->memmap[VIRT_GIC_REDIST].base,
+ 2, vms->memmap[VIRT_GIC_REDIST].size,
+ 2, vms->memmap[VIRT_GIC_REDIST2].base,
+ 2, vms->memmap[VIRT_GIC_REDIST2].size);
+ }
+
if (vms->virt) {
qemu_fdt_setprop_cells(vms->fdt, "/intc", "interrupts",
GIC_FDT_IRQ_TYPE_PPI, ARCH_GICV3_MAINT_IRQ,
@@ -510,6 +530,7 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
SysBusDevice *gicbusdev;
const char *gictype;
int type = vms->gic_version, i;
+ uint32_t nb_redist_regions = 0;
gictype = (type == 3) ? gicv3_class_name() : gic_class_name();
@@ -523,11 +544,34 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
if (!kvm_irqchip_in_kernel()) {
qdev_prop_set_bit(gicdev, "has-security-extensions", vms->secure);
}
+
+ if (type == 3) {
+ uint32_t redist0_capacity =
+ vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
+ uint32_t redist0_count = MIN(smp_cpus, redist0_capacity);
+
+ nb_redist_regions = virt_gicv3_redist_region_count(vms);
+
+ qdev_prop_set_uint32(gicdev, "len-redist-region-count",
+ nb_redist_regions);
+ qdev_prop_set_uint32(gicdev, "redist-region-count[0]", redist0_count);
+
+ if (nb_redist_regions == 2) {
+ uint32_t redist1_capacity =
+ vms->memmap[VIRT_GIC_REDIST2].size / GICV3_REDIST_SIZE;
+
+ qdev_prop_set_uint32(gicdev, "redist-region-count[1]",
+ MIN(smp_cpus - redist0_count, redist1_capacity));
+ }
+ }
qdev_init_nofail(gicdev);
gicbusdev = SYS_BUS_DEVICE(gicdev);
sysbus_mmio_map(gicbusdev, 0, vms->memmap[VIRT_GIC_DIST].base);
if (type == 3) {
sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_REDIST].base);
+ if (nb_redist_regions == 2) {
+ sysbus_mmio_map(gicbusdev, 2, vms->memmap[VIRT_GIC_REDIST2].base);
+ }
} else {
sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_CPU].base);
}
@@ -1001,10 +1045,9 @@ static void create_pcie(VirtMachineState *vms, qemu_irq *pic)
hwaddr size_mmio_high = vms->memmap[VIRT_PCIE_MMIO_HIGH].size;
hwaddr base_pio = vms->memmap[VIRT_PCIE_PIO].base;
hwaddr size_pio = vms->memmap[VIRT_PCIE_PIO].size;
- hwaddr base_ecam = vms->memmap[VIRT_PCIE_ECAM].base;
- hwaddr size_ecam = vms->memmap[VIRT_PCIE_ECAM].size;
+ hwaddr base_ecam, size_ecam;
hwaddr base = base_mmio;
- int nr_pcie_buses = size_ecam / PCIE_MMCFG_SIZE_MIN;
+ int nr_pcie_buses;
int irq = vms->irqmap[VIRT_PCIE];
MemoryRegion *mmio_alias;
MemoryRegion *mmio_reg;
@@ -1012,12 +1055,16 @@ static void create_pcie(VirtMachineState *vms, qemu_irq *pic)
MemoryRegion *ecam_reg;
DeviceState *dev;
char *nodename;
- int i;
+ int i, ecam_id;
PCIHostState *pci;
dev = qdev_create(NULL, TYPE_GPEX_HOST);
qdev_init_nofail(dev);
+ ecam_id = VIRT_ECAM_ID(vms->highmem_ecam);
+ base_ecam = vms->memmap[ecam_id].base;
+ size_ecam = vms->memmap[ecam_id].size;
+ nr_pcie_buses = size_ecam / PCIE_MMCFG_SIZE_MIN;
/* Map only the first size_ecam bytes of ECAM space */
ecam_alias = g_new0(MemoryRegion, 1);
ecam_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
@@ -1271,6 +1318,7 @@ static void machvirt_init(MachineState *machine)
int n, virt_max_cpus;
MemoryRegion *ram = g_new(MemoryRegion, 1);
bool firmware_loaded = bios_name || drive_get(IF_PFLASH, 0, 0);
+ bool aarch64 = true;
/* We can probe only here because during property set
* KVM is not available yet
@@ -1322,7 +1370,8 @@ static void machvirt_init(MachineState *machine)
* many redistributors we can fit into the memory map.
*/
if (vms->gic_version == 3) {
- virt_max_cpus = vms->memmap[VIRT_GIC_REDIST].size / 0x20000;
+ virt_max_cpus = vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
+ virt_max_cpus += vms->memmap[VIRT_GIC_REDIST2].size / GICV3_REDIST_SIZE;
} else {
virt_max_cpus = GIC_NCPU;
}
@@ -1385,6 +1434,8 @@ static void machvirt_init(MachineState *machine)
numa_cpu_pre_plug(&possible_cpus->cpus[cs->cpu_index], DEVICE(cpuobj),
&error_fatal);
+ aarch64 &= object_property_get_bool(cpuobj, "aarch64", NULL);
+
if (!vms->secure) {
object_property_set_bool(cpuobj, false, "has_el3", NULL);
}
@@ -1443,6 +1494,8 @@ static void machvirt_init(MachineState *machine)
create_uart(vms, pic, VIRT_SECURE_UART, secure_sysmem, serial_hd(1));
}
+ vms->highmem_ecam &= vms->highmem && (!firmware_loaded || aarch64);
+
create_rtc(vms, pic);
create_pcie(vms, pic);
@@ -1653,11 +1706,11 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
mc->init = machvirt_init;
- /* Start max_cpus at the maximum QEMU supports. We'll further restrict
- * it later in machvirt_init, where we have more information about the
+ /* Start with max_cpus set to 512, which is the maximum supported by KVM.
+ * The value may be reduced later when we have more information about the
* configuration of the particular instance.
*/
- mc->max_cpus = 255;
+ mc->max_cpus = 512;
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_CALXEDA_XGMAC);
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_AMD_XGBE);
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
@@ -1697,7 +1750,7 @@ type_init(machvirt_machine_init);
#define VIRT_COMPAT_2_12 \
HW_COMPAT_2_12
-static void virt_2_12_instance_init(Object *obj)
+static void virt_3_0_instance_init(Object *obj)
{
VirtMachineState *vms = VIRT_MACHINE(obj);
VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
@@ -1740,6 +1793,8 @@ static void virt_2_12_instance_init(Object *obj)
"Set GIC version. "
"Valid values are 2, 3 and host", NULL);
+ vms->highmem_ecam = !vmc->no_highmem_ecam;
+
if (vmc->no_its) {
vms->its = false;
} else {
@@ -1765,11 +1820,26 @@ static void virt_2_12_instance_init(Object *obj)
vms->irqmap = a15irqmap;
}
+static void virt_machine_3_0_options(MachineClass *mc)
+{
+}
+DEFINE_VIRT_MACHINE_AS_LATEST(3, 0)
+
+static void virt_2_12_instance_init(Object *obj)
+{
+ virt_3_0_instance_init(obj);
+}
+
static void virt_machine_2_12_options(MachineClass *mc)
{
+ VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
+
+ virt_machine_3_0_options(mc);
SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_12);
+ vmc->no_highmem_ecam = true;
+ mc->max_cpus = 255;
}
-DEFINE_VIRT_MACHINE_AS_LATEST(2, 12)
+DEFINE_VIRT_MACHINE(2, 12)
#define VIRT_COMPAT_2_11 \
HW_COMPAT_2_11