arch/x86/kernel/apic/io_apic.c
Source file repositories/reference/linux-study-clean/arch/x86/kernel/apic/io_apic.c
File Facts
- System
- Linux kernel
- Corpus path
arch/x86/kernel/apic/io_apic.c- Extension
.c- Size
- 78812 bytes
- Lines
- 2958
- 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.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- 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/mm.hlinux/interrupt.hlinux/irq.hlinux/init.hlinux/delay.hlinux/sched.hlinux/pci.hlinux/mc146818rtc.hlinux/compiler.hlinux/acpi.hlinux/export.hlinux/syscore_ops.hlinux/freezer.hlinux/kthread.hlinux/jiffies.hlinux/slab.hlinux/memblock.hlinux/msi.hasm/irqdomain.hasm/io.hasm/smp.hasm/cpu.hasm/desc.hasm/proto.hasm/acpi.hasm/dma.hasm/timer.hasm/time.hasm/i8259.hasm/setup.hasm/irq_remapping.hasm/hw_irq.h
Detected Declarations
struct irq_pin_liststruct mp_chip_datastruct mp_ioapic_gsistruct io_apicfunction mpc_ioapic_idfunction mpc_ioapic_addrfunction mp_ioapic_pin_countfunction mp_pin_to_gsifunction mp_is_legacy_irqfunction disable_ioapic_supportfunction parse_noapicfunction mp_save_irqfunction alloc_ioapic_saved_registersfunction free_ioapic_saved_registersfunction arch_early_ioapic_initfunction io_apic_eoifunction native_io_apic_readfunction io_apic_writefunction __ioapic_read_entryfunction ioapic_read_entryfunction __ioapic_write_entryfunction ioapic_write_entryfunction ioapic_mask_entryfunction add_pin_to_irq_nodefunction __remove_pin_from_irqfunction list_for_each_entry_safefunction io_apic_modify_irqfunction for_each_irq_pinfunction io_apic_syncfunction mask_ioapic_irqfunction __unmask_ioapicfunction unmask_ioapic_irqfunction Specsfunction eoi_ioapic_pinfunction clear_IO_APIC_pinfunction clear_IO_APICfunction ioapic_pirq_setupfunction save_ioapic_entriesfunction for_each_ioapicfunction mask_ioapic_entriesfunction for_each_ioapicfunction for_each_pinfunction restore_ioapic_entriesfunction for_each_ioapicfunction find_irq_entryfunction find_isa_irq_pinfunction find_isa_irq_apicfunction for_each_ioapic
Annotated Snippet
device_initcall(ioapic_init_ops);
static int io_apic_get_redir_entries(int ioapic)
{
union IO_APIC_reg_01 reg_01;
guard(raw_spinlock_irqsave)(&ioapic_lock);
reg_01.raw = io_apic_read(ioapic, 1);
/*
* The register returns the maximum index redir index supported,
* which is one less than the total number of redir entries.
*/
return reg_01.bits.entries + 1;
}
unsigned int arch_dynirq_lower_bound(unsigned int from)
{
unsigned int ret;
/*
* dmar_alloc_hwirq() may be called before setup_IO_APIC(), so use
* gsi_top if ioapic_dynirq_base hasn't been initialized yet.
*/
ret = ioapic_dynirq_base ? : gsi_top;
/*
* For DT enabled machines ioapic_dynirq_base is irrelevant and
* always 0. gsi_top can be 0 if there is no IO/APIC registered.
* 0 is an invalid interrupt number for dynamic allocations. Return
* @from instead.
*/
return ret ? : from;
}
#ifdef CONFIG_X86_32
static int io_apic_get_unique_id(int ioapic, int apic_id)
{
static DECLARE_BITMAP(apic_id_map, MAX_LOCAL_APIC);
const u32 broadcast_id = 0xF;
union IO_APIC_reg_00 reg_00;
int i = 0;
/* Initialize the ID map */
if (bitmap_empty(apic_id_map, MAX_LOCAL_APIC))
copy_phys_cpu_present_map(apic_id_map);
scoped_guard (raw_spinlock_irqsave, &ioapic_lock)
reg_00.raw = io_apic_read(ioapic, 0);
if (apic_id >= broadcast_id) {
pr_warn("IOAPIC[%d]: Invalid apic_id %d, trying %d\n",
ioapic, apic_id, reg_00.bits.ID);
apic_id = reg_00.bits.ID;
}
/* Every APIC in a system must have a unique ID */
if (test_bit(apic_id, apic_id_map)) {
for (i = 0; i < broadcast_id; i++) {
if (!test_bit(i, apic_id_map))
break;
}
if (i == broadcast_id)
panic("Max apic_id exceeded!\n");
pr_warn("IOAPIC[%d]: apic_id %d already used, trying %d\n", ioapic, apic_id, i);
apic_id = i;
}
set_bit(apic_id, apic_id_map);
if (reg_00.bits.ID != apic_id) {
reg_00.bits.ID = apic_id;
scoped_guard (raw_spinlock_irqsave, &ioapic_lock) {
io_apic_write(ioapic, 0, reg_00.raw);
reg_00.raw = io_apic_read(ioapic, 0);
}
/* Sanity check */
if (reg_00.bits.ID != apic_id) {
pr_err("IOAPIC[%d]: Unable to change apic_id!\n", ioapic);
return -1;
}
}
apic_pr_verbose("IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id);
return apic_id;
Annotation
- Immediate include surface: `linux/mm.h`, `linux/interrupt.h`, `linux/irq.h`, `linux/init.h`, `linux/delay.h`, `linux/sched.h`, `linux/pci.h`, `linux/mc146818rtc.h`.
- Detected declarations: `struct irq_pin_list`, `struct mp_chip_data`, `struct mp_ioapic_gsi`, `struct io_apic`, `function mpc_ioapic_id`, `function mpc_ioapic_addr`, `function mp_ioapic_pin_count`, `function mp_pin_to_gsi`, `function mp_is_legacy_irq`, `function disable_ioapic_support`.
- Atlas domain: Architecture Layer / arch/x86.
- Implementation status: integration implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
- 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.