Skip to content

Commit 335ad94

Browse files
committed
Merge tag 'x86-cpu-2020-08-03' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 cpu updates from Ingo Molar: - prepare for Intel's new SERIALIZE instruction - enable split-lock debugging on more CPUs - add more Intel CPU models - optimize stack canary initialization a bit - simplify the Spectre logic a bit * tag 'x86-cpu-2020-08-03' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/cpu: Refactor sync_core() for readability x86/cpu: Relocate sync_core() to sync_core.h x86/cpufeatures: Add enumeration for SERIALIZE instruction x86/split_lock: Enable the split lock feature on Sapphire Rapids and Alder Lake CPUs x86/cpu: Add Lakefield, Alder Lake and Rocket Lake models to the to Intel CPU family x86/stackprotector: Pre-initialize canary for secondary CPUs x86/speculation: Merge one test in spectre_v2_user_select_mitigation()
2 parents 4ee4810 + f69ca62 commit 335ad94

File tree

15 files changed

+105
-88
lines changed

15 files changed

+105
-88
lines changed

arch/x86/include/asm/cpufeatures.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@
367367
#define X86_FEATURE_SRBDS_CTRL (18*32+ 9) /* "" SRBDS mitigation MSR available */
368368
#define X86_FEATURE_MD_CLEAR (18*32+10) /* VERW clears CPU buffers */
369369
#define X86_FEATURE_TSX_FORCE_ABORT (18*32+13) /* "" TSX_FORCE_ABORT */
370+
#define X86_FEATURE_SERIALIZE (18*32+14) /* SERIALIZE instruction */
370371
#define X86_FEATURE_PCONFIG (18*32+18) /* Intel PCONFIG */
371372
#define X86_FEATURE_ARCH_LBR (18*32+19) /* Intel ARCH LBR */
372373
#define X86_FEATURE_SPEC_CTRL (18*32+26) /* "" Speculation Control (IBRS + IBPB) */

arch/x86/include/asm/intel-family.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,15 @@
8989
#define INTEL_FAM6_COMETLAKE 0xA5
9090
#define INTEL_FAM6_COMETLAKE_L 0xA6
9191

92+
#define INTEL_FAM6_ROCKETLAKE 0xA7
93+
9294
#define INTEL_FAM6_SAPPHIRERAPIDS_X 0x8F
9395

96+
/* Hybrid Core/Atom Processors */
97+
98+
#define INTEL_FAM6_LAKEFIELD 0x8A
99+
#define INTEL_FAM6_ALDERLAKE 0x97
100+
94101
/* "Small Core" Processors (Atom) */
95102

96103
#define INTEL_FAM6_ATOM_BONNELL 0x1C /* Diamondville, Pineview */

arch/x86/include/asm/processor.h

Lines changed: 0 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -678,70 +678,6 @@ static inline unsigned int cpuid_edx(unsigned int op)
678678
return edx;
679679
}
680680

681-
/*
682-
* This function forces the icache and prefetched instruction stream to
683-
* catch up with reality in two very specific cases:
684-
*
685-
* a) Text was modified using one virtual address and is about to be executed
686-
* from the same physical page at a different virtual address.
687-
*
688-
* b) Text was modified on a different CPU, may subsequently be
689-
* executed on this CPU, and you want to make sure the new version
690-
* gets executed. This generally means you're calling this in a IPI.
691-
*
692-
* If you're calling this for a different reason, you're probably doing
693-
* it wrong.
694-
*/
695-
static inline void sync_core(void)
696-
{
697-
/*
698-
* There are quite a few ways to do this. IRET-to-self is nice
699-
* because it works on every CPU, at any CPL (so it's compatible
700-
* with paravirtualization), and it never exits to a hypervisor.
701-
* The only down sides are that it's a bit slow (it seems to be
702-
* a bit more than 2x slower than the fastest options) and that
703-
* it unmasks NMIs. The "push %cs" is needed because, in
704-
* paravirtual environments, __KERNEL_CS may not be a valid CS
705-
* value when we do IRET directly.
706-
*
707-
* In case NMI unmasking or performance ever becomes a problem,
708-
* the next best option appears to be MOV-to-CR2 and an
709-
* unconditional jump. That sequence also works on all CPUs,
710-
* but it will fault at CPL3 (i.e. Xen PV).
711-
*
712-
* CPUID is the conventional way, but it's nasty: it doesn't
713-
* exist on some 486-like CPUs, and it usually exits to a
714-
* hypervisor.
715-
*
716-
* Like all of Linux's memory ordering operations, this is a
717-
* compiler barrier as well.
718-
*/
719-
#ifdef CONFIG_X86_32
720-
asm volatile (
721-
"pushfl\n\t"
722-
"pushl %%cs\n\t"
723-
"pushl $1f\n\t"
724-
"iret\n\t"
725-
"1:"
726-
: ASM_CALL_CONSTRAINT : : "memory");
727-
#else
728-
unsigned int tmp;
729-
730-
asm volatile (
731-
"mov %%ss, %0\n\t"
732-
"pushq %q0\n\t"
733-
"pushq %%rsp\n\t"
734-
"addq $8, (%%rsp)\n\t"
735-
"pushfq\n\t"
736-
"mov %%cs, %0\n\t"
737-
"pushq %q0\n\t"
738-
"pushq $1f\n\t"
739-
"iretq\n\t"
740-
"1:"
741-
: "=&r" (tmp), ASM_CALL_CONSTRAINT : : "cc", "memory");
742-
#endif
743-
}
744-
745681
extern void select_idle_routine(const struct cpuinfo_x86 *c);
746682
extern void amd_e400_c1e_apic_setup(void);
747683

