[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH RFC 12/16] hw/arm: move shared devices related functions to arm.c
From: |
Xu Yandong |
Subject: |
[PATCH RFC 12/16] hw/arm: move shared devices related functions to arm.c and export them |
Date: |
Mon, 17 Feb 2020 02:51:24 -0500 |
Move device related functions to arm.c, include RTC(pl031), UART(pl011),
virtio devices.
Signed-off-by: Xu Yandong <address@hidden>
---
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
- [PATCH RFC 15/16] hw/arm: move shared cpu related functions to arm.c and export them, (continued)
- [PATCH RFC 15/16] hw/arm: move shared cpu related functions to arm.c and export them, Xu Yandong, 2020/02/17
- [PATCH RFC 10/16] hw/arm: split create_gic function, Xu Yandong, 2020/02/17
- [PATCH RFC 04/16] hw/arm: move shared irqmap member to ArmMachine, Xu Yandong, 2020/02/17
- [PATCH RFC 01/16] hw/arm/arm: Introduce ArmMachineState and ArmMachineClass, Xu Yandong, 2020/02/17
- [PATCH RFC 07/16] hw/arm/virt: split virt extension related codes from create_gic, Xu Yandong, 2020/02/17
- [PATCH RFC 11/16] hw/arm: move shared psci_enable and claim_edge_triggered_timers member to ArmMachine, Xu Yandong, 2020/02/17
- [PATCH RFC 03/16] hw/arm: move shared memmap member to ArmMachine, Xu Yandong, 2020/02/17
- [PATCH RFC 06/16] hw/arm/virt: split MSI related codes from create_gic, Xu Yandong, 2020/02/17
- [PATCH RFC 08/16] hw/arm/virt: split secure extension related codes from create_gic, Xu Yandong, 2020/02/17
- [PATCH RFC 02/16] hw/arm: move shared fdt member to ArmMachine, Xu Yandong, 2020/02/17
- [PATCH RFC 12/16] hw/arm: move shared devices related functions to arm.c and export them,
Xu Yandong <=
- [PATCH RFC 13/16] hw/arm: move shared fdt related functions to arm.c and export them, Xu Yandong, 2020/02/17
- [PATCH RFC 16/16] hw/arm: Introduce the microvm machine type, Xu Yandong, 2020/02/17