Message ID | 1432175331-12548-8-git-send-email-zhaoshenglong@huawei.com |
---|---|
State | New |
Headers | show |
On Thu, 21 May 2015 10:28:34 +0800 Shannon Zhao <zhaoshenglong@huawei.com> wrote: > From: Shannon Zhao <shannon.zhao@linaro.org> > > DSDT consists of the usual common table header plus a definition > block in AML encoding which describes all devices in the platform. > > After initializing DSDT with header information the namespace is > created which is followed by the device encodings. The devices are > described using the Resource Template for the 32-Bit Fixed Memory > Range and the Extended Interrupt Descriptors. > > Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com> > Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org> > --- > hw/arm/virt-acpi-build.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 130 insertions(+) > > diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c > index b8a5bd8..a1d6045 100644 > --- a/hw/arm/virt-acpi-build.c > +++ b/hw/arm/virt-acpi-build.c > @@ -40,6 +40,132 @@ > #include "hw/hw.h" > #include "hw/acpi/aml-build.h" > > +static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus) > +{ > + uint16_t i; > + > + for (i = 0; i < smp_cpus; i++) { > + Aml *dev = aml_device("C%03x", i); > + aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0007"))); > + aml_append(dev, aml_name_decl("_UID", aml_int(i))); > + Aml *crs = aml_resource_template(); > + aml_append(dev, aml_name_decl("_CRS", crs)); what is this empty _CRS for? > + aml_append(scope, dev); > + } > +} > + > +static void acpi_dsdt_add_uart(Aml *scope, const MemMapEntry *uart_memmap, > + int uart_irq) > +{ > + Aml *dev = aml_device("COM0"); > + aml_append(dev, aml_name_decl("_HID", aml_string("ARMH0011"))); > + aml_append(dev, aml_name_decl("_UID", aml_int(0))); > + > + Aml *crs = aml_resource_template(); > + aml_append(crs, aml_memory32_fixed(uart_memmap->base, > + uart_memmap->size, AML_READ_WRITE)); > + aml_append(crs, > + aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, > + AML_EXCLUSIVE, uart_irq + 32)); what does magic "+ 32" do here? > + aml_append(dev, aml_name_decl("_CRS", crs)); > + aml_append(scope, dev); > +} > + > +static void acpi_dsdt_add_rtc(Aml *scope, const MemMapEntry *rtc_memmap, > + int rtc_irq) > +{ > + Aml *dev = aml_device("RTC0"); > + aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0013"))); > + aml_append(dev, aml_name_decl("_UID", aml_int(0))); > + > + Aml *crs = aml_resource_template(); > + aml_append(crs, aml_memory32_fixed(rtc_memmap->base, > + rtc_memmap->size, AML_READ_WRITE)); > + aml_append(crs, > + aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, > + AML_EXCLUSIVE, rtc_irq + 32)); ditto? > + aml_append(dev, aml_name_decl("_CRS", crs)); > + aml_append(scope, dev); > +} > + > +static void acpi_dsdt_add_flash(Aml *scope, const MemMapEntry *flash_memmap) > +{ > + Aml *dev, *crs; > + hwaddr base = flash_memmap->base; > + hwaddr size = flash_memmap->size; > + > + dev = aml_device("FLS0"); > + aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0015"))); > + aml_append(dev, aml_name_decl("_UID", aml_int(0))); > + > + crs = aml_resource_template(); > + aml_append(crs, aml_memory32_fixed(base, size, AML_READ_WRITE)); > + aml_append(dev, aml_name_decl("_CRS", crs)); > + aml_append(scope, dev); > + > + dev = aml_device("FLS1"); > + aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0015"))); > + aml_append(dev, aml_name_decl("_UID", aml_int(1))); > + crs = aml_resource_template(); > + aml_append(crs, aml_memory32_fixed(base + size, size, AML_READ_WRITE)); > + aml_append(dev, aml_name_decl("_CRS", crs)); > + aml_append(scope, dev); > +} > + > +static void acpi_dsdt_add_virtio(Aml *scope, > + const MemMapEntry *virtio_mmio_memmap, > + int mmio_irq, int num) > +{ > + hwaddr base = virtio_mmio_memmap->base; > + hwaddr size = virtio_mmio_memmap->size; > + int irq = mmio_irq + 32; again magic offset > + int i; > + > + for (i = 0; i < num; i++) { > + Aml *dev = aml_device("VR%02u", i); > + aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0005"))); > + aml_append(dev, aml_name_decl("_UID", aml_int(i))); > + > + Aml *crs = aml_resource_template(); > + aml_append(crs, aml_memory32_fixed(base, size, AML_READ_WRITE)); > + aml_append(crs, > + aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, > + AML_EXCLUSIVE, irq + i)); > + aml_append(dev, aml_name_decl("_CRS", crs)); > + aml_append(scope, dev); > + base += size; > + } > +} > + > +/* DSDT */ > +static void > +build_dsdt(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info) > +{ > + Aml *scope, *dsdt; > + const MemMapEntry *memmap = guest_info->memmap; > + const int *irqmap = guest_info->irqmap; > + > + dsdt = init_aml_allocator(); > + /* Reserve space for header */ > + acpi_data_push(dsdt->buf, sizeof(AcpiTableHeader)); > + > + scope = aml_scope("\\_SB"); > + acpi_dsdt_add_cpus(scope, guest_info->smp_cpus); > + acpi_dsdt_add_uart(scope, &memmap[VIRT_UART], irqmap[VIRT_UART]); > + acpi_dsdt_add_rtc(scope, &memmap[VIRT_RTC], irqmap[VIRT_RTC]); > + acpi_dsdt_add_flash(scope, &memmap[VIRT_FLASH]); > + acpi_dsdt_add_virtio(scope, &memmap[VIRT_MMIO], > + irqmap[VIRT_MMIO], NUM_VIRTIO_TRANSPORTS); > + aml_append(dsdt, scope); > + > + /* copy AML table into ACPI tables blob and patch header there */ > + g_array_append_vals(table_data, dsdt->buf->data, dsdt->buf->len); > + build_header(linker, table_data, > + (void *)(table_data->data + table_data->len - dsdt->buf->len), > + "DSDT", dsdt->buf->len, 5); > + free_aml_allocator(); > +} > + > typedef > struct AcpiBuildState { > /* Copy of table in RAM (for patching). */ > @@ -55,6 +181,7 @@ static > void virt_acpi_build(VirtGuestInfo *guest_info, AcpiBuildTables *tables) > { > GArray *table_offsets; > + GArray *tables_blob = tables->table_data; > > table_offsets = g_array_new(false, true /* clear */, > sizeof(uint32_t)); > @@ -72,6 +199,9 @@ void virt_acpi_build(VirtGuestInfo *guest_info, AcpiBuildTables *tables) > * DSDT > */ > > + /* DSDT is pointed to by FADT */ > + build_dsdt(tables_blob, tables->linker, guest_info); > + > /* Cleanup memory that's no longer used. */ > g_array_free(table_offsets, true); > }
On 2015/5/21 16:42, Igor Mammedov wrote: > On Thu, 21 May 2015 10:28:34 +0800 > Shannon Zhao <zhaoshenglong@huawei.com> wrote: > >> From: Shannon Zhao <shannon.zhao@linaro.org> >> >> DSDT consists of the usual common table header plus a definition >> block in AML encoding which describes all devices in the platform. >> >> After initializing DSDT with header information the namespace is >> created which is followed by the device encodings. The devices are >> described using the Resource Template for the 32-Bit Fixed Memory >> Range and the Extended Interrupt Descriptors. >> >> Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com> >> Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org> >> --- >> hw/arm/virt-acpi-build.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++ >> 1 file changed, 130 insertions(+) >> >> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c >> index b8a5bd8..a1d6045 100644 >> --- a/hw/arm/virt-acpi-build.c >> +++ b/hw/arm/virt-acpi-build.c >> @@ -40,6 +40,132 @@ >> #include "hw/hw.h" >> #include "hw/acpi/aml-build.h" >> >> +static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus) >> +{ >> + uint16_t i; >> + >> + for (i = 0; i < smp_cpus; i++) { >> + Aml *dev = aml_device("C%03x", i); >> + aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0007"))); >> + aml_append(dev, aml_name_decl("_UID", aml_int(i))); >> + Aml *crs = aml_resource_template(); >> + aml_append(dev, aml_name_decl("_CRS", crs)); > what is this empty _CRS for? > Oops, I don't remember how this is introduced. Will remove it. Thanks. > >> + aml_append(scope, dev); >> + } >> +} >> + >> +static void acpi_dsdt_add_uart(Aml *scope, const MemMapEntry *uart_memmap, >> + int uart_irq) >> +{ >> + Aml *dev = aml_device("COM0"); >> + aml_append(dev, aml_name_decl("_HID", aml_string("ARMH0011"))); >> + aml_append(dev, aml_name_decl("_UID", aml_int(0))); >> + >> + Aml *crs = aml_resource_template(); >> + aml_append(crs, aml_memory32_fixed(uart_memmap->base, >> + uart_memmap->size, AML_READ_WRITE)); >> + aml_append(crs, >> + aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, >> + AML_EXCLUSIVE, uart_irq + 32)); > what does magic "+ 32" do here? > On ARM first 32 IRQs are for SGI and PPI, after IRQ 32 are for SPI. The a15irqmap[] in virt.c records the irqs of devices and these irqs are SPIs. For DT, it will add 32 by kernel, while for ACPI we must add 32 when generating tables. >> + aml_append(dev, aml_name_decl("_CRS", crs)); >> + aml_append(scope, dev); >> +} >> + >> +static void acpi_dsdt_add_rtc(Aml *scope, const MemMapEntry *rtc_memmap, >> + int rtc_irq) >> +{ >> + Aml *dev = aml_device("RTC0"); >> + aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0013"))); >> + aml_append(dev, aml_name_decl("_UID", aml_int(0))); >> + >> + Aml *crs = aml_resource_template(); >> + aml_append(crs, aml_memory32_fixed(rtc_memmap->base, >> + rtc_memmap->size, AML_READ_WRITE)); >> + aml_append(crs, >> + aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, >> + AML_EXCLUSIVE, rtc_irq + 32)); > ditto? > >> + aml_append(dev, aml_name_decl("_CRS", crs)); >> + aml_append(scope, dev); >> +} >> + >> +static void acpi_dsdt_add_flash(Aml *scope, const MemMapEntry *flash_memmap) >> +{ >> + Aml *dev, *crs; >> + hwaddr base = flash_memmap->base; >> + hwaddr size = flash_memmap->size; >> + >> + dev = aml_device("FLS0"); >> + aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0015"))); >> + aml_append(dev, aml_name_decl("_UID", aml_int(0))); >> + >> + crs = aml_resource_template(); >> + aml_append(crs, aml_memory32_fixed(base, size, AML_READ_WRITE)); >> + aml_append(dev, aml_name_decl("_CRS", crs)); >> + aml_append(scope, dev); >> + >> + dev = aml_device("FLS1"); >> + aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0015"))); >> + aml_append(dev, aml_name_decl("_UID", aml_int(1))); >> + crs = aml_resource_template(); >> + aml_append(crs, aml_memory32_fixed(base + size, size, AML_READ_WRITE)); >> + aml_append(dev, aml_name_decl("_CRS", crs)); >> + aml_append(scope, dev); >> +} >> + >> +static void acpi_dsdt_add_virtio(Aml *scope, >> + const MemMapEntry *virtio_mmio_memmap, >> + int mmio_irq, int num) >> +{ >> + hwaddr base = virtio_mmio_memmap->base; >> + hwaddr size = virtio_mmio_memmap->size; >> + int irq = mmio_irq + 32; > again magic offset > >> + int i; >> + >> + for (i = 0; i < num; i++) { >> + Aml *dev = aml_device("VR%02u", i); >> + aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0005"))); >> + aml_append(dev, aml_name_decl("_UID", aml_int(i))); >> + >> + Aml *crs = aml_resource_template(); >> + aml_append(crs, aml_memory32_fixed(base, size, AML_READ_WRITE)); >> + aml_append(crs, >> + aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, >> + AML_EXCLUSIVE, irq + i)); >> + aml_append(dev, aml_name_decl("_CRS", crs)); >> + aml_append(scope, dev); >> + base += size; >> + } >> +} >> + >> +/* DSDT */ >> +static void >> +build_dsdt(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info) >> +{ >> + Aml *scope, *dsdt; >> + const MemMapEntry *memmap = guest_info->memmap; >> + const int *irqmap = guest_info->irqmap; >> + >> + dsdt = init_aml_allocator(); >> + /* Reserve space for header */ >> + acpi_data_push(dsdt->buf, sizeof(AcpiTableHeader)); >> + >> + scope = aml_scope("\\_SB"); >> + acpi_dsdt_add_cpus(scope, guest_info->smp_cpus); >> + acpi_dsdt_add_uart(scope, &memmap[VIRT_UART], irqmap[VIRT_UART]); >> + acpi_dsdt_add_rtc(scope, &memmap[VIRT_RTC], irqmap[VIRT_RTC]); >> + acpi_dsdt_add_flash(scope, &memmap[VIRT_FLASH]); >> + acpi_dsdt_add_virtio(scope, &memmap[VIRT_MMIO], >> + irqmap[VIRT_MMIO], NUM_VIRTIO_TRANSPORTS); >> + aml_append(dsdt, scope); >> + >> + /* copy AML table into ACPI tables blob and patch header there */ >> + g_array_append_vals(table_data, dsdt->buf->data, dsdt->buf->len); >> + build_header(linker, table_data, >> + (void *)(table_data->data + table_data->len - dsdt->buf->len), >> + "DSDT", dsdt->buf->len, 5); >> + free_aml_allocator(); >> +} >> + >> typedef >> struct AcpiBuildState { >> /* Copy of table in RAM (for patching). */ >> @@ -55,6 +181,7 @@ static >> void virt_acpi_build(VirtGuestInfo *guest_info, AcpiBuildTables *tables) >> { >> GArray *table_offsets; >> + GArray *tables_blob = tables->table_data; >> >> table_offsets = g_array_new(false, true /* clear */, >> sizeof(uint32_t)); >> @@ -72,6 +199,9 @@ void virt_acpi_build(VirtGuestInfo *guest_info, AcpiBuildTables *tables) >> * DSDT >> */ >> >> + /* DSDT is pointed to by FADT */ >> + build_dsdt(tables_blob, tables->linker, guest_info); >> + >> /* Cleanup memory that's no longer used. */ >> g_array_free(table_offsets, true); >> } > > > . >
On Thu, 21 May 2015 17:10:00 +0800 Shannon Zhao <zhaoshenglong@huawei.com> wrote: > > > On 2015/5/21 16:42, Igor Mammedov wrote: > > On Thu, 21 May 2015 10:28:34 +0800 > > Shannon Zhao <zhaoshenglong@huawei.com> wrote: > > > >> From: Shannon Zhao <shannon.zhao@linaro.org> > >> > >> DSDT consists of the usual common table header plus a definition > >> block in AML encoding which describes all devices in the platform. > >> > >> After initializing DSDT with header information the namespace is > >> created which is followed by the device encodings. The devices are > >> described using the Resource Template for the 32-Bit Fixed Memory > >> Range and the Extended Interrupt Descriptors. > >> > >> Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com> > >> Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org> > >> --- > >> hw/arm/virt-acpi-build.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++ > >> 1 file changed, 130 insertions(+) > >> > >> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c > >> index b8a5bd8..a1d6045 100644 > >> --- a/hw/arm/virt-acpi-build.c > >> +++ b/hw/arm/virt-acpi-build.c > >> @@ -40,6 +40,132 @@ > >> #include "hw/hw.h" > >> #include "hw/acpi/aml-build.h" > >> > >> +static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus) > >> +{ > >> + uint16_t i; > >> + > >> + for (i = 0; i < smp_cpus; i++) { > >> + Aml *dev = aml_device("C%03x", i); > >> + aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0007"))); > >> + aml_append(dev, aml_name_decl("_UID", aml_int(i))); > >> + Aml *crs = aml_resource_template(); > >> + aml_append(dev, aml_name_decl("_CRS", crs)); > > what is this empty _CRS for? > > > Oops, I don't remember how this is introduced. Will remove it. Thanks. > > > > >> + aml_append(scope, dev); > >> + } > >> +} > >> + > >> +static void acpi_dsdt_add_uart(Aml *scope, const MemMapEntry *uart_memmap, > >> + int uart_irq) > >> +{ > >> + Aml *dev = aml_device("COM0"); > >> + aml_append(dev, aml_name_decl("_HID", aml_string("ARMH0011"))); > >> + aml_append(dev, aml_name_decl("_UID", aml_int(0))); > >> + > >> + Aml *crs = aml_resource_template(); > >> + aml_append(crs, aml_memory32_fixed(uart_memmap->base, > >> + uart_memmap->size, AML_READ_WRITE)); > >> + aml_append(crs, > >> + aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, > >> + AML_EXCLUSIVE, uart_irq + 32)); > > what does magic "+ 32" do here? > > > On ARM first 32 IRQs are for SGI and PPI, after IRQ 32 are for SPI. The > a15irqmap[] in virt.c records the irqs of devices and these irqs are > SPIs. For DT, it will add 32 by kernel, while for ACPI we must add 32 > when generating tables. Perhaps replace 32 with a define that describes it and pass already offseted value to acpi_dsdt_add_uart() and in other places do the same. > > >> + aml_append(dev, aml_name_decl("_CRS", crs)); > >> + aml_append(scope, dev); > >> +} > >> + > >> +static void acpi_dsdt_add_rtc(Aml *scope, const MemMapEntry *rtc_memmap, > >> + int rtc_irq) > >> +{ > >> + Aml *dev = aml_device("RTC0"); > >> + aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0013"))); > >> + aml_append(dev, aml_name_decl("_UID", aml_int(0))); > >> + > >> + Aml *crs = aml_resource_template(); > >> + aml_append(crs, aml_memory32_fixed(rtc_memmap->base, > >> + rtc_memmap->size, AML_READ_WRITE)); > >> + aml_append(crs, > >> + aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, > >> + AML_EXCLUSIVE, rtc_irq + 32)); > > ditto? > > > >> + aml_append(dev, aml_name_decl("_CRS", crs)); > >> + aml_append(scope, dev); > >> +} > >> + > >> +static void acpi_dsdt_add_flash(Aml *scope, const MemMapEntry *flash_memmap) > >> +{ > >> + Aml *dev, *crs; > >> + hwaddr base = flash_memmap->base; > >> + hwaddr size = flash_memmap->size; > >> + > >> + dev = aml_device("FLS0"); > >> + aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0015"))); > >> + aml_append(dev, aml_name_decl("_UID", aml_int(0))); > >> + > >> + crs = aml_resource_template(); > >> + aml_append(crs, aml_memory32_fixed(base, size, AML_READ_WRITE)); > >> + aml_append(dev, aml_name_decl("_CRS", crs)); > >> + aml_append(scope, dev); > >> + > >> + dev = aml_device("FLS1"); > >> + aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0015"))); > >> + aml_append(dev, aml_name_decl("_UID", aml_int(1))); > >> + crs = aml_resource_template(); > >> + aml_append(crs, aml_memory32_fixed(base + size, size, AML_READ_WRITE)); > >> + aml_append(dev, aml_name_decl("_CRS", crs)); > >> + aml_append(scope, dev); > >> +} > >> + > >> +static void acpi_dsdt_add_virtio(Aml *scope, > >> + const MemMapEntry *virtio_mmio_memmap, > >> + int mmio_irq, int num) > >> +{ > >> + hwaddr base = virtio_mmio_memmap->base; > >> + hwaddr size = virtio_mmio_memmap->size; > >> + int irq = mmio_irq + 32; > > again magic offset > > > >> + int i; > >> + > >> + for (i = 0; i < num; i++) { > >> + Aml *dev = aml_device("VR%02u", i); > >> + aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0005"))); > >> + aml_append(dev, aml_name_decl("_UID", aml_int(i))); > >> + > >> + Aml *crs = aml_resource_template(); > >> + aml_append(crs, aml_memory32_fixed(base, size, AML_READ_WRITE)); > >> + aml_append(crs, > >> + aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, > >> + AML_EXCLUSIVE, irq + i)); > >> + aml_append(dev, aml_name_decl("_CRS", crs)); > >> + aml_append(scope, dev); > >> + base += size; > >> + } > >> +} > >> + > >> +/* DSDT */ > >> +static void > >> +build_dsdt(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info) > >> +{ > >> + Aml *scope, *dsdt; > >> + const MemMapEntry *memmap = guest_info->memmap; > >> + const int *irqmap = guest_info->irqmap; > >> + > >> + dsdt = init_aml_allocator(); > >> + /* Reserve space for header */ > >> + acpi_data_push(dsdt->buf, sizeof(AcpiTableHeader)); > >> + > >> + scope = aml_scope("\\_SB"); > >> + acpi_dsdt_add_cpus(scope, guest_info->smp_cpus); > >> + acpi_dsdt_add_uart(scope, &memmap[VIRT_UART], irqmap[VIRT_UART]); > >> + acpi_dsdt_add_rtc(scope, &memmap[VIRT_RTC], irqmap[VIRT_RTC]); > >> + acpi_dsdt_add_flash(scope, &memmap[VIRT_FLASH]); > >> + acpi_dsdt_add_virtio(scope, &memmap[VIRT_MMIO], > >> + irqmap[VIRT_MMIO], NUM_VIRTIO_TRANSPORTS); > >> + aml_append(dsdt, scope); > >> + > >> + /* copy AML table into ACPI tables blob and patch header there */ > >> + g_array_append_vals(table_data, dsdt->buf->data, dsdt->buf->len); > >> + build_header(linker, table_data, > >> + (void *)(table_data->data + table_data->len - dsdt->buf->len), > >> + "DSDT", dsdt->buf->len, 5); > >> + free_aml_allocator(); > >> +} > >> + > >> typedef > >> struct AcpiBuildState { > >> /* Copy of table in RAM (for patching). */ > >> @@ -55,6 +181,7 @@ static > >> void virt_acpi_build(VirtGuestInfo *guest_info, AcpiBuildTables *tables) > >> { > >> GArray *table_offsets; > >> + GArray *tables_blob = tables->table_data; > >> > >> table_offsets = g_array_new(false, true /* clear */, > >> sizeof(uint32_t)); > >> @@ -72,6 +199,9 @@ void virt_acpi_build(VirtGuestInfo *guest_info, AcpiBuildTables *tables) > >> * DSDT > >> */ > >> > >> + /* DSDT is pointed to by FADT */ > >> + build_dsdt(tables_blob, tables->linker, guest_info); > >> + > >> /* Cleanup memory that's no longer used. */ > >> g_array_free(table_offsets, true); > >> } > > > > > > . > > >
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index b8a5bd8..a1d6045 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -40,6 +40,132 @@ #include "hw/hw.h" #include "hw/acpi/aml-build.h" +static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus) +{ + uint16_t i; + + for (i = 0; i < smp_cpus; i++) { + Aml *dev = aml_device("C%03x", i); + aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0007"))); + aml_append(dev, aml_name_decl("_UID", aml_int(i))); + Aml *crs = aml_resource_template(); + aml_append(dev, aml_name_decl("_CRS", crs)); + aml_append(scope, dev); + } +} + +static void acpi_dsdt_add_uart(Aml *scope, const MemMapEntry *uart_memmap, + int uart_irq) +{ + Aml *dev = aml_device("COM0"); + aml_append(dev, aml_name_decl("_HID", aml_string("ARMH0011"))); + aml_append(dev, aml_name_decl("_UID", aml_int(0))); + + Aml *crs = aml_resource_template(); + aml_append(crs, aml_memory32_fixed(uart_memmap->base, + uart_memmap->size, AML_READ_WRITE)); + aml_append(crs, + aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, + AML_EXCLUSIVE, uart_irq + 32)); + aml_append(dev, aml_name_decl("_CRS", crs)); + aml_append(scope, dev); +} + +static void acpi_dsdt_add_rtc(Aml *scope, const MemMapEntry *rtc_memmap, + int rtc_irq) +{ + Aml *dev = aml_device("RTC0"); + aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0013"))); + aml_append(dev, aml_name_decl("_UID", aml_int(0))); + + Aml *crs = aml_resource_template(); + aml_append(crs, aml_memory32_fixed(rtc_memmap->base, + rtc_memmap->size, AML_READ_WRITE)); + aml_append(crs, + aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, + AML_EXCLUSIVE, rtc_irq + 32)); + aml_append(dev, aml_name_decl("_CRS", crs)); + aml_append(scope, dev); +} + +static void acpi_dsdt_add_flash(Aml *scope, const MemMapEntry *flash_memmap) +{ + Aml *dev, *crs; + hwaddr base = flash_memmap->base; + hwaddr size = flash_memmap->size; + + dev = aml_device("FLS0"); + aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0015"))); + aml_append(dev, aml_name_decl("_UID", aml_int(0))); + + crs = aml_resource_template(); + aml_append(crs, aml_memory32_fixed(base, size, AML_READ_WRITE)); + aml_append(dev, aml_name_decl("_CRS", crs)); + aml_append(scope, dev); + + dev = aml_device("FLS1"); + aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0015"))); + aml_append(dev, aml_name_decl("_UID", aml_int(1))); + crs = aml_resource_template(); + aml_append(crs, aml_memory32_fixed(base + size, size, AML_READ_WRITE)); + aml_append(dev, aml_name_decl("_CRS", crs)); + aml_append(scope, dev); +} + +static void acpi_dsdt_add_virtio(Aml *scope, + const MemMapEntry *virtio_mmio_memmap, + int mmio_irq, int num) +{ + hwaddr base = virtio_mmio_memmap->base; + hwaddr size = virtio_mmio_memmap->size; + int irq = mmio_irq + 32; + int i; + + for (i = 0; i < num; i++) { + Aml *dev = aml_device("VR%02u", i); + aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0005"))); + aml_append(dev, aml_name_decl("_UID", aml_int(i))); + + Aml *crs = aml_resource_template(); + aml_append(crs, aml_memory32_fixed(base, size, AML_READ_WRITE)); + aml_append(crs, + aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, + AML_EXCLUSIVE, irq + i)); + aml_append(dev, aml_name_decl("_CRS", crs)); + aml_append(scope, dev); + base += size; + } +} + +/* DSDT */ +static void +build_dsdt(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info) +{ + Aml *scope, *dsdt; + const MemMapEntry *memmap = guest_info->memmap; + const int *irqmap = guest_info->irqmap; + + dsdt = init_aml_allocator(); + /* Reserve space for header */ + acpi_data_push(dsdt->buf, sizeof(AcpiTableHeader)); + + scope = aml_scope("\\_SB"); + acpi_dsdt_add_cpus(scope, guest_info->smp_cpus); + acpi_dsdt_add_uart(scope, &memmap[VIRT_UART], irqmap[VIRT_UART]); + acpi_dsdt_add_rtc(scope, &memmap[VIRT_RTC], irqmap[VIRT_RTC]); + acpi_dsdt_add_flash(scope, &memmap[VIRT_FLASH]); + acpi_dsdt_add_virtio(scope, &memmap[VIRT_MMIO], + irqmap[VIRT_MMIO], NUM_VIRTIO_TRANSPORTS); + aml_append(dsdt, scope); + + /* copy AML table into ACPI tables blob and patch header there */ + g_array_append_vals(table_data, dsdt->buf->data, dsdt->buf->len); + build_header(linker, table_data, + (void *)(table_data->data + table_data->len - dsdt->buf->len), + "DSDT", dsdt->buf->len, 5); + free_aml_allocator(); +} + typedef struct AcpiBuildState { /* Copy of table in RAM (for patching). */ @@ -55,6 +181,7 @@ static void virt_acpi_build(VirtGuestInfo *guest_info, AcpiBuildTables *tables) { GArray *table_offsets; + GArray *tables_blob = tables->table_data; table_offsets = g_array_new(false, true /* clear */, sizeof(uint32_t)); @@ -72,6 +199,9 @@ void virt_acpi_build(VirtGuestInfo *guest_info, AcpiBuildTables *tables) * DSDT */ + /* DSDT is pointed to by FADT */ + build_dsdt(tables_blob, tables->linker, guest_info); + /* Cleanup memory that's no longer used. */ g_array_free(table_offsets, true); }