diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c index 411c0e5374..cd25d06f05 100644 --- a/hw/acpi/aml-build.c +++ b/hw/acpi/aml-build.c @@ -598,23 +598,27 @@ Aml *aml_memory32_fixed(uint32_t addr, uint32_t size, Aml *aml_interrupt(AmlConsumerAndProducer con_and_pro, AmlLevelAndEdge level_and_edge, AmlActiveHighAndLow high_and_low, AmlShared shared, - uint32_t irq) + uint32_t *irq_list, uint8_t irq_count) { + int i; Aml *var = aml_alloc(); uint8_t irq_flags = con_and_pro | (level_and_edge << 1) | (high_and_low << 2) | (shared << 3); + const int header_bytes_in_len = 2; + uint16_t len = header_bytes_in_len + irq_count * sizeof(uint32_t); + + assert(irq_count > 0); build_append_byte(var->buf, 0x89); /* Extended irq descriptor */ - build_append_byte(var->buf, 6); /* Length, bits[7:0] minimum value = 6 */ - build_append_byte(var->buf, 0); /* Length, bits[15:8] minimum value = 0 */ + build_append_byte(var->buf, len & 0xFF); /* Length, bits[7:0] */ + build_append_byte(var->buf, len >> 8); /* Length, bits[15:8] */ build_append_byte(var->buf, irq_flags); /* Interrupt Vector Information. */ - build_append_byte(var->buf, 0x01); /* Interrupt table length = 1 */ + build_append_byte(var->buf, irq_count); /* Interrupt table length */ - /* Interrupt Number */ - build_append_byte(var->buf, extract32(irq, 0, 8)); /* bits[7:0] */ - build_append_byte(var->buf, extract32(irq, 8, 8)); /* bits[15:8] */ - build_append_byte(var->buf, extract32(irq, 16, 8)); /* bits[23:16] */ - build_append_byte(var->buf, extract32(irq, 24, 8)); /* bits[31:24] */ + /* Interrupt Number List */ + for (i = 0; i < irq_count; i++) { + build_append_int_noprefix(var->buf, irq_list[i], 4); + } return var; } diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 4be32223bc..9123649e66 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -71,7 +71,7 @@ static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus) } static void acpi_dsdt_add_uart(Aml *scope, const MemMapEntry *uart_memmap, - int uart_irq) + uint32_t uart_irq) { Aml *dev = aml_device("COM0"); aml_append(dev, aml_name_decl("_HID", aml_string("ARMH0011"))); @@ -82,7 +82,7 @@ static void acpi_dsdt_add_uart(Aml *scope, const MemMapEntry *uart_memmap, uart_memmap->size, AML_READ_WRITE)); aml_append(crs, aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, - AML_EXCLUSIVE, uart_irq)); + AML_EXCLUSIVE, &uart_irq, 1)); aml_append(dev, aml_name_decl("_CRS", crs)); /* The _ADR entry is used to link this device to the UART described @@ -94,7 +94,7 @@ static void acpi_dsdt_add_uart(Aml *scope, const MemMapEntry *uart_memmap, } static void acpi_dsdt_add_rtc(Aml *scope, const MemMapEntry *rtc_memmap, - int rtc_irq) + uint32_t rtc_irq) { Aml *dev = aml_device("RTC0"); aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0013"))); @@ -105,7 +105,7 @@ static void acpi_dsdt_add_rtc(Aml *scope, const MemMapEntry *rtc_memmap, rtc_memmap->size, AML_READ_WRITE)); aml_append(crs, aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, - AML_EXCLUSIVE, rtc_irq)); + AML_EXCLUSIVE, &rtc_irq, 1)); aml_append(dev, aml_name_decl("_CRS", crs)); aml_append(scope, dev); } @@ -136,14 +136,14 @@ static void acpi_dsdt_add_flash(Aml *scope, const MemMapEntry *flash_memmap) static void acpi_dsdt_add_virtio(Aml *scope, const MemMapEntry *virtio_mmio_memmap, - int mmio_irq, int num) + uint32_t mmio_irq, int num) { hwaddr base = virtio_mmio_memmap->base; hwaddr size = virtio_mmio_memmap->size; - int irq = mmio_irq; int i; for (i = 0; i < num; i++) { + uint32_t irq = mmio_irq + 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))); @@ -152,15 +152,15 @@ static void acpi_dsdt_add_virtio(Aml *scope, 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_EXCLUSIVE, &irq, 1)); aml_append(dev, aml_name_decl("_CRS", crs)); aml_append(scope, dev); base += size; } } -static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap, int irq, - bool use_highmem) +static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap, + uint32_t irq, bool use_highmem) { Aml *method, *crs, *ifctx, *UUID, *ifctx1, *elsectx, *buf; int i, bus_no; @@ -199,18 +199,19 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap, int irq, /* Create GSI link device */ for (i = 0; i < PCI_NUM_PINS; i++) { + uint32_t irqs = irq + i; Aml *dev_gsi = aml_device("GSI%d", i); aml_append(dev_gsi, aml_name_decl("_HID", aml_string("PNP0C0F"))); aml_append(dev_gsi, aml_name_decl("_UID", aml_int(0))); crs = aml_resource_template(); aml_append(crs, aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, - AML_EXCLUSIVE, irq + i)); + AML_EXCLUSIVE, &irqs, 1)); aml_append(dev_gsi, aml_name_decl("_PRS", crs)); crs = aml_resource_template(); aml_append(crs, aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, - AML_EXCLUSIVE, irq + i)); + AML_EXCLUSIVE, &irqs, 1)); aml_append(dev_gsi, aml_name_decl("_CRS", crs)); method = aml_method("_SRS", 1, AML_NOTSERIALIZED); aml_append(dev_gsi, method); diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h index a3580e10c8..c2c0be3e77 100644 --- a/include/hw/acpi/aml-build.h +++ b/include/hw/acpi/aml-build.h @@ -223,7 +223,7 @@ Aml *aml_memory32_fixed(uint32_t addr, uint32_t size, Aml *aml_interrupt(AmlConsumerAndProducer con_and_pro, AmlLevelAndEdge level_and_edge, AmlActiveHighAndLow high_and_low, AmlShared shared, - uint32_t irq); + uint32_t *irq_list, uint8_t irq_count); Aml *aml_io(AmlIODecode dec, uint16_t min_base, uint16_t max_base, uint8_t aln, uint8_t len); Aml *aml_operation_region(const char *name, AmlRegionSpace rs,