qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [RFC PATCH 7/7] hw/arm/virt: Enable dynamic generation of A


From: Alexander Spyridakis
Subject: [Qemu-devel] [RFC PATCH 7/7] hw/arm/virt: Enable dynamic generation of ACPI v5.1 tables
Date: Thu, 30 Oct 2014 18:51:52 +0100

Expose the needed device information to the table generation
insfrastructure and assemble the final compacted ACPI binary
blob in the guest memory.

Signed-off-by: Alvise Rigo <address@hidden>
---
 hw/arm/boot.c        | 26 +++++++++++++++++++++++++
 hw/arm/virt-acpi.c   | 18 +++++++++++++++++-
 hw/arm/virt.c        | 54 ++++++++++++++++++++++++++++++++++++++++++++++++----
 include/hw/arm/arm.h |  2 ++
 4 files changed, 95 insertions(+), 5 deletions(-)

diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index bffbea5..74c8eb5 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -179,6 +179,11 @@ static inline bool have_dtb(const struct arm_boot_info 
*info)
     return info->dtb_filename || info->get_dtb;
 }
 
+static inline bool have_acpi(const struct arm_boot_info *info)
+{
+    return info->get_acpi;
+}
+
 #define WRITE_WORD(p, value) do { \
     stl_phys_notdirty(&address_space_memory, p, value);  \
     p += 4;                       \
@@ -438,6 +443,20 @@ fail:
     return -1;
 }
 
+static int load_acpi(hwaddr addr, const struct arm_boot_info *binfo,
+                                                  hwaddr addr_limit)
+{
+    void *acpi_blob = NULL;
+    int acpi_size;
+
+    acpi_blob = binfo->get_acpi(binfo, &acpi_size);
+    rom_add_blob_fixed("acpi", acpi_blob, acpi_size, binfo->acpi_base_addr);
+    g_free(acpi_blob);
+    /* TODO: check to not write outside memory boundaries */
+
+    return 0;
+}
+
 static void do_cpu_reset(void *opaque)
 {
     ARMCPU *cpu = opaque;
@@ -497,6 +516,13 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info 
*info)
         qemu_register_reset(do_cpu_reset, ARM_CPU(cs));
     }
 
