All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH RFC 00/16] Implement Microvm for aarch64 architecture
@ 2020-02-17  7:51 Xu Yandong
  2020-02-17  7:51 ` [PATCH RFC 01/16] hw/arm/arm: Introduce ArmMachineState and ArmMachineClass Xu Yandong
                   ` (17 more replies)
  0 siblings, 18 replies; 19+ messages in thread
From: Xu Yandong @ 2020-02-17  7:51 UTC (permalink / raw)
  To: peter.maydell
  Cc: zhang.zhanghailiang, slp, Xu Yandong, qemu-devel, qemu-arm, wu.wubin

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="y", Size: 5809 bytes --]

Implement Microvm for aarch64 architecture

This series attempts to implement microvm for aarch64
architecture.

Just like how Sergio Lopez does for implementing microvm
for x86 architecture. We remove parts of emulate devices which
are not needed in microvm, compared with normal VM,
We only keep PL011 (UART), PL031 (RTC) and virtio-mmio
devices for microvm of aarch64.

We compared the boot time between virt VM and microvm With the
follow command lines:
For microvm:
qemu-system-aarch64 \
    -cpu host \
    -smp 1,sockets=1,cores=1,threads=1 \
    -m 1024M \
    -machine microvm,accel=kvm,gic-version=3 \
    -kernel vmlinux.bin \
    -drive id=test,file=ubuntu-rootfs.img,format=raw,if=none \
    -device virtio-blk-device,drive=test \
    -netdev tap,id=tap0,script=no,downscript=no \
    -device virtio-net-device,netdev=tap0 \
    -append "root=/dev/vda rw printk.time=y" \
    -nographic
Normal VM:Only changed the machine type to 'virt'
qemu-system-aarch64 \
    -cpu host \
    -smp 1,sockets=1,cores=1,threads=1 \
    -m 1024M \
    -machine virt,accel=kvm,gic-version=3 \
    -kernel vmlinux.bin \
    -drive id=test,file=ubuntu-rootfs.img,format=raw,if=none \
    -device virtio-blk-device,drive=test \
    -netdev tap,id=tap0,script=no,downscript=no \
    -device virtio-net-device,netdev=tap0 \
    -append "root=/dev/vda rw printk.time=y" \
    -nographic

This is the test results:
1. Boot time
1) boot time after dropped caches(echo 3 > /proc/sys/vm/drop_caches)
normal virt Machine: 204 ms
microvm Machine: 132 ms

2) boot time with caches
normal virt Machine: 168 ms
microvm Machine: 71 ms

2. MMIO regions
normal virt Machine:
address-space: memory
  0000000000000000-ffffffffffffffff (prio 0, i/o): system
    0000000000000000-0000000003ffffff (prio 0, romd): virt.flash0
    0000000004000000-0000000007ffffff (prio 0, romd): virt.flash1
    0000000008000000-000000000800ffff (prio 0, i/o): gicv3_dist
    0000000008080000-000000000809ffff (prio 0, i/o): gicv3_its
      0000000008080000-000000000808ffff (prio 0, i/o): control
      0000000008090000-000000000809ffff (prio 0, i/o): translation
    00000000080a0000-00000000080bffff (prio 0, i/o): gicv3_redist_region[0]
    0000000009000000-0000000009000fff (prio 0, i/o): pl011
    0000000009010000-0000000009010fff (prio 0, i/o): pl031
    0000000009020000-0000000009020007 (prio 0, i/o): fwcfg.data
    0000000009020008-0000000009020009 (prio 0, i/o): fwcfg.ctl
    0000000009020010-0000000009020017 (prio 0, i/o): fwcfg.dma
    0000000009030000-0000000009030fff (prio 0, i/o): pl061
    000000000a000000-000000000a0001ff (prio 0, i/o): virtio-mmio
 	... skipped 30 virtio-mmio region
    000000000a003e00-000000000a003fff (prio 0, i/o): virtio-mmio
    000000000c000000-000000000dffffff (prio 0, i/o): platform bus
    0000000010000000-000000003efeffff (prio 0, i/o): alias pcie-mmio @gpex_mmio 0000000010000000-000000003efeffff
    000000003eff0000-000000003effffff (prio 0, i/o): gpex_ioport
      000000003eff1000-000000003eff101f (prio 1, i/o): virtio-pci
    0000000040000000-000000007fffffff (prio 0, ram): mach-virt.ram
    0000004010000000-000000401fffffff (prio 0, i/o): alias pcie-ecam @pcie-mmcfg-mmio 0000000000000000-000000000fffffff
    0000008000000000-000000ffffffffff (prio 0, i/o): alias pcie-mmio-high @gpex_mmio 0000008000000000-000000ffffffffff

microvm Machine:
address-space: memory
  0000000000000000-ffffffffffffffff (prio 0, i/o): system
  0000000008000000-000000000800ffff (prio 0, i/o): gicv3_dist
    00000000080a0000-00000000080bffff (prio 0, i/o): gicv3_redist_region[0]
    0000000009000000-0000000009000fff (prio 0, i/o): pl011
    0000000009010000-0000000009010fff (prio 0, i/o): pl031
    000000000a000000-000000000a0001ff (prio 0, i/o): virtio-mmio
	... skipped 30 virtio-mmio region
    000000000a003e00-000000000a003fff (prio 0, i/o): virtio-mmio
    0000000040000000-000000007fffffff (prio 0, ram): mach-virt.ram

Please review this series.

Thinks,
Xu Yandong.

Xu Yandong (16):
  hw/arm/arm: Introduce ArmMachineState and ArmMachineClass
  hw/arm: move shared fdt member to ArmMachine
  hw/arm: move shared memmap member to ArmMachine
  hw/arm: move shared irqmap member to ArmMachine
  hw/arm: move shared smp_cpus member to ArmMachine
  hw/arm/virt: split MSI related codes from create_gic
  hw/arm/virt: split virt extension related codes from create_gic
  hw/arm/virt: split secure extension related codes from create_gic
  hw/arm: move shared gic member to ArmMachine
  hw/arm: split create_gic function
  hw/arm: move shared psci_enable and claim_edge_triggered_timers member
    to ArmMachine
  hw/arm: move shared devices related functions to arm.c and export them
  hw/arm: move shared fdt related functions to arm.c and export them
  hw/arm: move shared bootinfo member to ArmMachine
  hw/arm: move shared cpu related functions to arm.c and export them
  hw/arm: Introduce the microvm machine type

 default-configs/aarch64-softmmu.mak |    2 +
 hw/arm/Kconfig                      |    7 +
 hw/arm/Makefile.objs                |    3 +-
 hw/arm/arm.c                        |  687 +++++++++++++++++
 hw/arm/microvm.c                    |  303 ++++++++
 hw/arm/virt-acpi-build.c            |   48 +-
 hw/arm/virt.c                       | 1079 +++++++--------------------
 include/hw/arm/arm.h                |  152 ++++
 include/hw/arm/microvm.h            |   40 +
 include/hw/arm/virt.h               |   86 +--
 10 files changed, 1505 insertions(+), 902 deletions(-)
 create mode 100644 hw/arm/arm.c
 create mode 100644 hw/arm/microvm.c
 create mode 100644 include/hw/arm/arm.h
 create mode 100644 include/hw/arm/microvm.h

-- 
2.18.1



^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH RFC 01/16] hw/arm/arm: Introduce ArmMachineState and ArmMachineClass
  2020-02-17  7:51 [PATCH RFC 00/16] Implement Microvm for aarch64 architecture Xu Yandong
@ 2020-02-17  7:51 ` Xu Yandong
  2020-02-17  7:51 ` [PATCH RFC 02/16] hw/arm: move shared fdt member to ArmMachine Xu Yandong
                   ` (16 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Xu Yandong @ 2020-02-17  7:51 UTC (permalink / raw)
  To: peter.maydell
  Cc: zhang.zhanghailiang, slp, Xu Yandong, qemu-devel, qemu-arm, wu.wubin

In the following patches, VirtMachineState and VirtMachineClass will
splited to and deriving ArmMachineState and ArmMachineClass.
This allows sharing code with other arm machine types.

Signed-off-by: Xu Yandong <xuyandong2@huawei.com>
---
 hw/arm/Makefile.objs  |   2 +-
 hw/arm/arm.c          |  77 ++++++++++++++++++++++++++++++++
 hw/arm/virt.c         |  11 +----
 include/hw/arm/arm.h  | 100 ++++++++++++++++++++++++++++++++++++++++++
 include/hw/arm/virt.h |  61 ++------------------------
 5 files changed, 183 insertions(+), 68 deletions(-)
 create mode 100644 hw/arm/arm.c
 create mode 100644 include/hw/arm/arm.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 336f6dd374..51fcee2ac8 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -1,6 +1,6 @@
 obj-y += boot.o
 obj-$(CONFIG_PLATFORM_BUS) += sysbus-fdt.o
-obj-$(CONFIG_ARM_VIRT) += virt.o
+obj-$(CONFIG_ARM_VIRT) += arm.o virt.o
 obj-$(CONFIG_ACPI) += virt-acpi-build.o
 obj-$(CONFIG_DIGIC) += digic_boards.o
 obj-$(CONFIG_EXYNOS4) += exynos4_boards.o
diff --git a/hw/arm/arm.c b/hw/arm/arm.c
new file mode 100644
index 0000000000..4261d56832
--- /dev/null
+++ b/hw/arm/arm.c
@@ -0,0 +1,77 @@
+/*
+ * ARM mach-virt emulation
+ * Copyright (c) 2013 Linaro Limited
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Emulate a virtual board which works by passing Linux all the information
+ * it needs about what devices are present via the device tree.
+ * There are some restrictions about what we can do here:
+ *  + we can only present devices whose Linux drivers will work based
+ *    purely on the device tree with no platform data at all
+ * This is essentially the same approach kvmtool uses.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/arm/arm.h"
+#include "sysemu/device_tree.h"
+#include "sysemu/numa.h"
+#include "hw/loader.h"
+#include "exec/address-spaces.h"
+#include "qemu/bitops.h"
+#include "qemu/error-report.h"
+#include "qemu/module.h"
+#include "hw/arm/sysbus-fdt.h"
+#include "hw/platform-bus.h"
+#include "hw/qdev-properties.h"
+#include "hw/arm/fdt.h"
+#include "hw/intc/arm_gic.h"
+#include "kvm_arm.h"
+
+static void arm_machine_class_init(ObjectClass *oc, void *data)
+{
+    MachineClass *mc = MACHINE_CLASS(oc);
+
+    mc->block_default_type = IF_VIRTIO;
+    mc->no_cdrom = 1;
+    mc->pci_allow_0_address = true;
+    /* We know we will never create a pre-ARMv7 CPU which needs 1K pages */
+    mc->minimum_page_bits = 12;
+    mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a15");
+    mc->numa_mem_supported = true;
+    mc->auto_enable_numa_with_memhp = true;
+}
+
+static void arm_instance_init(Object *obj)
+{
+}
+
+static const TypeInfo arm_machine_info = {
+    .name          = TYPE_ARM_MACHINE,
+    .parent        = TYPE_MACHINE,
+    .abstract      = true,
+    .instance_size = sizeof(ArmMachineState),
+    .class_size    = sizeof(ArmMachineClass),
+    .class_init    = arm_machine_class_init,
+    .instance_init = arm_instance_init,
+    .interfaces = (InterfaceInfo[]) {
+         { }
+    },
+};
+
+static void macharm_machine_init(void)
+{
+    type_register_static(&arm_machine_info);
+}
+type_init(macharm_machine_init);
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index f788fe27d6..355007fd32 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -37,6 +37,7 @@
 #include "hw/boards.h"
 #include "hw/arm/boot.h"
 #include "hw/arm/primecell.h"
+#include "hw/arm/arm.h"
 #include "hw/arm/virt.h"
 #include "hw/block/flash.h"
 #include "hw/vfio/vfio-calxeda-xgmac.h"
@@ -2041,14 +2042,8 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
     machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_AMD_XGBE);
     machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
     machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_PLATFORM);
-    mc->block_default_type = IF_VIRTIO;
-    mc->no_cdrom = 1;
-    mc->pci_allow_0_address = true;
-    /* We know we will never create a pre-ARMv7 CPU which needs 1K pages */
-    mc->minimum_page_bits = 12;
     mc->possible_cpu_arch_ids = virt_possible_cpu_arch_ids;
     mc->cpu_index_to_instance_props = virt_cpu_index_to_props;
-    mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a15");
     mc->get_default_cpu_node_id = virt_get_default_cpu_node_id;
     mc->kvm_type = virt_kvm_type;
     assert(!mc->get_hotplug_handler);
@@ -2056,8 +2051,6 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
     hc->pre_plug = virt_machine_device_pre_plug_cb;
     hc->plug = virt_machine_device_plug_cb;
     hc->unplug_request = virt_machine_device_unplug_request_cb;
-    mc->numa_mem_supported = true;
-    mc->auto_enable_numa_with_memhp = true;
 }
 
 static void virt_instance_init(Object *obj)
@@ -2133,7 +2126,7 @@ static void virt_instance_init(Object *obj)
 
 static const TypeInfo virt_machine_info = {
     .name          = TYPE_VIRT_MACHINE,
-    .parent        = TYPE_MACHINE,
+    .parent        = TYPE_ARM_MACHINE,
     .abstract      = true,
     .instance_size = sizeof(VirtMachineState),
     .class_size    = sizeof(VirtMachineClass),
diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h
new file mode 100644
index 0000000000..2aa9ee3d05
--- /dev/null
+++ b/include/hw/arm/arm.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2015 Linaro Limited
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.*
+ */
+
+#ifndef QEMU_ARM_ARM_H
+#define QEMU_ARM_ARM_H
+
+#include "exec/hwaddr.h"
+#include "hw/boards.h"
+#include "hw/arm/boot.h"
+#include "hw/intc/arm_gicv3_common.h"
+
+#define NUM_GICV2M_SPIS       64
+#define NUM_VIRTIO_TRANSPORTS 32
+#define NUM_SMMU_IRQS          4
+
+#define ARCH_GIC_MAINT_IRQ  9
+
+#define ARCH_TIMER_VIRT_IRQ   11
+#define ARCH_TIMER_S_EL1_IRQ  13
+#define ARCH_TIMER_NS_EL1_IRQ 14
+#define ARCH_TIMER_NS_EL2_IRQ 10
+
+#define VIRTUAL_PMU_IRQ 7
+
+#define PPI(irq) ((irq) + 16)
+
+
+enum {
+    VIRT_FLASH,
+    VIRT_MEM,
+    VIRT_CPUPERIPHS,
+    VIRT_GIC_DIST,
+    VIRT_GIC_CPU,
+    VIRT_GIC_V2M,
+    VIRT_GIC_HYP,
+    VIRT_GIC_VCPU,
+    VIRT_GIC_ITS,
+    VIRT_GIC_REDIST,
+    VIRT_SMMU,
+    VIRT_UART,
+    VIRT_MMIO,
+    VIRT_RTC,
+    VIRT_FW_CFG,
+    VIRT_PCIE,
+    VIRT_PCIE_MMIO,
+    VIRT_PCIE_PIO,
+    VIRT_PCIE_ECAM,
+    VIRT_PLATFORM_BUS,
+    VIRT_GPIO,
+    VIRT_SECURE_UART,
+    VIRT_SECURE_MEM,
+    VIRT_PCDIMM_ACPI,
+    VIRT_ACPI_GED,
+    VIRT_LOWMEMMAP_LAST,
+};
+
+/* indices of IO regions located after the RAM */
+enum {
+    VIRT_HIGH_GIC_REDIST2 =  VIRT_LOWMEMMAP_LAST,
+    VIRT_HIGH_PCIE_ECAM,
+    VIRT_HIGH_PCIE_MMIO,
+};
+
+/* indices of IO regions located after the RAM */
+
+typedef struct MemMapEntry {
+    hwaddr base;
+    hwaddr size;
+} MemMapEntry;
+
+typedef struct {
+    MachineClass parent;
+} ArmMachineClass;
+
+typedef struct {
+    MachineState parent;
+} ArmMachineState;
+
+#define TYPE_ARM_MACHINE   MACHINE_TYPE_NAME("arm")
+#define ARM_MACHINE(obj) \
+    OBJECT_CHECK(ArmMachineState, (obj), TYPE_ARM_MACHINE)
+#define ARM_MACHINE_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(ArmMachineClass, obj, TYPE_ARM_MACHINE)
+#define ARM_MACHINE_CLASS(klass) \
+    OBJECT_CLASS_CHECK(ArmMachineClass, klass, TYPE_ARM_MACHINE)
+
+#endif /* QEMU_ARM_ARM_H */
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index 71508bf40c..aa0cc852a5 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -37,57 +37,7 @@
 #include "hw/block/flash.h"
 #include "sysemu/kvm.h"
 #include "hw/intc/arm_gicv3_common.h"
-
-#define NUM_GICV2M_SPIS       64
-#define NUM_VIRTIO_TRANSPORTS 32
-#define NUM_SMMU_IRQS          4
-
-#define ARCH_GIC_MAINT_IRQ  9
-
-#define ARCH_TIMER_VIRT_IRQ   11
-#define ARCH_TIMER_S_EL1_IRQ  13
-#define ARCH_TIMER_NS_EL1_IRQ 14
-#define ARCH_TIMER_NS_EL2_IRQ 10
-
-#define VIRTUAL_PMU_IRQ 7
-
-#define PPI(irq) ((irq) + 16)
-
-enum {
-    VIRT_FLASH,
-    VIRT_MEM,
-    VIRT_CPUPERIPHS,
-    VIRT_GIC_DIST,
-    VIRT_GIC_CPU,
-    VIRT_GIC_V2M,
-    VIRT_GIC_HYP,
-    VIRT_GIC_VCPU,
-    VIRT_GIC_ITS,
-    VIRT_GIC_REDIST,
-    VIRT_SMMU,
-    VIRT_UART,
-    VIRT_MMIO,
-    VIRT_RTC,
-    VIRT_FW_CFG,
-    VIRT_PCIE,
-    VIRT_PCIE_MMIO,
-    VIRT_PCIE_PIO,
-    VIRT_PCIE_ECAM,
-    VIRT_PLATFORM_BUS,
-    VIRT_GPIO,
-    VIRT_SECURE_UART,
-    VIRT_SECURE_MEM,
-    VIRT_PCDIMM_ACPI,
-    VIRT_ACPI_GED,
-    VIRT_LOWMEMMAP_LAST,
-};
-
-/* indices of IO regions located after the RAM */
-enum {
-    VIRT_HIGH_GIC_REDIST2 =  VIRT_LOWMEMMAP_LAST,
-    VIRT_HIGH_PCIE_ECAM,
-    VIRT_HIGH_PCIE_MMIO,
-};
+#include "hw/arm/arm.h"
 
 typedef enum VirtIOMMUType {
     VIRT_IOMMU_NONE,
@@ -95,13 +45,8 @@ typedef enum VirtIOMMUType {
     VIRT_IOMMU_VIRTIO,
 } VirtIOMMUType;
 
-typedef struct MemMapEntry {
-    hwaddr base;
-    hwaddr size;
-} MemMapEntry;
-
 typedef struct {
-    MachineClass parent;
+    ArmMachineClass parent;
     bool disallow_affinity_adjustment;
     bool no_its;
     bool no_pmu;
@@ -113,7 +58,7 @@ typedef struct {
 } VirtMachineClass;
 
 typedef struct {
-    MachineState parent;
+    ArmMachineState parent;
     Notifier machine_done;
     DeviceState *platform_bus_dev;
     FWCfgState *fw_cfg;
-- 
2.18.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH RFC 02/16] hw/arm: move shared fdt member to ArmMachine
  2020-02-17  7:51 [PATCH RFC 00/16] Implement Microvm for aarch64 architecture Xu Yandong
  2020-02-17  7:51 ` [PATCH RFC 01/16] hw/arm/arm: Introduce ArmMachineState and ArmMachineClass Xu Yandong
