2018-09-10 13:20:25

by Wen Pu

[permalink] [raw]
Subject: [PATCH v6 00/16] Add support for Hygon Dhyana Family 18h processor

As a new x86 CPU Vendor, Chengdu Haiguang IC Design Co., Ltd (Hygon)
is a Joint Venture between AMD and Haiguang Information Technology Co.,
Ltd., and aims at providing high performance x86 processor for China
server market.

The first generation Hygon's processor(Dhyana) originates from AMD
technology and shares most of the architecture with AMD's family 17h,
but with different CPU Vendor ID("HygonGenuine")/PCIE Device Vendor ID
(0x1D94)/Family series number (Family 18h).

To enable the support of Linux kernel to Hygon's CPU, we added a new
vendor type (X86_VENDOR_HYGON, with value of 9) in arch/x86/include/
asm/processor.h, and shared most of kernel support codes with AMD
family 17h.

As Hygon will negotiate with AMD to make sure that only Hygon will
use family 18h, so try to minimize code modification and share most
codes with AMD under this consideration.

This patch series have been applied and tested successfully on Hygon
Dhyana SoC silicon. Also tested on AMD EPYC (Family 17h) processor,
it works fine and makes no harm to the existing codes.


v5->v6:
- Rebased on 4.19-rc3 and tested against it.
- Add Reviewed-by from Borislav Petkov for cacheinfo, smpboot,
alternative and kvm.
- Rework the patch subjects and patch descriptions.
- Rework vendor checking for some patches to minimize the code
modification.

v4->v5:
- Rebased on 4.19-rc1 and tested against it.
- Add Reviewed-by from Boris Ostrovsky for Xen.
- Rework EDAC patch without vendor checking for minimal modification.

v3->v4:
- Rebased on 4.18.3 and tested against it.
- Merge patchs 05/17 perfctr and 10/17 events in v3 to patch 05/16
PMU for better patch function group.
- Add hygon_get_topology_early() in patch 01/16.
- Rework vendor checking and refine coding style.
- Add Acked-by from Bjorn Helgaas for pci.
- Add Acked-by from Rafael J. Wysocki for cpufreq and acpi.

v2->v3:
- Rebased on 4.18-rc8 and tested against it.
- Rework vendor checking codes to improve consistency.

v1->v2:
- Rebased on 4.18-rc6 and tested against it.
- Split the patchset to small series of patches.
- Rework patch descriptions.
- Create a separated arch/x86/kernel/cpu/hygon.c for Dhyana CPU
initialization to reduce long-term maintenance effort.


Pu Wen (16):
x86/cpu: Create Hygon Dhyana architecture support file
x86/cpu: Get cache info and setup cache cpumap for Hygon Dhyana
x86/cpu/mtrr: Support TOP_MEM2 and get MTRR number
x86/smpboot: SMP init nodelay and not flush caches before sleep
perf/x86: Add Hygon Dhyana support to PMU infrastructure
x86/alternative: Init ideal_nops for Hygon Dhyana
x86/pci: Add Hygon Dhyana support to PCI and north bridge
x86/apic: Add Hygon Dhyana support to APIC
x86/bugs: Add mitigation to spectre and no meltdown for Hygon Dhyana
x86/mce: Add Hygon Dhyana support to MCE infrastructure
x86/kvm: Add Hygon Dhyana support to KVM infrastructure
x86/xen: Add Hygon Dhyana support to Xen
ACPI, x86: Add Hygon Dhyana support
cpufreq, x86: Add Hygon Dhyana support
EDAC, amd64: Add Hygon Dhyana support
cpupower, x86: Add Hygon Dhyana support

MAINTAINERS | 6 +
arch/x86/Kconfig.cpu | 14 +
arch/x86/events/amd/core.c | 4 +
arch/x86/events/amd/uncore.c | 20 +-
arch/x86/events/core.c | 4 +
arch/x86/include/asm/cacheinfo.h | 1 +
arch/x86/include/asm/kvm_emulate.h | 4 +
arch/x86/include/asm/mce.h | 2 +
arch/x86/include/asm/processor.h | 3 +-
arch/x86/include/asm/virtext.h | 5 +-
arch/x86/kernel/alternative.c | 4 +
arch/x86/kernel/amd_nb.c | 47 ++-
arch/x86/kernel/apic/apic.c | 13 +-
arch/x86/kernel/apic/probe_32.c | 1 +
arch/x86/kernel/cpu/Makefile | 1 +
arch/x86/kernel/cpu/bugs.c | 6 +-
arch/x86/kernel/cpu/cacheinfo.c | 31 +-
arch/x86/kernel/cpu/common.c | 1 +
arch/x86/kernel/cpu/cpu.h | 1 +
arch/x86/kernel/cpu/hygon.c | 411 +++++++++++++++++++++
arch/x86/kernel/cpu/mcheck/mce-severity.c | 3 +-
arch/x86/kernel/cpu/mcheck/mce.c | 20 +-
arch/x86/kernel/cpu/mtrr/cleanup.c | 3 +-
arch/x86/kernel/cpu/mtrr/mtrr.c | 2 +-
arch/x86/kernel/cpu/perfctr-watchdog.c | 2 +
arch/x86/kernel/smpboot.c | 4 +-
arch/x86/kvm/emulate.c | 11 +-
arch/x86/pci/amd_bus.c | 6 +-
arch/x86/xen/pmu.c | 12 +-
drivers/acpi/acpi_pad.c | 1 +
drivers/acpi/processor_idle.c | 1 +
drivers/cpufreq/acpi-cpufreq.c | 5 +
drivers/cpufreq/amd_freq_sensitivity.c | 9 +-
drivers/edac/amd64_edac.c | 8 +-
drivers/edac/mce_amd.c | 4 +-
include/linux/pci_ids.h | 2 +
tools/power/cpupower/utils/cpufreq-info.c | 6 +-
tools/power/cpupower/utils/helpers/amd.c | 4 +-
tools/power/cpupower/utils/helpers/cpuid.c | 8 +-
tools/power/cpupower/utils/helpers/helpers.h | 2 +-
tools/power/cpupower/utils/helpers/misc.c | 2 +-
.../cpupower/utils/idle_monitor/mperf_monitor.c | 3 +-
42 files changed, 646 insertions(+), 51 deletions(-)
create mode 100644 arch/x86/kernel/cpu/hygon.c

--
2.7.4



2018-09-10 13:18:49

by Wen Pu

[permalink] [raw]
Subject: [PATCH v6 02/16] x86/cpu: Get cache info and setup cache cpumap for Hygon Dhyana

The Hygon Dhyana CPU has topology extensions bit in CPUID. With this
bit, the kernel can get the cache information. So add support in
cpuid4_cache_lookup_regs() to get the correct cache size.

The Hygon Dhyana CPU also discovers num_cache_leaves via CPUID leaf
0x8000001d, so add support to it in find_num_cache_leaves().

Also add cacheinfo_hygon_init_llc_id() and init_hygon_cacheinfo()
functions to initialize Dhyana cache info. Setup cache cpumap in
the same way as AMD does.

Reviewed-by: Borislav Petkov <[email protected]>
Signed-off-by: Pu Wen <[email protected]>
---
arch/x86/include/asm/cacheinfo.h | 1 +
arch/x86/kernel/cpu/cacheinfo.c | 31 +++++++++++++++++++++++++++++--
arch/x86/kernel/cpu/cpu.h | 1 +
arch/x86/kernel/cpu/hygon.c | 3 +++
4 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/arch/x86/include/asm/cacheinfo.h b/arch/x86/include/asm/cacheinfo.h
index e958e28..86b63c7 100644
--- a/arch/x86/include/asm/cacheinfo.h
+++ b/arch/x86/include/asm/cacheinfo.h
@@ -3,5 +3,6 @@
#define _ASM_X86_CACHEINFO_H

void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, int cpu, u8 node_id);
+void cacheinfo_hygon_init_llc_id(struct cpuinfo_x86 *c, int cpu, u8 node_id);

#endif /* _ASM_X86_CACHEINFO_H */
diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinfo.c
index 0c5fcbd..dc1b934 100644
--- a/arch/x86/kernel/cpu/cacheinfo.c
+++ b/arch/x86/kernel/cpu/cacheinfo.c
@@ -602,6 +602,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);
}
@@ -625,7 +629,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;
@@ -678,6 +683,22 @@ void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, int cpu, u8 node_id)
}
}

+void cacheinfo_hygon_init_llc_id(struct cpuinfo_x86 *c, int cpu, u8 node_id)
+{
+ /*
+ * 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 (!cpuid_edx(0x80000006))
+ return;
+
+ /*
+ * LLC is at the core complex level.
+ * Core complex ID is ApicId[3] for these processors.
+ */
+ per_cpu(cpu_llc_id, cpu) = c->apicid >> 3;
+}
+
void init_amd_cacheinfo(struct cpuinfo_x86 *c)
{

@@ -691,6 +712,11 @@ void init_amd_cacheinfo(struct cpuinfo_x86 *c)
}
}

+void init_hygon_cacheinfo(struct cpuinfo_x86 *c)
+{
+ num_cache_leaves = find_num_cache_leaves(c);
+}
+
void init_intel_cacheinfo(struct cpuinfo_x86 *c)
{
/* Cache sizes */
@@ -913,7 +939,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;
}
diff --git a/arch/x86/kernel/cpu/cpu.h b/arch/x86/kernel/cpu/cpu.h
index 7b229af..da5446a 100644
--- a/arch/x86/kernel/cpu/cpu.h
+++ b/arch/x86/kernel/cpu/cpu.h
@@ -54,6 +54,7 @@ extern u32 get_scattered_cpuid_leaf(unsigned int level,
enum cpuid_regs_idx reg);
extern void init_intel_cacheinfo(struct cpuinfo_x86 *c);
extern void init_amd_cacheinfo(struct cpuinfo_x86 *c);
+extern void init_hygon_cacheinfo(struct cpuinfo_x86 *c);

extern void detect_num_cpu_cores(struct cpuinfo_x86 *c);
extern int detect_extended_topology_early(struct cpuinfo_x86 *c);
diff --git a/arch/x86/kernel/cpu/hygon.c b/arch/x86/kernel/cpu/hygon.c
index 9f5679e..ac70997 100644
--- a/arch/x86/kernel/cpu/hygon.c
+++ b/arch/x86/kernel/cpu/hygon.c
@@ -90,6 +90,7 @@ static void hygon_get_topology(struct cpuinfo_x86 *c)
if (!err)
c->x86_coreid_bits = get_count_order(c->x86_max_cores);

