diff mbox series

[v4,01/15] x86/cpu: Create Hygon Dhyana architecture support file

Message ID eb635da990e92443a91b2ae598ed354e35975efa.1553935727.git.puwen@hygon.cn (mailing list archive)
State Superseded
Headers show
Series Add support for Hygon Dhyana Family 18h processor | expand

Commit Message

Pu Wen March 30, 2019, 10:42 a.m. UTC
Add x86 architecture support for a new processor: Hygon Dhyana Family
18h. To make Hygon initialization flow more clear, carve out code from
amd.c into a separate file hygon.c, and remove unnecessary code for
Hygon Dhyana.

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

Hygon can fully use the function early_init_amd(), so make this common
function non-static and direct call it from Hygon code.

Add a separate hygon_get_topology(), which calculate phys_proc_id from
AcpiId[6](see reference [1]).

Reference:
[1] https://git.kernel.org/tip/e0ceeae708cebf22c990c3d703a4ca187dc837f5

Signed-off-by: Pu Wen <puwen@hygon.cn>
---
 xen/arch/x86/cpu/Makefile         |  1 +
 xen/arch/x86/cpu/amd.c            |  2 +-
 xen/arch/x86/cpu/common.c         |  1 +
 xen/arch/x86/cpu/cpu.h            |  3 ++
 xen/arch/x86/cpu/hygon.c          | 92 +++++++++++++++++++++++++++++++++++++++
 xen/include/asm-x86/x86-vendors.h |  3 +-
 6 files changed, 100 insertions(+), 2 deletions(-)
 create mode 100644 xen/arch/x86/cpu/hygon.c

Comments

Andrew Cooper April 2, 2019, 12:13 p.m. UTC | #1
On 30/03/2019 10:42, Pu Wen wrote:
> +static const struct cpu_dev hygon_cpu_dev = {
> +	.c_vendor	= "Hygon",
> +	.c_ident 	= { "HygonGenuine" },
> +	.c_early_init	= early_init_amd,
> +	.c_init		= init_hygon,
> +};
> +
> +int __init hygon_init_cpu(void)
> +{
> +	cpu_devs[X86_VENDOR_HYGON] = &hygon_cpu_dev;
> +	return 0;
> +}
> diff --git a/xen/include/asm-x86/x86-vendors.h b/xen/include/asm-x86/x86-vendors.h
> index 38a81c3..fa1cbb4 100644
> --- a/xen/include/asm-x86/x86-vendors.h
> +++ b/xen/include/asm-x86/x86-vendors.h
> @@ -9,6 +9,7 @@
>  #define X86_VENDOR_AMD 2
>  #define X86_VENDOR_CENTAUR 3
>  #define X86_VENDOR_SHANGHAI 4
> -#define X86_VENDOR_NUM 5
> +#define X86_VENDOR_HYGON 5
> +#define X86_VENDOR_NUM 6

This change will need rebasing over
http://xenbits.xen.org/gitweb/?p=xen.git;a=commitdiff;h=e72309ffbe7c4e507649c74749f130cda691131c
, which has dropped the .c_ident field for a more efficient lookup
mechanism.

Hopefully the adjustments are all obvious.  If not, I can draft a patch.

~Andrew
Pu Wen April 2, 2019, 1:09 p.m. UTC | #2
On 2019/4/2 20:16, Andrew Cooper wrote:
> On 30/03/2019 10:42, Pu Wen wrote:
>> +static const struct cpu_dev hygon_cpu_dev = {
>> +	.c_vendor	= "Hygon",
>> +	.c_ident 	= { "HygonGenuine" },
>> +	.c_early_init	= early_init_amd,
>> +	.c_init		= init_hygon,
>> +};
>> +
>> +int __init hygon_init_cpu(void)
>> +{
>> +	cpu_devs[X86_VENDOR_HYGON] = &hygon_cpu_dev;
>> +	return 0;
>> +}
>> diff --git a/xen/include/asm-x86/x86-vendors.h b/xen/include/asm-x86/x86-vendors.h
>> index 38a81c3..fa1cbb4 100644
>> --- a/xen/include/asm-x86/x86-vendors.h
>> +++ b/xen/include/asm-x86/x86-vendors.h
>> @@ -9,6 +9,7 @@
>>   #define X86_VENDOR_AMD 2
>>   #define X86_VENDOR_CENTAUR 3
>>   #define X86_VENDOR_SHANGHAI 4
>> -#define X86_VENDOR_NUM 5
>> +#define X86_VENDOR_HYGON 5
>> +#define X86_VENDOR_NUM 6
> 
> This change will need rebasing over
> http://xenbits.xen.org/gitweb/?p=xen.git;a=commitdiff;h=e72309ffbe7c4e507649c74749f130cda691131c
> , which has dropped the .c_ident field for a more efficient lookup