@ 2020-02-17  7:51 ` Xu Yandong
  2020-02-17  7:51 ` [PATCH RFC 03/16] hw/arm: move shared memmap " Xu Yandong
                   ` (15 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Xu Yandong @ 2020-02-17  7:51 UTC (permalink / raw)
  To: peter.maydell
  Cc: zhang.zhanghailiang, slp, Xu Yandong, qemu-devel, qemu-arm, wu.wubin

Move fdt and fdt_size member from VirtMachineState to ArmMachineState.

Signed-off-by: Xu Yandong <xuyandong2@huawei.com>
---
 hw/arm/virt.c         | 303 ++++++++++++++++++++++--------------------
 include/hw/arm/arm.h  |   2 +
 include/hw/arm/virt.h |   2 -
 3 files changed, 163 insertions(+), 144 deletions(-)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 355007fd32..41b2076ce1 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -211,15 +211,16 @@ static bool cpu_type_valid(const char *cpu)
 static void create_fdt(VirtMachineState *vms)
 {
     MachineState *ms = MACHINE(vms);
+    ArmMachineState *ams = ARM_MACHINE(vms);
     int nb_numa_nodes = ms->numa_state->num_nodes;
-    void *fdt = create_device_tree(&vms->fdt_size);
+    void *fdt = create_device_tree(&ams->fdt_size);
 
     if (!fdt) {
         error_report("create_device_tree() failed");
         exit(1);
     }
 
-    vms->fdt = fdt;
+    ams->fdt = fdt;
 
     /* Header */
     qemu_fdt_setprop_string(fdt, "/", "compatible", "linux,dummy-virt");
@@ -288,6 +289,7 @@ static void fdt_add_timer_nodes(const VirtMachineState *vms)
      * the correct information.
      */
     ARMCPU *armcpu;
+    ArmMachineState *ams = ARM_MACHINE(vms);
     VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
     uint32_t irqflags = GIC_FDT_IRQ_FLAGS_LEVEL_HI;
 
@@ -301,19 +303,19 @@ static void fdt_add_timer_nodes(const VirtMachineState *vms)
                              (1 << vms->smp_cpus) - 1);
     }
 
-    qemu_fdt_add_subnode(vms->fdt, "/timer");
+    qemu_fdt_add_subnode(ams->fdt, "/timer");
 
     armcpu = ARM_CPU(qemu_get_cpu(0));
     if (arm_feature(&armcpu->env, ARM_FEATURE_V8)) {
         const char compat[] = "arm,armv8-timer\0arm,armv7-timer";
-        qemu_fdt_setprop(vms->fdt, "/timer", "compatible",
+        qemu_fdt_setprop(ams->fdt, "/timer", "compatible",
                          compat, sizeof(compat));
     } else {
-        qemu_fdt_setprop_string(vms->fdt, "/timer", "compatible",
+        qemu_fdt_setprop_string(ams->fdt, "/timer", "compatible",
                                 "arm,armv7-timer");
     }
-    qemu_fdt_setprop(vms->fdt, "/timer", "always-on", NULL, 0);
-    qemu_fdt_setprop_cells(vms->fdt, "/timer", "interrupts",
+    qemu_fdt_setprop(ams->fdt, "/timer", "always-on", NULL, 0);
+    qemu_fdt_setprop_cells(ams->fdt, "/timer", "interrupts",
                        GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_S_EL1_IRQ, irqflags,
                        GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_NS_EL1_IRQ, irqflags,
                        GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_VIRT_IRQ, irqflags,
@@ -325,6 +327,7 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms)
     int cpu;
     int addr_cells = 1;
     const MachineState *ms = MACHINE(vms);
+    const ArmMachineState *ams = ARM_MACHINE(vms);
 
     /*
      * From Documentation/devicetree/bindings/arm/cpus.txt
@@ -348,36 +351,36 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms)
         }
     }
 
-    qemu_fdt_add_subnode(vms->fdt, "/cpus");
-    qemu_fdt_setprop_cell(vms->fdt, "/cpus", "#address-cells", addr_cells);
-    qemu_fdt_setprop_cell(vms->fdt, "/cpus", "#size-cells", 0x0);
+    qemu_fdt_add_subnode(ams->fdt, "/cpus");
+    qemu_fdt_setprop_cell(ams->fdt, "/cpus", "#address-cells", addr_cells);
+    qemu_fdt_setprop_cell(ams->fdt, "/cpus", "#size-cells", 0x0);
 
     for (cpu = vms->smp_cpus - 1; cpu >= 0; cpu--) {
         char *nodename = g_strdup_printf("/cpus/cpu@%d", cpu);
         ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu));
         CPUState *cs = CPU(armcpu);
 
-        qemu_fdt_add_subnode(vms->fdt, nodename);
-        qemu_fdt_setprop_string(vms->fdt, nodename, "device_type", "cpu");
-        qemu_fdt_setprop_string(vms->fdt, nodename, "compatible",
+        qemu_fdt_add_subnode(ams->fdt, nodename);
+        qemu_fdt_setprop_string(ams->fdt, nodename, "device_type", "cpu");
+        qemu_fdt_setprop_string(ams->fdt, nodename, "compatible",
                                     armcpu->dtb_compatible);
 
         if (vms->psci_conduit != QEMU_PSCI_CONDUIT_DISABLED
             && vms->smp_cpus > 1) {
-            qemu_fdt_setprop_string(vms->fdt, nodename,
+            qemu_fdt_setprop_string(ams->fdt, nodename,
                                         "enable-method", "psci");
         }
 
         if (addr_cells == 2) {
-            qemu_fdt_setprop_u64(vms->fdt, nodename, "reg",
+            qemu_fdt_setprop_u64(ams->fdt, nodename, "reg",
                                  armcpu->mp_affinity);
         } else {
-            qemu_fdt_setprop_cell(vms->fdt, nodename, "reg",
+            qemu_fdt_setprop_cell(ams->fdt, nodename, "reg",
                                   armcpu->mp_affinity);
         }
 
         if (ms->possible_cpus->cpus[cs->cpu_index].props.has_node_id) {
-            qemu_fdt_setprop_cell(vms->fdt, nodename, "numa-node-id",
+            qemu_fdt_setprop_cell(ams->fdt, nodename, "numa-node-id",
                 ms->possible_cpus->cpus[cs->cpu_index].props.node_id);
         }
 
@@ -388,71 +391,74 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms)
 static void fdt_add_its_gic_node(VirtMachineState *vms)
 {
     char *nodename;
+    ArmMachineState *ams = ARM_MACHINE(vms);
 
-    vms->msi_phandle = qemu_fdt_alloc_phandle(vms->fdt);
+    vms->msi_phandle = qemu_fdt_alloc_phandle(ams->fdt);
     nodename = g_strdup_printf("/intc/its@%" PRIx64,
                                vms->memmap[VIRT_GIC_ITS].base);
-    qemu_fdt_add_subnode(vms->fdt, nodename);
-    qemu_fdt_setprop_string(vms->fdt, nodename, "compatible",
+    qemu_fdt_add_subnode(ams->fdt, nodename);
+    qemu_fdt_setprop_string(ams->fdt, nodename, "compatible",
                             "arm,gic-v3-its");
-    qemu_fdt_setprop(vms->fdt, nodename, "msi-controller", NULL, 0);
-    qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
+    qemu_fdt_setprop(ams->fdt, nodename, "msi-controller", NULL, 0);
+    qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "reg",
                                  2, vms->memmap[VIRT_GIC_ITS].base,
                                  2, vms->memmap[VIRT_GIC_ITS].size);
-    qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle", vms->msi_phandle);
+    qemu_fdt_setprop_cell(ams->fdt, nodename, "phandle", vms->msi_phandle);
     g_free(nodename);
 }
 
 static void fdt_add_v2m_gic_node(VirtMachineState *vms)
 {
     char *nodename;
+    ArmMachineState *ams = ARM_MACHINE(vms);
 
     nodename = g_strdup_printf("/intc/v2m@%" PRIx64,
                                vms->memmap[VIRT_GIC_V2M].base);
-    vms->msi_phandle = qemu_fdt_alloc_phandle(vms->fdt);
-    qemu_fdt_add_subnode(vms->fdt, nodename);
-    qemu_fdt_setprop_string(vms->fdt, nodename, "compatible",
+    vms->msi_phandle = qemu_fdt_alloc_phandle(ams->fdt);
+    qemu_fdt_add_subnode(ams->fdt, nodename);
+    qemu_fdt_setprop_string(ams->fdt, nodename, "compatible",
                             "arm,gic-v2m-frame");
-    qemu_fdt_setprop(vms->fdt, nodename, "msi-controller", NULL, 0);
-    qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
+    qemu_fdt_setprop(ams->fdt, nodename, "msi-controller", NULL, 0);
+    qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "reg",
                                  2, vms->memmap[VIRT_GIC_V2M].base,
                                  2, vms->memmap[VIRT_GIC_V2M].size);
-    qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle", vms->msi_phandle);
+    qemu_fdt_setprop_cell(ams->fdt, nodename, "phandle", vms->msi_phandle);
     g_free(nodename);
 }
 
 static void fdt_add_gic_node(VirtMachineState *vms)
 {
     char *nodename;
+    ArmMachineState *ams = ARM_MACHINE(vms);
 
-    vms->gic_phandle = qemu_fdt_alloc_phandle(vms->fdt);
-    qemu_fdt_setprop_cell(vms->fdt, "/", "interrupt-parent", vms->gic_phandle);
+    vms->gic_phandle = qemu_fdt_alloc_phandle(ams->fdt);
+    qemu_fdt_setprop_cell(ams->fdt, "/", "interrupt-parent", vms->gic_phandle);
 
     nodename = g_strdup_printf("/intc@%" PRIx64,
                                vms->memmap[VIRT_GIC_DIST].base);
-    qemu_fdt_add_subnode(vms->fdt, nodename);
-    qemu_fdt_setprop_cell(vms->fdt, nodename, "#interrupt-cells", 3);
-    qemu_fdt_setprop(vms->fdt, nodename, "interrupt-controller", NULL, 0);
-    qemu_fdt_setprop_cell(vms->fdt, nodename, "#address-cells", 0x2);
-    qemu_fdt_setprop_cell(vms->fdt, nodename, "#size-cells", 0x2);
-    qemu_fdt_setprop(vms->fdt, nodename, "ranges", NULL, 0);
+    qemu_fdt_add_subnode(ams->fdt, nodename);
+    qemu_fdt_setprop_cell(ams->fdt, nodename, "#interrupt-cells", 3);
+    qemu_fdt_setprop(ams->fdt, nodename, "interrupt-controller", NULL, 0);
+    qemu_fdt_setprop_cell(ams->fdt, nodename, "#address-cells", 0x2);
+    qemu_fdt_setprop_cell(ams->fdt, nodename, "#size-cells", 0x2);
+    qemu_fdt_setprop(ams->fdt, nodename, "ranges", NULL, 0);
     if (vms->gic_version == 3) {
         int nb_redist_regions = virt_gicv3_redist_region_count(vms);
 
-        qemu_fdt_setprop_string(vms->fdt, nodename, "compatible",
+        qemu_fdt_setprop_string(ams->fdt, nodename, "compatible",
                                 "arm,gic-v3");
 
-        qemu_fdt_setprop_cell(vms->fdt, nodename,
+        qemu_fdt_setprop_cell(ams->fdt, nodename,
                               "#redistributor-regions", nb_redist_regions);
 
         if (nb_redist_regions == 1) {
-            qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
+            qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "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, nodename, "reg",
+            qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "reg",
                                  2, vms->memmap[VIRT_GIC_DIST].base,
                                  2, vms->memmap[VIRT_GIC_DIST].size,
                                  2, vms->memmap[VIRT_GIC_REDIST].base,
@@ -462,22 +468,22 @@ static void fdt_add_gic_node(VirtMachineState *vms)
         }
 
         if (vms->virt) {
-            qemu_fdt_setprop_cells(vms->fdt, nodename, "interrupts",
+            qemu_fdt_setprop_cells(ams->fdt, nodename, "interrupts",
                                    GIC_FDT_IRQ_TYPE_PPI, ARCH_GIC_MAINT_IRQ,
                                    GIC_FDT_IRQ_FLAGS_LEVEL_HI);
         }
     } else {
         /* 'cortex-a15-gic' means 'GIC v2' */
-        qemu_fdt_setprop_string(vms->fdt, nodename, "compatible",
+        qemu_fdt_setprop_string(ams->fdt, nodename, "compatible",
                                 "arm,cortex-a15-gic");
         if (!vms->virt) {
-            qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
+            qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "reg",
                                          2, vms->memmap[VIRT_GIC_DIST].base,
                                          2, vms->memmap[VIRT_GIC_DIST].size,
                                          2, vms->memmap[VIRT_GIC_CPU].base,
                                          2, vms->memmap[VIRT_GIC_CPU].size);
         } else {
-            qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
+            qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "reg",
                                          2, vms->memmap[VIRT_GIC_DIST].base,
                                          2, vms->memmap[VIRT_GIC_DIST].size,
                                          2, vms->memmap[VIRT_GIC_CPU].base,
@@ -486,13 +492,13 @@ static void fdt_add_gic_node(VirtMachineState *vms)
                                          2, vms->memmap[VIRT_GIC_HYP].size,
                                          2, vms->memmap[VIRT_GIC_VCPU].base,
                                          2, vms->memmap[VIRT_GIC_VCPU].size);
-            qemu_fdt_setprop_cells(vms->fdt, nodename, "interrupts",
+            qemu_fdt_setprop_cells(ams->fdt, nodename, "interrupts",
                                    GIC_FDT_IRQ_TYPE_PPI, ARCH_GIC_MAINT_IRQ,
                                    GIC_FDT_IRQ_FLAGS_LEVEL_HI);
         }
     }
 
-    qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle", vms->gic_phandle);
+    qemu_fdt_setprop_cell(ams->fdt, nodename, "phandle", vms->gic_phandle);
     g_free(nodename);
 }
 
@@ -500,6 +506,7 @@ static void fdt_add_pmu_nodes(const VirtMachineState *vms)
 {
     CPUState *cpu;
     ARMCPU *armcpu;
+    const ArmMachineState *ams = ARM_MACHINE(vms);
     uint32_t irqflags = GIC_FDT_IRQ_FLAGS_LEVEL_HI;
 
     CPU_FOREACH(cpu) {
@@ -522,12 +529,12 @@ static void fdt_add_pmu_nodes(const VirtMachineState *vms)
     }
 
     armcpu = ARM_CPU(qemu_get_cpu(0));
-    qemu_fdt_add_subnode(vms->fdt, "/pmu");
+    qemu_fdt_add_subnode(ams->fdt, "/pmu");
     if (arm_feature(&armcpu->env, ARM_FEATURE_V8)) {
         const char compat[] = "arm,armv8-pmuv3";
-        qemu_fdt_setprop(vms->fdt, "/pmu", "compatible",
+        qemu_fdt_setprop(ams->fdt, "/pmu", "compatible",
                          compat, sizeof(compat));
-        qemu_fdt_setprop_cells(vms->fdt, "/pmu", "interrupts",
+        qemu_fdt_setprop_cells(ams->fdt, "/pmu", "interrupts",
                                GIC_FDT_IRQ_TYPE_PPI, VIRTUAL_PMU_IRQ, irqflags);
     }
 }
@@ -720,6 +727,7 @@ static void create_uart(const VirtMachineState *vms, int uart,
                         MemoryRegion *mem, Chardev *chr)
 {
     char *nodename;
+    const ArmMachineState *ams = ARM_MACHINE(vms);
     hwaddr base = vms->memmap[uart].base;
     hwaddr size = vms->memmap[uart].size;
     int irq = vms->irqmap[uart];
@@ -735,29 +743,29 @@ static void create_uart(const VirtMachineState *vms, int uart,
     sysbus_connect_irq(s, 0, qdev_get_gpio_in(vms->gic, irq));
 
     nodename = g_strdup_printf("/pl011@%" PRIx64, base);
-    qemu_fdt_add_subnode(vms->fdt, nodename);
+    qemu_fdt_add_subnode(ams->fdt, nodename);
     /* Note that we can't use setprop_string because of the embedded NUL */
-    qemu_fdt_setprop(vms->fdt, nodename, "compatible",
+    qemu_fdt_setprop(ams->fdt, nodename, "compatible",
                          compat, sizeof(compat));
-    qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
+    qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "reg",
                                      2, base, 2, size);
-    qemu_fdt_setprop_cells(vms->fdt, nodename, "interrupts",
+    qemu_fdt_setprop_cells(ams->fdt, nodename, "interrupts",
                                GIC_FDT_IRQ_TYPE_SPI, irq,
                                GIC_FDT_IRQ_FLAGS_LEVEL_HI);
-    qemu_fdt_setprop_cells(vms->fdt, nodename, "clocks",
+    qemu_fdt_setprop_cells(ams->fdt, nodename, "clocks",
                                vms->clock_phandle, vms->clock_phandle);
-    qemu_fdt_setprop(vms->fdt, nodename, "clock-names",
+    qemu_fdt_setprop(ams->fdt, nodename, "clock-names",
                          clocknames, sizeof(clocknames));
 
     if (uart == VIRT_UART) {
-        qemu_fdt_setprop_string(vms->fdt, "/chosen", "stdout-path", nodename);
+        qemu_fdt_setprop_string(ams->fdt, "/chosen", "stdout-path", nodename);
     } else {
         /* Mark as not usable by the normal world */
-        qemu_fdt_setprop_string(vms->fdt, nodename, "status", "disabled");
-        qemu_fdt_setprop_string(vms->fdt, nodename, "secure-status", "okay");
+        qemu_fdt_setprop_string(ams->fdt, nodename, "status", "disabled");
+        qemu_fdt_setprop_string(ams->fdt, nodename, "secure-status", "okay");
 
-        qemu_fdt_add_subnode(vms->fdt, "/secure-chosen");
-        qemu_fdt_setprop_string(vms->fdt, "/secure-chosen", "stdout-path",
+        qemu_fdt_add_subnode(ams->fdt, "/secure-chosen");
+        qemu_fdt_setprop_string(ams->fdt, "/secure-chosen", "stdout-path",
                                 nodename);
     }
 
@@ -767,6 +775,7 @@ static void create_uart(const VirtMachineState *vms, int uart,
 static void create_rtc(const VirtMachineState *vms)
 {
     char *nodename;
+    const ArmMachineState *ams = ARM_MACHINE(vms);
     hwaddr base = vms->memmap[VIRT_RTC].base;
     hwaddr size = vms->memmap[VIRT_RTC].size;
     int irq = vms->irqmap[VIRT_RTC];
@@ -775,15 +784,15 @@ static void create_rtc(const VirtMachineState *vms)
     sysbus_create_simple("pl031", base, qdev_get_gpio_in(vms->gic, irq));
 
     nodename = g_strdup_printf("/pl031@%" PRIx64, base);
-    qemu_fdt_add_subnode(vms->fdt, nodename);
-    qemu_fdt_setprop(vms->fdt, nodename, "compatible", compat, sizeof(compat));
-    qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
+    qemu_fdt_add_subnode(ams->fdt, nodename);
+    qemu_fdt_setprop(ams->fdt, nodename, "compatible", compat, sizeof(compat));
+    qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "reg",
                                  2, base, 2, size);
-    qemu_fdt_setprop_cells(vms->fdt, nodename, "interrupts",
+    qemu_fdt_setprop_cells(ams->fdt, nodename, "interrupts",
                            GIC_FDT_IRQ_TYPE_SPI, irq,
                            GIC_FDT_IRQ_FLAGS_LEVEL_HI);
-    qemu_fdt_setprop_cell(vms->fdt, nodename, "clocks", vms->clock_phandle);
-    qemu_fdt_setprop_string(vms->fdt, nodename, "clock-names", "apb_pclk");
+    qemu_fdt_setprop_cell(ams->fdt, nodename, "clocks", vms->clock_phandle);
+    qemu_fdt_setprop_string(ams->fdt, nodename, "clock-names", "apb_pclk");
     g_free(nodename);
 }
 
@@ -804,6 +813,7 @@ static void create_gpio(const VirtMachineState *vms)
 {
     char *nodename;
     DeviceState *pl061_dev;
+    const ArmMachineState *ams = ARM_MACHINE(vms);
     hwaddr base = vms->memmap[VIRT_GPIO].base;
     hwaddr size = vms->memmap[VIRT_GPIO].size;
     int irq = vms->irqmap[VIRT_GPIO];
@@ -812,34 +822,34 @@ static void create_gpio(const VirtMachineState *vms)
     pl061_dev = sysbus_create_simple("pl061", base,
                                      qdev_get_gpio_in(vms->gic, irq));
 
-    uint32_t phandle = qemu_fdt_alloc_phandle(vms->fdt);
+    uint32_t phandle = qemu_fdt_alloc_phandle(ams->fdt);
     nodename = g_strdup_printf("/pl061@%" PRIx64, base);
-    qemu_fdt_add_subnode(vms->fdt, nodename);
-    qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
+    qemu_fdt_add_subnode(ams->fdt, nodename);
+    qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "reg",
                                  2, base, 2, size);
-    qemu_fdt_setprop(vms->fdt, nodename, "compatible", compat, sizeof(compat));
-    qemu_fdt_setprop_cell(vms->fdt, nodename, "#gpio-cells", 2);
-    qemu_fdt_setprop(vms->fdt, nodename, "gpio-controller", NULL, 0);
-    qemu_fdt_setprop_cells(vms->fdt, nodename, "interrupts",
+    qemu_fdt_setprop(ams->fdt, nodename, "compatible", compat, sizeof(compat));
+    qemu_fdt_setprop_cell(ams->fdt, nodename, "#gpio-cells", 2);
+    qemu_fdt_setprop(ams->fdt, nodename, "gpio-controller", NULL, 0);
+    qemu_fdt_setprop_cells(ams->fdt, nodename, "interrupts",
                            GIC_FDT_IRQ_TYPE_SPI, irq,
                            GIC_FDT_IRQ_FLAGS_LEVEL_HI);
-    qemu_fdt_setprop_cell(vms->fdt, nodename, "clocks", vms->clock_phandle);
-    qemu_fdt_setprop_string(vms->fdt, nodename, "clock-names", "apb_pclk");
-    qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle", phandle);
+    qemu_fdt_setprop_cell(ams->fdt, nodename, "clocks", vms->clock_phandle);
+    qemu_fdt_setprop_string(ams->fdt, nodename, "clock-names", "apb_pclk");
+    qemu_fdt_setprop_cell(ams->fdt, nodename, "phandle", phandle);
 
     gpio_key_dev = sysbus_create_simple("gpio-key", -1,
                                         qdev_get_gpio_in(pl061_dev, 3));
-    qemu_fdt_add_subnode(vms->fdt, "/gpio-keys");
-    qemu_fdt_setprop_string(vms->fdt, "/gpio-keys", "compatible", "gpio-keys");
-    qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys", "#size-cells", 0);
-    qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys", "#address-cells", 1);
+    qemu_fdt_add_subnode(ams->fdt, "/gpio-keys");
+    qemu_fdt_setprop_string(ams->fdt, "/gpio-keys", "compatible", "gpio-keys");
+    qemu_fdt_setprop_cell(ams->fdt, "/gpio-keys", "#size-cells", 0);
+    qemu_fdt_setprop_cell(ams->fdt, "/gpio-keys", "#address-cells", 1);
 
-    qemu_fdt_add_subnode(vms->fdt, "/gpio-keys/poweroff");
-    qemu_fdt_setprop_string(vms->fdt, "/gpio-keys/poweroff",
+    qemu_fdt_add_subnode(ams->fdt, "/gpio-keys/poweroff");
+    qemu_fdt_setprop_string(ams->fdt, "/gpio-keys/poweroff",
                             "label", "GPIO Key Poweroff");
-    qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys/poweroff", "linux,code",
+    qemu_fdt_setprop_cell(ams->fdt, "/gpio-keys/poweroff", "linux,code",
                           KEY_POWER);
-    qemu_fdt_setprop_cells(vms->fdt, "/gpio-keys/poweroff",
+    qemu_fdt_setprop_cells(ams->fdt, "/gpio-keys/poweroff",
                            "gpios", phandle, 3, 0);
     g_free(nodename);
 }
@@ -847,6 +857,7 @@ static void create_gpio(const VirtMachineState *vms)
 static void create_virtio_devices(const VirtMachineState *vms)
 {
     int i;
+    const ArmMachineState *ams = ARM_MACHINE(vms);
     hwaddr size = vms->memmap[VIRT_MMIO].size;
 
     /* We create the transports in forwards order. Since qbus_realize()
@@ -897,15 +908,15 @@ static void create_virtio_devices(const VirtMachineState *vms)
         hwaddr base = vms->memmap[VIRT_MMIO].base + i * size;
 
         nodename = g_strdup_printf("/virtio_mmio@%" PRIx64, base);
-        qemu_fdt_add_subnode(vms->fdt, nodename);
-        qemu_fdt_setprop_string(vms->fdt, nodename,
+        qemu_fdt_add_subnode(ams->fdt, nodename);
+        qemu_fdt_setprop_string(ams->fdt, nodename,
                                 "compatible", "virtio,mmio");
-        qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
+        qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "reg",
                                      2, base, 2, size);
-        qemu_fdt_setprop_cells(vms->fdt, nodename, "interrupts",
+        qemu_fdt_setprop_cells(ams->fdt, nodename, "interrupts",
                                GIC_FDT_IRQ_TYPE_SPI, irq,
                                GIC_FDT_IRQ_FLAGS_EDGE_LO_HI);
-        qemu_fdt_setprop(vms->fdt, nodename, "dma-coherent", NULL, 0);
+        qemu_fdt_setprop(ams->fdt, nodename, "dma-coherent", NULL, 0);
         g_free(nodename);
     }
 }
@@ -985,6 +996,7 @@ static void virt_flash_fdt(VirtMachineState *vms,
                            MemoryRegion *sysmem,
                            MemoryRegion *secure_sysmem)
 {
+    ArmMachineState *ams = ARM_MACHINE(vms);
     hwaddr flashsize = vms->memmap[VIRT_FLASH].size / 2;
     hwaddr flashbase = vms->memmap[VIRT_FLASH].base;
     char *nodename;
@@ -992,12 +1004,12 @@ static void virt_flash_fdt(VirtMachineState *vms,
     if (sysmem == secure_sysmem) {
         /* Report both flash devices as a single node in the DT */
         nodename = g_strdup_printf("/flash@%" PRIx64, flashbase);
-        qemu_fdt_add_subnode(vms->fdt, nodename);
-        qemu_fdt_setprop_string(vms->fdt, nodename, "compatible", "cfi-flash");
-        qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
+        qemu_fdt_add_subnode(ams->fdt, nodename);
+        qemu_fdt_setprop_string(ams->fdt, nodename, "compatible", "cfi-flash");
+        qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "reg",
                                      2, flashbase, 2, flashsize,
                                      2, flashbase + flashsize, 2, flashsize);
-        qemu_fdt_setprop_cell(vms->fdt, nodename, "bank-width", 4);
+        qemu_fdt_setprop_cell(ams->fdt, nodename, "bank-width", 4);
         g_free(nodename);
     } else {
         /*
@@ -1005,21 +1017,21 @@ static void virt_flash_fdt(VirtMachineState *vms,
          * only visible to the secure world.
          */
         nodename = g_strdup_printf("/secflash@%" PRIx64, flashbase);
-        qemu_fdt_add_subnode(vms->fdt, nodename);
-        qemu_fdt_setprop_string(vms->fdt, nodename, "compatible", "cfi-flash");
-        qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
+        qemu_fdt_add_subnode(ams->fdt, nodename);
+        qemu_fdt_setprop_string(ams->fdt, nodename, "compatible", "cfi-flash");
+        qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "reg",
                                      2, flashbase, 2, flashsize);
-        qemu_fdt_setprop_cell(vms->fdt, nodename, "bank-width", 4);
-        qemu_fdt_setprop_string(vms->fdt, nodename, "status", "disabled");
-        qemu_fdt_setprop_string(vms->fdt, nodename, "secure-status", "okay");
+        qemu_fdt_setprop_cell(ams->fdt, nodename, "bank-width", 4);
+        qemu_fdt_setprop_string(ams->fdt, nodename, "status", "disabled");
+        qemu_fdt_setprop_string(ams->fdt, nodename, "secure-status", "okay");
         g_free(nodename);
 
         nodename = g_strdup_printf("/flash@%" PRIx64, flashbase);
-        qemu_fdt_add_subnode(vms->fdt, nodename);
-        qemu_fdt_setprop_string(vms->fdt, nodename, "compatible", "cfi-flash");
-        qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
+        qemu_fdt_add_subnode(ams->fdt, nodename);
+        qemu_fdt_setprop_string(ams->fdt, nodename, "compatible", "cfi-flash");
+        qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "reg",
                                      2, flashbase + flashsize, 2, flashsize);
-        qemu_fdt_setprop_cell(vms->fdt, nodename, "bank-width", 4);
+        qemu_fdt_setprop_cell(ams->fdt, nodename, "bank-width", 4);
         g_free(nodename);
     }
 }
@@ -1075,6 +1087,7 @@ static bool virt_firmware_init(VirtMachineState *vms,
 static FWCfgState *create_fw_cfg(const VirtMachineState *vms, AddressSpace *as)
 {
     MachineState *ms = MACHINE(vms);
+    const ArmMachineState *ams = ARM_MACHINE(vms);
     hwaddr base = vms->memmap[VIRT_FW_CFG].base;
     hwaddr size = vms->memmap[VIRT_FW_CFG].size;
     FWCfgState *fw_cfg;
@@ -1084,12 +1097,12 @@ static FWCfgState *create_fw_cfg(const VirtMachineState *vms, AddressSpace *as)
     fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)ms->smp.cpus);
 
     nodename = g_strdup_printf("/fw-cfg@%" PRIx64, base);
-    qemu_fdt_add_subnode(vms->fdt, nodename);
-    qemu_fdt_setprop_string(vms->fdt, nodename,
+    qemu_fdt_add_subnode(ams->fdt, nodename);
+    qemu_fdt_setprop_string(ams->fdt, nodename,
                             "compatible", "qemu,fw-cfg-mmio");
-    qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
+    qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "reg",
                                  2, base, 2, size);
-    qemu_fdt_setprop(vms->fdt, nodename, "dma-coherent", NULL, 0);
+    qemu_fdt_setprop(ams->fdt, nodename, "dma-coherent", NULL, 0);
     g_free(nodename);
     return fw_cfg;
 }
@@ -1101,6 +1114,7 @@ static void create_pcie_irq_map(const VirtMachineState *vms,
     int devfn, pin;
     uint32_t full_irq_map[4 * 4 * 10] = { 0 };
     uint32_t *irq_map = full_irq_map;
+    const ArmMachineState *ams = ARM_MACHINE(vms);
 
     for (devfn = 0; devfn <= 0x18; devfn += 0x8) {
         for (pin = 0; pin < 4; pin++) {
@@ -1122,10 +1136,10 @@ static void create_pcie_irq_map(const VirtMachineState *vms,
         }
     }
 
-    qemu_fdt_setprop(vms->fdt, nodename, "interrupt-map",
+    qemu_fdt_setprop(ams->fdt, nodename, "interrupt-map",
                      full_irq_map, sizeof(full_irq_map));
 
-    qemu_fdt_setprop_cells(vms->fdt, nodename, "interrupt-map-mask",
+    qemu_fdt_setprop_cells(ams->fdt, nodename, "interrupt-map-mask",
                            0x1800, 0, 0, /* devfn (PCI_SLOT(3)) */
                            0x7           /* PCI irq */);
 }
@@ -1134,6 +1148,7 @@ static void create_smmu(const VirtMachineState *vms,
                         PCIBus *bus)
 {
     char *node;
+    const ArmMachineState *ams = ARM_MACHINE(vms);
     const char compat[] = "arm,smmu-v3";
     int irq =  vms->irqmap[VIRT_SMMU];
     int i;
@@ -1158,31 +1173,32 @@ static void create_smmu(const VirtMachineState *vms,
     }
 
     node = g_strdup_printf("/smmuv3@%" PRIx64, base);
-    qemu_fdt_add_subnode(vms->fdt, node);
-    qemu_fdt_setprop(vms->fdt, node, "compatible", compat, sizeof(compat));
-    qemu_fdt_setprop_sized_cells(vms->fdt, node, "reg", 2, base, 2, size);
+    qemu_fdt_add_subnode(ams->fdt, node);
+    qemu_fdt_setprop(ams->fdt, node, "compatible", compat, sizeof(compat));
+    qemu_fdt_setprop_sized_cells(ams->fdt, node, "reg", 2, base, 2, size);
 
-    qemu_fdt_setprop_cells(vms->fdt, node, "interrupts",
+    qemu_fdt_setprop_cells(ams->fdt, node, "interrupts",
             GIC_FDT_IRQ_TYPE_SPI, irq    , GIC_FDT_IRQ_FLAGS_EDGE_LO_HI,
             GIC_FDT_IRQ_TYPE_SPI, irq + 1, GIC_FDT_IRQ_FLAGS_EDGE_LO_HI,
             GIC_FDT_IRQ_TYPE_SPI, irq + 2, GIC_FDT_IRQ_FLAGS_EDGE_LO_HI,
             GIC_FDT_IRQ_TYPE_SPI, irq + 3, GIC_FDT_IRQ_FLAGS_EDGE_LO_HI);
 
-    qemu_fdt_setprop(vms->fdt, node, "interrupt-names", irq_names,
+    qemu_fdt_setprop(ams->fdt, node, "interrupt-names", irq_names,
                      sizeof(irq_names));
 
-    qemu_fdt_setprop_cell(vms->fdt, node, "clocks", vms->clock_phandle);
-    qemu_fdt_setprop_string(vms->fdt, node, "clock-names", "apb_pclk");
-    qemu_fdt_setprop(vms->fdt, node, "dma-coherent", NULL, 0);
+    qemu_fdt_setprop_cell(ams->fdt, node, "clocks", vms->clock_phandle);
+    qemu_fdt_setprop_string(ams->fdt, node, "clock-names", "apb_pclk");
+    qemu_fdt_setprop(ams->fdt, node, "dma-coherent", NULL, 0);
 
-    qemu_fdt_setprop_cell(vms->fdt, node, "#iommu-cells", 1);
+    qemu_fdt_setprop_cell(ams->fdt, node, "#iommu-cells", 1);
 
-    qemu_fdt_setprop_cell(vms->fdt, node, "phandle", vms->iommu_phandle);
+    qemu_fdt_setprop_cell(ams->fdt, node, "phandle", vms->iommu_phandle);
     g_free(node);
 }
 
 static void create_pcie(VirtMachineState *vms)
 {
+    ArmMachineState *ams = ARM_MACHINE(vms);
     hwaddr base_mmio = vms->memmap[VIRT_PCIE_MMIO].base;
     hwaddr size_mmio = vms->memmap[VIRT_PCIE_MMIO].size;
     hwaddr base_mmio_high = vms->memmap[VIRT_HIGH_PCIE_MMIO].base;
@@ -1260,27 +1276,27 @@ static void create_pcie(VirtMachineState *vms)
     }
 
     nodename = g_strdup_printf("/pcie@%" PRIx64, base);
-    qemu_fdt_add_subnode(vms->fdt, nodename);
-    qemu_fdt_setprop_string(vms->fdt, nodename,
+    qemu_fdt_add_subnode(ams->fdt, nodename);
+    qemu_fdt_setprop_string(ams->fdt, nodename,
                             "compatible", "pci-host-ecam-generic");
-    qemu_fdt_setprop_string(vms->fdt, nodename, "device_type", "pci");
-    qemu_fdt_setprop_cell(vms->fdt, nodename, "#address-cells", 3);
-    qemu_fdt_setprop_cell(vms->fdt, nodename, "#size-cells", 2);
-    qemu_fdt_setprop_cell(vms->fdt, nodename, "linux,pci-domain", 0);
-    qemu_fdt_setprop_cells(vms->fdt, nodename, "bus-range", 0,
+    qemu_fdt_setprop_string(ams->fdt, nodename, "device_type", "pci");
+    qemu_fdt_setprop_cell(ams->fdt, nodename, "#address-cells", 3);
+    qemu_fdt_setprop_cell(ams->fdt, nodename, "#size-cells", 2);
+    qemu_fdt_setprop_cell(ams->fdt, nodename, "linux,pci-domain", 0);
+    qemu_fdt_setprop_cells(ams->fdt, nodename, "bus-range", 0,
                            nr_pcie_buses - 1);
-    qemu_fdt_setprop(vms->fdt, nodename, "dma-coherent", NULL, 0);
+    qemu_fdt_setprop(ams->fdt, nodename, "dma-coherent", NULL, 0);
 
     if (vms->msi_phandle) {
-        qemu_fdt_setprop_cells(vms->fdt, nodename, "msi-parent",
+        qemu_fdt_setprop_cells(ams->fdt, nodename, "msi-parent",
                                vms->msi_phandle);
     }
 
-    qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
+    qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "reg",
                                  2, base_ecam, 2, size_ecam);
 
     if (vms->highmem) {
-        qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "ranges",
+        qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "ranges",
                                      1, FDT_PCI_RANGE_IOPORT, 2, 0,
                                      2, base_pio, 2, size_pio,
                                      1, FDT_PCI_RANGE_MMIO, 2, base_mmio,
@@ -1289,22 +1305,22 @@ static void create_pcie(VirtMachineState *vms)
                                      2, base_mmio_high,
                                      2, base_mmio_high, 2, size_mmio_high);
     } else {
-        qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "ranges",
+        qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "ranges",
                                      1, FDT_PCI_RANGE_IOPORT, 2, 0,
                                      2, base_pio, 2, size_pio,
                                      1, FDT_PCI_RANGE_MMIO, 2, base_mmio,
                                      2, base_mmio, 2, size_mmio);
     }
 
-    qemu_fdt_setprop_cell(vms->fdt, nodename, "#interrupt-cells", 1);
+    qemu_fdt_setprop_cell(ams->fdt, nodename, "#interrupt-cells", 1);
     create_pcie_irq_map(vms, vms->gic_phandle, irq, nodename);
 
     if (vms->iommu) {
-        vms->iommu_phandle = qemu_fdt_alloc_phandle(vms->fdt);
+        vms->iommu_phandle = qemu_fdt_alloc_phandle(ams->fdt);
 
         create_smmu(vms, pci->bus);
 
-        qemu_fdt_setprop_cells(vms->fdt, nodename, "iommu-map",
+        qemu_fdt_setprop_cells(ams->fdt, nodename, "iommu-map",
                                0x0, vms->iommu_phandle, 0x0, 0x10000);
     }
 
@@ -1341,6 +1357,7 @@ static void create_secure_ram(VirtMachineState *vms,
 {
     MemoryRegion *secram = g_new(MemoryRegion, 1);
     char *nodename;
+    ArmMachineState *ams = ARM_MACHINE(vms);
     hwaddr base = vms->memmap[VIRT_SECURE_MEM].base;
     hwaddr size = vms->memmap[VIRT_SECURE_MEM].size;
 
@@ -1349,20 +1366,21 @@ static void create_secure_ram(VirtMachineState *vms,
     memory_region_add_subregion(secure_sysmem, base, secram);
 
     nodename = g_strdup_printf("/secram@%" PRIx64, base);
-    qemu_fdt_add_subnode(vms->fdt, nodename);
-    qemu_fdt_setprop_string(vms->fdt, nodename, "device_type", "memory");
-    qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", 2, base, 2, size);
-    qemu_fdt_setprop_string(vms->fdt, nodename, "status", "disabled");
-    qemu_fdt_setprop_string(vms->fdt, nodename, "secure-status", "okay");
+    qemu_fdt_add_subnode(ams->fdt, nodename);
+    qemu_fdt_setprop_string(ams->fdt, nodename, "device_type", "memory");
+    qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "reg", 2, base, 2, size);
+    qemu_fdt_setprop_string(ams->fdt, nodename, "status", "disabled");
+    qemu_fdt_setprop_string(ams->fdt, nodename, "secure-status", "okay");
 
     g_free(nodename);
 }
 
 static void *machvirt_dtb(const struct arm_boot_info *binfo, int *fdt_size)
 {
-    const VirtMachineState *board = container_of(binfo, VirtMachineState,
+    const VirtMachineState *vms = container_of(binfo, VirtMachineState,
                                                  bootinfo);
 
+    ArmMachineState *board = ARM_MACHINE(vms);
     *fdt_size = board->fdt_size;
     return board->fdt;
 }
@@ -1400,6 +1418,7 @@ void virt_machine_done(Notifier *notifier, void *data)
     VirtMachineState *vms = container_of(notifier, VirtMachineState,
                                          machine_done);
     MachineState *ms = MACHINE(vms);
+    ArmMachineState *ams = ARM_MACHINE(vms);
     ARMCPU *cpu = ARM_CPU(first_cpu);
     struct arm_boot_info *info = &vms->bootinfo;
     AddressSpace *as = arm_boot_address_space(cpu, info);
@@ -1412,7 +1431,7 @@ void virt_machine_done(Notifier *notifier, void *data)
      * while qemu takes charge of the qom stuff.
      */
     if (info->dtb_filename == NULL) {
-        platform_bus_add_all_fdt_nodes(vms->fdt, "/intc",
+        platform_bus_add_all_fdt_nodes(ams->fdt, "/intc",
                                        vms->memmap[VIRT_PLATFORM_BUS].base,
                                        vms->memmap[VIRT_PLATFORM_BUS].size,
                                        vms->irqmap[VIRT_PLATFORM_BUS]);
diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h
index 2aa9ee3d05..b3b3daa95a 100644
--- a/include/hw/arm/arm.h
+++ b/include/hw/arm/arm.h
@@ -87,6 +87,8 @@ typedef struct {
 
 typedef struct {
     MachineState parent;
+    void *fdt;
+    int fdt_size;
 } ArmMachineState;
 
 #define TYPE_ARM_MACHINE   MACHINE_TYPE_NAME("arm")
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index aa0cc852a5..ad353bad92 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -74,8 +74,6 @@ typedef struct {
     MemMapEntry *memmap;
     const int *irqmap;
     int smp_cpus;
-    void *fdt;
-    int fdt_size;
     uint32_t clock_phandle;
     uint32_t gic_phandle;
     uint32_t msi_phandle;
-- 
2.18.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH RFC 03/16] hw/arm: move shared memmap member to ArmMachine
  2020-02-17  7:51 [PATCH RFC 00/16] Implement Microvm for aarch64 architecture Xu Yandong
  2020-02-17  7:51 ` [PATCH RFC 01/16] hw/arm/arm: Introduce ArmMachineState and ArmMachineClass Xu Yandong
  2020-02-17  7:51 ` [PATCH RFC 02/16] hw/arm: move shared fdt member to ArmMachine Xu Yandong
@ 2020-02-17  7:51 ` Xu Yandong
  2020-02-17  7:51 ` [PATCH RFC 04/16] hw/arm: move shared irqmap " Xu Yandong
                   ` (14 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Xu Yandong @ 2020-02-17  7:51 UTC (permalink / raw)
  To: peter.maydell
  Cc: zhang.zhanghailiang, slp, Michael S. Tsirkin, Xu Yandong,
	qemu-devel, Shannon Zhao, qemu-arm, Igor Mammedov, wu.wubin

Move memmap member from VirtMachineState to ArmMachineState.

Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Shannon Zhao <shannon.zhaosl@gmail.com>
Signed-off-by: Xu Yandong <xuyandong2@huawei.com>
---
 hw/arm/virt-acpi-build.c |  21 +++--
 hw/arm/virt.c            | 178 ++++++++++++++++++++-------------------
 include/hw/arm/arm.h     |   1 +
 include/hw/arm/virt.h    |   4 +-
 4 files changed, 110 insertions(+), 94 deletions(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index bd5f771e9b..ef61a651c1 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -43,6 +43,7 @@
 #include "hw/acpi/generic_event_device.h"
 #include "hw/pci/pcie_host.h"
 #include "hw/pci/pci.h"
+#include "hw/arm/arm.h"
 #include "hw/arm/virt.h"
 #include "sysemu/numa.h"
 #include "sysemu/reset.h"
@@ -383,6 +384,7 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
     AcpiIortSmmu3 *smmu;
     size_t node_size, iort_node_offset, iort_length, smmu_offset = 0;
     AcpiIortRC *rc;
+    ArmMachineState *ams = ARM_MACHINE(vms);
 
     iort = acpi_data_push(table_data, sizeof(*iort));
 
@@ -424,7 +426,7 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
         smmu->length = cpu_to_le16(node_size);
         smmu->mapping_count = cpu_to_le32(1);
         smmu->mapping_offset = cpu_to_le32(sizeof(*smmu));
-        smmu->base_address = cpu_to_le64(vms->memmap[VIRT_SMMU].base);
+        smmu->base_address = cpu_to_le64(ams->memmap[VIRT_SMMU].base);
         smmu->flags = cpu_to_le32(ACPI_IORT_SMMU_V3_COHACC_OVERRIDE);
         smmu->event_gsiv = cpu_to_le32(irq);
         smmu->pri_gsiv = cpu_to_le32(irq + 1);
@@ -484,7 +486,8 @@ static void
 build_spcr(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
 {
     AcpiSerialPortConsoleRedirection *spcr;
-    const MemMapEntry *uart_memmap = &vms->memmap[VIRT_UART];
+    ArmMachineState *ams = ARM_MACHINE(vms);
+    const MemMapEntry *uart_memmap = &ams->memmap[VIRT_UART];
     int irq = vms->irqmap[VIRT_UART] + ARM_SPI_BASE;
     int spcr_start = table_data->len;
 
@@ -524,6 +527,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
     uint64_t mem_base;
     MachineClass *mc = MACHINE_GET_CLASS(vms);
     MachineState *ms = MACHINE(vms);
+    ArmMachineState *ams = ARM_MACHINE(vms);
     const CPUArchIdList *cpu_list = mc->possible_cpu_arch_ids(ms);
 
     srat_start = table_data->len;
@@ -539,7 +543,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
         core->flags = cpu_to_le32(1);
     }
 
-    mem_base = vms->memmap[VIRT_MEM].base;
+    mem_base = ams->memmap[VIRT_MEM].base;
     for (i = 0; i < ms->numa_state->num_nodes; ++i) {
         if (ms->numa_state->nodes[i].node_mem > 0) {
             numamem = acpi_data_push(table_data, sizeof(*numamem));
@@ -602,8 +606,9 @@ static void
 build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
 {
     VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
+    ArmMachineState *ams = ARM_MACHINE(vms);
     int madt_start = table_data->len;
-    const MemMapEntry *memmap = vms->memmap;
+    const MemMapEntry *memmap = ams->memmap;
     const int *irqmap = vms->irqmap;
     AcpiMultipleApicTable *madt;
     AcpiMadtGenericDistributor *gicd;
@@ -723,7 +728,8 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
 {
     Aml *scope, *dsdt;
     MachineState *ms = MACHINE(vms);
-    const MemMapEntry *memmap = vms->memmap;
+    ArmMachineState *ams = ARM_MACHINE(vms);
+    const MemMapEntry *memmap = ams->memmap;
     const int *irqmap = vms->irqmap;
 
     dsdt = init_aml_allocator();
@@ -796,6 +802,7 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
     unsigned dsdt, xsdt;
     GArray *tables_blob = tables->table_data;
     MachineState *ms = MACHINE(vms);
+    ArmMachineState *ams = ARM_MACHINE(vms);
 
     table_offsets = g_array_new(false, true /* clear */,
                                         sizeof(uint32_t));
@@ -821,8 +828,8 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
     acpi_add_table(table_offsets, tables_blob);
     {
         AcpiMcfgInfo mcfg = {
-           .base = vms->memmap[VIRT_ECAM_ID(vms->highmem_ecam)].base,
-           .size = vms->memmap[VIRT_ECAM_ID(vms->highmem_ecam)].size,
+           .base = ams->memmap[VIRT_ECAM_ID(vms->highmem_ecam)].base,
+           .size = ams->memmap[VIRT_ECAM_ID(vms->highmem_ecam)].size,
         };
         build_mcfg(tables_blob, tables->linker, &mcfg);
     }
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 41b2076ce1..1dea640719 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -395,14 +395,14 @@ static void fdt_add_its_gic_node(VirtMachineState *vms)
 
     vms->msi_phandle = qemu_fdt_alloc_phandle(ams->fdt);
     nodename = g_strdup_printf("/intc/its@%" PRIx64,
-                               vms->memmap[VIRT_GIC_ITS].base);
+                               ams->memmap[VIRT_GIC_ITS].base);
     qemu_fdt_add_subnode(ams->fdt, nodename);
     qemu_fdt_setprop_string(ams->fdt, nodename, "compatible",
                             "arm,gic-v3-its");
     qemu_fdt_setprop(ams->fdt, nodename, "msi-controller", NULL, 0);
     qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "reg",
-                                 2, vms->memmap[VIRT_GIC_ITS].base,
-                                 2, vms->memmap[VIRT_GIC_ITS].size);
+                                 2, ams->memmap[VIRT_GIC_ITS].base,
+                                 2, ams->memmap[VIRT_GIC_ITS].size);
     qemu_fdt_setprop_cell(ams->fdt, nodename, "phandle", vms->msi_phandle);
     g_free(nodename);
 }
@@ -413,15 +413,15 @@ static void fdt_add_v2m_gic_node(VirtMachineState *vms)
     ArmMachineState *ams = ARM_MACHINE(vms);
 
     nodename = g_strdup_printf("/intc/v2m@%" PRIx64,
-                               vms->memmap[VIRT_GIC_V2M].base);
+                               ams->memmap[VIRT_GIC_V2M].base);
     vms->msi_phandle = qemu_fdt_alloc_phandle(ams->fdt);
     qemu_fdt_add_subnode(ams->fdt, nodename);
     qemu_fdt_setprop_string(ams->fdt, nodename, "compatible",
                             "arm,gic-v2m-frame");
     qemu_fdt_setprop(ams->fdt, nodename, "msi-controller", NULL, 0);
     qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "reg",
-                                 2, vms->memmap[VIRT_GIC_V2M].base,
-                                 2, vms->memmap[VIRT_GIC_V2M].size);
+                                 2, ams->memmap[VIRT_GIC_V2M].base,
+                                 2, ams->memmap[VIRT_GIC_V2M].size);
     qemu_fdt_setprop_cell(ams->fdt, nodename, "phandle", vms->msi_phandle);
     g_free(nodename);
 }
