Skip to content

Commit

Permalink
x86: add hygon family 18h
Browse files Browse the repository at this point in the history
  • Loading branch information
samuelliao-tx authored and Lei Chen committed Mar 13, 2020
1 parent 6ec6c5a commit 660998b
Show file tree
Hide file tree
Showing 41 changed files with 196 additions and 46 deletions.
4 changes: 4 additions & 0 deletions arch/x86/events/amd/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -782,6 +782,10 @@ static int __init amd_core_pmu_init(void)
* We fallback to using default amd_get_event_constraints.
*/
break;
case 0x18:
pr_cont("Fam18h ");
/* Using default amd_get_event_constraints. */
break;
default:
pr_err("core perfctr but no constraints; unknown hardware!\n");
return -ENODEV;
Expand Down
16 changes: 11 additions & 5 deletions arch/x86/events/amd/uncore.c
Original file line number Diff line number Diff line change
Expand Up @@ -515,15 +515,16 @@ static int __init amd_uncore_init(void)
{
int ret = -ENODEV;

if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD &&
boot_cpu_data.x86_vendor != X86_VENDOR_HYGON)
return -ENODEV;

if (!boot_cpu_has(X86_FEATURE_TOPOEXT))
return -ENODEV;

if (boot_cpu_data.x86 == 0x17) {
if (boot_cpu_data.x86 == 0x17 || boot_cpu_data.x86 == 0x18) {
/*
* For F17h, the Northbridge counters are repurposed as Data
* For F17h/F18h, the Northbridge counters are repurposed as Data
* Fabric counters. Also, L3 counters are supported too. The PMUs
* are exported based on family as either L2 or L3 and NB or DF.
*/
Expand Down Expand Up @@ -557,7 +558,10 @@ static int __init amd_uncore_init(void)
if (ret)
goto fail_nb;

pr_info("AMD NB counters detected\n");
pr_info("%s NB counters detected\n",
boot_cpu_data.x86_vendor == X86_VENDOR_HYGON ?
"HYGON" : "AMD");

ret = 0;
}

Expand All @@ -571,7 +575,9 @@ static int __init amd_uncore_init(void)
if (ret)
goto fail_llc;

pr_info("AMD LLC counters detected\n");
pr_info("%s LLC counters detected\n",
boot_cpu_data.x86_vendor == X86_VENDOR_HYGON ?
"HYGON" : "AMD");
ret = 0;
}

Expand Down
4 changes: 4 additions & 0 deletions arch/x86/events/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1756,6 +1756,10 @@ static int __init init_hw_perf_events(void)
case X86_VENDOR_AMD:
err = amd_pmu_init();
break;
case X86_VENDOR_HYGON:
err = amd_pmu_init();
x86_pmu.name = "HYGON";
break;
default:
err = -ENOTSUPP;
}
Expand Down
3 changes: 3 additions & 0 deletions arch/x86/include/asm/amd_nb.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ static inline u16 amd_pci_dev_to_node_id(struct pci_dev *pdev)