Oh, this is already in the staging branch!

> mechanism.
> 
> Hopefully the adjustments are all obvious.  If not, I can draft a patch.

I'll try to rework this patch rebasing over the latest staging branch
for your review. Thanks.
Jan Beulich April 3, 2019, 8:42 a.m. UTC | #3
>>> On 30.03.19 at 11:42, <puwen@hygon.cn> wrote:
> +static void init_hygon(struct cpuinfo_x86 *c)
> +{
> +	unsigned long long value;
> +
> +	/* Attempt to set LFENCE to be Dispatch Serialising. */
> +	if (rdmsr_safe(MSR_AMD64_DE_CFG, value))
> +		/* Unable to read.  Assume the safer default. */
> +		__clear_bit(X86_FEATURE_LFENCE_DISPATCH, c->x86_capability);
> +	if (value & AMD64_DE_CFG_LFENCE_SERIALISE)
> +		/* Dispatch Serialising. */
> +		__set_bit(X86_FEATURE_LFENCE_DISPATCH, c->x86_capability);

This still isn't in line with the AMD code it was derived from. In
particular code and comment do not match up: You don't make any
attempt to actually _set_ the intended mode, you only record the
setting found in the feature flags.

> +	/*
> +	 * If the user has explicitly chosen to disable Memory Disambiguation
> +	 * to mitigiate Speculative Store Bypass, poke the appropriate MSR.
> +	 */
> + 	if (opt_ssbd && !rdmsr_safe(MSR_AMD64_LS_CFG, value))
> + 	{

Since you've decided to inherit style from amd.c, the opening brace
belongs on the previous line (more instances further down).

> +		value |= 1ull << 10;
> +		wrmsr_safe(MSR_AMD64_LS_CFG, value);
> +	}
> +
> +	display_cacheinfo(c);

Above from here amd.c sets MFENCE_RDTSC as well. Why would
this not be needed for Hygon?

> +	if (cpu_has(c, X86_FEATURE_ITSC))
> +	{
> +		__set_bit(X86_FEATURE_CONSTANT_TSC, c->x86_capability);
> +		__set_bit(X86_FEATURE_NONSTOP_TSC, c->x86_capability);
> +		__set_bit(X86_FEATURE_TSC_RELIABLE, c->x86_capability);
> +	}

There is a CPUID extended level check around this and ...

> +	c->x86_max_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;

... also around this in the AMD original. Why did you drop this?
Please don't forget that we may run virtualized ourselves, and
that the respective leaves may have got hidden by the lower
level hypervisor.

Jan
Pu Wen April 3, 2019, 10:05 a.m. UTC | #4
On 2019/4/3 16:43, Jan Beulich wrote:
> On 30.03.19 at 11:42, <puwen@hygon.cn> wrote:
>> +static void init_hygon(struct cpuinfo_x86 *c)
>> +{
>> +	unsigned long long value;
>> +
>> +	/* Attempt to set LFENCE to be Dispatch Serialising. */
>> +	if (rdmsr_safe(MSR_AMD64_DE_CFG, value))
>> +		/* Unable to read.  Assume the safer default. */
>> +		__clear_bit(X86_FEATURE_LFENCE_DISPATCH, c->x86_capability);
>> +	if (value & AMD64_DE_CFG_LFENCE_SERIALISE)
>> +		/* Dispatch Serialising. */
>> +		__set_bit(X86_FEATURE_LFENCE_DISPATCH, c->x86_capability);
> 
> This still isn't in line with the AMD code it was derived from. In
> particular code and comment do not match up: You don't make any
> attempt to actually _set_ the intended mode, you only record the
> setting found in the feature flags.

The code is derived but not fully copied. I tested the conditionals and 
found that the other branches are not reached on Hygon platforms, so I 
removed them.

Our firmware will make sure that the bit AMD64_DE_CFG_LFENCE_SERIALISE 
will be set. So I just check here instead of setting. If you think 
retaining all the original conditionals is better, I'll do that. :)

>> +	/*
>> +	 * If the user has explicitly chosen to disable Memory Disambiguation
>> +	 * to mitigiate Speculative Store Bypass, poke the appropriate MSR.
>> +	 */
>> + 	if (opt_ssbd && !rdmsr_safe(MSR_AMD64_LS_CFG, value))
>> + 	{
> 
> Since you've decided to inherit style from amd.c, the opening brace
> belongs on the previous line (more instances further down).

I'm a little confused about which style to follow? In v3 series I 
followed the style of the derived code. But in other patch you told me 
to follow the Xen coding style, so in v4 series I changed the style to 
match the bracing section of CODING_STYLE.

Anyway I can still inherit the style from amd.c.

>> +		value |= 1ull << 10;
>> +		wrmsr_safe(MSR_AMD64_LS_CFG, value);
>> +	}
>> +
>> +	display_cacheinfo(c);
> 
> Above from here amd.c sets MFENCE_RDTSC as well. Why would
> this not be needed for Hygon?

Because Hygon has feature LFENCE_DISPATCH, so the feature MFENCE_RDTSC 
will not be set here.

But if you think the conditional should be retained here for some reason 
(even though the conditional may not be touched), I'll add it.

>> +	if (cpu_has(c, X86_FEATURE_ITSC))
>> +	{
>> +		__set_bit(X86_FEATURE_CONSTANT_TSC, c->x86_capability);
>> +		__set_bit(X86_FEATURE_NONSTOP_TSC, c->x86_capability);
>> +		__set_bit(X86_FEATURE_TSC_RELIABLE, c->x86_capability);
>> +	}
> 
> There is a CPUID extended level check around this and ...
> 
>> +	c->x86_max_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;
> 
> ... also around this in the AMD original. Why did you drop this?

The reason is somehow the same as the explanations above. Hygon CPU 
always has CPUID extended level, so I think there is no need to check it 
here.

Different from AMD, which has many old families without the CPUID 
extended level, Hygon CPU is derived from AMD family 17h and always has 
the extended features.

> Please don't forget that we may run virtualized ourselves, and
> that the respective leaves may have got hidden by the lower
> level hypervisor.

I think this is the most important reason. Previously I only considered 
to run Hygon Xen on bare hardware, which is the most important usage for 
a server processor. To match all the using cases I'll add the checking 
you mentioned above.
Jan Beulich April 3, 2019, 10:21 a.m. UTC | #5
>>> On 03.04.19 at 12:05, <puwen@hygon.cn> wrote:
> On 2019/4/3 16:43, Jan Beulich wrote:
>> On 30.03.19 at 11:42, <puwen@hygon.cn> wrote:
>>> +static void init_hygon(struct cpuinfo_x86 *c)
>>> +{
>>> +	unsigned long long value;
>>> +
>>> +	/* Attempt to set LFENCE to be Dispatch Serialising. */
>>> +	if (rdmsr_safe(MSR_AMD64_DE_CFG, value))
>>> +		/* Unable to read.  Assume the safer default. */
>>> +		__clear_bit(X86_FEATURE_LFENCE_DISPATCH, c->x86_capability);
>>> +	if (value & AMD64_DE_CFG_LFENCE_SERIALISE)
>>> +		/* Dispatch Serialising. */
>>> +		__set_bit(X86_FEATURE_LFENCE_DISPATCH, c->x86_capability);
>> 
>> This still isn't in line with the AMD code it was derived from. In
>> particular code and comment do not match up: You don't make any
>> attempt to actually _set_ the intended mode, you only record the
>> setting found in the feature flags.
> 
> The code is derived but not fully copied. I tested the conditionals and 
> found that the other branches are not reached on Hygon platforms, so I 
> removed them.
> 
> Our firmware will make sure that the bit AMD64_DE_CFG_LFENCE_SERIALISE 
> will be set. So I just check here instead of setting. If you think 
> retaining all the original conditionals is better, I'll do that. :)

I'm not convinced you need to retain everything, but you surely
shouldn't limit code to work just on your specific variant of
firmware.

>>> +	/*
>>> +	 * If the user has explicitly chosen to disable Memory Disambiguation
>>> +	 * to mitigiate Speculative Store Bypass, poke the appropriate MSR.
>>> +	 */
>>> + 	if (opt_ssbd && !rdmsr_safe(MSR_AMD64_LS_CFG, value))
>>> + 	{
>> 
>> Since you've decided to inherit style from amd.c, the opening brace
>> belongs on the previous line (more instances further down).
> 
> I'm a little confused about which style to follow? In v3 series I 
> followed the style of the derived code. But in other patch you told me 
> to follow the Xen coding style, so in v4 series I changed the style to 
> match the bracing section of CODING_STYLE.

Well, taking just the brace placement part doesn't make this
the file Xen style. In my earlier response to that style
question I did suggest you switch to Xen style for the new
file. I'd still view this as the preferred option, but then all
aspects should be taken care of. But I won't insist, yet in that
case clean Linux style is the only other alternative.

>>> +		value |= 1ull << 10;
>>> +		wrmsr_safe(MSR_AMD64_LS_CFG, value);
>>> +	}
>>> +
>>> +	display_cacheinfo(c);
>> 
>> Above from here amd.c sets MFENCE_RDTSC as well. Why would
>> this not be needed for Hygon?
> 
> Because Hygon has feature LFENCE_DISPATCH, so the feature MFENCE_RDTSC 
> will not be set here.
> 
> But if you think the conditional should be retained here for some reason 
> (even though the conditional may not be touched), I'll add it.

See above - yes, I think it should be retained.

Jan
Pu Wen April 3, 2019, 3:27 p.m. UTC | #6
On 2019/4/3 18:22, Jan Beulich wrote:
> On 03.04.19 at 12:05, <puwen@hygon.cn> wrote:
>> I'm a little confused about which style to follow? In v3 series I
>> followed the style of the derived code. But in other patch you told me
>> to follow the Xen coding style, so in v4 series I changed the style to
>> match the bracing section of CODING_STYLE.
> 
> Well, taking just the brace placement part doesn't make this
> the file Xen style. In my earlier response to that style
> question I did suggest you switch to Xen style for the new
> file. I'd still view this as the preferred option, but then all
> aspects should be taken care of. But I won't insist, yet in that
> case clean Linux style is the only other alternative.

Will inherit the style from amd.c in hygon.c.

>> But if you think the conditional should be retained here for some reason
>> (even though the conditional may not be touched), I'll add it.
> 
> See above - yes, I think it should be retained.

Okay, will retain the conditionals.
diff mbox series

Patch

diff --git a/xen/arch/x86/cpu/Makefile b/xen/arch/x86/cpu/Makefile
index 34a01ca..466acc8 100644
--- a/xen/arch/x86/cpu/Makefile
+++ b/xen/arch/x86/cpu/Makefile
@@ -4,6 +4,7 @@  subdir-y += mtrr
 obj-y += amd.o
 obj-y += centaur.o
 obj-y += common.o
+obj-y += hygon.o
 obj-y += intel.o
 obj-y += intel_cacheinfo.o
 obj-y += mwait-idle.o
diff --git a/xen/arch/x86/cpu/amd.c b/xen/arch/x86/cpu/amd.c
index c790416..061ebdc 100644
--- a/xen/arch/x86/cpu/amd.c
+++ b/xen/arch/x86/cpu/amd.c
@@ -526,7 +526,7 @@  static void amd_get_topology(struct cpuinfo_x86 *c)
                                                           : c->cpu_core_id);
 }
 
-static void early_init_amd(struct cpuinfo_x86 *c)
+void early_init_amd(struct cpuinfo_x86 *c)
 {
 	if (c == &boot_cpu_data)
 		amd_init_levelling();
diff --git a/xen/arch/x86/cpu/common.c b/xen/arch/x86/cpu/common.c
index 53bb0a9..db1ebf1 100644
--- a/xen/arch/x86/cpu/common.c
+++ b/xen/arch/x86/cpu/common.c
@@ -710,6 +710,7 @@  void __init early_cpu_init(void)
 	amd_init_cpu();
 	centaur_init_cpu();
 	shanghai_init_cpu();
+	hygon_init_cpu();
 	early_cpu_detect();
 }
 
diff --git a/xen/arch/x86/cpu/cpu.h b/xen/arch/x86/cpu/cpu.h
index 2fcb931..6c52a56 100644
--- a/xen/arch/x86/cpu/cpu.h
+++ b/xen/arch/x86/cpu/cpu.h
@@ -17,7 +17,10 @@  extern unsigned int opt_cpuid_mask_ext_ecx, opt_cpuid_mask_ext_edx;
 extern int get_model_name(struct cpuinfo_x86 *c);
 extern void display_cacheinfo(struct cpuinfo_x86 *c);
 
+void early_init_amd(struct cpuinfo_x86 *c);
+
 int intel_cpu_init(void);
 int amd_init_cpu(void);
 int centaur_init_cpu(void);
 int shanghai_init_cpu(void);
+int hygon_init_cpu(void);
diff --git a/xen/arch/x86/cpu/hygon.c b/xen/arch/x86/cpu/hygon.c
new file mode 100644
index 0000000..7ccbd84
--- /dev/null
+++ b/xen/arch/x86/cpu/hygon.c
@@ -0,0 +1,92 @@ 
+#include <xen/init.h>
+#include <asm/processor.h>
+#include <asm/hvm/support.h>
+#include <asm/spec_ctrl.h>
+
+#include "cpu.h"
+
+#define APICID_SOCKET_ID_BIT 6
+
+static void hygon_get_topology(struct cpuinfo_x86 *c)
+{
+	unsigned int ebx;
+
+	if (c->x86_max_cores <= 1)
+		return;
+
+	/* Socket ID is ApicId[6] for Hygon processors. */
+	c->phys_proc_id >>= APICID_SOCKET_ID_BIT;
+
+	ebx = cpuid_ebx(0x8000001e);
+	c->x86_num_siblings = ((ebx >> 8) & 0x3) + 1;
+	c->x86_max_cores /= c->x86_num_siblings;
+	c->cpu_core_id = ebx & 0xff;
+
+	if (opt_cpu_info)
+	        printk("CPU %d(%d) -> Processor %d, Core %d\n",
+	                smp_processor_id(), c->x86_max_cores,
+	                        c->phys_proc_id, c->cpu_core_id);
+}
+
+static void init_hygon(struct cpuinfo_x86 *c)
+{
+	unsigned long long value;
+
+	/* Attempt to set LFENCE to be Dispatch Serialising. */
+	if (rdmsr_safe(MSR_AMD64_DE_CFG, value))
+		/* Unable to read.  Assume the safer default. */
+		__clear_bit(X86_FEATURE_LFENCE_DISPATCH, c->x86_capability);
+	if (value & AMD64_DE_CFG_LFENCE_SERIALISE)
+		/* Dispatch Serialising. */
+		__set_bit(X86_FEATURE_LFENCE_DISPATCH, c->x86_capability);
+
+	/*
+	 * If the user has explicitly chosen to disable Memory Disambiguation
+	 * to mitigiate Speculative Store Bypass, poke the appropriate MSR.
+	 */
+ 	if (opt_ssbd && !rdmsr_safe(MSR_AMD64_LS_CFG, value))
+ 	{
+		value |= 1ull << 10;
+		wrmsr_safe(MSR_AMD64_LS_CFG, value);
+	}
+
+	display_cacheinfo(c);
+
+	if (cpu_has(c, X86_FEATURE_ITSC))
+	{
+		__set_bit(X86_FEATURE_CONSTANT_TSC, c->x86_capability);
+		__set_bit(X86_FEATURE_NONSTOP_TSC, c->x86_capability);
+		__set_bit(X86_FEATURE_TSC_RELIABLE, c->x86_capability);
+	}
+
+	c->x86_max_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;
+
+	hygon_get_topology(c);
+
+	/* Hygon CPUs do not support SYSENTER outside of legacy mode. */
+	__clear_bit(X86_FEATURE_SEP, c->x86_capability);
+
+	/* Hygon processors have APIC timer running in deep C states. */
+	if (opt_arat)
+		__set_bit(X86_FEATURE_ARAT, c->x86_capability);
+
+	if (cpu_has(c, X86_FEATURE_EFRO))
+	{
+		rdmsrl(MSR_K7_HWCR, value);
+		value |= (1 << 27); /* Enable read-only APERF/MPERF bit */
+		wrmsrl(MSR_K7_HWCR, value);
+	}
+}
+
+static const struct cpu_dev hygon_cpu_dev = {
+	.c_vendor	= "Hygon",
+	.c_ident 	= { "HygonGenuine" },
+	.c_early_init	= early_init_amd,
+	.c_init		= init_hygon,
+};
+
+int __init hygon_init_cpu(void)
+{
+	cpu_devs[X86_VENDOR_HYGON] = &hygon_cpu_dev;
+	return 0;
+}
diff --git a/xen/include/asm-x86/x86-vendors.h b/xen/include/asm-x86/x86-vendors.h
index 38a81c3..fa1cbb4 100644
--- a/xen/include/asm-x86/x86-vendors.h
+++ b/xen/include/asm-x86/x86-vendors.h
@@ -9,6 +9,7 @@ 
 #define X86_VENDOR_AMD 2
 #define X86_VENDOR_CENTAUR 3
 #define X86_VENDOR_SHANGHAI 4
-#define X86_VENDOR_NUM 5
+#define X86_VENDOR_HYGON 5
+#define X86_VENDOR_NUM 6
 
 #endif	/* __XEN_X86_VENDORS_H__ */