arch/x86/kernel/cpu/topology.c

Source file repositories/reference/linux-study-clean/arch/x86/kernel/cpu/topology.c

File Facts

System
Linux kernel
Corpus path
arch/x86/kernel/cpu/topology.c
Extension
.c
Size
17124 bytes
Lines
572
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.

Dependency Surface

Detected Declarations

Annotated Snippet

if (is_bsp || !has_apic_base) {
			topo_info.real_bsp_apic_id = apic_id;
			return false;
		}
		/*
		 * If the boot APIC is enumerated first, but the APICBASE
		 * MSR does not have the BSP bit set, then there is no way
		 * to discover the real BSP here. Assume a crash kernel and
		 * limit the number of CPUs to 1 as an INIT to the real BSP
		 * would reset the machine.
		 */
		pr_warn("Enumerated BSP APIC %x is not marked in APICBASE MSR\n", apic_id);
		pr_warn("Assuming crash kernel. Limiting to one CPU to prevent machine INIT\n");
		set_nr_cpu_ids(1);
		goto fwbug;
	}

	pr_warn("Boot CPU APIC ID not the first enumerated APIC ID: %x != %x\n",
		topo_info.boot_cpu_apic_id, apic_id);

	if (is_bsp) {
		/*
		 * The boot CPU has the APIC BSP bit set. Use it and complain
		 * about the broken firmware enumeration.
		 */
		topo_info.real_bsp_apic_id = topo_info.boot_cpu_apic_id;
		goto fwbug;
	}

	pr_warn("Crash kernel detected. Disabling real BSP to prevent machine INIT\n");

	topo_info.real_bsp_apic_id = apic_id;
	return true;

fwbug:
	pr_warn(FW_BUG "APIC enumeration order not specification compliant\n");
	return false;
}

static unsigned int topo_unit_count(u32 lvlid, enum x86_topology_domains at_level,
				    unsigned long *map)
{
	unsigned int end;

	/* Calculate the exclusive end */
	end = lvlid + (1U << x86_topo_system.dom_shifts[at_level]);
	return bitmap_weight_from(map, lvlid, end);
}

static __init void topo_register_apic(u32 apic_id, u32 acpi_id, bool present)
{
	int cpu, dom;

	if (present) {
		set_bit(apic_id, phys_cpu_present_map);

		/*
		 * Double registration is valid in case of the boot CPU
		 * APIC because that is registered before the enumeration
		 * of the APICs via firmware parsers or VM guest
		 * mechanisms.
		 */
		if (apic_id == topo_info.boot_cpu_apic_id)
			cpu = 0;
		else
			cpu = topo_get_cpunr(apic_id);

		cpuid_to_apicid[cpu] = apic_id;
		topo_set_cpuids(cpu, apic_id, acpi_id);
	} else {
		topo_info.nr_disabled_cpus++;
	}

	/*
	 * Register present and possible CPUs in the domain
	 * maps. cpu_possible_map will be updated in
	 * topology_init_possible_cpus() after enumeration is done.
	 */
	for (dom = TOPO_SMT_DOMAIN; dom < TOPO_MAX_DOMAIN; dom++)
		set_bit(topo_apicid(apic_id, dom), apic_maps[dom].map);
}

/**
 * topology_register_apic - Register an APIC in early topology maps
 * @apic_id:	The APIC ID to set up
 * @acpi_id:	The ACPI ID associated to the APIC
 * @present:	True if the corresponding CPU is present
 */
void __init topology_register_apic(u32 apic_id, u32 acpi_id, bool present)
{

Annotation

Implementation Notes