+ cacheinfo_hygon_init_llc_id(c, cpu, node_id);
} else if (cpu_has(c, X86_FEATURE_NODEID_MSR)) {
u64 value;

@@ -324,6 +325,8 @@ static void init_hygon(struct cpuinfo_x86 *c)
hygon_get_topology(c);
srat_detect_node(c);

+ init_hygon_cacheinfo(c);
+
if (cpu_has(c, X86_FEATURE_XMM2)) {
unsigned long long val;
int ret;
--
2.7.4


2018-09-10 13:20:32

by Wen Pu

[permalink] [raw]
Subject: [PATCH v6 03/16] x86/cpu/mtrr: Support TOP_MEM2 and get MTRR number

The Hygon Dhyana CPU have a special magic MSR way to force WB for
memory >4GB, and support TOP_MEM2. Therefore, it is necessary to
add Hygon Dhyana support in amd_special_default_mtrr().

The number of variable MTRRs for Hygon is 2 as AMD's.

Signed-off-by: Pu Wen <[email protected]>
---
arch/x86/kernel/cpu/mtrr/cleanup.c | 3 ++-
arch/x86/kernel/cpu/mtrr/mtrr.c | 2 +-
2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/cpu/mtrr/cleanup.c b/arch/x86/kernel/cpu/mtrr/cleanup.c
index 765afd5..3668c5d 100644
--- a/arch/x86/kernel/cpu/mtrr/cleanup.c
+++ b/arch/x86/kernel/cpu/mtrr/cleanup.c
@@ -831,7 +831,8 @@ int __init amd_special_default_mtrr(void)
{
u32 l, h;

- 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 0;
if (boot_cpu_data.x86 < 0xf)
return 0;
diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.c b/arch/x86/kernel/cpu/mtrr/mtrr.c
index 9a19c80..507039c 100644
--- a/arch/x86/kernel/cpu/mtrr/mtrr.c
+++ b/arch/x86/kernel/cpu/mtrr/mtrr.c
@@ -127,7 +127,7 @@ static void __init set_num_var_ranges(void)

if (use_intel())
rdmsr(MSR_MTRRcap, config, dummy);
- else if (is_cpu(AMD))
+ else if (is_cpu(AMD) || is_cpu(HYGON))
config = 2;
else if (is_cpu(CYRIX) || is_cpu(CENTAUR))
config = 8;
--
2.7.4


2018-09-10 13:20:38

by Wen Pu

[permalink] [raw]
Subject: [PATCH v6 01/16] x86/cpu: Create Hygon Dhyana architecture support file

Add x86 architecture support for new processor Hygon Dhyana Family
18h. Rework to create a separated file(arch/x86/kernel/cpu/hygon.c)
from the AMD one(arch/x86/kernel/cpu/amd.c) to initialize Dhyana.
In this way we can remove old AMD architecture support codes and
generate a clear initialization flow for Hygon Dhyana CPU. It also
reduce the long-term maintenance effort. Add Maintainer information
for hygon.c in accordance.

To identify Hygon Dhyana CPU, add a new vendor type X86_VENDOR_HYGON(9)
for system recognition.

To enable the config for Hygon Dhyana CPU, add a separated Kconfig
entry(CPU_SUP_HYGON) in kernel config setup. And select CPU_SUP_AMD
to solve the dependency issues in kernel.

Signed-off-by: Pu Wen <[email protected]>
---
MAINTAINERS | 6 +
arch/x86/Kconfig.cpu | 14 ++
arch/x86/include/asm/processor.h | 3 +-
arch/x86/kernel/cpu/Makefile | 1 +
arch/x86/kernel/cpu/hygon.c | 408 +++++++++++++++++++++++++++++++++++++++
5 files changed, 431 insertions(+), 1 deletion(-)
create mode 100644 arch/x86/kernel/cpu/hygon.c

diff --git a/MAINTAINERS b/MAINTAINERS
index d870cb5..e924b39 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6760,6 +6760,12 @@ S: Maintained
F: mm/memory-failure.c
F: mm/hwpoison-inject.c

+HYGON PROCESSOR SUPPORT
+M: Pu Wen <[email protected]>
+L: [email protected]
+S: Maintained
+F: arch/x86/kernel/cpu/hygon.c
+
Hyper-V CORE AND DRIVERS
M: "K. Y. Srinivasan" <[email protected]>
M: Haiyang Zhang <[email protected]>
diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu
index 638411f..6adce15 100644
--- a/arch/x86/Kconfig.cpu
+++ b/arch/x86/Kconfig.cpu
@@ -426,6 +426,20 @@ config CPU_SUP_AMD

If unsure, say N.

+config CPU_SUP_HYGON
+ default y
+ bool "Support Hygon processors" if PROCESSOR_SELECT
+ select CPU_SUP_AMD
+ help
+ This enables detection, tunings and quirks for Hygon processors
+
+ You need this enabled if you want your kernel to run on an
+ Hygon CPU. Disabling this option on other types of CPUs
+ makes the kernel a tiny bit smaller. Disabling it on an Hygon
+ CPU might render the kernel unbootable.
+
+ If unsure, say N.
+
config CPU_SUP_CENTAUR
default y
bool "Support Centaur processors" if PROCESSOR_SELECT
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index d53c54b..d4dfd02 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -155,7 +155,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

diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile
index 347137e..1f5d229 100644
--- a/arch/x86/kernel/cpu/Makefile
+++ b/arch/x86/kernel/cpu/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_X86_FEATURE_NAMES) += capflags.o powerflags.o

obj-$(CONFIG_CPU_SUP_INTEL) += intel.o intel_pconfig.o
obj-$(CONFIG_CPU_SUP_AMD) += amd.o
+obj-$(CONFIG_CPU_SUP_HYGON) += hygon.o
obj-$(CONFIG_CPU_SUP_CYRIX_32) += cyrix.o
obj-$(CONFIG_CPU_SUP_CENTAUR) += centaur.o
obj-$(CONFIG_CPU_SUP_TRANSMETA_32) += transmeta.o
diff --git a/arch/x86/kernel/cpu/hygon.c b/arch/x86/kernel/cpu/hygon.c
new file mode 100644
index 0000000..9f5679e
--- /dev/null
+++ b/arch/x86/kernel/cpu/hygon.c
@@ -0,0 +1,408 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Hygon Processor Support for Linux
+ *
+ * Copyright (C) 2018 Chengdu Haiguang IC Design Co., Ltd.
+ *
+ * Author: Pu Wen <[email protected]>
+ *
+ * This file is licensed under the terms of the GNU General
+ * License v2.0 or later. See file COPYING for details.
+ */
+#include <linux/io.h>
+
+#include <asm/cpu.h>
+#include <asm/smp.h>
+#include <asm/cacheinfo.h>
+#include <asm/spec-ctrl.h>
+#include <asm/delay.h>
+#ifdef CONFIG_X86_64
+# include <asm/set_memory.h>
+#endif
+
+#include "cpu.h"
+
+/*
+ * nodes_per_socket: Stores the number of nodes per socket.
+ * Refer to CPUID Fn8000_001E_ECX Node Identifiers[10:8]
+ */
+static u32 nodes_per_socket = 1;
+
+#ifdef CONFIG_NUMA
+/*
+ * To workaround broken NUMA config. Read the comment in
+ * srat_detect_node().
+ */
+static int nearby_node(int apicid)
+{
+ int i, node;
+
+ for (i = apicid - 1; i >= 0; i--) {
+ node = __apicid_to_node[i];
+ if (node != NUMA_NO_NODE && node_online(node))
+ return node;
+ }
+ for (i = apicid + 1; i < MAX_LOCAL_APIC; i++) {
+ node = __apicid_to_node[i];
+ if (node != NUMA_NO_NODE && node_online(node))
+ return node;
+ }
+ return first_node(node_online_map); /* Shouldn't happen */
+}
+#endif
+
+static void hygon_get_topology_early(struct cpuinfo_x86 *c)
+{
+ if (cpu_has(c, X86_FEATURE_TOPOEXT))
+ smp_num_siblings = ((cpuid_ebx(0x8000001e) >> 8) & 0xff) + 1;
+}
+
+/*
+ * Fixup core topology information for
+ * (1) Hygon multi-node processors
+ * Assumption: Number of cores in each internal node is the same.
+ * (2) Hygon processors supporting compute units
+ */
+static void hygon_get_topology(struct cpuinfo_x86 *c)
+{
+ u8 node_id;
+ int cpu = smp_processor_id();
+
+ /* get information required for multi-node processors */
+ if (boot_cpu_has(X86_FEATURE_TOPOEXT)) {
+ int err;
+ u32 eax, ebx, ecx, edx;
+
+ cpuid(0x8000001e, &eax, &ebx, &ecx, &edx);
+
+ node_id = ecx & 0xff;
+
+ c->cpu_core_id = ebx & 0xff;
+
+ if (smp_num_siblings > 1)
+ c->x86_max_cores /= smp_num_siblings;
+
+ /*
+ * In case leaf B is available, use it to derive
+ * topology information.
+ */
+ err = detect_extended_topology(c);
+ if (!err)
+ c->x86_coreid_bits = get_count_order(c->x86_max_cores);
+
+ } else if (cpu_has(c, X86_FEATURE_NODEID_MSR)) {
+ u64 value;
+
+ rdmsrl(MSR_FAM10H_NODE_ID, value);
+ node_id = value & 7;
+
+ per_cpu(cpu_llc_id, cpu) = node_id;
+ } else
+ return;
+
+ if (nodes_per_socket > 1)
+ set_cpu_cap(c, X86_FEATURE_AMD_DCM);
+}
+
+/*
+ * On Hygon setup the lower bits of the APIC id distinguish the cores.
+ * Assumes number of cores is a power of two.
+ */
+static void hygon_detect_cmp(struct cpuinfo_x86 *c)
+{
+ unsigned int bits;
+ int cpu = smp_processor_id();
+
+ bits = c->x86_coreid_bits;
+ /* Low order bits define the core id (index of core in socket) */
+ c->cpu_core_id = c->initial_apicid & ((1 << bits)-1);
+ /* Convert the initial APIC ID into the socket ID */
+ c->phys_proc_id = c->initial_apicid >> bits;
+ /* use socket ID also for last level cache */
+ per_cpu(cpu_llc_id, cpu) = c->phys_proc_id;
+}
+
+static void srat_detect_node(struct cpuinfo_x86 *c)
+{
+#ifdef CONFIG_NUMA
+ int cpu = smp_processor_id();
+ int node;
+ unsigned int apicid = c->apicid;
+
+ node = numa_cpu_node(cpu);
+ if (node == NUMA_NO_NODE)
+ node = per_cpu(cpu_llc_id, cpu);
+
+ /*
+ * On multi-fabric platform (e.g. Numascale NumaChip) a
+ * platform-specific handler needs to be called to fixup some
+ * IDs of the CPU.
+ */
+ if (x86_cpuinit.fixup_cpu_id)
+ x86_cpuinit.fixup_cpu_id(c, node);
+
+ if (!node_online(node)) {
+ /*
+ * Two possibilities here:
+ *
+ * - The CPU is missing memory and no node was created. In
+ * that case try picking one from a nearby CPU.
+ *
+ * - The APIC IDs differ from the HyperTransport node IDs.
+ * Assume they are all increased by a constant offset, but
+ * in the same order as the HT nodeids. If that doesn't
+ * result in a usable node fall back to the path for the
+ * previous case.
+ *
+ * This workaround operates directly on the mapping between
+ * APIC ID and NUMA node, assuming certain relationship
+ * between APIC ID, HT node ID and NUMA topology. As going
+ * through CPU mapping may alter the outcome, directly
+ * access __apicid_to_node[].
+ */
+ int ht_nodeid = c->initial_apicid;
+
+ if (__apicid_to_node[ht_nodeid] != NUMA_NO_NODE)
+ node = __apicid_to_node[ht_nodeid];
+ /* Pick a nearby node */
+ if (!node_online(node))
+ node = nearby_node(apicid);
+ }
+ numa_set_node(cpu, node);
+#endif
+}
+
+static void early_init_hygon_mc(struct cpuinfo_x86 *c)
+{
+#ifdef CONFIG_SMP
+ unsigned int bits, ecx;
+
+ /* Multi core CPU? */
+ if (c->extended_cpuid_level < 0x80000008)
+ return;
+
+ ecx = cpuid_ecx(0x80000008);
+
+ c->x86_max_cores = (ecx & 0xff) + 1;
+
+ /* CPU telling us the core id bits shift? */
+ bits = (ecx >> 12) & 0xF;
+
+ /* Otherwise recompute */
+ if (bits == 0) {
+ while ((1 << bits) < c->x86_max_cores)
+ bits++;
+ }
+
+ c->x86_coreid_bits = bits;
+#endif
+}
+
+static void bsp_init_hygon(struct cpuinfo_x86 *c)
+{
+#ifdef CONFIG_X86_64
+ unsigned long long tseg;
+
+ /*
+ * Split up direct mapping around the TSEG SMM area.
+ * Don't do it for gbpages because there seems very little
+ * benefit in doing so.
+ */
+ if (!rdmsrl_safe(MSR_K8_TSEG_ADDR, &tseg)) {
+ unsigned long pfn = tseg >> PAGE_SHIFT;
+
+ pr_debug("tseg: %010llx\n", tseg);
+ if (pfn_range_is_mapped(pfn, pfn + 1))
+ set_memory_4k((unsigned long)__va(tseg), 1);
+ }
+#endif
+
+ if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
+ u64 val;
+
+ rdmsrl(MSR_K7_HWCR, val);
+ if (!(val & BIT(24)))
+ pr_warn(FW_BUG "TSC doesn't count with P0 frequency!\n");
+ }
+
+ if (cpu_has(c, X86_FEATURE_MWAITX))
+ use_mwaitx_delay();
+
+ if (boot_cpu_has(X86_FEATURE_TOPOEXT)) {
+ u32 ecx;
+
+ ecx = cpuid_ecx(0x8000001e);
+ nodes_per_socket = ((ecx >> 8) & 7) + 1;
+ } else if (boot_cpu_has(X86_FEATURE_NODEID_MSR)) {
+ u64 value;
+
+ rdmsrl(MSR_FAM10H_NODE_ID, value);
+ nodes_per_socket = ((value >> 3) & 7) + 1;
+ }
+
+ if (!boot_cpu_has(X86_FEATURE_AMD_SSBD) &&
+ !boot_cpu_has(X86_FEATURE_VIRT_SSBD)) {
+ /*
+ * Try to cache the base value so further operations can
+ * avoid RMW. If that faults, do not enable SSBD.
+ */
+ if (!rdmsrl_safe(MSR_AMD64_LS_CFG, &x86_amd_ls_cfg_base)) {
+ setup_force_cpu_cap(X86_FEATURE_LS_CFG_SSBD);
+ setup_force_cpu_cap(X86_FEATURE_SSBD);
+ x86_amd_ls_cfg_ssbd_mask = 1ULL << 10;
+ }
+ }
+}
+
+static void early_init_hygon(struct cpuinfo_x86 *c)
+{
+ u32 dummy;
+
+ early_init_hygon_mc(c);
+
+ set_cpu_cap(c, X86_FEATURE_K8);
+
+ rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy);
+
+ /*
+ * c->x86_power is 8000_0007 edx. Bit 8 is TSC runs at constant rate
+ * with P/T states and does not stop in deep C-states
+ */
+ if (c->x86_power & (1 << 8)) {
+ set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
+ set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC);
+ }
+
+ /* Bit 12 of 8000_0007 edx is accumulated power mechanism. */
+ if (c->x86_power & BIT(12))
+ set_cpu_cap(c, X86_FEATURE_ACC_POWER);
+
+#ifdef CONFIG_X86_64
+ set_cpu_cap(c, X86_FEATURE_SYSCALL32);
+#endif
+
+#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_PCI)
+ /*
+ * ApicID can always be treated as an 8-bit value for Hygon APIC So, we
+ * can safely set X86_FEATURE_EXTD_APICID unconditionally.
+ */
+ if (boot_cpu_has(X86_FEATURE_APIC))
+ set_cpu_cap(c, X86_FEATURE_EXTD_APICID);
+#endif
+
+ /*
+ * This is only needed to tell the kernel whether to use VMCALL
+ * and VMMCALL. VMMCALL is never executed except under virt, so
+ * we can set it unconditionally.
+ */
+ set_cpu_cap(c, X86_FEATURE_VMMCALL);
+
+ hygon_get_topology_early(c);
+}
+
+static void init_hygon(struct cpuinfo_x86 *c)
+{
+ early_init_hygon(c);
+
+ /*
+ * Bit 31 in normal CPUID used for nonstandard 3DNow ID;
+ * 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway
+ */
+ clear_cpu_cap(c, 0*32+31);
+
+ set_cpu_cap(c, X86_FEATURE_REP_GOOD);
+
+ /* get apicid instead of initial apic id from cpuid */
+ c->apicid = hard_smp_processor_id();
+
+ set_cpu_cap(c, X86_FEATURE_ZEN);
+ set_cpu_cap(c, X86_FEATURE_CPB);
+
+ cpu_detect_cache_sizes(c);
+
+ hygon_detect_cmp(c);
+ hygon_get_topology(c);
+ srat_detect_node(c);
+
+ if (cpu_has(c, X86_FEATURE_XMM2)) {
+ unsigned long long val;
+ int ret;
+
+ /*
+ * A serializing LFENCE has less overhead than MFENCE, so
+ * use it for execution serialization. On families which
+ * don't have that MSR, LFENCE is already serializing.
+ * msr_set_bit() uses the safe accessors, too, even if the MSR
+ * is not present.
+ */
+ msr_set_bit(MSR_F10H_DECFG,
+ MSR_F10H_DECFG_LFENCE_SERIALIZE_BIT);
+
+ /*
+ * Verify that the MSR write was successful (could be running
+ * under a hypervisor) and only then assume that LFENCE is
+ * serializing.
+ */
+ ret = rdmsrl_safe(MSR_F10H_DECFG, &val);
+ if (!ret && (val & MSR_F10H_DECFG_LFENCE_SERIALIZE)) {
+ /* A serializing LFENCE stops RDTSC speculation */
+ set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC);
+ } else {
+ /* MFENCE stops RDTSC speculation */
+ set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC);
+ }
+ }
+
+ /*
+ * Hygon processors have APIC timer running in deep C states.
+ */
+ set_cpu_cap(c, X86_FEATURE_ARAT);
+
+ /* Hygon CPUs don't reset SS attributes on SYSRET, Xen does. */
+ if (!cpu_has(c, X86_FEATURE_XENPV))
+ set_cpu_bug(c, X86_BUG_SYSRET_SS_ATTRS);
+}
+
+static void cpu_detect_tlb_hygon(struct cpuinfo_x86 *c)
+{
+ u32 ebx, eax, ecx, edx;
+ u16 mask = 0xfff;
+
+ if (c->extended_cpuid_level < 0x80000006)
+ return;
+
+ cpuid(0x80000006, &eax, &ebx, &ecx, &edx);
+
+ tlb_lld_4k[ENTRIES] = (ebx >> 16) & mask;
+ tlb_lli_4k[ENTRIES] = ebx & mask;
+
+ /* Handle DTLB 2M and 4M sizes, fall back to L1 if L2 is disabled */
+ if (!((eax >> 16) & mask))
+ tlb_lld_2m[ENTRIES] = (cpuid_eax(0x80000005) >> 16) & 0xff;
+ else
+ tlb_lld_2m[ENTRIES] = (eax >> 16) & mask;
+
+ /* a 4M entry uses two 2M entries */
+ tlb_lld_4m[ENTRIES] = tlb_lld_2m[ENTRIES] >> 1;
+
+ /* Handle ITLB 2M and 4M sizes, fall back to L1 if L2 is disabled */
+ if (!(eax & mask)) {
+ cpuid(0x80000005, &eax, &ebx, &ecx, &edx);
+ tlb_lli_2m[ENTRIES] = eax & 0xff;
+ } else
+ tlb_lli_2m[ENTRIES] = eax & mask;
+
+ 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_hygon,
+ .c_detect_tlb = cpu_detect_tlb_hygon,
+ .c_bsp_init = bsp_init_hygon,
+ .c_init = init_hygon,
+ .c_x86_vendor = X86_VENDOR_HYGON,
+};
+
+cpu_dev_register(hygon_cpu_dev);
--
2.7.4


