1 #include <xen/init.h>
2 #include <asm/processor.h>
3 #include <asm/hvm/support.h>
4 #include <asm/spec_ctrl.h>
5 
6 #include "cpu.h"
7 
8 #define APICID_SOCKET_ID_BIT 6
9 
hygon_get_topology(struct cpuinfo_x86 * c)10 static void hygon_get_topology(struct cpuinfo_x86 *c)
11 {
12 	unsigned int ebx;
13 
14 	if (c->x86_max_cores <= 1)
15 		return;
16 
17 	/* Socket ID is ApicId[6] for Hygon processors. */
18 	c->phys_proc_id >>= APICID_SOCKET_ID_BIT;
19 
20 	ebx = cpuid_ebx(0x8000001e);
21 	c->x86_num_siblings = ((ebx >> 8) & 0x3) + 1;
22 	c->x86_max_cores /= c->x86_num_siblings;
23 	c->cpu_core_id = ebx & 0xff;
24 
25 	if (opt_cpu_info)
26 	        printk("CPU %d(%d) -> Processor %d, Core %d\n",
27 	                smp_processor_id(), c->x86_max_cores,
28 	                        c->phys_proc_id, c->cpu_core_id);
29 }
30 
init_hygon(struct cpuinfo_x86 * c)31 static void init_hygon(struct cpuinfo_x86 *c)
32 {
33 	unsigned long long value;
34 
35 	/*
36 	 * Attempt to set lfence to be Dispatch Serialising.  This MSR almost
37 	 * certainly isn't virtualised (and Xen at least will leak the real
38 	 * value in but silently discard writes), as well as being per-core
39 	 * rather than per-thread, so do a full safe read/write/readback cycle
40 	 * in the worst case.
41 	 */
42 	if (rdmsr_safe(MSR_AMD64_DE_CFG, value))
43 		/* Unable to read.  Assume the safer default. */
44 		__clear_bit(X86_FEATURE_LFENCE_DISPATCH,
45 			    c->x86_capability);
46 	else if (value & AMD64_DE_CFG_LFENCE_SERIALISE)
47 		/* Already dispatch serialising. */
48 		__set_bit(X86_FEATURE_LFENCE_DISPATCH,
49 			  c->x86_capability);
50 	else if (wrmsr_safe(MSR_AMD64_DE_CFG,
51 			    value | AMD64_DE_CFG_LFENCE_SERIALISE) ||
52 		 rdmsr_safe(MSR_AMD64_DE_CFG, value) ||
53 		 !(value & AMD64_DE_CFG_LFENCE_SERIALISE))
54 		/* Attempt to set failed.  Assume the safer default. */
55 		__clear_bit(X86_FEATURE_LFENCE_DISPATCH,
56 			    c->x86_capability);
57 	else
58 		/* Successfully enabled! */
59 		__set_bit(X86_FEATURE_LFENCE_DISPATCH,
60 			  c->x86_capability);
61 
62 	/*
63 	 * If the user has explicitly chosen to disable Memory Disambiguation
64 	 * to mitigiate Speculative Store Bypass, poke the appropriate MSR.
65 	 */
66 	if (opt_ssbd && !rdmsr_safe(MSR_AMD64_LS_CFG, value)) {
67 		value |= 1ull << 10;
68 		wrmsr_safe(MSR_AMD64_LS_CFG, value);
69 	}
70 
71 	/* MFENCE stops RDTSC speculation */
72 	if (!cpu_has_lfence_dispatch)
73 		__set_bit(X86_FEATURE_MFENCE_RDTSC, c->x86_capability);
74 
75 	display_cacheinfo(c);
76 
77 	if (c->extended_cpuid_level >= 0x80000008)
78 		c->x86_max_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;
79 
80 	if (c->extended_cpuid_level >= 0x80000007) {
81 		if (cpu_has(c, X86_FEATURE_ITSC)) {
82 			__set_bit(X86_FEATURE_CONSTANT_TSC, c->x86_capability);
83 			__set_bit(X86_FEATURE_NONSTOP_TSC, c->x86_capability);
84 			__set_bit(X86_FEATURE_TSC_RELIABLE, c->x86_capability);
85 		}
86 	}
87 
88 	hygon_get_topology(c);
89 
90 	/* Hygon CPUs do not support SYSENTER outside of legacy mode. */
91 	__clear_bit(X86_FEATURE_SEP, c->x86_capability);
92 
93 	/* Hygon processors have APIC timer running in deep C states. */
94 	if (opt_arat)
95 		__set_bit(X86_FEATURE_ARAT, c->x86_capability);
96 
97 	if (cpu_has(c, X86_FEATURE_EFRO)) {
98 		rdmsrl(MSR_K7_HWCR, value);
99 		value |= (1 << 27); /* Enable read-only APERF/MPERF bit */
100 		wrmsrl(MSR_K7_HWCR, value);
101 	}
102 
103 	amd_log_freq(c);
104 }
105 
106 const struct cpu_dev hygon_cpu_dev = {
107 	.c_early_init	= early_init_amd,
108 	.c_init		= init_hygon,
109 };
110