This patchset moves all generation of ACPI tables from guest BIOS to the hypervisor.
Although ACPI tables come from a system BIOS on real hw, it makes sense that the ACPI tables are coupled with the virtual machine, since they have to abstract the x86 machine to the OS's.
Several future developments that this will enable: - make it easier to use alternative firmware: any firmware can just load the ACPI tables from QEMU. case in point OVMF. - make it easier to add more chipsets without bumping into fw_cfg boundaries. - describe a complex configuration e.g. a bridged PCI topology to enable acpi hotplug of devices behind a PCI bridge, or for multi-root topology.
If you look at the actual code: i386: imports ACPI table generation code from seabios you will see that it's more complex than it needs to be, with lots of low level casts and similar tricks.
There's also a bit of duplication where we already declare similar acpi structures in qemu.
This is the result of code being a direct port from seabios. Laszlo's patch (build ACPI MADT (APIC) for fw_cfg) shows how this will be cleaned up by follow-up work. I think it's best to do it in this order: port code directly, and apply cleanups and reduce duplication that results, on top. This way it's much easier to see that we don't introduce regressions.
In particular, for a simple VM with piix, I booted a guest on qemu with and without the change, and verified that ACPI tables are unchanged except for trivial pointer address changes.
Such binary compatibility makes it easier to be confident that this change won't break things.
So the idea is Laszlo's patchset (patches 2-7) will be rebased on top of this patchset, this way we'll get small cleanup changes, where each step is easy to verify as not changing anything from Guest POV.
One issue this patchset creates is cross-version migration. Specifically migration to qemu 1.5 will not work if it happens while bios is accessing fw_cfg when we migrate. This is a general problem of the fw_cfg implementation, I plan to extend fw_cfg implementation to address this.
I plan to test q35 and numa setups before I submit this for inclusion, in a similar way.
git trees, for those interested in testing this:
git://git.kernel.org/pub/scm/virt/kvm/mst/qemu.git acpi
git://git.kernel.org/pub/scm/virt/kvm/mst/seabios.git acpi
bios patchset will be posted tomorrow (need to clean up the commit log a bit).
Laszlo Ersek (1): refer to FWCfgState explicitly
Michael S. Tsirkin (12): apic: rename apic specific bitopts hw/i386/pc.c: move IO_APIC_DEFAULT_ADDRESS to include/hw/i386/apic.h fw_cfg: move typedef to qemu/typedefs.h i386: add ACPI table files from seabios acpi: add rules to compile ASL source acpi: pre-compiled ASL files range: add Range structure i386: add bios linker/loader i386: generate pc guest info pc: pass PCI hole ranges to Guests i386: ACPI table generation code from seabios pc: reuse guest info for legacy fw cfg
configure | 9 +- hw/acpi/ich9.c | 7 +- hw/acpi/piix4.c | 44 +- hw/core/loader.c | 2 +- hw/i386/Makefile.objs | 27 + hw/i386/acpi-build.c | 685 ++++ hw/i386/acpi-dsdt-cpu-hotplug.dsl | 93 + hw/i386/acpi-dsdt-dbug.dsl | 41 + hw/i386/acpi-dsdt-hpet.dsl | 51 + hw/i386/acpi-dsdt-isa.dsl | 117 + hw/i386/acpi-dsdt-pci-crs.dsl | 105 + hw/i386/acpi-dsdt.dsl | 343 ++ hw/i386/acpi-dsdt.hex.generated | 4409 ++++++++++++++++++++ hw/i386/bios-linker-loader.c | 155 + hw/i386/multiboot.c | 2 +- hw/i386/multiboot.h | 4 +- hw/i386/pc.c | 159 +- hw/i386/pc_piix.c | 28 +- hw/i386/pc_q35.c | 14 +- hw/i386/q35-acpi-dsdt.dsl | 452 +++ hw/i386/q35-acpi-dsdt.hex.generated | 7346 ++++++++++++++++++++++++++++++++++ hw/i386/ssdt-misc.dsl | 73 + hw/i386/ssdt-misc.hex.generated | 190 + hw/i386/ssdt-pcihp.dsl | 51 + hw/i386/ssdt-pcihp.hex.generated | 108 + hw/i386/ssdt-proc.dsl | 63 + hw/i386/ssdt-proc.hex.generated | 134 + hw/intc/apic.c | 42 +- hw/isa/lpc_ich9.c | 11 +- hw/mips/mips_malta.c | 2 +- hw/pci-host/q35.c | 5 + hw/sparc/sun4m.c | 6 +- hw/sparc64/sun4u.c | 2 +- include/hw/acpi/ich9.h | 2 +- include/hw/i386/acpi-build.h | 9 + include/hw/i386/apic.h | 2 + include/hw/i386/bios-linker-loader.h | 26 + include/hw/i386/ich9.h | 3 +- include/hw/i386/pc.h | 67 +- include/hw/loader.h | 3 +- include/hw/nvram/fw_cfg.h | 2 +- include/hw/pci-host/q35.h | 2 + include/qemu/range.h | 22 + include/qemu/typedefs.h | 2 + scripts/acpi_extract.py | 362 ++ scripts/acpi_extract_preprocess.py | 52 + scripts/update-acpi.sh | 4 + 47 files changed, 15248 insertions(+), 90 deletions(-) create mode 100644 hw/i386/acpi-build.c create mode 100644 hw/i386/acpi-dsdt-cpu-hotplug.dsl create mode 100644 hw/i386/acpi-dsdt-dbug.dsl create mode 100644 hw/i386/acpi-dsdt-hpet.dsl create mode 100644 hw/i386/acpi-dsdt-isa.dsl create mode 100644 hw/i386/acpi-dsdt-pci-crs.dsl create mode 100644 hw/i386/acpi-dsdt.dsl create mode 100644 hw/i386/acpi-dsdt.hex.generated create mode 100644 hw/i386/bios-linker-loader.c create mode 100644 hw/i386/q35-acpi-dsdt.dsl create mode 100644 hw/i386/q35-acpi-dsdt.hex.generated create mode 100644 hw/i386/ssdt-misc.dsl create mode 100644 hw/i386/ssdt-misc.hex.generated create mode 100644 hw/i386/ssdt-pcihp.dsl create mode 100644 hw/i386/ssdt-pcihp.hex.generated create mode 100644 hw/i386/ssdt-proc.dsl create mode 100644 hw/i386/ssdt-proc.hex.generated create mode 100644 include/hw/i386/acpi-build.h create mode 100644 include/hw/i386/bios-linker-loader.h create mode 100755 scripts/acpi_extract.py create mode 100755 scripts/acpi_extract_preprocess.py create mode 100644 scripts/update-acpi.sh
From: Laszlo Ersek lersek@redhat.com Subject: refer to FWCfgState explicitly
Currently some places use pointer-to-void even though they mean pointer-to-FWCfgState. Clean them up.
Signed-off-by: Laszlo Ersek lersek@redhat.com Signed-off-by: Michael S. Tsirkin mst@redhat.com --- hw/acpi/piix4.c | 2 +- hw/core/loader.c | 2 +- hw/i386/multiboot.c | 2 +- hw/i386/multiboot.h | 4 +++- hw/i386/pc.c | 24 ++++++++++++------------ hw/i386/pc_piix.c | 2 +- hw/sparc/sun4m.c | 6 +++--- hw/sparc64/sun4u.c | 2 +- include/hw/i386/pc.h | 19 ++++++++++--------- include/hw/loader.h | 3 ++- 10 files changed, 35 insertions(+), 31 deletions(-)
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index c4af1cc..e6525ac 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -447,7 +447,7 @@ static int piix4_pm_initfn(PCIDevice *dev)
i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, qemu_irq sci_irq, qemu_irq smi_irq, - int kvm_enabled, void *fw_cfg) + int kvm_enabled, FWCfgState *fw_cfg) { PCIDevice *dev; PIIX4PMState *s; diff --git a/hw/core/loader.c b/hw/core/loader.c index 7507914..a711145 100644 --- a/hw/core/loader.c +++ b/hw/core/loader.c @@ -733,7 +733,7 @@ int rom_load_all(void) return 0; }
-void rom_set_fw(void *f) +void rom_set_fw(FWCfgState *f) { fw_cfg = f; } diff --git a/hw/i386/multiboot.c b/hw/i386/multiboot.c index d696507..09211e0 100644 --- a/hw/i386/multiboot.c +++ b/hw/i386/multiboot.c @@ -124,7 +124,7 @@ static void mb_add_mod(MultibootState *s, s->mb_mods_count++; }
-int load_multiboot(void *fw_cfg, +int load_multiboot(FWCfgState *fw_cfg, FILE *f, const char *kernel_filename, const char *initrd_filename, diff --git a/hw/i386/multiboot.h b/hw/i386/multiboot.h index 98fb1b7..60de309 100644 --- a/hw/i386/multiboot.h +++ b/hw/i386/multiboot.h @@ -1,7 +1,9 @@ #ifndef QEMU_MULTIBOOT_H #define QEMU_MULTIBOOT_H
-int load_multiboot(void *fw_cfg, +#include "hw/nvram/fw_cfg.h" + +int load_multiboot(FWCfgState *fw_cfg, FILE *f, const char *kernel_filename, const char *initrd_filename, diff --git a/hw/i386/pc.c b/hw/i386/pc.c index f13dde5..338a672 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -593,9 +593,9 @@ static unsigned int pc_apic_id_limit(unsigned int max_cpus) return x86_cpu_apic_id_from_index(max_cpus - 1) + 1; }
-static void *bochs_bios_init(void) +static FWCfgState *bochs_bios_init(void) { - void *fw_cfg; + FWCfgState *fw_cfg; uint8_t *smbios_table; size_t smbios_len; uint64_t *numa_fw_cfg; @@ -672,7 +672,7 @@ static long get_file_size(FILE *f) return size; }
-static void load_linux(void *fw_cfg, +static void load_linux(FWCfgState *fw_cfg, const char *kernel_filename, const char *initrd_filename, const char *kernel_cmdline, @@ -1010,19 +1010,19 @@ void pc_acpi_init(const char *default_dsdt) } }
-void *pc_memory_init(MemoryRegion *system_memory, - const char *kernel_filename, - const char *kernel_cmdline, - const char *initrd_filename, - ram_addr_t below_4g_mem_size, - ram_addr_t above_4g_mem_size, - MemoryRegion *rom_memory, - MemoryRegion **ram_memory) +FWCfgState *pc_memory_init(MemoryRegion *system_memory, + const char *kernel_filename, + const char *kernel_cmdline, + const char *initrd_filename, + ram_addr_t below_4g_mem_size, + ram_addr_t above_4g_mem_size, + MemoryRegion *rom_memory, + MemoryRegion **ram_memory) { int linux_boot, i; MemoryRegion *ram, *option_rom_mr; MemoryRegion *ram_below_4g, *ram_above_4g; - void *fw_cfg; + FWCfgState *fw_cfg;
linux_boot = (kernel_filename != NULL);
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index f7c80ad..207115c 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -89,7 +89,7 @@ static void pc_init1(MemoryRegion *system_memory, MemoryRegion *pci_memory; MemoryRegion *rom_memory; DeviceState *icc_bridge; - void *fw_cfg = NULL; + FWCfgState *fw_cfg = NULL;
icc_bridge = qdev_create(NULL, TYPE_ICC_BRIDGE); object_property_add_child(qdev_get_machine(), "icc-bridge", diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c index 635115f..47439fe 100644 --- a/hw/sparc/sun4m.c +++ b/hw/sparc/sun4m.c @@ -873,7 +873,7 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, ram_addr_t RAM_size, qemu_irq *cpu_halt; unsigned long kernel_size; DriveInfo *fd[MAX_FD]; - void *fw_cfg; + FWCfgState *fw_cfg; unsigned int num_vsimms;
/* init CPUs */ @@ -1591,7 +1591,7 @@ static void sun4d_hw_init(const struct sun4d_hwdef *hwdef, ram_addr_t RAM_size, espdma_irq, ledma_irq; qemu_irq esp_reset, dma_enable; unsigned long kernel_size; - void *fw_cfg; + FWCfgState *fw_cfg; DeviceState *dev;
/* init CPUs */ @@ -1792,7 +1792,7 @@ static void sun4c_hw_init(const struct sun4c_hwdef *hwdef, ram_addr_t RAM_size, qemu_irq fdc_tc; unsigned long kernel_size; DriveInfo *fd[MAX_FD]; - void *fw_cfg; + FWCfgState *fw_cfg; DeviceState *dev; unsigned int i;
diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c index 5c2bbd4..5ce5ed6 100644 --- a/hw/sparc64/sun4u.c +++ b/hw/sparc64/sun4u.c @@ -818,7 +818,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem, qemu_irq *ivec_irqs, *pbm_irqs; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; DriveInfo *fd[MAX_FD]; - void *fw_cfg; + FWCfgState *fw_cfg;
/* init CPUs */ cpu = cpu_devinit(cpu_model, hwdef); diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 417afe4..def52aa 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -9,6 +9,7 @@ #include "net/net.h" #include "exec/memory.h" #include "hw/i386/ioapic.h" +#include "hw/nvram/fw_cfg.h"
/* PC-style peripherals (also used by other machines). */
@@ -81,14 +82,14 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level); void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge); void pc_hot_add_cpu(const int64_t id, Error **errp); void pc_acpi_init(const char *default_dsdt); -void *pc_memory_init(MemoryRegion *system_memory, - const char *kernel_filename, - const char *kernel_cmdline, - const char *initrd_filename, - ram_addr_t below_4g_mem_size, - ram_addr_t above_4g_mem_size, - MemoryRegion *rom_memory, - MemoryRegion **ram_memory); +FWCfgState *pc_memory_init(MemoryRegion *system_memory, + const char *kernel_filename, + const char *kernel_cmdline, + const char *initrd_filename, + ram_addr_t below_4g_mem_size, + ram_addr_t above_4g_mem_size, + MemoryRegion *rom_memory, + MemoryRegion **ram_memory); qemu_irq *pc_allocate_cpu_irq(void); DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus); void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi, @@ -112,7 +113,7 @@ void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name);
i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, qemu_irq sci_irq, qemu_irq smi_irq, - int kvm_enabled, void *fw_cfg); + int kvm_enabled, FWCfgState *fw_cfg); void piix4_smbus_register_device(SMBusDevice *dev, uint8_t addr);
/* hpet.c */ diff --git a/include/hw/loader.h b/include/hw/loader.h index 0958f06..15d4cc9 100644 --- a/include/hw/loader.h +++ b/include/hw/loader.h @@ -1,6 +1,7 @@ #ifndef LOADER_H #define LOADER_H #include "qapi/qmp/qdict.h" +#include "hw/nvram/fw_cfg.h"
/* loader.c */ int get_image_size(const char *filename); @@ -30,7 +31,7 @@ int rom_add_blob(const char *name, const void *blob, size_t len, int rom_add_elf_program(const char *name, void *data, size_t datasize, size_t romsize, hwaddr addr); int rom_load_all(void); -void rom_set_fw(void *f); +void rom_set_fw(FWCfgState *f); int rom_copy(uint8_t *dest, hwaddr addr, size_t size); void *rom_ptr(hwaddr addr); void do_info_roms(Monitor *mon, const QDict *qdict);
Signed-off-by: Michael S. Tsirkin mst@redhat.com Signed-off-by: Laszlo Ersek lersek@redhat.com Signed-off-by: Michael S. Tsirkin mst@redhat.com --- hw/i386/pc.c | 2 -- include/hw/i386/apic.h | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 197d218..f13dde5 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -75,8 +75,6 @@ #define FW_CFG_E820_TABLE (FW_CFG_ARCH_LOCAL + 3) #define FW_CFG_HPET (FW_CFG_ARCH_LOCAL + 4)
-#define IO_APIC_DEFAULT_ADDRESS 0xfec00000 - #define E820_NR_ENTRIES 16
struct e820_entry { diff --git a/include/hw/i386/apic.h b/include/hw/i386/apic.h index 1d48e02..edbb37f 100644 --- a/include/hw/i386/apic.h +++ b/include/hw/i386/apic.h @@ -26,6 +26,8 @@ void apic_designate_bsp(DeviceState *d); /* pc.c */ DeviceState *cpu_get_current_apic(void);
+#define IO_APIC_DEFAULT_ADDRESS 0xfec00000 + /* cpu.c */ bool cpu_is_bsp(X86CPU *cpu);
apic has its own version of bitops, with the difference that it works on u32 and not long. Add apic_ prefix to avoid namespace clashes.
Signed-off-by: Michael S. Tsirkin mst@redhat.com --- hw/intc/apic.c | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-)
diff --git a/hw/intc/apic.c b/hw/intc/apic.c index 756dff0..46cb097 100644 --- a/hw/intc/apic.c +++ b/hw/intc/apic.c @@ -40,18 +40,18 @@ static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask, uint8_t dest, uint8_t dest_mode);
/* Find first bit starting from msb */ -static int fls_bit(uint32_t value) +static int apic_fls_bit(uint32_t value) { return 31 - clz32(value); }
/* Find first bit starting from lsb */ -static int ffs_bit(uint32_t value) +static int apic_ffs_bit(uint32_t value) { return ctz32(value); }
-static inline void set_bit(uint32_t *tab, int index) +static inline void apic_set_bit(uint32_t *tab, int index) { int i, mask; i = index >> 5; @@ -59,7 +59,7 @@ static inline void set_bit(uint32_t *tab, int index) tab[i] |= mask; }
-static inline void reset_bit(uint32_t *tab, int index) +static inline void apic_reset_bit(uint32_t *tab, int index) { int i, mask; i = index >> 5; @@ -67,7 +67,7 @@ static inline void reset_bit(uint32_t *tab, int index) tab[i] &= ~mask; }
-static inline int get_bit(uint32_t *tab, int index) +static inline int apic_get_bit(uint32_t *tab, int index) { int i, mask; i = index >> 5; @@ -81,7 +81,7 @@ static int get_highest_priority_int(uint32_t *tab) int i; for (i = 7; i >= 0; i--) { if (tab[i] != 0) { - return i * 32 + fls_bit(tab[i]); + return i * 32 + apic_fls_bit(tab[i]); } } return -1; @@ -184,7 +184,7 @@ void apic_deliver_pic_intr(DeviceState *d, int level) case APIC_DM_FIXED: if (!(lvt & APIC_LVT_LEVEL_TRIGGER)) break; - reset_bit(s->irr, lvt & 0xff); + apic_reset_bit(s->irr, lvt & 0xff); /* fall through */ case APIC_DM_EXTINT: cpu_reset_interrupt(CPU(s->cpu), CPU_INTERRUPT_HARD); @@ -230,7 +230,7 @@ static void apic_bus_deliver(const uint32_t *deliver_bitmask, d = -1; for(i = 0; i < MAX_APIC_WORDS; i++) { if (deliver_bitmask[i]) { - d = i * 32 + ffs_bit(deliver_bitmask[i]); + d = i * 32 + apic_ffs_bit(deliver_bitmask[i]); break; } } @@ -386,13 +386,13 @@ void apic_poll_irq(DeviceState *d)
static void apic_set_irq(APICCommonState *s, int vector_num, int trigger_mode) { - apic_report_irq_delivered(!get_bit(s->irr, vector_num)); + apic_report_irq_delivered(!apic_get_bit(s->irr, vector_num));
- set_bit(s->irr, vector_num); + apic_set_bit(s->irr, vector_num); if (trigger_mode) - set_bit(s->tmr, vector_num); + apic_set_bit(s->tmr, vector_num); else - reset_bit(s->tmr, vector_num); + apic_reset_bit(s->tmr, vector_num); if (s->vapic_paddr) { apic_sync_vapic(s, SYNC_ISR_IRR_TO_VAPIC); /* @@ -412,8 +412,8 @@ static void apic_eoi(APICCommonState *s) isrv = get_highest_priority_int(s->isr); if (isrv < 0) return; - reset_bit(s->isr, isrv); - if (!(s->spurious_vec & APIC_SV_DIRECTED_IO) && get_bit(s->tmr, isrv)) { + apic_reset_bit(s->isr, isrv); + if (!(s->spurious_vec & APIC_SV_DIRECTED_IO) && apic_get_bit(s->tmr, isrv)) { ioapic_eoi_broadcast(isrv); } apic_sync_vapic(s, SYNC_FROM_VAPIC | SYNC_TO_VAPIC); @@ -452,7 +452,7 @@ static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask, int idx = apic_find_dest(dest); memset(deliver_bitmask, 0x00, MAX_APIC_WORDS * sizeof(uint32_t)); if (idx >= 0) - set_bit(deliver_bitmask, idx); + apic_set_bit(deliver_bitmask, idx); } } else { /* XXX: cluster mode */ @@ -462,11 +462,11 @@ static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask, if (apic_iter) { if (apic_iter->dest_mode == 0xf) { if (dest & apic_iter->log_dest) - set_bit(deliver_bitmask, i); + apic_set_bit(deliver_bitmask, i); } else if (apic_iter->dest_mode == 0x0) { if ((dest & 0xf0) == (apic_iter->log_dest & 0xf0) && (dest & apic_iter->log_dest & 0x0f)) { - set_bit(deliver_bitmask, i); + apic_set_bit(deliver_bitmask, i); } } } else { @@ -509,14 +509,14 @@ static void apic_deliver(DeviceState *d, uint8_t dest, uint8_t dest_mode, break; case 1: memset(deliver_bitmask, 0x00, sizeof(deliver_bitmask)); - set_bit(deliver_bitmask, s->idx); + apic_set_bit(deliver_bitmask, s->idx); break; case 2: memset(deliver_bitmask, 0xff, sizeof(deliver_bitmask)); break; case 3: memset(deliver_bitmask, 0xff, sizeof(deliver_bitmask)); - reset_bit(deliver_bitmask, s->idx); + apic_reset_bit(deliver_bitmask, s->idx); break; }
@@ -573,8 +573,8 @@ int apic_get_interrupt(DeviceState *d) apic_sync_vapic(s, SYNC_TO_VAPIC); return s->spurious_vec & 0xff; } - reset_bit(s->irr, intno); - set_bit(s->isr, intno); + apic_reset_bit(s->irr, intno); + apic_set_bit(s->isr, intno); apic_sync_vapic(s, SYNC_TO_VAPIC);
/* re-inject if there is still a pending PIC interrupt */
Less header dependencies this way.
Signed-off-by: Michael S. Tsirkin mst@redhat.com --- include/hw/i386/pc.h | 1 - include/hw/nvram/fw_cfg.h | 2 +- include/qemu/typedefs.h | 1 + 3 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index def52aa..1c2baaf 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -9,7 +9,6 @@ #include "net/net.h" #include "exec/memory.h" #include "hw/i386/ioapic.h" -#include "hw/nvram/fw_cfg.h"
/* PC-style peripherals (also used by other machines). */
diff --git a/include/hw/nvram/fw_cfg.h b/include/hw/nvram/fw_cfg.h index 3e4a334..f37714e 100644 --- a/include/hw/nvram/fw_cfg.h +++ b/include/hw/nvram/fw_cfg.h @@ -6,6 +6,7 @@ #include <stddef.h>
#include "exec/hwaddr.h" +#include "qemu/typedefs.h" #endif
#define FW_CFG_SIGNATURE 0x00 @@ -60,7 +61,6 @@ typedef struct FWCfgFiles {
typedef void (*FWCfgCallback)(void *opaque, uint8_t *data);
-typedef struct FWCfgState FWCfgState; void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len); void fw_cfg_add_string(FWCfgState *s, uint16_t key, const char *value); void fw_cfg_add_i16(FWCfgState *s, uint16_t key, uint16_t value); diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h index 93aae81..afe4ec7 100644 --- a/include/qemu/typedefs.h +++ b/include/qemu/typedefs.h @@ -61,5 +61,6 @@ typedef struct EventNotifier EventNotifier; typedef struct VirtIODevice VirtIODevice; typedef struct QEMUSGList QEMUSGList; typedef struct SHPCDevice SHPCDevice; +typedef struct FWCfgState FWCfgState;
#endif /* QEMU_TYPEDEFS_H */
This adds ASL code as well as scripts for processing it, imported from seabios git tree commit 51684b7ced75fb76776e8ee84833fcfb6ecf12dd
Will be used for runtime acpi table generation.
Note: This patch reuses some code from SeaBIOS, which was originally under LGPLv2 and then relicensed to GPLv3 or LGPLv3, in QEMU under GPLv2+. This relicensing has been acked by all contributors that had contributed to the code since the v2->v3 relicense. ACKs approving the v2+ relicensing are listed below. The list might include ACKs from people not holding copyright on any parts of the reused code, but it's better to err on the side of caution and include them.
Affected SeaBIOS files (GPLv2+ license headers added) http://thread.gmane.org/gmane.comp.bios.coreboot.seabios/5949:
src/acpi-dsdt-cpu-hotplug.dsl | 15 +++++++++++++++ src/acpi-dsdt-dbug.dsl | 15 +++++++++++++++ src/acpi-dsdt-hpet.dsl | 15 +++++++++++++++ src/acpi-dsdt-isa.dsl | 15 +++++++++++++++ src/acpi-dsdt-pci-crs.dsl | 15 +++++++++++++++ src/acpi.c | 14 +++++++++++++- src/acpi.h | 14 ++++++++++++++ src/ssdt-misc.dsl | 15 +++++++++++++++ src/ssdt-pcihp.dsl | 15 +++++++++++++++ src/ssdt-proc.dsl | 15 +++++++++++++++ tools/acpi_extract.py | 13 ++++++++++++- tools/acpi_extract_preprocess.py | 13 ++++++++++++- 12 files changed, 171 insertions(+), 3 deletions(-)
Each one of the listed people agreed to the following:
If you allow the use of your contribution in QEMU under the terms of GPLv2 or later as proposed by this patch, please respond to this mail including the line:
Acked-by: Name <email address>
Acked-by: Gerd Hoffmann kraxel@redhat.com Acked-by: Jan Kiszka jan.kiszka@siemens.com Acked-by: Jason Baron jbaron@akamai.com Acked-by: David Woodhouse David.Woodhouse@intel.com Acked-by: Gleb Natapov gleb@redhat.com Acked-by: Marcelo Tosatti mtosatti@redhat.com Acked-by: Dave Frodin dave.frodin@se-eng.com Acked-by: Paolo Bonzini pbonzini@redhat.com Acked-by: Kevin O'Connor kevin@koconnor.net Acked-by: Laszlo Ersek lersek@redhat.com Acked-by: Kenji Kaneshige kaneshige.kenji@jp.fujitsu.com Acked-by: Isaku Yamahata yamahata@valinux.co.jp Acked-by: Magnus Christensson magnus.christensson@intel.com Acked-by: Hu Tao hutao@cn.fujitsu.com Acked-by: Eduardo Habkost ehabkost@redhat.com
Signed-off-by: Michael S. Tsirkin mst@redhat.com --- hw/i386/acpi-dsdt-cpu-hotplug.dsl | 93 ++++++++ hw/i386/acpi-dsdt-dbug.dsl | 41 ++++ hw/i386/acpi-dsdt-hpet.dsl | 51 +++++ hw/i386/acpi-dsdt-isa.dsl | 117 ++++++++++ hw/i386/acpi-dsdt-pci-crs.dsl | 105 +++++++++ hw/i386/acpi-dsdt.dsl | 343 ++++++++++++++++++++++++++++ hw/i386/q35-acpi-dsdt.dsl | 452 +++++++++++++++++++++++++++++++++++++ hw/i386/ssdt-misc.dsl | 73 ++++++ hw/i386/ssdt-pcihp.dsl | 51 +++++ hw/i386/ssdt-proc.dsl | 63 ++++++ scripts/acpi_extract.py | 362 +++++++++++++++++++++++++++++ scripts/acpi_extract_preprocess.py | 52 +++++ 12 files changed, 1803 insertions(+) create mode 100644 hw/i386/acpi-dsdt-cpu-hotplug.dsl create mode 100644 hw/i386/acpi-dsdt-dbug.dsl create mode 100644 hw/i386/acpi-dsdt-hpet.dsl create mode 100644 hw/i386/acpi-dsdt-isa.dsl create mode 100644 hw/i386/acpi-dsdt-pci-crs.dsl create mode 100644 hw/i386/acpi-dsdt.dsl create mode 100644 hw/i386/q35-acpi-dsdt.dsl create mode 100644 hw/i386/ssdt-misc.dsl create mode 100644 hw/i386/ssdt-pcihp.dsl create mode 100644 hw/i386/ssdt-proc.dsl create mode 100755 scripts/acpi_extract.py create mode 100755 scripts/acpi_extract_preprocess.py
diff --git a/hw/i386/acpi-dsdt-cpu-hotplug.dsl b/hw/i386/acpi-dsdt-cpu-hotplug.dsl new file mode 100644 index 0000000..c96ac42 --- /dev/null +++ b/hw/i386/acpi-dsdt-cpu-hotplug.dsl @@ -0,0 +1,93 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that 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/. + */ + +/**************************************************************** + * CPU hotplug + ****************************************************************/ + +Scope(_SB) { + /* Objects filled in by run-time generated SSDT */ + External(NTFY, MethodObj) + External(CPON, PkgObj) + + /* Methods called by run-time generated SSDT Processor objects */ + Method(CPMA, 1, NotSerialized) { + // _MAT method - create an madt apic buffer + // Arg0 = Processor ID = Local APIC ID + // Local0 = CPON flag for this cpu + Store(DerefOf(Index(CPON, Arg0)), Local0) + // Local1 = Buffer (in madt apic form) to return + Store(Buffer(8) {0x00, 0x08, 0x00, 0x00, 0x00, 0, 0, 0}, Local1) + // Update the processor id, lapic id, and enable/disable status + Store(Arg0, Index(Local1, 2)) + Store(Arg0, Index(Local1, 3)) + Store(Local0, Index(Local1, 4)) + Return (Local1) + } + Method(CPST, 1, NotSerialized) { + // _STA method - return ON status of cpu + // Arg0 = Processor ID = Local APIC ID + // Local0 = CPON flag for this cpu + Store(DerefOf(Index(CPON, Arg0)), Local0) + If (Local0) { + Return (0xF) + } Else { + Return (0x0) + } + } + Method(CPEJ, 2, NotSerialized) { + // _EJ0 method - eject callback + Sleep(200) + } + + /* CPU hotplug notify method */ + OperationRegion(PRST, SystemIO, 0xaf00, 32) + Field(PRST, ByteAcc, NoLock, Preserve) { + PRS, 256 + } + Method(PRSC, 0) { + // Local5 = active cpu bitmap + Store(PRS, Local5) + // Local2 = last read byte from bitmap + Store(Zero, Local2) + // Local0 = Processor ID / APIC ID iterator + Store(Zero, Local0) + While (LLess(Local0, SizeOf(CPON))) { + // Local1 = CPON flag for this cpu + Store(DerefOf(Index(CPON, Local0)), Local1) + If (And(Local0, 0x07)) { + // Shift down previously read bitmap byte + ShiftRight(Local2, 1, Local2) + } Else { + // Read next byte from cpu bitmap + Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2) + } + // Local3 = active state for this cpu + Store(And(Local2, 1), Local3) + + If (LNotEqual(Local1, Local3)) { + // State change - update CPON with new state + Store(Local3, Index(CPON, Local0)) + // Do CPU notify + If (LEqual(Local3, 1)) { + NTFY(Local0, 1) + } Else { + NTFY(Local0, 3) + } + } + Increment(Local0) + } + } +} diff --git a/hw/i386/acpi-dsdt-dbug.dsl b/hw/i386/acpi-dsdt-dbug.dsl new file mode 100644 index 0000000..86230f7 --- /dev/null +++ b/hw/i386/acpi-dsdt-dbug.dsl @@ -0,0 +1,41 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that 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/. + */ + +/**************************************************************** + * Debugging + ****************************************************************/ + +Scope() { + /* Debug Output */ + OperationRegion(DBG, SystemIO, 0x0402, 0x01) + Field(DBG, ByteAcc, NoLock, Preserve) { + DBGB, 8, + } + + /* Debug method - use this method to send output to the QEMU + * BIOS debug port. This method handles strings, integers, + * and buffers. For example: DBUG("abc") DBUG(0x123) */ + Method(DBUG, 1) { + ToHexString(Arg0, Local0) + ToBuffer(Local0, Local0) + Subtract(SizeOf(Local0), 1, Local1) + Store(Zero, Local2) + While (LLess(Local2, Local1)) { + Store(DerefOf(Index(Local0, Local2)), DBGB) + Increment(Local2) + } + Store(0x0A, DBGB) + } +} diff --git a/hw/i386/acpi-dsdt-hpet.dsl b/hw/i386/acpi-dsdt-hpet.dsl new file mode 100644 index 0000000..dfde174 --- /dev/null +++ b/hw/i386/acpi-dsdt-hpet.dsl @@ -0,0 +1,51 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that 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/. + */ + +/**************************************************************** + * HPET + ****************************************************************/ + +Scope(_SB) { + Device(HPET) { + Name(_HID, EISAID("PNP0103")) + Name(_UID, 0) + OperationRegion(HPTM, SystemMemory, 0xFED00000, 0x400) + Field(HPTM, DWordAcc, Lock, Preserve) { + VEND, 32, + PRD, 32, + } + Method(_STA, 0, NotSerialized) { + Store(VEND, Local0) + Store(PRD, Local1) + ShiftRight(Local0, 16, Local0) + If (LOr(LEqual(Local0, 0), LEqual(Local0, 0xffff))) { + Return (0x0) + } + If (LOr(LEqual(Local1, 0), LGreater(Local1, 100000000))) { + Return (0x0) + } + Return (0x0F) + } + Name(_CRS, ResourceTemplate() { +#if 0 /* This makes WinXP BSOD for not yet figured reasons. */ + IRQNoFlags() {2, 8} +#endif + Memory32Fixed(ReadOnly, + 0xFED00000, // Address Base + 0x00000400, // Address Length + ) + }) + } +} diff --git a/hw/i386/acpi-dsdt-isa.dsl b/hw/i386/acpi-dsdt-isa.dsl new file mode 100644 index 0000000..89caa16 --- /dev/null +++ b/hw/i386/acpi-dsdt-isa.dsl @@ -0,0 +1,117 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that 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/. + */ + +/* Common legacy ISA style devices. */ +Scope(_SB.PCI0.ISA) { + + Device(RTC) { + Name(_HID, EisaId("PNP0B00")) + Name(_CRS, ResourceTemplate() { + IO(Decode16, 0x0070, 0x0070, 0x10, 0x02) + IRQNoFlags() { 8 } + IO(Decode16, 0x0072, 0x0072, 0x02, 0x06) + }) + } + + Device(KBD) { + Name(_HID, EisaId("PNP0303")) + Method(_STA, 0, NotSerialized) { + Return (0x0f) + } + Name(_CRS, ResourceTemplate() { + IO(Decode16, 0x0060, 0x0060, 0x01, 0x01) + IO(Decode16, 0x0064, 0x0064, 0x01, 0x01) + IRQNoFlags() { 1 } + }) + } + + Device(MOU) { + Name(_HID, EisaId("PNP0F13")) + Method(_STA, 0, NotSerialized) { + Return (0x0f) + } + Name(_CRS, ResourceTemplate() { + IRQNoFlags() { 12 } + }) + } + + Device(FDC0) { + Name(_HID, EisaId("PNP0700")) + Method(_STA, 0, NotSerialized) { + Store(FDEN, Local0) + If (LEqual(Local0, 0)) { + Return (0x00) + } Else { + Return (0x0F) + } + } + Name(_CRS, ResourceTemplate() { + IO(Decode16, 0x03F2, 0x03F2, 0x00, 0x04) + IO(Decode16, 0x03F7, 0x03F7, 0x00, 0x01) + IRQNoFlags() { 6 } + DMA(Compatibility, NotBusMaster, Transfer8) { 2 } + }) + } + + Device(LPT) { + Name(_HID, EisaId("PNP0400")) + Method(_STA, 0, NotSerialized) { + Store(LPEN, Local0) + If (LEqual(Local0, 0)) { + Return (0x00) + } Else { + Return (0x0F) + } + } + Name(_CRS, ResourceTemplate() { + IO(Decode16, 0x0378, 0x0378, 0x08, 0x08) + IRQNoFlags() { 7 } + }) + } + + Device(COM1) { + Name(_HID, EisaId("PNP0501")) + Name(_UID, 0x01) + Method(_STA, 0, NotSerialized) { + Store(CAEN, Local0) + If (LEqual(Local0, 0)) { + Return (0x00) + } Else { + Return (0x0F) + } + } + Name(_CRS, ResourceTemplate() { + IO(Decode16, 0x03F8, 0x03F8, 0x00, 0x08) + IRQNoFlags() { 4 } + }) + } + + Device(COM2) { + Name(_HID, EisaId("PNP0501")) + Name(_UID, 0x02) + Method(_STA, 0, NotSerialized) { + Store(CBEN, Local0) + If (LEqual(Local0, 0)) { + Return (0x00) + } Else { + Return (0x0F) + } + } + Name(_CRS, ResourceTemplate() { + IO(Decode16, 0x02F8, 0x02F8, 0x00, 0x08) + IRQNoFlags() { 3 } + }) + } +} diff --git a/hw/i386/acpi-dsdt-pci-crs.dsl b/hw/i386/acpi-dsdt-pci-crs.dsl new file mode 100644 index 0000000..b375a19 --- /dev/null +++ b/hw/i386/acpi-dsdt-pci-crs.dsl @@ -0,0 +1,105 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that 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/. + */ + +/* PCI CRS (current resources) definition. */ +Scope(_SB.PCI0) { + + Name(CRES, ResourceTemplate() { + WordBusNumber(ResourceProducer, MinFixed, MaxFixed, PosDecode, + 0x0000, // Address Space Granularity + 0x0000, // Address Range Minimum + 0x00FF, // Address Range Maximum + 0x0000, // Address Translation Offset + 0x0100, // Address Length + ,, ) + IO(Decode16, + 0x0CF8, // Address Range Minimum + 0x0CF8, // Address Range Maximum + 0x01, // Address Alignment + 0x08, // Address Length + ) + WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, + 0x0000, // Address Space Granularity + 0x0000, // Address Range Minimum + 0x0CF7, // Address Range Maximum + 0x0000, // Address Translation Offset + 0x0CF8, // Address Length + ,, , TypeStatic) + WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, + 0x0000, // Address Space Granularity + 0x0D00, // Address Range Minimum + 0xFFFF, // Address Range Maximum + 0x0000, // Address Translation Offset + 0xF300, // Address Length + ,, , TypeStatic) + DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite, + 0x00000000, // Address Space Granularity + 0x000A0000, // Address Range Minimum + 0x000BFFFF, // Address Range Maximum + 0x00000000, // Address Translation Offset + 0x00020000, // Address Length + ,, , AddressRangeMemory, TypeStatic) + DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite, + 0x00000000, // Address Space Granularity + 0xE0000000, // Address Range Minimum + 0xFEBFFFFF, // Address Range Maximum + 0x00000000, // Address Translation Offset + 0x1EC00000, // Address Length + ,, PW32, AddressRangeMemory, TypeStatic) + }) + + Name(CR64, ResourceTemplate() { + QWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite, + 0x00000000, // Address Space Granularity + 0x8000000000, // Address Range Minimum + 0xFFFFFFFFFF, // Address Range Maximum + 0x00000000, // Address Translation Offset + 0x8000000000, // Address Length + ,, PW64, AddressRangeMemory, TypeStatic) + }) + + Method(_CRS, 0) { + /* Fields provided by dynamically created ssdt */ + External(P0S, IntObj) + External(P0E, IntObj) + External(P1V, IntObj) + External(P1S, BuffObj) + External(P1E, BuffObj) + External(P1L, BuffObj) + + /* fixup 32bit pci io window */ + CreateDWordField(CRES, _SB.PCI0.PW32._MIN, PS32) + CreateDWordField(CRES, _SB.PCI0.PW32._MAX, PE32) + CreateDWordField(CRES, _SB.PCI0.PW32._LEN, PL32) + Store(P0S, PS32) + Store(P0E, PE32) + Store(Add(Subtract(P0E, P0S), 1), PL32) + + If (LEqual(P1V, Zero)) { + Return (CRES) + } + + /* fixup 64bit pci io window */ + CreateQWordField(CR64, _SB.PCI0.PW64._MIN, PS64) + CreateQWordField(CR64, _SB.PCI0.PW64._MAX, PE64) + CreateQWordField(CR64, _SB.PCI0.PW64._LEN, PL64) + Store(P1S, PS64) + Store(P1E, PE64) + Store(P1L, PL64) + /* add window and return result */ + ConcatenateResTemplate(CRES, CR64, Local0) + Return (Local0) + } +} diff --git a/hw/i386/acpi-dsdt.dsl b/hw/i386/acpi-dsdt.dsl new file mode 100644 index 0000000..90efce0 --- /dev/null +++ b/hw/i386/acpi-dsdt.dsl @@ -0,0 +1,343 @@ +/* + * Bochs/QEMU ACPI DSDT ASL definition + * + * Copyright (c) 2006 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +ACPI_EXTRACT_ALL_CODE AcpiDsdtAmlCode + +DefinitionBlock ( + "acpi-dsdt.aml", // Output Filename + "DSDT", // Signature + 0x01, // DSDT Compliance Revision + "BXPC", // OEMID + "BXDSDT", // TABLE ID + 0x1 // OEM Revision + ) +{ + +#include "acpi-dsdt-dbug.dsl" + + +/**************************************************************** + * PCI Bus definition + ****************************************************************/ + + Scope(_SB) { + Device(PCI0) { + Name(_HID, EisaId("PNP0A03")) + Name(_ADR, 0x00) + Name(_UID, 1) + } + } + +#include "acpi-dsdt-pci-crs.dsl" +#include "acpi-dsdt-hpet.dsl" + + +/**************************************************************** + * VGA + ****************************************************************/ + + Scope(_SB.PCI0) { + Device(VGA) { + Name(_ADR, 0x00020000) + OperationRegion(PCIC, PCI_Config, Zero, 0x4) + Field(PCIC, DWordAcc, NoLock, Preserve) { + VEND, 32 + } + Method(_S1D, 0, NotSerialized) { + Return (0x00) + } + Method(_S2D, 0, NotSerialized) { + Return (0x00) + } + Method(_S3D, 0, NotSerialized) { + If (LEqual(VEND, 0x1001b36)) { + Return (0x03) // QXL + } Else { + Return (0x00) + } + } + } + } + + +/**************************************************************** + * PIIX4 PM + ****************************************************************/ + + Scope(_SB.PCI0) { + Device(PX13) { + Name(_ADR, 0x00010003) + OperationRegion(P13C, PCI_Config, 0x00, 0xff) + } + } + + +/**************************************************************** + * PIIX3 ISA bridge + ****************************************************************/ + + Scope(_SB.PCI0) { + Device(ISA) { + Name(_ADR, 0x00010000) + + /* PIIX PCI to ISA irq remapping */ + OperationRegion(P40C, PCI_Config, 0x60, 0x04) + + /* enable bits */ + Field(_SB.PCI0.PX13.P13C, AnyAcc, NoLock, Preserve) { + Offset(0x5f), + , 7, + LPEN, 1, // LPT + Offset(0x67), + , 3, + CAEN, 1, // COM1 + , 3, + CBEN, 1, // COM2 + } + Name(FDEN, 1) + } + } + +#include "acpi-dsdt-isa.dsl" + + +/**************************************************************** + * PCI hotplug + ****************************************************************/ + + Scope(_SB.PCI0) { + OperationRegion(PCST, SystemIO, 0xae00, 0x08) + Field(PCST, DWordAcc, NoLock, WriteAsZeros) { + PCIU, 32, + PCID, 32, + } + + OperationRegion(SEJ, SystemIO, 0xae08, 0x04) + Field(SEJ, DWordAcc, NoLock, WriteAsZeros) { + B0EJ, 32, + } + + /* Methods called by bulk generated PCI devices below */ + + /* Methods called by hotplug devices */ + Method(PCEJ, 1, NotSerialized) { + // _EJ0 method - eject callback + Store(ShiftLeft(1, Arg0), B0EJ) + Return (0x0) + } + + /* Hotplug notification method supplied by SSDT */ + External(_SB.PCI0.PCNT, MethodObj) + + /* PCI hotplug notify method */ + Method(PCNF, 0) { + // Local0 = iterator + Store(Zero, Local0) + While (LLess(Local0, 31)) { + Increment(Local0) + If (And(PCIU, ShiftLeft(1, Local0))) { + PCNT(Local0, 1) + } + If (And(PCID, ShiftLeft(1, Local0))) { + PCNT(Local0, 3) + } + } + } + } + + +/**************************************************************** + * PCI IRQs + ****************************************************************/ + + Scope(_SB) { + Scope(PCI0) { + Name(_PRT, Package() { + /* PCI IRQ routing table, example from ACPI 2.0a specification, + section 6.2.8.1 */ + /* Note: we provide the same info as the PCI routing + table of the Bochs BIOS */ + +#define prt_slot(nr, lnk0, lnk1, lnk2, lnk3) \ + Package() { nr##ffff, 0, lnk0, 0 }, \ + Package() { nr##ffff, 1, lnk1, 0 }, \ + Package() { nr##ffff, 2, lnk2, 0 }, \ + Package() { nr##ffff, 3, lnk3, 0 } + +#define prt_slot0(nr) prt_slot(nr, LNKD, LNKA, LNKB, LNKC) +#define prt_slot1(nr) prt_slot(nr, LNKA, LNKB, LNKC, LNKD) +#define prt_slot2(nr) prt_slot(nr, LNKB, LNKC, LNKD, LNKA) +#define prt_slot3(nr) prt_slot(nr, LNKC, LNKD, LNKA, LNKB) + + prt_slot0(0x0000), + /* Device 1 is power mgmt device, and can only use irq 9 */ + prt_slot(0x0001, LNKS, LNKB, LNKC, LNKD), + prt_slot2(0x0002), + prt_slot3(0x0003), + prt_slot0(0x0004), + prt_slot1(0x0005), + prt_slot2(0x0006), + prt_slot3(0x0007), + prt_slot0(0x0008), + prt_slot1(0x0009), + prt_slot2(0x000a), + prt_slot3(0x000b), + prt_slot0(0x000c), + prt_slot1(0x000d), + prt_slot2(0x000e), + prt_slot3(0x000f), + prt_slot0(0x0010), + prt_slot1(0x0011), + prt_slot2(0x0012), + prt_slot3(0x0013), + prt_slot0(0x0014), + prt_slot1(0x0015), + prt_slot2(0x0016), + prt_slot3(0x0017), + prt_slot0(0x0018), + prt_slot1(0x0019), + prt_slot2(0x001a), + prt_slot3(0x001b), + prt_slot0(0x001c), + prt_slot1(0x001d), + prt_slot2(0x001e), + prt_slot3(0x001f), + }) + } + + Field(PCI0.ISA.P40C, ByteAcc, NoLock, Preserve) { + PRQ0, 8, + PRQ1, 8, + PRQ2, 8, + PRQ3, 8 + } + + Method(IQST, 1, NotSerialized) { + // _STA method - get status + If (And(0x80, Arg0)) { + Return (0x09) + } + Return (0x0B) + } + Method(IQCR, 1, NotSerialized) { + // _CRS method - get current settings + Name(PRR0, ResourceTemplate() { + Interrupt(, Level, ActiveHigh, Shared) { 0 } + }) + CreateDWordField(PRR0, 0x05, PRRI) + If (LLess(Arg0, 0x80)) { + Store(Arg0, PRRI) + } + Return (PRR0) + } + +#define define_link(link, uid, reg) \ + Device(link) { \ + Name(_HID, EISAID("PNP0C0F")) \ + Name(_UID, uid) \ + Name(_PRS, ResourceTemplate() { \ + Interrupt(, Level, ActiveHigh, Shared) { \ + 5, 10, 11 \ + } \ + }) \ + Method(_STA, 0, NotSerialized) { \ + Return (IQST(reg)) \ + } \ + Method(_DIS, 0, NotSerialized) { \ + Or(reg, 0x80, reg) \ + } \ + Method(_CRS, 0, NotSerialized) { \ + Return (IQCR(reg)) \ + } \ + Method(_SRS, 1, NotSerialized) { \ + CreateDWordField(Arg0, 0x05, PRRI) \ + Store(PRRI, reg) \ + } \ + } + + define_link(LNKA, 0, PRQ0) + define_link(LNKB, 1, PRQ1) + define_link(LNKC, 2, PRQ2) + define_link(LNKD, 3, PRQ3) + + Device(LNKS) { + Name(_HID, EISAID("PNP0C0F")) + Name(_UID, 4) + Name(_PRS, ResourceTemplate() { + Interrupt(, Level, ActiveHigh, Shared) { 9 } + }) + + // The SCI cannot be disabled and is always attached to GSI 9, + // so these are no-ops. We only need this link to override the + // polarity to active high and match the content of the MADT. + Method(_STA, 0, NotSerialized) { Return (0x0b) } + Method(_DIS, 0, NotSerialized) { } + Method(_CRS, 0, NotSerialized) { Return (_PRS) } + Method(_SRS, 1, NotSerialized) { } + } + } + +#include "acpi-dsdt-cpu-hotplug.dsl" + + +/**************************************************************** + * General purpose events + ****************************************************************/ + + Scope(_GPE) { + Name(_HID, "ACPI0006") + + Method(_L00) { + } + Method(_E01) { + // PCI hotplug event + _SB.PCI0.PCNF() + } + Method(_E02) { + // CPU hotplug event + _SB.PRSC() + } + Method(_L03) { + } + Method(_L04) { + } + Method(_L05) { + } + Method(_L06) { + } + Method(_L07) { + } + Method(_L08) { + } + Method(_L09) { + } + Method(_L0A) { + } + Method(_L0B) { + } + Method(_L0C) { + } + Method(_L0D) { + } + Method(_L0E) { + } + Method(_L0F) { + } + } +} diff --git a/hw/i386/q35-acpi-dsdt.dsl b/hw/i386/q35-acpi-dsdt.dsl new file mode 100644 index 0000000..21c89b0 --- /dev/null +++ b/hw/i386/q35-acpi-dsdt.dsl @@ -0,0 +1,452 @@ +/* + * Bochs/QEMU ACPI DSDT ASL definition + * + * Copyright (c) 2006 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +/* + * Copyright (c) 2010 Isaku Yamahata + * yamahata at valinux co jp + * Based on acpi-dsdt.dsl, but heavily modified for q35 chipset. + */ + +ACPI_EXTRACT_ALL_CODE Q35AcpiDsdtAmlCode + +DefinitionBlock ( + "q35-acpi-dsdt.aml",// Output Filename + "DSDT", // Signature + 0x01, // DSDT Compliance Revision + "BXPC", // OEMID + "BXDSDT", // TABLE ID + 0x2 // OEM Revision + ) +{ + +#include "acpi-dsdt-dbug.dsl" + + Scope(_SB) { + OperationRegion(PCST, SystemIO, 0xae00, 0x0c) + OperationRegion(PCSB, SystemIO, 0xae0c, 0x01) + Field(PCSB, AnyAcc, NoLock, WriteAsZeros) { + PCIB, 8, + } + } + + +/**************************************************************** + * PCI Bus definition + ****************************************************************/ + + Scope(_SB) { + Device(PCI0) { + Name(_HID, EisaId("PNP0A08")) + Name(_CID, EisaId("PNP0A03")) + Name(_ADR, 0x00) + Name(_UID, 1) + + // _OSC: based on sample of ACPI3.0b spec + Name(SUPP, 0) // PCI _OSC Support Field value + Name(CTRL, 0) // PCI _OSC Control Field value + Method(_OSC, 4) { + // Create DWORD-addressable fields from the Capabilities Buffer + CreateDWordField(Arg3, 0, CDW1) + + // Check for proper UUID + If (LEqual(Arg0, ToUUID("33DB4D5B-1FF7-401C-9657-7441C03DD766"))) { + // Create DWORD-addressable fields from the Capabilities Buffer + CreateDWordField(Arg3, 4, CDW2) + CreateDWordField(Arg3, 8, CDW3) + + // Save Capabilities DWORD2 & 3 + Store(CDW2, SUPP) + Store(CDW3, CTRL) + + // Always allow native PME, AER (no dependencies) + // Never allow SHPC (no SHPC controller in this system) + And(CTRL, 0x1D, CTRL) + +#if 0 // For now, nothing to do + If (Not(And(CDW1, 1))) { // Query flag clear? + // Disable GPEs for features granted native control. + If (And(CTRL, 0x01)) { // Hot plug control granted? + Store(0, HPCE) // clear the hot plug SCI enable bit + Store(1, HPCS) // clear the hot plug SCI status bit + } + If (And(CTRL, 0x04)) { // PME control granted? + Store(0, PMCE) // clear the PME SCI enable bit + Store(1, PMCS) // clear the PME SCI status bit + } + If (And(CTRL, 0x10)) { // OS restoring PCI Express cap structure? + // Set status to not restore PCI Express cap structure + // upon resume from S3 + Store(1, S3CR) + } + } +#endif + If (LNotEqual(Arg1, One)) { + // Unknown revision + Or(CDW1, 0x08, CDW1) + } + If (LNotEqual(CDW3, CTRL)) { + // Capabilities bits were masked + Or(CDW1, 0x10, CDW1) + } + // Update DWORD3 in the buffer + Store(CTRL, CDW3) + } Else { + Or(CDW1, 4, CDW1) // Unrecognized UUID + } + Return (Arg3) + } + } + } + +#include "acpi-dsdt-pci-crs.dsl" +#include "acpi-dsdt-hpet.dsl" + + +/**************************************************************** + * VGA + ****************************************************************/ + + Scope(_SB.PCI0) { + Device(VGA) { + Name(_ADR, 0x00010000) + Method(_S1D, 0, NotSerialized) { + Return (0x00) + } + Method(_S2D, 0, NotSerialized) { + Return (0x00) + } + Method(_S3D, 0, NotSerialized) { + Return (0x00) + } + } + } + + +/**************************************************************** + * LPC ISA bridge + ****************************************************************/ + + Scope(_SB.PCI0) { + /* PCI D31:f0 LPC ISA bridge */ + Device(ISA) { + /* PCI D31:f0 */ + Name(_ADR, 0x001f0000) + + /* ICH9 PCI to ISA irq remapping */ + OperationRegion(PIRQ, PCI_Config, 0x60, 0x0C) + + OperationRegion(LPCD, PCI_Config, 0x80, 0x2) + Field(LPCD, AnyAcc, NoLock, Preserve) { + COMA, 3, + , 1, + COMB, 3, + + Offset(0x01), + LPTD, 2, + , 2, + FDCD, 2 + } + OperationRegion(LPCE, PCI_Config, 0x82, 0x2) + Field(LPCE, AnyAcc, NoLock, Preserve) { + CAEN, 1, + CBEN, 1, + LPEN, 1, + FDEN, 1 + } + } + } + +#include "acpi-dsdt-isa.dsl" + + +/**************************************************************** + * PCI IRQs + ****************************************************************/ + + /* Zero => PIC mode, One => APIC Mode */ + Name(\PICF, Zero) + Method(_PIC, 1, NotSerialized) { + Store(Arg0, \PICF) + } + + Scope(_SB) { + Scope(PCI0) { +#define prt_slot_lnk(nr, lnk0, lnk1, lnk2, lnk3) \ + Package() { nr##ffff, 0, lnk0, 0 }, \ + Package() { nr##ffff, 1, lnk1, 0 }, \ + Package() { nr##ffff, 2, lnk2, 0 }, \ + Package() { nr##ffff, 3, lnk3, 0 } + +#define prt_slot_lnkA(nr) prt_slot_lnk(nr, LNKA, LNKB, LNKC, LNKD) +#define prt_slot_lnkB(nr) prt_slot_lnk(nr, LNKB, LNKC, LNKD, LNKA) +#define prt_slot_lnkC(nr) prt_slot_lnk(nr, LNKC, LNKD, LNKA, LNKB) +#define prt_slot_lnkD(nr) prt_slot_lnk(nr, LNKD, LNKA, LNKB, LNKC) + +#define prt_slot_lnkE(nr) prt_slot_lnk(nr, LNKE, LNKF, LNKG, LNKH) +#define prt_slot_lnkF(nr) prt_slot_lnk(nr, LNKF, LNKG, LNKH, LNKE) +#define prt_slot_lnkG(nr) prt_slot_lnk(nr, LNKG, LNKH, LNKE, LNKF) +#define prt_slot_lnkH(nr) prt_slot_lnk(nr, LNKH, LNKE, LNKF, LNKG) + + Name(PRTP, package() { + prt_slot_lnkE(0x0000), + prt_slot_lnkF(0x0001), + prt_slot_lnkG(0x0002), + prt_slot_lnkH(0x0003), + prt_slot_lnkE(0x0004), + prt_slot_lnkF(0x0005), + prt_slot_lnkG(0x0006), + prt_slot_lnkH(0x0007), + prt_slot_lnkE(0x0008), + prt_slot_lnkF(0x0009), + prt_slot_lnkG(0x000a), + prt_slot_lnkH(0x000b), + prt_slot_lnkE(0x000c), + prt_slot_lnkF(0x000d), + prt_slot_lnkG(0x000e), + prt_slot_lnkH(0x000f), + prt_slot_lnkE(0x0010), + prt_slot_lnkF(0x0011), + prt_slot_lnkG(0x0012), + prt_slot_lnkH(0x0013), + prt_slot_lnkE(0x0014), + prt_slot_lnkF(0x0015), + prt_slot_lnkG(0x0016), + prt_slot_lnkH(0x0017), + prt_slot_lnkE(0x0018), + + /* INTA -> PIRQA for slot 25 - 31 + see the default value of D<N>IR */ + prt_slot_lnkA(0x0019), + prt_slot_lnkA(0x001a), + prt_slot_lnkA(0x001b), + prt_slot_lnkA(0x001c), + prt_slot_lnkA(0x001d), + + /* PCIe->PCI bridge. use PIRQ[E-H] */ + prt_slot_lnkE(0x001e), + + prt_slot_lnkA(0x001f) + }) + +#define prt_slot_gsi(nr, gsi0, gsi1, gsi2, gsi3) \ + Package() { nr##ffff, 0, gsi0, 0 }, \ + Package() { nr##ffff, 1, gsi1, 0 }, \ + Package() { nr##ffff, 2, gsi2, 0 }, \ + Package() { nr##ffff, 3, gsi3, 0 } + +#define prt_slot_gsiA(nr) prt_slot_gsi(nr, GSIA, GSIB, GSIC, GSID) +#define prt_slot_gsiB(nr) prt_slot_gsi(nr, GSIB, GSIC, GSID, GSIA) +#define prt_slot_gsiC(nr) prt_slot_gsi(nr, GSIC, GSID, GSIA, GSIB) +#define prt_slot_gsiD(nr) prt_slot_gsi(nr, GSID, GSIA, GSIB, GSIC) + +#define prt_slot_gsiE(nr) prt_slot_gsi(nr, GSIE, GSIF, GSIG, GSIH) +#define prt_slot_gsiF(nr) prt_slot_gsi(nr, GSIF, GSIG, GSIH, GSIE) +#define prt_slot_gsiG(nr) prt_slot_gsi(nr, GSIG, GSIH, GSIE, GSIF) +#define prt_slot_gsiH(nr) prt_slot_gsi(nr, GSIH, GSIE, GSIF, GSIG) + + Name(PRTA, package() { + prt_slot_gsiE(0x0000), + prt_slot_gsiF(0x0001), + prt_slot_gsiG(0x0002), + prt_slot_gsiH(0x0003), + prt_slot_gsiE(0x0004), + prt_slot_gsiF(0x0005), + prt_slot_gsiG(0x0006), + prt_slot_gsiH(0x0007), + prt_slot_gsiE(0x0008), + prt_slot_gsiF(0x0009), + prt_slot_gsiG(0x000a), + prt_slot_gsiH(0x000b), + prt_slot_gsiE(0x000c), + prt_slot_gsiF(0x000d), + prt_slot_gsiG(0x000e), + prt_slot_gsiH(0x000f), + prt_slot_gsiE(0x0010), + prt_slot_gsiF(0x0011), + prt_slot_gsiG(0x0012), + prt_slot_gsiH(0x0013), + prt_slot_gsiE(0x0014), + prt_slot_gsiF(0x0015), + prt_slot_gsiG(0x0016), + prt_slot_gsiH(0x0017), + prt_slot_gsiE(0x0018), + + /* INTA -> PIRQA for slot 25 - 31, but 30 + see the default value of D<N>IR */ + prt_slot_gsiA(0x0019), + prt_slot_gsiA(0x001a), + prt_slot_gsiA(0x001b), + prt_slot_gsiA(0x001c), + prt_slot_gsiA(0x001d), + + /* PCIe->PCI bridge. use PIRQ[E-H] */ + prt_slot_gsiE(0x001e), + + prt_slot_gsiA(0x001f) + }) + + Method(_PRT, 0, NotSerialized) { + /* PCI IRQ routing table, example from ACPI 2.0a specification, + section 6.2.8.1 */ + /* Note: we provide the same info as the PCI routing + table of the Bochs BIOS */ + If (LEqual(\PICF, Zero)) { + Return (PRTP) + } Else { + Return (PRTA) + } + } + } + + Field(PCI0.ISA.PIRQ, ByteAcc, NoLock, Preserve) { + PRQA, 8, + PRQB, 8, + PRQC, 8, + PRQD, 8, + + Offset(0x08), + PRQE, 8, + PRQF, 8, + PRQG, 8, + PRQH, 8 + } + + Method(IQST, 1, NotSerialized) { + // _STA method - get status + If (And(0x80, Arg0)) { + Return (0x09) + } + Return (0x0B) + } + Method(IQCR, 1, NotSerialized) { + // _CRS method - get current settings + Name(PRR0, ResourceTemplate() { + Interrupt(, Level, ActiveHigh, Shared) { 0 } + }) + CreateDWordField(PRR0, 0x05, PRRI) + Store(And(Arg0, 0x0F), PRRI) + Return (PRR0) + } + +#define define_link(link, uid, reg) \ + Device(link) { \ + Name(_HID, EISAID("PNP0C0F")) \ + Name(_UID, uid) \ + Name(_PRS, ResourceTemplate() { \ + Interrupt(, Level, ActiveHigh, Shared) { \ + 5, 10, 11 \ + } \ + }) \ + Method(_STA, 0, NotSerialized) { \ + Return (IQST(reg)) \ + } \ + Method(_DIS, 0, NotSerialized) { \ + Or(reg, 0x80, reg) \ + } \ + Method(_CRS, 0, NotSerialized) { \ + Return (IQCR(reg)) \ + } \ + Method(_SRS, 1, NotSerialized) { \ + CreateDWordField(Arg0, 0x05, PRRI) \ + Store(PRRI, reg) \ + } \ + } + + define_link(LNKA, 0, PRQA) + define_link(LNKB, 1, PRQB) + define_link(LNKC, 2, PRQC) + define_link(LNKD, 3, PRQD) + define_link(LNKE, 4, PRQE) + define_link(LNKF, 5, PRQF) + define_link(LNKG, 6, PRQG) + define_link(LNKH, 7, PRQH) + +#define define_gsi_link(link, uid, gsi) \ + Device(link) { \ + Name(_HID, EISAID("PNP0C0F")) \ + Name(_UID, uid) \ + Name(_PRS, ResourceTemplate() { \ + Interrupt(, Level, ActiveHigh, Shared) { \ + gsi \ + } \ + }) \ + Name(_CRS, ResourceTemplate() { \ + Interrupt(, Level, ActiveHigh, Shared) { \ + gsi \ + } \ + }) \ + Method(_SRS, 1, NotSerialized) { \ + } \ + } + + define_gsi_link(GSIA, 0, 0x10) + define_gsi_link(GSIB, 0, 0x11) + define_gsi_link(GSIC, 0, 0x12) + define_gsi_link(GSID, 0, 0x13) + define_gsi_link(GSIE, 0, 0x14) + define_gsi_link(GSIF, 0, 0x15) + define_gsi_link(GSIG, 0, 0x16) + define_gsi_link(GSIH, 0, 0x17) + } + +#include "acpi-dsdt-cpu-hotplug.dsl" + + +/**************************************************************** + * General purpose events + ****************************************************************/ + + Scope(_GPE) { + Name(_HID, "ACPI0006") + + Method(_L00) { + } + Method(_L01) { + // CPU hotplug event + _SB.PRSC() + } + Method(_L02) { + } + Method(_L03) { + } + Method(_L04) { + } + Method(_L05) { + } + Method(_L06) { + } + Method(_L07) { + } + Method(_L08) { + } + Method(_L09) { + } + Method(_L0A) { + } + Method(_L0B) { + } + Method(_L0C) { + } + Method(_L0D) { + } + Method(_L0E) { + } + Method(_L0F) { + } + } +} diff --git a/hw/i386/ssdt-misc.dsl b/hw/i386/ssdt-misc.dsl new file mode 100644 index 0000000..ac11e96 --- /dev/null +++ b/hw/i386/ssdt-misc.dsl @@ -0,0 +1,73 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that 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/. + */ + +ACPI_EXTRACT_ALL_CODE ssdp_misc_aml + +DefinitionBlock ("ssdt-misc.aml", "SSDT", 0x01, "BXPC", "BXSSDTSUSP", 0x1) +{ + +/**************************************************************** + * PCI memory ranges + ****************************************************************/ + + Scope() { + ACPI_EXTRACT_NAME_DWORD_CONST acpi_pci32_start + Name(P0S, 0x12345678) + ACPI_EXTRACT_NAME_DWORD_CONST acpi_pci32_end + Name(P0E, 0x12345678) + ACPI_EXTRACT_NAME_BYTE_CONST acpi_pci64_valid + Name(P1V, 0x12) + ACPI_EXTRACT_NAME_BUFFER8 acpi_pci64_start + Name(P1S, Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }) + ACPI_EXTRACT_NAME_BUFFER8 acpi_pci64_end + Name(P1E, Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }) + ACPI_EXTRACT_NAME_BUFFER8 acpi_pci64_length + Name(P1L, Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }) + } + + +/**************************************************************** + * Suspend + ****************************************************************/ + + Scope() { + /* + * S3 (suspend-to-ram), S4 (suspend-to-disk) and S5 (power-off) type codes: + * must match piix4 emulation. + */ + + ACPI_EXTRACT_NAME_STRING acpi_s3_name + Name(_S3, Package(0x04) { + One, /* PM1a_CNT.SLP_TYP */ + One, /* PM1b_CNT.SLP_TYP */ + Zero, /* reserved */ + Zero /* reserved */ + }) + ACPI_EXTRACT_NAME_STRING acpi_s4_name + ACPI_EXTRACT_PKG_START acpi_s4_pkg + Name(_S4, Package(0x04) { + 0x2, /* PM1a_CNT.SLP_TYP */ + 0x2, /* PM1b_CNT.SLP_TYP */ + Zero, /* reserved */ + Zero /* reserved */ + }) + Name(_S5, Package(0x04) { + Zero, /* PM1a_CNT.SLP_TYP */ + Zero, /* PM1b_CNT.SLP_TYP */ + Zero, /* reserved */ + Zero /* reserved */ + }) + } +} diff --git a/hw/i386/ssdt-pcihp.dsl b/hw/i386/ssdt-pcihp.dsl new file mode 100644 index 0000000..d29a5b9 --- /dev/null +++ b/hw/i386/ssdt-pcihp.dsl @@ -0,0 +1,51 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that 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/. + */ + +ACPI_EXTRACT_ALL_CODE ssdp_pcihp_aml + +DefinitionBlock ("ssdt-pcihp.aml", "SSDT", 0x01, "BXPC", "BXSSDTPCIHP", 0x1) +{ + +/**************************************************************** + * PCI hotplug + ****************************************************************/ + + /* Objects supplied by DSDT */ + External(_SB.PCI0, DeviceObj) + External(_SB.PCI0.PCEJ, MethodObj) + + Scope(_SB.PCI0) { + + /* Bulk generated PCI hotplug devices */ + ACPI_EXTRACT_DEVICE_START ssdt_pcihp_start + ACPI_EXTRACT_DEVICE_END ssdt_pcihp_end + ACPI_EXTRACT_DEVICE_STRING ssdt_pcihp_name + + // Method _EJ0 can be patched by BIOS to EJ0_ + // at runtime, if the slot is detected to not support hotplug. + // Extract the offset of the address dword and the + // _EJ0 name to allow this patching. + Device(SAA) { + ACPI_EXTRACT_NAME_BYTE_CONST ssdt_pcihp_id + Name(_SUN, 0xAA) + ACPI_EXTRACT_NAME_DWORD_CONST ssdt_pcihp_adr + Name(_ADR, 0xAA0000) + ACPI_EXTRACT_METHOD_STRING ssdt_pcihp_ej0 + Method(_EJ0, 1) { + Return (PCEJ(_SUN)) + } + } + } +} diff --git a/hw/i386/ssdt-proc.dsl b/hw/i386/ssdt-proc.dsl new file mode 100644 index 0000000..58333c7 --- /dev/null +++ b/hw/i386/ssdt-proc.dsl @@ -0,0 +1,63 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that 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/. + */ + +/* This file is the basis for the ssdt table generated in src/acpi.c. + * It defines the contents of the per-cpu Processor() object. At + * runtime, a dynamically generated SSDT will contain one copy of this + * AML snippet for every possible cpu in the system. The objects will + * be placed in the _SB_ namespace. + * + * In addition to the aml code generated from this file, the + * src/acpi.c file creates a NTFY method with an entry for each cpu: + * Method(NTFY, 2) { + * If (LEqual(Arg0, 0x00)) { Notify(CP00, Arg1) } + * If (LEqual(Arg0, 0x01)) { Notify(CP01, Arg1) } + * ... + * } + * and a CPON array with the list of active and inactive cpus: + * Name(CPON, Package() { One, One, ..., Zero, Zero, ... }) + */ + +ACPI_EXTRACT_ALL_CODE ssdp_proc_aml + +DefinitionBlock ("ssdt-proc.aml", "SSDT", 0x01, "BXPC", "BXSSDT", 0x1) +{ + ACPI_EXTRACT_PROCESSOR_START ssdt_proc_start + ACPI_EXTRACT_PROCESSOR_END ssdt_proc_end + ACPI_EXTRACT_PROCESSOR_STRING ssdt_proc_name + Processor(CPAA, 0xAA, 0x0000b010, 0x06) { + ACPI_EXTRACT_NAME_BYTE_CONST ssdt_proc_id + Name(ID, 0xAA) +/* + * The src/acpi.c code requires the above ACP_EXTRACT tags so that it can update + * CPAA and 0xAA with the appropriate CPU id (see + * SD_OFFSET_CPUHEX/CPUID1/CPUID2). Don't change the above without + * also updating the C code. + */ + Name(_HID, "ACPI0007") + External(CPMA, MethodObj) + External(CPST, MethodObj) + External(CPEJ, MethodObj) + Method(_MAT, 0) { + Return (CPMA(ID)) + } + Method(_STA, 0) { + Return (CPST(ID)) + } + Method(_EJ0, 1, NotSerialized) { + CPEJ(ID, Arg0) + } + } +} diff --git a/scripts/acpi_extract.py b/scripts/acpi_extract.py new file mode 100755 index 0000000..fbedc6b --- /dev/null +++ b/scripts/acpi_extract.py @@ -0,0 +1,362 @@ +#!/usr/bin/python +# Copyright (C) 2011 Red Hat, Inc., Michael S. Tsirkin mst@redhat.com +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that 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/. + +# Process mixed ASL/AML listing (.lst file) produced by iasl -l +# Locate and execute ACPI_EXTRACT directives, output offset info +# +# Documentation of ACPI_EXTRACT_* directive tags: +# +# These directive tags output offset information from AML for BIOS runtime +# table generation. +# Each directive is of the form: +# ACPI_EXTRACT_<TYPE> <array_name> <Operator> (...) +# and causes the extractor to create an array +# named <array_name> with offset, in the generated AML, +# of an object of a given type in the following <Operator>. +# +# A directive must fit on a single code line. +# +# Object type in AML is verified, a mismatch causes a build failure. +# +# Directives and operators currently supported are: +# ACPI_EXTRACT_NAME_DWORD_CONST - extract a Dword Const object from Name() +# ACPI_EXTRACT_NAME_WORD_CONST - extract a Word Const object from Name() +# ACPI_EXTRACT_NAME_BYTE_CONST - extract a Byte Const object from Name() +# ACPI_EXTRACT_METHOD_STRING - extract a NameString from Method() +# ACPI_EXTRACT_NAME_STRING - extract a NameString from Name() +# ACPI_EXTRACT_PROCESSOR_START - start of Processor() block +# ACPI_EXTRACT_PROCESSOR_STRING - extract a NameString from Processor() +# ACPI_EXTRACT_PROCESSOR_END - offset at last byte of Processor() + 1 +# ACPI_EXTRACT_PKG_START - start of Package block +# +# ACPI_EXTRACT_ALL_CODE - create an array storing the generated AML bytecode +# +# ACPI_EXTRACT is not allowed anywhere else in code, except in comments. + +import re; +import sys; +import fileinput; + +aml = [] +asl = [] +output = {} +debug = "" + +class asl_line: + line = None + lineno = None + aml_offset = None + +def die(diag): + sys.stderr.write("Error: %s; %s\n" % (diag, debug)) + sys.exit(1) + +#Store an ASL command, matching AML offset, and input line (for debugging) +def add_asl(lineno, line): + l = asl_line() + l.line = line + l.lineno = lineno + l.aml_offset = len(aml) + asl.append(l) + +#Store an AML byte sequence +#Verify that offset output by iasl matches # of bytes so far +def add_aml(offset, line): + o = int(offset, 16); + # Sanity check: offset must match size of code so far + if (o != len(aml)): + die("Offset 0x%x != 0x%x" % (o, len(aml))) + # Strip any trailing dots and ASCII dump after " + line = re.sub(r'\s*.*\s*".*$',"", line) + # Strip traling whitespace + line = re.sub(r'\s+$',"", line) + # Strip leading whitespace + line = re.sub(r'^\s+',"", line) + # Split on whitespace + code = re.split(r'\s+', line) + for c in code: + # Require a legal hex number, two digits + if (not(re.search(r'^[0-9A-Fa-f][0-9A-Fa-f]$', c))): + die("Unexpected octet %s" % c); + aml.append(int(c, 16)); + +# Process aml bytecode array, decoding AML +def aml_pkglen_bytes(offset): + # PkgLength can be multibyte. Bits 8-7 give the # of extra bytes. + pkglenbytes = aml[offset] >> 6; + return pkglenbytes + 1 + +def aml_pkglen(offset): + pkgstart = offset + pkglenbytes = aml_pkglen_bytes(offset) + pkglen = aml[offset] & 0x3F + # If multibyte, first nibble only uses bits 0-3 + if ((pkglenbytes > 1) and (pkglen & 0x30)): + die("PkgLen bytes 0x%x but first nibble 0x%x expected 0x0X" % + (pkglen, pkglen)) + offset += 1 + pkglenbytes -= 1 + for i in range(pkglenbytes): + pkglen |= aml[offset + i] << (i * 8 + 4) + if (len(aml) < pkgstart + pkglen): + die("PckgLen 0x%x at offset 0x%x exceeds AML size 0x%x" % + (pkglen, offset, len(aml))) + return pkglen + +# Given method offset, find its NameString offset +def aml_method_string(offset): + #0x14 MethodOp PkgLength NameString MethodFlags TermList + if (aml[offset] != 0x14): + die( "Method offset 0x%x: expected 0x14 actual 0x%x" % + (offset, aml[offset])); + offset += 1; + pkglenbytes = aml_pkglen_bytes(offset) + offset += pkglenbytes; + return offset; + +# Given name offset, find its NameString offset +def aml_name_string(offset): + #0x08 NameOp NameString DataRef + if (aml[offset] != 0x08): + die( "Name offset 0x%x: expected 0x08 actual 0x%x" % + (offset, aml[offset])); + offset += 1 + # Block Name Modifier. Skip it. + if (aml[offset] == 0x5c or aml[offset] == 0x5e): + offset += 1 + return offset; + +# Given data offset, find 8 byte buffer offset +def aml_data_buffer8(offset): + #0x08 NameOp NameString DataRef + expect = [0x11, 0x0B, 0x0A, 0x08] + if (aml[offset:offset+4] != expect): + die( "Name offset 0x%x: expected %s actual %s" % + (offset, aml[offset:offset+4], expect)) + return offset + len(expect) + +# Given data offset, find dword const offset +def aml_data_dword_const(offset): + #0x08 NameOp NameString DataRef + if (aml[offset] != 0x0C): + die( "Name offset 0x%x: expected 0x0C actual 0x%x" % + (offset, aml[offset])); + return offset + 1; + +# Given data offset, find word const offset +def aml_data_word_const(offset): + #0x08 NameOp NameString DataRef + if (aml[offset] != 0x0B): + die( "Name offset 0x%x: expected 0x0B actual 0x%x" % + (offset, aml[offset])); + return offset + 1; + +# Given data offset, find byte const offset +def aml_data_byte_const(offset): + #0x08 NameOp NameString DataRef + if (aml[offset] != 0x0A): + die( "Name offset 0x%x: expected 0x0A actual 0x%x" % + (offset, aml[offset])); + return offset + 1; + +# Find name'd buffer8 +def aml_name_buffer8(offset): + return aml_data_buffer8(aml_name_string(offset) + 4) + +# Given name offset, find dword const offset +def aml_name_dword_const(offset): + return aml_data_dword_const(aml_name_string(offset) + 4) + +# Given name offset, find word const offset +def aml_name_word_const(offset): + return aml_data_word_const(aml_name_string(offset) + 4) + +# Given name offset, find byte const offset +def aml_name_byte_const(offset): + return aml_data_byte_const(aml_name_string(offset) + 4) + +def aml_device_start(offset): + #0x5B 0x82 DeviceOp PkgLength NameString + if ((aml[offset] != 0x5B) or (aml[offset + 1] != 0x82)): + die( "Name offset 0x%x: expected 0x5B 0x82 actual 0x%x 0x%x" % + (offset, aml[offset], aml[offset + 1])); + return offset + +def aml_device_string(offset): + #0x5B 0x82 DeviceOp PkgLength NameString + start = aml_device_start(offset) + offset += 2 + pkglenbytes = aml_pkglen_bytes(offset) + offset += pkglenbytes + return offset + +def aml_device_end(offset): + start = aml_device_start(offset) + offset += 2 + pkglenbytes = aml_pkglen_bytes(offset) + pkglen = aml_pkglen(offset) + return offset + pkglen + +def aml_processor_start(offset): + #0x5B 0x83 ProcessorOp PkgLength NameString ProcID + if ((aml[offset] != 0x5B) or (aml[offset + 1] != 0x83)): + die( "Name offset 0x%x: expected 0x5B 0x83 actual 0x%x 0x%x" % + (offset, aml[offset], aml[offset + 1])); + return offset + +def aml_processor_string(offset): + #0x5B 0x83 ProcessorOp PkgLength NameString ProcID + start = aml_processor_start(offset) + offset += 2 + pkglenbytes = aml_pkglen_bytes(offset) + offset += pkglenbytes + return offset + +def aml_processor_end(offset): + start = aml_processor_start(offset) + offset += 2 + pkglenbytes = aml_pkglen_bytes(offset) + pkglen = aml_pkglen(offset) + return offset + pkglen + +def aml_package_start(offset): + offset = aml_name_string(offset) + 4 + # 0x12 PkgLength NumElements PackageElementList + if (aml[offset] != 0x12): + die( "Name offset 0x%x: expected 0x12 actual 0x%x" % + (offset, aml[offset])); + offset += 1 + return offset + aml_pkglen_bytes(offset) + 1 + +lineno = 0 +for line in fileinput.input(): + # Strip trailing newline + line = line.rstrip(); + # line number and debug string to output in case of errors + lineno = lineno + 1 + debug = "input line %d: %s" % (lineno, line) + #ASL listing: space, then line#, then ...., then code + pasl = re.compile('^\s+([0-9]+)(:\s\s|....)\s*') + m = pasl.search(line) + if (m): + add_asl(lineno, pasl.sub("", line)); + # AML listing: offset in hex, then ...., then code + paml = re.compile('^([0-9A-Fa-f]+)(:\s\s|....)\s*') + m = paml.search(line) + if (m): + add_aml(m.group(1), paml.sub("", line)) + +# Now go over code +# Track AML offset of a previous non-empty ASL command +prev_aml_offset = -1 +for i in range(len(asl)): + debug = "input line %d: %s" % (asl[i].lineno, asl[i].line) + + l = asl[i].line + + # skip if not an extract directive + a = len(re.findall(r'ACPI_EXTRACT', l)) + if (not a): + # If not empty, store AML offset. Will be used for sanity checks + # IASL seems to put {}. at random places in the listing. + # Ignore any non-words for the purpose of this test. + m = re.search(r'\w+', l) + if (m): + prev_aml_offset = asl[i].aml_offset + continue + + if (a > 1): + die("Expected at most one ACPI_EXTRACT per line, actual %d" % a) + + mext = re.search(r''' + ^\s* # leading whitespace + /*\s* # start C comment + (ACPI_EXTRACT_\w+) # directive: group(1) + \s+ # whitspace separates directive from array name + (\w+) # array name: group(2) + \s**/ # end of C comment + \s*$ # trailing whitespace + ''', l, re.VERBOSE) + if (not mext): + die("Stray ACPI_EXTRACT in input") + + # previous command must have produced some AML, + # otherwise we are in a middle of a block + if (prev_aml_offset == asl[i].aml_offset): + die("ACPI_EXTRACT directive in the middle of a block") + + directive = mext.group(1) + array = mext.group(2) + offset = asl[i].aml_offset + + if (directive == "ACPI_EXTRACT_ALL_CODE"): + if array in output: + die("%s directive used more than once" % directive) + output[array] = aml + continue + if (directive == "ACPI_EXTRACT_NAME_BUFFER8"): + offset = aml_name_buffer8(offset) + elif (directive == "ACPI_EXTRACT_NAME_DWORD_CONST"): + offset = aml_name_dword_const(offset) + elif (directive == "ACPI_EXTRACT_NAME_WORD_CONST"): + offset = aml_name_word_const(offset) + elif (directive == "ACPI_EXTRACT_NAME_BYTE_CONST"): + offset = aml_name_byte_const(offset) + elif (directive == "ACPI_EXTRACT_NAME_STRING"): + offset = aml_name_string(offset) + elif (directive == "ACPI_EXTRACT_METHOD_STRING"): + offset = aml_method_string(offset) + elif (directive == "ACPI_EXTRACT_DEVICE_START"): + offset = aml_device_start(offset) + elif (directive == "ACPI_EXTRACT_DEVICE_STRING"): + offset = aml_device_string(offset) + elif (directive == "ACPI_EXTRACT_DEVICE_END"): + offset = aml_device_end(offset) + elif (directive == "ACPI_EXTRACT_PROCESSOR_START"): + offset = aml_processor_start(offset) + elif (directive == "ACPI_EXTRACT_PROCESSOR_STRING"): + offset = aml_processor_string(offset) + elif (directive == "ACPI_EXTRACT_PROCESSOR_END"): + offset = aml_processor_end(offset) + elif (directive == "ACPI_EXTRACT_PKG_START"): + offset = aml_package_start(offset) + else: + die("Unsupported directive %s" % directive) + + if array not in output: + output[array] = [] + output[array].append(offset) + +debug = "at end of file" + +def get_value_type(maxvalue): + #Use type large enough to fit the table + if (maxvalue >= 0x10000): + return "int" + elif (maxvalue >= 0x100): + return "short" + else: + return "char" + +# Pretty print output +for array in output.keys(): + otype = get_value_type(max(output[array])) + odata = [] + for value in output[array]: + odata.append("0x%x" % value) + sys.stdout.write("static unsigned %s %s[] = {\n" % (otype, array)) + sys.stdout.write(",\n".join(odata)) + sys.stdout.write('\n};\n'); diff --git a/scripts/acpi_extract_preprocess.py b/scripts/acpi_extract_preprocess.py new file mode 100755 index 0000000..c986160 --- /dev/null +++ b/scripts/acpi_extract_preprocess.py @@ -0,0 +1,52 @@ +#!/usr/bin/python +# Copyright (C) 2011 Red Hat, Inc., Michael S. Tsirkin mst@redhat.com +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that 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/. + +# Read a preprocessed ASL listing and put each ACPI_EXTRACT +# directive in a comment, to make iasl skip it. +# We also put each directive on a new line, the machinery +# in tools/acpi_extract.py requires this. + +import re; +import sys; +import fileinput; + +def die(diag): + sys.stderr.write("Error: %s\n" % (diag)) + sys.exit(1) + +# Note: () around pattern make split return matched string as part of list +psplit = re.compile(r''' ( + \b # At word boundary + ACPI_EXTRACT_\w+ # directive + \s+ # some whitespace + \w+ # array name + )''', re.VERBOSE); + +lineno = 0 +for line in fileinput.input(): + # line number and debug string to output in case of errors + lineno = lineno + 1 + debug = "input line %d: %s" % (lineno, line.rstrip()) + + s = psplit.split(line); + # The way split works, each odd item is the matching ACPI_EXTRACT directive. + # Put each in a comment, and on a line by itself. + for i in range(len(s)): + if (i % 2): + sys.stdout.write("\n/* %s */\n" % s[i]) + else: + sys.stdout.write(s[i]) +
Detect presence of IASL compiler and use it to process ASL source. If not there, use pre-compiled files in-tree. Add script to update the in-tree files.
Signed-off-by: Michael S. Tsirkin mst@redhat.com --- configure | 9 ++++++++- hw/i386/Makefile.objs | 22 ++++++++++++++++++++++ scripts/update-acpi.sh | 4 ++++ 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 scripts/update-acpi.sh
diff --git a/configure b/configure index 9439f1c..6255a83 100755 --- a/configure +++ b/configure @@ -119,6 +119,7 @@ path_of() { # default parameters source_path=`dirname "$0"` cpu="" +iasl="iasl" interp_prefix="/usr/gnemul/qemu-%M" static="no" cross_prefix="" @@ -249,6 +250,8 @@ for opt do ;; --cc=*) CC="$optarg" ;; + --iasl=*) iasl="$optarg" + ;; --source-path=*) source_path="$optarg" ;; --cpu=*) cpu="$optarg" @@ -1062,6 +1065,7 @@ echo "Advanced options (experts only):" echo " --source-path=PATH path of source code [$source_path]" echo " --cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix]" echo " --cc=CC use C compiler CC [$cc]" +echo " --iasl=IASL use ACPI compiler IASL [$iasl]" echo " --host-cc=CC use C compiler CC [$host_cc] for code run at" echo " build time" echo " --objcc=OBJCC use Objective-C compiler OBJCC [$objcc]" @@ -4053,6 +4057,9 @@ else fi echo "PYTHON=$python" >> $config_host_mak echo "CC=$cc" >> $config_host_mak +if $iasl -h > /dev/null 2>&1; then + echo "IASL=$iasl" >> $config_host_mak +fi echo "CC_I386=$cc_i386" >> $config_host_mak echo "HOST_CC=$host_cc" >> $config_host_mak echo "OBJCC=$objcc" >> $config_host_mak @@ -4541,7 +4548,7 @@ for rom in seabios vgabios ; do echo "BCC=bcc" >> $config_mak echo "CPP=$cpp" >> $config_mak echo "OBJCOPY=objcopy" >> $config_mak - echo "IASL=iasl" >> $config_mak + echo "IASL=$iasl" >> $config_mak echo "LD=$ld" >> $config_mak done
diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs index 205d22e..013d250 100644 --- a/hw/i386/Makefile.objs +++ b/hw/i386/Makefile.objs @@ -4,3 +4,25 @@ obj-y += pc.o pc_piix.o pc_q35.o obj-$(CONFIG_XEN) += xen_domainbuild.o xen_machine_pv.o
obj-y += kvmvapic.o + +iasl-option=$(shell if test -z "`$(1) $(2) 2>&1 > /dev/null`" \ + ; then echo "$(2)"; else echo "$(3)"; fi ;) + +ifdef IASL +#IASL Present. Generate hex files from .dsl +hw/i386/%.hex: $(SRC_PATH)/hw/i386/%.dsl $(SRC_PATH)/scripts/acpi_extract_preprocess.py $(SRC_PATH)/scripts/acpi_extract.py + $(call quiet-command, cpp -P $< -o $*.dsl.i.orig, " CPP $(TARGET_DIR)$*.dsl.i.orig") + $(call quiet-command, $(PYTHON) $(SRC_PATH)/scripts/acpi_extract_preprocess.py $*.dsl.i.orig > $*.dsl.i, " ACPI_PREPROCESS $(TARGET_DIR)$*.dsl.i") + $(call quiet-command, $(IASL) $(call iasl-option,$(IASL),-Pn,) -vs -l -tc -p $* $*.dsl.i $(if $(V), , > /dev/null) 2>&1 ," IASL $(TARGET_DIR)$*.dsl.i") + $(call quiet-command, $(SRC_PATH)/scripts/acpi_extract.py $*.lst > $*.off, " ACPI_EXTRACT $(TARGET_DIR)$*.off") + $(call quiet-command, cat $*.off > $@, " CAT $(TARGET_DIR)$@") +else +#IASL Not present. Restore pre-generated hex files. +hw/i386/%.hex: $(SRC_PATH)/hw/i386/%.hex.generated + $(call quiet-command, cp -f $< $@, " CP $(TARGET_DIR)$@") +endif + +.PHONY: cleanhex +cleanhex: + rm -f hw/i386/*hex +clean: cleanhex diff --git a/scripts/update-acpi.sh b/scripts/update-acpi.sh new file mode 100644 index 0000000..b5f05ff --- /dev/null +++ b/scripts/update-acpi.sh @@ -0,0 +1,4 @@ +cd x86_64-softmmu +for file in hw/i386/*.hex; do + cp -f $file ../$file.generated +done
Add pre-compiled ASL files. Useful for systems that do not have IASL.
Signed-off-by: Michael S. Tsirkin mst@redhat.com --- hw/i386/acpi-dsdt.hex.generated | 4409 +++++++++++++++++++++ hw/i386/q35-acpi-dsdt.hex.generated | 7346 +++++++++++++++++++++++++++++++++++ hw/i386/ssdt-misc.hex.generated | 190 + hw/i386/ssdt-pcihp.hex.generated | 108 + hw/i386/ssdt-proc.hex.generated | 134 + 5 files changed, 12187 insertions(+) create mode 100644 hw/i386/acpi-dsdt.hex.generated create mode 100644 hw/i386/q35-acpi-dsdt.hex.generated create mode 100644 hw/i386/ssdt-misc.hex.generated create mode 100644 hw/i386/ssdt-pcihp.hex.generated create mode 100644 hw/i386/ssdt-proc.hex.generated
diff --git a/hw/i386/acpi-dsdt.hex.generated b/hw/i386/acpi-dsdt.hex.generated new file mode 100644 index 0000000..68cab3e --- /dev/null +++ b/hw/i386/acpi-dsdt.hex.generated @@ -0,0 +1,4409 @@ +static unsigned char AcpiDsdtAmlCode[] = { +0x44, +0x53, +0x44, +0x54, +0x37, +0x11, +0x0, +0x0, +0x1, +0xe1, +0x42, +0x58, +0x50, +0x43, +0x0, +0x0, +0x42, +0x58, +0x44, +0x53, +0x44, +0x54, +0x0, +0x0, +0x1, +0x0, +0x0, +0x0, +0x49, +0x4e, +0x54, +0x4c, +0x28, +0x5, +0x10, +0x20, +0x10, +0x49, +0x4, +0x5c, +0x0, +0x5b, +0x80, +0x44, +0x42, +0x47, +0x5f, +0x1, +0xb, +0x2, +0x4, +0x1, +0x5b, +0x81, +0xb, +0x44, +0x42, +0x47, +0x5f, +0x1, +0x44, +0x42, +0x47, +0x42, +0x8, +0x14, +0x2c, +0x44, +0x42, +0x55, +0x47, +0x1, +0x98, +0x68, +0x60, +0x96, +0x60, +0x60, +0x74, +0x87, +0x60, +0x1, +0x61, +0x70, +0x0, +0x62, +0xa2, +0x10, +0x95, +0x62, +0x61, +0x70, +0x83, +0x88, +0x60, +0x62, +0x0, +0x44, +0x42, +0x47, +0x42, +0x75, +0x62, +0x70, +0xa, +0xa, +0x44, +0x42, +0x47, +0x42, +0x10, +0x22, +0x5f, +0x53, +0x42, +0x5f, +0x5b, +0x82, +0x1b, +0x50, +0x43, +0x49, +0x30, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0xa, +0x3, +0x8, +0x5f, +0x41, +0x44, +0x52, +0x0, +0x8, +0x5f, +0x55, +0x49, +0x44, +0x1, +0x10, +0x4e, +0x15, +0x2e, +0x5f, +0x53, +0x42, +0x5f, +0x50, +0x43, +0x49, +0x30, +0x8, +0x43, +0x52, +0x45, +0x53, +0x11, +0x42, +0x7, +0xa, +0x6e, +0x88, +0xd, +0x0, +0x2, +0xc, +0x0, +0x0, +0x0, +0x0, +0x0, +0xff, +0x0, +0x0, +0x0, +0x0, +0x1, +0x47, +0x1, +0xf8, +0xc, +0xf8, +0xc, +0x1, +0x8, +0x88, +0xd, +0x0, +0x1, +0xc, +0x3, +0x0, +0x0, +0x0, +0x0, +0xf7, +0xc, +0x0, +0x0, +0xf8, +0xc, +0x88, +0xd, +0x0, +0x1, +0xc, +0x3, +0x0, +0x0, +0x0, +0xd, +0xff, +0xff, +0x0, +0x0, +0x0, +0xf3, +0x87, +0x17, +0x0, +0x0, +0xc, +0x3, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0xa, +0x0, +0xff, +0xff, +0xb, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x2, +0x0, +0x87, +0x17, +0x0, +0x0, +0xc, +0x1, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0xe0, +0xff, +0xff, +0xbf, +0xfe, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0xc0, +0x1e, +0x79, +0x0, +0x8, +0x43, +0x52, +0x36, +0x34, +0x11, +0x33, +0xa, +0x30, +0x8a, +0x2b, +0x0, +0x0, +0xc, +0x3, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x80, +0x0, +0x0, +0x0, +0xff, +0xff, +0xff, +0xff, +0xff, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x80, +0x0, +0x0, +0x0, +0x79, +0x0, +0x14, +0x41, +0xa, +0x5f, +0x43, +0x52, +0x53, +0x0, +0x8a, +0x43, +0x52, +0x45, +0x53, +0xa, +0x5c, +0x50, +0x53, +0x33, +0x32, +0x8a, +0x43, +0x52, +0x45, +0x53, +0xa, +0x60, +0x50, +0x45, +0x33, +0x32, +0x8a, +0x43, +0x52, +0x45, +0x53, +0xa, +0x68, +0x50, +0x4c, +0x33, +0x32, +0x70, +0x50, +0x30, +0x53, +0x5f, +0x50, +0x53, +0x33, +0x32, +0x70, +0x50, +0x30, +0x45, +0x5f, +0x50, +0x45, +0x33, +0x32, +0x70, +0x72, +0x74, +0x50, +0x30, +0x45, +0x5f, +0x50, +0x30, +0x53, +0x5f, +0x0, +0x1, +0x0, +0x50, +0x4c, +0x33, +0x32, +0xa0, +0xc, +0x93, +0x50, +0x31, +0x56, +0x5f, +0x0, +0xa4, +0x43, +0x52, +0x45, +0x53, +0x8f, +0x43, +0x52, +0x36, +0x34, +0xa, +0xe, +0x50, +0x53, +0x36, +0x34, +0x8f, +0x43, +0x52, +0x36, +0x34, +0xa, +0x16, +0x50, +0x45, +0x36, +0x34, +0x8f, +0x43, +0x52, +0x36, +0x34, +0xa, +0x26, +0x50, +0x4c, +0x36, +0x34, +0x70, +0x50, +0x31, +0x53, +0x5f, +0x50, +0x53, +0x36, +0x34, +0x70, +0x50, +0x31, +0x45, +0x5f, +0x50, +0x45, +0x36, +0x34, +0x70, +0x50, +0x31, +0x4c, +0x5f, +0x50, +0x4c, +0x36, +0x34, +0x84, +0x43, +0x52, +0x45, +0x53, +0x43, +0x52, +0x36, +0x34, +0x60, +0xa4, +0x60, +0x10, +0x4d, +0x8, +0x5f, +0x53, +0x42, +0x5f, +0x5b, +0x82, +0x45, +0x8, +0x48, +0x50, +0x45, +0x54, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0x1, +0x3, +0x8, +0x5f, +0x55, +0x49, +0x44, +0x0, +0x5b, +0x80, +0x48, +0x50, +0x54, +0x4d, +0x0, +0xc, +0x0, +0x0, +0xd0, +0xfe, +0xb, +0x0, +0x4, +0x5b, +0x81, +0x10, +0x48, +0x50, +0x54, +0x4d, +0x13, +0x56, +0x45, +0x4e, +0x44, +0x20, +0x50, +0x52, +0x44, +0x5f, +0x20, +0x14, +0x36, +0x5f, +0x53, +0x54, +0x41, +0x0, +0x70, +0x56, +0x45, +0x4e, +0x44, +0x60, +0x70, +0x50, +0x52, +0x44, +0x5f, +0x61, +0x7a, +0x60, +0xa, +0x10, +0x60, +0xa0, +0xc, +0x91, +0x93, +0x60, +0x0, +0x93, +0x60, +0xb, +0xff, +0xff, +0xa4, +0x0, +0xa0, +0xe, +0x91, +0x93, +0x61, +0x0, +0x94, +0x61, +0xc, +0x0, +0xe1, +0xf5, +0x5, +0xa4, +0x0, +0xa4, +0xa, +0xf, +0x8, +0x5f, +0x43, +0x52, +0x53, +0x11, +0x11, +0xa, +0xe, +0x86, +0x9, +0x0, +0x0, +0x0, +0x0, +0xd0, +0xfe, +0x0, +0x4, +0x0, +0x0, +0x79, +0x0, +0x10, +0x40, +0x6, +0x2e, +0x5f, +0x53, +0x42, +0x5f, +0x50, +0x43, +0x49, +0x30, +0x5b, +0x82, +0x43, +0x5, +0x56, +0x47, +0x41, +0x5f, +0x8, +0x5f, +0x41, +0x44, +0x52, +0xc, +0x0, +0x0, +0x2, +0x0, +0x5b, +0x80, +0x50, +0x43, +0x49, +0x43, +0x2, +0x0, +0xa, +0x4, +0x5b, +0x81, +0xb, +0x50, +0x43, +0x49, +0x43, +0x3, +0x56, +0x45, +0x4e, +0x44, +0x20, +0x14, +0x8, +0x5f, +0x53, +0x31, +0x44, +0x0, +0xa4, +0x0, +0x14, +0x8, +0x5f, +0x53, +0x32, +0x44, +0x0, +0xa4, +0x0, +0x14, +0x19, +0x5f, +0x53, +0x33, +0x44, +0x0, +0xa0, +0xe, +0x93, +0x56, +0x45, +0x4e, +0x44, +0xc, +0x36, +0x1b, +0x0, +0x1, +0xa4, +0xa, +0x3, +0xa1, +0x3, +0xa4, +0x0, +0x10, +0x25, +0x2e, +0x5f, +0x53, +0x42, +0x5f, +0x50, +0x43, +0x49, +0x30, +0x5b, +0x82, +0x19, +0x50, +0x58, +0x31, +0x33, +0x8, +0x5f, +0x41, +0x44, +0x52, +0xc, +0x3, +0x0, +0x1, +0x0, +0x5b, +0x80, +0x50, +0x31, +0x33, +0x43, +0x2, +0x0, +0xa, +0xff, +0x10, +0x46, +0x5, +0x2e, +0x5f, +0x53, +0x42, +0x5f, +0x50, +0x43, +0x49, +0x30, +0x5b, +0x82, +0x49, +0x4, +0x49, +0x53, +0x41, +0x5f, +0x8, +0x5f, +0x41, +0x44, +0x52, +0xc, +0x0, +0x0, +0x1, +0x0, +0x5b, +0x80, +0x50, +0x34, +0x30, +0x43, +0x2, +0xa, +0x60, +0xa, +0x4, +0x5b, +0x81, +0x26, +0x5e, +0x2e, +0x50, +0x58, +0x31, +0x33, +0x50, +0x31, +0x33, +0x43, +0x0, +0x0, +0x48, +0x2f, +0x0, +0x7, +0x4c, +0x50, +0x45, +0x4e, +0x1, +0x0, +0x38, +0x0, +0x3, +0x43, +0x41, +0x45, +0x4e, +0x1, +0x0, +0x3, +0x43, +0x42, +0x45, +0x4e, +0x1, +0x8, +0x46, +0x44, +0x45, +0x4e, +0x1, +0x10, +0x4c, +0x1b, +0x2f, +0x3, +0x5f, +0x53, +0x42, +0x5f, +0x50, +0x43, +0x49, +0x30, +0x49, +0x53, +0x41, +0x5f, +0x5b, +0x82, +0x2d, +0x52, +0x54, +0x43, +0x5f, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0xb, +0x0, +0x8, +0x5f, +0x43, +0x52, +0x53, +0x11, +0x18, +0xa, +0x15, +0x47, +0x1, +0x70, +0x0, +0x70, +0x0, +0x10, +0x2, +0x22, +0x0, +0x1, +0x47, +0x1, +0x72, +0x0, +0x72, +0x0, +0x2, +0x6, +0x79, +0x0, +0x5b, +0x82, +0x37, +0x4b, +0x42, +0x44, +0x5f, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0x3, +0x3, +0x14, +0x9, +0x5f, +0x53, +0x54, +0x41, +0x0, +0xa4, +0xa, +0xf, +0x8, +0x5f, +0x43, +0x52, +0x53, +0x11, +0x18, +0xa, +0x15, +0x47, +0x1, +0x60, +0x0, +0x60, +0x0, +0x1, +0x1, +0x47, +0x1, +0x64, +0x0, +0x64, +0x0, +0x1, +0x1, +0x22, +0x2, +0x0, +0x79, +0x0, +0x5b, +0x82, +0x27, +0x4d, +0x4f, +0x55, +0x5f, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0xf, +0x13, +0x14, +0x9, +0x5f, +0x53, +0x54, +0x41, +0x0, +0xa4, +0xa, +0xf, +0x8, +0x5f, +0x43, +0x52, +0x53, +0x11, +0x8, +0xa, +0x5, +0x22, +0x0, +0x10, +0x79, +0x0, +0x5b, +0x82, +0x4a, +0x4, +0x46, +0x44, +0x43, +0x30, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0x7, +0x0, +0x14, +0x18, +0x5f, +0x53, +0x54, +0x41, +0x0, +0x70, +0x46, +0x44, +0x45, +0x4e, +0x60, +0xa0, +0x6, +0x93, +0x60, +0x0, +0xa4, +0x0, +0xa1, +0x4, +0xa4, +0xa, +0xf, +0x8, +0x5f, +0x43, +0x52, +0x53, +0x11, +0x1b, +0xa, +0x18, +0x47, +0x1, +0xf2, +0x3, +0xf2, +0x3, +0x0, +0x4, +0x47, +0x1, +0xf7, +0x3, +0xf7, +0x3, +0x0, +0x1, +0x22, +0x40, +0x0, +0x2a, +0x4, +0x0, +0x79, +0x0, +0x5b, +0x82, +0x3e, +0x4c, +0x50, +0x54, +0x5f, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0x4, +0x0, +0x14, +0x18, +0x5f, +0x53, +0x54, +0x41, +0x0, +0x70, +0x4c, +0x50, +0x45, +0x4e, +0x60, +0xa0, +0x6, +0x93, +0x60, +0x0, +0xa4, +0x0, +0xa1, +0x4, +0xa4, +0xa, +0xf, +0x8, +0x5f, +0x43, +0x52, +0x53, +0x11, +0x10, +0xa, +0xd, +0x47, +0x1, +0x78, +0x3, +0x78, +0x3, +0x8, +0x8, +0x22, +0x80, +0x0, +0x79, +0x0, +0x5b, +0x82, +0x45, +0x4, +0x43, +0x4f, +0x4d, +0x31, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0x5, +0x1, +0x8, +0x5f, +0x55, +0x49, +0x44, +0x1, +0x14, +0x18, +0x5f, +0x53, +0x54, +0x41, +0x0, +0x70, +0x43, +0x41, +0x45, +0x4e, +0x60, +0xa0, +0x6, +0x93, +0x60, +0x0, +0xa4, +0x0, +0xa1, +0x4, +0xa4, +0xa, +0xf, +0x8, +0x5f, +0x43, +0x52, +0x53, +0x11, +0x10, +0xa, +0xd, +0x47, +0x1, +0xf8, +0x3, +0xf8, +0x3, +0x0, +0x8, +0x22, +0x10, +0x0, +0x79, +0x0, +0x5b, +0x82, +0x46, +0x4, +0x43, +0x4f, +0x4d, +0x32, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0x5, +0x1, +0x8, +0x5f, +0x55, +0x49, +0x44, +0xa, +0x2, +0x14, +0x18, +0x5f, +0x53, +0x54, +0x41, +0x0, +0x70, +0x43, +0x42, +0x45, +0x4e, +0x60, +0xa0, +0x6, +0x93, +0x60, +0x0, +0xa4, +0x0, +0xa1, +0x4, +0xa4, +0xa, +0xf, +0x8, +0x5f, +0x43, +0x52, +0x53, +0x11, +0x10, +0xa, +0xd, +0x47, +0x1, +0xf8, +0x2, +0xf8, +0x2, +0x0, +0x8, +0x22, +0x8, +0x0, +0x79, +0x0, +0x10, +0x4b, +0x8, +0x2e, +0x5f, +0x53, +0x42, +0x5f, +0x50, +0x43, +0x49, +0x30, +0x5b, +0x80, +0x50, +0x43, +0x53, +0x54, +0x1, +0xb, +0x0, +0xae, +0xa, +0x8, +0x5b, +0x81, +0x10, +0x50, +0x43, +0x53, +0x54, +0x43, +0x50, +0x43, +0x49, +0x55, +0x20, +0x50, +0x43, +0x49, +0x44, +0x20, +0x5b, +0x80, +0x53, +0x45, +0x4a, +0x5f, +0x1, +0xb, +0x8, +0xae, +0xa, +0x4, +0x5b, +0x81, +0xb, +0x53, +0x45, +0x4a, +0x5f, +0x43, +0x42, +0x30, +0x45, +0x4a, +0x20, +0x14, +0x11, +0x50, +0x43, +0x45, +0x4a, +0x1, +0x70, +0x79, +0x1, +0x68, +0x0, +0x42, +0x30, +0x45, +0x4a, +0xa4, +0x0, +0x14, +0x36, +0x50, +0x43, +0x4e, +0x46, +0x0, +0x70, +0x0, +0x60, +0xa2, +0x2c, +0x95, +0x60, +0xa, +0x1f, +0x75, +0x60, +0xa0, +0x11, +0x7b, +0x50, +0x43, +0x49, +0x55, +0x79, +0x1, +0x60, +0x0, +0x0, +0x50, +0x43, +0x4e, +0x54, +0x60, +0x1, +0xa0, +0x12, +0x7b, +0x50, +0x43, +0x49, +0x44, +0x79, +0x1, +0x60, +0x0, +0x0, +0x50, +0x43, +0x4e, +0x54, +0x60, +0xa, +0x3, +0x10, +0x4a, +0xa0, +0x5f, +0x53, +0x42, +0x5f, +0x10, +0x47, +0x74, +0x50, +0x43, +0x49, +0x30, +0x8, +0x5f, +0x50, +0x52, +0x54, +0x12, +0x4b, +0x73, +0x80, +0x12, +0xb, +0x4, +0xb, +0xff, +0xff, +0x0, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x12, +0xb, +0x4, +0xb, +0xff, +0xff, +0x1, +0x4c, +0x4e, +0x4b, +0x41, +0x0, +0x12, +0xc, +0x4, +0xb, +0xff, +0xff, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x12, +0xc, +0x4, +0xb, +0xff, +0xff, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x53, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x2, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x2, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x2, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x2, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x41, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x3, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x3, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x3, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x41, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x3, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x4, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x4, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x41, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x4, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x4, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x5, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x41, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x5, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x5, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x5, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x6, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x6, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x6, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x6, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x41, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x7, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x7, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x7, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x41, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x7, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x8, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x8, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x41, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x8, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x8, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x9, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x41, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x9, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x9, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x9, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0xa, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0xa, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0xa, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0xa, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x41, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0xb, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0xb, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0xb, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x41, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0xb, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0xc, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0xc, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x41, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0xc, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0xc, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0xd, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x41, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0xd, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0xd, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0xd, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0xe, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0xe, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0xe, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0xe, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x41, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0xf, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0xf, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0xf, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x41, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0xf, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x10, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x10, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x41, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x10, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x10, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x11, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x41, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x11, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x11, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x11, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x12, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x12, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x12, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x12, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x41, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x13, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x13, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x13, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x41, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x13, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x14, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x14, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x41, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x14, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x14, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x15, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x41, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x15, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x15, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x15, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x16, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x16, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x16, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x16, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x41, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x17, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x17, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x17, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x41, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x17, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x18, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x18, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x41, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x18, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x18, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x19, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x41, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x19, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x19, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x19, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1a, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1a, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1a, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1a, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x41, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1b, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1b, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1b, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x41, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1b, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1c, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1c, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x41, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1c, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1c, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1d, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x41, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1d, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1d, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1d, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1e, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1e, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1e, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1e, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x41, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1f, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1f, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1f, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x41, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1f, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x5b, +0x81, +0x24, +0x2f, +0x3, +0x50, +0x43, +0x49, +0x30, +0x49, +0x53, +0x41, +0x5f, +0x50, +0x34, +0x30, +0x43, +0x1, +0x50, +0x52, +0x51, +0x30, +0x8, +0x50, +0x52, +0x51, +0x31, +0x8, +0x50, +0x52, +0x51, +0x32, +0x8, +0x50, +0x52, +0x51, +0x33, +0x8, +0x14, +0x13, +0x49, +0x51, +0x53, +0x54, +0x1, +0xa0, +0x9, +0x7b, +0xa, +0x80, +0x68, +0x0, +0xa4, +0xa, +0x9, +0xa4, +0xa, +0xb, +0x14, +0x36, +0x49, +0x51, +0x43, +0x52, +0x1, +0x8, +0x50, +0x52, +0x52, +0x30, +0x11, +0xe, +0xa, +0xb, +0x89, +0x6, +0x0, +0x9, +0x1, +0x0, +0x0, +0x0, +0x0, +0x79, +0x0, +0x8a, +0x50, +0x52, +0x52, +0x30, +0xa, +0x5, +0x50, +0x52, +0x52, +0x49, +0xa0, +0xb, +0x95, +0x68, +0xa, +0x80, +0x70, +0x68, +0x50, +0x52, +0x52, +0x49, +0xa4, +0x50, +0x52, +0x52, +0x30, +0x5b, +0x82, +0x4c, +0x7, +0x4c, +0x4e, +0x4b, +0x41, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0xc, +0xf, +0x8, +0x5f, +0x55, +0x49, +0x44, +0x0, +0x8, +0x5f, +0x50, +0x52, +0x53, +0x11, +0x16, +0xa, +0x13, +0x89, +0xe, +0x0, +0x9, +0x3, +0x5, +0x0, +0x0, +0x0, +0xa, +0x0, +0x0, +0x0, +0xb, +0x0, +0x0, +0x0, +0x79, +0x0, +0x14, +0xf, +0x5f, +0x53, +0x54, +0x41, +0x0, +0xa4, +0x49, +0x51, +0x53, +0x54, +0x50, +0x52, +0x51, +0x30, +0x14, +0x11, +0x5f, +0x44, +0x49, +0x53, +0x0, +0x7d, +0x50, +0x52, +0x51, +0x30, +0xa, +0x80, +0x50, +0x52, +0x51, +0x30, +0x14, +0xf, +0x5f, +0x43, +0x52, +0x53, +0x0, +0xa4, +0x49, +0x51, +0x43, +0x52, +0x50, +0x52, +0x51, +0x30, +0x14, +0x17, +0x5f, +0x53, +0x52, +0x53, +0x1, +0x8a, +0x68, +0xa, +0x5, +0x50, +0x52, +0x52, +0x49, +0x70, +0x50, +0x52, +0x52, +0x49, +0x50, +0x52, +0x51, +0x30, +0x5b, +0x82, +0x4c, +0x7, +0x4c, +0x4e, +0x4b, +0x42, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0xc, +0xf, +0x8, +0x5f, +0x55, +0x49, +0x44, +0x1, +0x8, +0x5f, +0x50, +0x52, +0x53, +0x11, +0x16, +0xa, +0x13, +0x89, +0xe, +0x0, +0x9, +0x3, +0x5, +0x0, +0x0, +0x0, +0xa, +0x0, +0x0, +0x0, +0xb, +0x0, +0x0, +0x0, +0x79, +0x0, +0x14, +0xf, +0x5f, +0x53, +0x54, +0x41, +0x0, +0xa4, +0x49, +0x51, +0x53, +0x54, +0x50, +0x52, +0x51, +0x31, +0x14, +0x11, +0x5f, +0x44, +0x49, +0x53, +0x0, +0x7d, +0x50, +0x52, +0x51, +0x31, +0xa, +0x80, +0x50, +0x52, +0x51, +0x31, +0x14, +0xf, +0x5f, +0x43, +0x52, +0x53, +0x0, +0xa4, +0x49, +0x51, +0x43, +0x52, +0x50, +0x52, +0x51, +0x31, +0x14, +0x17, +0x5f, +0x53, +0x52, +0x53, +0x1, +0x8a, +0x68, +0xa, +0x5, +0x50, +0x52, +0x52, +0x49, +0x70, +0x50, +0x52, +0x52, +0x49, +0x50, +0x52, +0x51, +0x31, +0x5b, +0x82, +0x4d, +0x7, +0x4c, +0x4e, +0x4b, +0x43, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0xc, +0xf, +0x8, +0x5f, +0x55, +0x49, +0x44, +0xa, +0x2, +0x8, +0x5f, +0x50, +0x52, +0x53, +0x11, +0x16, +0xa, +0x13, +0x89, +0xe, +0x0, +0x9, +0x3, +0x5, +0x0, +0x0, +0x0, +0xa, +0x0, +0x0, +0x0, +0xb, +0x0, +0x0, +0x0, +0x79, +0x0, +0x14, +0xf, +0x5f, +0x53, +0x54, +0x41, +0x0, +0xa4, +0x49, +0x51, +0x53, +0x54, +0x50, +0x52, +0x51, +0x32, +0x14, +0x11, +0x5f, +0x44, +0x49, +0x53, +0x0, +0x7d, +0x50, +0x52, +0x51, +0x32, +0xa, +0x80, +0x50, +0x52, +0x51, +0x32, +0x14, +0xf, +0x5f, +0x43, +0x52, +0x53, +0x0, +0xa4, +0x49, +0x51, +0x43, +0x52, +0x50, +0x52, +0x51, +0x32, +0x14, +0x17, +0x5f, +0x53, +0x52, +0x53, +0x1, +0x8a, +0x68, +0xa, +0x5, +0x50, +0x52, +0x52, +0x49, +0x70, +0x50, +0x52, +0x52, +0x49, +0x50, +0x52, +0x51, +0x32, +0x5b, +0x82, +0x4d, +0x7, +0x4c, +0x4e, +0x4b, +0x44, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0xc, +0xf, +0x8, +0x5f, +0x55, +0x49, +0x44, +0xa, +0x3, +0x8, +0x5f, +0x50, +0x52, +0x53, +0x11, +0x16, +0xa, +0x13, +0x89, +0xe, +0x0, +0x9, +0x3, +0x5, +0x0, +0x0, +0x0, +0xa, +0x0, +0x0, +0x0, +0xb, +0x0, +0x0, +0x0, +0x79, +0x0, +0x14, +0xf, +0x5f, +0x53, +0x54, +0x41, +0x0, +0xa4, +0x49, +0x51, +0x53, +0x54, +0x50, +0x52, +0x51, +0x33, +0x14, +0x11, +0x5f, +0x44, +0x49, +0x53, +0x0, +0x7d, +0x50, +0x52, +0x51, +0x33, +0xa, +0x80, +0x50, +0x52, +0x51, +0x33, +0x14, +0xf, +0x5f, +0x43, +0x52, +0x53, +0x0, +0xa4, +0x49, +0x51, +0x43, +0x52, +0x50, +0x52, +0x51, +0x33, +0x14, +0x17, +0x5f, +0x53, +0x52, +0x53, +0x1, +0x8a, +0x68, +0xa, +0x5, +0x50, +0x52, +0x52, +0x49, +0x70, +0x50, +0x52, +0x52, +0x49, +0x50, +0x52, +0x51, +0x33, +0x5b, +0x82, +0x4f, +0x4, +0x4c, +0x4e, +0x4b, +0x53, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0xc, +0xf, +0x8, +0x5f, +0x55, +0x49, +0x44, +0xa, +0x4, +0x8, +0x5f, +0x50, +0x52, +0x53, +0x11, +0xe, +0xa, +0xb, +0x89, +0x6, +0x0, +0x9, +0x1, +0x9, +0x0, +0x0, +0x0, +0x79, +0x0, +0x14, +0x9, +0x5f, +0x53, +0x54, +0x41, +0x0, +0xa4, +0xa, +0xb, +0x14, +0x6, +0x5f, +0x44, +0x49, +0x53, +0x0, +0x14, +0xb, +0x5f, +0x43, +0x52, +0x53, +0x0, +0xa4, +0x5f, +0x50, +0x52, +0x53, +0x14, +0x6, +0x5f, +0x53, +0x52, +0x53, +0x1, +0x10, +0x47, +0xe, +0x5f, +0x53, +0x42, +0x5f, +0x14, +0x35, +0x43, +0x50, +0x4d, +0x41, +0x1, +0x70, +0x83, +0x88, +0x43, +0x50, +0x4f, +0x4e, +0x68, +0x0, +0x60, +0x70, +0x11, +0xb, +0xa, +0x8, +0x0, +0x8, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x61, +0x70, +0x68, +0x88, +0x61, +0xa, +0x2, +0x0, +0x70, +0x68, +0x88, +0x61, +0xa, +0x3, +0x0, +0x70, +0x60, +0x88, +0x61, +0xa, +0x4, +0x0, +0xa4, +0x61, +0x14, +0x1a, +0x43, +0x50, +0x53, +0x54, +0x1, +0x70, +0x83, +0x88, +0x43, +0x50, +0x4f, +0x4e, +0x68, +0x0, +0x60, +0xa0, +0x5, +0x60, +0xa4, +0xa, +0xf, +0xa1, +0x3, +0xa4, +0x0, +0x14, +0xa, +0x43, +0x50, +0x45, +0x4a, +0x2, +0x5b, +0x22, +0xa, +0xc8, +0x5b, +0x80, +0x50, +0x52, +0x53, +0x54, +0x1, +0xb, +0x0, +0xaf, +0xa, +0x20, +0x5b, +0x81, +0xc, +0x50, +0x52, +0x53, +0x54, +0x1, +0x50, +0x52, +0x53, +0x5f, +0x40, +0x10, +0x14, +0x4a, +0x6, +0x50, +0x52, +0x53, +0x43, +0x0, +0x70, +0x50, +0x52, +0x53, +0x5f, +0x65, +0x70, +0x0, +0x62, +0x70, +0x0, +0x60, +0xa2, +0x46, +0x5, +0x95, +0x60, +0x87, +0x43, +0x50, +0x4f, +0x4e, +0x70, +0x83, +0x88, +0x43, +0x50, +0x4f, +0x4e, +0x60, +0x0, +0x61, +0xa0, +0xa, +0x7b, +0x60, +0xa, +0x7, +0x0, +0x7a, +0x62, +0x1, +0x62, +0xa1, +0xc, +0x70, +0x83, +0x88, +0x65, +0x7a, +0x60, +0xa, +0x3, +0x0, +0x0, +0x62, +0x70, +0x7b, +0x62, +0x1, +0x0, +0x63, +0xa0, +0x22, +0x92, +0x93, +0x61, +0x63, +0x70, +0x63, +0x88, +0x43, +0x50, +0x4f, +0x4e, +0x60, +0x0, +0xa0, +0xa, +0x93, +0x63, +0x1, +0x4e, +0x54, +0x46, +0x59, +0x60, +0x1, +0xa1, +0x8, +0x4e, +0x54, +0x46, +0x59, +0x60, +0xa, +0x3, +0x75, +0x60, +0x10, +0x4e, +0x9, +0x5f, +0x47, +0x50, +0x45, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xd, +0x41, +0x43, +0x50, +0x49, +0x30, +0x30, +0x30, +0x36, +0x0, +0x14, +0x6, +0x5f, +0x4c, +0x30, +0x30, +0x0, +0x14, +0x15, +0x5f, +0x45, +0x30, +0x31, +0x0, +0x5c, +0x2f, +0x3, +0x5f, +0x53, +0x42, +0x5f, +0x50, +0x43, +0x49, +0x30, +0x50, +0x43, +0x4e, +0x46, +0x14, +0x10, +0x5f, +0x45, +0x30, +0x32, +0x0, +0x5c, +0x2e, +0x5f, +0x53, +0x42, +0x5f, +0x50, +0x52, +0x53, +0x43, +0x14, +0x6, +0x5f, +0x4c, +0x30, +0x33, +0x0, +0x14, +0x6, +0x5f, +0x4c, +0x30, +0x34, +0x0, +0x14, +0x6, +0x5f, +0x4c, +0x30, +0x35, +0x0, +0x14, +0x6, +0x5f, +0x4c, +0x30, +0x36, +0x0, +0x14, +0x6, +0x5f, +0x4c, +0x30, +0x37, +0x0, +0x14, +0x6, +0x5f, +0x4c, +0x30, +0x38, +0x0, +0x14, +0x6, +0x5f, +0x4c, +0x30, +0x39, +0x0, +0x14, +0x6, +0x5f, +0x4c, +0x30, +0x41, +0x0, +0x14, +0x6, +0x5f, +0x4c, +0x30, +0x42, +0x0, +0x14, +0x6, +0x5f, +0x4c, +0x30, +0x43, +0x0, +0x14, +0x6, +0x5f, +0x4c, +0x30, +0x44, +0x0, +0x14, +0x6, +0x5f, +0x4c, +0x30, +0x45, +0x0, +0x14, +0x6, +0x5f, +0x4c, +0x30, +0x46, +0x0 +}; diff --git a/hw/i386/q35-acpi-dsdt.hex.generated b/hw/i386/q35-acpi-dsdt.hex.generated new file mode 100644 index 0000000..3a6168d --- /dev/null +++ b/hw/i386/q35-acpi-dsdt.hex.generated @@ -0,0 +1,7346 @@ +static unsigned char Q35AcpiDsdtAmlCode[] = { +0x44, +0x53, +0x44, +0x54, +0xb0, +0x1c, +0x0, +0x0, +0x1, +0x7, +0x42, +0x58, +0x50, +0x43, +0x0, +0x0, +0x42, +0x58, +0x44, +0x53, +0x44, +0x54, +0x0, +0x0, +0x2, +0x0, +0x0, +0x0, +0x49, +0x4e, +0x54, +0x4c, +0x28, +0x5, +0x10, +0x20, +0x10, +0x49, +0x4, +0x5c, +0x0, +0x5b, +0x80, +0x44, +0x42, +0x47, +0x5f, +0x1, +0xb, +0x2, +0x4, +0x1, +0x5b, +0x81, +0xb, +0x44, +0x42, +0x47, +0x5f, +0x1, +0x44, +0x42, +0x47, +0x42, +0x8, +0x14, +0x2c, +0x44, +0x42, +0x55, +0x47, +0x1, +0x98, +0x68, +0x60, +0x96, +0x60, +0x60, +0x74, +0x87, +0x60, +0x1, +0x61, +0x70, +0x0, +0x62, +0xa2, +0x10, +0x95, +0x62, +0x61, +0x70, +0x83, +0x88, +0x60, +0x62, +0x0, +0x44, +0x42, +0x47, +0x42, +0x75, +0x62, +0x70, +0xa, +0xa, +0x44, +0x42, +0x47, +0x42, +0x10, +0x29, +0x5f, +0x53, +0x42, +0x5f, +0x5b, +0x80, +0x50, +0x43, +0x53, +0x54, +0x1, +0xb, +0x0, +0xae, +0xa, +0xc, +0x5b, +0x80, +0x50, +0x43, +0x53, +0x42, +0x1, +0xb, +0xc, +0xae, +0x1, +0x5b, +0x81, +0xb, +0x50, +0x43, +0x53, +0x42, +0x40, +0x50, +0x43, +0x49, +0x42, +0x8, +0x10, +0x4f, +0xc, +0x5f, +0x53, +0x42, +0x5f, +0x5b, +0x82, +0x47, +0xc, +0x50, +0x43, +0x49, +0x30, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0xa, +0x8, +0x8, +0x5f, +0x43, +0x49, +0x44, +0xc, +0x41, +0xd0, +0xa, +0x3, +0x8, +0x5f, +0x41, +0x44, +0x52, +0x0, +0x8, +0x5f, +0x55, +0x49, +0x44, +0x1, +0x8, +0x53, +0x55, +0x50, +0x50, +0x0, +0x8, +0x43, +0x54, +0x52, +0x4c, +0x0, +0x14, +0x44, +0x9, +0x5f, +0x4f, +0x53, +0x43, +0x4, +0x8a, +0x6b, +0x0, +0x43, +0x44, +0x57, +0x31, +0xa0, +0x46, +0x7, +0x93, +0x68, +0x11, +0x13, +0xa, +0x10, +0x5b, +0x4d, +0xdb, +0x33, +0xf7, +0x1f, +0x1c, +0x40, +0x96, +0x57, +0x74, +0x41, +0xc0, +0x3d, +0xd7, +0x66, +0x8a, +0x6b, +0xa, +0x4, +0x43, +0x44, +0x57, +0x32, +0x8a, +0x6b, +0xa, +0x8, +0x43, +0x44, +0x57, +0x33, +0x70, +0x43, +0x44, +0x57, +0x32, +0x53, +0x55, +0x50, +0x50, +0x70, +0x43, +0x44, +0x57, +0x33, +0x43, +0x54, +0x52, +0x4c, +0x7b, +0x43, +0x54, +0x52, +0x4c, +0xa, +0x1d, +0x43, +0x54, +0x52, +0x4c, +0xa0, +0x10, +0x92, +0x93, +0x69, +0x1, +0x7d, +0x43, +0x44, +0x57, +0x31, +0xa, +0x8, +0x43, +0x44, +0x57, +0x31, +0xa0, +0x16, +0x92, +0x93, +0x43, +0x44, +0x57, +0x33, +0x43, +0x54, +0x52, +0x4c, +0x7d, +0x43, +0x44, +0x57, +0x31, +0xa, +0x10, +0x43, +0x44, +0x57, +0x31, +0x70, +0x43, +0x54, +0x52, +0x4c, +0x43, +0x44, +0x57, +0x33, +0xa1, +0xc, +0x7d, +0x43, +0x44, +0x57, +0x31, +0xa, +0x4, +0x43, +0x44, +0x57, +0x31, +0xa4, +0x6b, +0x10, +0x4e, +0x15, +0x2e, +0x5f, +0x53, +0x42, +0x5f, +0x50, +0x43, +0x49, +0x30, +0x8, +0x43, +0x52, +0x45, +0x53, +0x11, +0x42, +0x7, +0xa, +0x6e, +0x88, +0xd, +0x0, +0x2, +0xc, +0x0, +0x0, +0x0, +0x0, +0x0, +0xff, +0x0, +0x0, +0x0, +0x0, +0x1, +0x47, +0x1, +0xf8, +0xc, +0xf8, +0xc, +0x1, +0x8, +0x88, +0xd, +0x0, +0x1, +0xc, +0x3, +0x0, +0x0, +0x0, +0x0, +0xf7, +0xc, +0x0, +0x0, +0xf8, +0xc, +0x88, +0xd, +0x0, +0x1, +0xc, +0x3, +0x0, +0x0, +0x0, +0xd, +0xff, +0xff, +0x0, +0x0, +0x0, +0xf3, +0x87, +0x17, +0x0, +0x0, +0xc, +0x3, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0xa, +0x0, +0xff, +0xff, +0xb, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x2, +0x0, +0x87, +0x17, +0x0, +0x0, +0xc, +0x1, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0xe0, +0xff, +0xff, +0xbf, +0xfe, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0xc0, +0x1e, +0x79, +0x0, +0x8, +0x43, +0x52, +0x36, +0x34, +0x11, +0x33, +0xa, +0x30, +0x8a, +0x2b, +0x0, +0x0, +0xc, +0x3, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x80, +0x0, +0x0, +0x0, +0xff, +0xff, +0xff, +0xff, +0xff, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x80, +0x0, +0x0, +0x0, +0x79, +0x0, +0x14, +0x41, +0xa, +0x5f, +0x43, +0x52, +0x53, +0x0, +0x8a, +0x43, +0x52, +0x45, +0x53, +0xa, +0x5c, +0x50, +0x53, +0x33, +0x32, +0x8a, +0x43, +0x52, +0x45, +0x53, +0xa, +0x60, +0x50, +0x45, +0x33, +0x32, +0x8a, +0x43, +0x52, +0x45, +0x53, +0xa, +0x68, +0x50, +0x4c, +0x33, +0x32, +0x70, +0x50, +0x30, +0x53, +0x5f, +0x50, +0x53, +0x33, +0x32, +0x70, +0x50, +0x30, +0x45, +0x5f, +0x50, +0x45, +0x33, +0x32, +0x70, +0x72, +0x74, +0x50, +0x30, +0x45, +0x5f, +0x50, +0x30, +0x53, +0x5f, +0x0, +0x1, +0x0, +0x50, +0x4c, +0x33, +0x32, +0xa0, +0xc, +0x93, +0x50, +0x31, +0x56, +0x5f, +0x0, +0xa4, +0x43, +0x52, +0x45, +0x53, +0x8f, +0x43, +0x52, +0x36, +0x34, +0xa, +0xe, +0x50, +0x53, +0x36, +0x34, +0x8f, +0x43, +0x52, +0x36, +0x34, +0xa, +0x16, +0x50, +0x45, +0x36, +0x34, +0x8f, +0x43, +0x52, +0x36, +0x34, +0xa, +0x26, +0x50, +0x4c, +0x36, +0x34, +0x70, +0x50, +0x31, +0x53, +0x5f, +0x50, +0x53, +0x36, +0x34, +0x70, +0x50, +0x31, +0x45, +0x5f, +0x50, +0x45, +0x36, +0x34, +0x70, +0x50, +0x31, +0x4c, +0x5f, +0x50, +0x4c, +0x36, +0x34, +0x84, +0x43, +0x52, +0x45, +0x53, +0x43, +0x52, +0x36, +0x34, +0x60, +0xa4, +0x60, +0x10, +0x4d, +0x8, +0x5f, +0x53, +0x42, +0x5f, +0x5b, +0x82, +0x45, +0x8, +0x48, +0x50, +0x45, +0x54, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0x1, +0x3, +0x8, +0x5f, +0x55, +0x49, +0x44, +0x0, +0x5b, +0x80, +0x48, +0x50, +0x54, +0x4d, +0x0, +0xc, +0x0, +0x0, +0xd0, +0xfe, +0xb, +0x0, +0x4, +0x5b, +0x81, +0x10, +0x48, +0x50, +0x54, +0x4d, +0x13, +0x56, +0x45, +0x4e, +0x44, +0x20, +0x50, +0x52, +0x44, +0x5f, +0x20, +0x14, +0x36, +0x5f, +0x53, +0x54, +0x41, +0x0, +0x70, +0x56, +0x45, +0x4e, +0x44, +0x60, +0x70, +0x50, +0x52, +0x44, +0x5f, +0x61, +0x7a, +0x60, +0xa, +0x10, +0x60, +0xa0, +0xc, +0x91, +0x93, +0x60, +0x0, +0x93, +0x60, +0xb, +0xff, +0xff, +0xa4, +0x0, +0xa0, +0xe, +0x91, +0x93, +0x61, +0x0, +0x94, +0x61, +0xc, +0x0, +0xe1, +0xf5, +0x5, +0xa4, +0x0, +0xa4, +0xa, +0xf, +0x8, +0x5f, +0x43, +0x52, +0x53, +0x11, +0x11, +0xa, +0xe, +0x86, +0x9, +0x0, +0x0, +0x0, +0x0, +0xd0, +0xfe, +0x0, +0x4, +0x0, +0x0, +0x79, +0x0, +0x10, +0x36, +0x2e, +0x5f, +0x53, +0x42, +0x5f, +0x50, +0x43, +0x49, +0x30, +0x5b, +0x82, +0x2a, +0x56, +0x47, +0x41, +0x5f, +0x8, +0x5f, +0x41, +0x44, +0x52, +0xc, +0x0, +0x0, +0x1, +0x0, +0x14, +0x8, +0x5f, +0x53, +0x31, +0x44, +0x0, +0xa4, +0x0, +0x14, +0x8, +0x5f, +0x53, +0x32, +0x44, +0x0, +0xa4, +0x0, +0x14, +0x8, +0x5f, +0x53, +0x33, +0x44, +0x0, +0xa4, +0x0, +0x10, +0x4c, +0x7, +0x2e, +0x5f, +0x53, +0x42, +0x5f, +0x50, +0x43, +0x49, +0x30, +0x5b, +0x82, +0x4f, +0x6, +0x49, +0x53, +0x41, +0x5f, +0x8, +0x5f, +0x41, +0x44, +0x52, +0xc, +0x0, +0x0, +0x1f, +0x0, +0x5b, +0x80, +0x50, +0x49, +0x52, +0x51, +0x2, +0xa, +0x60, +0xa, +0xc, +0x5b, +0x80, +0x4c, +0x50, +0x43, +0x44, +0x2, +0xa, +0x80, +0xa, +0x2, +0x5b, +0x81, +0x20, +0x4c, +0x50, +0x43, +0x44, +0x0, +0x43, +0x4f, +0x4d, +0x41, +0x3, +0x0, +0x1, +0x43, +0x4f, +0x4d, +0x42, +0x3, +0x0, +0x1, +0x4c, +0x50, +0x54, +0x44, +0x2, +0x0, +0x2, +0x46, +0x44, +0x43, +0x44, +0x2, +0x5b, +0x80, +0x4c, +0x50, +0x43, +0x45, +0x2, +0xa, +0x82, +0xa, +0x2, +0x5b, +0x81, +0x1a, +0x4c, +0x50, +0x43, +0x45, +0x0, +0x43, +0x41, +0x45, +0x4e, +0x1, +0x43, +0x42, +0x45, +0x4e, +0x1, +0x4c, +0x50, +0x45, +0x4e, +0x1, +0x46, +0x44, +0x45, +0x4e, +0x1, +0x10, +0x4c, +0x1b, +0x2f, +0x3, +0x5f, +0x53, +0x42, +0x5f, +0x50, +0x43, +0x49, +0x30, +0x49, +0x53, +0x41, +0x5f, +0x5b, +0x82, +0x2d, +0x52, +0x54, +0x43, +0x5f, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0xb, +0x0, +0x8, +0x5f, +0x43, +0x52, +0x53, +0x11, +0x18, +0xa, +0x15, +0x47, +0x1, +0x70, +0x0, +0x70, +0x0, +0x10, +0x2, +0x22, +0x0, +0x1, +0x47, +0x1, +0x72, +0x0, +0x72, +0x0, +0x2, +0x6, +0x79, +0x0, +0x5b, +0x82, +0x37, +0x4b, +0x42, +0x44, +0x5f, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0x3, +0x3, +0x14, +0x9, +0x5f, +0x53, +0x54, +0x41, +0x0, +0xa4, +0xa, +0xf, +0x8, +0x5f, +0x43, +0x52, +0x53, +0x11, +0x18, +0xa, +0x15, +0x47, +0x1, +0x60, +0x0, +0x60, +0x0, +0x1, +0x1, +0x47, +0x1, +0x64, +0x0, +0x64, +0x0, +0x1, +0x1, +0x22, +0x2, +0x0, +0x79, +0x0, +0x5b, +0x82, +0x27, +0x4d, +0x4f, +0x55, +0x5f, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0xf, +0x13, +0x14, +0x9, +0x5f, +0x53, +0x54, +0x41, +0x0, +0xa4, +0xa, +0xf, +0x8, +0x5f, +0x43, +0x52, +0x53, +0x11, +0x8, +0xa, +0x5, +0x22, +0x0, +0x10, +0x79, +0x0, +0x5b, +0x82, +0x4a, +0x4, +0x46, +0x44, +0x43, +0x30, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0x7, +0x0, +0x14, +0x18, +0x5f, +0x53, +0x54, +0x41, +0x0, +0x70, +0x46, +0x44, +0x45, +0x4e, +0x60, +0xa0, +0x6, +0x93, +0x60, +0x0, +0xa4, +0x0, +0xa1, +0x4, +0xa4, +0xa, +0xf, +0x8, +0x5f, +0x43, +0x52, +0x53, +0x11, +0x1b, +0xa, +0x18, +0x47, +0x1, +0xf2, +0x3, +0xf2, +0x3, +0x0, +0x4, +0x47, +0x1, +0xf7, +0x3, +0xf7, +0x3, +0x0, +0x1, +0x22, +0x40, +0x0, +0x2a, +0x4, +0x0, +0x79, +0x0, +0x5b, +0x82, +0x3e, +0x4c, +0x50, +0x54, +0x5f, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0x4, +0x0, +0x14, +0x18, +0x5f, +0x53, +0x54, +0x41, +0x0, +0x70, +0x4c, +0x50, +0x45, +0x4e, +0x60, +0xa0, +0x6, +0x93, +0x60, +0x0, +0xa4, +0x0, +0xa1, +0x4, +0xa4, +0xa, +0xf, +0x8, +0x5f, +0x43, +0x52, +0x53, +0x11, +0x10, +0xa, +0xd, +0x47, +0x1, +0x78, +0x3, +0x78, +0x3, +0x8, +0x8, +0x22, +0x80, +0x0, +0x79, +0x0, +0x5b, +0x82, +0x45, +0x4, +0x43, +0x4f, +0x4d, +0x31, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0x5, +0x1, +0x8, +0x5f, +0x55, +0x49, +0x44, +0x1, +0x14, +0x18, +0x5f, +0x53, +0x54, +0x41, +0x0, +0x70, +0x43, +0x41, +0x45, +0x4e, +0x60, +0xa0, +0x6, +0x93, +0x60, +0x0, +0xa4, +0x0, +0xa1, +0x4, +0xa4, +0xa, +0xf, +0x8, +0x5f, +0x43, +0x52, +0x53, +0x11, +0x10, +0xa, +0xd, +0x47, +0x1, +0xf8, +0x3, +0xf8, +0x3, +0x0, +0x8, +0x22, +0x10, +0x0, +0x79, +0x0, +0x5b, +0x82, +0x46, +0x4, +0x43, +0x4f, +0x4d, +0x32, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0x5, +0x1, +0x8, +0x5f, +0x55, +0x49, +0x44, +0xa, +0x2, +0x14, +0x18, +0x5f, +0x53, +0x54, +0x41, +0x0, +0x70, +0x43, +0x42, +0x45, +0x4e, +0x60, +0xa0, +0x6, +0x93, +0x60, +0x0, +0xa4, +0x0, +0xa1, +0x4, +0xa4, +0xa, +0xf, +0x8, +0x5f, +0x43, +0x52, +0x53, +0x11, +0x10, +0xa, +0xd, +0x47, +0x1, +0xf8, +0x2, +0xf8, +0x2, +0x0, +0x8, +0x22, +0x8, +0x0, +0x79, +0x0, +0x8, +0x50, +0x49, +0x43, +0x46, +0x0, +0x14, +0xc, +0x5f, +0x50, +0x49, +0x43, +0x1, +0x70, +0x68, +0x50, +0x49, +0x43, +0x46, +0x10, +0x8e, +0x55, +0x1, +0x5f, +0x53, +0x42, +0x5f, +0x10, +0x43, +0xea, +0x50, +0x43, +0x49, +0x30, +0x8, +0x50, +0x52, +0x54, +0x50, +0x12, +0x4b, +0x73, +0x80, +0x12, +0xb, +0x4, +0xb, +0xff, +0xff, +0x0, +0x4c, +0x4e, +0x4b, +0x45, +0x0, +0x12, +0xb, +0x4, +0xb, +0xff, +0xff, +0x1, +0x4c, +0x4e, +0x4b, +0x46, +0x0, +0x12, +0xc, +0x4, +0xb, +0xff, +0xff, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x47, +0x0, +0x12, +0xc, +0x4, +0xb, +0xff, +0xff, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x48, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x46, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x47, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x48, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x45, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x2, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x47, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x2, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x48, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x2, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x45, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x2, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x46, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x3, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x48, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x3, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x45, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x3, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x46, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x3, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x47, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x4, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x45, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x4, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x46, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x4, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x47, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x4, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x48, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x5, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x46, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x5, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x47, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x5, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x48, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x5, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x45, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x6, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x47, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x6, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x48, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x6, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x45, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x6, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x46, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x7, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x48, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x7, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x45, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x7, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x46, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x7, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x47, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x8, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x45, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x8, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x46, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x8, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x47, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x8, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x48, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x9, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x46, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x9, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x47, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x9, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x48, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x9, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x45, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0xa, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x47, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0xa, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x48, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0xa, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x45, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0xa, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x46, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0xb, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x48, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0xb, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x45, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0xb, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x46, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0xb, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x47, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0xc, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x45, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0xc, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x46, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0xc, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x47, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0xc, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x48, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0xd, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x46, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0xd, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x47, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0xd, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x48, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0xd, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x45, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0xe, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x47, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0xe, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x48, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0xe, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x45, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0xe, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x46, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0xf, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x48, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0xf, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x45, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0xf, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x46, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0xf, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x47, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x10, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x45, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x10, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x46, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x10, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x47, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x10, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x48, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x11, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x46, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x11, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x47, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x11, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x48, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x11, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x45, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x12, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x47, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x12, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x48, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x12, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x45, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x12, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x46, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x13, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x48, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x13, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x45, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x13, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x46, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x13, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x47, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x14, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x45, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x14, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x46, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x14, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x47, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x14, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x48, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x15, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x46, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x15, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x47, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x15, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x48, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x15, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x45, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x16, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x47, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x16, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x48, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x16, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x45, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x16, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x46, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x17, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x48, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x17, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x45, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x17, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x46, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x17, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x47, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x18, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x45, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x18, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x46, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x18, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x47, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x18, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x48, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x19, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x41, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x19, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x19, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x19, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1a, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x41, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1a, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1a, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1a, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1b, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x41, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1b, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1b, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1b, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1c, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x41, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1c, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1c, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1c, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1d, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x41, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1d, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1d, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1d, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1e, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x45, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1e, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x46, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1e, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x47, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1e, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x48, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1f, +0x0, +0x0, +0x4c, +0x4e, +0x4b, +0x41, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1f, +0x0, +0x1, +0x4c, +0x4e, +0x4b, +0x42, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1f, +0x0, +0xa, +0x2, +0x4c, +0x4e, +0x4b, +0x43, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1f, +0x0, +0xa, +0x3, +0x4c, +0x4e, +0x4b, +0x44, +0x0, +0x8, +0x50, +0x52, +0x54, +0x41, +0x12, +0x4b, +0x73, +0x80, +0x12, +0xb, +0x4, +0xb, +0xff, +0xff, +0x0, +0x47, +0x53, +0x49, +0x45, +0x0, +0x12, +0xb, +0x4, +0xb, +0xff, +0xff, +0x1, +0x47, +0x53, +0x49, +0x46, +0x0, +0x12, +0xc, +0x4, +0xb, +0xff, +0xff, +0xa, +0x2, +0x47, +0x53, +0x49, +0x47, +0x0, +0x12, +0xc, +0x4, +0xb, +0xff, +0xff, +0xa, +0x3, +0x47, +0x53, +0x49, +0x48, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1, +0x0, +0x0, +0x47, +0x53, +0x49, +0x46, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1, +0x0, +0x1, +0x47, +0x53, +0x49, +0x47, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1, +0x0, +0xa, +0x2, +0x47, +0x53, +0x49, +0x48, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1, +0x0, +0xa, +0x3, +0x47, +0x53, +0x49, +0x45, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x2, +0x0, +0x0, +0x47, +0x53, +0x49, +0x47, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x2, +0x0, +0x1, +0x47, +0x53, +0x49, +0x48, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x2, +0x0, +0xa, +0x2, +0x47, +0x53, +0x49, +0x45, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x2, +0x0, +0xa, +0x3, +0x47, +0x53, +0x49, +0x46, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x3, +0x0, +0x0, +0x47, +0x53, +0x49, +0x48, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x3, +0x0, +0x1, +0x47, +0x53, +0x49, +0x45, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x3, +0x0, +0xa, +0x2, +0x47, +0x53, +0x49, +0x46, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x3, +0x0, +0xa, +0x3, +0x47, +0x53, +0x49, +0x47, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x4, +0x0, +0x0, +0x47, +0x53, +0x49, +0x45, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x4, +0x0, +0x1, +0x47, +0x53, +0x49, +0x46, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x4, +0x0, +0xa, +0x2, +0x47, +0x53, +0x49, +0x47, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x4, +0x0, +0xa, +0x3, +0x47, +0x53, +0x49, +0x48, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x5, +0x0, +0x0, +0x47, +0x53, +0x49, +0x46, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x5, +0x0, +0x1, +0x47, +0x53, +0x49, +0x47, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x5, +0x0, +0xa, +0x2, +0x47, +0x53, +0x49, +0x48, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x5, +0x0, +0xa, +0x3, +0x47, +0x53, +0x49, +0x45, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x6, +0x0, +0x0, +0x47, +0x53, +0x49, +0x47, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x6, +0x0, +0x1, +0x47, +0x53, +0x49, +0x48, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x6, +0x0, +0xa, +0x2, +0x47, +0x53, +0x49, +0x45, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x6, +0x0, +0xa, +0x3, +0x47, +0x53, +0x49, +0x46, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x7, +0x0, +0x0, +0x47, +0x53, +0x49, +0x48, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x7, +0x0, +0x1, +0x47, +0x53, +0x49, +0x45, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x7, +0x0, +0xa, +0x2, +0x47, +0x53, +0x49, +0x46, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x7, +0x0, +0xa, +0x3, +0x47, +0x53, +0x49, +0x47, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x8, +0x0, +0x0, +0x47, +0x53, +0x49, +0x45, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x8, +0x0, +0x1, +0x47, +0x53, +0x49, +0x46, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x8, +0x0, +0xa, +0x2, +0x47, +0x53, +0x49, +0x47, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x8, +0x0, +0xa, +0x3, +0x47, +0x53, +0x49, +0x48, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x9, +0x0, +0x0, +0x47, +0x53, +0x49, +0x46, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x9, +0x0, +0x1, +0x47, +0x53, +0x49, +0x47, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x9, +0x0, +0xa, +0x2, +0x47, +0x53, +0x49, +0x48, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x9, +0x0, +0xa, +0x3, +0x47, +0x53, +0x49, +0x45, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0xa, +0x0, +0x0, +0x47, +0x53, +0x49, +0x47, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0xa, +0x0, +0x1, +0x47, +0x53, +0x49, +0x48, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0xa, +0x0, +0xa, +0x2, +0x47, +0x53, +0x49, +0x45, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0xa, +0x0, +0xa, +0x3, +0x47, +0x53, +0x49, +0x46, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0xb, +0x0, +0x0, +0x47, +0x53, +0x49, +0x48, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0xb, +0x0, +0x1, +0x47, +0x53, +0x49, +0x45, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0xb, +0x0, +0xa, +0x2, +0x47, +0x53, +0x49, +0x46, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0xb, +0x0, +0xa, +0x3, +0x47, +0x53, +0x49, +0x47, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0xc, +0x0, +0x0, +0x47, +0x53, +0x49, +0x45, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0xc, +0x0, +0x1, +0x47, +0x53, +0x49, +0x46, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0xc, +0x0, +0xa, +0x2, +0x47, +0x53, +0x49, +0x47, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0xc, +0x0, +0xa, +0x3, +0x47, +0x53, +0x49, +0x48, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0xd, +0x0, +0x0, +0x47, +0x53, +0x49, +0x46, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0xd, +0x0, +0x1, +0x47, +0x53, +0x49, +0x47, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0xd, +0x0, +0xa, +0x2, +0x47, +0x53, +0x49, +0x48, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0xd, +0x0, +0xa, +0x3, +0x47, +0x53, +0x49, +0x45, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0xe, +0x0, +0x0, +0x47, +0x53, +0x49, +0x47, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0xe, +0x0, +0x1, +0x47, +0x53, +0x49, +0x48, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0xe, +0x0, +0xa, +0x2, +0x47, +0x53, +0x49, +0x45, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0xe, +0x0, +0xa, +0x3, +0x47, +0x53, +0x49, +0x46, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0xf, +0x0, +0x0, +0x47, +0x53, +0x49, +0x48, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0xf, +0x0, +0x1, +0x47, +0x53, +0x49, +0x45, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0xf, +0x0, +0xa, +0x2, +0x47, +0x53, +0x49, +0x46, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0xf, +0x0, +0xa, +0x3, +0x47, +0x53, +0x49, +0x47, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x10, +0x0, +0x0, +0x47, +0x53, +0x49, +0x45, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x10, +0x0, +0x1, +0x47, +0x53, +0x49, +0x46, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x10, +0x0, +0xa, +0x2, +0x47, +0x53, +0x49, +0x47, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x10, +0x0, +0xa, +0x3, +0x47, +0x53, +0x49, +0x48, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x11, +0x0, +0x0, +0x47, +0x53, +0x49, +0x46, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x11, +0x0, +0x1, +0x47, +0x53, +0x49, +0x47, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x11, +0x0, +0xa, +0x2, +0x47, +0x53, +0x49, +0x48, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x11, +0x0, +0xa, +0x3, +0x47, +0x53, +0x49, +0x45, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x12, +0x0, +0x0, +0x47, +0x53, +0x49, +0x47, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x12, +0x0, +0x1, +0x47, +0x53, +0x49, +0x48, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x12, +0x0, +0xa, +0x2, +0x47, +0x53, +0x49, +0x45, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x12, +0x0, +0xa, +0x3, +0x47, +0x53, +0x49, +0x46, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x13, +0x0, +0x0, +0x47, +0x53, +0x49, +0x48, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x13, +0x0, +0x1, +0x47, +0x53, +0x49, +0x45, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x13, +0x0, +0xa, +0x2, +0x47, +0x53, +0x49, +0x46, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x13, +0x0, +0xa, +0x3, +0x47, +0x53, +0x49, +0x47, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x14, +0x0, +0x0, +0x47, +0x53, +0x49, +0x45, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x14, +0x0, +0x1, +0x47, +0x53, +0x49, +0x46, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x14, +0x0, +0xa, +0x2, +0x47, +0x53, +0x49, +0x47, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x14, +0x0, +0xa, +0x3, +0x47, +0x53, +0x49, +0x48, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x15, +0x0, +0x0, +0x47, +0x53, +0x49, +0x46, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x15, +0x0, +0x1, +0x47, +0x53, +0x49, +0x47, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x15, +0x0, +0xa, +0x2, +0x47, +0x53, +0x49, +0x48, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x15, +0x0, +0xa, +0x3, +0x47, +0x53, +0x49, +0x45, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x16, +0x0, +0x0, +0x47, +0x53, +0x49, +0x47, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x16, +0x0, +0x1, +0x47, +0x53, +0x49, +0x48, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x16, +0x0, +0xa, +0x2, +0x47, +0x53, +0x49, +0x45, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x16, +0x0, +0xa, +0x3, +0x47, +0x53, +0x49, +0x46, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x17, +0x0, +0x0, +0x47, +0x53, +0x49, +0x48, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x17, +0x0, +0x1, +0x47, +0x53, +0x49, +0x45, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x17, +0x0, +0xa, +0x2, +0x47, +0x53, +0x49, +0x46, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x17, +0x0, +0xa, +0x3, +0x47, +0x53, +0x49, +0x47, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x18, +0x0, +0x0, +0x47, +0x53, +0x49, +0x45, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x18, +0x0, +0x1, +0x47, +0x53, +0x49, +0x46, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x18, +0x0, +0xa, +0x2, +0x47, +0x53, +0x49, +0x47, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x18, +0x0, +0xa, +0x3, +0x47, +0x53, +0x49, +0x48, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x19, +0x0, +0x0, +0x47, +0x53, +0x49, +0x41, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x19, +0x0, +0x1, +0x47, +0x53, +0x49, +0x42, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x19, +0x0, +0xa, +0x2, +0x47, +0x53, +0x49, +0x43, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x19, +0x0, +0xa, +0x3, +0x47, +0x53, +0x49, +0x44, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1a, +0x0, +0x0, +0x47, +0x53, +0x49, +0x41, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1a, +0x0, +0x1, +0x47, +0x53, +0x49, +0x42, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1a, +0x0, +0xa, +0x2, +0x47, +0x53, +0x49, +0x43, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1a, +0x0, +0xa, +0x3, +0x47, +0x53, +0x49, +0x44, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1b, +0x0, +0x0, +0x47, +0x53, +0x49, +0x41, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1b, +0x0, +0x1, +0x47, +0x53, +0x49, +0x42, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1b, +0x0, +0xa, +0x2, +0x47, +0x53, +0x49, +0x43, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1b, +0x0, +0xa, +0x3, +0x47, +0x53, +0x49, +0x44, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1c, +0x0, +0x0, +0x47, +0x53, +0x49, +0x41, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1c, +0x0, +0x1, +0x47, +0x53, +0x49, +0x42, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1c, +0x0, +0xa, +0x2, +0x47, +0x53, +0x49, +0x43, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1c, +0x0, +0xa, +0x3, +0x47, +0x53, +0x49, +0x44, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1d, +0x0, +0x0, +0x47, +0x53, +0x49, +0x41, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1d, +0x0, +0x1, +0x47, +0x53, +0x49, +0x42, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1d, +0x0, +0xa, +0x2, +0x47, +0x53, +0x49, +0x43, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1d, +0x0, +0xa, +0x3, +0x47, +0x53, +0x49, +0x44, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1e, +0x0, +0x0, +0x47, +0x53, +0x49, +0x45, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1e, +0x0, +0x1, +0x47, +0x53, +0x49, +0x46, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1e, +0x0, +0xa, +0x2, +0x47, +0x53, +0x49, +0x47, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1e, +0x0, +0xa, +0x3, +0x47, +0x53, +0x49, +0x48, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1f, +0x0, +0x0, +0x47, +0x53, +0x49, +0x41, +0x0, +0x12, +0xd, +0x4, +0xc, +0xff, +0xff, +0x1f, +0x0, +0x1, +0x47, +0x53, +0x49, +0x42, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1f, +0x0, +0xa, +0x2, +0x47, +0x53, +0x49, +0x43, +0x0, +0x12, +0xe, +0x4, +0xc, +0xff, +0xff, +0x1f, +0x0, +0xa, +0x3, +0x47, +0x53, +0x49, +0x44, +0x0, +0x14, +0x1a, +0x5f, +0x50, +0x52, +0x54, +0x0, +0xa0, +0xc, +0x93, +0x50, +0x49, +0x43, +0x46, +0x0, +0xa4, +0x50, +0x52, +0x54, +0x50, +0xa1, +0x6, +0xa4, +0x50, +0x52, +0x54, +0x41, +0x5b, +0x81, +0x3a, +0x2f, +0x3, +0x50, +0x43, +0x49, +0x30, +0x49, +0x53, +0x41, +0x5f, +0x50, +0x49, +0x52, +0x51, +0x1, +0x50, +0x52, +0x51, +0x41, +0x8, +0x50, +0x52, +0x51, +0x42, +0x8, +0x50, +0x52, +0x51, +0x43, +0x8, +0x50, +0x52, +0x51, +0x44, +0x8, +0x0, +0x20, +0x50, +0x52, +0x51, +0x45, +0x8, +0x50, +0x52, +0x51, +0x46, +0x8, +0x50, +0x52, +0x51, +0x47, +0x8, +0x50, +0x52, +0x51, +0x48, +0x8, +0x14, +0x13, +0x49, +0x51, +0x53, +0x54, +0x1, +0xa0, +0x9, +0x7b, +0xa, +0x80, +0x68, +0x0, +0xa4, +0xa, +0x9, +0xa4, +0xa, +0xb, +0x14, +0x34, +0x49, +0x51, +0x43, +0x52, +0x1, +0x8, +0x50, +0x52, +0x52, +0x30, +0x11, +0xe, +0xa, +0xb, +0x89, +0x6, +0x0, +0x9, +0x1, +0x0, +0x0, +0x0, +0x0, +0x79, +0x0, +0x8a, +0x50, +0x52, +0x52, +0x30, +0xa, +0x5, +0x50, +0x52, +0x52, +0x49, +0x70, +0x7b, +0x68, +0xa, +0xf, +0x0, +0x50, +0x52, +0x52, +0x49, +0xa4, +0x50, +0x52, +0x52, +0x30, +0x5b, +0x82, +0x4c, +0x7, +0x4c, +0x4e, +0x4b, +0x41, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0xc, +0xf, +0x8, +0x5f, +0x55, +0x49, +0x44, +0x0, +0x8, +0x5f, +0x50, +0x52, +0x53, +0x11, +0x16, +0xa, +0x13, +0x89, +0xe, +0x0, +0x9, +0x3, +0x5, +0x0, +0x0, +0x0, +0xa, +0x0, +0x0, +0x0, +0xb, +0x0, +0x0, +0x0, +0x79, +0x0, +0x14, +0xf, +0x5f, +0x53, +0x54, +0x41, +0x0, +0xa4, +0x49, +0x51, +0x53, +0x54, +0x50, +0x52, +0x51, +0x41, +0x14, +0x11, +0x5f, +0x44, +0x49, +0x53, +0x0, +0x7d, +0x50, +0x52, +0x51, +0x41, +0xa, +0x80, +0x50, +0x52, +0x51, +0x41, +0x14, +0xf, +0x5f, +0x43, +0x52, +0x53, +0x0, +0xa4, +0x49, +0x51, +0x43, +0x52, +0x50, +0x52, +0x51, +0x41, +0x14, +0x17, +0x5f, +0x53, +0x52, +0x53, +0x1, +0x8a, +0x68, +0xa, +0x5, +0x50, +0x52, +0x52, +0x49, +0x70, +0x50, +0x52, +0x52, +0x49, +0x50, +0x52, +0x51, +0x41, +0x5b, +0x82, +0x4c, +0x7, +0x4c, +0x4e, +0x4b, +0x42, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0xc, +0xf, +0x8, +0x5f, +0x55, +0x49, +0x44, +0x1, +0x8, +0x5f, +0x50, +0x52, +0x53, +0x11, +0x16, +0xa, +0x13, +0x89, +0xe, +0x0, +0x9, +0x3, +0x5, +0x0, +0x0, +0x0, +0xa, +0x0, +0x0, +0x0, +0xb, +0x0, +0x0, +0x0, +0x79, +0x0, +0x14, +0xf, +0x5f, +0x53, +0x54, +0x41, +0x0, +0xa4, +0x49, +0x51, +0x53, +0x54, +0x50, +0x52, +0x51, +0x42, +0x14, +0x11, +0x5f, +0x44, +0x49, +0x53, +0x0, +0x7d, +0x50, +0x52, +0x51, +0x42, +0xa, +0x80, +0x50, +0x52, +0x51, +0x42, +0x14, +0xf, +0x5f, +0x43, +0x52, +0x53, +0x0, +0xa4, +0x49, +0x51, +0x43, +0x52, +0x50, +0x52, +0x51, +0x42, +0x14, +0x17, +0x5f, +0x53, +0x52, +0x53, +0x1, +0x8a, +0x68, +0xa, +0x5, +0x50, +0x52, +0x52, +0x49, +0x70, +0x50, +0x52, +0x52, +0x49, +0x50, +0x52, +0x51, +0x42, +0x5b, +0x82, +0x4d, +0x7, +0x4c, +0x4e, +0x4b, +0x43, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0xc, +0xf, +0x8, +0x5f, +0x55, +0x49, +0x44, +0xa, +0x2, +0x8, +0x5f, +0x50, +0x52, +0x53, +0x11, +0x16, +0xa, +0x13, +0x89, +0xe, +0x0, +0x9, +0x3, +0x5, +0x0, +0x0, +0x0, +0xa, +0x0, +0x0, +0x0, +0xb, +0x0, +0x0, +0x0, +0x79, +0x0, +0x14, +0xf, +0x5f, +0x53, +0x54, +0x41, +0x0, +0xa4, +0x49, +0x51, +0x53, +0x54, +0x50, +0x52, +0x51, +0x43, +0x14, +0x11, +0x5f, +0x44, +0x49, +0x53, +0x0, +0x7d, +0x50, +0x52, +0x51, +0x43, +0xa, +0x80, +0x50, +0x52, +0x51, +0x43, +0x14, +0xf, +0x5f, +0x43, +0x52, +0x53, +0x0, +0xa4, +0x49, +0x51, +0x43, +0x52, +0x50, +0x52, +0x51, +0x43, +0x14, +0x17, +0x5f, +0x53, +0x52, +0x53, +0x1, +0x8a, +0x68, +0xa, +0x5, +0x50, +0x52, +0x52, +0x49, +0x70, +0x50, +0x52, +0x52, +0x49, +0x50, +0x52, +0x51, +0x43, +0x5b, +0x82, +0x4d, +0x7, +0x4c, +0x4e, +0x4b, +0x44, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0xc, +0xf, +0x8, +0x5f, +0x55, +0x49, +0x44, +0xa, +0x3, +0x8, +0x5f, +0x50, +0x52, +0x53, +0x11, +0x16, +0xa, +0x13, +0x89, +0xe, +0x0, +0x9, +0x3, +0x5, +0x0, +0x0, +0x0, +0xa, +0x0, +0x0, +0x0, +0xb, +0x0, +0x0, +0x0, +0x79, +0x0, +0x14, +0xf, +0x5f, +0x53, +0x54, +0x41, +0x0, +0xa4, +0x49, +0x51, +0x53, +0x54, +0x50, +0x52, +0x51, +0x44, +0x14, +0x11, +0x5f, +0x44, +0x49, +0x53, +0x0, +0x7d, +0x50, +0x52, +0x51, +0x44, +0xa, +0x80, +0x50, +0x52, +0x51, +0x44, +0x14, +0xf, +0x5f, +0x43, +0x52, +0x53, +0x0, +0xa4, +0x49, +0x51, +0x43, +0x52, +0x50, +0x52, +0x51, +0x44, +0x14, +0x17, +0x5f, +0x53, +0x52, +0x53, +0x1, +0x8a, +0x68, +0xa, +0x5, +0x50, +0x52, +0x52, +0x49, +0x70, +0x50, +0x52, +0x52, +0x49, +0x50, +0x52, +0x51, +0x44, +0x5b, +0x82, +0x4d, +0x7, +0x4c, +0x4e, +0x4b, +0x45, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0xc, +0xf, +0x8, +0x5f, +0x55, +0x49, +0x44, +0xa, +0x4, +0x8, +0x5f, +0x50, +0x52, +0x53, +0x11, +0x16, +0xa, +0x13, +0x89, +0xe, +0x0, +0x9, +0x3, +0x5, +0x0, +0x0, +0x0, +0xa, +0x0, +0x0, +0x0, +0xb, +0x0, +0x0, +0x0, +0x79, +0x0, +0x14, +0xf, +0x5f, +0x53, +0x54, +0x41, +0x0, +0xa4, +0x49, +0x51, +0x53, +0x54, +0x50, +0x52, +0x51, +0x45, +0x14, +0x11, +0x5f, +0x44, +0x49, +0x53, +0x0, +0x7d, +0x50, +0x52, +0x51, +0x45, +0xa, +0x80, +0x50, +0x52, +0x51, +0x45, +0x14, +0xf, +0x5f, +0x43, +0x52, +0x53, +0x0, +0xa4, +0x49, +0x51, +0x43, +0x52, +0x50, +0x52, +0x51, +0x45, +0x14, +0x17, +0x5f, +0x53, +0x52, +0x53, +0x1, +0x8a, +0x68, +0xa, +0x5, +0x50, +0x52, +0x52, +0x49, +0x70, +0x50, +0x52, +0x52, +0x49, +0x50, +0x52, +0x51, +0x45, +0x5b, +0x82, +0x4d, +0x7, +0x4c, +0x4e, +0x4b, +0x46, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0xc, +0xf, +0x8, +0x5f, +0x55, +0x49, +0x44, +0xa, +0x5, +0x8, +0x5f, +0x50, +0x52, +0x53, +0x11, +0x16, +0xa, +0x13, +0x89, +0xe, +0x0, +0x9, +0x3, +0x5, +0x0, +0x0, +0x0, +0xa, +0x0, +0x0, +0x0, +0xb, +0x0, +0x0, +0x0, +0x79, +0x0, +0x14, +0xf, +0x5f, +0x53, +0x54, +0x41, +0x0, +0xa4, +0x49, +0x51, +0x53, +0x54, +0x50, +0x52, +0x51, +0x46, +0x14, +0x11, +0x5f, +0x44, +0x49, +0x53, +0x0, +0x7d, +0x50, +0x52, +0x51, +0x46, +0xa, +0x80, +0x50, +0x52, +0x51, +0x46, +0x14, +0xf, +0x5f, +0x43, +0x52, +0x53, +0x0, +0xa4, +0x49, +0x51, +0x43, +0x52, +0x50, +0x52, +0x51, +0x46, +0x14, +0x17, +0x5f, +0x53, +0x52, +0x53, +0x1, +0x8a, +0x68, +0xa, +0x5, +0x50, +0x52, +0x52, +0x49, +0x70, +0x50, +0x52, +0x52, +0x49, +0x50, +0x52, +0x51, +0x46, +0x5b, +0x82, +0x4d, +0x7, +0x4c, +0x4e, +0x4b, +0x47, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0xc, +0xf, +0x8, +0x5f, +0x55, +0x49, +0x44, +0xa, +0x6, +0x8, +0x5f, +0x50, +0x52, +0x53, +0x11, +0x16, +0xa, +0x13, +0x89, +0xe, +0x0, +0x9, +0x3, +0x5, +0x0, +0x0, +0x0, +0xa, +0x0, +0x0, +0x0, +0xb, +0x0, +0x0, +0x0, +0x79, +0x0, +0x14, +0xf, +0x5f, +0x53, +0x54, +0x41, +0x0, +0xa4, +0x49, +0x51, +0x53, +0x54, +0x50, +0x52, +0x51, +0x47, +0x14, +0x11, +0x5f, +0x44, +0x49, +0x53, +0x0, +0x7d, +0x50, +0x52, +0x51, +0x47, +0xa, +0x80, +0x50, +0x52, +0x51, +0x47, +0x14, +0xf, +0x5f, +0x43, +0x52, +0x53, +0x0, +0xa4, +0x49, +0x51, +0x43, +0x52, +0x50, +0x52, +0x51, +0x47, +0x14, +0x17, +0x5f, +0x53, +0x52, +0x53, +0x1, +0x8a, +0x68, +0xa, +0x5, +0x50, +0x52, +0x52, +0x49, +0x70, +0x50, +0x52, +0x52, +0x49, +0x50, +0x52, +0x51, +0x47, +0x5b, +0x82, +0x4d, +0x7, +0x4c, +0x4e, +0x4b, +0x48, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0xc, +0xf, +0x8, +0x5f, +0x55, +0x49, +0x44, +0xa, +0x7, +0x8, +0x5f, +0x50, +0x52, +0x53, +0x11, +0x16, +0xa, +0x13, +0x89, +0xe, +0x0, +0x9, +0x3, +0x5, +0x0, +0x0, +0x0, +0xa, +0x0, +0x0, +0x0, +0xb, +0x0, +0x0, +0x0, +0x79, +0x0, +0x14, +0xf, +0x5f, +0x53, +0x54, +0x41, +0x0, +0xa4, +0x49, +0x51, +0x53, +0x54, +0x50, +0x52, +0x51, +0x48, +0x14, +0x11, +0x5f, +0x44, +0x49, +0x53, +0x0, +0x7d, +0x50, +0x52, +0x51, +0x48, +0xa, +0x80, +0x50, +0x52, +0x51, +0x48, +0x14, +0xf, +0x5f, +0x43, +0x52, +0x53, +0x0, +0xa4, +0x49, +0x51, +0x43, +0x52, +0x50, +0x52, +0x51, +0x48, +0x14, +0x17, +0x5f, +0x53, +0x52, +0x53, +0x1, +0x8a, +0x68, +0xa, +0x5, +0x50, +0x52, +0x52, +0x49, +0x70, +0x50, +0x52, +0x52, +0x49, +0x50, +0x52, +0x51, +0x48, +0x5b, +0x82, +0x45, +0x4, +0x47, +0x53, +0x49, +0x41, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0xc, +0xf, +0x8, +0x5f, +0x55, +0x49, +0x44, +0x0, +0x8, +0x5f, +0x50, +0x52, +0x53, +0x11, +0xe, +0xa, +0xb, +0x89, +0x6, +0x0, +0x9, +0x1, +0x10, +0x0, +0x0, +0x0, +0x79, +0x0, +0x8, +0x5f, +0x43, +0x52, +0x53, +0x11, +0xe, +0xa, +0xb, +0x89, +0x6, +0x0, +0x9, +0x1, +0x10, +0x0, +0x0, +0x0, +0x79, +0x0, +0x14, +0x6, +0x5f, +0x53, +0x52, +0x53, +0x1, +0x5b, +0x82, +0x45, +0x4, +0x47, +0x53, +0x49, +0x42, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0xc, +0xf, +0x8, +0x5f, +0x55, +0x49, +0x44, +0x0, +0x8, +0x5f, +0x50, +0x52, +0x53, +0x11, +0xe, +0xa, +0xb, +0x89, +0x6, +0x0, +0x9, +0x1, +0x11, +0x0, +0x0, +0x0, +0x79, +0x0, +0x8, +0x5f, +0x43, +0x52, +0x53, +0x11, +0xe, +0xa, +0xb, +0x89, +0x6, +0x0, +0x9, +0x1, +0x11, +0x0, +0x0, +0x0, +0x79, +0x0, +0x14, +0x6, +0x5f, +0x53, +0x52, +0x53, +0x1, +0x5b, +0x82, +0x45, +0x4, +0x47, +0x53, +0x49, +0x43, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0xc, +0xf, +0x8, +0x5f, +0x55, +0x49, +0x44, +0x0, +0x8, +0x5f, +0x50, +0x52, +0x53, +0x11, +0xe, +0xa, +0xb, +0x89, +0x6, +0x0, +0x9, +0x1, +0x12, +0x0, +0x0, +0x0, +0x79, +0x0, +0x8, +0x5f, +0x43, +0x52, +0x53, +0x11, +0xe, +0xa, +0xb, +0x89, +0x6, +0x0, +0x9, +0x1, +0x12, +0x0, +0x0, +0x0, +0x79, +0x0, +0x14, +0x6, +0x5f, +0x53, +0x52, +0x53, +0x1, +0x5b, +0x82, +0x45, +0x4, +0x47, +0x53, +0x49, +0x44, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0xc, +0xf, +0x8, +0x5f, +0x55, +0x49, +0x44, +0x0, +0x8, +0x5f, +0x50, +0x52, +0x53, +0x11, +0xe, +0xa, +0xb, +0x89, +0x6, +0x0, +0x9, +0x1, +0x13, +0x0, +0x0, +0x0, +0x79, +0x0, +0x8, +0x5f, +0x43, +0x52, +0x53, +0x11, +0xe, +0xa, +0xb, +0x89, +0x6, +0x0, +0x9, +0x1, +0x13, +0x0, +0x0, +0x0, +0x79, +0x0, +0x14, +0x6, +0x5f, +0x53, +0x52, +0x53, +0x1, +0x5b, +0x82, +0x45, +0x4, +0x47, +0x53, +0x49, +0x45, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0xc, +0xf, +0x8, +0x5f, +0x55, +0x49, +0x44, +0x0, +0x8, +0x5f, +0x50, +0x52, +0x53, +0x11, +0xe, +0xa, +0xb, +0x89, +0x6, +0x0, +0x9, +0x1, +0x14, +0x0, +0x0, +0x0, +0x79, +0x0, +0x8, +0x5f, +0x43, +0x52, +0x53, +0x11, +0xe, +0xa, +0xb, +0x89, +0x6, +0x0, +0x9, +0x1, +0x14, +0x0, +0x0, +0x0, +0x79, +0x0, +0x14, +0x6, +0x5f, +0x53, +0x52, +0x53, +0x1, +0x5b, +0x82, +0x45, +0x4, +0x47, +0x53, +0x49, +0x46, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0xc, +0xf, +0x8, +0x5f, +0x55, +0x49, +0x44, +0x0, +0x8, +0x5f, +0x50, +0x52, +0x53, +0x11, +0xe, +0xa, +0xb, +0x89, +0x6, +0x0, +0x9, +0x1, +0x15, +0x0, +0x0, +0x0, +0x79, +0x0, +0x8, +0x5f, +0x43, +0x52, +0x53, +0x11, +0xe, +0xa, +0xb, +0x89, +0x6, +0x0, +0x9, +0x1, +0x15, +0x0, +0x0, +0x0, +0x79, +0x0, +0x14, +0x6, +0x5f, +0x53, +0x52, +0x53, +0x1, +0x5b, +0x82, +0x45, +0x4, +0x47, +0x53, +0x49, +0x47, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0xc, +0xf, +0x8, +0x5f, +0x55, +0x49, +0x44, +0x0, +0x8, +0x5f, +0x50, +0x52, +0x53, +0x11, +0xe, +0xa, +0xb, +0x89, +0x6, +0x0, +0x9, +0x1, +0x16, +0x0, +0x0, +0x0, +0x79, +0x0, +0x8, +0x5f, +0x43, +0x52, +0x53, +0x11, +0xe, +0xa, +0xb, +0x89, +0x6, +0x0, +0x9, +0x1, +0x16, +0x0, +0x0, +0x0, +0x79, +0x0, +0x14, +0x6, +0x5f, +0x53, +0x52, +0x53, +0x1, +0x5b, +0x82, +0x45, +0x4, +0x47, +0x53, +0x49, +0x48, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xc, +0x41, +0xd0, +0xc, +0xf, +0x8, +0x5f, +0x55, +0x49, +0x44, +0x0, +0x8, +0x5f, +0x50, +0x52, +0x53, +0x11, +0xe, +0xa, +0xb, +0x89, +0x6, +0x0, +0x9, +0x1, +0x17, +0x0, +0x0, +0x0, +0x79, +0x0, +0x8, +0x5f, +0x43, +0x52, +0x53, +0x11, +0xe, +0xa, +0xb, +0x89, +0x6, +0x0, +0x9, +0x1, +0x17, +0x0, +0x0, +0x0, +0x79, +0x0, +0x14, +0x6, +0x5f, +0x53, +0x52, +0x53, +0x1, +0x10, +0x47, +0xe, +0x5f, +0x53, +0x42, +0x5f, +0x14, +0x35, +0x43, +0x50, +0x4d, +0x41, +0x1, +0x70, +0x83, +0x88, +0x43, +0x50, +0x4f, +0x4e, +0x68, +0x0, +0x60, +0x70, +0x11, +0xb, +0xa, +0x8, +0x0, +0x8, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x61, +0x70, +0x68, +0x88, +0x61, +0xa, +0x2, +0x0, +0x70, +0x68, +0x88, +0x61, +0xa, +0x3, +0x0, +0x70, +0x60, +0x88, +0x61, +0xa, +0x4, +0x0, +0xa4, +0x61, +0x14, +0x1a, +0x43, +0x50, +0x53, +0x54, +0x1, +0x70, +0x83, +0x88, +0x43, +0x50, +0x4f, +0x4e, +0x68, +0x0, +0x60, +0xa0, +0x5, +0x60, +0xa4, +0xa, +0xf, +0xa1, +0x3, +0xa4, +0x0, +0x14, +0xa, +0x43, +0x50, +0x45, +0x4a, +0x2, +0x5b, +0x22, +0xa, +0xc8, +0x5b, +0x80, +0x50, +0x52, +0x53, +0x54, +0x1, +0xb, +0x0, +0xaf, +0xa, +0x20, +0x5b, +0x81, +0xc, +0x50, +0x52, +0x53, +0x54, +0x1, +0x50, +0x52, +0x53, +0x5f, +0x40, +0x10, +0x14, +0x4a, +0x6, +0x50, +0x52, +0x53, +0x43, +0x0, +0x70, +0x50, +0x52, +0x53, +0x5f, +0x65, +0x70, +0x0, +0x62, +0x70, +0x0, +0x60, +0xa2, +0x46, +0x5, +0x95, +0x60, +0x87, +0x43, +0x50, +0x4f, +0x4e, +0x70, +0x83, +0x88, +0x43, +0x50, +0x4f, +0x4e, +0x60, +0x0, +0x61, +0xa0, +0xa, +0x7b, +0x60, +0xa, +0x7, +0x0, +0x7a, +0x62, +0x1, +0x62, +0xa1, +0xc, +0x70, +0x83, +0x88, +0x65, +0x7a, +0x60, +0xa, +0x3, +0x0, +0x0, +0x62, +0x70, +0x7b, +0x62, +0x1, +0x0, +0x63, +0xa0, +0x22, +0x92, +0x93, +0x61, +0x63, +0x70, +0x63, +0x88, +0x43, +0x50, +0x4f, +0x4e, +0x60, +0x0, +0xa0, +0xa, +0x93, +0x63, +0x1, +0x4e, +0x54, +0x46, +0x59, +0x60, +0x1, +0xa1, +0x8, +0x4e, +0x54, +0x46, +0x59, +0x60, +0xa, +0x3, +0x75, +0x60, +0x10, +0x4f, +0x8, +0x5f, +0x47, +0x50, +0x45, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xd, +0x41, +0x43, +0x50, +0x49, +0x30, +0x30, +0x30, +0x36, +0x0, +0x14, +0x6, +0x5f, +0x4c, +0x30, +0x30, +0x0, +0x14, +0x10, +0x5f, +0x4c, +0x30, +0x31, +0x0, +0x5c, +0x2e, +0x5f, +0x53, +0x42, +0x5f, +0x50, +0x52, +0x53, +0x43, +0x14, +0x6, +0x5f, +0x4c, +0x30, +0x32, +0x0, +0x14, +0x6, +0x5f, +0x4c, +0x30, +0x33, +0x0, +0x14, +0x6, +0x5f, +0x4c, +0x30, +0x34, +0x0, +0x14, +0x6, +0x5f, +0x4c, +0x30, +0x35, +0x0, +0x14, +0x6, +0x5f, +0x4c, +0x30, +0x36, +0x0, +0x14, +0x6, +0x5f, +0x4c, +0x30, +0x37, +0x0, +0x14, +0x6, +0x5f, +0x4c, +0x30, +0x38, +0x0, +0x14, +0x6, +0x5f, +0x4c, +0x30, +0x39, +0x0, +0x14, +0x6, +0x5f, +0x4c, +0x30, +0x41, +0x0, +0x14, +0x6, +0x5f, +0x4c, +0x30, +0x42, +0x0, +0x14, +0x6, +0x5f, +0x4c, +0x30, +0x43, +0x0, +0x14, +0x6, +0x5f, +0x4c, +0x30, +0x44, +0x0, +0x14, +0x6, +0x5f, +0x4c, +0x30, +0x45, +0x0, +0x14, +0x6, +0x5f, +0x4c, +0x30, +0x46, +0x0 +}; diff --git a/hw/i386/ssdt-misc.hex.generated b/hw/i386/ssdt-misc.hex.generated new file mode 100644 index 0000000..33a5266 --- /dev/null +++ b/hw/i386/ssdt-misc.hex.generated @@ -0,0 +1,190 @@ +static unsigned char acpi_pci64_length[] = { +0x6f +}; +static unsigned char acpi_s4_pkg[] = { +0x8f +}; +static unsigned char acpi_s3_name[] = { +0x7c +}; +static unsigned char acpi_pci32_start[] = { +0x2f +}; +static unsigned char acpi_pci64_valid[] = { +0x43 +}; +static unsigned char ssdp_misc_aml[] = { +0x53, +0x53, +0x44, +0x54, +0xa1, +0x0, +0x0, +0x0, +0x1, +0x19, +0x42, +0x58, +0x50, +0x43, +0x0, +0x0, +0x42, +0x58, +0x53, +0x53, +0x44, +0x54, +0x53, +0x55, +0x1, +0x0, +0x0, +0x0, +0x49, +0x4e, +0x54, +0x4c, +0x28, +0x5, +0x10, +0x20, +0x10, +0x42, +0x5, +0x5c, +0x0, +0x8, +0x50, +0x30, +0x53, +0x5f, +0xc, +0x78, +0x56, +0x34, +0x12, +0x8, +0x50, +0x30, +0x45, +0x5f, +0xc, +0x78, +0x56, +0x34, +0x12, +0x8, +0x50, +0x31, +0x56, +0x5f, +0xa, +0x12, +0x8, +0x50, +0x31, +0x53, +0x5f, +0x11, +0xb, +0xa, +0x8, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x8, +0x50, +0x31, +0x45, +0x5f, +0x11, +0xb, +0xa, +0x8, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x8, +0x50, +0x31, +0x4c, +0x5f, +0x11, +0xb, +0xa, +0x8, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x10, +0x29, +0x5c, +0x0, +0x8, +0x5f, +0x53, +0x33, +0x5f, +0x12, +0x6, +0x4, +0x1, +0x1, +0x0, +0x0, +0x8, +0x5f, +0x53, +0x34, +0x5f, +0x12, +0x8, +0x4, +0xa, +0x2, +0xa, +0x2, +0x0, +0x0, +0x8, +0x5f, +0x53, +0x35, +0x5f, +0x12, +0x6, +0x4, +0x0, +0x0, +0x0, +0x0 +}; +static unsigned char acpi_s4_name[] = { +0x88 +}; +static unsigned char acpi_pci64_start[] = { +0x4d +}; +static unsigned char acpi_pci64_end[] = { +0x5e +}; +static unsigned char acpi_pci32_end[] = { +0x39 +}; diff --git a/hw/i386/ssdt-pcihp.hex.generated b/hw/i386/ssdt-pcihp.hex.generated new file mode 100644 index 0000000..0d32a27 --- /dev/null +++ b/hw/i386/ssdt-pcihp.hex.generated @@ -0,0 +1,108 @@ +static unsigned char ssdt_pcihp_name[] = { +0x33 +}; +static unsigned char ssdt_pcihp_adr[] = { +0x44 +}; +static unsigned char ssdt_pcihp_end[] = { +0x58 +}; +static unsigned char ssdp_pcihp_aml[] = { +0x53, +0x53, +0x44, +0x54, +0x58, +0x0, +0x0, +0x0, +0x1, +0x77, +0x42, +0x58, +0x50, +0x43, +0x0, +0x0, +0x42, +0x58, +0x53, +0x53, +0x44, +0x54, +0x50, +0x43, +0x1, +0x0, +0x0, +0x0, +0x49, +0x4e, +0x54, +0x4c, +0x28, +0x5, +0x10, +0x20, +0x10, +0x33, +0x5c, +0x2e, +0x5f, +0x53, +0x42, +0x5f, +0x50, +0x43, +0x49, +0x30, +0x5b, +0x82, +0x26, +0x53, +0x41, +0x41, +0x5f, +0x8, +0x5f, +0x53, +0x55, +0x4e, +0xa, +0xaa, +0x8, +0x5f, +0x41, +0x44, +0x52, +0xc, +0x0, +0x0, +0xaa, +0x0, +0x14, +0xf, +0x5f, +0x45, +0x4a, +0x30, +0x1, +0xa4, +0x50, +0x43, +0x45, +0x4a, +0x5f, +0x53, +0x55, +0x4e +}; +static unsigned char ssdt_pcihp_start[] = { +0x30 +}; +static unsigned char ssdt_pcihp_id[] = { +0x3d +}; +static unsigned char ssdt_pcihp_ej0[] = { +0x4a +}; diff --git a/hw/i386/ssdt-proc.hex.generated b/hw/i386/ssdt-proc.hex.generated new file mode 100644 index 0000000..a28172e --- /dev/null +++ b/hw/i386/ssdt-proc.hex.generated @@ -0,0 +1,134 @@ +static unsigned char ssdt_proc_name[] = { +0x28 +}; +static unsigned char ssdp_proc_aml[] = { +0x53, +0x53, +0x44, +0x54, +0x78, +0x0, +0x0, +0x0, +0x1, +0xb3, +0x42, +0x58, +0x50, +0x43, +0x0, +0x0, +0x42, +0x58, +0x53, +0x53, +0x44, +0x54, +0x0, +0x0, +0x1, +0x0, +0x0, +0x0, +0x49, +0x4e, +0x54, +0x4c, +0x28, +0x5, +0x10, +0x20, +0x5b, +0x83, +0x42, +0x5, +0x43, +0x50, +0x41, +0x41, +0xaa, +0x10, +0xb0, +0x0, +0x0, +0x6, +0x8, +0x49, +0x44, +0x5f, +0x5f, +0xa, +0xaa, +0x8, +0x5f, +0x48, +0x49, +0x44, +0xd, +0x41, +0x43, +0x50, +0x49, +0x30, +0x30, +0x30, +0x37, +0x0, +0x14, +0xf, +0x5f, +0x4d, +0x41, +0x54, +0x0, +0xa4, +0x43, +0x50, +0x4d, +0x41, +0x49, +0x44, +0x5f, +0x5f, +0x14, +0xf, +0x5f, +0x53, +0x54, +0x41, +0x0, +0xa4, +0x43, +0x50, +0x53, +0x54, +0x49, +0x44, +0x5f, +0x5f, +0x14, +0xf, +0x5f, +0x45, +0x4a, +0x30, +0x1, +0x43, +0x50, +0x45, +0x4a, +0x49, +0x44, +0x5f, +0x5f, +0x68 +}; +static unsigned char ssdt_proc_id[] = { +0x38 +}; +static unsigned char ssdt_proc_end[] = { +0x78 +}; +static unsigned char ssdt_proc_start[] = { +0x24 +};
Sometimes we need to pass ranges around, add a handy structure for this purpose.
Signed-off-by: Michael S. Tsirkin mst@redhat.com --- include/qemu/range.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+)
diff --git a/include/qemu/range.h b/include/qemu/range.h index 3502372..4bcd346 100644 --- a/include/qemu/range.h +++ b/include/qemu/range.h @@ -1,6 +1,28 @@ #ifndef QEMU_RANGE_H #define QEMU_RANGE_H
+#include <inttypes.h> + +/* + * Operations on 64 address ranges. + * Notes: + * - ranges must not wrap around 0, but can include the last byte ~0x0LL. + * - this can not represent a full 0 to ~0x0LL range. + */ + +/* A structure representing a range of addresses. */ +struct Range { + uint64_t begin; /* First byte of the range, or 0 if empty. */ + uint64_t end; /* 1 + the last byte. 0 if range empty or ends at ~0x0LL. */ +}; +typedef struct Range Range; + +/* verify that range is not empty and does not overlap */ +static inline bool range_valid(struct Range *range) +{ + return range->begin + 1 <= range->end; +} + /* Get last byte of a range from offset + length. * Undefined for ranges that wrap around 0. */ static inline uint64_t range_get_last(uint64_t offset, uint64_t len)
This add a dynamic bios linker/loader. This will be used by acpi table generation code to: - load each table in the appropriate memory egment - link tables to each other - fix up checksums after said linking
Signed-off-by: Michael S. Tsirkin mst@redhat.com --- hw/i386/Makefile.objs | 1 + hw/i386/bios-linker-loader.c | 155 +++++++++++++++++++++++++++++++++++ include/hw/i386/bios-linker-loader.h | 26 ++++++ 3 files changed, 182 insertions(+) create mode 100644 hw/i386/bios-linker-loader.c create mode 100644 include/hw/i386/bios-linker-loader.h
diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs index 013d250..71be2da 100644 --- a/hw/i386/Makefile.objs +++ b/hw/i386/Makefile.objs @@ -4,6 +4,7 @@ obj-y += pc.o pc_piix.o pc_q35.o obj-$(CONFIG_XEN) += xen_domainbuild.o xen_machine_pv.o
obj-y += kvmvapic.o +obj-y += bios-linker-loader.o
iasl-option=$(shell if test -z "`$(1) $(2) 2>&1 > /dev/null`" \ ; then echo "$(2)"; else echo "$(3)"; fi ;) diff --git a/hw/i386/bios-linker-loader.c b/hw/i386/bios-linker-loader.c new file mode 100644 index 0000000..b2c87d7 --- /dev/null +++ b/hw/i386/bios-linker-loader.c @@ -0,0 +1,155 @@ +/* Dynamic linker/loader of ACPI tables + * + * Copyright (C) 2013 Red Hat Inc + * + * Author: Michael S. Tsirkin mst@redhat.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that 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 "hw/i386/bios-linker-loader.h" + +#include <string.h> +#include <assert.h> +#include "qemu/bswap.h" + +#define BIOS_LINKER_LOADER_FILESZ 56 + +struct BiosLinkerLoaderEntry { + uint32_t command; + union { + /* + * COMMAND_ALLOCATE - allocate a table from @alloc_file + * subject to @alloc_align alignment (must be power of 2) + * and @alloc_zone (can be HIGH or FSEG) requirements. + * + * Must appear exactly once for each file, and before + * this file is referenced by any other command. + */ + struct { + char alloc_file[BIOS_LINKER_LOADER_FILESZ]; + uint32_t alloc_align; + uint8_t alloc_zone; + }; + + /* + * COMMAND_ADD_POINTER - patch the table (originating from + * @dest_file) at @pointer_offset, by adding a pointer to the table + * originating from @src_file. 1,2,4 or 8 byte unsigned + * addition is used depending on @pointer_size. + */ + struct { + char pointer_dest_file[BIOS_LINKER_LOADER_FILESZ]; + char pointer_src_file[BIOS_LINKER_LOADER_FILESZ]; + uint32_t pointer_offset; + uint8_t pointer_size; + }; + + /* + * COMMAND_ADD_CHECKSUM - calculate checksum of the range specified by + * @cksum_start and @cksum_length fields, + * and then add the value at @cksum_offset. + * Checksum simply sums -X for each byte X in the range + * using 8-bit math. + */ + struct { + char cksum_file[BIOS_LINKER_LOADER_FILESZ]; + uint32_t cksum_offset; + uint32_t cksum_start; + uint32_t cksum_length; + }; + + /* padding */ + char pad[124]; + }; +}; +typedef struct BiosLinkerLoaderEntry BiosLinkerLoaderEntry; + +enum { + BIOS_LINKER_LOADER_COMMAND_ALLOCATE = 0x1, + BIOS_LINKER_LOADER_COMMAND_ADD_POINTER = 0x2, + BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM = 0x3, +}; + +enum { + BIOS_LINKER_LOADER_ALLOC_ZONE_HIGH = 0x1, + BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG = 0x2, +}; + +GArray *bios_linker_init(void) +{ + return g_array_new(false, true /* clear */, sizeof(BiosLinkerLoaderEntry)); +} + +/* Free linker wrapper and return the linker array. */ +void *bios_linker_cleanup(GArray *linker) +{ + return g_array_free(linker, false); +} + +void bios_linker_alloc(GArray *linker, + const char *file, + uint32_t alloc_align, + bool alloc_fseg) +{ + BiosLinkerLoaderEntry entry; + + memset(&entry, 0, sizeof entry); + strncpy(entry.alloc_file, file, sizeof entry.alloc_file - 1); + entry.command = cpu_to_le32(BIOS_LINKER_LOADER_COMMAND_ALLOCATE); + entry.alloc_align = cpu_to_le32(alloc_align); + entry.alloc_zone = cpu_to_le32(alloc_fseg ? + BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG : + BIOS_LINKER_LOADER_ALLOC_ZONE_HIGH); + + /* Alloc entries must come first, so prepend them */ + g_array_prepend_val(linker, entry); +} + +void bios_linker_add_checksum(GArray *linker, const char *file, void *table, + void *start, unsigned size, uint8_t *checksum) +{ + BiosLinkerLoaderEntry entry; + + memset(&entry, 0, sizeof entry); + strncpy(entry.cksum_file, file, sizeof entry.cksum_file - 1); + entry.command = cpu_to_le32(BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM); + entry.cksum_offset = cpu_to_le32(checksum - (uint8_t *)table); + entry.cksum_start = cpu_to_le32((uint8_t *)start - (uint8_t *)table); + entry.cksum_length = cpu_to_le32(size); + + g_array_append_val(linker, entry); +} + +void bios_linker_add_pointer(GArray *linker, + const char *dest_file, + const char *src_file, + GArray *table, void *pointer, + uint8_t pointer_size) +{ + BiosLinkerLoaderEntry entry; + + memset(&entry, 0, sizeof entry); + strncpy(entry.pointer_dest_file, dest_file, + sizeof entry.pointer_dest_file - 1); + strncpy(entry.pointer_src_file, src_file, + sizeof entry.pointer_src_file - 1); + entry.command = cpu_to_le32(BIOS_LINKER_LOADER_COMMAND_ADD_POINTER); + entry.pointer_offset = cpu_to_le32((gchar *)pointer - table->data); + entry.pointer_size = pointer_size; + assert(pointer_size == 1 || pointer_size == 2 || + pointer_size == 4 || pointer_size == 8); + + g_array_append_val(linker, entry); +} diff --git a/include/hw/i386/bios-linker-loader.h b/include/hw/i386/bios-linker-loader.h new file mode 100644 index 0000000..18c3868 --- /dev/null +++ b/include/hw/i386/bios-linker-loader.h @@ -0,0 +1,26 @@ +#ifndef BIOS_LINKER_LOADER_H +#define BIOS_LINKER_LOADER_H + +#include <glib.h> +#include <stdbool.h> +#include <inttypes.h> + +GArray *bios_linker_init(void); + +void bios_linker_alloc(GArray *linker, + const char *file, + uint32_t alloc_align, + bool alloc_fseg); + +void bios_linker_add_checksum(GArray *linker, const char *file, void *table, + void *start, unsigned size, uint8_t *checksum); + + +void bios_linker_add_pointer(GArray *linker, + const char *dest_file, + const char *src_file, + GArray *table, void *pointer, + uint8_t pointer_size); + +void *bios_linker_cleanup(GArray *linker); +#endif
Reduce code duplication by getting legacy fw cfg data from guest info structure.
Signed-off-by: Michael S. Tsirkin mst@redhat.com --- hw/i386/pc.c | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-)
diff --git a/hw/i386/pc.c b/hw/i386/pc.c index af414a4..41bfb5b 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -594,14 +594,13 @@ static unsigned int pc_apic_id_limit(unsigned int max_cpus) return x86_cpu_apic_id_from_index(max_cpus - 1) + 1; }
-static FWCfgState *bochs_bios_init(void) +static FWCfgState *bochs_bios_init(PcGuestInfo *guest_info) { FWCfgState *fw_cfg; uint8_t *smbios_table; size_t smbios_len; uint64_t *numa_fw_cfg; - int i, j; - unsigned int apic_id_limit = pc_apic_id_limit(max_cpus); + int i;
fw_cfg = fw_cfg_init(BIOS_CFG_IOPORT, BIOS_CFG_IOPORT + 1, 0, 0); /* FW_CFG_MAX_CPUS is a bit confusing/problematic on x86: @@ -618,7 +617,7 @@ static FWCfgState *bochs_bios_init(void) * [1] The only kind of "CPU identifier" used between SeaBIOS and QEMU is * the APIC ID, not the "CPU index" */ - fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)apic_id_limit); + fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)guest_info->apic_id_limit); fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1); fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); fw_cfg_add_bytes(fw_cfg, FW_CFG_ACPI_TABLES, @@ -637,24 +636,19 @@ static FWCfgState *bochs_bios_init(void) * of nodes, one word for each VCPU->node and one word for each node to * hold the amount of memory. */ - numa_fw_cfg = g_new0(uint64_t, 1 + apic_id_limit + nb_numa_nodes); - numa_fw_cfg[0] = cpu_to_le64(nb_numa_nodes); - for (i = 0; i < max_cpus; i++) { - unsigned int apic_id = x86_cpu_apic_id_from_index(i); - assert(apic_id < apic_id_limit); - for (j = 0; j < nb_numa_nodes; j++) { - if (test_bit(i, node_cpumask[j])) { - numa_fw_cfg[apic_id + 1] = cpu_to_le64(j); - break; - } - } + numa_fw_cfg = g_new0(uint64_t, 1 + guest_info->apic_id_limit + + guest_info->numa_nodes); + numa_fw_cfg[0] = cpu_to_le64(guest_info->numa_nodes); + for (i = 0; i < guest_info->apic_id_limit; i++) { + numa_fw_cfg[i + 1] = cpu_to_le64(guest_info->node_cpu[i]); } - for (i = 0; i < nb_numa_nodes; i++) { - numa_fw_cfg[apic_id_limit + 1 + i] = cpu_to_le64(node_mem[i]); + for (i = 0; i < guest_info->numa_nodes; i++) { + numa_fw_cfg[guest_info->apic_id_limit + 1 + i] = + cpu_to_le64(guest_info->node_mem[i]); } fw_cfg_add_bytes(fw_cfg, FW_CFG_NUMA, numa_fw_cfg, - (1 + apic_id_limit + nb_numa_nodes) * - sizeof(*numa_fw_cfg)); + (1 + guest_info->apic_id_limit + + guest_info->numa_nodes) * sizeof(*numa_fw_cfg));
return fw_cfg; } @@ -1151,7 +1145,7 @@ FWCfgState *pc_memory_init(MemoryRegion *system_memory, option_rom_mr, 1);
- fw_cfg = bochs_bios_init(); + fw_cfg = bochs_bios_init(guest_info); rom_set_fw(fw_cfg);
if (linux_boot) {
This fills in guest info table with misc information of interest to the guest. Will be used by ACPI table generation code.
Signed-off-by: Michael S. Tsirkin mst@redhat.com --- hw/acpi/ich9.c | 7 ++++- hw/acpi/piix4.c | 44 +++++++++++++++++++++++++- hw/i386/Makefile.objs | 2 ++ hw/i386/pc.c | 80 +++++++++++++++++++++++++++++++++++++++++++++-- hw/i386/pc_piix.c | 26 +++++++++++++-- hw/i386/pc_q35.c | 14 +++++++-- hw/isa/lpc_ich9.c | 11 +++++-- hw/mips/mips_malta.c | 2 +- hw/pci-host/q35.c | 5 +++ include/hw/acpi/ich9.h | 2 +- include/hw/i386/ich9.h | 3 +- include/hw/i386/pc.h | 53 +++++++++++++++++++++++++++++-- include/hw/pci-host/q35.h | 2 ++ include/qemu/typedefs.h | 1 + 14 files changed, 233 insertions(+), 19 deletions(-)
diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c index 4a17f32..764e27f 100644 --- a/hw/acpi/ich9.c +++ b/hw/acpi/ich9.c @@ -203,7 +203,7 @@ static void pm_powerdown_req(Notifier *n, void *opaque) }
void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm, - qemu_irq sci_irq) + qemu_irq sci_irq, PcGuestInfo *guest_info) { memory_region_init(&pm->io, "ich9-pm", ICH9_PMIO_SIZE); memory_region_set_enabled(&pm->io, false); @@ -219,6 +219,11 @@ void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm, ICH9_PMIO_GPE0_LEN); memory_region_add_subregion(&pm->io, ICH9_PMIO_GPE0_STS, &pm->io_gpe);
+ guest_info->gpe0_blk = PC_GUEST_PORT_ACPI_PM_BASE + ICH9_PMIO_GPE0_STS; + guest_info->gpe0_blk_len = ICH9_PMIO_GPE0_LEN; + guest_info->fix_rtc = true; + guest_info->platform_timer = false; + memory_region_init_io(&pm->io_smi, &ich9_smi_ops, pm, "apci-smi", 8); memory_region_add_subregion(&pm->io, ICH9_PMIO_SMI_EN, &pm->io_smi); diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index e6525ac..19a26f5 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -94,6 +94,8 @@ typedef struct PIIX4PMState {
CPUStatus gpe_cpu; Notifier cpu_added_notifier; + + PcGuestInfo *guest_info; } PIIX4PMState;
static void piix4_acpi_system_hot_add_init(MemoryRegion *parent, @@ -380,6 +382,27 @@ static void piix4_pm_powerdown_req(Notifier *n, void *opaque) acpi_pm1_evt_power_down(&s->ar); }
+static void piix4_update_guest_info(PIIX4PMState *s) +{ + PCIDevice *dev = &s->dev; + BusState *bus = qdev_get_parent_bus(&dev->qdev); + BusChild *kid, *next; + + memset(s->guest_info->slot_hotplug_enable, 0xff, + DIV_ROUND_UP(PCI_SLOT_MAX, BITS_PER_BYTE)); + + QTAILQ_FOREACH_SAFE(kid, &bus->children, sibling, next) { + DeviceState *qdev = kid->child; + PCIDevice *pdev = PCI_DEVICE(qdev); + PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pdev); + int slot = PCI_SLOT(pdev->devfn); + + if (pc->no_hotplug) { + clear_bit(slot, s->guest_info->slot_hotplug_enable); + } + } +} + static void piix4_pm_machine_ready(Notifier *n, void *opaque) { PIIX4PMState *s = container_of(n, PIIX4PMState, machine_ready); @@ -391,6 +414,9 @@ static void piix4_pm_machine_ready(Notifier *n, void *opaque) pci_conf[0x67] = (isa_is_ioport_assigned(0x3f8) ? 0x08 : 0) | (isa_is_ioport_assigned(0x2f8) ? 0x90 : 0);
+ if (s->guest_info) { + piix4_update_guest_info(s); + } }
static int piix4_pm_initfn(PCIDevice *dev) @@ -447,7 +473,8 @@ static int piix4_pm_initfn(PCIDevice *dev)
i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, qemu_irq sci_irq, qemu_irq smi_irq, - int kvm_enabled, FWCfgState *fw_cfg) + int kvm_enabled, FWCfgState *fw_cfg, + PcGuestInfo *guest_info) { PCIDevice *dev; PIIX4PMState *s; @@ -470,6 +497,21 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, fw_cfg_add_file(fw_cfg, "etc/system-states", g_memdup(suspend, 6), 6); }
+ if (guest_info) { + s->guest_info = guest_info; + + guest_info->s3_disabled = s->disable_s3; + guest_info->s4_disabled = s->disable_s4; + guest_info->s4_val = s->s4_val; + + guest_info->acpi_enable_cmd = ACPI_ENABLE; + guest_info->acpi_disable_cmd = ACPI_DISABLE; + guest_info->gpe0_blk = GPE_BASE; + guest_info->gpe0_blk_len = GPE_LEN; + guest_info->fix_rtc = false; + guest_info->platform_timer = true; + } + return s->smb.smbus; }
diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs index 71be2da..e783050 100644 --- a/hw/i386/Makefile.objs +++ b/hw/i386/Makefile.objs @@ -5,6 +5,8 @@ obj-$(CONFIG_XEN) += xen_domainbuild.o xen_machine_pv.o
obj-y += kvmvapic.o obj-y += bios-linker-loader.o +hw/i386/pc_piix.o: hw/i386/pc_piix.c hw/i386/acpi-dsdt.hex +hw/i386/pc_q35.o: hw/i386/pc_q35.c hw/i386/q35-acpi-dsdt.hex
iasl-option=$(shell if test -z "`$(1) $(2) 2>&1 > /dev/null`" \ ; then echo "$(2)"; else echo "$(3)"; fi ;) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 338a672..203c683 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -976,6 +976,74 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge) } }
+static void pc_set_cpu_guest_info(CPUState *cpu, void *arg) +{ + PcGuestInfo *guest_info = arg; + CPUClass *klass = CPU_GET_CLASS(cpu); + uint64_t apic_id = klass->get_arch_id(cpu); + int j; + + assert(apic_id <= MAX_CPUMASK_BITS); + assert(apic_id < guest_info->apic_id_limit); + + set_bit(apic_id, guest_info->found_cpus); + + for (j = 0; j < guest_info->numa_nodes; j++) { + assert(cpu->cpu_index < max_cpus); + if (test_bit(cpu->cpu_index, node_cpumask[j])) { + guest_info->node_cpu[apic_id] = cpu_to_le64(j); + break; + } + } +} + +typedef struct PcGuestInfoState { + PcGuestInfo info; + Notifier machine_done; +} PcGuestInfoState; + +static +void pc_guest_info_machine_done(Notifier *notifier, void *data) +{ + PcGuestInfoState *guest_info_state = container_of(notifier, + PcGuestInfoState, + machine_done); +} + +PcGuestInfo *pc_guest_info_init(ram_addr_t below_4g_mem_size, + ram_addr_t above_4g_mem_size) +{ + PcGuestInfoState *guest_info_state = g_malloc0(sizeof *guest_info_state); + PcGuestInfo *guest_info = &guest_info_state->info; + + guest_info->ram_size = below_4g_mem_size + above_4g_mem_size; + guest_info->apic_id_limit = pc_apic_id_limit(max_cpus); + guest_info->apic_xrupt_override = kvm_allows_irq0_override(); + guest_info->numa_nodes = nb_numa_nodes; + guest_info->node_mem = g_memdup(node_mem, guest_info->numa_nodes * + sizeof *guest_info->node_mem); + guest_info->node_cpu = g_malloc0(guest_info->apic_id_limit * + sizeof *guest_info->node_mem); + + memset(&guest_info->found_cpus, 0, sizeof guest_info->found_cpus); + qemu_for_each_cpu(pc_set_cpu_guest_info, guest_info); + + guest_info->pci_info.w32.end = IO_APIC_DEFAULT_ADDRESS; + if (sizeof(hwaddr) == 4) { + guest_info->pci_info.w64.begin = 0; + guest_info->pci_info.w64.end = 0; + } else { + guest_info->pci_info.w64.begin = 0x100000000ULL + above_4g_mem_size; + guest_info->pci_info.w64.end = guest_info->pci_info.w64.begin + + (0x1ULL << 62); + assert(range_valid(&guest_info->pci_info.w64)); + } + + guest_info_state->machine_done.notify = pc_guest_info_machine_done; + qemu_add_machine_init_done_notifier(&guest_info_state->machine_done); + return guest_info; +} + void pc_acpi_init(const char *default_dsdt) { char *filename; @@ -1017,7 +1085,8 @@ FWCfgState *pc_memory_init(MemoryRegion *system_memory, ram_addr_t below_4g_mem_size, ram_addr_t above_4g_mem_size, MemoryRegion *rom_memory, - MemoryRegion **ram_memory) + MemoryRegion **ram_memory, + PcGuestInfo *guest_info) { int linux_boot, i; MemoryRegion *ram, *option_rom_mr; @@ -1069,6 +1138,7 @@ FWCfgState *pc_memory_init(MemoryRegion *system_memory, for (i = 0; i < nb_option_roms; i++) { rom_add_option(option_rom[i].name, option_rom[i].bootindex); } + guest_info->fw_cfg = fw_cfg; return fw_cfg; }
@@ -1123,7 +1193,8 @@ static const MemoryRegionOps ioportF0_io_ops = { void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi, ISADevice **rtc_state, ISADevice **floppy, - bool no_vmport) + bool no_vmport, + PcGuestInfo *guest_info) { int i; DriveInfo *fd[MAX_FD]; @@ -1149,7 +1220,10 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi, * Without KVM_CAP_PIT_STATE2, we cannot switch off the in-kernel PIT * when the HPET wants to take over. Thus we have to disable the latter. */ - if (!no_hpet && (!kvm_irqchip_in_kernel() || kvm_has_pit_state2())) { + guest_info->has_hpet = !no_hpet && + (!kvm_irqchip_in_kernel() || kvm_has_pit_state2()); + + if (guest_info->has_hpet) { hpet = sysbus_try_create_simple("hpet", HPET_BASE, NULL);
if (hpet) { diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 207115c..cd2038a 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -50,6 +50,8 @@ # include <xen/hvm/hvm_info_table.h> #endif
+#include "hw/i386/acpi-dsdt.hex" + #define MAX_IDE_BUS 2
static const int ide_iobase[MAX_IDE_BUS] = { 0x1f0, 0x170 }; @@ -90,6 +92,7 @@ static void pc_init1(MemoryRegion *system_memory, MemoryRegion *rom_memory; DeviceState *icc_bridge; FWCfgState *fw_cfg = NULL; + PcGuestInfo *guest_info;
icc_bridge = qdev_create(NULL, TYPE_ICC_BRIDGE); object_property_add_child(qdev_get_machine(), "icc-bridge", @@ -119,12 +122,26 @@ static void pc_init1(MemoryRegion *system_memory, rom_memory = system_memory; }
+ guest_info = pc_guest_info_init(below_4g_mem_size, above_4g_mem_size); + + guest_info->dsdt_code = AcpiDsdtAmlCode; + guest_info->dsdt_size = sizeof AcpiDsdtAmlCode; + + /* Set PCI window size the way seabios has always done it. */ + /* TODO: consider just starting at below_4g_mem_size */ + if (ram_size <= 0x80000000) + guest_info->pci_info.w32.begin = 0x80000000; + else if (ram_size <= 0xc0000000) + guest_info->pci_info.w32.begin = 0xc0000000; + else + guest_info->pci_info.w32.begin = 0xe0000000; + /* allocate ram and load rom/bios */ if (!xen_enabled()) { fw_cfg = pc_memory_init(system_memory, kernel_filename, kernel_cmdline, initrd_filename, below_4g_mem_size, above_4g_mem_size, - rom_memory, &ram_memory); + rom_memory, &ram_memory, guest_info); }
gsi_state = g_malloc0(sizeof(*gsi_state)); @@ -179,7 +196,8 @@ static void pc_init1(MemoryRegion *system_memory, }
/* init basic PC hardware */ - pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, xen_enabled()); + pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, xen_enabled(), + guest_info);
pc_nic_init(isa_bus, pci_bus);
@@ -218,7 +236,9 @@ static void pc_init1(MemoryRegion *system_memory, /* TODO: Populate SPD eeprom data. */ smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100, gsi[9], *smi_irq, - kvm_enabled(), fw_cfg); + kvm_enabled(), fw_cfg, + guest_info); + guest_info->sci_int = 9; smbus_eeprom_init(smbus, 8, NULL, 0); }
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 4160e2b..9fd8143 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -43,6 +43,8 @@ #include "hw/usb.h" #include "hw/cpu/icc_bus.h"
+#include "hw/i386/q35-acpi-dsdt.hex" + /* ICH9 AHCI has 6 ports */ #define MAX_SATA_PORTS 6
@@ -77,6 +79,7 @@ static void pc_q35_init(QEMUMachineInitArgs *args) ICH9LPCState *ich9_lpc; PCIDevice *ahci; DeviceState *icc_bridge; + PcGuestInfo *guest_info;
icc_bridge = qdev_create(NULL, TYPE_ICC_BRIDGE); object_property_add_child(qdev_get_machine(), "icc-bridge", @@ -105,11 +108,15 @@ static void pc_q35_init(QEMUMachineInitArgs *args) rom_memory = get_system_memory(); }
+ guest_info = pc_guest_info_init(below_4g_mem_size, above_4g_mem_size); + guest_info->dsdt_code = Q35AcpiDsdtAmlCode; + guest_info->dsdt_size = sizeof Q35AcpiDsdtAmlCode; + /* allocate ram and load rom/bios */ if (!xen_enabled()) { pc_memory_init(get_system_memory(), kernel_filename, kernel_cmdline, initrd_filename, below_4g_mem_size, above_4g_mem_size, - rom_memory, &ram_memory); + rom_memory, &ram_memory, guest_info); }
/* irq lines */ @@ -131,6 +138,7 @@ static void pc_q35_init(QEMUMachineInitArgs *args) q35_host->mch.address_space_io = get_system_io();; q35_host->mch.below_4g_mem_size = below_4g_mem_size; q35_host->mch.above_4g_mem_size = above_4g_mem_size; + q35_host->mch.guest_info = guest_info; /* pci */ qdev_init_nofail(DEVICE(q35_host)); host_bus = q35_host->host.pci.bus; @@ -169,10 +177,10 @@ static void pc_q35_init(QEMUMachineInitArgs *args) pc_register_ferr_irq(gsi[13]);
/* init basic PC hardware */ - pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, false); + pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, false, guest_info);
/* connect pm stuff to lpc */ - ich9_lpc_pm_init(lpc); + ich9_lpc_pm_init(lpc, guest_info);
/* ahci and SATA device, for q35 1 ahci controller is built-in */ ahci = pci_create_simple_multifunction(host_bus, diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c index 667e882..a742fcb 100644 --- a/hw/isa/lpc_ich9.c +++ b/hw/isa/lpc_ich9.c @@ -312,6 +312,13 @@ PCIINTxRoute ich9_route_intx_pin_to_irq(void *opaque, int pirq_pin) return route; }
+void ich9_lpc_set_guest_info(PcGuestInfo *guest_info) +{ + guest_info->sci_int = 9; + guest_info->acpi_enable_cmd = ICH9_APM_ACPI_ENABLE; + guest_info->acpi_disable_cmd = ICH9_APM_ACPI_DISABLE; +} + static int ich9_lpc_sci_irq(ICH9LPCState *lpc) { switch (lpc->d.config[ICH9_LPC_ACPI_CTRL] & @@ -356,13 +363,13 @@ static void ich9_set_sci(void *opaque, int irq_num, int level) } }
-void ich9_lpc_pm_init(PCIDevice *lpc_pci) +void ich9_lpc_pm_init(PCIDevice *lpc_pci, PcGuestInfo *guest_info) { ICH9LPCState *lpc = ICH9_LPC_DEVICE(lpc_pci); qemu_irq *sci_irq;
sci_irq = qemu_allocate_irqs(ich9_set_sci, lpc, 1); - ich9_pm_init(lpc_pci, &lpc->pm, sci_irq[0]); + ich9_pm_init(lpc_pci, &lpc->pm, sci_irq[0], guest_info);
ich9_lpc_reset(&lpc->d.qdev); } diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c index 9d521cc..6ac08e1 100644 --- a/hw/mips/mips_malta.c +++ b/hw/mips/mips_malta.c @@ -965,7 +965,7 @@ void mips_malta_init(QEMUMachineInitArgs *args) pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1); pci_create_simple(pci_bus, piix4_devfn + 2, "piix4-usb-uhci"); smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100, - isa_get_irq(NULL, 9), NULL, 0, NULL); + isa_get_irq(NULL, 9), NULL, 0, NULL, NULL); /* TODO: Populate SPD eeprom data. */ smbus_eeprom_init(smbus, 8, NULL, 0); pit = pit_init(isa_bus, 0x40, 0, NULL); diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c index 8467f86..857f16c 100644 --- a/hw/pci-host/q35.c +++ b/hw/pci-host/q35.c @@ -243,6 +243,11 @@ static int mch_init(PCIDevice *d) hwaddr pci_hole64_size; MCHPCIState *mch = MCH_PCI_DEVICE(d);
+ mch->guest_info->mcfg_base = MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT; + /* Leave enough space for the biggest MCFG BAR */ + mch->guest_info->pci_info.w32.begin = mch->guest_info->mcfg_base + + MCH_HOST_BRIDGE_PCIEXBAR_MAX; + /* setup pci memory regions */ memory_region_init_alias(&mch->pci_hole, "pci-hole", mch->pci_address_space, diff --git a/include/hw/acpi/ich9.h b/include/hw/acpi/ich9.h index b1fe71f..66ab31a 100644 --- a/include/hw/acpi/ich9.h +++ b/include/hw/acpi/ich9.h @@ -45,7 +45,7 @@ typedef struct ICH9LPCPMRegs { } ICH9LPCPMRegs;
void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm, - qemu_irq sci_irq); + qemu_irq sci_irq, PcGuestInfo *guest_info); void ich9_pm_iospace_update(ICH9LPCPMRegs *pm, uint32_t pm_io_base); extern const VMStateDescription vmstate_ich9_pm;
diff --git a/include/hw/i386/ich9.h b/include/hw/i386/ich9.h index c5f637b..7428452 100644 --- a/include/hw/i386/ich9.h +++ b/include/hw/i386/ich9.h @@ -15,10 +15,11 @@ #include "hw/acpi/ich9.h" #include "hw/pci/pci_bus.h"
+void ich9_lpc_set_guest_info(PcGuestInfo *guest_info); void ich9_lpc_set_irq(void *opaque, int irq_num, int level); int ich9_lpc_map_irq(PCIDevice *pci_dev, int intx); PCIINTxRoute ich9_route_intx_pin_to_irq(void *opaque, int pirq_pin); -void ich9_lpc_pm_init(PCIDevice *pci_lpc); +void ich9_lpc_pm_init(PCIDevice *pci_lpc, PcGuestInfo *guest_info); PCIBus *ich9_d2pbr_init(PCIBus *bus, int devfn, int sec_bus); i2c_bus *ich9_smb_init(PCIBus *bus, int devfn, uint32_t smb_io_base);
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 1c2baaf..f8d0871 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -10,8 +10,48 @@ #include "exec/memory.h" #include "hw/i386/ioapic.h"
+#include "qemu/range.h" +#include "qemu/bitmap.h" +#include "sysemu/sysemu.h" +#include "hw/pci/pci.h" + /* PC-style peripherals (also used by other machines). */
+typedef struct PcPciInfo { + Range w32; + Range w64; +} PcPciInfo; + +/* Matches the value hard-coded in BIOS */ +#define PC_GUEST_PORT_ACPI_PM_BASE 0xb000 + +struct PcGuestInfo { + PcPciInfo pci_info; + hwaddr ram_size; + unsigned apic_id_limit; + bool apic_xrupt_override; + bool has_hpet; + uint64_t numa_nodes; + uint64_t *node_mem; + uint64_t *node_cpu; + DECLARE_BITMAP(found_cpus, MAX_CPUMASK_BITS + 1); + bool s3_disabled; + bool s4_disabled; + uint8_t s4_val; + DECLARE_BITMAP(slot_hotplug_enable, PCI_SLOT_MAX); + uint16_t sci_int; + uint8_t acpi_enable_cmd; + uint8_t acpi_disable_cmd; + uint32_t gpe0_blk; + uint32_t gpe0_blk_len; + bool fix_rtc; + bool platform_timer; + uint64_t mcfg_base; + const unsigned char *dsdt_code; + unsigned dsdt_size; + FWCfgState *fw_cfg; +}; + /* parallel.c */ static inline bool parallel_init(ISABus *bus, int index, CharDriverState *chr) { @@ -81,6 +121,10 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level); void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge); void pc_hot_add_cpu(const int64_t id, Error **errp); void pc_acpi_init(const char *default_dsdt); + +PcGuestInfo *pc_guest_info_init(ram_addr_t below_4g_mem_size, + ram_addr_t above_4g_mem_size); + FWCfgState *pc_memory_init(MemoryRegion *system_memory, const char *kernel_filename, const char *kernel_cmdline, @@ -88,13 +132,15 @@ FWCfgState *pc_memory_init(MemoryRegion *system_memory, ram_addr_t below_4g_mem_size, ram_addr_t above_4g_mem_size, MemoryRegion *rom_memory, - MemoryRegion **ram_memory); + MemoryRegion **ram_memory, + PcGuestInfo *guest_info); qemu_irq *pc_allocate_cpu_irq(void); DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus); void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi, ISADevice **rtc_state, ISADevice **floppy, - bool no_vmport); + bool no_vmport, + PcGuestInfo *guest_info); void pc_init_ne2k_isa(ISABus *bus, NICInfo *nd); void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size, const char *boot_device, @@ -112,7 +158,8 @@ void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name);
i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, qemu_irq sci_irq, qemu_irq smi_irq, - int kvm_enabled, FWCfgState *fw_cfg); + int kvm_enabled, FWCfgState *fw_cfg, + PcGuestInfo *guest_info); void piix4_smbus_register_device(SMBusDevice *dev, uint8_t addr);
/* hpet.c */ diff --git a/include/hw/pci-host/q35.h b/include/hw/pci-host/q35.h index e182c82..b083831 100644 --- a/include/hw/pci-host/q35.h +++ b/include/hw/pci-host/q35.h @@ -55,6 +55,7 @@ typedef struct MCHPCIState { uint8_t smm_enabled; ram_addr_t below_4g_mem_size; ram_addr_t above_4g_mem_size; + PcGuestInfo *guest_info; } MCHPCIState;
typedef struct Q35PCIHost { @@ -81,6 +82,7 @@ typedef struct Q35PCIHost { #define MCH_HOST_BRIDGE_PCIEXBAR 0x60 /* 64bit register */ #define MCH_HOST_BRIDGE_PCIEXBAR_SIZE 8 /* 64bit register */ #define MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT 0xb0000000 +#define MCH_HOST_BRIDGE_PCIEXBAR_MAX (0x10000000) /* 256M */ #define MCH_HOST_BRIDGE_PCIEXBAR_ADMSK Q35_MASK(64, 35, 28) #define MCH_HOST_BRIDGE_PCIEXBAR_128ADMSK ((uint64_t)(1 << 26)) #define MCH_HOST_BRIDGE_PCIEXBAR_64ADMSK ((uint64_t)(1 << 25)) diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h index afe4ec7..ec0d0d1 100644 --- a/include/qemu/typedefs.h +++ b/include/qemu/typedefs.h @@ -62,5 +62,6 @@ typedef struct VirtIODevice VirtIODevice; typedef struct QEMUSGList QEMUSGList; typedef struct SHPCDevice SHPCDevice; typedef struct FWCfgState FWCfgState; +typedef struct PcGuestInfo PcGuestInfo;
#endif /* QEMU_TYPEDEFS_H */
This adds C code for generating ACPI tables at runtime, imported from seabios git tree commit 51684b7ced75fb76776e8ee84833fcfb6ecf12dd
Although ACPI tables come from a system BIOS on real hw, it makes sense that the ACPI tables are coupled with the virtual machine, since they have to abstract the x86 machine to the OS's.
Several future developments that this will enable: - describe a complex configuration e.g. a bridged PCI topology to enable acpi hotplug of devices behind a bridge, or multi-root. - make it easier to use alternative firmware: any firmware can just load the ACPI tables from QEMU. case in point OVMF. - make it easier to add more chipsets without bumping into fw_cfg boundaries.
Notes: The code structure was intentionally kept as close to the seabios original as possible, to simplify comparison and making sure we didn't lose anything in translation.
Will be cleaned up and made closer to qemu style in follow-up patches.
ACPI tables are exposed to guest as FW_CFG entries. This means that this patch breaks migration to older qemu revisions. This will be fixed by follow-up patches.
This patch reuses some code from SeaBIOS, which was originally under LGPLv2 and then relicensed to GPLv3 or LGPLv3, in QEMU under GPLv2+. This relicensing has been acked by all contributors that had contributed to the code since the v2->v3 relicense. ACKs approving the v2+ relicensing are listed below. The list might include ACKs from people not holding copyright on any parts of the reused code, but it's better to err on the side of caution and include them.
Affected SeaBIOS files (GPLv2+ license headers added) http://thread.gmane.org/gmane.comp.bios.coreboot.seabios/5949:
src/acpi-dsdt-cpu-hotplug.dsl | 15 +++++++++++++++ src/acpi-dsdt-dbug.dsl | 15 +++++++++++++++ src/acpi-dsdt-hpet.dsl | 15 +++++++++++++++ src/acpi-dsdt-isa.dsl | 15 +++++++++++++++ src/acpi-dsdt-pci-crs.dsl | 15 +++++++++++++++ src/acpi.c | 14 +++++++++++++- src/acpi.h | 14 ++++++++++++++ src/ssdt-misc.dsl | 15 +++++++++++++++ src/ssdt-pcihp.dsl | 15 +++++++++++++++ src/ssdt-proc.dsl | 15 +++++++++++++++ tools/acpi_extract.py | 13 ++++++++++++- tools/acpi_extract_preprocess.py | 13 ++++++++++++- 12 files changed, 171 insertions(+), 3 deletions(-)
Each one of the listed people agreed to the following:
If you allow the use of your contribution in QEMU under the terms of GPLv2 or later as proposed by this patch, please respond to this mail including the line:
Acked-by: Name <email address>
Acked-by: Gerd Hoffmann kraxel@redhat.com Acked-by: Jan Kiszka jan.kiszka@siemens.com Acked-by: Jason Baron jbaron@akamai.com Acked-by: David Woodhouse David.Woodhouse@intel.com Acked-by: Gleb Natapov gleb@redhat.com Acked-by: Marcelo Tosatti mtosatti@redhat.com Acked-by: Dave Frodin dave.frodin@se-eng.com Acked-by: Paolo Bonzini pbonzini@redhat.com Acked-by: Kevin O'Connor kevin@koconnor.net Acked-by: Laszlo Ersek lersek@redhat.com Acked-by: Kenji Kaneshige kaneshige.kenji@jp.fujitsu.com Acked-by: Isaku Yamahata yamahata@valinux.co.jp Acked-by: Magnus Christensson magnus.christensson@intel.com Acked-by: Hu Tao hutao@cn.fujitsu.com Acked-by: Eduardo Habkost ehabkost@redhat.com
Signed-off-by: Michael S. Tsirkin mst@redhat.com --- hw/i386/Makefile.objs | 2 + hw/i386/acpi-build.c | 685 +++++++++++++++++++++++++++++++++++++++++++ hw/i386/pc.c | 2 + include/hw/i386/acpi-build.h | 9 + 4 files changed, 698 insertions(+) create mode 100644 hw/i386/acpi-build.c create mode 100644 include/hw/i386/acpi-build.h
diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs index e783050..2ab2572 100644 --- a/hw/i386/Makefile.objs +++ b/hw/i386/Makefile.objs @@ -4,7 +4,9 @@ obj-y += pc.o pc_piix.o pc_q35.o obj-$(CONFIG_XEN) += xen_domainbuild.o xen_machine_pv.o
obj-y += kvmvapic.o +obj-y += acpi-build.o obj-y += bios-linker-loader.o +hw/i386/acpi-build.o: hw/i386/acpi-build.c hw/i386/acpi-dsdt.hex hw/i386/ssdt-proc.hex hw/i386/ssdt-pcihp.hex hw/i386/ssdt-misc.hex hw/i386/q35-acpi-dsdt.hex hw/i386/pc_piix.o: hw/i386/pc_piix.c hw/i386/acpi-dsdt.hex hw/i386/pc_q35.o: hw/i386/pc_q35.c hw/i386/q35-acpi-dsdt.hex
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c new file mode 100644 index 0000000..72606a8 --- /dev/null +++ b/hw/i386/acpi-build.c @@ -0,0 +1,685 @@ +/* Support for generating ACPI tables and passing them to Guests + * + * Copyright (C) 2008-2010 Kevin O'Connor kevin@koconnor.net + * Copyright (C) 2006 Fabrice Bellard + * Copyright (C) 2013 Red Hat Inc + * + * Author: Michael S. Tsirkin mst@redhat.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that 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 "hw/i386/acpi-build.h" +#include <stddef.h> +#include <glib.h> +#include "qemu/bitmap.h" +#include "qemu/range.h" +#include "hw/pci/pci.h" +#include "qom/cpu.h" +#include "hw/i386/pc.h" +#include "target-i386/cpu.h" +#include "hw/timer/hpet.h" +#include "hw/i386/acpi-defs.h" +#include "hw/acpi/acpi.h" +#include "hw/nvram/fw_cfg.h" +#include "hw/i386/bios-linker-loader.h" + +#define ACPI_BUILD_APPNAME "Bochs" +#define ACPI_BUILD_APPNAME6 "BOCHS " +#define ACPI_BUILD_APPNAME4 "BXPC" + +#define ACPI_BUILD_DPRINTF(level, fmt, ...) do {} while(0) + +#define ACPI_BUILD_TABLE_FILE "etc/acpi/tables" +#define ACPI_BUILD_RSDP_FILE "etc/acpi/rsdp" + +static void +build_header(GArray *linker, GArray *table_data, + AcpiTableHeader *h, uint32_t sig, int len, uint8_t rev) +{ + h->signature = cpu_to_le32(sig); + h->length = cpu_to_le32(len); + h->revision = rev; + memcpy(h->oem_id, ACPI_BUILD_APPNAME6, 6); + memcpy(h->oem_table_id, ACPI_BUILD_APPNAME4, 4); + memcpy(h->oem_table_id + 4, (void*)&sig, 4); + h->oem_revision = cpu_to_le32(1); + memcpy(h->asl_compiler_id, ACPI_BUILD_APPNAME4, 4); + h->asl_compiler_revision = cpu_to_le32(1); + h->checksum = 0; + /* Checksum to be filled in by Guest linker */ + bios_linker_add_checksum(linker, ACPI_BUILD_TABLE_FILE, + table_data->data, h, len, &h->checksum); +} + +#define ACPI_PORT_SMI_CMD 0x00b2 /* TODO: this is APM_CNT_IOPORT */ +#define ACPI_PORT_PM_BASE 0xb000 + +static inline void *acpi_data_push(GArray *table_data, unsigned size) +{ + unsigned off = table_data->len; + g_array_set_size(table_data, off + size); + return table_data->data + off; +} + +static unsigned acpi_data_len(GArray *table) +{ + return table->len * g_array_get_element_size(table); +} + +static inline void acpi_add_table(GArray *table_offsets, GArray *table_data) +{ + uint32_t offset = cpu_to_le32(table_data->len); + g_array_append_val(table_offsets, offset); +} + +/* FACS */ +static void +build_facs(GArray *table_data, GArray *linker, PcGuestInfo *guest_info) +{ + AcpiFacsDescriptorRev1 *facs = acpi_data_push(table_data, sizeof *facs); + facs->signature = cpu_to_le32(ACPI_FACS_SIGNATURE); + facs->length = cpu_to_le32(sizeof(*facs)); +} + +/* Load chipset information into FADT */ +static void fadt_setup(AcpiFadtDescriptorRev1 *fadt, PcGuestInfo *guest_info) +{ + fadt->model = 1; + fadt->reserved1 = 0; + fadt->sci_int = cpu_to_le16(guest_info->sci_int); + fadt->smi_cmd = cpu_to_le32(ACPI_PORT_SMI_CMD); + fadt->acpi_enable = guest_info->acpi_enable_cmd; + fadt->acpi_disable = guest_info->acpi_disable_cmd; + fadt->pm1a_evt_blk = cpu_to_le32(ACPI_PORT_PM_BASE); + fadt->pm1a_cnt_blk = cpu_to_le32(ACPI_PORT_PM_BASE + 0x04); + fadt->pm_tmr_blk = cpu_to_le32(ACPI_PORT_PM_BASE + 0x08); + fadt->gpe0_blk = cpu_to_le32(guest_info->gpe0_blk); + fadt->pm1_evt_len = 4; + fadt->pm1_cnt_len = 2; + fadt->pm_tmr_len = 4; + fadt->gpe0_blk_len = guest_info->gpe0_blk_len; + fadt->plvl2_lat = cpu_to_le16(0xfff); /* C2 state not supported */ + fadt->plvl3_lat = cpu_to_le16(0xfff); /* C3 state not supported */ + fadt->flags = cpu_to_le32((1 << ACPI_FADT_F_WBINVD) | + (1 << ACPI_FADT_F_PROC_C1) | + (1 << ACPI_FADT_F_SLP_BUTTON) | + (1 << ACPI_FADT_F_RTC_S4)); + if (guest_info->fix_rtc) { + fadt->flags |= cpu_to_le32(1 << ACPI_FADT_F_FIX_RTC); + } + if (guest_info->platform_timer) { + fadt->flags |= cpu_to_le32(1 << ACPI_FADT_F_USE_PLATFORM_CLOCK); + } +} + + +/* FADT */ +static void +build_fadt(GArray *table_data, GArray *linker, PcGuestInfo *guest_info, + unsigned facs, unsigned dsdt) +{ + AcpiFadtDescriptorRev1 *fadt = acpi_data_push(table_data, sizeof(*fadt)); + + fadt->firmware_ctrl = cpu_to_le32(facs); + /* FACS address to be filled by Guest linker */ + bios_linker_add_pointer(linker, ACPI_BUILD_TABLE_FILE, ACPI_BUILD_TABLE_FILE, + table_data, &fadt->firmware_ctrl, + sizeof fadt->firmware_ctrl); + + fadt->dsdt = cpu_to_le32(dsdt); + /* DSDT address to be filled by Guest linker */ + bios_linker_add_pointer(linker, ACPI_BUILD_TABLE_FILE, ACPI_BUILD_TABLE_FILE, + table_data, &fadt->dsdt, + sizeof fadt->dsdt); + + fadt_setup(fadt, guest_info); + + build_header(linker, table_data, + (void*)fadt, ACPI_FACP_SIGNATURE, sizeof(*fadt), 1); +} + +static void +build_madt(GArray *table_data, GArray *linker, FWCfgState *fw_cfg, PcGuestInfo *guest_info) +{ + int madt_size; + + AcpiMultipleApicTable *madt; + AcpiMadtProcessorApic *apic; + AcpiMadtIoApic *io_apic; + AcpiMadtIntsrcovr *intsrcovr; + AcpiMadtLocalNmi *local_nmi; + + madt_size = (sizeof(AcpiMultipleApicTable) + + sizeof(AcpiMadtProcessorApic) * guest_info->apic_id_limit + + sizeof(AcpiMadtIoApic) + + sizeof(AcpiMadtIntsrcovr) * 16 + + sizeof(AcpiMadtLocalNmi)); + madt = acpi_data_push(table_data, madt_size); + madt->local_apic_address = cpu_to_le32(APIC_DEFAULT_ADDRESS); + madt->flags = cpu_to_le32(1); + apic = (void*)&madt[1]; + int i; + for (i=0; i < guest_info->apic_id_limit; i++) { + apic->type = ACPI_APIC_PROCESSOR; + apic->length = sizeof(*apic); + apic->processor_id = i; + apic->local_apic_id = i; + if (test_bit(i, guest_info->found_cpus)) + apic->flags = cpu_to_le32(1); + else + apic->flags = cpu_to_le32(0); + apic++; + } + io_apic = (void*)apic; + io_apic->type = ACPI_APIC_IO; + io_apic->length = sizeof(*io_apic); +#define ACPI_BUILD_IOAPIC_ID 0x0 + io_apic->io_apic_id = ACPI_BUILD_IOAPIC_ID; + io_apic->address = cpu_to_le32(IO_APIC_DEFAULT_ADDRESS); + io_apic->interrupt = cpu_to_le32(0); + + intsrcovr = (void*)&io_apic[1]; + if (guest_info->apic_xrupt_override) { + memset(intsrcovr, 0, sizeof(*intsrcovr)); + intsrcovr->type = ACPI_APIC_XRUPT_OVERRIDE; + intsrcovr->length = sizeof(*intsrcovr); + intsrcovr->source = 0; + intsrcovr->gsi = cpu_to_le32(2); + intsrcovr->flags = cpu_to_le16(0); /* conforms to bus specifications */ + intsrcovr++; + } + for (i = 1; i < 16; i++) { +#define ACPI_BUILD_PCI_IRQS ((1<<5) | (1<<9) | (1<<10) | (1<<11)) + if (!(ACPI_BUILD_PCI_IRQS & (1 << i))) + /* No need for a INT source override structure. */ + continue; + memset(intsrcovr, 0, sizeof(*intsrcovr)); + intsrcovr->type = ACPI_APIC_XRUPT_OVERRIDE; + intsrcovr->length = sizeof(*intsrcovr); + intsrcovr->source = i; + intsrcovr->gsi = cpu_to_le32(i); + intsrcovr->flags = cpu_to_le16(0xd); /* active high, level triggered */ + intsrcovr++; + } + + local_nmi = (void*)intsrcovr; + local_nmi->type = ACPI_APIC_LOCAL_NMI; + local_nmi->length = sizeof(*local_nmi); + local_nmi->processor_id = 0xff; /* all processors */ + local_nmi->flags = cpu_to_le16(0); + local_nmi->lint = 1; /* ACPI_LINT1 */ + local_nmi++; + + build_header(linker, table_data, + (void*)madt, ACPI_APIC_SIGNATURE, + (void*)local_nmi - (void*)madt, 1); +} + +/* Encode a hex value */ +static inline char acpi_get_hex(uint32_t val) { + val &= 0x0f; + return (val <= 9) ? ('0' + val) : ('A' + val - 10); +} + +/* Encode a length in an SSDT. */ +static uint8_t * +acpi_encode_len(uint8_t *ssdt_ptr, int length, int bytes) +{ + switch (bytes) { + default: + case 4: ssdt_ptr[3] = ((length >> 20) & 0xff); + case 3: ssdt_ptr[2] = ((length >> 12) & 0xff); + case 2: ssdt_ptr[1] = ((length >> 4) & 0xff); + ssdt_ptr[0] = (((bytes - 1) & 0x3) << 6) | (length & 0x0f); + break; + case 1: ssdt_ptr[0] = length & 0x3f; + } + return ssdt_ptr + bytes; +} + +#include "hw/i386/ssdt-proc.hex" + +/* 0x5B 0x83 ProcessorOp PkgLength NameString ProcID */ +#define ACPI_PROC_OFFSET_CPUHEX (*ssdt_proc_name - *ssdt_proc_start + 2) +#define ACPI_PROC_OFFSET_CPUID1 (*ssdt_proc_name - *ssdt_proc_start + 4) +#define ACPI_PROC_OFFSET_CPUID2 (*ssdt_proc_id - *ssdt_proc_start) +#define ACPI_PROC_SIZEOF (*ssdt_proc_end - *ssdt_proc_start) +#define ACPI_PROC_AML (ssdp_proc_aml + *ssdt_proc_start) + +/* 0x5B 0x82 DeviceOp PkgLength NameString */ +#define ACPI_PCIHP_OFFSET_HEX (*ssdt_pcihp_name - *ssdt_pcihp_start + 1) +#define ACPI_PCIHP_OFFSET_ID (*ssdt_pcihp_id - *ssdt_pcihp_start) +#define ACPI_PCIHP_OFFSET_ADR (*ssdt_pcihp_adr - *ssdt_pcihp_start) +#define ACPI_PCIHP_OFFSET_EJ0 (*ssdt_pcihp_ej0 - *ssdt_pcihp_start) +#define ACPI_PCIHP_SIZEOF (*ssdt_pcihp_end - *ssdt_pcihp_start) +#define ACPI_PCIHP_AML (ssdp_pcihp_aml + *ssdt_pcihp_start) + +#define ACPI_SSDT_SIGNATURE 0x54445353 /* SSDT */ +#define ACPI_SSDT_HEADER_LENGTH 36 + +#include "hw/i386/ssdt-misc.hex" +#include "hw/i386/ssdt-pcihp.hex" + +static uint8_t* +build_notify(uint8_t *ssdt_ptr, const char *name, int skip, int count, + const char *target, int ofs) +{ + int i; + + count -= skip; + + *(ssdt_ptr++) = 0x14; /* MethodOp */ + ssdt_ptr = acpi_encode_len(ssdt_ptr, 2+5+(12*count), 2); + memcpy(ssdt_ptr, name, 4); + ssdt_ptr += 4; + *(ssdt_ptr++) = 0x02; /* MethodOp */ + + for (i = skip; count-- > 0; i++) { + *(ssdt_ptr++) = 0xA0; /* IfOp */ + ssdt_ptr = acpi_encode_len(ssdt_ptr, 11, 1); + *(ssdt_ptr++) = 0x93; /* LEqualOp */ + *(ssdt_ptr++) = 0x68; /* Arg0Op */ + *(ssdt_ptr++) = 0x0A; /* BytePrefix */ + *(ssdt_ptr++) = i; + *(ssdt_ptr++) = 0x86; /* NotifyOp */ + memcpy(ssdt_ptr, target, 4); + ssdt_ptr[ofs] = acpi_get_hex(i >> 4); + ssdt_ptr[ofs + 1] = acpi_get_hex(i); + ssdt_ptr += 4; + *(ssdt_ptr++) = 0x69; /* Arg1Op */ + } + return ssdt_ptr; +} + +static void patch_pcihp(int slot, uint8_t *ssdt_ptr, uint32_t eject) +{ + ssdt_ptr[ACPI_PCIHP_OFFSET_HEX] = acpi_get_hex(slot >> 4); + ssdt_ptr[ACPI_PCIHP_OFFSET_HEX+1] = acpi_get_hex(slot); + ssdt_ptr[ACPI_PCIHP_OFFSET_ID] = slot; + ssdt_ptr[ACPI_PCIHP_OFFSET_ADR + 2] = slot; + + /* Runtime patching of ACPI_EJ0: to disable hotplug for a slot, + * replace the method name: _EJ0 by ACPI_EJ0_. */ + /* Sanity check */ + assert (!memcmp(ssdt_ptr + ACPI_PCIHP_OFFSET_EJ0, "_EJ0", 4)); + + if (!eject) { + memcpy(ssdt_ptr + ACPI_PCIHP_OFFSET_EJ0, "EJ0_", 4); + } +} + +static void +build_ssdt(GArray *table_data, GArray *linker, + FWCfgState *fw_cfg, PcGuestInfo *guest_info) +{ + int acpi_cpus = MIN(0xff, guest_info->apic_id_limit); + int length = (sizeof(ssdp_misc_aml) /* _S3_ / _S4_ / _S5_ */ + + (1+3+4) /* Scope(_SB_) */ + + (acpi_cpus * ACPI_PROC_SIZEOF) /* procs */ + + (1+2+5+(12*acpi_cpus)) /* NTFY */ + + (6+2+1+(1*acpi_cpus)) /* CPON */ + + (1+3+4) /* Scope(PCI0) */ + + ((PCI_SLOT_MAX - 1) * ACPI_PCIHP_SIZEOF) /* slots */ + + (1+2+5+(12*(PCI_SLOT_MAX - 1)))); /* PCNT */ + uint8_t *ssdt = acpi_data_push(table_data, length); + uint8_t *ssdt_ptr = ssdt; + + /* Copy header and encode fwcfg values in the S3_ / S4_ / S5_ packages */ + memcpy(ssdt_ptr, ssdp_misc_aml, sizeof(ssdp_misc_aml)); + if (guest_info->s3_disabled) { + ssdt_ptr[acpi_s3_name[0]] = 'X'; + } + if (guest_info->s4_disabled) { + ssdt_ptr[acpi_s4_name[0]] = 'X'; + } else { + ssdt_ptr[acpi_s4_pkg[0] + 1] = ssdt[acpi_s4_pkg[0] + 3] = + guest_info->s4_val; + } + + *(uint32_t*)&ssdt_ptr[acpi_pci32_start[0]] = + cpu_to_le32(guest_info->pci_info.w32.begin); + *(uint32_t*)&ssdt_ptr[acpi_pci32_end[0]] = + cpu_to_le32(guest_info->pci_info.w32.end - 1); + + if (range_valid(&guest_info->pci_info.w64)) { + ssdt_ptr[acpi_pci64_valid[0]] = 1; + *(uint64_t*)&ssdt_ptr[acpi_pci64_start[0]] = + cpu_to_le64(guest_info->pci_info.w64.begin); + *(uint64_t*)&ssdt_ptr[acpi_pci64_end[0]] = + cpu_to_le64(guest_info->pci_info.w64.end - 1); + *(uint64_t*)&ssdt_ptr[acpi_pci64_length[0]] = + cpu_to_le64(guest_info->pci_info.w64.end - + guest_info->pci_info.w64.begin); + } else { + ssdt_ptr[acpi_pci64_valid[0]] = 0; + } + + ssdt_ptr += sizeof(ssdp_misc_aml); + + /* build Scope(_SB_) header */ + *(ssdt_ptr++) = 0x10; /* ScopeOp */ + ssdt_ptr = acpi_encode_len(ssdt_ptr, length - (ssdt_ptr - ssdt), 3); + *(ssdt_ptr++) = '_'; + *(ssdt_ptr++) = 'S'; + *(ssdt_ptr++) = 'B'; + *(ssdt_ptr++) = '_'; + + /* build Processor object for each processor */ + int i; + for (i=0; i<acpi_cpus; i++) { + memcpy(ssdt_ptr, ACPI_PROC_AML, ACPI_PROC_SIZEOF); + ssdt_ptr[ACPI_PROC_OFFSET_CPUHEX] = acpi_get_hex(i >> 4); + ssdt_ptr[ACPI_PROC_OFFSET_CPUHEX+1] = acpi_get_hex(i); + ssdt_ptr[ACPI_PROC_OFFSET_CPUID1] = i; + ssdt_ptr[ACPI_PROC_OFFSET_CPUID2] = i; + ssdt_ptr += ACPI_PROC_SIZEOF; + } + + /* build "Method(NTFY, 2) {If (LEqual(Arg0, 0x00)) {Notify(CP00, Arg1)} ...}" */ + /* Arg0 = Processor ID = APIC ID */ + ssdt_ptr = build_notify(ssdt_ptr, "NTFY", 0, acpi_cpus, "CP00", 2); + + /* build "Name(CPON, Package() { One, One, ..., Zero, Zero, ... })" */ + *(ssdt_ptr++) = 0x08; /* NameOp */ + *(ssdt_ptr++) = 'C'; + *(ssdt_ptr++) = 'P'; + *(ssdt_ptr++) = 'O'; + *(ssdt_ptr++) = 'N'; + *(ssdt_ptr++) = 0x12; /* PackageOp */ + ssdt_ptr = acpi_encode_len(ssdt_ptr, 2+1+(1*acpi_cpus), 2); + *(ssdt_ptr++) = acpi_cpus; + for (i=0; i<acpi_cpus; i++) + *(ssdt_ptr++) = (test_bit(i, guest_info->found_cpus)) ? 0x01 : 0x00; + + /* build Scope(PCI0) opcode */ + *(ssdt_ptr++) = 0x10; /* ScopeOp */ + ssdt_ptr = acpi_encode_len(ssdt_ptr, length - (ssdt_ptr - ssdt), 3); + *(ssdt_ptr++) = 'P'; + *(ssdt_ptr++) = 'C'; + *(ssdt_ptr++) = 'I'; + *(ssdt_ptr++) = '0'; + + /* build Device object for each slot */ + for (i = 1; i < PCI_SLOT_MAX; i++) { + bool eject = test_bit(i, guest_info->slot_hotplug_enable); + memcpy(ssdt_ptr, ACPI_PCIHP_AML, ACPI_PCIHP_SIZEOF); + patch_pcihp(i, ssdt_ptr, eject); + ssdt_ptr += ACPI_PCIHP_SIZEOF; + } + + ssdt_ptr = build_notify(ssdt_ptr, "PCNT", 1, PCI_SLOT_MAX, "S00_", 1); + + build_header(linker, table_data, + (void*)ssdt, ACPI_SSDT_SIGNATURE, ssdt_ptr - ssdt, 1); +} + +static void +build_hpet(GArray *table_data, GArray *linker) +{ + Acpi20Hpet *hpet; + + hpet = acpi_data_push(table_data, sizeof(*hpet)); + /* Note timer_block_id value must be kept in sync with value advertised by + * emulated hpet + */ + hpet->timer_block_id = cpu_to_le32(0x8086a201); + hpet->addr.address = cpu_to_le64(HPET_BASE); + build_header(linker, table_data, + (void*)hpet, ACPI_HPET_SIGNATURE, sizeof(*hpet), 1); +} + +static void +acpi_build_srat_memory(AcpiSratMemoryAffinity *numamem, + uint64_t base, uint64_t len, int node, int enabled) +{ + numamem->type = ACPI_SRAT_MEMORY; + numamem->length = sizeof(*numamem); + memset(numamem->proximity, 0, 4); + numamem->proximity[0] = node; + numamem->flags = cpu_to_le32(!!enabled); + numamem->base_addr = cpu_to_le64(base); + numamem->range_length = cpu_to_le64(len); +} + +static void +build_srat(GArray *table_data, GArray *linker, + FWCfgState *fw_cfg, PcGuestInfo *guest_info) +{ + AcpiSystemResourceAffinityTable *srat; + AcpiSratProcessorAffinity *core; + AcpiSratMemoryAffinity *numamem; + + int i; + uint64_t curnode; + int srat_size; + int slots; + uint64_t mem_len, mem_base, next_base; + + srat_size = sizeof(*srat) + + sizeof(AcpiSratProcessorAffinity) * guest_info->apic_id_limit + + sizeof(AcpiSratMemoryAffinity) * (guest_info->numa_nodes + 2); + + srat = acpi_data_push(table_data, srat_size); + srat->reserved1 = cpu_to_le32(1); + core = (void*)(srat + 1); + + for (i = 0; i < guest_info->apic_id_limit; ++i) { + core->type = ACPI_SRAT_PROCESSOR; + core->length = sizeof(*core); + core->local_apic_id = i; + curnode = guest_info->node_cpu[i]; + core->proximity_lo = curnode; + memset(core->proximity_hi, 0, 3); + core->local_sapic_eid = 0; + if (test_bit(i, guest_info->found_cpus)) + core->flags = cpu_to_le32(1); + else + core->flags = cpu_to_le32(0); + core++; + } + + + /* the memory map is a bit tricky, it contains at least one hole + * from 640k-1M and possibly another one from 3.5G-4G. + */ + numamem = (void*)core; + slots = 0; + next_base = 0; + + acpi_build_srat_memory(numamem, 0, 640*1024, 0, 1); + next_base = 1024 * 1024; + numamem++; + slots++; + for (i = 1; i < guest_info->numa_nodes + 1; ++i) { + mem_base = next_base; + mem_len = guest_info->node_mem[i - 1]; + if (i == 1) + mem_len -= 1024 * 1024; + next_base = mem_base + mem_len; + + /* Cut out the ACPI_PCI hole */ + if (mem_base <= guest_info->ram_size && + next_base > guest_info->ram_size) { + mem_len -= next_base - guest_info->ram_size; + if (mem_len > 0) { + acpi_build_srat_memory(numamem, mem_base, mem_len, i-1, 1); + numamem++; + slots++; + } + mem_base = 1ULL << 32; + mem_len = next_base - guest_info->ram_size; + next_base += (1ULL << 32) - guest_info->ram_size; + } + acpi_build_srat_memory(numamem, mem_base, mem_len, i-1, 1); + numamem++; + slots++; + } + for (; slots < guest_info->numa_nodes + 2; slots++) { + acpi_build_srat_memory(numamem, 0, 0, 0, 0); + numamem++; + } + + build_header(linker, table_data, + (void*)srat, ACPI_SRAT_SIGNATURE, srat_size, 1); +} + +static void +build_mcfg_q35(GArray *table_data, GArray *linker, PcGuestInfo *guest_info) +{ + AcpiTableMcfg *mcfg; + + int len = sizeof(*mcfg) + 1 * sizeof(mcfg->allocation[0]); + mcfg = acpi_data_push(table_data, len); + mcfg->allocation[0].address = cpu_to_le64(guest_info->mcfg_base); + /* Only a single allocation so no need to play with segments */ + mcfg->allocation[0].pci_segment = cpu_to_le16(0); + mcfg->allocation[0].start_bus_number = 0; + mcfg->allocation[0].end_bus_number = 0xFF; + + build_header(linker, table_data, (void *)mcfg, ACPI_MCFG_SIGNATURE, len, 1); +} + +static void +build_dsdt(GArray *table_data, GArray *linker, PcGuestInfo *guest_info) +{ + void *dsdt; + assert(guest_info->dsdt_code && guest_info->dsdt_size); + dsdt = acpi_data_push(table_data, guest_info->dsdt_size); + memcpy(dsdt, guest_info->dsdt_code, guest_info->dsdt_size); +} + +/* Build final rsdt table */ +static void +build_rsdt(GArray *table_data, GArray *linker, GArray *table_offsets) +{ + AcpiRsdtDescriptorRev1 *rsdt; + size_t rsdt_len; + int i; + + rsdt_len = sizeof(*rsdt) + sizeof(uint32_t) * table_offsets->len; + rsdt = acpi_data_push(table_data, rsdt_len); + memcpy(rsdt->table_offset_entry, table_offsets->data, + sizeof(uint32_t) * table_offsets->len); + for (i = 0; i < table_offsets->len; ++i) { + /* rsdt->table_offset_entry to be filled by Guest linker */ + bios_linker_add_pointer(linker, + ACPI_BUILD_TABLE_FILE, ACPI_BUILD_TABLE_FILE, + table_data, &rsdt->table_offset_entry[i], + sizeof(uint32_t)); + } + build_header(linker, table_data, + (void*)rsdt, ACPI_RSDT_SIGNATURE, rsdt_len, 1); +} + +static GArray * +build_rsdp(GArray *linker, unsigned rsdt) +{ + GArray *rsdp_table; + AcpiRsdpDescriptor *rsdp; + + rsdp_table = g_array_new(false, true /* clear */, sizeof *rsdp); + g_array_set_size(rsdp_table, 1); + rsdp = (void *)rsdp_table->data; + + bios_linker_alloc(linker, ACPI_BUILD_RSDP_FILE, 1, true /* fseg memory */); + + rsdp->signature = cpu_to_le64(ACPI_RSDP_SIGNATURE); + memcpy(rsdp->oem_id, ACPI_BUILD_APPNAME6, 6); + rsdp->rsdt_physical_address = cpu_to_le32(rsdt); + /* Address to be filled by Guest linker */ + bios_linker_add_pointer(linker, ACPI_BUILD_RSDP_FILE, ACPI_BUILD_TABLE_FILE, + rsdp_table, &rsdp->rsdt_physical_address, + sizeof rsdp->rsdt_physical_address); + rsdp->checksum = 0; + /* Checksum to be filled by Guest linker */ + bios_linker_add_checksum(linker, ACPI_BUILD_RSDP_FILE, + rsdp, rsdp, sizeof *rsdp, &rsdp->checksum); + + return rsdp_table; +} + +#define ACPI_MAX_ACPI_TABLES 20 +void acpi_setup(PcGuestInfo *guest_info) +{ + GArray *table_data, *table_offsets, *rsdp, *linker; + unsigned facs, dsdt, rsdt; + + if (!guest_info->fw_cfg) { + ACPI_BUILD_DPRINTF(3, "No fw cfg. Boiling out.\n"); + } + + table_data = g_array_new(false, true /* clear */, 1); + table_offsets = g_array_new(false, true /* clear */, + sizeof(uint32_t)); + linker = bios_linker_init(); + + ACPI_BUILD_DPRINTF(3, "init ACPI tables\n"); + + bios_linker_alloc(linker, ACPI_BUILD_TABLE_FILE, 64 /* Ensure FACS is aligned */, + false /* high memory */); + + /* + * FACS is pointed to by FADT. + * We place it first since it's the only table that has alignment + * requirements. + */ + facs = table_data->len; + build_facs(table_data, linker, guest_info); + + /* DSDT is pointed to by FADT */ + dsdt = table_data->len; + build_dsdt(table_data, linker, guest_info); + + /* ACPI tables pointed to by RSDT */ + acpi_add_table(table_offsets, table_data); + build_fadt(table_data, linker, guest_info, facs, dsdt); + acpi_add_table(table_offsets, table_data); + build_ssdt(table_data, linker, guest_info->fw_cfg, guest_info); + acpi_add_table(table_offsets, table_data); + build_madt(table_data, linker, guest_info->fw_cfg, guest_info); + acpi_add_table(table_offsets, table_data); + if (guest_info->has_hpet) { + build_hpet(table_data, linker); + } + if (guest_info->numa_nodes) { + acpi_add_table(table_offsets, table_data); + build_srat(table_data, linker, guest_info->fw_cfg, guest_info); + } + if (guest_info->mcfg_base) { + acpi_add_table(table_offsets, table_data); + build_mcfg_q35(table_data, linker, guest_info); + } + + /* RSDT is pointed to by RSDP */ + rsdt = table_data->len; + build_rsdt(table_data, linker, table_offsets); + + /* RSDP is in FSEG memory, so allocate it separately */ + rsdp = build_rsdp(linker, rsdt); + + /* Now expose it all to Guest */ + fw_cfg_add_file(guest_info->fw_cfg, ACPI_BUILD_TABLE_FILE, + table_data->data, table_data->len); + fw_cfg_add_file(guest_info->fw_cfg, ACPI_BUILD_RSDP_FILE, + rsdp->data, acpi_data_len(rsdp)); + fw_cfg_add_file(guest_info->fw_cfg, "etc/linker-script", + linker->data, acpi_data_len(linker)); + + /* Cleanup GArray wrappers and memory if no longer used. */ + bios_linker_cleanup(linker); + g_array_free(table_offsets, true); + g_array_free(rsdp, false); + g_array_free(table_data, false); +} diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 68d2610..af414a4 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -55,6 +55,7 @@ #include "hw/acpi/acpi.h" #include "hw/cpu/icc_bus.h" #include "hw/boards.h" +#include "hw/i386/acpi-build.h"
/* debug PC/ISA interrupts */ //#define DEBUG_IRQ @@ -1029,6 +1030,7 @@ void pc_guest_info_machine_done(Notifier *notifier, void *data) PcGuestInfoState, machine_done); pc_fw_cfg_guest_info(&guest_info_state->info); + acpi_setup(&guest_info_state->info); }
PcGuestInfo *pc_guest_info_init(ram_addr_t below_4g_mem_size, diff --git a/include/hw/i386/acpi-build.h b/include/hw/i386/acpi-build.h new file mode 100644 index 0000000..e57b1aa --- /dev/null +++ b/include/hw/i386/acpi-build.h @@ -0,0 +1,9 @@ + +#ifndef HW_I386_ACPI_BUILD_H +#define HW_I386_ACPI_BUILD_H + +#include "qemu/typedefs.h" + +void acpi_setup(PcGuestInfo *); + +#endif
Guest currently has to jump through lots of hoops to guess the PCI hole ranges. It's fragile, and makes us change BIOS each time we add a new chipset. Let's report the window in a ROM file, to make BIOS do exactly what QEMU intends.
Signed-off-by: Michael S. Tsirkin mst@redhat.com --- hw/i386/pc.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+)
diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 203c683..68d2610 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -997,6 +997,26 @@ static void pc_set_cpu_guest_info(CPUState *cpu, void *arg) } }
+/* pci-info ROM file. Little endian format */ +typedef struct PcRomPciInfo { + uint64_t w32_min; + uint64_t w32_max; + uint64_t w64_min; + uint64_t w64_max; +} PcRomPciInfo; + +static void pc_fw_cfg_guest_info(PcGuestInfo *guest_info) +{ + PcRomPciInfo *info = g_malloc(sizeof *info); + info->w32_min = cpu_to_le64(guest_info->pci_info.w32.begin); + info->w32_max = cpu_to_le64(guest_info->pci_info.w32.end); + info->w64_min = cpu_to_le64(guest_info->pci_info.w64.begin); + info->w64_max = cpu_to_le64(guest_info->pci_info.w64.end); + /* Pass PCI hole info to guest via a side channel. + * Required so guest PCI enumeration does the right thing. */ + fw_cfg_add_file(guest_info->fw_cfg, "etc/pci-info", info, sizeof *info); +} + typedef struct PcGuestInfoState { PcGuestInfo info; Notifier machine_done; @@ -1008,6 +1028,7 @@ void pc_guest_info_machine_done(Notifier *notifier, void *data) PcGuestInfoState *guest_info_state = container_of(notifier, PcGuestInfoState, machine_done); + pc_fw_cfg_guest_info(&guest_info_state->info); }
PcGuestInfo *pc_guest_info_init(ram_addr_t below_4g_mem_size,
"Michael S. Tsirkin" mst@redhat.com writes:
This patchset moves all generation of ACPI tables from guest BIOS to the hypervisor.
Although ACPI tables come from a system BIOS on real hw, it makes sense that the ACPI tables are coupled with the virtual machine, since they have to abstract the x86 machine to the OS's.
Several future developments that this will enable:
- make it easier to use alternative firmware: any firmware can just load the ACPI tables from QEMU. case in point OVMF.
UEFI obviously can create ACPI tables already so I don't think this is a valid advantage.
You could use this argument to say that QEMU should implement int13 or int10 too...
- make it easier to add more chipsets without bumping into fw_cfg boundaries.
But then you're just introducing a different boundary (the ACPI tables).
fw_cfg is a cross-platform interface so it makes a lot more sense to add more features to it to better enumerate the underlying platform.
- describe a complex configuration e.g. a bridged PCI topology to enable acpi hotplug of devices behind a PCI bridge, or for multi-root topology.
This has strong analogies to generating device trees and is also a good reason why exposing this information via a common interface (fw_cfg) would be a good idea.
If you look at the actual code: i386: imports ACPI table generation code from seabios you will see that it's more complex than it needs to be, with lots of low level casts and similar tricks.
There's also a bit of duplication where we already declare similar acpi structures in qemu.
This is the result of code being a direct port from seabios. Laszlo's patch (build ACPI MADT (APIC) for fw_cfg) shows how this will be cleaned up by follow-up work. I think it's best to do it in this order: port code directly, and apply cleanups and reduce duplication that results, on top. This way it's much easier to see that we don't introduce regressions.
In particular, for a simple VM with piix, I booted a guest on qemu with and without the change, and verified that ACPI tables are unchanged except for trivial pointer address changes.
Such binary compatibility makes it easier to be confident that this change won't break things.
So the idea is Laszlo's patchset (patches 2-7) will be rebased on top of this patchset, this way we'll get small cleanup changes, where each step is easy to verify as not changing anything from Guest POV.
One issue this patchset creates is cross-version migration. Specifically migration to qemu 1.5 will not work if it happens while bios is accessing fw_cfg when we migrate. This is a general problem of the fw_cfg implementation, I plan to extend fw_cfg implementation to address this.
I plan to test q35 and numa setups before I submit this for inclusion, in a similar way.
git trees, for those interested in testing this:
git://git.kernel.org/pub/scm/virt/kvm/mst/qemu.git acpi
git://git.kernel.org/pub/scm/virt/kvm/mst/seabios.git acpi
bios patchset will be posted tomorrow (need to clean up the commit log a bit).
I don't think it's a good idea to move BIOS functionality in QEMU.
We don't frequently add firmware or chipsets so it seems like we're optimizing for an uncommon scenario here.
Regards,
Anthony Liguori
Laszlo Ersek (1): refer to FWCfgState explicitly
Michael S. Tsirkin (12): apic: rename apic specific bitopts hw/i386/pc.c: move IO_APIC_DEFAULT_ADDRESS to include/hw/i386/apic.h fw_cfg: move typedef to qemu/typedefs.h i386: add ACPI table files from seabios acpi: add rules to compile ASL source acpi: pre-compiled ASL files range: add Range structure i386: add bios linker/loader i386: generate pc guest info pc: pass PCI hole ranges to Guests i386: ACPI table generation code from seabios pc: reuse guest info for legacy fw cfg
configure | 9 +- hw/acpi/ich9.c | 7 +- hw/acpi/piix4.c | 44 +- hw/core/loader.c | 2 +- hw/i386/Makefile.objs | 27 + hw/i386/acpi-build.c | 685 ++++ hw/i386/acpi-dsdt-cpu-hotplug.dsl | 93 + hw/i386/acpi-dsdt-dbug.dsl | 41 + hw/i386/acpi-dsdt-hpet.dsl | 51 + hw/i386/acpi-dsdt-isa.dsl | 117 + hw/i386/acpi-dsdt-pci-crs.dsl | 105 + hw/i386/acpi-dsdt.dsl | 343 ++ hw/i386/acpi-dsdt.hex.generated | 4409 ++++++++++++++++++++ hw/i386/bios-linker-loader.c | 155 + hw/i386/multiboot.c | 2 +- hw/i386/multiboot.h | 4 +- hw/i386/pc.c | 159 +- hw/i386/pc_piix.c | 28 +- hw/i386/pc_q35.c | 14 +- hw/i386/q35-acpi-dsdt.dsl | 452 +++ hw/i386/q35-acpi-dsdt.hex.generated | 7346 ++++++++++++++++++++++++++++++++++ hw/i386/ssdt-misc.dsl | 73 + hw/i386/ssdt-misc.hex.generated | 190 + hw/i386/ssdt-pcihp.dsl | 51 + hw/i386/ssdt-pcihp.hex.generated | 108 + hw/i386/ssdt-proc.dsl | 63 + hw/i386/ssdt-proc.hex.generated | 134 + hw/intc/apic.c | 42 +- hw/isa/lpc_ich9.c | 11 +- hw/mips/mips_malta.c | 2 +- hw/pci-host/q35.c | 5 + hw/sparc/sun4m.c | 6 +- hw/sparc64/sun4u.c | 2 +- include/hw/acpi/ich9.h | 2 +- include/hw/i386/acpi-build.h | 9 + include/hw/i386/apic.h | 2 + include/hw/i386/bios-linker-loader.h | 26 + include/hw/i386/ich9.h | 3 +- include/hw/i386/pc.h | 67 +- include/hw/loader.h | 3 +- include/hw/nvram/fw_cfg.h | 2 +- include/hw/pci-host/q35.h | 2 + include/qemu/range.h | 22 + include/qemu/typedefs.h | 2 + scripts/acpi_extract.py | 362 ++ scripts/acpi_extract_preprocess.py | 52 + scripts/update-acpi.sh | 4 + 47 files changed, 15248 insertions(+), 90 deletions(-) create mode 100644 hw/i386/acpi-build.c create mode 100644 hw/i386/acpi-dsdt-cpu-hotplug.dsl create mode 100644 hw/i386/acpi-dsdt-dbug.dsl create mode 100644 hw/i386/acpi-dsdt-hpet.dsl create mode 100644 hw/i386/acpi-dsdt-isa.dsl create mode 100644 hw/i386/acpi-dsdt-pci-crs.dsl create mode 100644 hw/i386/acpi-dsdt.dsl create mode 100644 hw/i386/acpi-dsdt.hex.generated create mode 100644 hw/i386/bios-linker-loader.c create mode 100644 hw/i386/q35-acpi-dsdt.dsl create mode 100644 hw/i386/q35-acpi-dsdt.hex.generated create mode 100644 hw/i386/ssdt-misc.dsl create mode 100644 hw/i386/ssdt-misc.hex.generated create mode 100644 hw/i386/ssdt-pcihp.dsl create mode 100644 hw/i386/ssdt-pcihp.hex.generated create mode 100644 hw/i386/ssdt-proc.dsl create mode 100644 hw/i386/ssdt-proc.hex.generated create mode 100644 include/hw/i386/acpi-build.h create mode 100644 include/hw/i386/bios-linker-loader.h create mode 100755 scripts/acpi_extract.py create mode 100755 scripts/acpi_extract_preprocess.py create mode 100644 scripts/update-acpi.sh
-- MST
On Mon, May 13, 2013 at 03:38:51PM -0500, Anthony Liguori wrote:
"Michael S. Tsirkin" mst@redhat.com writes:
git trees, for those interested in testing this:
git://git.kernel.org/pub/scm/virt/kvm/mst/qemu.git acpi
git://git.kernel.org/pub/scm/virt/kvm/mst/seabios.git acpi
bios patchset will be posted tomorrow (need to clean up the commit log a bit).
I don't think it's a good idea to move BIOS functionality in QEMU.
We don't frequently add firmware or chipsets so it seems like we're optimizing for an uncommon scenario here.
Your objection has come as a surprise to me. Are you stating that you don't think QEMU should generate the ACPI tables and pass them through to SeaBIOS via fw_cfg?
I do think it would be worthwhile to do the above. If we look at the ACPI tables that are currently generated in SeaBIOS, nearly every field describes the hardware. (I've described this in some detail at: http://lists.gnu.org/archive/html/qemu-devel/2013-02/msg04417.html ) When generating ACPI tables, SeaBIOS can only guess at what the QEMU hardware is or it must receive the hardware details directly from QEMU.
When receiving hardware information from QEMU today, a one-off fw_cfg format is inevitably created. Currently there are seven different fw_cfg entries that control various "bios tables". (These are "irq0-override", "system-states", "numa-nodes", "acpi tables", "smbios tables", "pvpanic-port", and "max cpus".) Of these, only one has any use directly to SeaBIOS (max cpus) - the rest are purely pass through to one or more of the various guest visible bios tables.
The problem with generating custom fw_cfg structures to describe the hardware, is that it inevitably causes the creation of new (poorly documented) structures that serve only to pass the info so another program can create an industry standard structure with the info. A good example of this is the FW_CFG_NUMA entry. If one looks at the definition of this fw_cfg structure (see hw/i386/pc.c:bochs_bios_init) they will find a complex structure (it's actually two dynamically sized arrays of two different values with the size of the first dynamically sized array determined by the FW_CFG_MAX_CPUS fw_cfg entry). This undocumented fw_cfg structure serves no purpose other than to generate an ACPI SRAT table. Had QEMU just populated an SRAT table and put it into a fw_cfg entry then there would be a much better documented and understood interface. Had SeaBIOS wanted to know the numa information (it doesn't) it would be much easier for it to parse out the well documented ACPI SRAT table passed via fw_cfg then it would be for it to handle the cumbersome undocumented fw_cfg entry present today.
There have been several requests recently to add more enhanced and detailed ACPI tables to SeaBIOS that require new custom fw_cfg entries. I've been pushing back on them because I don't wish to invent new custom fw_cfg entries and propagate the code throughout QEMU and SeaBIOS, when the sole goal is to create an industry standard ACPI table. We're better off accepting that the goal is an ACPI table, that only QEMU has the knowledge to generate it, and that QEMU is the best place to generate it.
Hopefully I've misunderstood your objection or you will reconsider.
Cheers, -Kevin
Hi,
Several future developments that this will enable:
- make it easier to use alternative firmware: any firmware can just load the ACPI tables from QEMU. case in point OVMF.
UEFI obviously can create ACPI tables already so I don't think this is a valid advantage.
Yea, but it doesn't do all the patching seabios does, so some features simply don't work. Generating the tables in qemu instead will zap those differnces and will make it alot easier to bring all firmware images (seabios, ovmf, coreboot, ...) to feature parity without duplicating the code needed for that in all firmwares.
You could use this argument to say that QEMU should implement int13 or int10 too...
This is comparing apples and oranges.
This has strong analogies to generating device trees
Indeed, both acpi and device trees describe the hardware emulated by qemu. Comparing acpi + device trees makes alot more sense than comparing acpi with int10 ...
and is also a good reason why exposing this information via a common interface (fw_cfg) would be a good idea.
Huh? As far I know we generate device trees in qemu instead of expecting pseries firmware compile them from fw_cfg information.
cheers, Gerd
On 14 May 2013 10:29, Gerd Hoffmann kraxel@redhat.com wrote:
Anthony wrote:
and is also a good reason why exposing this information via a common interface (fw_cfg) would be a good idea.
Huh? As far I know we generate device trees in qemu
It depends. For ARM we insist that the user provides the device tree that corresponds to the kernel they're going to run, and then we just tweak it a bit. (For the upcoming 'mach-virt' pure-virtual hardware we're going to end up generating a device tree completely from scratch, though.)
Not sure fw_cfg is particularly relevant though -- for device tree the obvious "nice" way to do it would be to have the device tree generating/modifying code able to walk the QOM object tree introspecting it to identify hardware presence and properties. That's probably not doable today though. (I need to look more closely at PPC device tree handling, really.)
thanks -- PMM
Gerd Hoffmann kraxel@redhat.com writes:
Hi,
Several future developments that this will enable:
- make it easier to use alternative firmware: any firmware can just load the ACPI tables from QEMU. case in point OVMF.
UEFI obviously can create ACPI tables already so I don't think this is a valid advantage.
Yea, but it doesn't do all the patching seabios does, so some features simply don't work. Generating the tables in qemu instead will zap those differnces and will make it alot easier to bring all firmware images (seabios, ovmf, coreboot, ...) to feature parity without duplicating the code needed for that in all firmwares.
The fact that different firmwares duplicate functionality is the based on the fact that the different firmwares inheritently duplication functionality by the virtue of being different projects.
You could use this argument to say that QEMU should implement int13 or int10 too...
This is comparing apples and oranges.
This has strong analogies to generating device trees
Indeed, both acpi and device trees describe the hardware emulated by qemu. Comparing acpi + device trees makes alot more sense than comparing acpi with int10 ...
and is also a good reason why exposing this information via a common interface (fw_cfg) would be a good idea.
Huh? As far I know we generate device trees in qemu instead of expecting pseries firmware compile them from fw_cfg information.
It depends on what firmware you are using.
We don't really generate device trees in general in QEMU.
As Peter mentioned, in an ideal world we'd generate them from the QOM graph. That should happen in the firmware and it could be enabled by adding just a couple fw_cfg commands to navigate the QOM graph (analogs to qom-list and qom-get in QMP).
Regards,
Anthony Liguori
cheers, Gerd
Hi,
and is also a good reason why exposing this information via a common interface (fw_cfg) would be a good idea.
Huh? As far I know we generate device trees in qemu instead of expecting pseries firmware compile them from fw_cfg information.
It depends on what firmware you are using.
Of course. On archs which don't use device trees in the first place it doesn't make sense.
We don't really generate device trees in general in QEMU.
pseries does (thats why the hard libfdt dependency if you want pseries support). arm wants move into that direction too.
As Peter mentioned, in an ideal world we'd generate them from the QOM graph.
Sure.
That should happen in the firmware and it could be enabled by adding just a couple fw_cfg commands to navigate the QOM graph (analogs to qom-list and qom-get in QMP).
I don't think Peter intended to imply *that* ...
cheers, Gerd
Gerd Hoffmann kraxel@redhat.com writes:
Hi,
and is also a good reason why exposing this information via a common interface (fw_cfg) would be a good idea.
Huh? As far I know we generate device trees in qemu instead of expecting pseries firmware compile them from fw_cfg information.
It depends on what firmware you are using.
Of course. On archs which don't use device trees in the first place it doesn't make sense.
We don't really generate device trees in general in QEMU.
pseries does (thats why the hard libfdt dependency if you want pseries support). arm wants move into that direction too.
pseries is a bad example because it's not a real hardware platform. It's emulating what PowerVM does. It's more akin to the xenpv machine than a real piece of hardware.
As Peter mentioned, in an ideal world we'd generate them from the QOM graph.
Sure.
That should happen in the firmware and it could be enabled by adding just a couple fw_cfg commands to navigate the QOM graph (analogs to qom-list and qom-get in QMP).
I don't think Peter intended to imply *that* ...
Yes, this has been discussed dozens of times in the past. And as I've said in the past, generating device trees belongs in the firmware. It's a firmware/OS interface.
It's not just an academic argument though. We want to expose hardware interfaces that are rich enough for firmware to do whatever it needs to do to initialize the system. There are a lot of things that are normally only visible to firmware that we don't emulate today.
In exposing this information, we ought to attempt to do so in an architectural neutral way.
ACPI is not architectural neutral. You could argue that that's okay because we only need to support two things: ACPI and device trees. But that's not quite right.
Device trees very often have platform specific quirks so a generated device tree in common code is not going to have the right set of quirks for any given system.
Having a good interface for firmware to generate ACPI tables and device trees solves this problem in a much nicer way. It enables firmware to display whatever type of tree it wants (ACPI or device tree) and also provides the flexibility to implement the necessary quirks for that platform.
Regards,
Anthony Liguori
cheers, Gerd
On Mon, May 13, 2013 at 03:38:51PM -0500, Anthony Liguori wrote:
I don't think it's a good idea to move BIOS functionality in QEMU.
Just to clarify: generating ACPI tables is not BIOS functionality. It ended up in seabios for historical reasons.
A normal scenario for ACPI tables is that they are written in ASL and compiled with IASL. The tables are then stored in some ROM device - most of them, except FACP, can actually be mapped directly from ROM if necessary.
You won't normally find real BIOS probing PCI slots for hotplug support and writing EJ0 methods dynamically - instead the assumption is that hardware (in this case QEMU) supplies its own static description in form of ACPI tables.
My patchset uses FW_CFG as such a ROM device. It would be easy to switch to something else instead of FW_CFG. Is this what you are suggesting?
"Michael S. Tsirkin" mst@redhat.com writes:
On Mon, May 13, 2013 at 03:38:51PM -0500, Anthony Liguori wrote:
I don't think it's a good idea to move BIOS functionality in QEMU.
Just to clarify: generating ACPI tables is not BIOS functionality. It ended up in seabios for historical reasons.
A normal scenario for ACPI tables is that they are written in ASL and compiled with IASL.
I wouldn't call this the normal scenario. Some tables are static but more tables are dynamic than you'd think. If you're a firmware engineer and you have to support dozens of platforms, it's much easier to make the tables dynamic than attempt to maintain dozens of ASL descriptions.
A lot of what you'd consider to be static is actually dynamic in a multi-node system.
The tables are then stored in some ROM device - most of them, except FACP, can actually be mapped directly from ROM if necessary.
You won't normally find real BIOS probing PCI slots for hotplug support and writing EJ0 methods dynamically - instead the assumption is that hardware (in this case QEMU) supplies its own static description in form of ACPI tables.
Actually, this is a very good example. In more modern boxes like Flex, there's a PCI-Express backplane that all of the nodes are connected to with a common set of slots for all nodes. You can configure in firmware how the slots map to each node.
I can share an acpi dump from one of these systems when after I head into the office this morning.
This is what's nice about a switched PCI complex. You have tremendous amounts of flexibility in how you set things up.
Regards,
Anthony Liguori
My patchset uses FW_CFG as such a ROM device. It would be easy to switch to something else instead of FW_CFG. Is this what you are suggesting?
-- MST
On Tue, May 14, 2013 at 08:34:43AM -0500, Anthony Liguori wrote:
"Michael S. Tsirkin" mst@redhat.com writes:
On Mon, May 13, 2013 at 03:38:51PM -0500, Anthony Liguori wrote:
I don't think it's a good idea to move BIOS functionality in QEMU.
Just to clarify: generating ACPI tables is not BIOS functionality. It ended up in seabios for historical reasons.
A normal scenario for ACPI tables is that they are written in ASL and compiled with IASL.
I wouldn't call this the normal scenario. Some tables are static but more tables are dynamic than you'd think. If you're a firmware engineer and you have to support dozens of platforms, it's much easier to make the tables dynamic than attempt to maintain dozens of ASL descriptions.
A lot of what you'd consider to be static is actually dynamic in a multi-node system.
The tables are then stored in some ROM device - most of them, except FACP, can actually be mapped directly from ROM if necessary.
You won't normally find real BIOS probing PCI slots for hotplug support and writing EJ0 methods dynamically - instead the assumption is that hardware (in this case QEMU) supplies its own static description in form of ACPI tables.
Actually, this is a very good example. In more modern boxes like Flex, there's a PCI-Express backplane that all of the nodes are connected to with a common set of slots for all nodes. You can configure in firmware how the slots map to each node.
So if you tell BIOS how to map slots to nodes it can generate SRAT. Fine but it still never needs to discover which hardware is there.
I can share an acpi dump from one of these systems when after I head into the office this morning.
This is what's nice about a switched PCI complex. You have tremendous amounts of flexibility in how you set things up.
Regards,
Anthony Liguori
My patchset uses FW_CFG as such a ROM device. It would be easy to switch to something else instead of FW_CFG. Is this what you are suggesting?
-- MST
Hi,
Actually, this is a very good example. In more modern boxes like Flex, there's a PCI-Express backplane that all of the nodes are connected to with a common set of slots for all nodes. You can configure in firmware how the slots map to each node.
Well, we don't configure the dynamic things we have today (s3/s4 enable, numa nodes, pci hotplug, ...) using some firmware setup utility, but using qemu command line switches.
So we have no reason to generate acpi tables in the firmware, we can equally well do it in qemu.
The advantages of doing it in qemu:
(1) We don't have to create/extend fw_cfg interfaces to pass all sorts of config info. (2) It decouples qemu and seabios; we don't have to touch seabios for every new feature which needs something acpi-ish. For example we could have done pvpanic support without touching seabios. (3) We don't have to duplicate the logic which compiles acpi tables from fw_cfg in seabios & ovmf.
The advantages of doing it in seabios:
(*) Your list here, I don't see any.
cheers, Gerd
On Tue, May 14, 2013 at 6:34 AM, Anthony Liguori anthony@codemonkey.ws wrote:
"Michael S. Tsirkin" mst@redhat.com writes:
On Mon, May 13, 2013 at 03:38:51PM -0500, Anthony Liguori wrote:
I don't think it's a good idea to move BIOS functionality in QEMU.
Just to clarify: generating ACPI tables is not BIOS functionality. It ended up in seabios for historical reasons.
A normal scenario for ACPI tables is that they are written in ASL and compiled with IASL.
I wouldn't call this the normal scenario. Some tables are static but more tables are dynamic than you'd think. If you're a firmware engineer and you have to support dozens of platforms, it's much easier to make the tables dynamic than attempt to maintain dozens of ASL descriptions.
Anthony is right. Firmware for "real" systems contains the tables as binary aml output from the asl compiler, but also goes through extensive hoops to tweak the ACPI information.
On the other hand, "real firmware" doesn't have the luxury of being able to just download the ACPI tables like fw-cfg might be able to offer.
I'm a little concerned that firmware might find a desire to still customize the tables, and thus the fw-cfg solution might be too restricting. It does seem to work out okay for other VMM projects though. (It does seem to be working for Xen in OVMF. But, I'm not certain how well it is working, since I don't have a Xen setup.)
I mentioned in the other thread that perhaps QEMU could also consider making the ACPI code available under some 'appropriate' license, which would allow firmware writers to leverage the code directly if desired. Perhaps a dual/multi license situation for the relevant files?
But, if the fw-cfg route works, then it seems the easiest option for firmware writers.
-Jordan
On Mon, May 13, 2013 at 03:38:51PM -0500, Anthony Liguori wrote:
I don't think it's a good idea to move BIOS functionality in QEMU.
We don't frequently add firmware or chipsets so it seems like we're optimizing for an uncommon scenario here.
Regards,
Anthony Liguori
By the way, on x86 we already load some ACPI tables through fw_cfg:
hw/i386/pc_piix.c: pc_acpi_init("acpi-dsdt.aml"); hw/i386/pc_q35.c: pc_acpi_init("q35-acpi-dsdt.aml");
so putting all other tables in one place will just make things more consistent.
Yes, ACPI is messy, and pc-specific, but IMO that's life: it's better to give guests as much help as we can if it's messy, not push the messiness out for guests to handle.