[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, >dt_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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemu-devel] [RFC PATCH 7/7] hw/arm/virt: Enable dynamic generation of ACPI v5.1 tables,
Alexander Spyridakis <=