Skip to content

Commit 1ca8677

Browse files
Lorenzo Pieralisirafaeljw
authored andcommitted
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>
1 parent 9ace475 commit 1ca8677

4 files changed

Lines changed: 44 additions & 29 deletions

File tree

drivers/acpi/pci_irq.c

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ static int acpi_pci_irq_check_entry(acpi_handle handle, struct pci_dev *dev,
188188
* the IRQ value, which is hardwired to specific interrupt inputs on
189189
* the interrupt controller.
190190
*/
191-
pr_debug("%04x:%02x:%02x[%c] -> %s[%d]\n",
191+
pr_debug("%04x:%02x:%02x[%c] -> %s[%u]\n",
192192
entry->id.segment, entry->id.bus, entry->id.device,
193193
pin_name(entry->pin), prt->source, entry->index);
194194

@@ -384,7 +384,7 @@ static inline bool acpi_pci_irq_valid(struct pci_dev *dev, u8 pin)
384384
int acpi_pci_irq_enable(struct pci_dev *dev)
385385
{
386386
struct acpi_prt_entry *entry;
387-
int gsi;
387+
u32 gsi;
388388
u8 pin;
389389
int triggering = ACPI_LEVEL_SENSITIVE;
390390
/*
@@ -422,18 +422,21 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
422422
return 0;
423423
}
424424

425+
rc = -ENODEV;
426+
425427
if (entry) {
426428
if (entry->link)
427-
gsi = acpi_pci_link_allocate_irq(entry->link,
429+
rc = acpi_pci_link_allocate_irq(entry->link,
428430
entry->index,
429431
&triggering, &polarity,
430-
&link);
431-
else
432+
&link, &gsi);
433+
else {
432434
gsi = entry->index;
433-
} else
434-
gsi = -1;
435+
rc = 0;
436+
}
437+
}
435438

436-
if (gsi < 0) {
439+
if (rc < 0) {
437440
/*
438441
* No IRQ known to the ACPI subsystem - maybe the BIOS /
439442
* driver reported one, then use it. Exit in any case.

drivers/acpi/pci_link.c

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ static int acpi_isa_irq_penalty[ACPI_MAX_ISA_IRQS] = {
448448
/* >IRQ15 */
449449
};
450450

451-
static int acpi_irq_pci_sharing_penalty(int irq)
451+
static int acpi_irq_pci_sharing_penalty(u32 irq)
452452
{
453453
struct acpi_pci_link *link;
454454
int penalty = 0;
@@ -474,7 +474,7 @@ static int acpi_irq_pci_sharing_penalty(int irq)
474474
return penalty;
475475
}
476476

477-
static int acpi_irq_get_penalty(int irq)
477+
static int acpi_irq_get_penalty(u32 irq)
478478
{
479479
int penalty = 0;
480480

@@ -528,7 +528,7 @@ static int acpi_irq_balance = -1; /* 0: static, 1: balance */
528528
static int acpi_pci_link_allocate(struct acpi_pci_link *link)
529529
{
530530
acpi_handle handle = link->device->handle;
531-
int irq;
531+
u32 irq;
532532
int i;
533533

534534
if (link->irq.initialized) {
@@ -598,44 +598,53 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
598598
return 0;
599599
}
600600

601-
/*
602-
* acpi_pci_link_allocate_irq
603-
* success: return IRQ >= 0
604-
* failure: return -1
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
605614
*/
606615
int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
607-
int *polarity, char **name)
616+
int *polarity, char **name, u32 *gsi)
608617
{
609618
struct acpi_device *device = acpi_fetch_acpi_dev(handle);
610619
struct acpi_pci_link *link;
611620

612621
if (!device) {
613622
acpi_handle_err(handle, "Invalid link device\n");
614-
return -1;
623+
return -ENODEV;
615624
}
616625

617626
link = acpi_driver_data(device);
618627
if (!link) {
619628
acpi_handle_err(handle, "Invalid link context\n");
620-
return -1;
629+
return -ENODEV;
621630
}
622631

623632
/* TBD: Support multiple index (IRQ) entries per Link Device */
624633
if (index) {
625634
acpi_handle_err(handle, "Invalid index %d\n", index);
626-
return -1;
635+
return -ENODEV;
627636
}
628637

629638
mutex_lock(&acpi_link_lock);
630639
if (acpi_pci_link_allocate(link)) {
631640
mutex_unlock(&acpi_link_lock);
632-
return -1;
641+
return -ENODEV;
633642
}
634643

635644
if (!link->irq.active) {
636645
mutex_unlock(&acpi_link_lock);
637646
acpi_handle_err(handle, "Link active IRQ is 0!\n");
638-
return -1;
647+
return -ENODEV;
639648
}
640649
link->refcnt++;
641650
mutex_unlock(&acpi_link_lock);
@@ -647,7 +656,9 @@ int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
647656
if (name)
648657
*name = acpi_device_bid(link->device);
649658
acpi_handle_debug(handle, "Link is referenced\n");
650-
return link->irq.active;
659+
*gsi = link->irq.active;
660+
661+
return 0;
651662
}
652663

653664
/*

drivers/xen/acpi.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,11 @@ int xen_acpi_get_gsi_info(struct pci_dev *dev,
8989
int *trigger_out,
9090
int *polarity_out)
9191
{
92-
int gsi;
92+
u32 gsi;
9393
u8 pin;
9494
struct acpi_prt_entry *entry;
9595
int trigger = ACPI_LEVEL_SENSITIVE;
96-
int polarity = acpi_irq_model == ACPI_IRQ_MODEL_GIC ?
96+
int ret, polarity = acpi_irq_model == ACPI_IRQ_MODEL_GIC ?
9797
ACPI_ACTIVE_HIGH : ACPI_ACTIVE_LOW;
9898

9999
if (!dev || !gsi_out || !trigger_out || !polarity_out)
@@ -105,17 +105,18 @@ int xen_acpi_get_gsi_info(struct pci_dev *dev,
105105

106106
entry = acpi_pci_irq_lookup(dev, pin);
107107
if (entry) {
108+
ret = 0;
108109
if (entry->link)
109-
gsi = acpi_pci_link_allocate_irq(entry->link,
110+
ret = acpi_pci_link_allocate_irq(entry->link,
110111
entry->index,
111112
&trigger, &polarity,
112-
NULL);
113+
NULL, &gsi);
113114
else
114115
gsi = entry->index;
115116
} else
116-
gsi = -1;
117+
ret = -ENODEV;
117118

118-
if (gsi < 0)
119+
if (ret < 0)
119120
return -EINVAL;
120121

121122
*gsi_out = gsi;

include/acpi/acpi_drivers.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151

5252
int acpi_irq_penalty_init(void);
5353
int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
54-
int *polarity, char **name);
54+
int *polarity, char **name, u32 *gsi);
5555
int acpi_pci_link_free_irq(acpi_handle handle);
5656

5757
/* ACPI PCI Device Binding */

0 commit comments

Comments
 (0)