static inline bool amd_gart_present(void)
{
if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
return false;

/* GART present only on Fam15h, upto model 0fh */
if (boot_cpu_data.x86 == 0xf || boot_cpu_data.x86 == 0x10 ||
(boot_cpu_data.x86 == 0x15 && boot_cpu_data.x86_model < 0x10))
Expand Down
4 changes: 4 additions & 0 deletions arch/x86/include/asm/kvm_emulate.h
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,10 @@ struct x86_emulate_ctxt {
#define X86EMUL_CPUID_VENDOR_AMDisbetterI_ecx 0x21726574
#define X86EMUL_CPUID_VENDOR_AMDisbetterI_edx 0x74656273

#define X86EMUL_CPUID_VENDOR_HygonGenuine_ebx 0x6f677948
#define X86EMUL_CPUID_VENDOR_HygonGenuine_ecx 0x656e6975
#define X86EMUL_CPUID_VENDOR_HygonGenuine_edx 0x6e65476e

#define X86EMUL_CPUID_VENDOR_GenuineIntel_ebx 0x756e6547
#define X86EMUL_CPUID_VENDOR_GenuineIntel_ecx 0x6c65746e
#define X86EMUL_CPUID_VENDOR_GenuineIntel_edx 0x49656e69
Expand Down
3 changes: 2 additions & 1 deletion arch/x86/include/asm/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,8 @@ enum cpuid_regs_idx {
#define X86_VENDOR_CENTAUR 5
#define X86_VENDOR_TRANSMETA 7
#define X86_VENDOR_NSC 8
#define X86_VENDOR_NUM 9
#define X86_VENDOR_HYGON 9
#define X86_VENDOR_NUM 10

#define X86_VENDOR_UNKNOWN 0xff

Expand Down
5 changes: 3 additions & 2 deletions arch/x86/include/asm/virtext.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,10 @@ static inline void cpu_emergency_vmxoff(void)
*/
static inline int cpu_has_svm(const char **msg)
{
if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) {
if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD &&
boot_cpu_data.x86_vendor != X86_VENDOR_HYGON) {
if (msg)
*msg = "not amd";
*msg = "not amd or hygon";
return 0;
}

Expand Down
1 change: 1 addition & 0 deletions arch/x86/kernel/acpi/cstate.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ static int __init ffh_cstate_init(void)
struct cpuinfo_x86 *c = &boot_cpu_data;

if (c->x86_vendor != X86_VENDOR_INTEL &&
c->x86_vendor != X86_VENDOR_HYGON &&
c->x86_vendor != X86_VENDOR_AMD)
return -1;

Expand Down
4 changes: 4 additions & 0 deletions arch/x86/kernel/alternative.c
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,10 @@ void __init arch_init_ideal_nops(void)
}
break;

case X86_VENDOR_HYGON:
ideal_nops = p6_nops;
return;

case X86_VENDOR_AMD:
if (boot_cpu_data.x86 > 0xf) {
ideal_nops = p6_nops;
Expand Down
10 changes: 9 additions & 1 deletion arch/x86/kernel/amd_nb.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ static u32 *flush_words;

static const struct pci_device_id amd_root_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_ROOT) },
{ PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_AMD_17H_ROOT) },
{}
};

Expand All @@ -40,6 +41,7 @@ const struct pci_device_id amd_nb_misc_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F3) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_DF_F3) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CNB17H_F3) },
{ PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_AMD_17H_DF_F3) },
{}
};
EXPORT_SYMBOL_GPL(amd_nb_misc_ids);
Expand All @@ -52,6 +54,7 @@ static const struct pci_device_id amd_nb_link_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F4) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_DF_F4) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CNB17H_F4) },
{ PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_AMD_17H_DF_F4) },
{}
};

Expand Down Expand Up @@ -258,6 +261,10 @@ bool __init early_is_amd_nb(u32 device)
const struct pci_device_id *id;
u32 vendor = device & 0xffff;

if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD &&
boot_cpu_data.x86_vendor != X86_VENDOR_HYGON)
return false;

device >>= 16;
for (id = amd_nb_misc_ids; id->vendor; id++)
if (vendor == id->vendor && device == id->device)
Expand All @@ -271,7 +278,8 @@ struct resource *amd_get_mmconfig_range(struct resource *res)
u64 base, msr;
unsigned int segn_busn_bits;

if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD &&
boot_cpu_data.x86_vendor != X86_VENDOR_HYGON)
return NULL;

/* assume all cpus from fam10h have mmconfig */
Expand Down
7 changes: 7 additions & 0 deletions arch/x86/kernel/apic/apic.c
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,11 @@ static int modern_apic(void)
if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
boot_cpu_data.x86 >= 0xf)
return 1;

/* Hygon systems use modern APIC */
if (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON)
return 1;

