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