@@ -435,7 +435,7 @@ static void fdt_add_gic_node(VirtMachineState *vms)
     qemu_fdt_setprop_cell(ams->fdt, "/", "interrupt-parent", vms->gic_phandle);
 
     nodename = g_strdup_printf("/intc@%" PRIx64,
-                               vms->memmap[VIRT_GIC_DIST].base);
+                               ams->memmap[VIRT_GIC_DIST].base);
     qemu_fdt_add_subnode(ams->fdt, nodename);
     qemu_fdt_setprop_cell(ams->fdt, nodename, "#interrupt-cells", 3);
     qemu_fdt_setprop(ams->fdt, nodename, "interrupt-controller", NULL, 0);
@@ -453,18 +453,18 @@ static void fdt_add_gic_node(VirtMachineState *vms)
 
         if (nb_redist_regions == 1) {
             qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "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, ams->memmap[VIRT_GIC_DIST].base,
+                                         2, ams->memmap[VIRT_GIC_DIST].size,
+                                         2, ams->memmap[VIRT_GIC_REDIST].base,
+                                         2, ams->memmap[VIRT_GIC_REDIST].size);
         } else {
             qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "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_HIGH_GIC_REDIST2].base,
-                                 2, vms->memmap[VIRT_HIGH_GIC_REDIST2].size);
+                                 2, ams->memmap[VIRT_GIC_DIST].base,
+                                 2, ams->memmap[VIRT_GIC_DIST].size,
+                                 2, ams->memmap[VIRT_GIC_REDIST].base,
+                                 2, ams->memmap[VIRT_GIC_REDIST].size,
+                                 2, ams->memmap[VIRT_HIGH_GIC_REDIST2].base,
+                                 2, ams->memmap[VIRT_HIGH_GIC_REDIST2].size);
         }
 
         if (vms->virt) {
@@ -478,20 +478,20 @@ static void fdt_add_gic_node(VirtMachineState *vms)
                                 "arm,cortex-a15-gic");
         if (!vms->virt) {
             qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "reg",
-                                         2, vms->memmap[VIRT_GIC_DIST].base,
-                                         2, vms->memmap[VIRT_GIC_DIST].size,
-                                         2, vms->memmap[VIRT_GIC_CPU].base,
-                                         2, vms->memmap[VIRT_GIC_CPU].size);
+                                         2, ams->memmap[VIRT_GIC_DIST].base,
+                                         2, ams->memmap[VIRT_GIC_DIST].size,
+                                         2, ams->memmap[VIRT_GIC_CPU].base,
+                                         2, ams->memmap[VIRT_GIC_CPU].size);
         } else {
             qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "reg",
-                                         2, vms->memmap[VIRT_GIC_DIST].base,
-                                         2, vms->memmap[VIRT_GIC_DIST].size,
-                                         2, vms->memmap[VIRT_GIC_CPU].base,
-                                         2, vms->memmap[VIRT_GIC_CPU].size,
-                                         2, vms->memmap[VIRT_GIC_HYP].base,
-                                         2, vms->memmap[VIRT_GIC_HYP].size,
-                                         2, vms->memmap[VIRT_GIC_VCPU].base,
-                                         2, vms->memmap[VIRT_GIC_VCPU].size);
+                                         2, ams->memmap[VIRT_GIC_DIST].base,
+                                         2, ams->memmap[VIRT_GIC_DIST].size,
+                                         2, ams->memmap[VIRT_GIC_CPU].base,
+                                         2, ams->memmap[VIRT_GIC_CPU].size,
+                                         2, ams->memmap[VIRT_GIC_HYP].base,
+                                         2, ams->memmap[VIRT_GIC_HYP].size,
+                                         2, ams->memmap[VIRT_GIC_VCPU].base,
+                                         2, ams->memmap[VIRT_GIC_VCPU].size);
             qemu_fdt_setprop_cells(ams->fdt, nodename, "interrupts",
                                    GIC_FDT_IRQ_TYPE_PPI, ARCH_GIC_MAINT_IRQ,
                                    GIC_FDT_IRQ_FLAGS_LEVEL_HI);
@@ -543,6 +543,7 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms)
 {
     DeviceState *dev;
     MachineState *ms = MACHINE(vms);
+    ArmMachineState *ams = ARM_MACHINE(vms);
     int irq = vms->irqmap[VIRT_ACPI_GED];
     uint32_t event = ACPI_GED_PWR_DOWN_EVT;
 
@@ -553,8 +554,8 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms)
     dev = qdev_create(NULL, TYPE_ACPI_GED);
     qdev_prop_set_uint32(dev, "ged-event", event);
 
-    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vms->memmap[VIRT_ACPI_GED].base);
-    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, vms->memmap[VIRT_PCDIMM_ACPI].base);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, ams->memmap[VIRT_ACPI_GED].base);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, ams->memmap[VIRT_PCDIMM_ACPI].base);
     sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(vms->gic, irq));
 
     qdev_init_nofail(dev);
@@ -564,6 +565,7 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms)
 
 static void create_its(VirtMachineState *vms)
 {
+    ArmMachineState *ams = ARM_MACHINE(vms);
     const char *itsclass = its_class_name();
     DeviceState *dev;
 
@@ -577,7 +579,7 @@ static void create_its(VirtMachineState *vms)
     object_property_set_link(OBJECT(dev), OBJECT(vms->gic), "parent-gicv3",
                              &error_abort);
     qdev_init_nofail(dev);
-    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vms->memmap[VIRT_GIC_ITS].base);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, ams->memmap[VIRT_GIC_ITS].base);
 
     fdt_add_its_gic_node(vms);
 }
@@ -585,11 +587,12 @@ static void create_its(VirtMachineState *vms)
 static void create_v2m(VirtMachineState *vms)
 {
     int i;
+    ArmMachineState *ams = ARM_MACHINE(vms);
     int irq = vms->irqmap[VIRT_GIC_V2M];
     DeviceState *dev;
 
     dev = qdev_create(NULL, "arm-gicv2m");
-    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vms->memmap[VIRT_GIC_V2M].base);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, ams->memmap[VIRT_GIC_V2M].base);
     qdev_prop_set_uint32(dev, "base-spi", irq);
     qdev_prop_set_uint32(dev, "num-spi", NUM_GICV2M_SPIS);
     qdev_init_nofail(dev);
@@ -605,6 +608,7 @@ static void create_v2m(VirtMachineState *vms)
 static void create_gic(VirtMachineState *vms)
 {
     MachineState *ms = MACHINE(vms);
+    ArmMachineState *ams = ARM_MACHINE(vms);
     /* We create a standalone GIC */
     SysBusDevice *gicbusdev;
     const char *gictype;
@@ -627,7 +631,7 @@ static void create_gic(VirtMachineState *vms)
 
     if (type == 3) {
         uint32_t redist0_capacity =
-                    vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
+                    ams->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);
@@ -638,7 +642,7 @@ static void create_gic(VirtMachineState *vms)
 
         if (nb_redist_regions == 2) {
             uint32_t redist1_capacity =
-                    vms->memmap[VIRT_HIGH_GIC_REDIST2].size / GICV3_REDIST_SIZE;
+                    ams->memmap[VIRT_HIGH_GIC_REDIST2].size / GICV3_REDIST_SIZE;
 
             qdev_prop_set_uint32(vms->gic, "redist-region-count[1]",
                 MIN(smp_cpus - redist0_count, redist1_capacity));
@@ -651,18 +655,18 @@ static void create_gic(VirtMachineState *vms)
     }
     qdev_init_nofail(vms->gic);
     gicbusdev = SYS_BUS_DEVICE(vms->gic);
-    sysbus_mmio_map(gicbusdev, 0, vms->memmap[VIRT_GIC_DIST].base);
+    sysbus_mmio_map(gicbusdev, 0, ams->memmap[VIRT_GIC_DIST].base);
     if (type == 3) {
-        sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_REDIST].base);
+        sysbus_mmio_map(gicbusdev, 1, ams->memmap[VIRT_GIC_REDIST].base);
         if (nb_redist_regions == 2) {
             sysbus_mmio_map(gicbusdev, 2,
-                            vms->memmap[VIRT_HIGH_GIC_REDIST2].base);
+                            ams->memmap[VIRT_HIGH_GIC_REDIST2].base);
         }
     } else {
-        sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_CPU].base);
+        sysbus_mmio_map(gicbusdev, 1, ams->memmap[VIRT_GIC_CPU].base);
         if (vms->virt) {
-            sysbus_mmio_map(gicbusdev, 2, vms->memmap[VIRT_GIC_HYP].base);
-            sysbus_mmio_map(gicbusdev, 3, vms->memmap[VIRT_GIC_VCPU].base);
+            sysbus_mmio_map(gicbusdev, 2, ams->memmap[VIRT_GIC_HYP].base);
+            sysbus_mmio_map(gicbusdev, 3, ams->memmap[VIRT_GIC_VCPU].base);
         }
     }
 
