ACPI: PCI: IRQ: Fix INTx GSIs signedness

In ACPI Global System Interrupts (GSIs) are described using a 32-bit
value.

ACPI/PCI legacy interrupts (INTx) parsing code treats GSIs as 'int',
which poses issues if the GSI interrupt value is a 32-bit value with the
MSB set (as required in some interrupt configurations - eg ARM64 GICv5
systems) because acpi_pci_link_allocate_irq() treats a negative gsi
return value as a failed GSI allocation (and acpi_irq_get_penalty()
would trigger an out-of-bounds array dereference if the 'irq' param is
a negative value).

Fix ACPI/PCI legacy INTx parsing by converting variables representing
GSIs from 'int' to 'u32' bringing the code in line with the ACPI
specification and fixing the current parsing issue.

Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
Reviewed-by: Bjorn Helgaas <bhelgaas@google.com>
Link: https://patch.msgid.link/20260105101705.36703-1-lpieralisi@kernel.org
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

authored by Lorenzo Pieralisi and committed by Rafael J. Wysocki 1ca8677d 9ace4753

Changed files
+44 -29
drivers
include
+11 -8
drivers/acpi/pci_irq.c
··· 188 * the IRQ value, which is hardwired to specific interrupt inputs on 189 * the interrupt controller. 190 */ 191 - pr_debug("%04x:%02x:%02x[%c] -> %s[%d]\n", 192 entry->id.segment, entry->id.bus, entry->id.device, 193 pin_name(entry->pin), prt->source, entry->index); 194 ··· 384 int acpi_pci_irq_enable(struct pci_dev *dev) 385 { 386 struct acpi_prt_entry *entry; 387 - int gsi; 388 u8 pin; 389 int triggering = ACPI_LEVEL_SENSITIVE; 390 /* ··· 422 return 0; 423 } 424 425 if (entry) { 426 if (entry->link) 427 - gsi = acpi_pci_link_allocate_irq(entry->link, 428 entry->index, 429 &triggering, &polarity, 430 - &link); 431 - else 432 gsi = entry->index; 433 - } else 434 - gsi = -1; 435 436 - if (gsi < 0) { 437 /* 438 * No IRQ known to the ACPI subsystem - maybe the BIOS / 439 * driver reported one, then use it. Exit in any case.
··· 188 * the IRQ value, which is hardwired to specific interrupt inputs on 189 * the interrupt controller. 190 */ 191 + pr_debug("%04x:%02x:%02x[%c] -> %s[%u]\n", 192 entry->id.segment, entry->id.bus, entry->id.device, 193 pin_name(entry->pin), prt->source, entry->index); 194 ··· 384 int acpi_pci_irq_enable(struct pci_dev *dev) 385 { 386 struct acpi_prt_entry *entry; 387 + u32 gsi; 388 u8 pin; 389 int triggering = ACPI_LEVEL_SENSITIVE; 390 /* ··· 422 return 0; 423 } 424 425 + rc = -ENODEV; 426 + 427 if (entry) { 428 if (entry->link) 429 + rc = acpi_pci_link_allocate_irq(entry->link, 430 entry->index, 431 &triggering, &polarity, 432 + &link, &gsi); 433 + else { 434 gsi = entry->index; 435 + rc = 0; 436 + } 437 + } 438 439 + if (rc < 0) { 440 /* 441 * No IRQ known to the ACPI subsystem - maybe the BIOS / 442 * driver reported one, then use it. Exit in any case.
+25 -14
drivers/acpi/pci_link.c
··· 448 /* >IRQ15 */ 449 }; 450 451 - static int acpi_irq_pci_sharing_penalty(int irq) 452 { 453 struct acpi_pci_link *link; 454 int penalty = 0; ··· 474 return penalty; 475 } 476 477 - static int acpi_irq_get_penalty(int irq) 478 { 479 int penalty = 0; 480 ··· 528 static int acpi_pci_link_allocate(struct acpi_pci_link *link) 529 { 530 acpi_handle handle = link->device->handle; 531 - int irq; 532 int i; 533 534 if (link->irq.initialized) { ··· 598 return 0; 599 } 600 601 - /* 602 - * acpi_pci_link_allocate_irq 603 - * success: return IRQ >= 0 604 - * failure: return -1 605 */ 606 int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering, 607 - int *polarity, char **name) 608 { 609 struct acpi_device *device = acpi_fetch_acpi_dev(handle); 610 struct acpi_pci_link *link; 611 612 if (!device) { 613 acpi_handle_err(handle, "Invalid link device\n"); 614 - return -1; 615 } 616 617 link = acpi_driver_data(device); 618 if (!link) { 619 acpi_handle_err(handle, "Invalid link context\n"); 620 - return -1; 621 } 622 623 /* TBD: Support multiple index (IRQ) entries per Link Device */ 624 if (index) { 625 acpi_handle_err(handle, "Invalid index %d\n", index); 626 - return -1; 627 } 628 629 mutex_lock(&acpi_link_lock); 630 if (acpi_pci_link_allocate(link)) { 631 mutex_unlock(&acpi_link_lock); 632 - return -1; 633 } 634 635 if (!link->irq.active) { 636 mutex_unlock(&acpi_link_lock); 637 acpi_handle_err(handle, "Link active IRQ is 0!\n"); 638 - return -1; 639 } 640 link->refcnt++; 641 mutex_unlock(&acpi_link_lock); ··· 656 if (name) 657 *name = acpi_device_bid(link->device); 658 acpi_handle_debug(handle, "Link is referenced\n"); 659 - return link->irq.active; 660 } 661 662 /*
··· 448 /* >IRQ15 */ 449 }; 450 451 + static int acpi_irq_pci_sharing_penalty(u32 irq) 452 { 453 struct acpi_pci_link *link; 454 int penalty = 0; ··· 474 return penalty; 475 } 476 477 + static int acpi_irq_get_penalty(u32 irq) 478 { 479 int penalty = 0; 480 ··· 528 static int acpi_pci_link_allocate(struct acpi_pci_link *link) 529 { 530 acpi_handle handle = link->device->handle; 531 + u32 irq; 532 int i; 533 534 if (link->irq.initialized) { ··· 598 return 0; 599 } 600 601 + /** 602 + * acpi_pci_link_allocate_irq(): Retrieve a link device GSI 603 + * 604 + * @handle: Handle for the link device 605 + * @index: GSI index 606 + * @triggering: pointer to store the GSI trigger 607 + * @polarity: pointer to store GSI polarity 608 + * @name: pointer to store link device name 609 + * @gsi: pointer to store GSI number 610 + * 611 + * Returns: 612 + * 0 on success with @triggering, @polarity, @name, @gsi initialized. 613 + * -ENODEV on failure 614 */ 615 int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering, 616 + int *polarity, char **name, u32 *gsi) 617 { 618 struct acpi_device *device = acpi_fetch_acpi_dev(handle); 619 struct acpi_pci_link *link; 620 621 if (!device) { 622 acpi_handle_err(handle, "Invalid link device\n"); 623 + return -ENODEV; 624 } 625 626 link = acpi_driver_data(device); 627 if (!link) { 628 acpi_handle_err(handle, "Invalid link context\n"); 629 + return -ENODEV; 630 } 631 632 /* TBD: Support multiple index (IRQ) entries per Link Device */ 633 if (index) { 634 acpi_handle_err(handle, "Invalid index %d\n", index); 635 + return -ENODEV; 636 } 637 638 mutex_lock(&acpi_link_lock); 639 if (acpi_pci_link_allocate(link)) { 640 mutex_unlock(&acpi_link_lock); 641 + return -ENODEV; 642 } 643 644 if (!link->irq.active) { 645 mutex_unlock(&acpi_link_lock); 646 acpi_handle_err(handle, "Link active IRQ is 0!\n"); 647 + return -ENODEV; 648 } 649 link->refcnt++; 650 mutex_unlock(&acpi_link_lock); ··· 647 if (name) 648 *name = acpi_device_bid(link->device); 649 acpi_handle_debug(handle, "Link is referenced\n"); 650 + *gsi = link->irq.active; 651 + 652 + return 0; 653 } 654 655 /*
+7 -6
drivers/xen/acpi.c
··· 89 int *trigger_out, 90 int *polarity_out) 91 { 92 - int gsi; 93 u8 pin; 94 struct acpi_prt_entry *entry; 95 int trigger = ACPI_LEVEL_SENSITIVE; 96 - int polarity = acpi_irq_model == ACPI_IRQ_MODEL_GIC ? 97 ACPI_ACTIVE_HIGH : ACPI_ACTIVE_LOW; 98 99 if (!dev || !gsi_out || !trigger_out || !polarity_out) ··· 105 106 entry = acpi_pci_irq_lookup(dev, pin); 107 if (entry) { 108 if (entry->link) 109 - gsi = acpi_pci_link_allocate_irq(entry->link, 110 entry->index, 111 &trigger, &polarity, 112 - NULL); 113 else 114 gsi = entry->index; 115 } else 116 - gsi = -1; 117 118 - if (gsi < 0) 119 return -EINVAL; 120 121 *gsi_out = gsi;
··· 89 int *trigger_out, 90 int *polarity_out) 91 { 92 + u32 gsi; 93 u8 pin; 94 struct acpi_prt_entry *entry; 95 int trigger = ACPI_LEVEL_SENSITIVE; 96 + int ret, polarity = acpi_irq_model == ACPI_IRQ_MODEL_GIC ? 97 ACPI_ACTIVE_HIGH : ACPI_ACTIVE_LOW; 98 99 if (!dev || !gsi_out || !trigger_out || !polarity_out) ··· 105 106 entry = acpi_pci_irq_lookup(dev, pin); 107 if (entry) { 108 + ret = 0; 109 if (entry->link) 110 + ret = acpi_pci_link_allocate_irq(entry->link, 111 entry->index, 112 &trigger, &polarity, 113 + NULL, &gsi); 114 else 115 gsi = entry->index; 116 } else 117 + ret = -ENODEV; 118 119 + if (ret < 0) 120 return -EINVAL; 121 122 *gsi_out = gsi;
+1 -1
include/acpi/acpi_drivers.h
··· 51 52 int acpi_irq_penalty_init(void); 53 int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering, 54 - int *polarity, char **name); 55 int acpi_pci_link_free_irq(acpi_handle handle); 56 57 /* ACPI PCI Device Binding */
··· 51 52 int acpi_irq_penalty_init(void); 53 int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering, 54 + int *polarity, char **name, u32 *gsi); 55 int acpi_pci_link_free_irq(acpi_handle handle); 56 57 /* ACPI PCI Device Binding */