arch/x86/kernel/cpu/topology_amd.c

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

File Facts

System
Linux kernel
Corpus path
arch/x86/kernel/cpu/topology_amd.c
Extension
.c
Size
6524 bytes
Lines
229
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.

Dependency Surface

Detected Declarations

Annotated Snippet

if (tscan->c->x86 >= 0x17) {
			/* Update the SMT domain, but do not propagate it. */
			unsigned int nthreads = leaf.core_nthreads + 1;

			topology_update_dom(tscan, TOPO_SMT_DOMAIN,
					    get_count_order(nthreads), nthreads);
		}
	}

	store_node(tscan, leaf.nnodes_per_socket + 1, leaf.node_id);

	if (tscan->c->x86_vendor == X86_VENDOR_AMD) {
		if (tscan->c->x86 == 0x15)
			tscan->c->topo.cu_id = leaf.core_id;

		cacheinfo_amd_init_llc_id(tscan->c, leaf.node_id);
	} else {
		/*
		 * Package ID is ApicId[6..] on certain Hygon CPUs. See
		 * commit e0ceeae708ce for explanation. The topology info
		 * is screwed up: The package shift is always 6 and the
		 * node ID is bit [4:5].
		 */
		if (!boot_cpu_has(X86_FEATURE_HYPERVISOR) && tscan->c->x86_model <= 0x3) {
			topology_set_dom(tscan, TOPO_CORE_DOMAIN, 6,
					 tscan->dom_ncpus[TOPO_CORE_DOMAIN]);
		}
		cacheinfo_hygon_init_llc_id(tscan->c);
	}
	return true;
}

static void parse_fam10h_node_id(struct topo_scan *tscan)
{
	union {
		struct {
			u64	node_id		:  3,
				nodes_per_pkg	:  3,
				unused		: 58;
		};
		u64		msr;
	} nid;

	if (!boot_cpu_has(X86_FEATURE_NODEID_MSR))
		return;

	rdmsrq(MSR_FAM10H_NODE_ID, nid.msr);
	store_node(tscan, nid.nodes_per_pkg + 1, nid.node_id);
	tscan->c->topo.llc_id = nid.node_id;
}

static void legacy_set_llc(struct topo_scan *tscan)
{
	unsigned int apicid = tscan->c->topo.initial_apicid;

	/* If none of the parsers set LLC ID then use the die ID for it. */
	if (tscan->c->topo.llc_id == BAD_APICID)
		tscan->c->topo.llc_id = apicid >> tscan->dom_shifts[TOPO_CORE_DOMAIN];
}

static void topoext_fixup(struct topo_scan *tscan)
{
	struct cpuinfo_x86 *c = tscan->c;
	u64 msrval;

	/* Try to re-enable TopologyExtensions if switched off by BIOS */
	if (cpu_has(c, X86_FEATURE_TOPOEXT) || c->x86_vendor != X86_VENDOR_AMD ||
	    c->x86 != 0x15 || c->x86_model < 0x10 || c->x86_model > 0x6f)
		return;

	if (msr_set_bit(MSR_AMD64_CPUID_EXT_FEAT,
			MSR_AMD64_CPUID_EXT_FEAT_TOPOEXT_BIT) <= 0)
		return;

	rdmsrq(MSR_AMD64_CPUID_EXT_FEAT, msrval);
	if (msrval & MSR_AMD64_CPUID_EXT_FEAT_TOPOEXT) {
		set_cpu_cap(c, X86_FEATURE_TOPOEXT);
		pr_info_once(FW_INFO "CPU: Re-enabling disabled Topology Extensions Support.\n");
	}
}

static void parse_topology_amd(struct topo_scan *tscan)
{
	if (cpu_feature_enabled(X86_FEATURE_AMD_HTR_CORES))
		tscan->c->topo.cpu_type = cpuid_ebx(0x80000026);

	/*
	 * Try to get SMT, CORE, TILE, and DIE shifts from extended
	 * CPUID leaf 0x8000_0026 on supported processors first. If
	 * extended CPUID leaf 0x8000_0026 is not supported, try to

Annotation

Implementation Notes