@@ -728,8 +732,8 @@ static void create_uart(const VirtMachineState *vms, int uart,
 {
     char *nodename;
     const ArmMachineState *ams = ARM_MACHINE(vms);
-    hwaddr base = vms->memmap[uart].base;
-    hwaddr size = vms->memmap[uart].size;
+    hwaddr base = ams->memmap[uart].base;
+    hwaddr size = ams->memmap[uart].size;
     int irq = vms->irqmap[uart];
     const char compat[] = "arm,pl011\0arm,primecell";
     const char clocknames[] = "uartclk\0apb_pclk";
@@ -776,8 +780,8 @@ static void create_rtc(const VirtMachineState *vms)
 {
     char *nodename;
     const ArmMachineState *ams = ARM_MACHINE(vms);
-    hwaddr base = vms->memmap[VIRT_RTC].base;
-    hwaddr size = vms->memmap[VIRT_RTC].size;
+    hwaddr base = ams->memmap[VIRT_RTC].base;
+    hwaddr size = ams->memmap[VIRT_RTC].size;
     int irq = vms->irqmap[VIRT_RTC];
     const char compat[] = "arm,pl031\0arm,primecell";
 
@@ -814,8 +818,8 @@ static void create_gpio(const VirtMachineState *vms)
     char *nodename;
     DeviceState *pl061_dev;
     const ArmMachineState *ams = ARM_MACHINE(vms);
-    hwaddr base = vms->memmap[VIRT_GPIO].base;
-    hwaddr size = vms->memmap[VIRT_GPIO].size;
+    hwaddr base = ams->memmap[VIRT_GPIO].base;
+    hwaddr size = ams->memmap[VIRT_GPIO].size;
     int irq = vms->irqmap[VIRT_GPIO];
     const char compat[] = "arm,pl061\0arm,primecell";
 
@@ -858,7 +862,7 @@ static void create_virtio_devices(const VirtMachineState *vms)
 {
     int i;
     const ArmMachineState *ams = ARM_MACHINE(vms);
-    hwaddr size = vms->memmap[VIRT_MMIO].size;
+    hwaddr size = ams->memmap[VIRT_MMIO].size;
 
     /* We create the transports in forwards order. Since qbus_realize()
      * prepends (not appends) new child buses, the incrementing loop below will
@@ -889,7 +893,7 @@ static void create_virtio_devices(const VirtMachineState *vms)
      */
     for (i = 0; i < NUM_VIRTIO_TRANSPORTS; i++) {
         int irq = vms->irqmap[VIRT_MMIO] + i;
-        hwaddr base = vms->memmap[VIRT_MMIO].base + i * size;
+        hwaddr base = ams->memmap[VIRT_MMIO].base + i * size;
 
         sysbus_create_simple("virtio-mmio", base,
                              qdev_get_gpio_in(vms->gic, irq));
@@ -905,7 +909,7 @@ static void create_virtio_devices(const VirtMachineState *vms)
     for (i = NUM_VIRTIO_TRANSPORTS - 1; i >= 0; i--) {
         char *nodename;
         int irq = vms->irqmap[VIRT_MMIO] + i;
-        hwaddr base = vms->memmap[VIRT_MMIO].base + i * size;
+        hwaddr base = ams->memmap[VIRT_MMIO].base + i * size;
 
         nodename = g_strdup_printf("/virtio_mmio@%" PRIx64, base);
         qemu_fdt_add_subnode(ams->fdt, nodename);
@@ -975,6 +979,7 @@ static void virt_flash_map(VirtMachineState *vms,
                            MemoryRegion *sysmem,
                            MemoryRegion *secure_sysmem)
 {
+    ArmMachineState *ams = ARM_MACHINE(vms);
     /*
      * Map two flash devices to fill the VIRT_FLASH space in the memmap.
      * sysmem is the system memory space. secure_sysmem is the secure view
@@ -983,8 +988,8 @@ static void virt_flash_map(VirtMachineState *vms,
      * If sysmem == secure_sysmem this means there is no separate Secure
      * address space and both flash devices are generally visible.
      */
-    hwaddr flashsize = vms->memmap[VIRT_FLASH].size / 2;
-    hwaddr flashbase = vms->memmap[VIRT_FLASH].base;
+    hwaddr flashsize = ams->memmap[VIRT_FLASH].size / 2;
+    hwaddr flashbase = ams->memmap[VIRT_FLASH].base;
 
     virt_flash_map1(vms->flash[0], flashbase, flashsize,
                     secure_sysmem);
@@ -997,8 +1002,8 @@ static void virt_flash_fdt(VirtMachineState *vms,
                            MemoryRegion *secure_sysmem)
 {
     ArmMachineState *ams = ARM_MACHINE(vms);
-    hwaddr flashsize = vms->memmap[VIRT_FLASH].size / 2;
-    hwaddr flashbase = vms->memmap[VIRT_FLASH].base;
+    hwaddr flashsize = ams->memmap[VIRT_FLASH].size / 2;
+    hwaddr flashbase = ams->memmap[VIRT_FLASH].base;
     char *nodename;
 
     if (sysmem == secure_sysmem) {
@@ -1088,8 +1093,8 @@ static FWCfgState *create_fw_cfg(const VirtMachineState *vms, AddressSpace *as)
 {
     MachineState *ms = MACHINE(vms);
     const ArmMachineState *ams = ARM_MACHINE(vms);
-    hwaddr base = vms->memmap[VIRT_FW_CFG].base;
-    hwaddr size = vms->memmap[VIRT_FW_CFG].size;
+    hwaddr base = ams->memmap[VIRT_FW_CFG].base;
+    hwaddr size = ams->memmap[VIRT_FW_CFG].size;
     FWCfgState *fw_cfg;
     char *nodename;
 
@@ -1152,8 +1157,8 @@ static void create_smmu(const VirtMachineState *vms,
     const char compat[] = "arm,smmu-v3";
     int irq =  vms->irqmap[VIRT_SMMU];
     int i;
-    hwaddr base = vms->memmap[VIRT_SMMU].base;
-    hwaddr size = vms->memmap[VIRT_SMMU].size;
+    hwaddr base = ams->memmap[VIRT_SMMU].base;
+    hwaddr size = ams->memmap[VIRT_SMMU].size;
     const char irq_names[] = "eventq\0priq\0cmdq-sync\0gerror";
     DeviceState *dev;
 
@@ -1199,12 +1204,12 @@ static void create_smmu(const VirtMachineState *vms,
 static void create_pcie(VirtMachineState *vms)
 {
     ArmMachineState *ams = ARM_MACHINE(vms);
-    hwaddr base_mmio = vms->memmap[VIRT_PCIE_MMIO].base;
-    hwaddr size_mmio = vms->memmap[VIRT_PCIE_MMIO].size;
-    hwaddr base_mmio_high = vms->memmap[VIRT_HIGH_PCIE_MMIO].base;
-    hwaddr size_mmio_high = vms->memmap[VIRT_HIGH_PCIE_MMIO].size;
-    hwaddr base_pio = vms->memmap[VIRT_PCIE_PIO].base;
-    hwaddr size_pio = vms->memmap[VIRT_PCIE_PIO].size;
+    hwaddr base_mmio = ams->memmap[VIRT_PCIE_MMIO].base;
+    hwaddr size_mmio = ams->memmap[VIRT_PCIE_MMIO].size;
+    hwaddr base_mmio_high = ams->memmap[VIRT_HIGH_PCIE_MMIO].base;
+    hwaddr size_mmio_high = ams->memmap[VIRT_HIGH_PCIE_MMIO].size;
+    hwaddr base_pio = ams->memmap[VIRT_PCIE_PIO].base;
+    hwaddr size_pio = ams->memmap[VIRT_PCIE_PIO].size;
     hwaddr base_ecam, size_ecam;
     hwaddr base = base_mmio;
     int nr_pcie_buses;
@@ -1222,8 +1227,8 @@ static void create_pcie(VirtMachineState *vms)
     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;
+    base_ecam = ams->memmap[ecam_id].base;
+    size_ecam = ams->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);
@@ -1333,11 +1338,12 @@ static void create_platform_bus(VirtMachineState *vms)
     SysBusDevice *s;
     int i;
     MemoryRegion *sysmem = get_system_memory();
+    ArmMachineState *ams = ARM_MACHINE(vms);
 
     dev = qdev_create(NULL, TYPE_PLATFORM_BUS_DEVICE);
     dev->id = TYPE_PLATFORM_BUS_DEVICE;
     qdev_prop_set_uint32(dev, "num_irqs", PLATFORM_BUS_NUM_IRQS);
-    qdev_prop_set_uint32(dev, "mmio_size", vms->memmap[VIRT_PLATFORM_BUS].size);
+    qdev_prop_set_uint32(dev, "mmio_size", ams->memmap[VIRT_PLATFORM_BUS].size);
     qdev_init_nofail(dev);
     vms->platform_bus_dev = dev;
 
@@ -1348,7 +1354,7 @@ static void create_platform_bus(VirtMachineState *vms)
     }
 
     memory_region_add_subregion(sysmem,
-                                vms->memmap[VIRT_PLATFORM_BUS].base,
+                                ams->memmap[VIRT_PLATFORM_BUS].base,
                                 sysbus_mmio_get_region(s, 0));
 }
 
@@ -1358,8 +1364,8 @@ static void create_secure_ram(VirtMachineState *vms,
     MemoryRegion *secram = g_new(MemoryRegion, 1);
     char *nodename;
     ArmMachineState *ams = ARM_MACHINE(vms);
-    hwaddr base = vms->memmap[VIRT_SECURE_MEM].base;
-    hwaddr size = vms->memmap[VIRT_SECURE_MEM].size;
+    hwaddr base = ams->memmap[VIRT_SECURE_MEM].base;
+    hwaddr size = ams->memmap[VIRT_SECURE_MEM].size;
 
     memory_region_init_ram(secram, NULL, "virt.secure-ram", size,
                            &error_fatal);
@@ -1432,8 +1438,8 @@ void virt_machine_done(Notifier *notifier, void *data)
      */
     if (info->dtb_filename == NULL) {
         platform_bus_add_all_fdt_nodes(ams->fdt, "/intc",
-                                       vms->memmap[VIRT_PLATFORM_BUS].base,
-                                       vms->memmap[VIRT_PLATFORM_BUS].size,
+                                       ams->memmap[VIRT_PLATFORM_BUS].base,
+                                       ams->memmap[VIRT_PLATFORM_BUS].size,
                                        vms->irqmap[VIRT_PLATFORM_BUS]);
     }
     if (arm_load_dtb(info->dtb_start, info, info->dtb_limit, as, ms) < 0) {
@@ -1470,13 +1476,14 @@ static uint64_t virt_cpu_mp_affinity(VirtMachineState *vms, int idx)
 static void virt_set_memmap(VirtMachineState *vms)
 {
     MachineState *ms = MACHINE(vms);
+    ArmMachineState *ams = ARM_MACHINE(vms);
     hwaddr base, device_memory_base, device_memory_size;
     int i;
 
-    vms->memmap = extended_memmap;
+    ams->memmap = extended_memmap;
 
     for (i = 0; i < ARRAY_SIZE(base_memmap); i++) {
-        vms->memmap[i] = base_memmap[i];
+        ams->memmap[i] = base_memmap[i];
     }
 
     if (ms->ram_slots > ACPI_MAX_RAM_SLOTS) {
@@ -1493,7 +1500,7 @@ static void virt_set_memmap(VirtMachineState *vms)
      * The device region size assumes 1GiB page max alignment per slot.
      */
     device_memory_base =
-        ROUND_UP(vms->memmap[VIRT_MEM].base + ms->ram_size, GiB);
+        ROUND_UP(ams->memmap[VIRT_MEM].base + ms->ram_size, GiB);
     device_memory_size = ms->maxram_size - ms->ram_size + ms->ram_slots * GiB;
 
     /* Base address of the high IO region */
@@ -1502,16 +1509,16 @@ static void virt_set_memmap(VirtMachineState *vms)
         error_report("maxmem/slots too huge");
         exit(EXIT_FAILURE);
     }
-    if (base < vms->memmap[VIRT_MEM].base + LEGACY_RAMLIMIT_BYTES) {
-        base = vms->memmap[VIRT_MEM].base + LEGACY_RAMLIMIT_BYTES;
+    if (base < ams->memmap[VIRT_MEM].base + LEGACY_RAMLIMIT_BYTES) {
+        base = ams->memmap[VIRT_MEM].base + LEGACY_RAMLIMIT_BYTES;
     }
 
     for (i = VIRT_LOWMEMMAP_LAST; i < ARRAY_SIZE(extended_memmap); i++) {
         hwaddr size = extended_memmap[i].size;
 
         base = ROUND_UP(base, size);
-        vms->memmap[i].base = base;
-        vms->memmap[i].size = size;
+        ams->memmap[i].base = base;
+        ams->memmap[i].size = size;
         base += size;
     }
     vms->highest_gpa = base - 1;
@@ -1526,6 +1533,7 @@ static void virt_set_memmap(VirtMachineState *vms)
 static void machvirt_init(MachineState *machine)
 {
     VirtMachineState *vms = VIRT_MACHINE(machine);
+    ArmMachineState *ams = ARM_MACHINE(vms);
     VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(machine);
     MachineClass *mc = MACHINE_GET_CLASS(machine);
     const CPUArchIdList *possible_cpus;
@@ -1543,7 +1551,7 @@ static void machvirt_init(MachineState *machine)
      * In accelerated mode, the memory map is computed earlier in kvm_type()
      * to create a VM with the right number of IPA bits.
      */
-    if (!vms->memmap) {
+    if (!ams->memmap) {
         virt_set_memmap(vms);
     }
 
@@ -1619,9 +1627,9 @@ static void machvirt_init(MachineState *machine)
      */
     if (vms->gic_version == 3) {
         virt_max_cpus =
-            vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
+            ams->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
         virt_max_cpus +=
-            vms->memmap[VIRT_HIGH_GIC_REDIST2].size / GICV3_REDIST_SIZE;
+            ams->memmap[VIRT_HIGH_GIC_REDIST2].size / GICV3_REDIST_SIZE;
     } else {
         virt_max_cpus = GIC_NCPU;
     }
@@ -1693,7 +1701,7 @@ static void machvirt_init(MachineState *machine)
         }
 
         if (object_property_find(cpuobj, "reset-cbar", NULL)) {
-            object_property_set_int(cpuobj, vms->memmap[VIRT_CPUPERIPHS].base,
+            object_property_set_int(cpuobj, ams->memmap[VIRT_CPUPERIPHS].base,
                                     "reset-cbar", &error_abort);
         }
 
@@ -1728,7 +1736,7 @@ static void machvirt_init(MachineState *machine)
 
     memory_region_allocate_system_memory(ram, NULL, "mach-virt.ram",
                                          machine->ram_size);
-    memory_region_add_subregion(sysmem, vms->memmap[VIRT_MEM].base, ram);
+    memory_region_add_subregion(sysmem, ams->memmap[VIRT_MEM].base, ram);
     if (machine->device_memory) {
         memory_region_add_subregion(sysmem, machine->device_memory->base,
                                     &machine->device_memory->mr);
@@ -1777,7 +1785,7 @@ static void machvirt_init(MachineState *machine)
     vms->bootinfo.ram_size = machine->ram_size;
     vms->bootinfo.nb_cpus = smp_cpus;
     vms->bootinfo.board_id = -1;
-    vms->bootinfo.loader_start = vms->memmap[VIRT_MEM].base;
+    vms->bootinfo.loader_start = ams->memmap[VIRT_MEM].base;
     vms->bootinfo.get_dtb = machvirt_dtb;
     vms->bootinfo.skip_dtb_autoload = true;
     vms->bootinfo.firmware_loaded = firmware_loaded;
diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h
index b3b3daa95a..f269668d41 100644
--- a/include/hw/arm/arm.h
+++ b/include/hw/arm/arm.h
@@ -87,6 +87,7 @@ typedef struct {
 
 typedef struct {
     MachineState parent;
+    MemMapEntry *memmap;
     void *fdt;
     int fdt_size;
 } ArmMachineState;
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index ad353bad92..1b460d8d31 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -71,7 +71,6 @@ typedef struct {
     int32_t gic_version;
     VirtIOMMUType iommu;
     struct arm_boot_info bootinfo;
-    MemMapEntry *memmap;
     const int *irqmap;
     int smp_cpus;
     uint32_t clock_phandle;
@@ -100,8 +99,9 @@ void virt_acpi_setup(VirtMachineState *vms);
 /* Return the number of used redistributor regions  */
 static inline int virt_gicv3_redist_region_count(VirtMachineState *vms)
 {
+    ArmMachineState *ams = ARM_MACHINE(vms);
     uint32_t redist0_capacity =
-                vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
+                ams->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
 
     assert(vms->gic_version == 3);
 
-- 
2.18.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH RFC 04/16] hw/arm: move shared irqmap member to ArmMachine
  2020-02-17  7:51 [PATCH RFC 00/16] Implement Microvm for aarch64 architecture Xu Yandong
                   ` (2 preceding siblings ...)
  2020-02-17  7:51 ` [PATCH RFC 03/16] hw/arm: move shared memmap " Xu Yandong
@ 2020-02-17  7:51 ` Xu Yandong
  2020-02-17  7:51 ` [PATCH RFC 05/16] hw/arm: move shared smp_cpus " Xu Yandong
                   ` (13 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Xu Yandong @ 2020-02-17  7:51 UTC (permalink / raw)
  To: peter.maydell
  Cc: zhang.zhanghailiang, slp, Michael S. Tsirkin, Xu Yandong,
	qemu-devel, Shannon Zhao, qemu-arm, Igor Mammedov, wu.wubin

Move irqmap member from VirtMachineState to ArmMachineState.

Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Shannon Zhao <shannon.zhaosl@gmail.com>
Signed-off-by: Xu Yandong <xuyandong2@huawei.com>
---
 hw/arm/virt-acpi-build.c |  8 ++++----
 hw/arm/virt.c            | 25 +++++++++++++------------
 include/hw/arm/arm.h     |  1 +
 include/hw/arm/virt.h    |  1 -
 4 files changed, 18 insertions(+), 17 deletions(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index ef61a651c1..27e6c95eca 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -414,7 +414,7 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
     its->identifiers[0] = 0; /* MADT translation_id */
 
     if (vms->iommu == VIRT_IOMMU_SMMUV3) {
-        int irq =  vms->irqmap[VIRT_SMMU] + ARM_SPI_BASE;
+        int irq =  ams->irqmap[VIRT_SMMU] + ARM_SPI_BASE;
 
         /* SMMUv3 node */
         smmu_offset = iort_node_offset + node_size;
@@ -488,7 +488,7 @@ build_spcr(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
     AcpiSerialPortConsoleRedirection *spcr;
     ArmMachineState *ams = ARM_MACHINE(vms);
     const MemMapEntry *uart_memmap = &ams->memmap[VIRT_UART];
-    int irq = vms->irqmap[VIRT_UART] + ARM_SPI_BASE;
+    int irq = ams->irqmap[VIRT_UART] + ARM_SPI_BASE;
     int spcr_start = table_data->len;
 
     spcr = acpi_data_push(table_data, sizeof(*spcr));
@@ -609,7 +609,7 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
     ArmMachineState *ams = ARM_MACHINE(vms);
     int madt_start = table_data->len;
     const MemMapEntry *memmap = ams->memmap;
-    const int *irqmap = vms->irqmap;
+    const int *irqmap = ams->irqmap;
     AcpiMultipleApicTable *madt;
     AcpiMadtGenericDistributor *gicd;
     AcpiMadtGenericMsiFrame *gic_msi;
@@ -730,7 +730,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
     MachineState *ms = MACHINE(vms);
     ArmMachineState *ams = ARM_MACHINE(vms);
     const MemMapEntry *memmap = ams->memmap;
-    const int *irqmap = vms->irqmap;
+    const int *irqmap = ams->irqmap;
 
     dsdt = init_aml_allocator();
     /* Reserve space for header */
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 1dea640719..e7eee13385 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -544,7 +544,7 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms)
     DeviceState *dev;
     MachineState *ms = MACHINE(vms);
     ArmMachineState *ams = ARM_MACHINE(vms);
-    int irq = vms->irqmap[VIRT_ACPI_GED];
+    int irq = ams->irqmap[VIRT_ACPI_GED];
     uint32_t event = ACPI_GED_PWR_DOWN_EVT;
 
     if (ms->ram_slots) {
@@ -588,7 +588,7 @@ static void create_v2m(VirtMachineState *vms)
 {
     int i;
     ArmMachineState *ams = ARM_MACHINE(vms);
-    int irq = vms->irqmap[VIRT_GIC_V2M];
+    int irq = ams->irqmap[VIRT_GIC_V2M];
     DeviceState *dev;
 
     dev = qdev_create(NULL, "arm-gicv2m");
@@ -734,7 +734,7 @@ static void create_uart(const VirtMachineState *vms, int uart,
     const ArmMachineState *ams = ARM_MACHINE(vms);
     hwaddr base = ams->memmap[uart].base;
     hwaddr size = ams->memmap[uart].size;
-    int irq = vms->irqmap[uart];
+    int irq = ams->irqmap[uart];
     const char compat[] = "arm,pl011\0arm,primecell";
     const char clocknames[] = "uartclk\0apb_pclk";
     DeviceState *dev = qdev_create(NULL, "pl011");
@@ -782,7 +782,7 @@ static void create_rtc(const VirtMachineState *vms)
     const ArmMachineState *ams = ARM_MACHINE(vms);
     hwaddr base = ams->memmap[VIRT_RTC].base;
     hwaddr size = ams->memmap[VIRT_RTC].size;
-    int irq = vms->irqmap[VIRT_RTC];
+    int irq = ams->irqmap[VIRT_RTC];
     const char compat[] = "arm,pl031\0arm,primecell";
 
     sysbus_create_simple("pl031", base, qdev_get_gpio_in(vms->gic, irq));
@@ -820,7 +820,7 @@ static void create_gpio(const VirtMachineState *vms)
     const ArmMachineState *ams = ARM_MACHINE(vms);
     hwaddr base = ams->memmap[VIRT_GPIO].base;
     hwaddr size = ams->memmap[VIRT_GPIO].size;
-    int irq = vms->irqmap[VIRT_GPIO];
+    int irq = ams->irqmap[VIRT_GPIO];
     const char compat[] = "arm,pl061\0arm,primecell";
 
     pl061_dev = sysbus_create_simple("pl061", base,
@@ -892,7 +892,7 @@ static void create_virtio_devices(const VirtMachineState *vms)
      * of disks users must use UUIDs or similar mechanisms.
      */
     for (i = 0; i < NUM_VIRTIO_TRANSPORTS; i++) {
-        int irq = vms->irqmap[VIRT_MMIO] + i;
+        int irq = ams->irqmap[VIRT_MMIO] + i;
         hwaddr base = ams->memmap[VIRT_MMIO].base + i * size;
 
         sysbus_create_simple("virtio-mmio", base,
@@ -908,7 +908,7 @@ static void create_virtio_devices(const VirtMachineState *vms)
      */
     for (i = NUM_VIRTIO_TRANSPORTS - 1; i >= 0; i--) {
         char *nodename;
-        int irq = vms->irqmap[VIRT_MMIO] + i;
+        int irq = ams->irqmap[VIRT_MMIO] + i;
         hwaddr base = ams->memmap[VIRT_MMIO].base + i * size;
 
         nodename = g_strdup_printf("/virtio_mmio@%" PRIx64, base);
@@ -1155,7 +1155,7 @@ static void create_smmu(const VirtMachineState *vms,
     char *node;
     const ArmMachineState *ams = ARM_MACHINE(vms);
     const char compat[] = "arm,smmu-v3";
-    int irq =  vms->irqmap[VIRT_SMMU];
+    int irq = ams->irqmap[VIRT_SMMU];
     int i;
     hwaddr base = ams->memmap[VIRT_SMMU].base;
     hwaddr size = ams->memmap[VIRT_SMMU].size;
@@ -1213,7 +1213,7 @@ static void create_pcie(VirtMachineState *vms)
     hwaddr base_ecam, size_ecam;
     hwaddr base = base_mmio;
     int nr_pcie_buses;
-    int irq = vms->irqmap[VIRT_PCIE];
+    int irq = ams->irqmap[VIRT_PCIE];
     MemoryRegion *mmio_alias;
     MemoryRegion *mmio_reg;
     MemoryRegion *ecam_alias;
@@ -1349,7 +1349,7 @@ static void create_platform_bus(VirtMachineState *vms)
 
     s = SYS_BUS_DEVICE(dev);
     for (i = 0; i < PLATFORM_BUS_NUM_IRQS; i++) {
-        int irq = vms->irqmap[VIRT_PLATFORM_BUS] + i;
+        int irq = ams->irqmap[VIRT_PLATFORM_BUS] + i;
         sysbus_connect_irq(s, i, qdev_get_gpio_in(vms->gic, irq));
     }
 
@@ -1440,7 +1440,7 @@ void virt_machine_done(Notifier *notifier, void *data)
         platform_bus_add_all_fdt_nodes(ams->fdt, "/intc",
                                        ams->memmap[VIRT_PLATFORM_BUS].base,
                                        ams->memmap[VIRT_PLATFORM_BUS].size,
-                                       vms->irqmap[VIRT_PLATFORM_BUS]);
+                                       ams->irqmap[VIRT_PLATFORM_BUS]);
     }
     if (arm_load_dtb(info->dtb_start, info, info->dtb_limit, as, ms) < 0) {
         exit(1);
@@ -2084,6 +2084,7 @@ static void virt_instance_init(Object *obj)
 {
     VirtMachineState *vms = VIRT_MACHINE(obj);
     VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
+    ArmMachineState *ams = ARM_MACHINE(vms);
 
     /* EL3 is disabled by default on virt: this makes us consistent
      * between KVM and TCG for this board, and it also allows us to
@@ -2146,7 +2147,7 @@ static void virt_instance_init(Object *obj)
                                     "Valid values are none and smmuv3",
                                     NULL);
 
-    vms->irqmap = a15irqmap;
+    ams->irqmap = a15irqmap;
 
     virt_flash_create(vms);
 }
diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h
index f269668d41..97cb902b6a 100644
--- a/include/hw/arm/arm.h
+++ b/include/hw/arm/arm.h
@@ -88,6 +88,7 @@ typedef struct {
 typedef struct {
     MachineState parent;
     MemMapEntry *memmap;
+    const int *irqmap;
     void *fdt;
     int fdt_size;
 } ArmMachineState;
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index 1b460d8d31..4028821a09 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -71,7 +71,6 @@ typedef struct {
     int32_t gic_version;
     VirtIOMMUType iommu;
     struct arm_boot_info bootinfo;
-    const int *irqmap;
     int smp_cpus;
     uint32_t clock_phandle;
     uint32_t gic_phandle;
-- 
2.18.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH RFC 05/16] hw/arm: move shared smp_cpus member to ArmMachine
  2020-02-17  7:51 [PATCH RFC 00/16] Implement Microvm for aarch64 architecture Xu Yandong
                   ` (3 preceding siblings ...)
  2020-02-17  7:51 ` [PATCH RFC 04/16] hw/arm: move shared irqmap " Xu Yandong
@ 2020-02-17  7:51 ` Xu Yandong
  2020-02-17  7:51 ` [PATCH RFC 06/16] hw/arm/virt: split MSI related codes from create_gic Xu Yandong
                   ` (12 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Xu Yandong @ 2020-02-17  7:51 UTC (permalink / raw)
  To: peter.maydell
  Cc: zhang.zhanghailiang, slp, Michael S. Tsirkin, Xu Yandong,
	qemu-devel, Shannon Zhao, qemu-arm, Igor Mammedov, wu.wubin

Move smp_cpus member from VirtMachineState to ArmMachineState.

Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Shannon Zhao <shannon.zhaosl@gmail.com>
Signed-off-by: Xu Yandong <xuyandong2@huawei.com>
---
 hw/arm/virt-acpi-build.c |  4 ++--
 hw/arm/virt.c            | 12 ++++++------
 include/hw/arm/arm.h     |  1 +
 include/hw/arm/virt.h    |  3 +--
 4 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 27e6c95eca..ef2761ef77 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -623,7 +623,7 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
     gicd->base_address = cpu_to_le64(memmap[VIRT_GIC_DIST].base);
     gicd->version = vms->gic_version;
 
-    for (i = 0; i < vms->smp_cpus; i++) {
+    for (i = 0; i < ams->smp_cpus; i++) {
         AcpiMadtGenericCpuInterface *gicc = acpi_data_push(table_data,
                                                            sizeof(*gicc));
         ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(i));
@@ -742,7 +742,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
      * the RTC ACPI device at all when using UEFI.
      */
     scope = aml_scope("\\_SB");
-    acpi_dsdt_add_cpus(scope, vms->smp_cpus);
+    acpi_dsdt_add_cpus(scope, ams->smp_cpus);
     acpi_dsdt_add_uart(scope, &memmap[VIRT_UART],
                        (irqmap[VIRT_UART] + ARM_SPI_BASE));
     acpi_dsdt_add_flash(scope, &memmap[VIRT_FLASH]);
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index e7eee13385..9031fd6757 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -300,7 +300,7 @@ static void fdt_add_timer_nodes(const VirtMachineState *vms)
     if (vms->gic_version == 2) {
         irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START,
                              GIC_FDT_IRQ_PPI_CPU_WIDTH,
-                             (1 << vms->smp_cpus) - 1);
+                             (1 << ams->smp_cpus) - 1);
     }
 
     qemu_fdt_add_subnode(ams->fdt, "/timer");
@@ -342,7 +342,7 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms)
      *  The simplest way to go is to examine affinity IDs of all our CPUs. If
      *  at least one of them has Aff3 populated, we set #address-cells to 2.
      */
-    for (cpu = 0; cpu < vms->smp_cpus; cpu++) {
+    for (cpu = 0; cpu < ams->smp_cpus; cpu++) {
         ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu));
 
         if (armcpu->mp_affinity & ARM_AFF3_MASK) {
@@ -355,7 +355,7 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms)
     qemu_fdt_setprop_cell(ams->fdt, "/cpus", "#address-cells", addr_cells);
     qemu_fdt_setprop_cell(ams->fdt, "/cpus", "#size-cells", 0x0);
 
-    for (cpu = vms->smp_cpus - 1; cpu >= 0; cpu--) {
+    for (cpu = ams->smp_cpus - 1; cpu >= 0; cpu--) {
         char *nodename = g_strdup_printf("/cpus/cpu@%d", cpu);
         ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu));
         CPUState *cs = CPU(armcpu);
@@ -366,7 +366,7 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms)
                                     armcpu->dtb_compatible);
 
         if (vms->psci_conduit != QEMU_PSCI_CONDUIT_DISABLED
-            && vms->smp_cpus > 1) {
+            && ams->smp_cpus > 1) {
             qemu_fdt_setprop_string(ams->fdt, nodename,
                                         "enable-method", "psci");
         }
@@ -525,7 +525,7 @@ static void fdt_add_pmu_nodes(const VirtMachineState *vms)
     if (vms->gic_version == 2) {
         irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START,
                              GIC_FDT_IRQ_PPI_CPU_WIDTH,
-                             (1 << vms->smp_cpus) - 1);
+                             (1 << ams->smp_cpus) - 1);
     }
 
     armcpu = ARM_CPU(qemu_get_cpu(0));
@@ -1641,7 +1641,7 @@ static void machvirt_init(MachineState *machine)
         exit(1);
     }
 
-    vms->smp_cpus = smp_cpus;
+    ams->smp_cpus = smp_cpus;
 
     if (vms->virt && kvm_enabled()) {
         error_report("mach-virt: KVM does not support providing "
diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h
index 97cb902b6a..469f603e77 100644
--- a/include/hw/arm/arm.h
+++ b/include/hw/arm/arm.h
@@ -89,6 +89,7 @@ typedef struct {
     MachineState parent;
     MemMapEntry *memmap;
     const int *irqmap;
+    int smp_cpus;
     void *fdt;
     int fdt_size;
 } ArmMachineState;
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index 4028821a09..dfc2a16010 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -71,7 +71,6 @@ typedef struct {
     int32_t gic_version;
     VirtIOMMUType iommu;
     struct arm_boot_info bootinfo;
-    int smp_cpus;
     uint32_t clock_phandle;
     uint32_t gic_phandle;
     uint32_t msi_phandle;
@@ -104,7 +103,7 @@ static inline int virt_gicv3_redist_region_count(VirtMachineState *vms)
 
     assert(vms->gic_version == 3);
 
-    return vms->smp_cpus > redist0_capacity ? 2 : 1;
+    return ams->smp_cpus > redist0_capacity ? 2 : 1;
 }
 
 #endif /* QEMU_ARM_VIRT_H */
-- 
2.18.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH RFC 06/16] hw/arm/virt: split MSI related codes from create_gic
  2020-02-17  7:51 [PATCH RFC 00/16] Implement Microvm for aarch64 architecture Xu Yandong
                   ` (4 preceding siblings ...)
  2020-02-17  7:51 ` [PATCH RFC 05/16] hw/arm: move shared smp_cpus " Xu Yandong
@ 2020-02-17  7:51 ` Xu Yandong
  2020-02-17  7:51 ` [PATCH RFC 07/16] hw/arm/virt: split virt extension " Xu Yandong
                   ` (11 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Xu Yandong @ 2020-02-17  7:51 UTC (permalink / raw)
  To: peter.maydell
  Cc: zhang.zhanghailiang, slp, Xu Yandong, qemu-devel, qemu-arm, wu.wubin

GICv2m and GICits is not always needed.

Signed-off-by: Xu Yandong <xuyandong2@huawei.com>
---
 hw/arm/virt.c | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 9031fd6757..32c3977e32 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -605,6 +605,15 @@ static void create_v2m(VirtMachineState *vms)
     fdt_add_v2m_gic_node(vms);
 }
 
+static void gic_set_msi_interrupt(VirtMachineState *vms)
+{
+    if (vms->gic_version == 3 && vms->its) {
+        create_its(vms);
+    } else if (vms->gic_version == 2) {
+        create_v2m(vms);
+    }
+}
+
 static void create_gic(VirtMachineState *vms)
 {
     MachineState *ms = MACHINE(vms);
@@ -719,12 +728,7 @@ static void create_gic(VirtMachineState *vms)
     }
 
     fdt_add_gic_node(vms);
-
-    if (type == 3 && vms->its) {
-        create_its(vms);
-    } else if (type == 2) {
-        create_v2m(vms);
-    }
+    gic_set_msi_interrupt(vms);
 }
 
 static void create_uart(const VirtMachineState *vms, int uart,
-- 
2.18.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH RFC 07/16] hw/arm/virt: split virt extension related codes from create_gic
  2020-02-17  7:51 [PATCH RFC 00/16] Implement Microvm for aarch64 architecture Xu Yandong
                   ` (5 preceding siblings ...)
  2020-02-17  7:51 ` [PATCH RFC 06/16] hw/arm/virt: split MSI related codes from create_gic Xu Yandong
@ 2020-02-17  7:51 ` Xu Yandong
  2020-02-17  7:51 ` [PATCH RFC 08/16] hw/arm/virt: split secure " Xu Yandong
                   ` (10 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Xu Yandong @ 2020-02-17  7:51 UTC (permalink / raw)
  To: peter.maydell
  Cc: zhang.zhanghailiang, slp, Xu Yandong, qemu-devel, qemu-arm, wu.wubin

EL2 extension is not always needed.

Signed-off-by: Xu Yandong <xuyandong2@huawei.com>
---
 hw/arm/virt.c | 116 +++++++++++++++++++++++++++++++++-----------------
 1 file changed, 77 insertions(+), 39 deletions(-)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 32c3977e32..afaf143888 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -426,6 +426,45 @@ static void fdt_add_v2m_gic_node(VirtMachineState *vms)
     g_free(nodename);
 }
 
+static void fdt_gic_set_virt_extension(VirtMachineState *vms)
+{
+    char *nodename;
+    ArmMachineState *ams = ARM_MACHINE(vms);
+
+    nodename = g_strdup_printf("/intc@%" PRIx64,
+                               ams->memmap[VIRT_GIC_DIST].base);
+
+
+    if (vms->gic_version == 3) {
+        if (vms->virt) {
+            qemu_fdt_setprop_cells(ams->fdt, nodename, "interrupts",
+                                   GIC_FDT_IRQ_TYPE_PPI, ARCH_GIC_MAINT_IRQ,
+                                   GIC_FDT_IRQ_FLAGS_LEVEL_HI);
+        }
+    } else {
+        if (!vms->virt) {
+            qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "reg",
+                                         2, ams->memmap[VIRT_GIC_DIST].base,
+                                         2, ams->memmap[VIRT_GIC_DIST].size,
+                                         2, ams->memmap[VIRT_GIC_CPU].base,
+                                         2, ams->memmap[VIRT_GIC_CPU].size);
+        } else {
+            qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "reg",
+                                         2, ams->memmap[VIRT_GIC_DIST].base,
+                                         2, ams->memmap[VIRT_GIC_DIST].size,
+                                         2, ams->memmap[VIRT_GIC_CPU].base,
+                                         2, ams->memmap[VIRT_GIC_CPU].size,
+                                         2, ams->memmap[VIRT_GIC_HYP].base,
+                                         2, ams->memmap[VIRT_GIC_HYP].size,
+                                         2, ams->memmap[VIRT_GIC_VCPU].base,
+                                         2, ams->memmap[VIRT_GIC_VCPU].size);
+            qemu_fdt_setprop_cells(ams->fdt, nodename, "interrupts",
+                                   GIC_FDT_IRQ_TYPE_PPI, ARCH_GIC_MAINT_IRQ,
+                                   GIC_FDT_IRQ_FLAGS_LEVEL_HI);
+        }
+    }
+}
+
 static void fdt_add_gic_node(VirtMachineState *vms)
 {
     char *nodename;
@@ -466,36 +505,10 @@ static void fdt_add_gic_node(VirtMachineState *vms)
                                  2, ams->memmap[VIRT_HIGH_GIC_REDIST2].base,
                                  2, ams->memmap[VIRT_HIGH_GIC_REDIST2].size);
         }
-
-        if (vms->virt) {
-            qemu_fdt_setprop_cells(ams->fdt, nodename, "interrupts",
-                                   GIC_FDT_IRQ_TYPE_PPI, ARCH_GIC_MAINT_IRQ,
-                                   GIC_FDT_IRQ_FLAGS_LEVEL_HI);
-        }
     } else {
         /* 'cortex-a15-gic' means 'GIC v2' */
         qemu_fdt_setprop_string(ams->fdt, nodename, "compatible",
                                 "arm,cortex-a15-gic");
-        if (!vms->virt) {
-            qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "reg",
-                                         2, ams->memmap[VIRT_GIC_DIST].base,
-                                         2, ams->memmap[VIRT_GIC_DIST].size,
-                                         2, ams->memmap[VIRT_GIC_CPU].base,
-                                         2, ams->memmap[VIRT_GIC_CPU].size);
-        } else {
-            qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "reg",
-                                         2, ams->memmap[VIRT_GIC_DIST].base,
-                                         2, ams->memmap[VIRT_GIC_DIST].size,
-                                         2, ams->memmap[VIRT_GIC_CPU].base,
-                                         2, ams->memmap[VIRT_GIC_CPU].size,
-                                         2, ams->memmap[VIRT_GIC_HYP].base,
-                                         2, ams->memmap[VIRT_GIC_HYP].size,
-                                         2, ams->memmap[VIRT_GIC_VCPU].base,
-                                         2, ams->memmap[VIRT_GIC_VCPU].size);
-            qemu_fdt_setprop_cells(ams->fdt, nodename, "interrupts",
-                                   GIC_FDT_IRQ_TYPE_PPI, ARCH_GIC_MAINT_IRQ,
-                                   GIC_FDT_IRQ_FLAGS_LEVEL_HI);
-        }
     }
 
     qemu_fdt_setprop_cell(ams->fdt, nodename, "phandle", vms->gic_phandle);
@@ -614,6 +627,40 @@ static void gic_set_msi_interrupt(VirtMachineState *vms)
     }
 }
 
+static void qdev_gic_set_virt_bit(VirtMachineState *vms)
+{
+    if (vms->gic_version != 3 && !kvm_irqchip_in_kernel()) {
+        qdev_prop_set_bit(vms->gic, "has-virtualization-extensions",
+                          vms->virt);
+    }
+}
+
+static void set_gic_virt_sysbus(VirtMachineState *vms)
+{
+    MachineState *ms = MACHINE(vms);
+    ArmMachineState *ams = ARM_MACHINE(vms);
+    SysBusDevice *gicbusdev;
+    int type = vms->gic_version, i;
+    unsigned int smp_cpus = ms->smp.cpus;
+
+    if (!vms->virt) {
+        return;
+    }
+
+    gicbusdev = SYS_BUS_DEVICE(vms->gic);
+    if (type != 3) {
+        sysbus_mmio_map(gicbusdev, 2, ams->memmap[VIRT_GIC_HYP].base);
+        sysbus_mmio_map(gicbusdev, 3, ams->memmap[VIRT_GIC_VCPU].base);
+    }
+
+    for (i = 0; i < smp_cpus; i++) {
+        int ppibase = NUM_IRQS + i * GIC_INTERNAL + GIC_NR_SGIS;
+        qemu_irq irq = qdev_get_gpio_in(vms->gic,
+                                        ppibase + ARCH_GIC_MAINT_IRQ);
+        sysbus_connect_irq(gicbusdev, i + 4 * smp_cpus, irq);
+    }
+}
+
 static void create_gic(VirtMachineState *vms)
 {
     MachineState *ms = MACHINE(vms);
@@ -656,12 +703,8 @@ static void create_gic(VirtMachineState *vms)
             qdev_prop_set_uint32(vms->gic, "redist-region-count[1]",
                 MIN(smp_cpus - redist0_count, redist1_capacity));
         }
-    } else {
-        if (!kvm_irqchip_in_kernel()) {
-            qdev_prop_set_bit(vms->gic, "has-virtualization-extensions",
-                              vms->virt);
-        }
     }
+    qdev_gic_set_virt_bit(vms);
     qdev_init_nofail(vms->gic);
     gicbusdev = SYS_BUS_DEVICE(vms->gic);
     sysbus_mmio_map(gicbusdev, 0, ams->memmap[VIRT_GIC_DIST].base);
@@ -673,10 +716,6 @@ static void create_gic(VirtMachineState *vms)
         }
     } else {
         sysbus_mmio_map(gicbusdev, 1, ams->memmap[VIRT_GIC_CPU].base);
-        if (vms->virt) {
-            sysbus_mmio_map(gicbusdev, 2, ams->memmap[VIRT_GIC_HYP].base);
-            sysbus_mmio_map(gicbusdev, 3, ams->memmap[VIRT_GIC_VCPU].base);
-        }
     }
 
     /* Wire the outputs from each CPU's generic timer and the GICv3
@@ -708,10 +747,6 @@ static void create_gic(VirtMachineState *vms)
                                             ppibase + ARCH_GIC_MAINT_IRQ);
             qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
                                         0, irq);
-        } else if (vms->virt) {
-            qemu_irq irq = qdev_get_gpio_in(vms->gic,
-                                            ppibase + ARCH_GIC_MAINT_IRQ);
-            sysbus_connect_irq(gicbusdev, i + 4 * smp_cpus, irq);
         }
 
         qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0,
@@ -727,7 +762,10 @@ static void create_gic(VirtMachineState *vms)
                            qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
     }
 
+    set_gic_virt_sysbus(vms);
     fdt_add_gic_node(vms);
+    fdt_gic_set_virt_extension(vms);
+
     gic_set_msi_interrupt(vms);
 }
 
-- 
2.18.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH RFC 08/16] hw/arm/virt: split secure extension related codes from create_gic
  2020-02-17  7:51 [PATCH RFC 00/16] Implement Microvm for aarch64 architecture Xu Yandong
                   ` (6 preceding siblings ...)
  2020-02-17  7:51 ` [PATCH RFC 07/16] hw/arm/virt: split virt extension " Xu Yandong
@ 2020-02-17  7:51 ` Xu Yandong
  2020-02-17  7:51 ` [PATCH RFC 09/16] hw/arm: move shared gic member to ArmMachine Xu Yandong
                   ` (9 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Xu Yandong @ 2020-02-17  7:51 UTC (permalink / raw)
  To: peter.maydell
  Cc: zhang.zhanghailiang, slp, Xu Yandong, qemu-devel, qemu-arm, wu.wubin

EL3 extension is not always needed.

Signed-off-by: Xu Yandong <xuyandong2@huawei.com>
---
 hw/arm/virt.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index afaf143888..087616190e 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -627,6 +627,14 @@ static void gic_set_msi_interrupt(VirtMachineState *vms)
     }
 }
 
+static void qdev_gic_set_secure_bit(VirtMachineState *vms)
+{
+    if (!kvm_irqchip_in_kernel()) {
+        qdev_prop_set_bit(vms->gic, "has-security-extensions",
+                          vms->secure);
+    }
+}
+
 static void qdev_gic_set_virt_bit(VirtMachineState *vms)
 {
     if (vms->gic_version != 3 && !kvm_irqchip_in_kernel()) {
@@ -681,9 +689,6 @@ static void create_gic(VirtMachineState *vms)
      * interrupts; there are always 32 of the former (mandated by GIC spec).
      */
     qdev_prop_set_uint32(vms->gic, "num-irq", NUM_IRQS + 32);
-    if (!kvm_irqchip_in_kernel()) {
-        qdev_prop_set_bit(vms->gic, "has-security-extensions", vms->secure);
-    }
 
     if (type == 3) {
         uint32_t redist0_capacity =
@@ -704,6 +709,7 @@ static void create_gic(VirtMachineState *vms)
                 MIN(smp_cpus - redist0_count, redist1_capacity));
         }
     }
+    qdev_gic_set_secure_bit(vms);
     qdev_gic_set_virt_bit(vms);
     qdev_init_nofail(vms->gic);
     gicbusdev = SYS_BUS_DEVICE(vms->gic);
-- 
2.18.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH RFC 09/16] hw/arm: move shared gic member to ArmMachine
  2020-02-17  7:51 [PATCH RFC 00/16] Implement Microvm for aarch64 architecture Xu Yandong
                   ` (7 preceding siblings ...)
  2020-02-17  7:51 ` [PATCH RFC 08/16] hw/arm/virt: split secure " Xu Yandong