2018-09-10 13:21:41

by Wen Pu

[permalink] [raw]
Subject: [PATCH v6 11/16] x86/kvm: Add Hygon Dhyana support to KVM infrastructure

The Hygon Dhyana CPU has the SVM feature as AMD family 17h does.
So enable the KVM infrastructure support to it.

Reviewed-by: Borislav Petkov <[email protected]>
Signed-off-by: Pu Wen <[email protected]>
---
arch/x86/include/asm/kvm_emulate.h | 4 ++++
arch/x86/include/asm/virtext.h | 5 +++--
arch/x86/kvm/emulate.c | 11 ++++++++++-
3 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h
index 0f82cd9..93c4bf5 100644
--- a/arch/x86/include/asm/kvm_emulate.h
+++ b/arch/x86/include/asm/kvm_emulate.h
@@ -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
diff --git a/arch/x86/include/asm/virtext.h b/arch/x86/include/asm/virtext.h
index 0116b2e..e05e0d3 100644
--- a/arch/x86/include/asm/virtext.h
+++ b/arch/x86/include/asm/virtext.h
@@ -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;
}

diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 106482d..34edf19 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -2711,7 +2711,16 @@ static bool em_syscall_is_enabled(struct x86_emulate_ctxt *ctxt)
edx == X86EMUL_CPUID_VENDOR_AMDisbetterI_edx)
return true;

- /* default: (not Intel, not AMD), apply Intel's stricter rules... */
+ /* Hygon ("HygonGenuine") */
+ if (ebx == X86EMUL_CPUID_VENDOR_HygonGenuine_ebx &&
+ ecx == X86EMUL_CPUID_VENDOR_HygonGenuine_ecx &&
+ edx == X86EMUL_CPUID_VENDOR_HygonGenuine_edx)
+ return true;
+
+ /*
+ * default: (not Intel, not AMD, not Hygon), apply Intel's
+ * stricter rules...
+ */
return false;
}

--
2.7.4


2018-09-10 13:21:50

by Wen Pu

[permalink] [raw]
Subject: [PATCH v6 05/16] perf/x86: Add Hygon Dhyana support to PMU infrastructure

The PMU architecture for Hygon Dhyana CPU is similar to the AMD Family
17h one. To support Hygon Dhyana PMU, call amd_pmu_init() to share
AMD PMU initialization flow, and change the PMU name to "HYGON".

The Hygon Dhyana CPU support both legacy and extension PMC MSRs(perf
counter registers and event selection registers), so add Hygon Dhyana
support to get bit offset in the similar way as AMD does.

Signed-off-by: Pu Wen <[email protected]>
---
arch/x86/events/amd/core.c | 4 ++++
arch/x86/events/amd/uncore.c | 20 +++++++++++++-------
arch/x86/events/core.c | 4 ++++
arch/x86/kernel/cpu/perfctr-watchdog.c | 2 ++
4 files changed, 23 insertions(+), 7 deletions(-)

diff --git a/arch/x86/events/amd/core.c b/arch/x86/events/amd/core.c
index c84584b..7d2d7c8 100644
--- a/arch/x86/events/amd/core.c
+++ b/arch/x86/events/amd/core.c
@@ -669,6 +669,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;
diff --git a/arch/x86/events/amd/uncore.c b/arch/x86/events/amd/uncore.c
index 981ba5e..c7d745b 100644
--- a/arch/x86/events/amd/uncore.c
+++ b/arch/x86/events/amd/uncore.c
@@ -507,17 +507,19 @@ 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
- * Fabric counters. Also, L3 counters are supported too. The PMUs
- * are exported based on family as either L2 or L3 and NB or DF.
+ * For F17h or 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.
*/
num_counters_nb = NUM_COUNTERS_NB;
num_counters_llc = NUM_COUNTERS_L3;
@@ -547,7 +549,9 @@ 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;
}

@@ -561,7 +565,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;
}

diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
index dfb2f7c..9c562f5 100644
--- a/arch/x86/events/core.c
+++ b/arch/x86/events/core.c
@@ -1776,6 +1776,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;
}
diff --git a/arch/x86/kernel/cpu/perfctr-watchdog.c b/arch/x86/kernel/cpu/perfctr-watchdog.c
index d389083..9556930 100644
--- a/arch/x86/kernel/cpu/perfctr-watchdog.c
+++ b/arch/x86/kernel/cpu/perfctr-watchdog.c
@@ -46,6 +46,7 @@ static inline unsigned int nmi_perfctr_msr_to_bit(unsigned int msr)
{
/* returns the bit offset of the performance counter register */
switch (boot_cpu_data.x86_vendor) {
+ case X86_VENDOR_HYGON:
case X86_VENDOR_AMD:
if (msr >= MSR_F15H_PERF_CTR)
return (msr - MSR_F15H_PERF_CTR) >> 1;
@@ -74,6 +75,7 @@ static inline unsigned int nmi_evntsel_msr_to_bit(unsigned int msr)
{
/* returns the bit offset of the event selection register */
switch (boot_cpu_data.x86_vendor) {
+ case X86_VENDOR_HYGON:
case X86_VENDOR_AMD:
if (msr >= MSR_F15H_PERF_CTL)
return (msr - MSR_F15H_PERF_CTL) >> 1;
--
2.7.4


2018-09-10 13:21:59

by Wen Pu

[permalink] [raw]
Subject: [PATCH v6 06/16] x86/alternative: Init ideal_nops for Hygon Dhyana

The ideal_nops for Hygon Dhyana CPU should be p6_nops.

Reviewed-by: Borislav Petkov <[email protected]>
Signed-off-by: Pu Wen <[email protected]>
---
arch/x86/kernel/alternative.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index b9d5e7c..184e9a0 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -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;
--
2.7.4


2018-09-10 13:21:59

by Wen Pu

[permalink] [raw]
Subject: [PATCH v6 04/16] x86/smpboot: SMP init nodelay and not flush caches before sleep

The Hygon Dhyana CPU use no delay in smp_quirk_init_udelay(),
and return in mwait_play_dead() as AMD does.

Reviewed-by: Borislav Petkov <[email protected]>
Signed-off-by: Pu Wen <[email protected]>
---
arch/x86/kernel/smpboot.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index f02ecaf..5369d7f 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -676,6 +676,7 @@ static void __init smp_quirk_init_udelay(void)

/* if modern processor, use no delay */
if (((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && (boot_cpu_data.x86 == 6)) ||
+ ((boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) && (boot_cpu_data.x86 >= 0x18)) ||
((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) && (boot_cpu_data.x86 >= 0xF))) {
init_udelay = 0;
return;
@@ -1592,7 +1593,8 @@ static inline void mwait_play_dead(void)
void *mwait_ptr;
int i;

- 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;
if (!this_cpu_has(X86_FEATURE_MWAIT))
return;
--
2.7.4


2018-09-10 13:22:15

by Wen Pu

[permalink] [raw]
Subject: [PATCH v6 07/16] x86/pci: Add Hygon Dhyana support to PCI and north bridge

As Hygon registered its PCI Vendor ID as a new one 0x1d94, and there
are PCI Devices 0x1450/0x1463/0x1464 for Host bridge on Hygon Dhyana
platforms, so add Hygon Dhyana support to the PCI and north bridge
subsystem by using the code path of AMD family 17h.

Acked-by: Bjorn Helgaas <[email protected]> # pci_ids.h
Signed-off-by: Pu Wen <[email protected]>
---
arch/x86/kernel/amd_nb.c | 47 +++++++++++++++++++++++++++++++++++++++++------
arch/x86/pci/amd_bus.c | 6 ++++--
include/linux/pci_ids.h | 2 ++
3 files changed, 47 insertions(+), 8 deletions(-)

diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c
index b481b95..3e2ea18 100644
--- a/arch/x86/kernel/amd_nb.c
+++ b/arch/x86/kernel/amd_nb.c
@@ -61,6 +61,21 @@ static const struct pci_device_id amd_nb_link_ids[] = {
{}
};

+static const struct pci_device_id hygon_root_ids[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_AMD_17H_ROOT) },
+ {}
+};
+
+const struct pci_device_id hygon_nb_misc_ids[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_AMD_17H_DF_F3) },
+ {}
+};
+
+static const struct pci_device_id hygon_nb_link_ids[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_AMD_17H_DF_F4) },
+ {}
+};
+
const struct amd_nb_bus_dev_range amd_nb_bus_dev_ranges[] __initconst = {
{ 0x00, 0x18, 0x20 },
{ 0xff, 0x00, 0x20 },
@@ -197,12 +212,25 @@ int amd_cache_northbridges(void)
u16 i = 0;
struct amd_northbridge *nb;
struct pci_dev *root, *misc, *link;
+ const struct pci_device_id *root_ids = NULL;
+ const struct pci_device_id *misc_ids = NULL;
+ const struct pci_device_id *link_ids = NULL;
+
+ if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
+ root_ids = amd_root_ids;
+ misc_ids = amd_nb_misc_ids;
+ link_ids = amd_nb_link_ids;
+ } else if (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) {
+ root_ids = hygon_root_ids;
+ misc_ids = hygon_nb_misc_ids;
+ link_ids = hygon_nb_link_ids;
+ }

if (amd_northbridges.num)
return 0;

misc = NULL;
- while ((misc = next_northbridge(misc, amd_nb_misc_ids)) != NULL)
+ while ((misc = next_northbridge(misc, misc_ids)) != NULL)
i++;