return lapic_get_version() >= 0x14;
}

Expand Down Expand Up @@ -1813,6 +1818,8 @@ static int __init detect_init_APIC(void)
(boot_cpu_data.x86 >= 15))
break;
goto no_apic;
case X86_VENDOR_HYGON:
break;
case X86_VENDOR_INTEL:
if (boot_cpu_data.x86 == 6 || boot_cpu_data.x86 == 15 ||
(boot_cpu_data.x86 == 5 && boot_cpu_has(X86_FEATURE_APIC)))
Expand Down
1 change: 1 addition & 0 deletions arch/x86/kernel/apic/probe_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ void __init default_setup_apic_routing(void)
break;
}
/* If P4 and above fall through */
case X86_VENDOR_HYGON:
case X86_VENDOR_AMD:
def_to_bigsmp = 1;
}
Expand Down
43 changes: 41 additions & 2 deletions arch/x86/kernel/cpu/amd.c
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,25 @@ static void amd_get_topology(struct cpuinfo_x86 *c)
c->x86_max_cores /= smp_num_siblings;
}

if (c->x86_vendor == X86_VENDOR_HYGON && cpuid_edx(0x80000006)) {
/*
* We may have multiple LLCs if L3 caches exist, so check if we
* have an L3 cache by looking at the L3 cache CPUID leaf.
*/
if (c->x86 == 0x17) {
/* Socket ID is ApicId[6] for these processors. */
c->phys_proc_id = c->initial_apicid >> 6;
/*
* LLC is at the core complex level.
* Core complex id is ApicId[3].
*/
per_cpu(cpu_llc_id, cpu) = c->apicid >> 3;
} else {
/* LLC is at the node level. */
per_cpu(cpu_llc_id, cpu) = node_id;
}
} else {

/*
* In case leaf B is available, use it to derive
* topology information.
Expand All @@ -361,7 +380,7 @@ static void amd_get_topology(struct cpuinfo_x86 *c)
c->x86_coreid_bits = get_count_order(c->x86_max_cores);

cacheinfo_amd_init_llc_id(c, cpu, node_id);

}
} else if (cpu_has(c, X86_FEATURE_NODEID_MSR)) {
u64 value;

Expand Down Expand Up @@ -551,13 +570,14 @@ static void bsp_init_amd(struct cpuinfo_x86 *c)

if (!boot_cpu_has(X86_FEATURE_AMD_SSBD) &&
!boot_cpu_has(X86_FEATURE_VIRT_SSBD) &&
c->x86 >= 0x15 && c->x86 <= 0x17) {
c->x86 >= 0x15 && c->x86 <= 0x18) {
unsigned int bit;

switch (c->x86) {
case 0x15: bit = 54; break;
case 0x16: bit = 33; break;
case 0x17: bit = 10; break;
case 0x18: bit = 10; break;
default: return;
}
/*
Expand Down Expand Up @@ -794,6 +814,12 @@ static void init_amd_zn(struct cpuinfo_x86 *c)
set_cpu_cap(c, X86_FEATURE_CPB);
}

static void init_hygon_dhyana(struct cpuinfo_x86 *c)
{
set_cpu_cap(c, X86_FEATURE_ZEN);
set_cpu_cap(c, X86_FEATURE_CPB);
}

static void init_amd(struct cpuinfo_x86 *c)
{
early_init_amd(c);
Expand Down Expand Up @@ -823,6 +849,7 @@ static void init_amd(struct cpuinfo_x86 *c)
case 0x12: init_amd_ln(c); break;
case 0x15: init_amd_bd(c); break;
case 0x17: init_amd_zn(c); break;
case 0x18: init_hygon_dhyana(c); break;
}

/*
Expand Down Expand Up @@ -955,6 +982,18 @@ static void cpu_detect_tlb_amd(struct cpuinfo_x86 *c)
tlb_lli_4m[ENTRIES] = tlb_lli_2m[ENTRIES] >> 1;
}

static const struct cpu_dev hygon_cpu_dev = {
.c_vendor = "Hygon",
.c_ident = { "HygonGenuine" },
.c_early_init = early_init_amd,
.c_detect_tlb = cpu_detect_tlb_amd,
.c_bsp_init = bsp_init_amd,
.c_init = init_amd,
.c_x86_vendor = X86_VENDOR_HYGON,
};

cpu_dev_register(hygon_cpu_dev);

static const struct cpu_dev amd_cpu_dev = {
.c_vendor = "AMD",
.c_ident = { "AuthenticAMD" },
Expand Down
4 changes: 3 additions & 1 deletion arch/x86/kernel/cpu/bugs.c
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,7 @@ static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void)
}

if (cmd == SPECTRE_V2_CMD_RETPOLINE_AMD &&
boot_cpu_data.x86_vendor != X86_VENDOR_HYGON &&
boot_cpu_data.x86_vendor != X86_VENDOR_AMD) {
pr_err("retpoline,amd selected but CPU is not AMD. Switching to AUTO select\n");
return SPECTRE_V2_CMD_AUTO;
Expand Down Expand Up @@ -511,7 +512,8 @@ static void __init spectre_v2_select_mitigation(void)
return;

retpoline_auto:
if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD ||
boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) {
retpoline_amd:
if (!boot_cpu_has(X86_FEATURE_LFENCE_RDTSC)) {
pr_err("Spectre mitigation: LFENCE not serializing, switching to generic retpoline\n");
Expand Down
10 changes: 8 additions & 2 deletions arch/x86/kernel/cpu/cacheinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,10 @@ cpuid4_cache_lookup_regs(int index, struct _cpuid4_info_regs *this_leaf)
else
amd_cpuid4(index, &eax, &ebx, &ecx);
amd_init_l3_cache(this_leaf, index);
} else if (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) {
cpuid_count(0x8000001d, index, &eax.full,
&ebx.full, &ecx.full, &edx);
amd_init_l3_cache(this_leaf, index);
} else {
cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx);
}
Expand All @@ -623,7 +627,8 @@ static int find_num_cache_leaves(struct cpuinfo_x86 *c)
union _cpuid4_leaf_eax cache_eax;
int i = -1;

if (c->x86_vendor == X86_VENDOR_AMD)
if (c->x86_vendor == X86_VENDOR_AMD ||
c->x86_vendor == X86_VENDOR_HYGON)
op = 0x8000001d;
else
op = 4;
Expand Down Expand Up @@ -910,7 +915,8 @@ static void __cache_cpumap_setup(unsigned int cpu, int index,
int index_msb, i;
struct cpuinfo_x86 *c = &cpu_data(cpu);

if (c->x86_vendor == X86_VENDOR_AMD) {
if (c->x86_vendor == X86_VENDOR_AMD ||
c->x86_vendor == X86_VENDOR_HYGON) {
if (__cache_amd_cpumap_setup(cpu, index, base))
return;
}
Expand Down
1 change: 1 addition & 0 deletions arch/x86/kernel/cpu/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -914,6 +914,7 @@ static const __initconst struct x86_cpu_id cpu_no_speculation[] = {

static const __initconst struct x86_cpu_id cpu_no_meltdown[] = {
{ X86_VENDOR_AMD },
{ X86_VENDOR_HYGON },
{}
};

Expand Down
3 changes: 2 additions & 1 deletion arch/x86/kernel/cpu/mcheck/mce-severity.c
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,8 @@ int (*mce_severity)(struct mce *m, int tolerant, char **msg, bool is_excp) =

void __init mcheck_vendor_init_severity(void)
{
if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD ||
boot_cpu_data.x86_vendor == X86_VENDOR_HYGON)
mce_severity = mce_severity_amd;
}

Expand Down
Loading

0 comments on commit 660998b

Please sign in to comment.