@ 2020-02-17  7:51 ` Xu Yandong
  2020-02-17  7:51 ` [PATCH RFC 10/16] hw/arm: split create_gic function Xu Yandong
                   ` (8 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Xu Yandong @ 2020-02-17  7:51 UTC (permalink / raw)
  To: peter.maydell
  Cc: zhang.zhanghailiang, slp, Michael S. Tsirkin, Xu Yandong,
	qemu-devel, Shannon Zhao, qemu-arm, Igor Mammedov, wu.wubin

Move gic member from VirtMachineState to ArmMachineState.

Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Shannon Zhao <shannon.zhaosl@gmail.com>
Signed-off-by: Xu Yandong <xuyandong2@huawei.com>
---
 hw/arm/arm.c             |  35 ++++++++++
 hw/arm/virt-acpi-build.c |   8 +--
 hw/arm/virt.c            | 139 +++++++++++++++------------------------
 include/hw/arm/arm.h     |  17 +++++
 include/hw/arm/virt.h    |  15 -----
 5 files changed, 110 insertions(+), 104 deletions(-)

diff --git a/hw/arm/arm.c b/hw/arm/arm.c
index 4261d56832..ecb99611ed 100644
--- a/hw/arm/arm.c
+++ b/hw/arm/arm.c
@@ -39,6 +39,32 @@
 #include "hw/intc/arm_gic.h"
 #include "kvm_arm.h"
 
+static char *virt_get_gic_version(Object *obj, Error **errp)
+{
+    ArmMachineState *ams = ARM_MACHINE(obj);
+    const char *val = ams->gic_version == 3 ? "3" : "2";
+
+    return g_strdup(val);
+}
+
+static void virt_set_gic_version(Object *obj, const char *value, Error **errp)
+{
+    ArmMachineState *ams = ARM_MACHINE(obj);
+
+    if (!strcmp(value, "3")) {
+        ams->gic_version = 3;
+    } else if (!strcmp(value, "2")) {
+        ams->gic_version = 2;
+    } else if (!strcmp(value, "host")) {
+        ams->gic_version = 0; /* Will probe later */
+    } else if (!strcmp(value, "max")) {
+        ams->gic_version = -1; /* Will probe later */
+    } else {
+        error_setg(errp, "Invalid gic-version value");
+        error_append_hint(errp, "Valid values are 3, 2, host, max.\n");
+    }
+}
+
 static void arm_machine_class_init(ObjectClass *oc, void *data)
 {
     MachineClass *mc = MACHINE_CLASS(oc);
@@ -55,6 +81,15 @@ static void arm_machine_class_init(ObjectClass *oc, void *data)
 
 static void arm_instance_init(Object *obj)
 {
+    ArmMachineState *ams = ARM_MACHINE(obj);
+    /* Default GIC type is v2 */
+    ams->gic_version = 2;
+    object_property_add_str(obj, "gic-version", virt_get_gic_version,
+                        virt_set_gic_version, NULL);
+    object_property_set_description(obj, "gic-version",
+                                    "Set GIC version. "
+                                    "Valid values are 2, 3 and host", NULL);
+
 }
 
 static const TypeInfo arm_machine_info = {
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index ef2761ef77..770c53f5d0 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -621,7 +621,7 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
     gicd->type = ACPI_APIC_GENERIC_DISTRIBUTOR;
     gicd->length = sizeof(*gicd);
     gicd->base_address = cpu_to_le64(memmap[VIRT_GIC_DIST].base);
-    gicd->version = vms->gic_version;
+    gicd->version = ams->gic_version;
 
     for (i = 0; i < ams->smp_cpus; i++) {
         AcpiMadtGenericCpuInterface *gicc = acpi_data_push(table_data,
@@ -630,7 +630,7 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
 
         gicc->type = ACPI_APIC_GENERIC_CPU_INTERFACE;
         gicc->length = sizeof(*gicc);
-        if (vms->gic_version == 2) {
+        if (ams->gic_version == 2) {
             gicc->base_address = cpu_to_le64(memmap[VIRT_GIC_CPU].base);
             gicc->gich_base_address = cpu_to_le64(memmap[VIRT_GIC_HYP].base);
             gicc->gicv_base_address = cpu_to_le64(memmap[VIRT_GIC_VCPU].base);
@@ -648,9 +648,9 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
         }
     }
 
-    if (vms->gic_version == 3) {
+    if (ams->gic_version == 3) {
         AcpiMadtGenericTranslator *gic_its;
-        int nb_redist_regions = virt_gicv3_redist_region_count(vms);
+        int nb_redist_regions = virt_gicv3_redist_region_count(ams);
         AcpiMadtGenericRedistributor *gicr = acpi_data_push(table_data,
                                                          sizeof *gicr);
 
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 087616190e..b9689b0f0c 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -100,10 +100,6 @@
 #define DEFINE_VIRT_MACHINE(major, minor) \
     DEFINE_VIRT_MACHINE_LATEST(major, minor, false)
 
-
-/* Number of external interrupt lines to configure the GIC with */
-#define NUM_IRQS 256
-
 #define PLATFORM_BUS_NUM_IRQS 64
 
 /* Legacy RAM limit in GB (< version 4.0) */
@@ -297,7 +293,7 @@ static void fdt_add_timer_nodes(const VirtMachineState *vms)
         irqflags = GIC_FDT_IRQ_FLAGS_EDGE_LO_HI;
     }
 
-    if (vms->gic_version == 2) {
+    if (ams->gic_version == 2) {
         irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START,
                              GIC_FDT_IRQ_PPI_CPU_WIDTH,
                              (1 << ams->smp_cpus) - 1);
@@ -435,7 +431,7 @@ static void fdt_gic_set_virt_extension(VirtMachineState *vms)
                                ams->memmap[VIRT_GIC_DIST].base);
 
 
-    if (vms->gic_version == 3) {
+    if (ams->gic_version == 3) {
         if (vms->virt) {
             qemu_fdt_setprop_cells(ams->fdt, nodename, "interrupts",
                                    GIC_FDT_IRQ_TYPE_PPI, ARCH_GIC_MAINT_IRQ,
@@ -470,8 +466,8 @@ static void fdt_add_gic_node(VirtMachineState *vms)
     char *nodename;
     ArmMachineState *ams = ARM_MACHINE(vms);
 
-    vms->gic_phandle = qemu_fdt_alloc_phandle(ams->fdt);
-    qemu_fdt_setprop_cell(ams->fdt, "/", "interrupt-parent", vms->gic_phandle);
+    ams->gic_phandle = qemu_fdt_alloc_phandle(ams->fdt);
+    qemu_fdt_setprop_cell(ams->fdt, "/", "interrupt-parent", ams->gic_phandle);
 
     nodename = g_strdup_printf("/intc@%" PRIx64,
                                ams->memmap[VIRT_GIC_DIST].base);
@@ -481,8 +477,8 @@ static void fdt_add_gic_node(VirtMachineState *vms)
     qemu_fdt_setprop_cell(ams->fdt, nodename, "#address-cells", 0x2);
     qemu_fdt_setprop_cell(ams->fdt, nodename, "#size-cells", 0x2);
     qemu_fdt_setprop(ams->fdt, nodename, "ranges", NULL, 0);
-    if (vms->gic_version == 3) {
-        int nb_redist_regions = virt_gicv3_redist_region_count(vms);
+    if (ams->gic_version == 3) {
+        int nb_redist_regions = virt_gicv3_redist_region_count(ams);
 
         qemu_fdt_setprop_string(ams->fdt, nodename, "compatible",
                                 "arm,gic-v3");
@@ -511,7 +507,7 @@ static void fdt_add_gic_node(VirtMachineState *vms)
                                 "arm,cortex-a15-gic");
     }
 
-    qemu_fdt_setprop_cell(ams->fdt, nodename, "phandle", vms->gic_phandle);
+    qemu_fdt_setprop_cell(ams->fdt, nodename, "phandle", ams->gic_phandle);
     g_free(nodename);
 }
 
@@ -535,7 +531,7 @@ static void fdt_add_pmu_nodes(const VirtMachineState *vms)
         }
     }
 
-    if (vms->gic_version == 2) {
+    if (ams->gic_version == 2) {
         irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START,
                              GIC_FDT_IRQ_PPI_CPU_WIDTH,
                              (1 << ams->smp_cpus) - 1);
@@ -569,7 +565,7 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms)
 
     sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, ams->memmap[VIRT_ACPI_GED].base);
     sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, ams->memmap[VIRT_PCDIMM_ACPI].base);
-    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(vms->gic, irq));
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(ams->gic, irq));
 
     qdev_init_nofail(dev);
 
@@ -589,7 +585,7 @@ static void create_its(VirtMachineState *vms)
 
     dev = qdev_create(NULL, itsclass);
 
-    object_property_set_link(OBJECT(dev), OBJECT(vms->gic), "parent-gicv3",
+    object_property_set_link(OBJECT(dev), OBJECT(ams->gic), "parent-gicv3",
                              &error_abort);
     qdev_init_nofail(dev);
     sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, ams->memmap[VIRT_GIC_ITS].base);
@@ -612,7 +608,7 @@ static void create_v2m(VirtMachineState *vms)
 
     for (i = 0; i < NUM_GICV2M_SPIS; i++) {
         sysbus_connect_irq(SYS_BUS_DEVICE(dev), i,
-                           qdev_get_gpio_in(vms->gic, irq + i));
+                           qdev_get_gpio_in(ams->gic, irq + i));
     }
 
     fdt_add_v2m_gic_node(vms);
@@ -620,25 +616,30 @@ static void create_v2m(VirtMachineState *vms)
 
 static void gic_set_msi_interrupt(VirtMachineState *vms)
 {
-    if (vms->gic_version == 3 && vms->its) {
+    ArmMachineState *ams = ARM_MACHINE(vms);
+    if (ams->gic_version == 3 && vms->its) {
         create_its(vms);
-    } else if (vms->gic_version == 2) {
+    } else if (ams->gic_version == 2) {
         create_v2m(vms);
     }
 }
 
 static void qdev_gic_set_secure_bit(VirtMachineState *vms)
 {
+    ArmMachineState *ams = ARM_MACHINE(vms);
+
     if (!kvm_irqchip_in_kernel()) {
-        qdev_prop_set_bit(vms->gic, "has-security-extensions",
+        qdev_prop_set_bit(ams->gic, "has-security-extensions",
                           vms->secure);
     }
 }
 
 static void qdev_gic_set_virt_bit(VirtMachineState *vms)
 {
-    if (vms->gic_version != 3 && !kvm_irqchip_in_kernel()) {
-        qdev_prop_set_bit(vms->gic, "has-virtualization-extensions",
+    ArmMachineState *ams = ARM_MACHINE(vms);
+
+    if (ams->gic_version != 3 && !kvm_irqchip_in_kernel()) {
+        qdev_prop_set_bit(ams->gic, "has-virtualization-extensions",
                           vms->virt);
     }
 }
@@ -648,14 +649,14 @@ static void set_gic_virt_sysbus(VirtMachineState *vms)
     MachineState *ms = MACHINE(vms);
     ArmMachineState *ams = ARM_MACHINE(vms);
     SysBusDevice *gicbusdev;
-    int type = vms->gic_version, i;
+    int type = ams->gic_version, i;
     unsigned int smp_cpus = ms->smp.cpus;
 
     if (!vms->virt) {
         return;
     }
 
-    gicbusdev = SYS_BUS_DEVICE(vms->gic);
+    gicbusdev = SYS_BUS_DEVICE(ams->gic);
     if (type != 3) {
         sysbus_mmio_map(gicbusdev, 2, ams->memmap[VIRT_GIC_HYP].base);
         sysbus_mmio_map(gicbusdev, 3, ams->memmap[VIRT_GIC_VCPU].base);
@@ -663,7 +664,7 @@ static void set_gic_virt_sysbus(VirtMachineState *vms)
 
     for (i = 0; i < smp_cpus; i++) {
         int ppibase = NUM_IRQS + i * GIC_INTERNAL + GIC_NR_SGIS;
-        qemu_irq irq = qdev_get_gpio_in(vms->gic,
+        qemu_irq irq = qdev_get_gpio_in(ams->gic,
                                         ppibase + ARCH_GIC_MAINT_IRQ);
         sysbus_connect_irq(gicbusdev, i + 4 * smp_cpus, irq);
     }
@@ -676,43 +677,43 @@ static void create_gic(VirtMachineState *vms)
     /* We create a standalone GIC */
     SysBusDevice *gicbusdev;
     const char *gictype;
-    int type = vms->gic_version, i;
+    int type = ams->gic_version, i;
     unsigned int smp_cpus = ms->smp.cpus;
     uint32_t nb_redist_regions = 0;
 
     gictype = (type == 3) ? gicv3_class_name() : gic_class_name();
 
-    vms->gic = qdev_create(NULL, gictype);
-    qdev_prop_set_uint32(vms->gic, "revision", type);
-    qdev_prop_set_uint32(vms->gic, "num-cpu", smp_cpus);
+    ams->gic = qdev_create(NULL, gictype);
+    qdev_prop_set_uint32(ams->gic, "revision", type);
+    qdev_prop_set_uint32(ams->gic, "num-cpu", smp_cpus);
     /* Note that the num-irq property counts both internal and external
      * interrupts; there are always 32 of the former (mandated by GIC spec).
      */
-    qdev_prop_set_uint32(vms->gic, "num-irq", NUM_IRQS + 32);
+    qdev_prop_set_uint32(ams->gic, "num-irq", NUM_IRQS + 32);
 
     if (type == 3) {
         uint32_t redist0_capacity =
                     ams->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);
+        nb_redist_regions = virt_gicv3_redist_region_count(ams);
 
-        qdev_prop_set_uint32(vms->gic, "len-redist-region-count",
+        qdev_prop_set_uint32(ams->gic, "len-redist-region-count",
                              nb_redist_regions);
-        qdev_prop_set_uint32(vms->gic, "redist-region-count[0]", redist0_count);
+        qdev_prop_set_uint32(ams->gic, "redist-region-count[0]", redist0_count);
 
         if (nb_redist_regions == 2) {
             uint32_t redist1_capacity =
                     ams->memmap[VIRT_HIGH_GIC_REDIST2].size / GICV3_REDIST_SIZE;
 
-            qdev_prop_set_uint32(vms->gic, "redist-region-count[1]",
+            qdev_prop_set_uint32(ams->gic, "redist-region-count[1]",
                 MIN(smp_cpus - redist0_count, redist1_capacity));
         }
     }
     qdev_gic_set_secure_bit(vms);
     qdev_gic_set_virt_bit(vms);
-    qdev_init_nofail(vms->gic);
-    gicbusdev = SYS_BUS_DEVICE(vms->gic);
+    qdev_init_nofail(ams->gic);
+    gicbusdev = SYS_BUS_DEVICE(ams->gic);
     sysbus_mmio_map(gicbusdev, 0, ams->memmap[VIRT_GIC_DIST].base);
     if (type == 3) {
         sysbus_mmio_map(gicbusdev, 1, ams->memmap[VIRT_GIC_REDIST].base);
@@ -744,19 +745,19 @@ static void create_gic(VirtMachineState *vms)
 
         for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
             qdev_connect_gpio_out(cpudev, irq,
-                                  qdev_get_gpio_in(vms->gic,
+                                  qdev_get_gpio_in(ams->gic,
                                                    ppibase + timer_irq[irq]));
         }
 
         if (type == 3) {
-            qemu_irq irq = qdev_get_gpio_in(vms->gic,
+            qemu_irq irq = qdev_get_gpio_in(ams->gic,
                                             ppibase + ARCH_GIC_MAINT_IRQ);
             qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
                                         0, irq);
         }
 
         qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0,
-                                    qdev_get_gpio_in(vms->gic, ppibase
+                                    qdev_get_gpio_in(ams->gic, ppibase
                                                      + VIRTUAL_PMU_IRQ));
 
         sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
@@ -792,7 +793,7 @@ static void create_uart(const VirtMachineState *vms, int uart,
     qdev_init_nofail(dev);
     memory_region_add_subregion(mem, base,
                                 sysbus_mmio_get_region(s, 0));
-    sysbus_connect_irq(s, 0, qdev_get_gpio_in(vms->gic, irq));
+    sysbus_connect_irq(s, 0, qdev_get_gpio_in(ams->gic, irq));
 
     nodename = g_strdup_printf("/pl011@%" PRIx64, base);
     qemu_fdt_add_subnode(ams->fdt, nodename);
@@ -833,7 +834,7 @@ static void create_rtc(const VirtMachineState *vms)
     int irq = ams->irqmap[VIRT_RTC];
     const char compat[] = "arm,pl031\0arm,primecell";
 
-    sysbus_create_simple("pl031", base, qdev_get_gpio_in(vms->gic, irq));
+    sysbus_create_simple("pl031", base, qdev_get_gpio_in(ams->gic, irq));
 
     nodename = g_strdup_printf("/pl031@%" PRIx64, base);
     qemu_fdt_add_subnode(ams->fdt, nodename);
@@ -872,7 +873,7 @@ static void create_gpio(const VirtMachineState *vms)
     const char compat[] = "arm,pl061\0arm,primecell";
 
     pl061_dev = sysbus_create_simple("pl061", base,
-                                     qdev_get_gpio_in(vms->gic, irq));
+                                     qdev_get_gpio_in(ams->gic, irq));
 
     uint32_t phandle = qemu_fdt_alloc_phandle(ams->fdt);
     nodename = g_strdup_printf("/pl061@%" PRIx64, base);
@@ -944,7 +945,7 @@ static void create_virtio_devices(const VirtMachineState *vms)
         hwaddr base = ams->memmap[VIRT_MMIO].base + i * size;
 
         sysbus_create_simple("virtio-mmio", base,
-                             qdev_get_gpio_in(vms->gic, irq));
+                             qdev_get_gpio_in(ams->gic, irq));
     }
 
     /* We add dtb nodes in reverse order so that they appear in the finished
@@ -1222,7 +1223,7 @@ static void create_smmu(const VirtMachineState *vms,
     sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
     for (i = 0; i < NUM_SMMU_IRQS; i++) {
         sysbus_connect_irq(SYS_BUS_DEVICE(dev), i,
-                           qdev_get_gpio_in(vms->gic, irq + i));
+                           qdev_get_gpio_in(ams->gic, irq + i));
     }
 
     node = g_strdup_printf("/smmuv3@%" PRIx64, base);
@@ -1311,7 +1312,7 @@ static void create_pcie(VirtMachineState *vms)
 
     for (i = 0; i < GPEX_NUM_IRQS; i++) {
         sysbus_connect_irq(SYS_BUS_DEVICE(dev), i,
-                           qdev_get_gpio_in(vms->gic, irq + i));
+                           qdev_get_gpio_in(ams->gic, irq + i));
         gpex_set_irq_num(GPEX_HOST(dev), i, irq + i);
     }
 
@@ -1366,7 +1367,7 @@ static void create_pcie(VirtMachineState *vms)
     }
 
     qemu_fdt_setprop_cell(ams->fdt, nodename, "#interrupt-cells", 1);
-    create_pcie_irq_map(vms, vms->gic_phandle, irq, nodename);
+    create_pcie_irq_map(vms, ams->gic_phandle, irq, nodename);
 
     if (vms->iommu) {
         vms->iommu_phandle = qemu_fdt_alloc_phandle(ams->fdt);
@@ -1398,7 +1399,7 @@ static void create_platform_bus(VirtMachineState *vms)
     s = SYS_BUS_DEVICE(dev);
     for (i = 0; i < PLATFORM_BUS_NUM_IRQS; i++) {
         int irq = ams->irqmap[VIRT_PLATFORM_BUS] + i;
-        sysbus_connect_irq(s, i, qdev_get_gpio_in(vms->gic, irq));
+        sysbus_connect_irq(s, i, qdev_get_gpio_in(ams->gic, irq));
     }
 
     memory_region_add_subregion(sysmem,
@@ -1501,6 +1502,7 @@ void virt_machine_done(Notifier *notifier, void *data)
 static uint64_t virt_cpu_mp_affinity(VirtMachineState *vms, int idx)
 {
     uint8_t clustersz = ARM_DEFAULT_CPUS_PER_CLUSTER;
+    ArmMachineState *ams = ARM_MACHINE(vms);
     VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
 
     if (!vmc->disallow_affinity_adjustment) {
@@ -1512,7 +1514,7 @@ static uint64_t virt_cpu_mp_affinity(VirtMachineState *vms, int idx)
          * purposes are to make TCG consistent (with 64-bit KVM hosts)
          * and to improve SGI efficiency.
          */
-        if (vms->gic_version == 3) {
+        if (ams->gic_version == 3) {
             clustersz = GICV3_TARGETLIST_BITS;
         } else {
             clustersz = GIC_TARGETLIST_BITS;
@@ -1606,19 +1608,19 @@ static void machvirt_init(MachineState *machine)
     /* We can probe only here because during property set
      * KVM is not available yet
      */
-    if (vms->gic_version <= 0) {
+    if (ams->gic_version <= 0) {
         /* "host" or "max" */
         if (!kvm_enabled()) {
-            if (vms->gic_version == 0) {
+            if (ams->gic_version == 0) {
                 error_report("gic-version=host requires KVM");
                 exit(1);
             } else {
                 /* "max": currently means 3 for TCG */
-                vms->gic_version = 3;
+                ams->gic_version = 3;
             }
         } else {
-            vms->gic_version = kvm_arm_vgic_probe();
-            if (!vms->gic_version) {
+            ams->gic_version = kvm_arm_vgic_probe();
+            if (!ams->gic_version) {
                 error_report(
                     "Unable to determine GIC version supported by host");
                 exit(1);
@@ -1673,7 +1675,7 @@ static void machvirt_init(MachineState *machine)
     /* The maximum number of CPUs depends on the GIC version, or on how
      * many redistributors we can fit into the memory map.
      */
-    if (vms->gic_version == 3) {
+    if (ams->gic_version == 3) {
         virt_max_cpus =
             ams->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
         virt_max_cpus +=
@@ -1899,32 +1901,6 @@ static void virt_set_its(Object *obj, bool value, Error **errp)
     vms->its = value;
 }
 
-static char *virt_get_gic_version(Object *obj, Error **errp)
-{
-    VirtMachineState *vms = VIRT_MACHINE(obj);
-    const char *val = vms->gic_version == 3 ? "3" : "2";
-
-    return g_strdup(val);
-}
-
-static void virt_set_gic_version(Object *obj, const char *value, Error **errp)
-{
-    VirtMachineState *vms = VIRT_MACHINE(obj);
-
-    if (!strcmp(value, "3")) {
-        vms->gic_version = 3;
-    } else if (!strcmp(value, "2")) {
-        vms->gic_version = 2;
-    } else if (!strcmp(value, "host")) {
-        vms->gic_version = 0; /* Will probe later */
-    } else if (!strcmp(value, "max")) {
-        vms->gic_version = -1; /* Will probe later */
-    } else {
-        error_setg(errp, "Invalid gic-version value");
-        error_append_hint(errp, "Valid values are 3, 2, host, max.\n");
-    }
-}
-
 static char *virt_get_iommu(Object *obj, Error **errp)
 {
     VirtMachineState *vms = VIRT_MACHINE(obj);
@@ -2164,13 +2140,6 @@ static void virt_instance_init(Object *obj)
                                     "Set on/off to enable/disable using "
                                     "physical address space above 32 bits",
                                     NULL);
-    /* Default GIC type is v2 */
-    vms->gic_version = 2;
-    object_property_add_str(obj, "gic-version", virt_get_gic_version,
-                        virt_set_gic_version, NULL);
-    object_property_set_description(obj, "gic-version",
-                                    "Set GIC version. "
-                                    "Valid values are 2, 3 and host", NULL);
 
     vms->highmem_ecam = !vmc->no_highmem_ecam;
 
diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h
index 469f603e77..f8bde03cc3 100644
--- a/include/hw/arm/arm.h
+++ b/include/hw/arm/arm.h
@@ -74,6 +74,9 @@ enum {
     VIRT_HIGH_PCIE_MMIO,
 };
 
+/* Number of external interrupt lines to configure the GIC with */
+#define NUM_IRQS 256
+
 /* indices of IO regions located after the RAM */
 
 typedef struct MemMapEntry {
@@ -87,11 +90,14 @@ typedef struct {
 
 typedef struct {
     MachineState parent;
+    int32_t gic_version;
     MemMapEntry *memmap;
     const int *irqmap;
     int smp_cpus;
     void *fdt;
     int fdt_size;
+    uint32_t gic_phandle;
+    DeviceState *gic;
 } ArmMachineState;
 
 #define TYPE_ARM_MACHINE   MACHINE_TYPE_NAME("arm")
@@ -102,4 +108,15 @@ typedef struct {
 #define ARM_MACHINE_CLASS(klass) \
     OBJECT_CLASS_CHECK(ArmMachineClass, klass, TYPE_ARM_MACHINE)
 
+/* Return the number of used redistributor regions  */
+static inline int virt_gicv3_redist_region_count(ArmMachineState *ams)
+{
+    uint32_t redist0_capacity =
+                ams->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
+
+    assert(ams->gic_version == 3);
+
+    return ams->smp_cpus > redist0_capacity ? 2 : 1;
+}
+
 #endif /* QEMU_ARM_ARM_H */
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index dfc2a16010..393afb7faf 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -68,16 +68,13 @@ typedef struct {
     bool highmem_ecam;
     bool its;
     bool virt;
-    int32_t gic_version;
     VirtIOMMUType iommu;
     struct arm_boot_info bootinfo;
     uint32_t clock_phandle;
-    uint32_t gic_phandle;
     uint32_t msi_phandle;
     uint32_t iommu_phandle;
     int psci_conduit;
     hwaddr highest_gpa;
-    DeviceState *gic;
     DeviceState *acpi_dev;
     Notifier powerdown_notifier;
 } VirtMachineState;
@@ -94,16 +91,4 @@ typedef struct {
 
 void virt_acpi_setup(VirtMachineState *vms);
 
-/* Return the number of used redistributor regions  */
-static inline int virt_gicv3_redist_region_count(VirtMachineState *vms)
-{
-    ArmMachineState *ams = ARM_MACHINE(vms);
-    uint32_t redist0_capacity =
-                ams->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
-
-    assert(vms->gic_version == 3);
-
-    return ams->smp_cpus > redist0_capacity ? 2 : 1;
-}
-
 #endif /* QEMU_ARM_VIRT_H */
-- 
2.18.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH RFC 10/16] hw/arm: split create_gic function
  2020-02-17  7:51 [PATCH RFC 00/16] Implement Microvm for aarch64 architecture Xu Yandong
                   ` (8 preceding siblings ...)
  2020-02-17  7:51 ` [PATCH RFC 09/16] hw/arm: move shared gic member to ArmMachine Xu Yandong
@ 2020-02-17  7:51 ` Xu Yandong
  2020-02-17  7:51 ` [PATCH RFC 11/16] hw/arm: move shared psci_enable and claim_edge_triggered_timers member to ArmMachine Xu Yandong
                   ` (7 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Xu Yandong @ 2020-02-17  7:51 UTC (permalink / raw)
  To: peter.maydell
  Cc: zhang.zhanghailiang, slp, Xu Yandong, qemu-devel, qemu-arm, wu.wubin

Split sharable GIC qdev create and sysbus initiatea codes as independent function.

Signed-off-by: Xu Yandong <xuyandong2@huawei.com>
---
 hw/arm/arm.c         | 106 +++++++++++++++++++++++++++++++++++++++++++
 hw/arm/virt.c        |  93 +------------------------------------
 include/hw/arm/arm.h |   4 ++
 3 files changed, 112 insertions(+), 91 deletions(-)

diff --git a/hw/arm/arm.c b/hw/arm/arm.c
index ecb99611ed..c51bf513d2 100644
--- a/hw/arm/arm.c
+++ b/hw/arm/arm.c
@@ -39,6 +39,112 @@
 #include "hw/intc/arm_gic.h"
 #include "kvm_arm.h"
 
+void qdev_create_gic(ArmMachineState *ams)
+{
+    MachineState *ms = MACHINE(ams);
+    /* We create a standalone GIC */
+    const char *gictype;
+    int type = ams->gic_version;
+    unsigned int smp_cpus = ms->smp.cpus;
+    uint32_t nb_redist_regions = 0;
+
+    gictype = (type == 3) ? gicv3_class_name() : gic_class_name();
+
+    ams->gic = qdev_create(NULL, gictype);
+    qdev_prop_set_uint32(ams->gic, "revision", type);
+    qdev_prop_set_uint32(ams->gic, "num-cpu", smp_cpus);
+    /* Note that the num-irq property counts both internal and external
+     * interrupts; there are always 32 of the former (mandated by GIC spec).
+     */
+    qdev_prop_set_uint32(ams->gic, "num-irq", NUM_IRQS + 32);
+
+    if (type == 3) {
+        uint32_t redist0_capacity =
+                    ams->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(ams);
+
+        qdev_prop_set_uint32(ams->gic, "len-redist-region-count",
+                             nb_redist_regions);
+        qdev_prop_set_uint32(ams->gic, "redist-region-count[0]", redist0_count);
+
+        if (nb_redist_regions == 2) {
+            uint32_t redist1_capacity =
+                    ams->memmap[VIRT_HIGH_GIC_REDIST2].size / GICV3_REDIST_SIZE;
+
+            qdev_prop_set_uint32(ams->gic, "redist-region-count[1]",
+                MIN(smp_cpus - redist0_count, redist1_capacity));
+        }
+    }
+}
+
+void init_gic_sysbus(ArmMachineState *ams)
+{
+    MachineState *ms = MACHINE(ams);
+    /* We create a standalone GIC */
+    SysBusDevice *gicbusdev;
+    int type = ams->gic_version, i;
+    unsigned int smp_cpus = ms->smp.cpus;
+    uint32_t nb_redist_regions = 0;
+
+    gicbusdev = SYS_BUS_DEVICE(ams->gic);
+    sysbus_mmio_map(gicbusdev, 0, ams->memmap[VIRT_GIC_DIST].base);
+    if (type == 3) {
+        sysbus_mmio_map(gicbusdev, 1, ams->memmap[VIRT_GIC_REDIST].base);
+        if (nb_redist_regions == 2) {
+            sysbus_mmio_map(gicbusdev, 2,
+                            ams->memmap[VIRT_HIGH_GIC_REDIST2].base);
+        }
+    } else {
+        sysbus_mmio_map(gicbusdev, 1, ams->memmap[VIRT_GIC_CPU].base);
+    }
+
+    /* Wire the outputs from each CPU's generic timer and the GICv3
+     * maintenance interrupt signal to the appropriate GIC PPI inputs,
+     * and the GIC's IRQ/FIQ/VIRQ/VFIQ interrupt outputs to the CPU's inputs.
+     */
+    for (i = 0; i < smp_cpus; i++) {
+        DeviceState *cpudev = DEVICE(qemu_get_cpu(i));
+        int ppibase = NUM_IRQS + i * GIC_INTERNAL + GIC_NR_SGIS;
+        int irq;
+        /* Mapping from the output timer irq lines from the CPU to the
+         * GIC PPI inputs we use for the virt board.
+         */
+        const int timer_irq[] = {
+            [GTIMER_PHYS] = ARCH_TIMER_NS_EL1_IRQ,
+            [GTIMER_VIRT] = ARCH_TIMER_VIRT_IRQ,
+            [GTIMER_HYP]  = ARCH_TIMER_NS_EL2_IRQ,
+            [GTIMER_SEC]  = ARCH_TIMER_S_EL1_IRQ,
+        };
+
+        for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
+            qdev_connect_gpio_out(cpudev, irq,
+                                  qdev_get_gpio_in(ams->gic,
+                                                   ppibase + timer_irq[irq]));
+        }
+
+        if (type == 3) {
+            qemu_irq irq = qdev_get_gpio_in(ams->gic,
+                                            ppibase + ARCH_GIC_MAINT_IRQ);
+            qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
+                                        0, irq);
+        }
+
+        qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0,
+                                    qdev_get_gpio_in(ams->gic, ppibase
+                                                     + VIRTUAL_PMU_IRQ));
+
+        sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
+        sysbus_connect_irq(gicbusdev, i + smp_cpus,
+                           qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
+        sysbus_connect_irq(gicbusdev, i + 2 * smp_cpus,
+                           qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
+        sysbus_connect_irq(gicbusdev, i + 3 * smp_cpus,
+                           qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
+    }
+}
+
 static char *virt_get_gic_version(Object *obj, Error **errp)
 {
     ArmMachineState *ams = ARM_MACHINE(obj);
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index b9689b0f0c..f971f49bcf 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -672,103 +672,14 @@ static void set_gic_virt_sysbus(VirtMachineState *vms)
 
 static void create_gic(VirtMachineState *vms)
 {
-    MachineState *ms = MACHINE(vms);
     ArmMachineState *ams = ARM_MACHINE(vms);
-    /* We create a standalone GIC */
-    SysBusDevice *gicbusdev;
-    const char *gictype;
-    int type = ams->gic_version, i;
-    unsigned int smp_cpus = ms->smp.cpus;
-    uint32_t nb_redist_regions = 0;
-
-    gictype = (type == 3) ? gicv3_class_name() : gic_class_name();
-
-    ams->gic = qdev_create(NULL, gictype);
-    qdev_prop_set_uint32(ams->gic, "revision", type);
-    qdev_prop_set_uint32(ams->gic, "num-cpu", smp_cpus);
-    /* Note that the num-irq property counts both internal and external
-     * interrupts; there are always 32 of the former (mandated by GIC spec).
-     */
-    qdev_prop_set_uint32(ams->gic, "num-irq", NUM_IRQS + 32);
 
-    if (type == 3) {
-        uint32_t redist0_capacity =
-                    ams->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(ams);
-
-        qdev_prop_set_uint32(ams->gic, "len-redist-region-count",
-                             nb_redist_regions);
-        qdev_prop_set_uint32(ams->gic, "redist-region-count[0]", redist0_count);
-
-        if (nb_redist_regions == 2) {
-            uint32_t redist1_capacity =
-                    ams->memmap[VIRT_HIGH_GIC_REDIST2].size / GICV3_REDIST_SIZE;
-
-            qdev_prop_set_uint32(ams->gic, "redist-region-count[1]",
-                MIN(smp_cpus - redist0_count, redist1_capacity));
-        }
-    }
+    qdev_create_gic(ams);
     qdev_gic_set_secure_bit(vms);
     qdev_gic_set_virt_bit(vms);
     qdev_init_nofail(ams->gic);
-    gicbusdev = SYS_BUS_DEVICE(ams->gic);
-    sysbus_mmio_map(gicbusdev, 0, ams->memmap[VIRT_GIC_DIST].base);
-    if (type == 3) {
-        sysbus_mmio_map(gicbusdev, 1, ams->memmap[VIRT_GIC_REDIST].base);
-        if (nb_redist_regions == 2) {
-            sysbus_mmio_map(gicbusdev, 2,
-                            ams->memmap[VIRT_HIGH_GIC_REDIST2].base);
-        }
-    } else {
-        sysbus_mmio_map(gicbusdev, 1, ams->memmap[VIRT_GIC_CPU].base);
-    }
-
-    /* Wire the outputs from each CPU's generic timer and the GICv3
-     * maintenance interrupt signal to the appropriate GIC PPI inputs,
-     * and the GIC's IRQ/FIQ/VIRQ/VFIQ interrupt outputs to the CPU's inputs.
-     */
-    for (i = 0; i < smp_cpus; i++) {
-        DeviceState *cpudev = DEVICE(qemu_get_cpu(i));
-        int ppibase = NUM_IRQS + i * GIC_INTERNAL + GIC_NR_SGIS;
-        int irq;
-        /* Mapping from the output timer irq lines from the CPU to the
-         * GIC PPI inputs we use for the virt board.
-         */
-        const int timer_irq[] = {
-            [GTIMER_PHYS] = ARCH_TIMER_NS_EL1_IRQ,
-            [GTIMER_VIRT] = ARCH_TIMER_VIRT_IRQ,
-            [GTIMER_HYP]  = ARCH_TIMER_NS_EL2_IRQ,
-            [GTIMER_SEC]  = ARCH_TIMER_S_EL1_IRQ,
-        };
-
-        for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
-            qdev_connect_gpio_out(cpudev, irq,
-                                  qdev_get_gpio_in(ams->gic,
-                                                   ppibase + timer_irq[irq]));
-        }
-
-        if (type == 3) {
-            qemu_irq irq = qdev_get_gpio_in(ams->gic,
-                                            ppibase + ARCH_GIC_MAINT_IRQ);
-            qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
-                                        0, irq);
-        }
-
-        qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0,
-                                    qdev_get_gpio_in(ams->gic, ppibase
-                                                     + VIRTUAL_PMU_IRQ));
-
-        sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
-        sysbus_connect_irq(gicbusdev, i + smp_cpus,
-                           qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
-        sysbus_connect_irq(gicbusdev, i + 2 * smp_cpus,
-                           qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
-        sysbus_connect_irq(gicbusdev, i + 3 * smp_cpus,
-                           qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
-    }
 
+    init_gic_sysbus(ams);
     set_gic_virt_sysbus(vms);
     fdt_add_gic_node(vms);
     fdt_gic_set_virt_extension(vms);
diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h
index f8bde03cc3..9ba51c4882 100644
--- a/include/hw/arm/arm.h
+++ b/include/hw/arm/arm.h
@@ -108,6 +108,10 @@ typedef struct {
 #define ARM_MACHINE_CLASS(klass) \
     OBJECT_CLASS_CHECK(ArmMachineClass, klass, TYPE_ARM_MACHINE)
 
+void qdev_create_gic(ArmMachineState *ams);
+
+void init_gic_sysbus(ArmMachineState *ams);
+
 /* Return the number of used redistributor regions  */
 static inline int virt_gicv3_redist_region_count(ArmMachineState *ams)
 {
-- 
2.18.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH RFC 11/16] hw/arm: move shared psci_enable and claim_edge_triggered_timers member to ArmMachine
  2020-02-17  7:51 [PATCH RFC 00/16] Implement Microvm for aarch64 architecture Xu Yandong
                   ` (9 preceding siblings ...)
  2020-02-17  7:51 ` [PATCH RFC 10/16] hw/arm: split create_gic function Xu Yandong
@ 2020-02-17  7:51 ` Xu Yandong
  2020-02-17  7:51 ` [PATCH RFC 12/16] hw/arm: move shared devices related functions to arm.c and export them Xu Yandong
                   ` (6 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Xu Yandong @ 2020-02-17  7:51 UTC (permalink / raw)
  To: peter.maydell
  Cc: zhang.zhanghailiang, slp, Michael S. Tsirkin, Xu Yandong,
	qemu-devel, Shannon Zhao, qemu-arm, Igor Mammedov, wu.wubin

Move psci_enable member from VirtMachineState to ArmMachineState.
Move claim_edge_triggered_timers member from VirtMachineClass to
ArmMachineClass.

Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Shannon Zhao <shannon.zhaosl@gmail.com>
Signed-off-by: Xu Yandong <xuyandong2@huawei.com>
---
 hw/arm/virt-acpi-build.c |  7 ++++---
 hw/arm/virt.c            | 14 +++++++-------
 include/hw/arm/arm.h     |  2 ++
 include/hw/arm/virt.h    |  2 --
 4 files changed, 13 insertions(+), 12 deletions(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 770c53f5d0..f2de897694 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -570,12 +570,12 @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
 static void
 build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
 {
-    VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
+    ArmMachineClass *amc = ARM_MACHINE_GET_CLASS(ARM_MACHINE(vms));
     int gtdt_start = table_data->len;
     AcpiGenericTimerTable *gtdt;
     uint32_t irqflags;
 
-    if (vmc->claim_edge_triggered_timers) {
+    if (amc->claim_edge_triggered_timers) {
         irqflags = ACPI_GTDT_INTERRUPT_MODE_EDGE;
     } else {
         irqflags = ACPI_GTDT_INTERRUPT_MODE_LEVEL;
@@ -696,6 +696,7 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
 static void build_fadt_rev5(GArray *table_data, BIOSLinker *linker,
                             VirtMachineState *vms, unsigned dsdt_tbl_offset)
 {
+    ArmMachineState *ams = ARM_MACHINE(vms);
     /* ACPI v5.1 */
     AcpiFadtData fadt = {
         .rev = 5,
@@ -704,7 +705,7 @@ static void build_fadt_rev5(GArray *table_data, BIOSLinker *linker,
         .xdsdt_tbl_offset = &dsdt_tbl_offset,
     };
 
-    switch (vms->psci_conduit) {
+    switch (ams->psci_conduit) {
     case QEMU_PSCI_CONDUIT_DISABLED:
         fadt.arm_boot_arch = 0;
         break;
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index f971f49bcf..2c0dfb2695 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -1576,11 +1576,11 @@ static void machvirt_init(MachineState *machine)
      * because if we're using KVM then we must use HVC).
      */
     if (vms->secure && firmware_loaded) {
-        vms->psci_conduit = QEMU_PSCI_CONDUIT_DISABLED;
+        ams->psci_conduit = QEMU_PSCI_CONDUIT_DISABLED;
     } else if (vms->virt) {
-        vms->psci_conduit = QEMU_PSCI_CONDUIT_SMC;
+        ams->psci_conduit = QEMU_PSCI_CONDUIT_SMC;
     } else {
-        vms->psci_conduit = QEMU_PSCI_CONDUIT_HVC;
+        ams->psci_conduit = QEMU_PSCI_CONDUIT_HVC;
     }
 
     /* The maximum number of CPUs depends on the GIC version, or on how
@@ -1641,8 +1641,8 @@ static void machvirt_init(MachineState *machine)
             object_property_set_bool(cpuobj, false, "has_el2", NULL);
         }
 
-        if (vms->psci_conduit != QEMU_PSCI_CONDUIT_DISABLED) {
-            object_property_set_int(cpuobj, vms->psci_conduit,
+        if (ams->psci_conduit != QEMU_PSCI_CONDUIT_DISABLED) {
+            object_property_set_int(cpuobj, ams->psci_conduit,
                                     "psci-conduit", NULL);
 
             /* Secondary CPUs start in PSCI powered-down state */
@@ -2186,14 +2186,14 @@ DEFINE_VIRT_MACHINE(2, 9)
 
 static void virt_machine_2_8_options(MachineClass *mc)
 {
-    VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
+    ArmMachineClass *amc = ARM_MACHINE_CLASS(OBJECT_CLASS(mc));
 
     virt_machine_2_9_options(mc);
     compat_props_add(mc->compat_props, hw_compat_2_8, hw_compat_2_8_len);
     /* For 2.8 and earlier we falsely claimed in the DT that
      * our timers were edge-triggered, not level-triggered.
      */
-    vmc->claim_edge_triggered_timers = true;
+    amc->claim_edge_triggered_timers = true;
 }
 DEFINE_VIRT_MACHINE(2, 8)
 
diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h
index 9ba51c4882..bb3680e583 100644
--- a/include/hw/arm/arm.h
+++ b/include/hw/arm/arm.h
@@ -86,6 +86,7 @@ typedef struct MemMapEntry {
 
 typedef struct {
     MachineClass parent;
+    bool claim_edge_triggered_timers;
 } ArmMachineClass;
 
 typedef struct {
@@ -97,6 +98,7 @@ typedef struct {
     void *fdt;
     int fdt_size;
     uint32_t gic_phandle;
+    int psci_conduit;
     DeviceState *gic;
 } ArmMachineState;
 
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index 393afb7faf..ad94634038 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -50,7 +50,6 @@ typedef struct {
     bool disallow_affinity_adjustment;
     bool no_its;
     bool no_pmu;
-    bool claim_edge_triggered_timers;
     bool smbios_old_sys_ver;
     bool no_highmem_ecam;
     bool no_ged;   /* Machines < 4.2 has no support for ACPI GED device */
@@ -73,7 +72,6 @@ typedef struct {
     uint32_t clock_phandle;
     uint32_t msi_phandle;
     uint32_t iommu_phandle;
-    int psci_conduit;
     hwaddr highest_gpa;
     DeviceState *acpi_dev;
     Notifier powerdown_notifier;
-- 
2.18.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH RFC 12/16] hw/arm: move shared devices related functions to arm.c and export them
  2020-02-17  7:51 [PATCH RFC 00/16] Implement Microvm for aarch64 architecture Xu Yandong
                   ` (10 preceding siblings ...)
  2020-02-17  7:51 ` [PATCH RFC 11/16] hw/arm: move shared psci_enable and claim_edge_triggered_timers member to ArmMachine Xu Yandong
@ 2020-02-17  7:51 ` Xu Yandong
  2020-02-17  7:51 ` [PATCH RFC 13/16] hw/arm: move shared fdt " Xu Yandong
                   ` (5 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Xu Yandong @ 2020-02-17  7:51 UTC (permalink / raw)
  To: peter.maydell
  Cc: zhang.zhanghailiang, slp, Xu Yandong, qemu-devel, qemu-arm, wu.wubin

Move device related functions to arm.c, include RTC(pl031), UART(pl011),
virtio devices.

Signed-off-by: Xu Yandong <xuyandong2@huawei.com>
---
 hw/arm/arm.c          | 137 +++++++++++++++++++++++++++++++++++++
 hw/arm/virt.c         | 156 +++---------------------------------------
 include/hw/arm/arm.h  |   8 +++
 include/hw/arm/virt.h |   1 -
 4 files changed, 153 insertions(+), 149 deletions(-)

diff --git a/hw/arm/arm.c b/hw/arm/arm.c
index c51bf513d2..6751c6a624 100644
--- a/hw/arm/arm.c
+++ b/hw/arm/arm.c
@@ -145,6 +145,143 @@ void init_gic_sysbus(ArmMachineState *ams)
     }
 }
 
+void create_uart(const ArmMachineState *ams, int uart,
+                        MemoryRegion *mem, Chardev *chr)
+{
+    char *nodename;
+    hwaddr base = ams->memmap[uart].base;
+    hwaddr size = ams->memmap[uart].size;
+    int irq = ams->irqmap[uart];
+    const char compat[] = "arm,pl011\0arm,primecell";
+    const char clocknames[] = "uartclk\0apb_pclk";
+    DeviceState *dev = qdev_create(NULL, "pl011");
+    SysBusDevice *s = SYS_BUS_DEVICE(dev);
+
+    qdev_prop_set_chr(dev, "chardev", chr);
+    qdev_init_nofail(dev);
+    memory_region_add_subregion(mem, base,
+                                sysbus_mmio_get_region(s, 0));
+    sysbus_connect_irq(s, 0, qdev_get_gpio_in(ams->gic, irq));
+
+    nodename = g_strdup_printf("/pl011@%" PRIx64, base);
+    qemu_fdt_add_subnode(ams->fdt, nodename);
+    /* Note that we can't use setprop_string because of the embedded NUL */
+    qemu_fdt_setprop(ams->fdt, nodename, "compatible",
+                         compat, sizeof(compat));
+    qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "reg",
+                                     2, base, 2, size);
+    qemu_fdt_setprop_cells(ams->fdt, nodename, "interrupts",
+                               GIC_FDT_IRQ_TYPE_SPI, irq,
+                               GIC_FDT_IRQ_FLAGS_LEVEL_HI);
+    qemu_fdt_setprop_cells(ams->fdt, nodename, "clocks",
+                               ams->clock_phandle, ams->clock_phandle);
+    qemu_fdt_setprop(ams->fdt, nodename, "clock-names",
+                         clocknames, sizeof(clocknames));
+
+    if (uart == VIRT_UART) {
+        qemu_fdt_setprop_string(ams->fdt, "/chosen", "stdout-path", nodename);
+    } else {
+        /* Mark as not usable by the normal world */
+        qemu_fdt_setprop_string(ams->fdt, nodename, "status", "disabled");
+        qemu_fdt_setprop_string(ams->fdt, nodename, "secure-status", "okay");
+
+        qemu_fdt_add_subnode(ams->fdt, "/secure-chosen");
+        qemu_fdt_setprop_string(ams->fdt, "/secure-chosen", "stdout-path",
+                                nodename);
+    }
+
+    g_free(nodename);
+}
+
+void create_rtc(const ArmMachineState *ams)
+{
+    char *nodename;
+    hwaddr base = ams->memmap[VIRT_RTC].base;
+    hwaddr size = ams->memmap[VIRT_RTC].size;
+    int irq = ams->irqmap[VIRT_RTC];
+    const char compat[] = "arm,pl031\0arm,primecell";
+
+    sysbus_create_simple("pl031", base, qdev_get_gpio_in(ams->gic, irq));
+
+    nodename = g_strdup_printf("/pl031@%" PRIx64, base);
+    qemu_fdt_add_subnode(ams->fdt, nodename);
+    qemu_fdt_setprop(ams->fdt, nodename, "compatible", compat, sizeof(compat));
+    qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "reg",
+                                 2, base, 2, size);
+    qemu_fdt_setprop_cells(ams->fdt, nodename, "interrupts",
+                           GIC_FDT_IRQ_TYPE_SPI, irq,
+                           GIC_FDT_IRQ_FLAGS_LEVEL_HI);
+    qemu_fdt_setprop_cell(ams->fdt, nodename, "clocks", ams->clock_phandle);
+    qemu_fdt_setprop_string(ams->fdt, nodename, "clock-names", "apb_pclk");
+    g_free(nodename);
+}
+
+void create_virtio_devices(const ArmMachineState *ams)
+{
+    int i;
+    hwaddr size = ams->memmap[VIRT_MMIO].size;
+
+    /* We create the transports in forwards order. Since qbus_realize()
+     * prepends (not appends) new child buses, the incrementing loop below will
+     * create a list of virtio-mmio buses with decreasing base addresses.
+     *
+     * When a -device option is processed from the command line,
+     * qbus_find_recursive() picks the next free virtio-mmio bus in forwards
+     * order. The upshot is that -device options in increasing command line
+     * order are mapped to virtio-mmio buses with decreasing base addresses.
+     *
+     * When this code was originally written, that arrangement ensured that the
+     * guest Linux kernel would give the lowest "name" (/dev/vda, eth0, etc) to
+     * the first -device on the command line. (The end-to-end order is a
+     * function of this loop, qbus_realize(), qbus_find_recursive(), and the
+     * guest kernel's name-to-address assignment strategy.)
+     *
+     * Meanwhile, the kernel's traversal seems to have been reversed; see eg.
+     * the message, if not necessarily the code, of commit 70161ff336.
+     * Therefore the loop now establishes the inverse of the original intent.
+     *
+     * Unfortunately, we can't counteract the kernel change by reversing the
+     * loop; it would break existing command lines.
+     *
+     * In any case, the kernel makes no guarantee about the stability of
+     * enumeration order of virtio devices (as demonstrated by it changing
+     * between kernel versions). For reliable and stable identification
+     * of disks users must use UUIDs or similar mechanisms.
+     */
+    for (i = 0; i < NUM_VIRTIO_TRANSPORTS; i++) {
+        int irq = ams->irqmap[VIRT_MMIO] + i;
+        hwaddr base = ams->memmap[VIRT_MMIO].base + i * size;
+
+        sysbus_create_simple("virtio-mmio", base,
+                             qdev_get_gpio_in(ams->gic, irq));
+    }
+
+    /* We add dtb nodes in reverse order so that they appear in the finished
+     * device tree lowest address first.
+     *
+     * Note that this mapping is independent of the loop above. The previous
+     * loop influences virtio device to virtio transport assignment, whereas
+     * this loop controls how virtio transports are laid out in the dtb.
+     */
+    for (i = NUM_VIRTIO_TRANSPORTS - 1; i >= 0; i--) {
+        char *nodename;
+        int irq = ams->irqmap[VIRT_MMIO] + i;
+        hwaddr base = ams->memmap[VIRT_MMIO].base + i * size;
+
+        nodename = g_strdup_printf("/virtio_mmio@%" PRIx64, base);
+        qemu_fdt_add_subnode(ams->fdt, nodename);
+        qemu_fdt_setprop_string(ams->fdt, nodename,
+                                "compatible", "virtio,mmio");
+        qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "reg",
+                                     2, base, 2, size);
+        qemu_fdt_setprop_cells(ams->fdt, nodename, "interrupts",
+                               GIC_FDT_IRQ_TYPE_SPI, irq,
+                               GIC_FDT_IRQ_FLAGS_EDGE_LO_HI);
+        qemu_fdt_setprop(ams->fdt, nodename, "dma-coherent", NULL, 0);
+        g_free(nodename);
+    }
+}
+
 static char *virt_get_gic_version(Object *obj, Error **errp)
 {
     ArmMachineState *ams = ARM_MACHINE(obj);
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 2c0dfb2695..b3267b873a 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -231,14 +231,14 @@ static void create_fdt(VirtMachineState *vms)
      * optional but in practice if you omit them the kernel refuses to
      * probe for the device.
      */
-    vms->clock_phandle = qemu_fdt_alloc_phandle(fdt);
+    ams->clock_phandle = qemu_fdt_alloc_phandle(fdt);
     qemu_fdt_add_subnode(fdt, "/apb-pclk");
     qemu_fdt_setprop_string(fdt, "/apb-pclk", "compatible", "fixed-clock");
     qemu_fdt_setprop_cell(fdt, "/apb-pclk", "#clock-cells", 0x0);
     qemu_fdt_setprop_cell(fdt, "/apb-pclk", "clock-frequency", 24000000);
     qemu_fdt_setprop_string(fdt, "/apb-pclk", "clock-output-names",
                                 "clk24mhz");
-    qemu_fdt_setprop_cell(fdt, "/apb-pclk", "phandle", vms->clock_phandle);
+    qemu_fdt_setprop_cell(fdt, "/apb-pclk", "phandle", ams->clock_phandle);
 
     if (nb_numa_nodes > 0 && ms->numa_state->have_numa_distance) {
         int size = nb_numa_nodes * nb_numa_nodes * 3 * sizeof(uint32_t);
@@ -687,79 +687,6 @@ static void create_gic(VirtMachineState *vms)
     gic_set_msi_interrupt(vms);
 }
 
-static void create_uart(const VirtMachineState *vms, int uart,
-                        MemoryRegion *mem, Chardev *chr)
-{
-    char *nodename;
-    const ArmMachineState *ams = ARM_MACHINE(vms);
-    hwaddr base = ams->memmap[uart].base;
-    hwaddr size = ams->memmap[uart].size;
-    int irq = ams->irqmap[uart];
-    const char compat[] = "arm,pl011\0arm,primecell";
-    const char clocknames[] = "uartclk\0apb_pclk";
-    DeviceState *dev = qdev_create(NULL, "pl011");
-    SysBusDevice *s = SYS_BUS_DEVICE(dev);
-
-    qdev_prop_set_chr(dev, "chardev", chr);
-    qdev_init_nofail(dev);
-    memory_region_add_subregion(mem, base,
-                                sysbus_mmio_get_region(s, 0));
-    sysbus_connect_irq(s, 0, qdev_get_gpio_in(ams->gic, irq));
-
-    nodename = g_strdup_printf("/pl011@%" PRIx64, base);
-    qemu_fdt_add_subnode(ams->fdt, nodename);
-    /* Note that we can't use setprop_string because of the embedded NUL */
-    qemu_fdt_setprop(ams->fdt, nodename, "compatible",
-                         compat, sizeof(compat));
-    qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "reg",
-                                     2, base, 2, size);
-    qemu_fdt_setprop_cells(ams->fdt, nodename, "interrupts",
-                               GIC_FDT_IRQ_TYPE_SPI, irq,
-                               GIC_FDT_IRQ_FLAGS_LEVEL_HI);
-    qemu_fdt_setprop_cells(ams->fdt, nodename, "clocks",
-                               vms->clock_phandle, vms->clock_phandle);
-    qemu_fdt_setprop(ams->fdt, nodename, "clock-names",
-                         clocknames, sizeof(clocknames));
-
-    if (uart == VIRT_UART) {
-        qemu_fdt_setprop_string(ams->fdt, "/chosen", "stdout-path", nodename);
-    } else {
-        /* Mark as not usable by the normal world */
-        qemu_fdt_setprop_string(ams->fdt, nodename, "status", "disabled");
-        qemu_fdt_setprop_string(ams->fdt, nodename, "secure-status", "okay");
-
-        qemu_fdt_add_subnode(ams->fdt, "/secure-chosen");
-        qemu_fdt_setprop_string(ams->fdt, "/secure-chosen", "stdout-path",
-                                nodename);
-    }
-
-    g_free(nodename);
-}
-
-static void create_rtc(const VirtMachineState *vms)
-{
-    char *nodename;
-    const ArmMachineState *ams = ARM_MACHINE(vms);
-    hwaddr base = ams->memmap[VIRT_RTC].base;
-    hwaddr size = ams->memmap[VIRT_RTC].size;
-    int irq = ams->irqmap[VIRT_RTC];
-    const char compat[] = "arm,pl031\0arm,primecell";
-
-    sysbus_create_simple("pl031", base, qdev_get_gpio_in(ams->gic, irq));
-
-    nodename = g_strdup_printf("/pl031@%" PRIx64, base);
-    qemu_fdt_add_subnode(ams->fdt, nodename);
-    qemu_fdt_setprop(ams->fdt, nodename, "compatible", compat, sizeof(compat));
-    qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "reg",
-                                 2, base, 2, size);
-    qemu_fdt_setprop_cells(ams->fdt, nodename, "interrupts",
-                           GIC_FDT_IRQ_TYPE_SPI, irq,
-                           GIC_FDT_IRQ_FLAGS_LEVEL_HI);
-    qemu_fdt_setprop_cell(ams->fdt, nodename, "clocks", vms->clock_phandle);
-    qemu_fdt_setprop_string(ams->fdt, nodename, "clock-names", "apb_pclk");
-    g_free(nodename);
-}
-
 static DeviceState *gpio_key_dev;
 static void virt_powerdown_req(Notifier *n, void *opaque)
 {
@@ -797,7 +724,7 @@ static void create_gpio(const VirtMachineState *vms)
     qemu_fdt_setprop_cells(ams->fdt, nodename, "interrupts",
                            GIC_FDT_IRQ_TYPE_SPI, irq,
                            GIC_FDT_IRQ_FLAGS_LEVEL_HI);
-    qemu_fdt_setprop_cell(ams->fdt, nodename, "clocks", vms->clock_phandle);
+    qemu_fdt_setprop_cell(ams->fdt, nodename, "clocks", ams->clock_phandle);
     qemu_fdt_setprop_string(ams->fdt, nodename, "clock-names", "apb_pclk");
     qemu_fdt_setprop_cell(ams->fdt, nodename, "phandle", phandle);
 
@@ -818,73 +745,6 @@ static void create_gpio(const VirtMachineState *vms)
     g_free(nodename);
 }
 
