Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

xen/pvh: Setup gsi for passthrough device

In PVH dom0, the gsis don't get registered, but the gsi of
a passthrough device must be configured for it to be able to be
mapped into a domU.

When assigning a device to passthrough, proactively setup the gsi
of the device during that process.

Signed-off-by: Jiqian Chen <Jiqian.Chen@amd.com>
Signed-off-by: Huang Rui <ray.huang@amd.com>
Signed-off-by: Jiqian Chen <Jiqian.Chen@amd.com>
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
Message-ID: <20240924061437.2636766-3-Jiqian.Chen@amd.com>
Signed-off-by: Juergen Gross <jgross@suse.com>

authored by

Jiqian Chen and committed by
Juergen Gross
b166b8ab 88801d04

+113 -1
+23
arch/x86/xen/enlighten_pvh.c
··· 4 4 #include <linux/mm.h> 5 5 6 6 #include <xen/hvc-console.h> 7 + #include <xen/acpi.h> 7 8 8 9 #include <asm/bootparam.h> 9 10 #include <asm/io_apic.h> ··· 28 27 */ 29 28 bool __ro_after_init xen_pvh; 30 29 EXPORT_SYMBOL_GPL(xen_pvh); 30 + 31 + #ifdef CONFIG_XEN_DOM0 32 + int xen_pvh_setup_gsi(int gsi, int trigger, int polarity) 33 + { 34 + int ret; 35 + struct physdev_setup_gsi setup_gsi; 36 + 37 + setup_gsi.gsi = gsi; 38 + setup_gsi.triggering = (trigger == ACPI_EDGE_SENSITIVE ? 0 : 1); 39 + setup_gsi.polarity = (polarity == ACPI_ACTIVE_HIGH ? 0 : 1); 40 + 41 + ret = HYPERVISOR_physdev_op(PHYSDEVOP_setup_gsi, &setup_gsi); 42 + if (ret == -EEXIST) { 43 + xen_raw_printk("Already setup the GSI :%d\n", gsi); 44 + ret = 0; 45 + } else if (ret) 46 + xen_raw_printk("Fail to setup GSI (%d)!\n", gsi); 47 + 48 + return ret; 49 + } 50 + EXPORT_SYMBOL_GPL(xen_pvh_setup_gsi); 51 + #endif 31 52 32 53 /* 33 54 * Reserve e820 UNUSABLE regions to inflate the memory balloon.
+1 -1
drivers/acpi/pci_irq.c
··· 288 288 } 289 289 #endif /* CONFIG_X86_IO_APIC */ 290 290 291 - static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin) 291 + struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin) 292 292 { 293 293 struct acpi_prt_entry *entry = NULL; 294 294 struct pci_dev *bridge;
+50
drivers/xen/acpi.c
··· 30 30 * IN THE SOFTWARE. 31 31 */ 32 32 33 + #include <linux/pci.h> 33 34 #include <xen/acpi.h> 34 35 #include <xen/interface/platform.h> 35 36 #include <asm/xen/hypercall.h> ··· 76 75 return xen_acpi_notify_hypervisor_state(sleep_state, val_a, 77 76 val_b, true); 78 77 } 78 + 79 + struct acpi_prt_entry { 80 + struct acpi_pci_id id; 81 + u8 pin; 82 + acpi_handle link; 83 + u32 index; 84 + }; 85 + 86 + int xen_acpi_get_gsi_info(struct pci_dev *dev, 87 + int *gsi_out, 88 + int *trigger_out, 89 + int *polarity_out) 90 + { 91 + int gsi; 92 + u8 pin; 93 + struct acpi_prt_entry *entry; 94 + int trigger = ACPI_LEVEL_SENSITIVE; 95 + int polarity = acpi_irq_model == ACPI_IRQ_MODEL_GIC ? 96 + ACPI_ACTIVE_HIGH : ACPI_ACTIVE_LOW; 97 + 98 + if (!dev || !gsi_out || !trigger_out || !polarity_out) 99 + return -EINVAL; 100 + 101 + pin = dev->pin; 102 + if (!pin) 103 + return -EINVAL; 104 + 105 + entry = acpi_pci_irq_lookup(dev, pin); 106 + if (entry) { 107 + if (entry->link) 108 + gsi = acpi_pci_link_allocate_irq(entry->link, 109 + entry->index, 110 + &trigger, &polarity, 111 + NULL); 112 + else 113 + gsi = entry->index; 114 + } else 115 + gsi = -1; 116 + 117 + if (gsi < 0) 118 + return -EINVAL; 119 + 120 + *gsi_out = gsi; 121 + *trigger_out = trigger; 122 + *polarity_out = polarity; 123 + 124 + return 0; 125 + } 126 + EXPORT_SYMBOL_GPL(xen_acpi_get_gsi_info);
+20
drivers/xen/xen-pciback/pci_stub.c
··· 21 21 #include <xen/events.h> 22 22 #include <xen/pci.h> 23 23 #include <xen/xen.h> 24 + #ifdef CONFIG_XEN_ACPI 25 + #include <xen/acpi.h> 26 + #endif 24 27 #include <asm/xen/hypervisor.h> 25 28 #include <xen/interface/physdev.h> 26 29 #include "pciback.h" ··· 370 367 static int pcistub_init_device(struct pci_dev *dev) 371 368 { 372 369 struct xen_pcibk_dev_data *dev_data; 370 + #ifdef CONFIG_XEN_ACPI 371 + int gsi, trigger, polarity; 372 + #endif 373 373 int err = 0; 374 374 375 375 dev_dbg(&dev->dev, "initializing...\n"); ··· 441 435 goto config_release; 442 436 pci_restore_state(dev); 443 437 } 438 + 439 + #ifdef CONFIG_XEN_ACPI 440 + if (xen_initial_domain() && xen_pvh_domain()) { 441 + err = xen_acpi_get_gsi_info(dev, &gsi, &trigger, &polarity); 442 + if (err) { 443 + dev_err(&dev->dev, "Fail to get gsi info!\n"); 444 + goto config_release; 445 + } 446 + err = xen_pvh_setup_gsi(gsi, trigger, polarity); 447 + if (err) 448 + goto config_release; 449 + } 450 + #endif 451 + 444 452 /* Now disable the device (this also ensures some private device 445 453 * data is setup before we export) 446 454 */
+1
include/linux/acpi.h
··· 362 362 363 363 struct pci_dev; 364 364 365 + struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin); 365 366 int acpi_pci_irq_enable (struct pci_dev *dev); 366 367 void acpi_penalize_isa_irq(int irq, int active); 367 368 bool acpi_isa_irq_available(int irq);
+18
include/xen/acpi.h
··· 67 67 acpi_suspend_lowlevel = xen_acpi_suspend_lowlevel; 68 68 } 69 69 } 70 + int xen_pvh_setup_gsi(int gsi, int trigger, int polarity); 71 + int xen_acpi_get_gsi_info(struct pci_dev *dev, 72 + int *gsi_out, 73 + int *trigger_out, 74 + int *polarity_out); 70 75 #else 71 76 static inline void xen_acpi_sleep_register(void) 72 77 { 78 + } 79 + 80 + static inline int xen_pvh_setup_gsi(int gsi, int trigger, int polarity) 81 + { 82 + return -1; 83 + } 84 + 85 + static inline int xen_acpi_get_gsi_info(struct pci_dev *dev, 86 + int *gsi_out, 87 + int *trigger_out, 88 + int *polarity_out) 89 + { 90 + return -1; 73 91 } 74 92 #endif 75 93