arch/x86/include/asm/special_insns.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,6 @@ static inline void clwb(volatile void *__p)
234234

235235
#define nop() asm volatile ("nop")
236236

237-
238237
#endif /* __KERNEL__ */
239238

240239
#endif /* _ASM_X86_SPECIAL_INSNS_H */

arch/x86/include/asm/stackprotector.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,15 @@ static __always_inline void boot_init_stack_canary(void)
9090
#endif
9191
}
9292

93+
static inline void cpu_init_stack_canary(int cpu, struct task_struct *idle)
94+
{
95+
#ifdef CONFIG_X86_64
96+
per_cpu(fixed_percpu_data.stack_canary, cpu) = idle->stack_canary;
97+
#else
98+
per_cpu(stack_canary.canary, cpu) = idle->stack_canary;
99+
#endif
100+
}
101+
93102
static inline void setup_stack_canary_segment(int cpu)
94103
{
95104
#ifdef CONFIG_X86_32
@@ -119,6 +128,9 @@ static inline void load_stack_canary_segment(void)
119128
static inline void setup_stack_canary_segment(int cpu)
120129
{ }
121130

131+
static inline void cpu_init_stack_canary(int cpu, struct task_struct *idle)
132+
{ }
133+
122134
static inline void load_stack_canary_segment(void)
123135
{
124136
#ifdef CONFIG_X86_32

arch/x86/include/asm/sync_core.h

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,78 @@
66
#include <asm/processor.h>
77
#include <asm/cpufeature.h>
88

9+
#ifdef CONFIG_X86_32
10+
static inline void iret_to_self(void)
11+
{
12+
asm volatile (
13+
"pushfl\n\t"
14+
"pushl %%cs\n\t"
15+
"pushl $1f\n\t"
16+
"iret\n\t"
17+
"1:"
18+
: ASM_CALL_CONSTRAINT : : "memory");
19+
}
20+
#else
21+
static inline void iret_to_self(void)
22+
{
23+
unsigned int tmp;
24+
25+
asm volatile (
26+
"mov %%ss, %0\n\t"
27+
"pushq %q0\n\t"
28+
"pushq %%rsp\n\t"
29+
"addq $8, (%%rsp)\n\t"
30+
"pushfq\n\t"
31+
"mov %%cs, %0\n\t"
32+
"pushq %q0\n\t"
33+
"pushq $1f\n\t"
34+
"iretq\n\t"
35+
"1:"
36+
: "=&r" (tmp), ASM_CALL_CONSTRAINT : : "cc", "memory");
37+
}
38+
#endif /* CONFIG_X86_32 */
39+
40+
/*
41+
* This function forces the icache and prefetched instruction stream to
42+
* catch up with reality in two very specific cases:
43+
*
44+
* a) Text was modified using one virtual address and is about to be executed
45+
* from the same physical page at a different virtual address.
46+
*
47+
* b) Text was modified on a different CPU, may subsequently be
48+
* executed on this CPU, and you want to make sure the new version
49+
* gets executed. This generally means you're calling this in a IPI.
50+
*
51+
* If you're calling this for a different reason, you're probably doing
52+
* it wrong.
53+
*/
54+
static inline void sync_core(void)
55+
{
56+
/*
57+
* There are quite a few ways to do this. IRET-to-self is nice
58+
* because it works on every CPU, at any CPL (so it's compatible
59+
* with paravirtualization), and it never exits to a hypervisor.
60+
* The only down sides are that it's a bit slow (it seems to be
61+
* a bit more than 2x slower than the fastest options) and that
62+
* it unmasks NMIs. The "push %cs" is needed because, in
63+
* paravirtual environments, __KERNEL_CS may not be a valid CS
64+
* value when we do IRET directly.
65+
*
66+
* In case NMI unmasking or performance ever becomes a problem,
67+
* the next best option appears to be MOV-to-CR2 and an
68+
* unconditional jump. That sequence also works on all CPUs,
69+
* but it will fault at CPL3 (i.e. Xen PV).
70+
*
71+
* CPUID is the conventional way, but it's nasty: it doesn't
72+
* exist on some 486-like CPUs, and it usually exits to a
73+
* hypervisor.
74+
*
75+
* Like all of Linux's memory ordering operations, this is a
76+
* compiler barrier as well.
77+
*/
78+
iret_to_self();
79+
}
80+
981
/*
1082
* Ensure that a core serializing instruction is issued before returning
1183
* to user-mode. x86 implements return to user-space through sysexit,

arch/x86/kernel/alternative.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <linux/kprobes.h>
1717
#include <linux/mmu_context.h>
1818
#include <linux/bsearch.h>
19+
#include <linux/sync_core.h>
1920
#include <asm/text-patching.h>
2021
#include <asm/alternative.h>
2122
#include <asm/sections.h>

arch/x86/kernel/cpu/bugs.c

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -763,10 +763,12 @@ spectre_v2_user_select_mitigation(enum spectre_v2_mitigation_cmd v2_cmd)
763763
}
764764

765765
/*
766-
* If enhanced IBRS is enabled or SMT impossible, STIBP is not
766+
* If no STIBP, enhanced IBRS is enabled or SMT impossible, STIBP is not
767767
* required.
768768
*/
769-
if (!smt_possible || spectre_v2_enabled == SPECTRE_V2_IBRS_ENHANCED)
769+
if (!boot_cpu_has(X86_FEATURE_STIBP) ||
770+
!smt_possible ||
771+
spectre_v2_enabled == SPECTRE_V2_IBRS_ENHANCED)
770772
return;
771773

772774
/*
@@ -778,12 +780,6 @@ spectre_v2_user_select_mitigation(enum spectre_v2_mitigation_cmd v2_cmd)
778780
boot_cpu_has(X86_FEATURE_AMD_STIBP_ALWAYS_ON))
779781
mode = SPECTRE_V2_USER_STRICT_PREFERRED;
780782

781-
/*
782-
* If STIBP is not available, clear the STIBP mode.
783-
*/
784-
if (!boot_cpu_has(X86_FEATURE_STIBP))
785-
mode = SPECTRE_V2_USER_NONE;
786-
787783
spectre_v2_user_stibp = mode;
788784

789785
set_mode:
@@ -1270,7 +1266,6 @@ static int ib_prctl_set(struct task_struct *task, unsigned long ctrl)
12701266
* Indirect branch speculation is always disabled in strict
12711267
* mode. It can neither be enabled if it was force-disabled
12721268
* by a previous prctl call.
1273-
12741269
*/
12751270
if (spectre_v2_user_ibpb == SPECTRE_V2_USER_STRICT ||
12761271
spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT ||

arch/x86/kernel/cpu/intel.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1156,6 +1156,8 @@ static const struct x86_cpu_id split_lock_cpu_ids[] __initconst = {
11561156
X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_L, 1),
11571157
X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE_L, 1),
11581158
X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE, 1),
1159+
X86_MATCH_INTEL_FAM6_MODEL(SAPPHIRERAPIDS_X, 1),
1160+
X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE, 1),
11591161
{}
11601162
};
11611163

arch/x86/kernel/cpu/mce/core.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include <linux/export.h>
4343
#include <linux/jump_label.h>
4444
#include <linux/set_memory.h>
45+
#include <linux/sync_core.h>
4546
#include <linux/task_work.h>
4647
#include <linux/hardirq.h>
4748

0 commit comments

Comments
 (0)