arch/x86/pci/xen.c
Source file repositories/reference/linux-study-clean/arch/x86/pci/xen.c
File Facts
- System
- Linux kernel
- Corpus path
arch/x86/pci/xen.c- Extension
.c- Size
- 14973 bytes
- Lines
- 588
- Domain
- Architecture Layer
- Bucket
- arch/x86
- Inferred role
- Architecture Layer: exported/initcall integration point
- Status
- integration implementation candidate
Why This File Exists
CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.
- CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/export.hlinux/init.hlinux/pci.hlinux/acpi.hlinux/io.hasm/io_apic.hasm/pci_x86.hasm/cpuid/api.hasm/xen/hypervisor.hxen/features.hxen/events.hxen/pci.hasm/xen/pci.hasm/xen/cpuid.hasm/apic.hasm/acpi.hasm/i8259.hlinux/msi.h
Detected Declarations
struct xen_msi_opsfunction modefunction xen_register_pirqfunction acpi_register_gsi_xen_hvmfunction xen_register_gsifunction acpi_register_gsi_xenfunction xen_setup_msi_irqsfunction xen_msi_compose_msgfunction xen_hvm_setup_msi_irqsfunction msi_for_each_descfunction xen_initdom_setup_msi_irqsfunction msi_for_each_descfunction xen_initdom_restore_msifunction xen_teardown_msi_irqsfunction msi_for_each_descfunction xen_pv_teardown_msi_irqsfunction xen_msi_domain_alloc_irqsfunction xen_msi_domain_free_irqsfunction xen_setup_pci_msifunction xen_setup_pci_msifunction xen_hvm_msi_initfunction pci_xen_hvm_initfunction pci_xen_initial_domainexport xen_pci_frontend
Annotated Snippet
struct xen_msi_ops {
int (*setup_msi_irqs)(struct pci_dev *dev, int nvec, int type);
void (*teardown_msi_irqs)(struct pci_dev *dev);
};
static struct xen_msi_ops xen_msi_ops __ro_after_init;
static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
{
int irq, ret, i;
struct msi_desc *msidesc;
int *v;
if (type == PCI_CAP_ID_MSI && nvec > 1)
return 1;
v = kzalloc_objs(int, max(1, nvec));
if (!v)
return -ENOMEM;
if (type == PCI_CAP_ID_MSIX)
ret = xen_pci_frontend_enable_msix(dev, v, nvec);
else
ret = xen_pci_frontend_enable_msi(dev, v);
if (ret)
goto error;
i = 0;
msi_for_each_desc(msidesc, &dev->dev, MSI_DESC_NOTASSOCIATED) {
irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i],
(type == PCI_CAP_ID_MSI) ? nvec : 1,
(type == PCI_CAP_ID_MSIX) ?
"pcifront-msi-x" :
"pcifront-msi",
DOMID_SELF);
if (irq < 0) {
ret = irq;
goto free;
}
i++;
}
kfree(v);
return msi_device_populate_sysfs(&dev->dev);
error:
if (ret == -ENOSYS)
dev_err(&dev->dev, "Xen PCI frontend has not registered MSI/MSI-X support!\n");
else if (ret)
dev_err(&dev->dev, "Xen PCI frontend error: %d!\n", ret);
free:
kfree(v);
return ret;
}
static void xen_msi_compose_msg(struct pci_dev *pdev, unsigned int pirq,
struct msi_msg *msg)
{
/*
* We set vector == 0 to tell the hypervisor we don't care about
* it, but we want a pirq setup instead. We use the dest_id fields
* to pass the pirq that we want.
*/
memset(msg, 0, sizeof(*msg));
msg->address_hi = X86_MSI_BASE_ADDRESS_HIGH;
msg->arch_addr_hi.destid_8_31 = pirq >> 8;
msg->arch_addr_lo.destid_0_7 = pirq & 0xFF;
msg->arch_addr_lo.base_address = X86_MSI_BASE_ADDRESS_LOW;
msg->arch_data.delivery_mode = APIC_DELIVERY_MODE_EXTINT;
}
static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
{
int irq, pirq;
struct msi_desc *msidesc;
struct msi_msg msg;
if (type == PCI_CAP_ID_MSI && nvec > 1)
return 1;
msi_for_each_desc(msidesc, &dev->dev, MSI_DESC_NOTASSOCIATED) {
pirq = xen_allocate_pirq_msi(dev, msidesc);
if (pirq < 0) {
irq = -ENODEV;
goto error;
}
xen_msi_compose_msg(dev, pirq, &msg);
__pci_write_msi_msg(msidesc, &msg);
dev_dbg(&dev->dev, "xen: msi bound to pirq=%d\n", pirq);
irq = xen_bind_pirq_msi_to_irq(dev, msidesc, pirq,
(type == PCI_CAP_ID_MSI) ? nvec : 1,
(type == PCI_CAP_ID_MSIX) ?
Annotation
- Immediate include surface: `linux/export.h`, `linux/init.h`, `linux/pci.h`, `linux/acpi.h`, `linux/io.h`, `asm/io_apic.h`, `asm/pci_x86.h`, `asm/cpuid/api.h`.
- Detected declarations: `struct xen_msi_ops`, `function mode`, `function xen_register_pirq`, `function acpi_register_gsi_xen_hvm`, `function xen_register_gsi`, `function acpi_register_gsi_xen`, `function xen_setup_msi_irqs`, `function xen_msi_compose_msg`, `function xen_hvm_setup_msi_irqs`, `function msi_for_each_desc`.
- Atlas domain: Architecture Layer / arch/x86.
- Implementation status: integration implementation candidate.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.