+    /* load ACPI blob */
+    if (have_acpi(info)) {
+        if (load_acpi(info->acpi_base_addr, info, 0) < 0) {
+            exit(1);
+        }
+    }
+
     /* Load the kernel.  */
     if (!info->kernel_filename) {
 
diff --git a/hw/arm/virt-acpi.c b/hw/arm/virt-acpi.c
index be490e7..19e6779 100644
--- a/hw/arm/virt-acpi.c
+++ b/hw/arm/virt-acpi.c
@@ -535,5 +535,21 @@ void acpi_build_tables(int smp_cpus,
 
 uint32_t acpi_make_blob(void **blob_ptr)
 {
-    return 0;
+    uint8_t *acpi_blob_ptr = NULL;
+    uint32_t blob_size, n;
+
+    for (n = RSDP, blob_size = 0; n <= DSDT; n++) {
+        blob_size += acpi_size[n];
+    }
+
+    *blob_ptr = (void *)g_malloc0(blob_size);
+    acpi_blob_ptr = *blob_ptr;
+
+    for (n = RSDP; n <= DSDT; n++) {
+        memcpy(acpi_blob_ptr, acpi_table[n], acpi_size[n]);
+        acpi_blob_ptr += acpi_size[n];
+        g_free(acpi_table[n]);
+    }
+
+    return blob_size;
 }
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 78f618d..5b40292 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -42,6 +42,8 @@
 #include "exec/address-spaces.h"
 #include "qemu/bitops.h"
 #include "qemu/error-report.h"
+#include "hw/acpi/acpi-defs.h"
+#include "hw/arm/virt-acpi.h"
 
 #define NUM_VIRTIO_TRANSPORTS 32
 
@@ -59,6 +61,11 @@
 #define GIC_FDT_IRQ_PPI_CPU_START 8
 #define GIC_FDT_IRQ_PPI_CPU_WIDTH 8
 
+#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
+
 enum {
     VIRT_FLASH,
     VIRT_MEM,
@@ -83,6 +90,8 @@ typedef struct VirtBoardInfo {
     int smp_cpus;
     void *fdt;
     int fdt_size;
+    void *acpi;
+    int acpi_size;
     uint32_t clock_phandle;
 } VirtBoardInfo;
 
@@ -119,6 +128,29 @@ static const int a15irqmap[] = {
     [VIRT_MMIO] = 16, /* ...to 16 + NUM_VIRTIO_TRANSPORTS - 1 */
 };
 
+static const struct acpi_madt_info madt_info = {
+    &a15memmap[VIRT_GIC_CPU].base,
+    &a15memmap[VIRT_GIC_DIST].base
+};
+
+static const struct acpi_dsdt_info dsdt_info = {
+    .uart_addr = &a15memmap[VIRT_UART].base,
+    .uart_irq = &a15irqmap[VIRT_UART],
+    .virtio_mmio_addr = &a15memmap[VIRT_MMIO].base,
+    .virtio_mmio_irq = &a15irqmap[VIRT_MMIO],
+    .virtio_mmio_num = NUM_VIRTIO_TRANSPORTS,
+    .rtc_addr = &a15memmap[VIRT_RTC].base,
+    .rtc_irq = &a15irqmap[VIRT_RTC],
+    .flash_addr = &a15memmap[VIRT_FLASH].base,
+};
+
+static const struct acpi_gtdt_info gtdt_info = {
+    ARCH_TIMER_VIRT_IRQ + 16,
+    ARCH_TIMER_S_EL1_IRQ + 16,
+    ARCH_TIMER_NS_EL1_IRQ + 16,
+    ARCH_TIMER_NS_EL2_IRQ + 16
+};
+
 static VirtBoardInfo machines[] = {
     {
         .cpu_model = "cortex-a15",
@@ -259,10 +291,10 @@ static void fdt_add_timer_nodes(const VirtBoardInfo *vbi)
                                 "arm,armv7-timer");
     }
     qemu_fdt_setprop_cells(vbi->fdt, "/timer", "interrupts",
-                               GIC_FDT_IRQ_TYPE_PPI, 13, irqflags,
-                               GIC_FDT_IRQ_TYPE_PPI, 14, irqflags,
-                               GIC_FDT_IRQ_TYPE_PPI, 11, irqflags,
-                               GIC_FDT_IRQ_TYPE_PPI, 10, irqflags);
+                       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 VirtBoardInfo *vbi)
@@ -527,6 +559,14 @@ static void *machvirt_dtb(const struct arm_boot_info 
*binfo, int *fdt_size)
     return board->fdt;
 }
 
+static void *machvirt_acpi(const struct arm_boot_info *binfo, int *acpi_size)
+{
+    const VirtBoardInfo *board = (const VirtBoardInfo *)binfo;
+
+    *acpi_size = board->acpi_size;
+    return board->acpi;
+}
+
 static void machvirt_init(MachineState *machine)
 {
     qemu_irq pic[NUM_IRQS];
@@ -604,6 +644,10 @@ static void machvirt_init(MachineState *machine)
      */
     create_virtio_devices(vbi, pic);
 
+    /* Build ACPI tables and form the binary blob */
+    acpi_build_tables(vbi->smp_cpus, &gtdt_info, &madt_info, &dsdt_info);
+    vbi->acpi_size = acpi_make_blob(&vbi->acpi);
+
     vbi->bootinfo.ram_size = machine->ram_size;
     vbi->bootinfo.kernel_filename = machine->kernel_filename;
     vbi->bootinfo.kernel_cmdline = machine->kernel_cmdline;
@@ -612,6 +656,8 @@ static void machvirt_init(MachineState *machine)
     vbi->bootinfo.board_id = -1;
     vbi->bootinfo.loader_start = vbi->memmap[VIRT_MEM].base;
     vbi->bootinfo.get_dtb = machvirt_dtb;
+    vbi->bootinfo.acpi_base_addr = ACPI_BASE_ADDRESS;
+    vbi->bootinfo.get_acpi = machvirt_acpi;
     arm_load_kernel(ARM_CPU(first_cpu), &vbi->bootinfo);
 }
 
diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h
index cefc9e6..806faaf 100644
--- a/include/hw/arm/arm.h
+++ b/include/hw/arm/arm.h
@@ -27,6 +27,7 @@ struct arm_boot_info {
     const char *initrd_filename;
     const char *dtb_filename;
     hwaddr loader_start;
+    hwaddr acpi_base_addr;
     /* multicore boards that use the default secondary core boot functions
      * need to put the address of the secondary boot code, the boot reg,
      * and the GIC address in the next 3 values, respectively. boards that
@@ -61,6 +62,7 @@ struct arm_boot_info {
      * the user it should implement this hook.
      */
     void (*modify_dtb)(const struct arm_boot_info *info, void *fdt);
+    void *(*get_acpi)(const struct arm_boot_info *info, int *size);
     /* Used internally by arm_boot.c */
     int is_linux;
     hwaddr initrd_start;
-- 
1.9.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]