if (!i)
@@ -218,11 +246,11 @@ int amd_cache_northbridges(void)
link = misc = root = NULL;
for (i = 0; i != amd_northbridges.num; i++) {
node_to_amd_nb(i)->root = root =
- next_northbridge(root, amd_root_ids);
+ next_northbridge(root, root_ids);
node_to_amd_nb(i)->misc = misc =
- next_northbridge(misc, amd_nb_misc_ids);
+ next_northbridge(misc, misc_ids);
node_to_amd_nb(i)->link = link =
- next_northbridge(link, amd_nb_link_ids);
+ next_northbridge(link, link_ids);
}

if (amd_gart_present())
@@ -263,9 +291,15 @@ bool __init early_is_amd_nb(u32 device)
{
const struct pci_device_id *id;
u32 vendor = device & 0xffff;
+ const struct pci_device_id *misc_ids = NULL;
+
+ if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
+ misc_ids = amd_nb_misc_ids;
+ else if (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON)
+ misc_ids = hygon_nb_misc_ids;

device >>= 16;
- for (id = amd_nb_misc_ids; id->vendor; id++)
+ for (id = misc_ids; id->vendor; id++)
if (vendor == id->vendor && device == id->device)
return true;
return false;
@@ -277,7 +311,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 */
diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c
index 649bdde..bfa50e6 100644
--- a/arch/x86/pci/amd_bus.c
+++ b/arch/x86/pci/amd_bus.c
@@ -93,7 +93,8 @@ static int __init early_root_info_init(void)
vendor = id & 0xffff;
device = (id>>16) & 0xffff;

- if (vendor != PCI_VENDOR_ID_AMD)
+ if (vendor != PCI_VENDOR_ID_AMD &&
+ vendor != PCI_VENDOR_ID_HYGON)
continue;

if (hb_probes[i].device == device) {
@@ -390,7 +391,8 @@ static int __init pci_io_ecs_init(void)

static int __init amd_postcore_init(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)
return 0;

early_root_info_init();
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index d157983..8a0841c 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -2561,6 +2561,8 @@

#define PCI_VENDOR_ID_AMAZON 0x1d0f

+#define PCI_VENDOR_ID_HYGON 0x1d94
+
#define PCI_VENDOR_ID_TEKRAM 0x1de1
#define PCI_DEVICE_ID_TEKRAM_DC290 0xdc29

--
2.7.4


2018-09-10 13:22:36

by Wen Pu

[permalink] [raw]
Subject: [PATCH v6 08/16] x86/apic: Add Hygon Dhyana support to APIC

Add Hygon Dhyana support to the APIC subsystem as it use modern APIC.
When running on 32 bit mode, bigsmp should be enabled if there are
more than 8 cores online.

Signed-off-by: Pu Wen <[email protected]>
---
arch/x86/kernel/apic/apic.c | 13 +++++++++++--
arch/x86/kernel/apic/probe_32.c | 1 +
2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 84132ed..709daf2 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -224,6 +224,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;
}

@@ -1211,9 +1216,11 @@ void __init sync_Arb_IDs(void)
{
/*
* Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1 And not
- * needed on AMD.
+ * needed on AMD or Hygon.
*/
- if (modern_apic() || boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
+ if (modern_apic() ||
+ boot_cpu_data.x86_vendor == X86_VENDOR_AMD ||
+ boot_cpu_data.x86_vendor == X86_VENDOR_HYGON)
return;

/*
@@ -1912,6 +1919,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)))
diff --git a/arch/x86/kernel/apic/probe_32.c b/arch/x86/kernel/apic/probe_32.c
index 02e8acb..47ff297 100644
--- a/arch/x86/kernel/apic/probe_32.c
+++ b/arch/x86/kernel/apic/probe_32.c
@@ -185,6 +185,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;
}
--
2.7.4


2018-09-10 13:22:55

by Wen Pu

[permalink] [raw]
Subject: [PATCH v6 12/16] x86/xen: Add Hygon Dhyana support to Xen

To make Xen works functionally on Hygon platforms, reuse AMD's Xen
support code path for Hygon Dhyana CPU.

There are six core performance events counters per thread, so there are
six MSRs for these counters(0-5). Also there are four legacy PMC MSRs,
they are alias of the counters(0-3).

In this version of kernel Hygon use the lagacy and safe versions of MSR
access. It works fine when VPMU enabled in Xen on Hygon platforms by
testing with perf.

Reviewed-by: Boris Ostrovsky <[email protected]>
Signed-off-by: Pu Wen <[email protected]>
---
arch/x86/xen/pmu.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/arch/x86/xen/pmu.c b/arch/x86/xen/pmu.c
index 7d00d4a..9403854 100644
--- a/arch/x86/xen/pmu.c
+++ b/arch/x86/xen/pmu.c
@@ -90,6 +90,12 @@ static void xen_pmu_arch_init(void)
k7_counters_mirrored = 0;
break;
}
+ } else if (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) {
+ amd_num_counters = F10H_NUM_COUNTERS;
+ amd_counters_base = MSR_K7_PERFCTR0;
+ amd_ctrls_base = MSR_K7_EVNTSEL0;
+ amd_msr_step = 1;
+ k7_counters_mirrored = 0;
} else {
uint32_t eax, ebx, ecx, edx;

@@ -285,7 +291,7 @@ static bool xen_amd_pmu_emulate(unsigned int msr, u64 *val, bool is_read)

bool pmu_msr_read(unsigned int msr, uint64_t *val, int *err)
{
- if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
+ if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) {
if (is_amd_pmu_msr(msr)) {
if (!xen_amd_pmu_emulate(msr, val, 1))
*val = native_read_msr_safe(msr, err);
@@ -308,7 +314,7 @@ bool pmu_msr_write(unsigned int msr, uint32_t low, uint32_t high, int *err)
{
uint64_t val = ((uint64_t)high << 32) | low;

- if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
+ if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) {
if (is_amd_pmu_msr(msr)) {
if (!xen_amd_pmu_emulate(msr, &val, 0))
*err = native_write_msr_safe(msr, low, high);
@@ -379,7 +385,7 @@ static unsigned long long xen_intel_read_pmc(int counter)

unsigned long long xen_read_pmc(int counter)
{
- if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
+ if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
return xen_amd_read_pmc(counter);
else
return xen_intel_read_pmc(counter);
--
2.7.4


2018-09-10 13:23:40

by Wen Pu

[permalink] [raw]
Subject: [PATCH v6 16/16] cpupower, x86: Add Hygon Dhyana support

Tool cpupower is useful to get CPU frequency information and monitor
power stats on Hygon Dhyana platforms. So add Hygon Dhyana support to
it by checking vendor and family to share the code path of AMD family
17h.

Signed-off-by: Pu Wen <[email protected]>
---
tools/power/cpupower/utils/cpufreq-info.c | 6 ++++--
tools/power/cpupower/utils/helpers/amd.c | 4 ++--
tools/power/cpupower/utils/helpers/cpuid.c | 8 +++++---
tools/power/cpupower/utils/helpers/helpers.h | 2 +-
tools/power/cpupower/utils/helpers/misc.c | 2 +-
tools/power/cpupower/utils/idle_monitor/mperf_monitor.c | 3 ++-
6 files changed, 15 insertions(+), 10 deletions(-)

diff --git a/tools/power/cpupower/utils/cpufreq-info.c b/tools/power/cpupower/utils/cpufreq-info.c
index df43cd4..56e54ea 100644
--- a/tools/power/cpupower/utils/cpufreq-info.c
+++ b/tools/power/cpupower/utils/cpufreq-info.c
@@ -170,6 +170,7 @@ static int get_boost_mode(unsigned int cpu)
unsigned long pstates[MAX_HW_PSTATES] = {0,};

if (cpupower_cpu_info.vendor != X86_VENDOR_AMD &&
+ cpupower_cpu_info.vendor != X86_VENDOR_HYGON &&
cpupower_cpu_info.vendor != X86_VENDOR_INTEL)
return 0;

@@ -190,8 +191,9 @@ static int get_boost_mode(unsigned int cpu)
printf(_(" Supported: %s\n"), support ? _("yes") : _("no"));
printf(_(" Active: %s\n"), active ? _("yes") : _("no"));

- if (cpupower_cpu_info.vendor == X86_VENDOR_AMD &&
- cpupower_cpu_info.family >= 0x10) {
+ if ((cpupower_cpu_info.vendor == X86_VENDOR_AMD &&
+ cpupower_cpu_info.family >= 0x10) ||
+ cpupower_cpu_info.vendor == X86_VENDOR_HYGON) {
ret = decode_pstates(cpu, cpupower_cpu_info.family, b_states,
pstates, &pstate_no);
if (ret)
diff --git a/tools/power/cpupower/utils/helpers/amd.c b/tools/power/cpupower/utils/helpers/amd.c
index bb41cdd..65beaee 100644
--- a/tools/power/cpupower/utils/helpers/amd.c
+++ b/tools/power/cpupower/utils/helpers/amd.c
@@ -45,7 +45,7 @@ static int get_did(int family, union msr_pstate pstate)

if (family == 0x12)
t = pstate.val & 0xf;
- else if (family == 0x17)
+ else if (family == 0x17 || family == 0x18)
t = pstate.fam17h_bits.did;
else
t = pstate.bits.did;
@@ -59,7 +59,7 @@ static int get_cof(int family, union msr_pstate pstate)
int fid, did, cof;

did = get_did(family, pstate);
- if (family == 0x17) {
+ if (family == 0x17 || family == 0x18) {
fid = pstate.fam17h_bits.fid;
cof = 200 * fid / did;
} else {
diff --git a/tools/power/cpupower/utils/helpers/cpuid.c b/tools/power/cpupower/utils/helpers/cpuid.c
index 732b0b4..5cc39d4 100644
--- a/tools/power/cpupower/utils/helpers/cpuid.c
+++ b/tools/power/cpupower/utils/helpers/cpuid.c
@@ -8,7 +8,7 @@
#include "helpers/helpers.h"

static const char *cpu_vendor_table[X86_VENDOR_MAX] = {
- "Unknown", "GenuineIntel", "AuthenticAMD",
+ "Unknown", "GenuineIntel", "AuthenticAMD", "HygonGenuine",
};

#if defined(__i386__) || defined(__x86_64__)
@@ -109,6 +109,7 @@ int get_cpu_info(struct cpupower_cpu_info *cpu_info)
fclose(fp);
/* Get some useful CPU capabilities from cpuid */
if (cpu_info->vendor != X86_VENDOR_AMD &&
+ cpu_info->vendor != X86_VENDOR_HYGON &&
cpu_info->vendor != X86_VENDOR_INTEL)
return ret;

@@ -124,8 +125,9 @@ int get_cpu_info(struct cpupower_cpu_info *cpu_info)
if (cpuid_level >= 6 && (cpuid_ecx(6) & 0x1))
cpu_info->caps |= CPUPOWER_CAP_APERF;

- /* AMD Boost state enable/disable register */
- if (cpu_info->vendor == X86_VENDOR_AMD) {
+ /* AMD or Hygon Boost state enable/disable register */
+ if (cpu_info->vendor == X86_VENDOR_AMD ||
+ cpu_info->vendor == X86_VENDOR_HYGON) {
if (ext_cpuid_level >= 0x80000007 &&
(cpuid_edx(0x80000007) & (1 << 9)))
cpu_info->caps |= CPUPOWER_CAP_AMD_CBP;
diff --git a/tools/power/cpupower/utils/helpers/helpers.h b/tools/power/cpupower/utils/helpers/helpers.h
index 41da392..9021396 100644
--- a/tools/power/cpupower/utils/helpers/helpers.h
+++ b/tools/power/cpupower/utils/helpers/helpers.h
@@ -61,7 +61,7 @@ extern int be_verbose;

/* cpuid and cpuinfo helpers **************************/
enum cpupower_cpu_vendor {X86_VENDOR_UNKNOWN = 0, X86_VENDOR_INTEL,
- X86_VENDOR_AMD, X86_VENDOR_MAX};
+ X86_VENDOR_AMD, X86_VENDOR_HYGON, X86_VENDOR_MAX};

#define CPUPOWER_CAP_INV_TSC 0x00000001
#define CPUPOWER_CAP_APERF 0x00000002
diff --git a/tools/power/cpupower/utils/helpers/misc.c b/tools/power/cpupower/utils/helpers/misc.c
index 80fdf55..f406adc 100644
--- a/tools/power/cpupower/utils/helpers/misc.c
+++ b/tools/power/cpupower/utils/helpers/misc.c
@@ -26,7 +26,7 @@ int cpufreq_has_boost_support(unsigned int cpu, int *support, int *active,
* has Hardware determined variable increments instead.
*/

- if (cpu_info.family == 0x17) {
+ if (cpu_info.family == 0x17 || cpu_info.family == 0x18) {
if (!read_msr(cpu, MSR_AMD_HWCR, &val)) {
if (!(val & CPUPOWER_AMD_CPBDIS))
*active = 1;
diff --git a/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c b/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c
index d7c2a6d..f2a7e9c 100644
--- a/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c
+++ b/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c
@@ -241,7 +241,8 @@ static int init_maxfreq_mode(void)
if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_INV_TSC))
goto use_sysfs;

- if (cpupower_cpu_info.vendor == X86_VENDOR_AMD) {
+ if (cpupower_cpu_info.vendor == X86_VENDOR_AMD ||
+ cpupower_cpu_info.vendor == X86_VENDOR_HYGON) {
/* MSR_AMD_HWCR tells us whether TSC runs at P0/mperf
* freq.
* A test whether hwcr is accessable/available would be:
--
2.7.4


2018-09-10 13:23:47

by Wen Pu

[permalink] [raw]
Subject: [PATCH v6 10/16] x86/mce: Add Hygon Dhyana support to MCE infrastructure

The machine check architecture for Hygon Dhyana CPU is similar to the
AMD family 17h one. To make MCE working on Hygon platforms, add vendor
checking for Hygon Dhyana to share the code path of AMD family 17h.

Signed-off-by: Pu Wen <[email protected]>
---
arch/x86/include/asm/mce.h | 2 ++
arch/x86/kernel/cpu/mcheck/mce-severity.c | 3 ++-
arch/x86/kernel/cpu/mcheck/mce.c | 20 +++++++++++++++-----
3 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index 3a17107..550f2c9 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -214,6 +214,8 @@ static inline void mce_amd_feature_init(struct cpuinfo_x86 *c) { }
static inline int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr) { return -EINVAL; };
#endif

+static inline void mce_hygon_feature_init(struct cpuinfo_x86 *c) { return mce_amd_feature_init(c); }
+
int mce_available(struct cpuinfo_x86 *c);
bool mce_is_memory_error(struct mce *m);

diff --git a/arch/x86/kernel/cpu/mcheck/mce-severity.c b/arch/x86/kernel/cpu/mcheck/mce-severity.c
index f34d89c..44396d5 100644
--- a/arch/x86/kernel/cpu/mcheck/mce-severity.c
+++ b/arch/x86/kernel/cpu/mcheck/mce-severity.c
@@ -336,7 +336,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;
}

diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 953b3ce..909f1d7 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -270,7 +270,7 @@ static void print_mce(struct mce *m)
{
__print_mce(m);

- if (m->cpuvendor != X86_VENDOR_AMD)
+ if (m->cpuvendor != X86_VENDOR_AMD && m->cpuvendor != X86_VENDOR_HYGON)
pr_emerg_ratelimited(HW_ERR "Run the above through 'mcelog --ascii'\n");
}

@@ -508,9 +508,9 @@ static int mce_usable_address(struct mce *m)

bool mce_is_memory_error(struct mce *m)
{
- if (m->cpuvendor == X86_VENDOR_AMD) {
+ if (m->cpuvendor == X86_VENDOR_AMD ||
+ m->cpuvendor == X86_VENDOR_HYGON) {
return amd_mce_is_memory_error(m);
-
} else if (m->cpuvendor == X86_VENDOR_INTEL) {
/*
* Intel SDM Volume 3B - 15.9.2 Compound Error Codes
@@ -539,6 +539,9 @@ static bool mce_is_correctable(struct mce *m)
if (m->cpuvendor == X86_VENDOR_AMD && m->status & MCI_STATUS_DEFERRED)
return false;

+ if (m->cpuvendor == X86_VENDOR_HYGON && m->status & MCI_STATUS_DEFERRED)
+ return false;
+
if (m->status & MCI_STATUS_UC)
return false;

@@ -1705,7 +1708,7 @@ static int __mcheck_cpu_ancient_init(struct cpuinfo_x86 *c)
*/
static void __mcheck_cpu_init_early(struct cpuinfo_x86 *c)
{
- if (c->x86_vendor == X86_VENDOR_AMD) {
+ if (c->x86_vendor == X86_VENDOR_AMD || c->x86_vendor == X86_VENDOR_HYGON) {
mce_flags.overflow_recov = !!cpu_has(c, X86_FEATURE_OVERFLOW_RECOV);
mce_flags.succor = !!cpu_has(c, X86_FEATURE_SUCCOR);
mce_flags.smca = !!cpu_has(c, X86_FEATURE_SMCA);
@@ -1746,6 +1749,11 @@ static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c)
mce_amd_feature_init(c);
break;
}
+
+ case X86_VENDOR_HYGON:
+ mce_hygon_feature_init(c);
+ break;
+
case X86_VENDOR_CENTAUR:
mce_centaur_feature_init(c);
break;
@@ -1971,12 +1979,14 @@ static void mce_disable_error_reporting(void)
static void vendor_disable_error_reporting(void)
{
/*
- * Don't clear on Intel or AMD CPUs. Some of these MSRs are socket-wide.
+ * Don't clear on Intel or AMD or Hygon CPUs. Some of these MSRs
+ * are socket-wide.
* Disabling them for just a single offlined CPU is bad, since it will
* inhibit reporting for all shared resources on the socket like the
* last level cache (LLC), the integrated memory controller (iMC), etc.
*/
if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL ||
+ boot_cpu_data.x86_vendor == X86_VENDOR_HYGON ||
boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
return;

--
2.7.4


2018-09-10 13:23:56

by Wen Pu

[permalink] [raw]
Subject: [PATCH v6 15/16] EDAC, amd64: Add Hygon Dhyana support

To make AMD64 EDAC and MCE drivers working on Hygon platforms, add
support for Hygon Dhyana CPU by using the code path of AMD family
17h.

Signed-off-by: Pu Wen <[email protected]>
---
drivers/edac/amd64_edac.c | 8 +++++++-
drivers/edac/mce_amd.c | 4 +++-
2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index 18aeabb..bf3314b 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -211,7 +211,7 @@ static int __set_scrub_rate(struct amd64_pvt *pvt, u32 new_bw, u32 min_rate)

scrubval = scrubrates[i].scrubval;

- if (pvt->fam == 0x17) {
+ if (pvt->fam == 0x17 || pvt->fam == 0x18) {
__f17h_set_scrubval(pvt, scrubval);
} else if (pvt->fam == 0x15 && pvt->model == 0x60) {
f15h_select_dct(pvt, 0);
@@ -264,6 +264,7 @@ static int get_scrub_rate(struct mem_ctl_info *mci)
break;

case 0x17:
+ case 0x18:
amd64_read_pci_cfg(pvt->F6, F17H_SCR_BASE_ADDR, &scrubval);
if (scrubval & BIT(0)) {
amd64_read_pci_cfg(pvt->F6, F17H_SCR_LIMIT_ADDR, &scrubval);
@@ -1044,6 +1045,7 @@ static void determine_memory_type(struct amd64_pvt *pvt)
goto ddr3;

case 0x17:
+ case 0x18:
if ((pvt->umc[0].dimm_cfg | pvt->umc[1].dimm_cfg) & BIT(5))
pvt->dram_type = MEM_LRDDR4;
else if ((pvt->umc[0].dimm_cfg | pvt->umc[1].dimm_cfg) & BIT(4))
@@ -3188,8 +3190,11 @@ static struct amd64_family_type *per_family_init(struct amd64_pvt *pvt)
break;

case 0x17:
+ case 0x18:
fam_type = &family_types[F17_CPUS];
pvt->ops = &family_types[F17_CPUS].ops;
+ if (pvt->fam == 0x18)
+ family_types[F17_CPUS].ctl_name = "F18h";
break;

default:
@@ -3428,6 +3433,7 @@ static const struct x86_cpu_id amd64_cpuids[] = {
{ X86_VENDOR_AMD, 0x15, X86_MODEL_ANY, X86_FEATURE_ANY, 0 },
{ X86_VENDOR_AMD, 0x16, X86_MODEL_ANY, X86_FEATURE_ANY, 0 },
{ X86_VENDOR_AMD, 0x17, X86_MODEL_ANY, X86_FEATURE_ANY, 0 },
+ { X86_VENDOR_HYGON, 0x18, X86_MODEL_ANY, X86_FEATURE_ANY, 0 },
{ }
};
MODULE_DEVICE_TABLE(x86cpu, amd64_cpuids);
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c
index 2ab4d61..c605089 100644
--- a/drivers/edac/mce_amd.c
+++ b/drivers/edac/mce_amd.c
@@ -1059,7 +1059,8 @@ static int __init mce_amd_init(void)
{
struct cpuinfo_x86 *c = &boot_cpu_data;

- if (c->x86_vendor != X86_VENDOR_AMD)
+ if (c->x86_vendor != X86_VENDOR_AMD &&
+ c->x86_vendor != X86_VENDOR_HYGON)
return -ENODEV;

fam_ops = kzalloc(sizeof(struct amd_decoder_ops), GFP_KERNEL);
@@ -1113,6 +1114,7 @@ static int __init mce_amd_init(void)
break;

case 0x17:
+ case 0x18:
xec_mask = 0x3f;
if (!boot_cpu_has(X86_FEATURE_SMCA)) {
printk(KERN_WARNING "Decoding supported only on Scalable MCA processors.\n");
--
2.7.4


2018-09-10 13:24:18

by Wen Pu

[permalink] [raw]
Subject: [PATCH v6 09/16] x86/bugs: Add mitigation to spectre and no meltdown for Hygon Dhyana

The Hygon Dhyana CPU has the same speculative execution as AMD family
17h, so share AMD spectre mitigation code for Hygon Dhyana.

Also Hygon Dhyana is not affected by meltdown vulnerability as AMD,
so add the exception for Hygon Dhyana.

Signed-off-by: Pu Wen <[email protected]>
---
arch/x86/kernel/cpu/bugs.c | 6 ++++--
arch/x86/kernel/cpu/common.c | 1 +
2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index 40bdaea..726010d 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -312,8 +312,9 @@ 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");
+ pr_err("retpoline,amd selected but CPU is not AMD or Hygon. Switching to AUTO select\n");
return SPECTRE_V2_CMD_AUTO;
}

@@ -371,7 +372,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");
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 44c4ef3..851cbe7 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -963,6 +963,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 },
{}
};

--
2.7.4


2018-09-10 13:25:44

by Wen Pu

[permalink] [raw]
Subject: [PATCH v6 13/16] ACPI, x86: Add Hygon Dhyana support

The Hygon Dhyana CPU has NONSTOP TSC feature, so enable the ACPI
driver support to it.

Acked-by: Rafael J. Wysocki <[email protected]>
Signed-off-by: Pu Wen <[email protected]>
---
drivers/acpi/acpi_pad.c | 1 +
drivers/acpi/processor_idle.c | 1 +
2 files changed, 2 insertions(+)

diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c
index 552c1f7..a47676a 100644
--- a/drivers/acpi/acpi_pad.c
+++ b/drivers/acpi/acpi_pad.c
@@ -70,6 +70,7 @@ static void power_saving_mwait_init(void)

#if defined(CONFIG_X86)
switch (boot_cpu_data.x86_vendor) {
+ case X86_VENDOR_HYGON:
case X86_VENDOR_AMD:
case X86_VENDOR_INTEL:
/*
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index abb559c..b2131c4 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -205,6 +205,7 @@ static void lapic_timer_state_broadcast(struct acpi_processor *pr,
static void tsc_check_state(int state)
{
switch (boot_cpu_data.x86_vendor) {
+ case X86_VENDOR_HYGON:
case X86_VENDOR_AMD:
case X86_VENDOR_INTEL:
case X86_VENDOR_CENTAUR:
--
2.7.4


2018-09-10 13:25:54

by Wen Pu

[permalink] [raw]
Subject: [PATCH v6 14/16] cpufreq, x86: Add Hygon Dhyana support

As the Hygon Dhyana CPU support ACPI P-States feature, and there is
SMBus device(PCI device ID 0x790b) on Hygon platform, so add Hygon
Dhyana support to the cpufreq driver by using the code path of AMD
family 17h.

Acked-by: Rafael J. Wysocki <[email protected]>
Signed-off-by: Pu Wen <[email protected]>
---
drivers/cpufreq/acpi-cpufreq.c | 5 +++++
drivers/cpufreq/amd_freq_sensitivity.c | 9 +++++++--
2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
index b61f4ec..d62fd37 100644
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
@@ -61,6 +61,7 @@ enum {

#define INTEL_MSR_RANGE (0xffff)
#define AMD_MSR_RANGE (0x7)
+#define HYGON_MSR_RANGE (0x7)

#define MSR_K7_HWCR_CPB_DIS (1ULL << 25)

@@ -95,6 +96,7 @@ static bool boost_state(unsigned int cpu)
rdmsr_on_cpu(cpu, MSR_IA32_MISC_ENABLE, &lo, &hi);
msr = lo | ((u64)hi << 32);
return !(msr & MSR_IA32_MISC_ENABLE_TURBO_DISABLE);
+ case X86_VENDOR_HYGON:
case X86_VENDOR_AMD:
rdmsr_on_cpu(cpu, MSR_K7_HWCR, &lo, &hi);
msr = lo | ((u64)hi << 32);
@@ -113,6 +115,7 @@ static int boost_set_msr(bool enable)
msr_addr = MSR_IA32_MISC_ENABLE;
msr_mask = MSR_IA32_MISC_ENABLE_TURBO_DISABLE;
break;
+ case X86_VENDOR_HYGON:
case X86_VENDOR_AMD:
msr_addr = MSR_K7_HWCR;
msr_mask = MSR_K7_HWCR_CPB_DIS;
@@ -225,6 +228,8 @@ static unsigned extract_msr(struct cpufreq_policy *policy, u32 msr)

if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
msr &= AMD_MSR_RANGE;
+ else if (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON)
+ msr &= HYGON_MSR_RANGE;
else
msr &= INTEL_MSR_RANGE;

diff --git a/drivers/cpufreq/amd_freq_sensitivity.c b/drivers/cpufreq/amd_freq_sensitivity.c
index be926d9..4ac7c3c 100644
--- a/drivers/cpufreq/amd_freq_sensitivity.c
+++ b/drivers/cpufreq/amd_freq_sensitivity.c
@@ -111,11 +111,16 @@ static int __init amd_freq_sensitivity_init(void)
{
u64 val;
struct pci_dev *pcidev;
+ unsigned int pci_vendor;

- if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
+ if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
+ pci_vendor = PCI_VENDOR_ID_AMD;
+ else if (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON)
+ pci_vendor = PCI_VENDOR_ID_HYGON;
+ else
return -ENODEV;

- pcidev = pci_get_device(PCI_VENDOR_ID_AMD,
+ pcidev = pci_get_device(pci_vendor,
PCI_DEVICE_ID_AMD_KERNCZ_SMBUS, NULL);

if (!pcidev) {
--
2.7.4


2018-09-10 16:40:36

by Borislav Petkov

[permalink] [raw]
Subject: Re: [PATCH v6 01/16] x86/cpu: Create Hygon Dhyana architecture support file

On Mon, Sep 10, 2018 at 09:15:29PM +0800, Pu Wen wrote:
> Add x86 architecture support for new processor Hygon Dhyana Family

"... for a new processor: Hygon... "

> 18h.

Instead of all that:

> Rework to create a separated file(arch/x86/kernel/cpu/hygon.c)
> from the AMD one(arch/x86/kernel/cpu/amd.c) to initialize Dhyana.


> In this way we can remove old AMD architecture support codes and
> generate a clear initialization flow for Hygon Dhyana CPU. It also
> reduce the long-term maintenance effort.

... simply say: "Carve out initialization code needed by Dhyana into a
separate compilation unit."

> Add Maintainer information
> for hygon.c in accordance.

That sentence is not needed - that fact is visible in the diff.

>
> To identify Hygon Dhyana CPU, add a new vendor type X86_VENDOR_HYGON(9)
> for system recognition.

No need for that "(9)" - also visible from the diff and an
implementation detail.

>
> To enable the config for Hygon Dhyana CPU, add a separated Kconfig
> entry(CPU_SUP_HYGON) in kernel config setup.

That sentence is not needed for the same reason as above.

> And select CPU_SUP_AMD
> to solve the dependency issues in kernel.

No, this should say: "Since Dhyana uses AMD functionality to a large
degree, select CPU_SUP_AMD which provides that functionality."

>
> Signed-off-by: Pu Wen <[email protected]>
> ---
> MAINTAINERS | 6 +
> arch/x86/Kconfig.cpu | 14 ++
> arch/x86/include/asm/processor.h | 3 +-
> arch/x86/kernel/cpu/Makefile | 1 +
> arch/x86/kernel/cpu/hygon.c | 408 +++++++++++++++++++++++++++++++++++++++
> 5 files changed, 431 insertions(+), 1 deletion(-)
> create mode 100644 arch/x86/kernel/cpu/hygon.c

With that taken care of:

Reviewed-by: Borislav Petkov <[email protected]>

--
Regards/Gruss,
Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.

2018-09-10 18:06:42

by Borislav Petkov

[permalink] [raw]
Subject: Re: [PATCH v6 03/16] x86/cpu/mtrr: Support TOP_MEM2 and get MTRR number

On Mon, Sep 10, 2018 at 09:16:03PM +0800, Pu Wen wrote:
> The Hygon Dhyana CPU have a special magic MSR way to force WB for

From the last review round:

Also, it is "The ... CPU has a special..."

Please take your time and incorporate *all* review feedback - no need to
*rush* a new revision out and drop review feedback.

> memory >4GB, and support TOP_MEM2. Therefore, it is necessary to
> add Hygon Dhyana support in amd_special_default_mtrr().
>
> The number of variable MTRRs for Hygon is 2 as AMD's.
>
> Signed-off-by: Pu Wen <[email protected]>
> ---
> arch/x86/kernel/cpu/mtrr/cleanup.c | 3 ++-
> arch/x86/kernel/cpu/mtrr/mtrr.c | 2 +-
> 2 files changed, 3 insertions(+), 2 deletions(-)

With that fixed:

Reviewed-by: Borislav Petkov <[email protected]>

--
Regards/Gruss,
Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.

2018-09-10 18:18:26

by Borislav Petkov

[permalink] [raw]
Subject: Re: [PATCH v6 05/16] perf/x86: Add Hygon Dhyana support to PMU infrastructure

On Mon, Sep 10, 2018 at 09:16:43PM +0800, Pu Wen wrote:
> The PMU architecture for Hygon Dhyana CPU is similar to the AMD Family
> 17h one. To support Hygon Dhyana PMU, call amd_pmu_init() to share
> AMD PMU initialization flow, and change the PMU name to "HYGON".
>
> The Hygon Dhyana CPU support both legacy and extension PMC MSRs(perf

I don't know but for some reason, you are writing "Hygon Dhyana CPU" as
being plural. But it is singular:

"The Hygon Dhyna CPU supports both ..."
^
|||

> counter registers and event selection registers), so add Hygon Dhyana
> support to get bit offset in the similar way as AMD does.

"to get bit offset"?

> Signed-off-by: Pu Wen <[email protected]>
> ---
> arch/x86/events/amd/core.c | 4 ++++
> arch/x86/events/amd/uncore.c | 20 +++++++++++++-------
> arch/x86/events/core.c | 4 ++++
> arch/x86/kernel/cpu/perfctr-watchdog.c | 2 ++
> 4 files changed, 23 insertions(+), 7 deletions(-)

With that addressed:

Reviewed-by: Borislav Petkov <[email protected]>

--
Regards/Gruss,
Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.

2018-09-11 06:34:09

by Wen Pu

[permalink] [raw]
Subject: Re: [PATCH v6 01/16] x86/cpu: Create Hygon Dhyana architecture support file

On 2018/9/11 0:38, Borislav Petkov wrote:
> That sentence is not needed for the same reason as above.
>
>> And select CPU_SUP_AMD
>> to solve the dependency issues in kernel.
>
> No, this should say: "Since Dhyana uses AMD functionality to a large
> degree, select CPU_SUP_AMD which provides that functionality."

Thanks for the detailed correction. Will improve the description and
remove unneeded sentences in next version of patch.

--
Regards,
Pu Wen


2018-09-11 06:41:43

by Wen Pu

[permalink] [raw]
Subject: Re: [PATCH v6 03/16] x86/cpu/mtrr: Support TOP_MEM2 and get MTRR number

On 2018/9/11 2:06, Borislav Petkov wrote:
> On Mon, Sep 10, 2018 at 09:16:03PM +0800, Pu Wen wrote:
>> The Hygon Dhyana CPU have a special magic MSR way to force WB for
>
> From the last review round:
>
> Also, it is "The ... CPU has a special..."
>
> Please take your time and incorporate *all* review feedback - no need to
> *rush* a new revision out and drop review feedback.

Sorry for not taking much care of the usage between singular and plural.
Will fix those typos.

--
Regards,
Pu Wen


2018-09-11 07:01:38

by Wen Pu

[permalink] [raw]
Subject: Re: [PATCH v6 05/16] perf/x86: Add Hygon Dhyana support to PMU infrastructure

On 2018/9/11 2:17, Borislav Petkov wrote:
>> The Hygon Dhyana CPU support both legacy and extension PMC MSRs(perf
>
> I don't know but for some reason, you are writing "Hygon Dhyana CPU" as
> being plural. But it is singular:
>
> "The Hygon Dhyna CPU supports both ..."
> ^
> |||

Will take more care of the usage between singular and plural and fix
the typo.

>> counter registers and event selection registers), so add Hygon Dhyana
>> support to get bit offset in the similar way as AMD does.
>
> "to get bit offset"?

These words are used with the tendency to explain what the patch do,
actually they are not needed and will be removed.

--
Regards,
Pu Wen


2018-09-11 10:08:22

by Borislav Petkov

[permalink] [raw]
Subject: Re: [PATCH v6 07/16] x86/pci: Add Hygon Dhyana support to PCI and north bridge

On Mon, Sep 10, 2018 at 09:17:11PM +0800, Pu Wen wrote:
> As Hygon registered its PCI Vendor ID as a new one 0x1d94, and there
> are PCI Devices 0x1450/0x1463/0x1464 for Host bridge on Hygon Dhyana
> platforms, so add Hygon Dhyana support to the PCI and north bridge
> subsystem by using the code path of AMD family 17h.
>
> Acked-by: Bjorn Helgaas <[email protected]> # pci_ids.h
> Signed-off-by: Pu Wen <[email protected]>
> ---
> arch/x86/kernel/amd_nb.c | 47 +++++++++++++++++++++++++++++++++++++++++------
> arch/x86/pci/amd_bus.c | 6 ++++--
> include/linux/pci_ids.h | 2 ++
> 3 files changed, 47 insertions(+), 8 deletions(-)

Reviewed-by: Borislav Petkov <[email protected]>

--
Regards/Gruss,
Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.

2018-09-11 10:15:18

by Borislav Petkov

[permalink] [raw]
Subject: Re: [PATCH v6 08/16] x86/apic: Add Hygon Dhyana support to APIC

On Mon, Sep 10, 2018 at 09:17:27PM +0800, Pu Wen wrote:
> Add Hygon Dhyana support to the APIC subsystem as it use modern APIC.
> When running on 32 bit mode, bigsmp should be enabled if there are
> more than 8 cores online.
>
> Signed-off-by: Pu Wen <[email protected]>
> ---
> arch/x86/kernel/apic/apic.c | 13 +++++++++++--
> arch/x86/kernel/apic/probe_32.c | 1 +
> 2 files changed, 12 insertions(+), 2 deletions(-)
>
> diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
> index 84132ed..709daf2 100644
> --- a/arch/x86/kernel/apic/apic.c
> +++ b/arch/x86/kernel/apic/apic.c
> @@ -224,6 +224,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;
> }
>
> @@ -1211,9 +1216,11 @@ void __init sync_Arb_IDs(void)
> {
> /*
> * Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1 And not
> - * needed on AMD.
> + * needed on AMD or Hygon.
> */
> - if (modern_apic() || boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
> + if (modern_apic() ||
> + boot_cpu_data.x86_vendor == X86_VENDOR_AMD ||
> + boot_cpu_data.x86_vendor == X86_VENDOR_HYGON)

This change is not needed, after the above hunk in modern_apic(), right?

With it removed:

Reviewed-by: Borislav Petkov <[email protected]>

--
Regards/Gruss,
Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.

2018-09-11 10:38:51

by Borislav Petkov

[permalink] [raw]
Subject: Re: [PATCH v6 09/16] x86/bugs: Add mitigation to spectre and no meltdown for Hygon Dhyana

On Mon, Sep 10, 2018 at 09:17:40PM +0800, Pu Wen wrote:
> The Hygon Dhyana CPU has the same speculative execution as AMD family
> 17h, so share AMD spectre mitigation code for Hygon Dhyana.
>
> Also Hygon Dhyana is not affected by meltdown vulnerability as AMD,
> so add the exception for Hygon Dhyana.
>
> Signed-off-by: Pu Wen <[email protected]>
> ---
> arch/x86/kernel/cpu/bugs.c | 6 ++++--
> arch/x86/kernel/cpu/common.c | 1 +
> 2 files changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
> index 40bdaea..726010d 100644
> --- a/arch/x86/kernel/cpu/bugs.c
> +++ b/arch/x86/kernel/cpu/bugs.c
> @@ -312,8 +312,9 @@ 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");
> + pr_err("retpoline,amd selected but CPU is not AMD or Hygon. Switching to AUTO select\n");

Didn't we say, no user-visible changes pls?

--
Regards/Gruss,
Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.

2018-09-11 10:43:30

by Borislav Petkov

[permalink] [raw]
Subject: Re: [PATCH v6 10/16] x86/mce: Add Hygon Dhyana support to MCE infrastructure

On Mon, Sep 10, 2018 at 09:17:54PM +0800, Pu Wen wrote:
> The machine check architecture for Hygon Dhyana CPU is similar to the
> AMD family 17h one. To make MCE working on Hygon platforms, add vendor
> checking for Hygon Dhyana to share the code path of AMD family 17h.
>
> Signed-off-by: Pu Wen <[email protected]>
> ---
> arch/x86/include/asm/mce.h | 2 ++
> arch/x86/kernel/cpu/mcheck/mce-severity.c | 3 ++-
> arch/x86/kernel/cpu/mcheck/mce.c | 20 +++++++++++++++-----
> 3 files changed, 19 insertions(+), 6 deletions(-)

Reviewed-by: Borislav Petkov <[email protected]>

--
Regards/Gruss,
Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.

2018-09-11 10:52:04

by Borislav Petkov

[permalink] [raw]
Subject: Re: [PATCH v6 15/16] EDAC, amd64: Add Hygon Dhyana support

On Mon, Sep 10, 2018 at 09:20:24PM +0800, Pu Wen wrote:
> To make AMD64 EDAC and MCE drivers working on Hygon platforms, add
> support for Hygon Dhyana CPU by using the code path of AMD family
> 17h.
>
> Signed-off-by: Pu Wen <[email protected]>
> ---
> drivers/edac/amd64_edac.c | 8 +++++++-
> drivers/edac/mce_amd.c | 4 +++-
> 2 files changed, 10 insertions(+), 2 deletions(-)

This one conflicts with

8960de4a5ca7 ("EDAC, amd64: Add Family 17h, models 10h-2fh support")

in my tree.

tglx, what do you suggest?

--
Regards/Gruss,
Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.

2018-09-11 13:04:48

by Wen Pu

[permalink] [raw]
Subject: Re: [PATCH v6 08/16] x86/apic: Add Hygon Dhyana support to APIC

On 2018/9/11 18:14, Borislav Petkov wrote:
>> @@ -1211,9 +1216,11 @@ void __init sync_Arb_IDs(void)
>> {
>> /*
>> * Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1 And not
>> - * needed on AMD.
>> + * needed on AMD or Hygon.
>> */
>> - if (modern_apic() || boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
>> + if (modern_apic() ||
>> + boot_cpu_data.x86_vendor == X86_VENDOR_AMD ||
>> + boot_cpu_data.x86_vendor == X86_VENDOR_HYGON)
>
> This change is not needed, after the above hunk in modern_apic(), right?

Yes, you are right. Since the Hygon Dhyana CPU always uses modern APIC,
so the function modern_apic will always return true for Hygon Dhyana.
I will remove this change in next version of patch.

>
> With it removed:
>
> Reviewed-by: Borislav Petkov <[email protected]>

--
Regards,
Pu Wen


2018-09-11 13:20:19

by Wen Pu

[permalink] [raw]
Subject: Re: [PATCH v6 09/16] x86/bugs: Add mitigation to spectre and no meltdown for Hygon Dhyana

On 2018/9/11 18:38, Borislav Petkov wrote:
>> 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");
>> + pr_err("retpoline,amd selected but CPU is not AMD or Hygon. Switching to AUTO select\n");
>
> Didn't we say, no user-visible changes pls?

Sorry for the incomplete modification. Will revert the pr_err string.

--
Regards,
Pu Wen


2018-09-19 17:22:26

by Tom Lendacky

[permalink] [raw]
Subject: Re: [PATCH v6 07/16] x86/pci: Add Hygon Dhyana support to PCI and north bridge

On 09/10/2018 08:17 AM, Pu Wen wrote:
> As Hygon registered its PCI Vendor ID as a new one 0x1d94, and there
> are PCI Devices 0x1450/0x1463/0x1464 for Host bridge on Hygon Dhyana
> platforms, so add Hygon Dhyana support to the PCI and north bridge
> subsystem by using the code path of AMD family 17h.
>
> Acked-by: Bjorn Helgaas <[email protected]> # pci_ids.h
> Signed-off-by: Pu Wen <[email protected]>
> ---
> arch/x86/kernel/amd_nb.c | 47 +++++++++++++++++++++++++++++++++++++++++------
> arch/x86/pci/amd_bus.c | 6 ++++--
> include/linux/pci_ids.h | 2 ++
> 3 files changed, 47 insertions(+), 8 deletions(-)
>
> diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c
> index b481b95..3e2ea18 100644
> --- a/arch/x86/kernel/amd_nb.c
> +++ b/arch/x86/kernel/amd_nb.c
> @@ -61,6 +61,21 @@ static const struct pci_device_id amd_nb_link_ids[] = {
> {}
> };
>
> +static const struct pci_device_id hygon_root_ids[] = {
> + { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_AMD_17H_ROOT) },
> + {}
> +};
> +
> +const struct pci_device_id hygon_nb_misc_ids[] = {
> + { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_AMD_17H_DF_F3) },
> + {}
> +};
> +
> +static const struct pci_device_id hygon_nb_link_ids[] = {
> + { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_AMD_17H_DF_F4) },
> + {}
> +};
> +
> const struct amd_nb_bus_dev_range amd_nb_bus_dev_ranges[] __initconst = {
> { 0x00, 0x18, 0x20 },
> { 0xff, 0x00, 0x20 },
> @@ -197,12 +212,25 @@ int amd_cache_northbridges(void)
> u16 i = 0;
> struct amd_northbridge *nb;
> struct pci_dev *root, *misc, *link;
> + const struct pci_device_id *root_ids = NULL;
> + const struct pci_device_id *misc_ids = NULL;
> + const struct pci_device_id *link_ids = NULL;
> +
> + if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
> + root_ids = amd_root_ids;
> + misc_ids = amd_nb_misc_ids;
> + link_ids = amd_nb_link_ids;
> + } else if (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) {
> + root_ids = hygon_root_ids;
> + misc_ids = hygon_nb_misc_ids;
> + link_ids = hygon_nb_link_ids;
> + }

To be compatible with "before this patch" you should probably do:

if (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) {
root_ids = hygon_root_ids;
misc_ids = hygon_nb_misc_ids;
link_ids = hygon_nb_link_ids;
} else {
root_ids = amd_root_ids;
misc_ids = amd_nb_misc_ids;
link_ids = amd_nb_link_ids;
}

That way they are always the AMD values if not your chip.

>
> if (amd_northbridges.num)
> return 0;
>
> misc = NULL;
> - while ((misc = next_northbridge(misc, amd_nb_misc_ids)) != NULL)
> + while ((misc = next_northbridge(misc, misc_ids)) != NULL)
> i++;
>
> if (!i)
> @@ -218,11 +246,11 @@ int amd_cache_northbridges(void)
> link = misc = root = NULL;
> for (i = 0; i != amd_northbridges.num; i++) {
> node_to_amd_nb(i)->root = root =
> - next_northbridge(root, amd_root_ids);
> + next_northbridge(root, root_ids);
> node_to_amd_nb(i)->misc = misc =
> - next_northbridge(misc, amd_nb_misc_ids);
> + next_northbridge(misc, misc_ids);
> node_to_amd_nb(i)->link = link =
> - next_northbridge(link, amd_nb_link_ids);
> + next_northbridge(link, link_ids);
> }
>
> if (amd_gart_present())
> @@ -263,9 +291,15 @@ bool __init early_is_amd_nb(u32 device)
> {
> const struct pci_device_id *id;
> u32 vendor = device & 0xffff;
> + const struct pci_device_id *misc_ids = NULL;
> +
> + if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
> + misc_ids = amd_nb_misc_ids;
> + else if (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON)
> + misc_ids = hygon_nb_misc_ids;

Same comment as above. This will probably eliminate the PANIC that
that was reported by LKP.

Thanks,
Tom

>
> device >>= 16;
> - for (id = amd_nb_misc_ids; id->vendor; id++)
> + for (id = misc_ids; id->vendor; id++)
> if (vendor == id->vendor && device == id->device)
> return true;
> return false;
> @@ -277,7 +311,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 */
> diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c
> index 649bdde..bfa50e6 100644
> --- a/arch/x86/pci/amd_bus.c
> +++ b/arch/x86/pci/amd_bus.c
> @@ -93,7 +93,8 @@ static int __init early_root_info_init(void)
> vendor = id & 0xffff;
> device = (id>>16) & 0xffff;
>
> - if (vendor != PCI_VENDOR_ID_AMD)
> + if (vendor != PCI_VENDOR_ID_AMD &&
> + vendor != PCI_VENDOR_ID_HYGON)
> continue;
>
> if (hb_probes[i].device == device) {
> @@ -390,7 +391,8 @@ static int __init pci_io_ecs_init(void)
>
> static int __init amd_postcore_init(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)
> return 0;
>
> early_root_info_init();
> diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
> index d157983..8a0841c 100644
> --- a/include/linux/pci_ids.h
> +++ b/include/linux/pci_ids.h
> @@ -2561,6 +2561,8 @@
>
> #define PCI_VENDOR_ID_AMAZON 0x1d0f
>
> +#define PCI_VENDOR_ID_HYGON 0x1d94
> +
> #define PCI_VENDOR_ID_TEKRAM 0x1de1
> #define PCI_DEVICE_ID_TEKRAM_DC290 0xdc29
>
>

2018-09-20 07:25:57

by Thomas Gleixner

[permalink] [raw]
Subject: Re: [PATCH v6 07/16] x86/pci: Add Hygon Dhyana support to PCI and north bridge

On Wed, 19 Sep 2018, Lendacky, Thomas wrote:
>
> To be compatible with "before this patch" you should probably do:
>
> if (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) {
> root_ids = hygon_root_ids;
> misc_ids = hygon_nb_misc_ids;
> link_ids = hygon_nb_link_ids;
> } else {
> root_ids = amd_root_ids;
> misc_ids = amd_nb_misc_ids;
> link_ids = amd_nb_link_ids;
> }
>
> That way they are always the AMD values if not your chip.

And please can we have a comment why this is called on anything which is
not AMD or HYGON. It's all but obvious and clearly unexpected.

Thanks,

tglx

2018-09-20 08:06:16

by Wen Pu

[permalink] [raw]
Subject: Re: [PATCH v6 07/16] x86/pci: Add Hygon Dhyana support to PCI and north bridge

On 2018/9/20 1:20, Lendacky, Thomas wrote:
>> @@ -197,12 +212,25 @@ int amd_cache_northbridges(void)
>> u16 i = 0;
>> struct amd_northbridge *nb;
>> struct pci_dev *root, *misc, *link;
>> + const struct pci_device_id *root_ids = NULL;
>> + const struct pci_device_id *misc_ids = NULL;
>> + const struct pci_device_id *link_ids = NULL;
>> +
>> + if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
>> + root_ids = amd_root_ids;
>> + misc_ids = amd_nb_misc_ids;
>> + link_ids = amd_nb_link_ids;
>> + } else if (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) {
>> + root_ids = hygon_root_ids;
>> + misc_ids = hygon_nb_misc_ids;
>> + link_ids = hygon_nb_link_ids;
>> + }
>
> To be compatible with "before this patch" you should probably do:
>
> if (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) {
> root_ids = hygon_root_ids;
> misc_ids = hygon_nb_misc_ids;
> link_ids = hygon_nb_link_ids;
> } else {
> root_ids = amd_root_ids;
> misc_ids = amd_nb_misc_ids;
> link_ids = amd_nb_link_ids;
> }
>
> That way they are always the AMD values if not your chip.
>
...
>> @@ -263,9 +291,15 @@ bool __init early_is_amd_nb(u32 device)
>> {
>> const struct pci_device_id *id;
>> u32 vendor = device & 0xffff;
>> + const struct pci_device_id *misc_ids = NULL;
>> +
>> + if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
>> + misc_ids = amd_nb_misc_ids;
>> + else if (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON)
>> + misc_ids = hygon_nb_misc_ids;
>
> Same comment as above. This will probably eliminate the PANIC that
> that was reported by LKP.

Yes, it's this modification that caused the PANIC reported by LKP.
Because the misc_ids will be NULL if running on Intel chip.

If change the vendor checking like this:

+ if (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON)
+ misc_ids = hygon_nb_misc_ids;
+ else
+ misc_ids = amd_nb_misc_ids;

The PANIC will be eliminated.

The PANIC will also be eliminated by adding AMD vendor checking in
amd_gart_present:

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

To prevent the function return true on non AMD platform.

Thanks,
Pu Wen


2018-10-01 19:39:22

by Shuah Khan

[permalink] [raw]
Subject: Re: [PATCH v6 16/16] cpupower, x86: Add Hygon Dhyana support

On 09/10/2018 07:20 AM, Pu Wen wrote:
> Tool cpupower is useful to get CPU frequency information and monitor
> power stats on Hygon Dhyana platforms. So add Hygon Dhyana support to
> it by checking vendor and family to share the code path of AMD family
> 17h.
>
> Signed-off-by: Pu Wen <[email protected]>

Looks good to me. I am assuming it will go into x86 with the rest of the
series.

Acked-by: Shuah Khan (Samsung OSG) <[email protected]>

thanks,
-- Shuah

2018-10-04 01:24:55

by Wen Pu

[permalink] [raw]
Subject: [RESEND PATCH v8 16/16] cpupower: Add Hygon Dhyana support

Tool cpupower is useful to get CPU frequency information and monitor
power stats on Hygon Dhyana platform. So add Hygon Dhyana support to
it by checking vendor and family to share the code path of AMD family
17h.

Signed-off-by: Pu Wen <[email protected]>
Acked-by: Shuah Khan (Samsung OSG) <[email protected]>
---
tools/power/cpupower/utils/cpufreq-info.c | 6 ++++--
tools/power/cpupower/utils/helpers/amd.c | 4 ++--
tools/power/cpupower/utils/helpers/cpuid.c | 8 +++++---
tools/power/cpupower/utils/helpers/helpers.h | 2 +-
tools/power/cpupower/utils/helpers/misc.c | 2 +-
tools/power/cpupower/utils/idle_monitor/mperf_monitor.c | 3 ++-
6 files changed, 15 insertions(+), 10 deletions(-)

diff --git a/tools/power/cpupower/utils/cpufreq-info.c b/tools/power/cpupower/utils/cpufreq-info.c
index df43cd4..56e54ea 100644
--- a/tools/power/cpupower/utils/cpufreq-info.c
+++ b/tools/power/cpupower/utils/cpufreq-info.c
@@ -170,6 +170,7 @@ static int get_boost_mode(unsigned int cpu)
unsigned long pstates[MAX_HW_PSTATES] = {0,};

if (cpupower_cpu_info.vendor != X86_VENDOR_AMD &&
+ cpupower_cpu_info.vendor != X86_VENDOR_HYGON &&
cpupower_cpu_info.vendor != X86_VENDOR_INTEL)
return 0;

@@ -190,8 +191,9 @@ static int get_boost_mode(unsigned int cpu)
printf(_(" Supported: %s\n"), support ? _("yes") : _("no"));
printf(_(" Active: %s\n"), active ? _("yes") : _("no"));

- if (cpupower_cpu_info.vendor == X86_VENDOR_AMD &&
- cpupower_cpu_info.family >= 0x10) {
+ if ((cpupower_cpu_info.vendor == X86_VENDOR_AMD &&
+ cpupower_cpu_info.family >= 0x10) ||
+ cpupower_cpu_info.vendor == X86_VENDOR_HYGON) {
ret = decode_pstates(cpu, cpupower_cpu_info.family, b_states,
pstates, &pstate_no);
if (ret)
diff --git a/tools/power/cpupower/utils/helpers/amd.c b/tools/power/cpupower/utils/helpers/amd.c
index bb41cdd..65beaee 100644
--- a/tools/power/cpupower/utils/helpers/amd.c
+++ b/tools/power/cpupower/utils/helpers/amd.c
@@ -45,7 +45,7 @@ static int get_did(int family, union msr_pstate pstate)

if (family == 0x12)
t = pstate.val & 0xf;
- else if (family == 0x17)
+ else if (family == 0x17 || family == 0x18)
t = pstate.fam17h_bits.did;
else
t = pstate.bits.did;
@@ -59,7 +59,7 @@ static int get_cof(int family, union msr_pstate pstate)
int fid, did, cof;

did = get_did(family, pstate);
- if (family == 0x17) {
+ if (family == 0x17 || family == 0x18) {
fid = pstate.fam17h_bits.fid;
cof = 200 * fid / did;
} else {
diff --git a/tools/power/cpupower/utils/helpers/cpuid.c b/tools/power/cpupower/utils/helpers/cpuid.c
index 732b0b4..5cc39d4 100644
--- a/tools/power/cpupower/utils/helpers/cpuid.c
+++ b/tools/power/cpupower/utils/helpers/cpuid.c
@@ -8,7 +8,7 @@
#include "helpers/helpers.h"

static const char *cpu_vendor_table[X86_VENDOR_MAX] = {
- "Unknown", "GenuineIntel", "AuthenticAMD",
+ "Unknown", "GenuineIntel", "AuthenticAMD", "HygonGenuine",
};

#if defined(__i386__) || defined(__x86_64__)
@@ -109,6 +109,7 @@ int get_cpu_info(struct cpupower_cpu_info *cpu_info)
fclose(fp);
/* Get some useful CPU capabilities from cpuid */
if (cpu_info->vendor != X86_VENDOR_AMD &&
+ cpu_info->vendor != X86_VENDOR_HYGON &&
cpu_info->vendor != X86_VENDOR_INTEL)
return ret;

@@ -124,8 +125,9 @@ int get_cpu_info(struct cpupower_cpu_info *cpu_info)
if (cpuid_level >= 6 && (cpuid_ecx(6) & 0x1))
cpu_info->caps |= CPUPOWER_CAP_APERF;

- /* AMD Boost state enable/disable register */
- if (cpu_info->vendor == X86_VENDOR_AMD) {
+ /* AMD or Hygon Boost state enable/disable register */
+ if (cpu_info->vendor == X86_VENDOR_AMD ||
+ cpu_info->vendor == X86_VENDOR_HYGON) {
if (ext_cpuid_level >= 0x80000007 &&
(cpuid_edx(0x80000007) & (1 << 9)))
cpu_info->caps |= CPUPOWER_CAP_AMD_CBP;
diff --git a/tools/power/cpupower/utils/helpers/helpers.h b/tools/power/cpupower/utils/helpers/helpers.h
index 41da392..9021396 100644
--- a/tools/power/cpupower/utils/helpers/helpers.h
+++ b/tools/power/cpupower/utils/helpers/helpers.h
@@ -61,7 +61,7 @@ extern int be_verbose;

/* cpuid and cpuinfo helpers **************************/
enum cpupower_cpu_vendor {X86_VENDOR_UNKNOWN = 0, X86_VENDOR_INTEL,
- X86_VENDOR_AMD, X86_VENDOR_MAX};
+ X86_VENDOR_AMD, X86_VENDOR_HYGON, X86_VENDOR_MAX};

#define CPUPOWER_CAP_INV_TSC 0x00000001
#define CPUPOWER_CAP_APERF 0x00000002
diff --git a/tools/power/cpupower/utils/helpers/misc.c b/tools/power/cpupower/utils/helpers/misc.c
index 80fdf55..f406adc 100644
--- a/tools/power/cpupower/utils/helpers/misc.c
+++ b/tools/power/cpupower/utils/helpers/misc.c
@@ -26,7 +26,7 @@ int cpufreq_has_boost_support(unsigned int cpu, int *support, int *active,
* has Hardware determined variable increments instead.
*/

- if (cpu_info.family == 0x17) {
+ if (cpu_info.family == 0x17 || cpu_info.family == 0x18) {
if (!read_msr(cpu, MSR_AMD_HWCR, &val)) {
if (!(val & CPUPOWER_AMD_CPBDIS))
*active = 1;
diff --git a/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c b/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c
index d7c2a6d..f2a7e9c 100644
--- a/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c
+++ b/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c
@@ -241,7 +241,8 @@ static int init_maxfreq_mode(void)
if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_INV_TSC))
goto use_sysfs;

- if (cpupower_cpu_info.vendor == X86_VENDOR_AMD) {
+ if (cpupower_cpu_info.vendor == X86_VENDOR_AMD ||
+ cpupower_cpu_info.vendor == X86_VENDOR_HYGON) {
/* MSR_AMD_HWCR tells us whether TSC runs at P0/mperf
* freq.
* A test whether hwcr is accessable/available would be:
--
2.7.4


Subject: [tip:x86/cpu] tools/cpupower: Add Hygon Dhyana support

Commit-ID: 995d5f64b62f20f05b8e0972f07ec4d6c23333c9
Gitweb: https://git.kernel.org/tip/995d5f64b62f20f05b8e0972f07ec4d6c23333c9
Author: Pu Wen <[email protected]>
AuthorDate: Thu, 4 Oct 2018 09:21:43 +0800
Committer: Borislav Petkov <[email protected]>
CommitDate: Thu, 4 Oct 2018 09:57:25 +0200

tools/cpupower: Add Hygon Dhyana support

The tool cpupower is useful to get CPU frequency information and monitor
power stats on the Hygon Dhyana platform. So add Hygon Dhyana support to
it by checking vendor and family to share the code path of AMD family
17h.

Signed-off-by: Pu Wen <[email protected]>
Signed-off-by: Borislav Petkov <[email protected]>
Acked-by: Shuah Khan (Samsung OSG) <[email protected]>
CC: Prarit Bhargava <[email protected]>
CC: Shuah Khan <[email protected]>
CC: Thomas Gleixner <[email protected]>
CC: Thomas Renninger <[email protected]>
CC: [email protected]
Link: http://lkml.kernel.org/r/5ce86123a7b9dad925ac583d88d2f921040e859b.1538583282.git.puwen@hygon.cn
---
tools/power/cpupower/utils/cpufreq-info.c | 6 ++++--
tools/power/cpupower/utils/helpers/amd.c | 4 ++--
tools/power/cpupower/utils/helpers/cpuid.c | 8 +++++---
tools/power/cpupower/utils/helpers/helpers.h | 2 +-
tools/power/cpupower/utils/helpers/misc.c | 2 +-
tools/power/cpupower/utils/idle_monitor/mperf_monitor.c | 3 ++-
6 files changed, 15 insertions(+), 10 deletions(-)

diff --git a/tools/power/cpupower/utils/cpufreq-info.c b/tools/power/cpupower/utils/cpufreq-info.c
index df43cd45d810..56e54eabc65c 100644
--- a/tools/power/cpupower/utils/cpufreq-info.c
+++ b/tools/power/cpupower/utils/cpufreq-info.c
@@ -170,6 +170,7 @@ static int get_boost_mode(unsigned int cpu)
unsigned long pstates[MAX_HW_PSTATES] = {0,};

if (cpupower_cpu_info.vendor != X86_VENDOR_AMD &&
+ cpupower_cpu_info.vendor != X86_VENDOR_HYGON &&
cpupower_cpu_info.vendor != X86_VENDOR_INTEL)
return 0;

@@ -190,8 +191,9 @@ static int get_boost_mode(unsigned int cpu)
printf(_(" Supported: %s\n"), support ? _("yes") : _("no"));
printf(_(" Active: %s\n"), active ? _("yes") : _("no"));

- if (cpupower_cpu_info.vendor == X86_VENDOR_AMD &&
- cpupower_cpu_info.family >= 0x10) {
+ if ((cpupower_cpu_info.vendor == X86_VENDOR_AMD &&
+ cpupower_cpu_info.family >= 0x10) ||
+ cpupower_cpu_info.vendor == X86_VENDOR_HYGON) {
ret = decode_pstates(cpu, cpupower_cpu_info.family, b_states,
pstates, &pstate_no);
if (ret)
diff --git a/tools/power/cpupower/utils/helpers/amd.c b/tools/power/cpupower/utils/helpers/amd.c
index bb41cdd0df6b..65beaeefeef0 100644
--- a/tools/power/cpupower/utils/helpers/amd.c
+++ b/tools/power/cpupower/utils/helpers/amd.c
@@ -45,7 +45,7 @@ static int get_did(int family, union msr_pstate pstate)

if (family == 0x12)
t = pstate.val & 0xf;
- else if (family == 0x17)
+ else if (family == 0x17 || family == 0x18)
t = pstate.fam17h_bits.did;
else
t = pstate.bits.did;
@@ -59,7 +59,7 @@ static int get_cof(int family, union msr_pstate pstate)
int fid, did, cof;

did = get_did(family, pstate);
- if (family == 0x17) {
+ if (family == 0x17 || family == 0x18) {
fid = pstate.fam17h_bits.fid;
cof = 200 * fid / did;
} else {
diff --git a/tools/power/cpupower/utils/helpers/cpuid.c b/tools/power/cpupower/utils/helpers/cpuid.c
index 732b0b41ba26..5cc39d4e23ed 100644
--- a/tools/power/cpupower/utils/helpers/cpuid.c
+++ b/tools/power/cpupower/utils/helpers/cpuid.c
@@ -8,7 +8,7 @@
#include "helpers/helpers.h"

static const char *cpu_vendor_table[X86_VENDOR_MAX] = {
- "Unknown", "GenuineIntel", "AuthenticAMD",
+ "Unknown", "GenuineIntel", "AuthenticAMD", "HygonGenuine",
};

#if defined(__i386__) || defined(__x86_64__)
@@ -109,6 +109,7 @@ out:
fclose(fp);
/* Get some useful CPU capabilities from cpuid */
if (cpu_info->vendor != X86_VENDOR_AMD &&
+ cpu_info->vendor != X86_VENDOR_HYGON &&
cpu_info->vendor != X86_VENDOR_INTEL)
return ret;

@@ -124,8 +125,9 @@ out:
if (cpuid_level >= 6 && (cpuid_ecx(6) & 0x1))
cpu_info->caps |= CPUPOWER_CAP_APERF;

- /* AMD Boost state enable/disable register */
- if (cpu_info->vendor == X86_VENDOR_AMD) {
+ /* AMD or Hygon Boost state enable/disable register */
+ if (cpu_info->vendor == X86_VENDOR_AMD ||
+ cpu_info->vendor == X86_VENDOR_HYGON) {
if (ext_cpuid_level >= 0x80000007 &&
(cpuid_edx(0x80000007) & (1 << 9)))
cpu_info->caps |= CPUPOWER_CAP_AMD_CBP;
diff --git a/tools/power/cpupower/utils/helpers/helpers.h b/tools/power/cpupower/utils/helpers/helpers.h
index 41da392be448..902139689315 100644
--- a/tools/power/cpupower/utils/helpers/helpers.h
+++ b/tools/power/cpupower/utils/helpers/helpers.h
@@ -61,7 +61,7 @@ extern int be_verbose;

/* cpuid and cpuinfo helpers **************************/
enum cpupower_cpu_vendor {X86_VENDOR_UNKNOWN = 0, X86_VENDOR_INTEL,
- X86_VENDOR_AMD, X86_VENDOR_MAX};
+ X86_VENDOR_AMD, X86_VENDOR_HYGON, X86_VENDOR_MAX};

#define CPUPOWER_CAP_INV_TSC 0x00000001
#define CPUPOWER_CAP_APERF 0x00000002
diff --git a/tools/power/cpupower/utils/helpers/misc.c b/tools/power/cpupower/utils/helpers/misc.c
index 80fdf55f414d..f406adc40bad 100644
--- a/tools/power/cpupower/utils/helpers/misc.c
+++ b/tools/power/cpupower/utils/helpers/misc.c
@@ -26,7 +26,7 @@ int cpufreq_has_boost_support(unsigned int cpu, int *support, int *active,
* has Hardware determined variable increments instead.
*/

- if (cpu_info.family == 0x17) {
+ if (cpu_info.family == 0x17 || cpu_info.family == 0x18) {
if (!read_msr(cpu, MSR_AMD_HWCR, &val)) {
if (!(val & CPUPOWER_AMD_CPBDIS))
*active = 1;
diff --git a/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c b/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c
index d7c2a6d13dea..f2a7e9cfd577 100644
--- a/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c
+++ b/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c
@@ -241,7 +241,8 @@ static int init_maxfreq_mode(void)
if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_INV_TSC))
goto use_sysfs;

- if (cpupower_cpu_info.vendor == X86_VENDOR_AMD) {
+ if (cpupower_cpu_info.vendor == X86_VENDOR_AMD ||
+ cpupower_cpu_info.vendor == X86_VENDOR_HYGON) {
/* MSR_AMD_HWCR tells us whether TSC runs at P0/mperf
* freq.
* A test whether hwcr is accessable/available would be: