// SPDX-License-Identifier: GPL-2.0
#include <linux/cpu.h>

#include <asm/apic.h>
#include <asm/memtype.h>
#include <asm/processor.h>

#include "cpu.h"

static bool parse_8000_0008(struct topo_scan *tscan)
{
	struct {
		// ecx
		u32	cpu_nthreads		:  8, // Number of physical threads - 1
						:  4, // Reserved
			apicid_coreid_len	:  4, // Number of thread core ID bits (shift) in APIC ID
			perf_tsc_len		:  2, // Performance time-stamp counter size
						: 14; // Reserved
	} ecx;
	unsigned int sft;

	if (tscan->c->extended_cpuid_level < 0x80000008)
		return false;

	cpuid_leaf_reg(0x80000008, CPUID_ECX, &ecx);

	/* If the thread bits are 0, then get the shift value from ecx.cpu_nthreads */
	sft = ecx.apicid_coreid_len;
	if (!sft)
		sft = get_count_order(ecx.cpu_nthreads + 1);

	/*
	 * cpu_nthreads describes the number of threads in the package
	 * sft is the number of APIC ID bits per package
	 *
	 * As the number of actual threads per core is not described in
	 * this leaf, just set the CORE domain shift and let the later
	 * parsers set SMT shift. Assume one thread per core by default
	 * which is correct if there are no other CPUID leafs to parse.
	 */
	topology_update_dom(tscan, TOPO_SMT_DOMAIN, 0, 1);
	topology_set_dom(tscan, TOPO_CORE_DOMAIN, sft, ecx.cpu_nthreads + 1);
	return true;
}

static void store_node(struct topo_scan *tscan, u16 nr_nodes, u16 node_id)
{
	/*
	 * Starting with Fam 17h the DIE domain could probably be used to
	 * retrieve the node info on AMD/HYGON. Analysis of CPUID dumps
	 * suggests it's the topmost bit(s) of the CPU cores area, but
	 * that's guess work and neither enumerated nor documented.
	 *
	 * Up to Fam 16h this does not work at all and the legacy node ID
	 * has to be used.
	 */
	tscan->amd_nodes_per_pkg = nr_nodes;
	tscan->amd_node_id = node_id;
}

static bool parse_8000_001e(struct topo_scan *tscan, bool has_topoext)
{
	struct {
		// eax
		u32	ext_apic_id		: 32; // Extended APIC ID
		// ebx
		u32	core_id			:  8, // Unique per-socket logical core unit ID
			core_nthreads		:  8, // #Threads per core (zero-based)
						: 16; // Reserved
		// ecx
		u32	node_id			:  8, // Node (die) ID of invoking logical CPU
			nnodes_per_socket	:  3, // #nodes in invoking logical CPU's package/socket
						: 21; // Reserved
		// edx
		u32				: 32; // Reserved
	} leaf;

	if (!boot_cpu_has(X86_FEATURE_TOPOEXT))
		return false;

	cpuid_leaf(0x8000001e, &leaf);

	tscan->c->topo.initial_apicid = leaf.ext_apic_id;

	/*
	 * If leaf 0xb is available, then the domain shifts are set
	 * already and nothing to do here. Only valid for family >= 0x17.
	 */
	if (!has_topoext && tscan->c->x86 >= 0x17) {
		/*
		 * Leaf 0x80000008 set the CORE domain shift already.
		 * 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;

	rdmsrl(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(0xc0011005, 54) <= 0)
		return;

	rdmsrl(0xc0011005, msrval);
	if (msrval & BIT_64(54)) {
		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)
{
	bool has_topoext = false;

	/*
	 * If the extended topology leaf 0x8000_001e is available
	 * 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
	 * get SMT and CORE shift from leaf 0xb first, then try to
	 * get the CORE shift from leaf 0x8000_0008.
	 */
	if (cpu_feature_enabled(X86_FEATURE_TOPOEXT))
		has_topoext = cpu_parse_topology_ext(tscan);

	if (!has_topoext && !parse_8000_0008(tscan))
		return;

	/* Prefer leaf 0x8000001e if available */
	if (parse_8000_001e(tscan, has_topoext))
		return;

	/* Try the NODEID MSR */
	parse_fam10h_node_id(tscan);
}

void cpu_parse_topology_amd(struct topo_scan *tscan)
{
	tscan->amd_nodes_per_pkg = 1;
	topoext_fixup(tscan);
	parse_topology_amd(tscan);
	legacy_set_llc(tscan);

	if (tscan->amd_nodes_per_pkg > 1)
		set_cpu_cap(tscan->c, X86_FEATURE_AMD_DCM);
}

void cpu_topology_fixup_amd(struct topo_scan *tscan)
{
	struct cpuinfo_x86 *c = tscan->c;

	/*
	 * Adjust the core_id relative to the node when there is more than
	 * one node.
	 */
	if (tscan->c->x86 < 0x17 && tscan->amd_nodes_per_pkg > 1)
		c->topo.core_id %= tscan->dom_ncpus[TOPO_CORE_DOMAIN] / tscan->amd_nodes_per_pkg;
}