-static void create_virtio_devices(const VirtMachineState *vms)
-{
-    int i;
-    const ArmMachineState *ams = ARM_MACHINE(vms);
-    hwaddr size = ams->memmap[VIRT_MMIO].size;
-
-    /* We create the transports in forwards order. Since qbus_realize()
-     * prepends (not appends) new child buses, the incrementing loop below will
-     * create a list of virtio-mmio buses with decreasing base addresses.
-     *
-     * When a -device option is processed from the command line,
-     * qbus_find_recursive() picks the next free virtio-mmio bus in forwards
-     * order. The upshot is that -device options in increasing command line
-     * order are mapped to virtio-mmio buses with decreasing base addresses.
-     *
-     * When this code was originally written, that arrangement ensured that the
-     * guest Linux kernel would give the lowest "name" (/dev/vda, eth0, etc) to
-     * the first -device on the command line. (The end-to-end order is a
-     * function of this loop, qbus_realize(), qbus_find_recursive(), and the
-     * guest kernel's name-to-address assignment strategy.)
-     *
-     * Meanwhile, the kernel's traversal seems to have been reversed; see eg.
-     * the message, if not necessarily the code, of commit 70161ff336.
-     * Therefore the loop now establishes the inverse of the original intent.
-     *
-     * Unfortunately, we can't counteract the kernel change by reversing the
-     * loop; it would break existing command lines.
-     *
-     * In any case, the kernel makes no guarantee about the stability of
-     * enumeration order of virtio devices (as demonstrated by it changing
-     * between kernel versions). For reliable and stable identification
-     * of disks users must use UUIDs or similar mechanisms.
-     */
-    for (i = 0; i < NUM_VIRTIO_TRANSPORTS; i++) {
-        int irq = ams->irqmap[VIRT_MMIO] + i;
-        hwaddr base = ams->memmap[VIRT_MMIO].base + i * size;
-
-        sysbus_create_simple("virtio-mmio", base,
-                             qdev_get_gpio_in(ams->gic, irq));
-    }
-
-    /* We add dtb nodes in reverse order so that they appear in the finished
-     * device tree lowest address first.
-     *
-     * Note that this mapping is independent of the loop above. The previous
-     * loop influences virtio device to virtio transport assignment, whereas
-     * this loop controls how virtio transports are laid out in the dtb.
-     */
-    for (i = NUM_VIRTIO_TRANSPORTS - 1; i >= 0; i--) {
-        char *nodename;
-        int irq = ams->irqmap[VIRT_MMIO] + i;
-        hwaddr base = ams->memmap[VIRT_MMIO].base + i * size;
-
-        nodename = g_strdup_printf("/virtio_mmio@%" PRIx64, base);
-        qemu_fdt_add_subnode(ams->fdt, nodename);
-        qemu_fdt_setprop_string(ams->fdt, nodename,
-                                "compatible", "virtio,mmio");
-        qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "reg",
-                                     2, base, 2, size);
-        qemu_fdt_setprop_cells(ams->fdt, nodename, "interrupts",
-                               GIC_FDT_IRQ_TYPE_SPI, irq,
-                               GIC_FDT_IRQ_FLAGS_EDGE_LO_HI);
-        qemu_fdt_setprop(ams->fdt, nodename, "dma-coherent", NULL, 0);
-        g_free(nodename);
-    }
-}
-
 #define VIRT_FLASH_SECTOR_SIZE (256 * KiB)
 
 static PFlashCFI01 *virt_flash_create1(VirtMachineState *vms,
@@ -1151,7 +1011,7 @@ static void create_smmu(const VirtMachineState *vms,
     qemu_fdt_setprop(ams->fdt, node, "interrupt-names", irq_names,
                      sizeof(irq_names));
 
-    qemu_fdt_setprop_cell(ams->fdt, node, "clocks", vms->clock_phandle);
+    qemu_fdt_setprop_cell(ams->fdt, node, "clocks", ams->clock_phandle);
     qemu_fdt_setprop_string(ams->fdt, node, "clock-names", "apb_pclk");
     qemu_fdt_setprop(ams->fdt, node, "dma-coherent", NULL, 0);
 
@@ -1709,16 +1569,16 @@ static void machvirt_init(MachineState *machine)
 
     fdt_add_pmu_nodes(vms);
 
-    create_uart(vms, VIRT_UART, sysmem, serial_hd(0));
+    create_uart(ams, VIRT_UART, sysmem, serial_hd(0));
 
     if (vms->secure) {
         create_secure_ram(vms, secure_sysmem);
-        create_uart(vms, VIRT_SECURE_UART, secure_sysmem, serial_hd(1));
+        create_uart(ams, VIRT_SECURE_UART, secure_sysmem, serial_hd(1));
     }
 
     vms->highmem_ecam &= vms->highmem && (!firmware_loaded || aarch64);
 
-    create_rtc(vms);
+    create_rtc(ams);
 
     create_pcie(vms);
 
@@ -1736,7 +1596,7 @@ static void machvirt_init(MachineState *machine)
      * (which will be automatically plugged in to the transports). If
      * no backend is created the transport will just sit harmlessly idle.
      */
-    create_virtio_devices(vms);
+    create_virtio_devices(ams);
 
     vms->fw_cfg = create_fw_cfg(vms, &address_space_memory);
     rom_set_fw(vms->fw_cfg);
diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h
index bb3680e583..8fec23985e 100644
--- a/include/hw/arm/arm.h
+++ b/include/hw/arm/arm.h
@@ -97,6 +97,7 @@ typedef struct {
     int smp_cpus;
     void *fdt;
     int fdt_size;
+    uint32_t clock_phandle;
     uint32_t gic_phandle;
     int psci_conduit;
     DeviceState *gic;
@@ -114,6 +115,13 @@ void qdev_create_gic(ArmMachineState *ams);
 
 void init_gic_sysbus(ArmMachineState *ams);
 
+void create_uart(const ArmMachineState *ams, int uart,
+                 MemoryRegion *mem, Chardev *chr);
+
+void create_rtc(const ArmMachineState *ams);
+
+void create_virtio_devices(const ArmMachineState *ams);
+
 /* Return the number of used redistributor regions  */
 static inline int virt_gicv3_redist_region_count(ArmMachineState *ams)
 {
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index ad94634038..086a27682f 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -69,7 +69,6 @@ typedef struct {
     bool virt;
     VirtIOMMUType iommu;
     struct arm_boot_info bootinfo;
-    uint32_t clock_phandle;
     uint32_t msi_phandle;
     uint32_t iommu_phandle;
     hwaddr highest_gpa;
-- 
2.18.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH RFC 13/16] hw/arm: move shared fdt related functions to arm.c and export them
  2020-02-17  7:51 [PATCH RFC 00/16] Implement Microvm for aarch64 architecture Xu Yandong
                   ` (11 preceding siblings ...)
  2020-02-17  7:51 ` [PATCH RFC 12/16] hw/arm: move shared devices related functions to arm.c and export them Xu Yandong
@ 2020-02-17  7:51 ` Xu Yandong
  2020-02-17  7:51 ` [PATCH RFC 14/16] hw/arm: move shared bootinfo member to ArmMachine Xu Yandong
                   ` (4 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Xu Yandong @ 2020-02-17  7:51 UTC (permalink / raw)
  To: peter.maydell
  Cc: zhang.zhanghailiang, slp, Xu Yandong, qemu-devel, qemu-arm, wu.wubin

Move fdt related functions that will be shared between VIRT and
non-VIRT machine types to arm.c.

Signed-off-by: Xu Yandong <xuyandong2@huawei.com>
---
 hw/arm/arm.c         | 226 ++++++++++++++++++++++++++++++++++++++++
 hw/arm/virt.c        | 238 +------------------------------------------
 include/hw/arm/arm.h |   8 ++
 3 files changed, 238 insertions(+), 234 deletions(-)

diff --git a/hw/arm/arm.c b/hw/arm/arm.c
index 6751c6a624..4bffee0f37 100644
--- a/hw/arm/arm.c
+++ b/hw/arm/arm.c
@@ -39,6 +39,232 @@
 #include "hw/intc/arm_gic.h"
 #include "kvm_arm.h"
 
+void create_fdt(ArmMachineState *ams)
+{
+    MachineState *ms = MACHINE(ams);
+    int nb_numa_nodes = ms->numa_state->num_nodes;
+    void *fdt = create_device_tree(&ams->fdt_size);
+
+    if (!fdt) {
+        error_report("create_device_tree() failed");
+        exit(1);
+    }
+
+    ams->fdt = fdt;
+
+    /* Header */
+    qemu_fdt_setprop_string(fdt, "/", "compatible", "linux,dummy-virt");
+    qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 0x2);
+    qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 0x2);
+
+    /* /chosen must exist for load_dtb to fill in necessary properties later */
+    qemu_fdt_add_subnode(fdt, "/chosen");
+
+    /* Clock node, for the benefit of the UART. The kernel device tree
+     * binding documentation claims the PL011 node clock properties are
+     * optional but in practice if you omit them the kernel refuses to
+     * probe for the device.
+     */
+    ams->clock_phandle = qemu_fdt_alloc_phandle(fdt);
+    qemu_fdt_add_subnode(fdt, "/apb-pclk");
+    qemu_fdt_setprop_string(fdt, "/apb-pclk", "compatible", "fixed-clock");
+    qemu_fdt_setprop_cell(fdt, "/apb-pclk", "#clock-cells", 0x0);
+    qemu_fdt_setprop_cell(fdt, "/apb-pclk", "clock-frequency", 24000000);
+    qemu_fdt_setprop_string(fdt, "/apb-pclk", "clock-output-names",
+                                "clk24mhz");
+    qemu_fdt_setprop_cell(fdt, "/apb-pclk", "phandle", ams->clock_phandle);
+
+    if (nb_numa_nodes > 0 && ms->numa_state->have_numa_distance) {
+        int size = nb_numa_nodes * nb_numa_nodes * 3 * sizeof(uint32_t);
+        uint32_t *matrix = g_malloc0(size);
+        int idx, i, j;
+
+        for (i = 0; i < nb_numa_nodes; i++) {
+            for (j = 0; j < nb_numa_nodes; j++) {
+                idx = (i * nb_numa_nodes + j) * 3;
+                matrix[idx + 0] = cpu_to_be32(i);
+                matrix[idx + 1] = cpu_to_be32(j);
+                matrix[idx + 2] =
+                    cpu_to_be32(ms->numa_state->nodes[i].distance[j]);
+            }
+        }
+
+        qemu_fdt_add_subnode(fdt, "/distance-map");
+        qemu_fdt_setprop_string(fdt, "/distance-map", "compatible",
+                                "numa-distance-map-v1");
+        qemu_fdt_setprop(fdt, "/distance-map", "distance-matrix",
+                         matrix, size);
+        g_free(matrix);
+    }
+}
+
+void fdt_add_timer_nodes(const ArmMachineState *ams)
+{
+    /* On real hardware these interrupts are level-triggered.
+     * On KVM they were edge-triggered before host kernel version 4.4,
+     * and level-triggered afterwards.
+     * On emulated QEMU they are level-triggered.
+     *
+     * Getting the DTB info about them wrong is awkward for some
+     * guest kernels:
+     *  pre-4.8 ignore the DT and leave the interrupt configured
+     *   with whatever the GIC reset value (or the bootloader) left it at
+     *  4.8 before rc6 honour the incorrect data by programming it back
+     *   into the GIC, causing problems
+     *  4.8rc6 and later ignore the DT and always write "level triggered"
+     *   into the GIC
+     *
+     * For backwards-compatibility, virt-2.8 and earlier will continue
+     * to say these are edge-triggered, but later machines will report
+     * the correct information.
+     */
+    ARMCPU *armcpu;
+    ArmMachineClass *amc = ARM_MACHINE_GET_CLASS(ams);
+    uint32_t irqflags = GIC_FDT_IRQ_FLAGS_LEVEL_HI;
+
+    if (amc->claim_edge_triggered_timers) {
+        irqflags = GIC_FDT_IRQ_FLAGS_EDGE_LO_HI;
+    }
+
+    if (ams->gic_version == 2) {
+        irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START,
+                             GIC_FDT_IRQ_PPI_CPU_WIDTH,
+                             (1 << ams->smp_cpus) - 1);
+    }
+
+    qemu_fdt_add_subnode(ams->fdt, "/timer");
+
+    armcpu = ARM_CPU(qemu_get_cpu(0));
+    if (arm_feature(&armcpu->env, ARM_FEATURE_V8)) {
+        const char compat[] = "arm,armv8-timer\0arm,armv7-timer";
+        qemu_fdt_setprop(ams->fdt, "/timer", "compatible",
+                         compat, sizeof(compat));
+    } else {
+        qemu_fdt_setprop_string(ams->fdt, "/timer", "compatible",
+                                "arm,armv7-timer");
+    }
+    qemu_fdt_setprop(ams->fdt, "/timer", "always-on", NULL, 0);
+    qemu_fdt_setprop_cells(ams->fdt, "/timer", "interrupts",
+                       GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_S_EL1_IRQ, irqflags,
+                       GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_NS_EL1_IRQ, irqflags,
+                       GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_VIRT_IRQ, irqflags,
+                       GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_NS_EL2_IRQ, irqflags);
+}
+
+void fdt_add_cpu_nodes(const ArmMachineState *ams)
+{
+    int cpu;
+    int addr_cells = 1;
+    const MachineState *ms = MACHINE(ams);
+
+    /*
+     * From Documentation/devicetree/bindings/arm/cpus.txt
+     *  On ARM v8 64-bit systems value should be set to 2,
+     *  that corresponds to the MPIDR_EL1 register size.
+     *  If MPIDR_EL1[63:32] value is equal to 0 on all CPUs
+     *  in the system, #address-cells can be set to 1, since
+     *  MPIDR_EL1[63:32] bits are not used for CPUs
+     *  identification.
+     *
+     *  Here we actually don't know whether our system is 32- or 64-bit one.
+     *  The simplest way to go is to examine affinity IDs of all our CPUs. If
+     *  at least one of them has Aff3 populated, we set #address-cells to 2.
+     */
+    for (cpu = 0; cpu < ams->smp_cpus; cpu++) {
+        ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu));
+
+        if (armcpu->mp_affinity & ARM_AFF3_MASK) {
+            addr_cells = 2;
+            break;
+        }
+    }
+
+    qemu_fdt_add_subnode(ams->fdt, "/cpus");
+    qemu_fdt_setprop_cell(ams->fdt, "/cpus", "#address-cells", addr_cells);
+    qemu_fdt_setprop_cell(ams->fdt, "/cpus", "#size-cells", 0x0);
+
+    for (cpu = ams->smp_cpus - 1; cpu >= 0; cpu--) {
+        char *nodename = g_strdup_printf("/cpus/cpu@%d", cpu);
+        ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu));
+        CPUState *cs = CPU(armcpu);
+
+        qemu_fdt_add_subnode(ams->fdt, nodename);
+        qemu_fdt_setprop_string(ams->fdt, nodename, "device_type", "cpu");
+        qemu_fdt_setprop_string(ams->fdt, nodename, "compatible",
+                                    armcpu->dtb_compatible);
+
+        if (ams->psci_conduit != QEMU_PSCI_CONDUIT_DISABLED
+            && ams->smp_cpus > 1) {
+            qemu_fdt_setprop_string(ams->fdt, nodename,
+                                        "enable-method", "psci");
+        }
+
+        if (addr_cells == 2) {
+            qemu_fdt_setprop_u64(ams->fdt, nodename, "reg",
+                                 armcpu->mp_affinity);
+        } else {
+            qemu_fdt_setprop_cell(ams->fdt, nodename, "reg",
+                                  armcpu->mp_affinity);
+        }
+
+        if (ms->possible_cpus->cpus[cs->cpu_index].props.has_node_id) {
+            qemu_fdt_setprop_cell(ams->fdt, nodename, "numa-node-id",
+                ms->possible_cpus->cpus[cs->cpu_index].props.node_id);
+        }
+
+        g_free(nodename);
+    }
+}
+
+void fdt_add_gic_node(ArmMachineState *ams)
+{
+    char *nodename;
+
+    ams->gic_phandle = qemu_fdt_alloc_phandle(ams->fdt);
+    qemu_fdt_setprop_cell(ams->fdt, "/", "interrupt-parent", ams->gic_phandle);
+
+    nodename = g_strdup_printf("/intc@%" PRIx64,
+                               ams->memmap[VIRT_GIC_DIST].base);
+    qemu_fdt_add_subnode(ams->fdt, nodename);
+    qemu_fdt_setprop_cell(ams->fdt, nodename, "#interrupt-cells", 3);
+    qemu_fdt_setprop(ams->fdt, nodename, "interrupt-controller", NULL, 0);
+    qemu_fdt_setprop_cell(ams->fdt, nodename, "#address-cells", 0x2);
+    qemu_fdt_setprop_cell(ams->fdt, nodename, "#size-cells", 0x2);
+    qemu_fdt_setprop(ams->fdt, nodename, "ranges", NULL, 0);
+    if (ams->gic_version == 3) {
+        int nb_redist_regions = virt_gicv3_redist_region_count(ams);
+
+        qemu_fdt_setprop_string(ams->fdt, nodename, "compatible",
+                                "arm,gic-v3");
+
+        qemu_fdt_setprop_cell(ams->fdt, nodename,
+                              "#redistributor-regions", nb_redist_regions);
+
+        if (nb_redist_regions == 1) {
+            qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "reg",
+                                         2, ams->memmap[VIRT_GIC_DIST].base,
+                                         2, ams->memmap[VIRT_GIC_DIST].size,
+                                         2, ams->memmap[VIRT_GIC_REDIST].base,
+                                         2, ams->memmap[VIRT_GIC_REDIST].size);
+        } else {
+            qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "reg",
+                                 2, ams->memmap[VIRT_GIC_DIST].base,
+                                 2, ams->memmap[VIRT_GIC_DIST].size,
+                                 2, ams->memmap[VIRT_GIC_REDIST].base,
+                                 2, ams->memmap[VIRT_GIC_REDIST].size,
+                                 2, ams->memmap[VIRT_HIGH_GIC_REDIST2].base,
+                                 2, ams->memmap[VIRT_HIGH_GIC_REDIST2].size);
+        }
+    } else {
+        /* 'cortex-a15-gic' means 'GIC v2' */
+        qemu_fdt_setprop_string(ams->fdt, nodename, "compatible",
+                                "arm,cortex-a15-gic");
+    }
+
+    qemu_fdt_setprop_cell(ams->fdt, nodename, "phandle", ams->gic_phandle);
+    g_free(nodename);
+}
+
 void qdev_create_gic(ArmMachineState *ams)
 {
     MachineState *ms = MACHINE(ams);
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index b3267b873a..11e753906b 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -204,186 +204,6 @@ static bool cpu_type_valid(const char *cpu)
     return false;
 }
 
-static void create_fdt(VirtMachineState *vms)
-{
-    MachineState *ms = MACHINE(vms);
-    ArmMachineState *ams = ARM_MACHINE(vms);
-    int nb_numa_nodes = ms->numa_state->num_nodes;
-    void *fdt = create_device_tree(&ams->fdt_size);
-
-    if (!fdt) {
-        error_report("create_device_tree() failed");
-        exit(1);
-    }
-
-    ams->fdt = fdt;
-
-    /* Header */
-    qemu_fdt_setprop_string(fdt, "/", "compatible", "linux,dummy-virt");
-    qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 0x2);
-    qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 0x2);
-
-    /* /chosen must exist for load_dtb to fill in necessary properties later */
-    qemu_fdt_add_subnode(fdt, "/chosen");
-
-    /* Clock node, for the benefit of the UART. The kernel device tree
-     * binding documentation claims the PL011 node clock properties are
-     * optional but in practice if you omit them the kernel refuses to
-     * probe for the device.
-     */
-    ams->clock_phandle = qemu_fdt_alloc_phandle(fdt);
-    qemu_fdt_add_subnode(fdt, "/apb-pclk");
-    qemu_fdt_setprop_string(fdt, "/apb-pclk", "compatible", "fixed-clock");
-    qemu_fdt_setprop_cell(fdt, "/apb-pclk", "#clock-cells", 0x0);
-    qemu_fdt_setprop_cell(fdt, "/apb-pclk", "clock-frequency", 24000000);
-    qemu_fdt_setprop_string(fdt, "/apb-pclk", "clock-output-names",
-                                "clk24mhz");
-    qemu_fdt_setprop_cell(fdt, "/apb-pclk", "phandle", ams->clock_phandle);
-
-    if (nb_numa_nodes > 0 && ms->numa_state->have_numa_distance) {
-        int size = nb_numa_nodes * nb_numa_nodes * 3 * sizeof(uint32_t);
-        uint32_t *matrix = g_malloc0(size);
-        int idx, i, j;
-
-        for (i = 0; i < nb_numa_nodes; i++) {
-            for (j = 0; j < nb_numa_nodes; j++) {
-                idx = (i * nb_numa_nodes + j) * 3;
-                matrix[idx + 0] = cpu_to_be32(i);
-                matrix[idx + 1] = cpu_to_be32(j);
-                matrix[idx + 2] =
-                    cpu_to_be32(ms->numa_state->nodes[i].distance[j]);
-            }
-        }
-
-        qemu_fdt_add_subnode(fdt, "/distance-map");
-        qemu_fdt_setprop_string(fdt, "/distance-map", "compatible",
-                                "numa-distance-map-v1");
-        qemu_fdt_setprop(fdt, "/distance-map", "distance-matrix",
-                         matrix, size);
-        g_free(matrix);
-    }
-}
-
-static void fdt_add_timer_nodes(const VirtMachineState *vms)
-{
-    /* On real hardware these interrupts are level-triggered.
-     * On KVM they were edge-triggered before host kernel version 4.4,
-     * and level-triggered afterwards.
-     * On emulated QEMU they are level-triggered.
-     *
-     * Getting the DTB info about them wrong is awkward for some
-     * guest kernels:
-     *  pre-4.8 ignore the DT and leave the interrupt configured
-     *   with whatever the GIC reset value (or the bootloader) left it at
-     *  4.8 before rc6 honour the incorrect data by programming it back
-     *   into the GIC, causing problems
-     *  4.8rc6 and later ignore the DT and always write "level triggered"
-     *   into the GIC
-     *
-     * For backwards-compatibility, virt-2.8 and earlier will continue
-     * to say these are edge-triggered, but later machines will report
-     * the correct information.
-     */
-    ARMCPU *armcpu;
-    ArmMachineState *ams = ARM_MACHINE(vms);
-    VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
-    uint32_t irqflags = GIC_FDT_IRQ_FLAGS_LEVEL_HI;
-
-    if (vmc->claim_edge_triggered_timers) {
-        irqflags = GIC_FDT_IRQ_FLAGS_EDGE_LO_HI;
-    }
-
-    if (ams->gic_version == 2) {
-        irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START,
-                             GIC_FDT_IRQ_PPI_CPU_WIDTH,
-                             (1 << ams->smp_cpus) - 1);
-    }
-
-    qemu_fdt_add_subnode(ams->fdt, "/timer");
-
-    armcpu = ARM_CPU(qemu_get_cpu(0));
-    if (arm_feature(&armcpu->env, ARM_FEATURE_V8)) {
-        const char compat[] = "arm,armv8-timer\0arm,armv7-timer";
-        qemu_fdt_setprop(ams->fdt, "/timer", "compatible",
-                         compat, sizeof(compat));
-    } else {
-        qemu_fdt_setprop_string(ams->fdt, "/timer", "compatible",
-                                "arm,armv7-timer");
-    }
-    qemu_fdt_setprop(ams->fdt, "/timer", "always-on", NULL, 0);
-    qemu_fdt_setprop_cells(ams->fdt, "/timer", "interrupts",
-                       GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_S_EL1_IRQ, irqflags,
-                       GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_NS_EL1_IRQ, irqflags,
-                       GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_VIRT_IRQ, irqflags,
-                       GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_NS_EL2_IRQ, irqflags);
-}
-
-static void fdt_add_cpu_nodes(const VirtMachineState *vms)
-{
-    int cpu;
-    int addr_cells = 1;
-    const MachineState *ms = MACHINE(vms);
-    const ArmMachineState *ams = ARM_MACHINE(vms);
-
-    /*
-     * From Documentation/devicetree/bindings/arm/cpus.txt
-     *  On ARM v8 64-bit systems value should be set to 2,
-     *  that corresponds to the MPIDR_EL1 register size.
-     *  If MPIDR_EL1[63:32] value is equal to 0 on all CPUs
-     *  in the system, #address-cells can be set to 1, since
-     *  MPIDR_EL1[63:32] bits are not used for CPUs
-     *  identification.
-     *
-     *  Here we actually don't know whether our system is 32- or 64-bit one.
-     *  The simplest way to go is to examine affinity IDs of all our CPUs. If
-     *  at least one of them has Aff3 populated, we set #address-cells to 2.
-     */
-    for (cpu = 0; cpu < ams->smp_cpus; cpu++) {
-        ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu));
-
-        if (armcpu->mp_affinity & ARM_AFF3_MASK) {
-            addr_cells = 2;
-            break;
-        }
-    }
-
-    qemu_fdt_add_subnode(ams->fdt, "/cpus");
-    qemu_fdt_setprop_cell(ams->fdt, "/cpus", "#address-cells", addr_cells);
-    qemu_fdt_setprop_cell(ams->fdt, "/cpus", "#size-cells", 0x0);
-
-    for (cpu = ams->smp_cpus - 1; cpu >= 0; cpu--) {
-        char *nodename = g_strdup_printf("/cpus/cpu@%d", cpu);
-        ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu));
-        CPUState *cs = CPU(armcpu);
-
-        qemu_fdt_add_subnode(ams->fdt, nodename);
-        qemu_fdt_setprop_string(ams->fdt, nodename, "device_type", "cpu");
-        qemu_fdt_setprop_string(ams->fdt, nodename, "compatible",
-                                    armcpu->dtb_compatible);
-
-        if (vms->psci_conduit != QEMU_PSCI_CONDUIT_DISABLED
-            && ams->smp_cpus > 1) {
-            qemu_fdt_setprop_string(ams->fdt, nodename,
-                                        "enable-method", "psci");
-        }
-
-        if (addr_cells == 2) {
-            qemu_fdt_setprop_u64(ams->fdt, nodename, "reg",
-                                 armcpu->mp_affinity);
-        } else {
-            qemu_fdt_setprop_cell(ams->fdt, nodename, "reg",
-                                  armcpu->mp_affinity);
-        }
-
-        if (ms->possible_cpus->cpus[cs->cpu_index].props.has_node_id) {
-            qemu_fdt_setprop_cell(ams->fdt, nodename, "numa-node-id",
-                ms->possible_cpus->cpus[cs->cpu_index].props.node_id);
-        }
-
-        g_free(nodename);
-    }
-}
-
 static void fdt_add_its_gic_node(VirtMachineState *vms)
 {
     char *nodename;
@@ -461,56 +281,6 @@ static void fdt_gic_set_virt_extension(VirtMachineState *vms)
     }
 }
 
-static void fdt_add_gic_node(VirtMachineState *vms)
-{
-    char *nodename;
-    ArmMachineState *ams = ARM_MACHINE(vms);
-
-    ams->gic_phandle = qemu_fdt_alloc_phandle(ams->fdt);
-    qemu_fdt_setprop_cell(ams->fdt, "/", "interrupt-parent", ams->gic_phandle);
-
-    nodename = g_strdup_printf("/intc@%" PRIx64,
-                               ams->memmap[VIRT_GIC_DIST].base);
-    qemu_fdt_add_subnode(ams->fdt, nodename);
-    qemu_fdt_setprop_cell(ams->fdt, nodename, "#interrupt-cells", 3);
-    qemu_fdt_setprop(ams->fdt, nodename, "interrupt-controller", NULL, 0);
-    qemu_fdt_setprop_cell(ams->fdt, nodename, "#address-cells", 0x2);
-    qemu_fdt_setprop_cell(ams->fdt, nodename, "#size-cells", 0x2);
-    qemu_fdt_setprop(ams->fdt, nodename, "ranges", NULL, 0);
-    if (ams->gic_version == 3) {
-        int nb_redist_regions = virt_gicv3_redist_region_count(ams);
-
-        qemu_fdt_setprop_string(ams->fdt, nodename, "compatible",
-                                "arm,gic-v3");
-
-        qemu_fdt_setprop_cell(ams->fdt, nodename,
-                              "#redistributor-regions", nb_redist_regions);
-
-        if (nb_redist_regions == 1) {
-            qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "reg",
-                                         2, ams->memmap[VIRT_GIC_DIST].base,
-                                         2, ams->memmap[VIRT_GIC_DIST].size,
-                                         2, ams->memmap[VIRT_GIC_REDIST].base,
-                                         2, ams->memmap[VIRT_GIC_REDIST].size);
-        } else {
-            qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "reg",
-                                 2, ams->memmap[VIRT_GIC_DIST].base,
-                                 2, ams->memmap[VIRT_GIC_DIST].size,
-                                 2, ams->memmap[VIRT_GIC_REDIST].base,
-                                 2, ams->memmap[VIRT_GIC_REDIST].size,
-                                 2, ams->memmap[VIRT_HIGH_GIC_REDIST2].base,
-                                 2, ams->memmap[VIRT_HIGH_GIC_REDIST2].size);
-        }
-    } else {
-        /* 'cortex-a15-gic' means 'GIC v2' */
-        qemu_fdt_setprop_string(ams->fdt, nodename, "compatible",
-                                "arm,cortex-a15-gic");
-    }
-
-    qemu_fdt_setprop_cell(ams->fdt, nodename, "phandle", ams->gic_phandle);
-    g_free(nodename);
-}
-
 static void fdt_add_pmu_nodes(const VirtMachineState *vms)
 {
     CPUState *cpu;
@@ -681,7 +451,7 @@ static void create_gic(VirtMachineState *vms)
 
     init_gic_sysbus(ams);
     set_gic_virt_sysbus(vms);
-    fdt_add_gic_node(vms);
+    fdt_add_gic_node(ams);
     fdt_gic_set_virt_extension(vms);
 
     gic_set_msi_interrupt(vms);
@@ -1470,7 +1240,7 @@ static void machvirt_init(MachineState *machine)
         exit(1);
     }
 
-    create_fdt(vms);
+    create_fdt(ams);
 
     possible_cpus = mc->possible_cpu_arch_ids(machine);
     for (n = 0; n < possible_cpus->len; n++) {
@@ -1536,8 +1306,8 @@ static void machvirt_init(MachineState *machine)
         object_property_set_bool(cpuobj, true, "realized", &error_fatal);
         object_unref(cpuobj);
     }
-    fdt_add_timer_nodes(vms);
-    fdt_add_cpu_nodes(vms);
+    fdt_add_timer_nodes(ams);
+    fdt_add_cpu_nodes(ams);
 
    if (!kvm_enabled()) {
         ARMCPU *cpu = ARM_CPU(first_cpu);
diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h
index 8fec23985e..743a90ba36 100644
--- a/include/hw/arm/arm.h
+++ b/include/hw/arm/arm.h
@@ -111,6 +111,14 @@ typedef struct {
 #define ARM_MACHINE_CLASS(klass) \
     OBJECT_CLASS_CHECK(ArmMachineClass, klass, TYPE_ARM_MACHINE)
 
+void create_fdt(ArmMachineState *ams);
+
+void fdt_add_timer_nodes(const ArmMachineState *ams);
+
+void fdt_add_cpu_nodes(const ArmMachineState *ams);
+
+void fdt_add_gic_node(ArmMachineState *ams);
+
 void qdev_create_gic(ArmMachineState *ams);
 
 void init_gic_sysbus(ArmMachineState *ams);
-- 
2.18.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH RFC 14/16] hw/arm: move shared bootinfo member to ArmMachine
  2020-02-17  7:51 [PATCH RFC 00/16] Implement Microvm for aarch64 architecture Xu Yandong
                   ` (12 preceding siblings ...)
  2020-02-17  7:51 ` [PATCH RFC 13/16] hw/arm: move shared fdt " Xu Yandong
@ 2020-02-17  7:51 ` Xu Yandong
  2020-02-17  7:51 ` [PATCH RFC 15/16] hw/arm: move shared cpu related functions to arm.c and export them Xu Yandong
                   ` (3 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Xu Yandong @ 2020-02-17  7:51 UTC (permalink / raw)
  To: peter.maydell
  Cc: zhang.zhanghailiang, slp, Xu Yandong, qemu-devel, qemu-arm, wu.wubin

Move bootinfo member from VirtMachineState to ArmMachineState.

Signed-off-by: Xu Yandong <xuyandong2@huawei.com>
---
 hw/arm/arm.c          |  9 +++++++++
 hw/arm/virt.c         | 28 +++++++++-------------------
 include/hw/arm/arm.h  |  3 +++
 include/hw/arm/virt.h |  1 -
 4 files changed, 21 insertions(+), 20 deletions(-)

diff --git a/hw/arm/arm.c b/hw/arm/arm.c
index 4bffee0f37..7d880dd8e7 100644
--- a/hw/arm/arm.c
+++ b/hw/arm/arm.c
@@ -508,6 +508,15 @@ void create_virtio_devices(const ArmMachineState *ams)
     }
 }
 
+void *machvirt_dtb(const struct arm_boot_info *binfo, int *fdt_size)
+{
+    const ArmMachineState *board = container_of(binfo, ArmMachineState,
+                                                 bootinfo);
+
+    *fdt_size = board->fdt_size;
+    return board->fdt;
+}
+
 static char *virt_get_gic_version(Object *obj, Error **errp)
 {
     ArmMachineState *ams = ARM_MACHINE(obj);
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 11e753906b..2f498ea687 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -971,16 +971,6 @@ static void create_secure_ram(VirtMachineState *vms,
     g_free(nodename);
 }
 
-static void *machvirt_dtb(const struct arm_boot_info *binfo, int *fdt_size)
-{
-    const VirtMachineState *vms = container_of(binfo, VirtMachineState,
-                                                 bootinfo);
-
-    ArmMachineState *board = ARM_MACHINE(vms);
-    *fdt_size = board->fdt_size;
-    return board->fdt;
-}
-
 static void virt_build_smbios(VirtMachineState *vms)
 {
     MachineClass *mc = MACHINE_GET_CLASS(vms);
@@ -1016,7 +1006,7 @@ void virt_machine_done(Notifier *notifier, void *data)
     MachineState *ms = MACHINE(vms);
     ArmMachineState *ams = ARM_MACHINE(vms);
     ARMCPU *cpu = ARM_CPU(first_cpu);
-    struct arm_boot_info *info = &vms->bootinfo;
+    struct arm_boot_info *info = &ams->bootinfo;
     AddressSpace *as = arm_boot_address_space(cpu, info);
 
     /*
@@ -1373,14 +1363,14 @@ static void machvirt_init(MachineState *machine)
 
     create_platform_bus(vms);
 
-    vms->bootinfo.ram_size = machine->ram_size;
-    vms->bootinfo.nb_cpus = smp_cpus;
-    vms->bootinfo.board_id = -1;
-    vms->bootinfo.loader_start = ams->memmap[VIRT_MEM].base;
-    vms->bootinfo.get_dtb = machvirt_dtb;
-    vms->bootinfo.skip_dtb_autoload = true;
-    vms->bootinfo.firmware_loaded = firmware_loaded;
-    arm_load_kernel(ARM_CPU(first_cpu), machine, &vms->bootinfo);
+    ams->bootinfo.ram_size = machine->ram_size;
+    ams->bootinfo.nb_cpus = smp_cpus;
+    ams->bootinfo.board_id = -1;
+    ams->bootinfo.loader_start = ams->memmap[VIRT_MEM].base;
+    ams->bootinfo.get_dtb = machvirt_dtb;
+    ams->bootinfo.skip_dtb_autoload = true;
+    ams->bootinfo.firmware_loaded = firmware_loaded;
+    arm_load_kernel(ARM_CPU(first_cpu), machine, &ams->bootinfo);
 
     vms->machine_done.notify = virt_machine_done;
     qemu_add_machine_init_done_notifier(&vms->machine_done);
diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h
index 743a90ba36..372f4dea28 100644
--- a/include/hw/arm/arm.h
+++ b/include/hw/arm/arm.h
@@ -92,6 +92,7 @@ typedef struct {
 typedef struct {
     MachineState parent;
     int32_t gic_version;
+    struct arm_boot_info bootinfo;
     MemMapEntry *memmap;
     const int *irqmap;
     int smp_cpus;
@@ -130,6 +131,8 @@ void create_rtc(const ArmMachineState *ams);
 
 void create_virtio_devices(const ArmMachineState *ams);
 
+void *machvirt_dtb(const struct arm_boot_info *binfo, int *fdt_size);
+
 /* Return the number of used redistributor regions  */
 static inline int virt_gicv3_redist_region_count(ArmMachineState *ams)
 {
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index 086a27682f..8276e2c02c 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -68,7 +68,6 @@ typedef struct {
     bool its;
     bool virt;
     VirtIOMMUType iommu;
-    struct arm_boot_info bootinfo;
     uint32_t msi_phandle;
     uint32_t iommu_phandle;
     hwaddr highest_gpa;
-- 
2.18.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH RFC 15/16] hw/arm: move shared cpu related functions to arm.c and export them
  2020-02-17  7:51 [PATCH RFC 00/16] Implement Microvm for aarch64 architecture Xu Yandong
                   ` (13 preceding siblings ...)
  2020-02-17  7:51 ` [PATCH RFC 14/16] hw/arm: move shared bootinfo member to ArmMachine Xu Yandong
@ 2020-02-17  7:51 ` Xu Yandong
  2020-02-17  7:51 ` [PATCH RFC 16/16] hw/arm: Introduce the microvm machine type Xu Yandong
                   ` (2 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Xu Yandong @ 2020-02-17  7:51 UTC (permalink / raw)
  To: peter.maydell
  Cc: zhang.zhanghailiang, slp, Xu Yandong, qemu-devel, qemu-arm, wu.wubin

Move cpu related functions that will be shared between VIRT and
non-VIRT machine types to arm.c.

Signed-off-by: Xu Yandong <xuyandong2@huawei.com>
---
 hw/arm/arm.c          | 89 ++++++++++++++++++++++++++++++++++++++++++
 hw/arm/virt.c         | 91 +------------------------------------------
 include/hw/arm/arm.h  |  3 ++
 include/hw/arm/virt.h |  1 -
 4 files changed, 94 insertions(+), 90 deletions(-)

diff --git a/hw/arm/arm.c b/hw/arm/arm.c
index 7d880dd8e7..8bb5d92d2e 100644
--- a/hw/arm/arm.c
+++ b/hw/arm/arm.c
@@ -39,6 +39,28 @@
 #include "hw/intc/arm_gic.h"
 #include "kvm_arm.h"
 
+static const char *valid_cpus[] = {
+    ARM_CPU_TYPE_NAME("cortex-a7"),
+    ARM_CPU_TYPE_NAME("cortex-a15"),
+    ARM_CPU_TYPE_NAME("cortex-a53"),
+    ARM_CPU_TYPE_NAME("cortex-a57"),
+    ARM_CPU_TYPE_NAME("cortex-a72"),
+    ARM_CPU_TYPE_NAME("host"),
+    ARM_CPU_TYPE_NAME("max"),
+};
+
+bool cpu_type_valid(const char *cpu)
+{
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(valid_cpus); i++) {
+        if (strcmp(cpu, valid_cpus[i]) == 0) {
+            return true;
+        }
+    }
+    return false;
+}
+
 void create_fdt(ArmMachineState *ams)
 {
     MachineState *ms = MACHINE(ams);
@@ -543,6 +565,70 @@ static void virt_set_gic_version(Object *obj, const char *value, Error **errp)
     }
 }
 
+static uint64_t virt_cpu_mp_affinity(ArmMachineState *ams, int idx)
+{
+    uint8_t clustersz = ARM_DEFAULT_CPUS_PER_CLUSTER;
+    ArmMachineClass *amc = ARM_MACHINE_GET_CLASS(ams);
+
+    if (!amc->disallow_affinity_adjustment) {
+        /* Adjust MPIDR like 64-bit KVM hosts, which incorporate the
+         * GIC's target-list limitations. 32-bit KVM hosts currently
+         * always create clusters of 4 CPUs, but that is expected to
+         * change when they gain support for gicv3. When KVM is enabled
+         * it will override the changes we make here, therefore our
+         * purposes are to make TCG consistent (with 64-bit KVM hosts)
+         * and to improve SGI efficiency.
+         */
+        if (ams->gic_version == 3) {
+            clustersz = GICV3_TARGETLIST_BITS;
+        } else {
+            clustersz = GIC_TARGETLIST_BITS;
+        }
+    }
+    return arm_cpu_mp_affinity(idx, clustersz);
+}
+
+
+static CpuInstanceProperties
+virt_cpu_index_to_props(MachineState *ms, unsigned cpu_index)
+{
+    MachineClass *mc = MACHINE_GET_CLASS(ms);
+    const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms);
+
+    assert(cpu_index < possible_cpus->len);
+    return possible_cpus->cpus[cpu_index].props;
+}
+
+
+static int64_t virt_get_default_cpu_node_id(const MachineState *ms, int idx)
+{
+    return idx % ms->numa_state->num_nodes;
+}
+
+static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms)
+{
+    int n;
+    unsigned int max_cpus = ms->smp.max_cpus;
+    ArmMachineState *ams = ARM_MACHINE(ms);
+
+    if (ms->possible_cpus) {
+        assert(ms->possible_cpus->len == max_cpus);
+        return ms->possible_cpus;
+    }
+
+    ms->possible_cpus = g_malloc0(sizeof(CPUArchIdList) +
+                                  sizeof(CPUArchId) * max_cpus);
+    ms->possible_cpus->len = max_cpus;
+    for (n = 0; n < ms->possible_cpus->len; n++) {
+        ms->possible_cpus->cpus[n].type = ms->cpu_type;
+        ms->possible_cpus->cpus[n].arch_id =
+            virt_cpu_mp_affinity(ams, n);
+        ms->possible_cpus->cpus[n].props.has_thread_id = true;
+        ms->possible_cpus->cpus[n].props.thread_id = n;
+    }
+    return ms->possible_cpus;
+}
+
 static void arm_machine_class_init(ObjectClass *oc, void *data)
 {
     MachineClass *mc = MACHINE_CLASS(oc);
@@ -555,6 +641,9 @@ static void arm_machine_class_init(ObjectClass *oc, void *data)
     mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a15");
     mc->numa_mem_supported = true;
     mc->auto_enable_numa_with_memhp = true;
+    mc->cpu_index_to_instance_props = virt_cpu_index_to_props;
+    mc->get_default_cpu_node_id = virt_get_default_cpu_node_id;
+    mc->possible_cpu_arch_ids = virt_possible_cpu_arch_ids;
 }
 
 static void arm_instance_init(Object *obj)
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 2f498ea687..14d20d5c46 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -182,28 +182,6 @@ static const int a15irqmap[] = {
     [VIRT_PLATFORM_BUS] = 112, /* ...to 112 + PLATFORM_BUS_NUM_IRQS -1 */
 };
 
-static const char *valid_cpus[] = {
-    ARM_CPU_TYPE_NAME("cortex-a7"),
-    ARM_CPU_TYPE_NAME("cortex-a15"),
-    ARM_CPU_TYPE_NAME("cortex-a53"),
-    ARM_CPU_TYPE_NAME("cortex-a57"),
-    ARM_CPU_TYPE_NAME("cortex-a72"),
-    ARM_CPU_TYPE_NAME("host"),
-    ARM_CPU_TYPE_NAME("max"),
-};
-
-static bool cpu_type_valid(const char *cpu)
-{
-    int i;
-
-    for (i = 0; i < ARRAY_SIZE(valid_cpus); i++) {
-        if (strcmp(cpu, valid_cpus[i]) == 0) {
-            return true;
-        }
-    }
-    return false;
-}
-
 static void fdt_add_its_gic_node(VirtMachineState *vms)
 {
     char *nodename;
@@ -1030,30 +1008,6 @@ void virt_machine_done(Notifier *notifier, void *data)
     virt_build_smbios(vms);
 }
 
-static uint64_t virt_cpu_mp_affinity(VirtMachineState *vms, int idx)
-{
-    uint8_t clustersz = ARM_DEFAULT_CPUS_PER_CLUSTER;
-    ArmMachineState *ams = ARM_MACHINE(vms);
-    VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
-
-    if (!vmc->disallow_affinity_adjustment) {
-        /* Adjust MPIDR like 64-bit KVM hosts, which incorporate the
-         * GIC's target-list limitations. 32-bit KVM hosts currently
-         * always create clusters of 4 CPUs, but that is expected to
-         * change when they gain support for gicv3. When KVM is enabled
-         * it will override the changes we make here, therefore our
-         * purposes are to make TCG consistent (with 64-bit KVM hosts)
-         * and to improve SGI efficiency.
-         */
-        if (ams->gic_version == 3) {
-            clustersz = GICV3_TARGETLIST_BITS;
-        } else {
-            clustersz = GIC_TARGETLIST_BITS;
-        }
-    }
-    return arm_cpu_mp_affinity(idx, clustersz);
-}
-
 static void virt_set_memmap(VirtMachineState *vms)
 {
     MachineState *ms = MACHINE(vms);
@@ -1460,45 +1414,6 @@ static void virt_set_iommu(Object *obj, const char *value, Error **errp)
     }
 }
 
-static CpuInstanceProperties
-virt_cpu_index_to_props(MachineState *ms, unsigned cpu_index)
-{
-    MachineClass *mc = MACHINE_GET_CLASS(ms);
-    const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms);
-
-    assert(cpu_index < possible_cpus->len);
-    return possible_cpus->cpus[cpu_index].props;
-}
-
-static int64_t virt_get_default_cpu_node_id(const MachineState *ms, int idx)
-{
-    return idx % ms->numa_state->num_nodes;
-}
-
-static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms)
-{
-    int n;
-    unsigned int max_cpus = ms->smp.max_cpus;
-    VirtMachineState *vms = VIRT_MACHINE(ms);
-
-    if (ms->possible_cpus) {
-        assert(ms->possible_cpus->len == max_cpus);
-        return ms->possible_cpus;
-    }
-
-    ms->possible_cpus = g_malloc0(sizeof(CPUArchIdList) +
-                                  sizeof(CPUArchId) * max_cpus);
-    ms->possible_cpus->len = max_cpus;
-    for (n = 0; n < ms->possible_cpus->len; n++) {
-        ms->possible_cpus->cpus[n].type = ms->cpu_type;
-        ms->possible_cpus->cpus[n].arch_id =
-            virt_cpu_mp_affinity(vms, n);
-        ms->possible_cpus->cpus[n].props.has_thread_id = true;
-        ms->possible_cpus->cpus[n].props.thread_id = n;
-    }
-    return ms->possible_cpus;
-}
-
 static void virt_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
                                  Error **errp)
 {
@@ -1624,9 +1539,6 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
     machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_AMD_XGBE);
     machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
     machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_PLATFORM);
-    mc->possible_cpu_arch_ids = virt_possible_cpu_arch_ids;
-    mc->cpu_index_to_instance_props = virt_cpu_index_to_props;
-    mc->get_default_cpu_node_id = virt_get_default_cpu_node_id;
     mc->kvm_type = virt_kvm_type;
     assert(!mc->get_hotplug_handler);
     mc->get_hotplug_handler = virt_machine_get_hotplug_handler;
@@ -1833,10 +1745,11 @@ DEFINE_VIRT_MACHINE(2, 7)
 static void virt_machine_2_6_options(MachineClass *mc)
 {
     VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
+    ArmMachineClass *amc = ARM_MACHINE_CLASS(OBJECT_CLASS(mc));
 
     virt_machine_2_7_options(mc);
     compat_props_add(mc->compat_props, hw_compat_2_6, hw_compat_2_6_len);
-    vmc->disallow_affinity_adjustment = true;
+    amc->disallow_affinity_adjustment = true;
     /* Disable PMU for 2.6 as PMU support was first introduced in 2.7 */
     vmc->no_pmu = true;
 }
diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h
index 372f4dea28..37a419b784 100644
--- a/include/hw/arm/arm.h
+++ b/include/hw/arm/arm.h
@@ -86,6 +86,7 @@ typedef struct MemMapEntry {
 
 typedef struct {
     MachineClass parent;
+    bool disallow_affinity_adjustment;
     bool claim_edge_triggered_timers;
 } ArmMachineClass;
 
@@ -112,6 +113,8 @@ typedef struct {
 #define ARM_MACHINE_CLASS(klass) \
     OBJECT_CLASS_CHECK(ArmMachineClass, klass, TYPE_ARM_MACHINE)
 
+bool cpu_type_valid(const char *cpu);
+
 void create_fdt(ArmMachineState *ams);
 
 void fdt_add_timer_nodes(const ArmMachineState *ams);
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index 8276e2c02c..aa66cd78d5 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -47,7 +47,6 @@ typedef enum VirtIOMMUType {
 
 typedef struct {
     ArmMachineClass parent;
-    bool disallow_affinity_adjustment;
     bool no_its;
     bool no_pmu;
     bool smbios_old_sys_ver;
-- 
2.18.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH RFC 16/16] hw/arm: Introduce the microvm machine type
  2020-02-17  7:51 [PATCH RFC 00/16] Implement Microvm for aarch64 architecture Xu Yandong
                   ` (14 preceding siblings ...)
  2020-02-17  7:51 ` [PATCH RFC 15/16] hw/arm: move shared cpu related functions to arm.c and export them Xu Yandong
@ 2020-02-17  7:51 ` Xu Yandong
  2020-02-17  8:19 ` [PATCH RFC 00/16] Implement Microvm for aarch64 architecture no-reply
  2020-02-17  9:56 ` Peter Maydell
  17 siblings, 0 replies; 19+ messages in thread
From: Xu Yandong @ 2020-02-17  7:51 UTC (permalink / raw)
  To: peter.maydell
  Cc: zhang.zhanghailiang, slp, Xu Yandong, qemu-devel, qemu-arm, wu.wubin

It's a minimalist machine type without PCI nor ACPI support, designed
for short-lived guests. microvm also establishes a baseline for
benchmarking and optimizing both QEMU and guest operating systems,
since it is optimized for both boot time and footprint.

Signed-off-by: Xu Yandong <xuyandong2@huawei.com>
---
 default-configs/aarch64-softmmu.mak |   2 +
 hw/arm/Kconfig                      |   7 +
 hw/arm/Makefile.objs                |   1 +
 hw/arm/arm.c                        |   8 +
 hw/arm/microvm.c                    | 303 ++++++++++++++++++++++++++++
 hw/arm/virt.c                       |  17 +-
 include/hw/arm/arm.h                |   2 +
 include/hw/arm/microvm.h            |  40 ++++
 include/hw/arm/virt.h               |   1 -
 9 files changed, 372 insertions(+), 9 deletions(-)
 create mode 100644 hw/arm/microvm.c
 create mode 100644 include/hw/arm/microvm.h

diff --git a/default-configs/aarch64-softmmu.mak b/default-configs/aarch64-softmmu.mak
index 958b1e08e4..e9e994801c 100644
--- a/default-configs/aarch64-softmmu.mak
+++ b/default-configs/aarch64-softmmu.mak
@@ -6,3 +6,5 @@ include arm-softmmu.mak
 CONFIG_XLNX_ZYNQMP_ARM=y
 CONFIG_XLNX_VERSAL=y
 CONFIG_SBSA_REF=y
+
+CONFIG_ARM_MICROVM=y
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 3d86691ae0..153ffbabac 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -25,6 +25,13 @@ config ARM_VIRT
     select ACPI_MEMORY_HOTPLUG
     select ACPI_HW_REDUCED
 
+config ARM_MICROVM
+    bool
+    select A15MPCORE
+    select PL011 # UART
+    select PL031 # RTC
+    select VIRTIO_MMIO
+
 config CHEETAH
     bool
     select OMAP
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 51fcee2ac8..2a2f643774 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -1,6 +1,7 @@
 obj-y += boot.o
 obj-$(CONFIG_PLATFORM_BUS) += sysbus-fdt.o
 obj-$(CONFIG_ARM_VIRT) += arm.o virt.o
+obj-$(CONFIG_ARM_MICROVM) += arm.o microvm.o
 obj-$(CONFIG_ACPI) += virt-acpi-build.o
 obj-$(CONFIG_DIGIC) += digic_boards.o
 obj-$(CONFIG_EXYNOS4) += exynos4_boards.o
diff --git a/hw/arm/arm.c b/hw/arm/arm.c
index 8bb5d92d2e..0c5bf1a2f8 100644
--- a/hw/arm/arm.c
+++ b/hw/arm/arm.c
@@ -306,6 +306,14 @@ void qdev_create_gic(ArmMachineState *ams)
      */
     qdev_prop_set_uint32(ams->gic, "num-irq", NUM_IRQS + 32);
 
+    if (!kvm_irqchip_in_kernel()) {
+        qdev_prop_set_bit(ams->gic, "has-security-extensions", false);
+        if (type != 3) {
+            qdev_prop_set_bit(ams->gic, "has-virtualization-extensions",
+                              false);
+        }
+    }
+
     if (type == 3) {
         uint32_t redist0_capacity =
                     ams->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
diff --git a/hw/arm/microvm.c b/hw/arm/microvm.c
new file mode 100644
index 0000000000..04f98d63cb
--- /dev/null
+++ b/hw/arm/microvm.c
@@ -0,0 +1,303 @@
+/*
+ * ARM mach-virt emulation
+ *
+ * Copyright (c) 2013 Linaro Limited
+ * Copyright (c) 2020 Huawei.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/units.h"
+#include "qapi/error.h"
+#include "hw/arm/arm.h"
+#include "hw/arm/microvm.h"
+#include "sysemu/device_tree.h"
+#include "sysemu/numa.h"
+#include "sysemu/sysemu.h"
+#include "hw/loader.h"
+#include "hw/qdev-properties.h"
+#include "hw/arm/fdt.h"
+#include "kvm_arm.h"
+
+/* Number of external interrupt lines to configure the GIC with */
+#define NUM_IRQS 256
+
+#define PLATFORM_BUS_NUM_IRQS 64
+
+/* Legacy RAM limit in GB (< version 4.0) */
+#define LEGACY_RAMLIMIT_GB 255
+#define LEGACY_RAMLIMIT_BYTES (LEGACY_RAMLIMIT_GB * GiB)
+
+/* Addresses and sizes of our components.
+ * 0..128MB is space for a flash device so we can run bootrom code such as UEFI.
+ * 128MB..256MB is used for miscellaneous device I/O.
+ * 256MB..1GB is reserved for possible future PCI support (ie where the
+ * PCI memory window will go if we add a PCI host controller).
+ * 1GB and up is RAM (which may happily spill over into the
+ * high memory region beyond 4GB).
+ * This represents a compromise between how much RAM can be given to
+ * a 32 bit VM and leaving space for expansion and in particular for PCI.
+ * Note that devices should generally be placed at multiples of 0x10000,
+ * to accommodate guests using 64K pages.
+ */
+static MemMapEntry base_memmap[] = {
+    /* Space up to 0x8000000 is reserved for a boot ROM */
+    [VIRT_CPUPERIPHS] =         { 0x08000000, 0x00020000 },
+    /* GIC distributor and CPU interfaces sit inside the CPU peripheral space */
+    [VIRT_GIC_DIST] =           { 0x08000000, 0x00010000 },
+    [VIRT_GIC_CPU] =            { 0x08010000, 0x00010000 },
+    /* This redistributor space allows up to 2*64kB*123 CPUs */
+    [VIRT_GIC_REDIST] =         { 0x080A0000, 0x00F60000 },
+    [VIRT_UART] =               { 0x09000000, 0x00001000 },
+    [VIRT_RTC] =                { 0x09010000, 0x00001000 },
+    [VIRT_MMIO] =               { 0x0a000000, 0x00000200 },
+    /* Actual RAM size depends on initial RAM and device memory settings */
+    [VIRT_MEM] =                { 0x40000000, LEGACY_RAMLIMIT_BYTES },
+    /* Additional 64 MB redist region (can contain up to 512 redistributors) */
+    [VIRT_HIGH_GIC_REDIST2] =   { 0x4000000000ULL, 0x4000000 },
+};
+
+static const int a15irqmap[] = {
+    [VIRT_UART] = 1,
+    [VIRT_RTC] = 2,
+    [VIRT_MMIO] = 16, /* ...to 16 + NUM_VIRTIO_TRANSPORTS - 1 */
+};
+
+static void fdt_gic_intc_node(MicrovmMachineState *mms)
+{
+    char *nodename;
+    ArmMachineState *ams = ARM_MACHINE(mms);
+
+    if (ams->gic_version == 3) {
+        return;
+    }
+
+    nodename = g_strdup_printf("/intc@%" PRIx64,
+                               ams->memmap[VIRT_GIC_DIST].base);
+
+    qemu_fdt_setprop_sized_cells(ams->fdt, nodename, "reg",
+            2, ams->memmap[VIRT_GIC_DIST].base,
+            2, ams->memmap[VIRT_GIC_DIST].size,
+            2, ams->memmap[VIRT_GIC_CPU].base,
+            2, ams->memmap[VIRT_GIC_CPU].size);
+
+    g_free(nodename);
+}
+
+
+static void create_gic(MicrovmMachineState *mms)
+{
+    ArmMachineState *ams = ARM_MACHINE(mms);
+
+    qdev_create_gic(ams);
+    qdev_init_nofail(ams->gic);
+
+    init_gic_sysbus(ams);
+    fdt_add_gic_node(ams);
+    fdt_gic_intc_node(mms);
+}
+
+static
+void microvm_machine_done(Notifier *notifier, void *data)
+{
+    ArmMachineState *ams = container_of(notifier, ArmMachineState,
+                                         machine_done);
+    MachineState *ms = MACHINE(ams);
+    ARMCPU *cpu = ARM_CPU(first_cpu);
+    struct arm_boot_info *info = &ams->bootinfo;
+    AddressSpace *as = arm_boot_address_space(cpu, info);
+
+    if (arm_load_dtb(info->dtb_start, info, info->dtb_limit, as, ms) < 0) {
+        exit(1);
+    }
+}
+
+static void microvm_init(MachineState *machine)
+{
+    ArmMachineState *ams = ARM_MACHINE(machine);
+    MicrovmMachineState *mms = MICROVM_MACHINE(machine);
+    MachineClass *mc = MACHINE_GET_CLASS(machine);
+    const CPUArchIdList *possible_cpus;
+    MemoryRegion *sysmem = get_system_memory();
+    int n, arm_max_cpus;
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    bool aarch64 = true;
+    unsigned int smp_cpus = machine->smp.cpus;
+    unsigned int max_cpus = machine->smp.max_cpus;
+
+    /* microvm, only support KVM */
+    if (!kvm_enabled()) {
+        error_report("microvm requires KVM");
+        exit(1);
+    }
+
+    /* We can probe only here because during property set
+     * KVM is not available yet
+     */
+    if (ams->gic_version <= 0) {
+        ams->gic_version = kvm_arm_vgic_probe();
+        if (!ams->gic_version) {
+            error_report(
+                "Unable to determine GIC version supported by host");
+            exit(1);
+        }
+    }
+
+    if (!cpu_type_valid(machine->cpu_type)) {
+        error_report("mach-virt: CPU type %s not supported", machine->cpu_type);
+        exit(1);
+    }
+
+    ams->psci_conduit = QEMU_PSCI_CONDUIT_HVC;
+
+    /* The maximum number of CPUs depends on the GIC version, or on how
+     * many redistributors we can fit into the memory map.
+     */
+    if (ams->gic_version == 3) {
+        arm_max_cpus =
+            ams->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
+        arm_max_cpus +=
+            ams->memmap[VIRT_HIGH_GIC_REDIST2].size / GICV3_REDIST_SIZE;
+    } else {
+        arm_max_cpus = GIC_NCPU;
+    }
+
+    if (max_cpus > arm_max_cpus) {
+        error_report("Number of SMP CPUs requested (%d) exceeds max CPUs "
+                     "supported by machine 'mach-microvm' (%d)",
+                     max_cpus, arm_max_cpus);
+        exit(1);
+    }
+
+    ams->smp_cpus = smp_cpus;
+
+    create_fdt(ams);
+
+    possible_cpus = mc->possible_cpu_arch_ids(machine);
+    for (n = 0; n < possible_cpus->len; n++) {
+        Object *cpuobj;
+        CPUState *cs;
+
+        if (n >= smp_cpus) {
+            break;
+        }
+
+        cpuobj = object_new(possible_cpus->cpus[n].type);
+        object_property_set_int(cpuobj, possible_cpus->cpus[n].arch_id,
+                                "mp-affinity", NULL);
+
+        cs = CPU(cpuobj);
+        cs->cpu_index = n;
+
+        numa_cpu_pre_plug(&possible_cpus->cpus[cs->cpu_index], DEVICE(cpuobj),
+                          &error_fatal);
+
+        aarch64 &= object_property_get_bool(cpuobj, "aarch64", NULL);
+
+        object_property_set_int(cpuobj, ams->psci_conduit,
+                                    "psci-conduit", NULL);
+
+         /* Secondary CPUs start in PSCI powered-down state */
+        if (n > 0) {
+            object_property_set_bool(cpuobj, true,
+                                     "start-powered-off", NULL);
+        }
+
+        if (object_property_find(cpuobj, "pmu", NULL)) {
+            object_property_set_bool(cpuobj, false, "pmu", NULL);
+        }
+
+        if (object_property_find(cpuobj, "reset-cbar", NULL)) {
+            object_property_set_int(cpuobj, ams->memmap[VIRT_CPUPERIPHS].base,
+                                    "reset-cbar", &error_abort);
+        }
+
+        object_property_set_link(cpuobj, OBJECT(sysmem), "memory",
+                                 &error_abort);
+
+        object_property_set_bool(cpuobj, true, "realized", &error_fatal);
+        object_unref(cpuobj);
+    }
+    fdt_add_timer_nodes(ams);
+    fdt_add_cpu_nodes(ams);
+
+    memory_region_allocate_system_memory(ram, NULL, "mach-virt.ram",
+                                         machine->ram_size);
+    memory_region_add_subregion(sysmem, ams->memmap[VIRT_MEM].base, ram);
+
+    create_gic(mms);
+
+    create_uart(ams, VIRT_UART, sysmem, serial_hd(0));
+    create_rtc(ams);
+
+    /* Create mmio transports, so the user can create virtio backends
+     * (which will be automatically plugged in to the transports). If
+     * no backend is created the transport will just sit harmlessly idle.
+     */
+    create_virtio_devices(ams);
+
+    ams->bootinfo.ram_size = machine->ram_size;
+    ams->bootinfo.nb_cpus = smp_cpus;
+    ams->bootinfo.board_id = -1;
+    ams->bootinfo.loader_start = ams->memmap[VIRT_MEM].base;
+    ams->bootinfo.get_dtb = machvirt_dtb;
+    ams->bootinfo.skip_dtb_autoload = true;
+    ams->bootinfo.firmware_loaded = false;
+    arm_load_kernel(ARM_CPU(first_cpu), machine, &ams->bootinfo);
+
+    ams->machine_done.notify = microvm_machine_done;
+    qemu_add_machine_init_done_notifier(&ams->machine_done);
+}
+
+static void microvm_class_init(ObjectClass *oc, void *data)
+{
+    MachineClass *mc = MACHINE_CLASS(oc);
+
+    mc->desc = "QEMU ARM MicroVM Virtual Machine";
+    mc->init = microvm_init;
+    /* 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 = 512;
+    mc->default_cpu_type = ARM_CPU_TYPE_NAME("host");
+    mc->default_machine_opts = "accel=kvm";
+}
+
+static void microvm_instance_init(Object *obj)
+{
+    ArmMachineState *ams = ARM_MACHINE(obj);
+
+    ams->memmap = base_memmap;
+    ams->irqmap = a15irqmap;
+}
+
+static const TypeInfo microvm_machine_info = {
+    .name          = TYPE_MICROVM_MACHINE,
+    .parent        = TYPE_ARM_MACHINE,
+    .instance_size = sizeof(MicrovmMachineState),
+    .instance_init = microvm_instance_init,
+    .class_size    = sizeof(MicrovmMachineClass),
+    .class_init    = microvm_class_init,
+    .interfaces = (InterfaceInfo[]) {
+         { }
+    },
+};
+
+static void microvm_machine_init(void)
+{
+    type_register_static(&microvm_machine_info);
+}
+
+type_init(microvm_machine_init);
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 14d20d5c46..c4ffeff4aa 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -979,10 +979,10 @@ static void virt_build_smbios(VirtMachineState *vms)
 static
 void virt_machine_done(Notifier *notifier, void *data)
 {
-    VirtMachineState *vms = container_of(notifier, VirtMachineState,
+    ArmMachineState *ams = container_of(notifier, ArmMachineState,
                                          machine_done);
-    MachineState *ms = MACHINE(vms);
-    ArmMachineState *ams = ARM_MACHINE(vms);
+    MachineState *ms = MACHINE(ams);
+    VirtMachineState *vms = VIRT_MACHINE(ams);
     ARMCPU *cpu = ARM_CPU(first_cpu);
     struct arm_boot_info *info = &ams->bootinfo;
     AddressSpace *as = arm_boot_address_space(cpu, info);
@@ -1056,7 +1056,7 @@ static void virt_set_memmap(VirtMachineState *vms)
         ams->memmap[i].size = size;
         base += size;
     }
-    vms->highest_gpa = base - 1;
+    ams->highest_gpa = base - 1;
     if (device_memory_size > 0) {
         ms->device_memory = g_malloc0(sizeof(*ms->device_memory));
         ms->device_memory->base = device_memory_base;
@@ -1260,7 +1260,7 @@ static void machvirt_init(MachineState *machine)
         if (aarch64 && vms->highmem) {
             int requested_pa_size, pamax = arm_pamax(cpu);
 
-            requested_pa_size = 64 - clz64(vms->highest_gpa);
+            requested_pa_size = 64 - clz64(ams->highest_gpa);
             if (pamax < requested_pa_size) {
                 error_report("VCPU supports less PA bits (%d) than requested "
                             "by the memory map (%d)", pamax, requested_pa_size);
@@ -1326,8 +1326,8 @@ static void machvirt_init(MachineState *machine)
     ams->bootinfo.firmware_loaded = firmware_loaded;
     arm_load_kernel(ARM_CPU(first_cpu), machine, &ams->bootinfo);
 
-    vms->machine_done.notify = virt_machine_done;
-    qemu_add_machine_init_done_notifier(&vms->machine_done);
+    ams->machine_done.notify = virt_machine_done;
+    qemu_add_machine_init_done_notifier(&ams->machine_done);
 }
 
 static bool virt_get_secure(Object *obj, Error **errp)
@@ -1501,13 +1501,14 @@ static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine,
 static int virt_kvm_type(MachineState *ms, const char *type_str)
 {
     VirtMachineState *vms = VIRT_MACHINE(ms);
+    ArmMachineState *ams = ARM_MACHINE(ms);
     int max_vm_pa_size = kvm_arm_get_max_vm_ipa_size(ms);
     int requested_pa_size;
 
     /* we freeze the memory map to compute the highest gpa */
     virt_set_memmap(vms);
 
-    requested_pa_size = 64 - clz64(vms->highest_gpa);
+    requested_pa_size = 64 - clz64(ams->highest_gpa);
 
     if (requested_pa_size > max_vm_pa_size) {
         error_report("-m and ,maxmem option values "
diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h
index 37a419b784..f9ec676579 100644
--- a/include/hw/arm/arm.h
+++ b/include/hw/arm/arm.h
@@ -92,6 +92,7 @@ typedef struct {
 
 typedef struct {
     MachineState parent;
+    Notifier machine_done;
     int32_t gic_version;
     struct arm_boot_info bootinfo;
     MemMapEntry *memmap;
@@ -102,6 +103,7 @@ typedef struct {
     uint32_t clock_phandle;
     uint32_t gic_phandle;
     int psci_conduit;
+    hwaddr highest_gpa;
     DeviceState *gic;
 } ArmMachineState;
 
diff --git a/include/hw/arm/microvm.h b/include/hw/arm/microvm.h
new file mode 100644
index 0000000000..be8e771b07
--- /dev/null
+++ b/include/hw/arm/microvm.h
@@ -0,0 +1,40 @@
+/*
+ *
+ * Copyright (c) 2015 Linaro Limited
+ * Copyright (c) 2020 Huawei.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef QEMU_ARM_MICROVM_H
+#define QEMU_ARM_MICROVM_H
+
+#include "hw/arm/arm.h"
+
+typedef struct {
+    ArmMachineClass parent;
+} MicrovmMachineClass;
+
+typedef struct {
+    ArmMachineState parent;
+} MicrovmMachineState;
+
+#define TYPE_MICROVM_MACHINE   MACHINE_TYPE_NAME("microvm")
+#define MICROVM_MACHINE(obj) \
+    OBJECT_CHECK(MicrovmMachineState, (obj), TYPE_MICROVM_MACHINE)
+#define MICROVM_MACHINE_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(MicrovmMachineClass, obj, TYPE_MICROVM_MACHINE)
+#define MICROVM_MACHINE_CLASS(klass) \
+    OBJECT_CLASS_CHECK(MicrovmMachineClass, klass, TYPE_MICROVM_MACHINE)
+
+#endif /* QEMU_ARM_MICROVM_H */
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index aa66cd78d5..4e32c650b4 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -69,7 +69,6 @@ typedef struct {
     VirtIOMMUType iommu;
     uint32_t msi_phandle;
     uint32_t iommu_phandle;
-    hwaddr highest_gpa;
     DeviceState *acpi_dev;
     Notifier powerdown_notifier;
 } VirtMachineState;
-- 
2.18.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH RFC 00/16] Implement Microvm for aarch64 architecture
  2020-02-17  7:51 [PATCH RFC 00/16] Implement Microvm for aarch64 architecture Xu Yandong
                   ` (15 preceding siblings ...)
  2020-02-17  7:51 ` [PATCH RFC 16/16] hw/arm: Introduce the microvm machine type Xu Yandong
@ 2020-02-17  8:19 ` no-reply
  2020-02-17  9:56 ` Peter Maydell
  17 siblings, 0 replies; 19+ messages in thread
From: no-reply @ 2020-02-17  8:19 UTC (permalink / raw)
  To: xuyandong2
  Cc: peter.maydell, zhang.zhanghailiang, slp, xuyandong2, qemu-devel,
	qemu-arm, wu.wubin

Patchew URL: https://patchew.org/QEMU/1581925888-103620-1-git-send-email-xuyandong2@huawei.com/



Hi,

This series failed the docker-quick@centos7 build test. Please find the testing commands and
their output below. If you have Docker installed, you can probably reproduce it
locally.

=== TEST SCRIPT BEGIN ===
#!/bin/bash
make docker-image-centos7 V=1 NETWORK=1
time make docker-test-quick@centos7 SHOW_ENV=1 J=14 NETWORK=1
=== TEST SCRIPT END ===

  TEST    iotest-qcow2: 190
socket_accept failed: Resource temporarily unavailable
**
ERROR:/tmp/qemu-test/src/tests/qtest/libqtest.c:272:qtest_init_without_qmp_handshake: assertion failed: (s->fd >= 0 && s->qmp_fd >= 0)
/tmp/qemu-test/src/tests/qtest/libqtest.c:140: kill_qemu() tried to terminate QEMU process but encountered exit status 1 (expected 0)
ERROR - Bail out! ERROR:/tmp/qemu-test/src/tests/qtest/libqtest.c:272:qtest_init_without_qmp_handshake: assertion failed: (s->fd >= 0 && s->qmp_fd >= 0)
make: *** [check-qtest-aarch64] Error 1
make: *** Waiting for unfinished jobs....
  TEST    iotest-qcow2: 191
  TEST    iotest-qcow2: 192
---
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['sudo', '-n', 'docker', 'run', '--label', 'com.qemu.instance.uuid=caf02b6d3be34c0c9411c2cbdb28758d', '-u', '1001', '--security-opt', 'seccomp=unconfined', '--rm', '-e', 'TARGET_LIST=', '-e', 'EXTRA_CONFIGURE_OPTS=', '-e', 'V=', '-e', 'J=14', '-e', 'DEBUG=', '-e', 'SHOW_ENV=1', '-e', 'CCACHE_DIR=/var/tmp/ccache', '-v', '/home/patchew/.cache/qemu-docker-ccache:/var/tmp/ccache:z', '-v', '/var/tmp/patchew-tester-tmp-2flvq84m/src/docker-src.2020-02-17-03.06.35.9047:/var/tmp/qemu:z,ro', 'qemu:centos7', '/var/tmp/qemu/run', 'test-quick']' returned non-zero exit status 2.
filter=--filter=label=com.qemu.instance.uuid=caf02b6d3be34c0c9411c2cbdb28758d
make[1]: *** [docker-run] Error 1
make[1]: Leaving directory `/var/tmp/patchew-tester-tmp-2flvq84m/src'
make: *** [docker-run-test-quick@centos7] Error 2

real    13m21.007s
user    0m8.792s


The full log is available at
http://patchew.org/logs/1581925888-103620-1-git-send-email-xuyandong2@huawei.com/testing.docker-quick@centos7/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-devel@redhat.com

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH RFC 00/16] Implement Microvm for aarch64 architecture
  2020-02-17  7:51 [PATCH RFC 00/16] Implement Microvm for aarch64 architecture Xu Yandong
                   ` (16 preceding siblings ...)
  2020-02-17  8:19 ` [PATCH RFC 00/16] Implement Microvm for aarch64 architecture no-reply
@ 2020-02-17  9:56 ` Peter Maydell
  17 siblings, 0 replies; 19+ messages in thread
From: Peter Maydell @ 2020-02-17  9:56 UTC (permalink / raw)
  To: Xu Yandong
  Cc: wu.wubin, qemu-arm, QEMU Developers, Sergio Lopez, zhanghailiang

On Mon, 17 Feb 2020 at 07:42, Xu Yandong <xuyandong2@huawei.com> wrote:
>
> Implement Microvm for aarch64 architecture
>
> This series attempts to implement microvm for aarch64
> architecture.
>
> Just like how Sergio Lopez does for implementing microvm
> for x86 architecture. We remove parts of emulate devices which
> are not needed in microvm, compared with normal VM,
> We only keep PL011 (UART), PL031 (RTC) and virtio-mmio
> devices for microvm of aarch64.

For x86, 'microvm' makes sense, because the standard
PC models are models of real hardware with a lot of
legacy baggage. The situation is different for aarch64.
The 'virt' board is already intended as a "minimal
machine for booting a VM that knows it's a VM".
Why do we need another model that's intended for the
same purpose?

It would be more interesting to look at whether there
are reasonable places where we could allow command
line options to have the 'virt' board not provide
some devices where that makes a significant speed
improvement. Analysis of where the extra time is
actually going would also be helpful.

NB: I'm pretty firmly against dropping PCI. This is
a pluggable discoverable bus, and it's a much better
way to provide virtio than virtio-mmio.

thanks
-- PMM


^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2020-02-17  9:57 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-17  7:51 [PATCH RFC 00/16] Implement Microvm for aarch64 architecture Xu Yandong
2020-02-17  7:51 ` [PATCH RFC 01/16] hw/arm/arm: Introduce ArmMachineState and ArmMachineClass Xu Yandong
2020-02-17  7:51 ` [PATCH RFC 02/16] hw/arm: move shared fdt member to ArmMachine Xu Yandong
2020-02-17  7:51 ` [PATCH RFC 03/16] hw/arm: move shared memmap " Xu Yandong
2020-02-17  7:51 ` [PATCH RFC 04/16] hw/arm: move shared irqmap " Xu Yandong
2020-02-17  7:51 ` [PATCH RFC 05/16] hw/arm: move shared smp_cpus " Xu Yandong
2020-02-17  7:51 ` [PATCH RFC 06/16] hw/arm/virt: split MSI related codes from create_gic Xu Yandong
2020-02-17  7:51 ` [PATCH RFC 07/16] hw/arm/virt: split virt extension " Xu Yandong
2020-02-17  7:51 ` [PATCH RFC 08/16] hw/arm/virt: split secure " Xu Yandong
2020-02-17  7:51 ` [PATCH RFC 09/16] hw/arm: move shared gic member to ArmMachine Xu Yandong
2020-02-17  7:51 ` [PATCH RFC 10/16] hw/arm: split create_gic function Xu Yandong
2020-02-17  7:51 ` [PATCH RFC 11/16] hw/arm: move shared psci_enable and claim_edge_triggered_timers member to ArmMachine Xu Yandong
2020-02-17  7:51 ` [PATCH RFC 12/16] hw/arm: move shared devices related functions to arm.c and export them Xu Yandong
2020-02-17  7:51 ` [PATCH RFC 13/16] hw/arm: move shared fdt " Xu Yandong
2020-02-17  7:51 ` [PATCH RFC 14/16] hw/arm: move shared bootinfo member to ArmMachine Xu Yandong
2020-02-17  7:51 ` [PATCH RFC 15/16] hw/arm: move shared cpu related functions to arm.c and export them Xu Yandong
2020-02-17  7:51 ` [PATCH RFC 16/16] hw/arm: Introduce the microvm machine type Xu Yandong
2020-02-17  8:19 ` [PATCH RFC 00/16] Implement Microvm for aarch64 architecture no-reply
2020-02-17  9:56 ` Peter Maydell

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.