arch/x86/kernel/apic/x2apic_cluster.c
Source file repositories/reference/linux-study-clean/arch/x86/kernel/apic/x2apic_cluster.c
File Facts
- System
- Linux kernel
- Corpus path
arch/x86/kernel/apic/x2apic_cluster.c- Extension
.c- Size
- 6793 bytes
- Lines
- 262
- Domain
- Architecture Layer
- Bucket
- arch/x86
- Inferred role
- Architecture Layer: implementation source
- Status
- source 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.
- 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/cpuhotplug.hlinux/cpumask.hlinux/slab.hlinux/mm.hasm/apic.hlocal.h
Detected Declarations
function x2apic_acpi_madt_oem_checkfunction x2apic_send_IPIfunction __x2apic_send_IPI_maskfunction x2apic_send_IPI_maskfunction x2apic_send_IPI_mask_allbutselffunction x2apic_calc_apicidfunction init_x2apic_ldrfunction prefill_clustermaskfunction for_each_present_cpufunction alloc_clustermaskfunction CPUsfunction x2apic_prepare_cpufunction x2apic_dead_cpufunction x2apic_cluster_probe
Annotated Snippet
if (apicid != BAD_APICID && apic_cluster(apicid) == cluster) {
cmsk = per_cpu(cluster_masks, cpu_i);
/*
* If the cluster is already initialized, just store
* the mask and return. There's no need to propagate.
*/
if (cmsk) {
per_cpu(cluster_masks, cpu) = cmsk;
return 0;
}
}
}
/*
* No CPU in the cluster has ever been initialized, so fall through to
* the boot time code which will also populate the cluster mask for any
* other CPU in the cluster which is (now) present.
*/
alloc:
cmsk = kzalloc_node(sizeof(*cmsk), GFP_KERNEL, node);
if (!cmsk)
return -ENOMEM;
per_cpu(cluster_masks, cpu) = cmsk;
prefill_clustermask(cmsk, cpu, cluster);
return 0;
}
static int x2apic_prepare_cpu(unsigned int cpu)
{
u32 phys_apicid = apic->cpu_present_to_apicid(cpu);
u32 cluster = apic_cluster(phys_apicid);
u32 logical_apicid = (cluster << 16) | (1 << (phys_apicid & 0xf));
int node = cpu_to_node(cpu);
x86_cpu_to_logical_apicid[cpu] = logical_apicid;
if (alloc_clustermask(cpu, cluster, node) < 0)
return -ENOMEM;
if (!zalloc_cpumask_var_node(&per_cpu(ipi_mask, cpu), GFP_KERNEL, node))
return -ENOMEM;
return 0;
}
static int x2apic_dead_cpu(unsigned int dead_cpu)
{
struct cpumask *cmsk = per_cpu(cluster_masks, dead_cpu);
if (cmsk)
cpumask_clear_cpu(dead_cpu, cmsk);
free_cpumask_var(per_cpu(ipi_mask, dead_cpu));
return 0;
}
static int x2apic_cluster_probe(void)
{
u32 slots;
if (!x2apic_mode)
return 0;
slots = max_t(u32, L1_CACHE_BYTES/sizeof(u32), nr_cpu_ids);
x86_cpu_to_logical_apicid = kcalloc(slots, sizeof(u32), GFP_KERNEL);
if (!x86_cpu_to_logical_apicid)
return 0;
if (cpuhp_setup_state(CPUHP_X2APIC_PREPARE, "x86/x2apic:prepare",
x2apic_prepare_cpu, x2apic_dead_cpu) < 0) {
pr_err("Failed to register X2APIC_PREPARE\n");
kfree(x86_cpu_to_logical_apicid);
x86_cpu_to_logical_apicid = NULL;
return 0;
}
init_x2apic_ldr();
return 1;
}
static struct apic apic_x2apic_cluster __ro_after_init = {
.name = "cluster x2apic",
.probe = x2apic_cluster_probe,
.acpi_madt_oem_check = x2apic_acpi_madt_oem_check,
.dest_mode_logical = true,
.disable_esr = 0,
.init_apic_ldr = init_x2apic_ldr,
.cpu_present_to_apicid = default_cpu_present_to_apicid,
Annotation
- Immediate include surface: `linux/cpuhotplug.h`, `linux/cpumask.h`, `linux/slab.h`, `linux/mm.h`, `asm/apic.h`, `local.h`.
- Detected declarations: `function x2apic_acpi_madt_oem_check`, `function x2apic_send_IPI`, `function __x2apic_send_IPI_mask`, `function x2apic_send_IPI_mask`, `function x2apic_send_IPI_mask_allbutself`, `function x2apic_calc_apicid`, `function init_x2apic_ldr`, `function prefill_clustermask`, `function for_each_present_cpu`, `function alloc_clustermask`.
- Atlas domain: Architecture Layer / arch/x86.
- Implementation status: source implementation candidate.
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.