Skip to content

Commit d61f1cc

Browse files
committed
Merge tag 'x86_cpu_for_6.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 CPU feature updates from Dave Hansen: "The biggest thing of note here is Linear Address Space Separation (LASS). It represents the first time I can think of that the upper=>kernel/lower=>user address space convention is actually recognized by the hardware on x86. It ensures that userspace can not even get the hardware to _start_ page walks for the kernel address space. This, of course, is a really nice generic side channel defense. This is really only a down payment on LASS support. There are still some details to work out in its interaction with EFI calls and vsyscall emulation. For now, LASS is disabled if either of those features is compiled in (which is almost always the case). There's also one straggler commit in here which converts an under-utilized AMD CPU feature leaf into a generic Linux-defined leaf so more feature can be packed in there. Summary: - Enable Linear Address Space Separation (LASS) - Change X86_FEATURE leaf 17 from an AMD leaf to Linux-defined" * tag 'x86_cpu_for_6.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/cpu: Enable LASS during CPU initialization selftests/x86: Update the negative vsyscall tests to expect a #GP x86/traps: Communicate a LASS violation in #GP message x86/kexec: Disable LASS during relocate kernel x86/alternatives: Disable LASS when patching kernel code x86/asm: Introduce inline memcpy and memset x86/cpu: Add an LASS dependency on SMAP x86/cpufeatures: Enumerate the LASS feature bits x86/cpufeatures: Make X86_FEATURE leaf 17 Linux-specific
2 parents a7610b8 + d5cb957 commit d61f1cc

15 files changed

Lines changed: 176 additions & 37 deletions

File tree

arch/x86/Kconfig.cpufeatures

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,10 @@ config X86_DISABLED_FEATURE_PCID
124124
def_bool y
125125
depends on !X86_64
126126

127+
config X86_DISABLED_FEATURE_LASS
128+
def_bool y
129+
depends on X86_32
130+
127131
config X86_DISABLED_FEATURE_PKU
128132
def_bool y
129133
depends on !X86_INTEL_MEMORY_PROTECTION_KEYS

arch/x86/include/asm/cpufeature.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ enum cpuid_leafs
3030
CPUID_6_EAX,
3131
CPUID_8000_000A_EDX,
3232
CPUID_7_ECX,
33-
CPUID_8000_0007_EBX,
33+
CPUID_LNX_6,
3434
CPUID_7_EDX,
3535
CPUID_8000_001F_EAX,
3636
CPUID_8000_0021_EAX,

arch/x86/include/asm/cpufeatures.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,7 @@
314314
#define X86_FEATURE_SM4 (12*32+ 2) /* SM4 instructions */
315315
#define X86_FEATURE_AVX_VNNI (12*32+ 4) /* "avx_vnni" AVX VNNI instructions */
316316
#define X86_FEATURE_AVX512_BF16 (12*32+ 5) /* "avx512_bf16" AVX512 BFLOAT16 instructions */
317+
#define X86_FEATURE_LASS (12*32+ 6) /* "lass" Linear Address Space Separation */
317318
#define X86_FEATURE_CMPCCXADD (12*32+ 7) /* CMPccXADD instructions */
318319
#define X86_FEATURE_ARCH_PERFMON_EXT (12*32+ 8) /* Intel Architectural PerfMon Extension */
319320
#define X86_FEATURE_FZRM (12*32+10) /* Fast zero-length REP MOVSB */
@@ -407,9 +408,12 @@
407408
#define X86_FEATURE_ENQCMD (16*32+29) /* "enqcmd" ENQCMD and ENQCMDS instructions */
408409
#define X86_FEATURE_SGX_LC (16*32+30) /* "sgx_lc" Software Guard Extensions Launch Control */
409410

410-
/* AMD-defined CPU features, CPUID level 0x80000007 (EBX), word 17 */
411+
/*
412+
* Linux-defined word for use with scattered/synthetic bits.
413+
*/
411414
#define X86_FEATURE_OVERFLOW_RECOV (17*32+ 0) /* "overflow_recov" MCA overflow recovery support */
412415
#define X86_FEATURE_SUCCOR (17*32+ 1) /* "succor" Uncorrectable error containment and recovery */
416+
413417
#define X86_FEATURE_SMCA (17*32+ 3) /* "smca" Scalable MCA */
414418

415419
/* Intel-defined CPU features, CPUID level 0x00000007:0 (EDX), word 18 */

arch/x86/include/asm/smap.h

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,55 @@
2323

2424
#else /* __ASSEMBLER__ */
2525

26+
/*
27+
* The CLAC/STAC instructions toggle the enforcement of
28+
* X86_FEATURE_SMAP along with X86_FEATURE_LASS.
29+
*
30+
* SMAP enforcement is based on the _PAGE_BIT_USER bit in the page
31+
* tables. The kernel is not allowed to touch pages with that bit set
32+
* unless the AC bit is set.
33+
*
34+
* Use stac()/clac() when accessing userspace (_PAGE_USER) mappings,
35+
* regardless of location.
36+
*
37+
* Note: a barrier is implicit in alternative().
38+
*/
39+
2640
static __always_inline void clac(void)
2741
{
28-
/* Note: a barrier is implicit in alternative() */
2942
alternative("", "clac", X86_FEATURE_SMAP);
3043
}
3144

3245
static __always_inline void stac(void)
3346
{
34-
/* Note: a barrier is implicit in alternative() */
3547
alternative("", "stac", X86_FEATURE_SMAP);
3648
}
3749

50+
/*
51+
* LASS enforcement is based on bit 63 of the virtual address. The
52+
* kernel is not allowed to touch memory in the lower half of the
53+
* virtual address space.
54+
*
55+
* Use lass_stac()/lass_clac() to toggle the AC bit for kernel data
56+
* accesses (!_PAGE_USER) that are blocked by LASS, but not by SMAP.
57+
*
58+
* Even with the AC bit set, LASS will continue to block instruction
59+
* fetches from the user half of the address space. To allow those,
60+
* clear CR4.LASS to disable the LASS mechanism entirely.
61+
*
62+
* Note: a barrier is implicit in alternative().
63+
*/
64+
65+
static __always_inline void lass_clac(void)
66+
{
67+
alternative("", "clac", X86_FEATURE_LASS);
68+
}
69+
70+
static __always_inline void lass_stac(void)
71+
{
72+
alternative("", "stac", X86_FEATURE_LASS);
73+
}
74+
3875
static __always_inline unsigned long smap_save(void)
3976
{
4077
unsigned long flags;

arch/x86/include/asm/string.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,32 @@
11
/* SPDX-License-Identifier: GPL-2.0 */
2+
#ifndef _ASM_X86_STRING_H
3+
#define _ASM_X86_STRING_H
4+
25
#ifdef CONFIG_X86_32
36
# include <asm/string_32.h>
47
#else
58
# include <asm/string_64.h>
69
#endif
10+
11+
static __always_inline void *__inline_memcpy(void *to, const void *from, size_t len)
12+
{
13+
void *ret = to;
14+
15+
asm volatile("rep movsb"
16+
: "+D" (to), "+S" (from), "+c" (len)
17+
: : "memory");
18+
return ret;
19+
}
20+
21+
static __always_inline void *__inline_memset(void *s, int v, size_t n)
22+
{
23+
void *ret = s;
24+
25+
asm volatile("rep stosb"
26+
: "+D" (s), "+c" (n)
27+
: "a" ((uint8_t)v)
28+
: "memory");
29+
return ret;
30+
}
31+
32+
#endif /* _ASM_X86_STRING_H */

arch/x86/include/uapi/asm/processor-flags.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@
136136
#define X86_CR4_PKE _BITUL(X86_CR4_PKE_BIT)
137137
#define X86_CR4_CET_BIT 23 /* enable Control-flow Enforcement Technology */
138138
#define X86_CR4_CET _BITUL(X86_CR4_CET_BIT)
139+
#define X86_CR4_LASS_BIT 27 /* enable Linear Address Space Separation support */
140+
#define X86_CR4_LASS _BITUL(X86_CR4_LASS_BIT)
139141
#define X86_CR4_LAM_SUP_BIT 28 /* LAM for supervisor pointers */
140142
#define X86_CR4_LAM_SUP _BITUL(X86_CR4_LAM_SUP_BIT)
141143

arch/x86/kernel/alternative.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2453,16 +2453,30 @@ void __init_or_module text_poke_early(void *addr, const void *opcode,
24532453
__ro_after_init struct mm_struct *text_poke_mm;
24542454
__ro_after_init unsigned long text_poke_mm_addr;
24552455

2456+
/*
2457+
* Text poking creates and uses a mapping in the lower half of the
2458+
* address space. Relax LASS enforcement when accessing the poking
2459+
* address.
2460+
*
2461+
* objtool enforces a strict policy of "no function calls within AC=1
2462+
* regions". Adhere to the policy by using inline versions of
2463+
* memcpy()/memset() that will never result in a function call.
2464+
*/
2465+
24562466
static void text_poke_memcpy(void *dst, const void *src, size_t len)
24572467
{
2458-
memcpy(dst, src, len);
2468+
lass_stac();
2469+
__inline_memcpy(dst, src, len);
2470+
lass_clac();
24592471
}
24602472

24612473
static void text_poke_memset(void *dst, const void *src, size_t len)
24622474
{
24632475
int c = *(const int *)src;
24642476

2465-
memset(dst, c, len);
2477+
lass_stac();
2478+
__inline_memset(dst, c, len);
2479+
lass_clac();
24662480
}
24672481

24682482
typedef void text_poke_f(void *dst, const void *src, size_t len);

arch/x86/kernel/cpu/common.c

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,28 @@ static __always_inline void setup_umip(struct cpuinfo_x86 *c)
406406
cr4_clear_bits(X86_CR4_UMIP);
407407
}
408408

409+
static __always_inline void setup_lass(struct cpuinfo_x86 *c)
410+
{
411+
if (!cpu_feature_enabled(X86_FEATURE_LASS))
412+
return;
413+
414+
/*
415+
* Legacy vsyscall page access causes a #GP when LASS is active.
416+
* Disable LASS because the #GP handler doesn't support vsyscall
417+
* emulation.
418+
*
419+
* Also disable LASS when running under EFI, as some runtime and
420+
* boot services rely on 1:1 mappings in the lower half.
421+
*/
422+
if (IS_ENABLED(CONFIG_X86_VSYSCALL_EMULATION) ||
423+
IS_ENABLED(CONFIG_EFI)) {
424+
setup_clear_cpu_cap(X86_FEATURE_LASS);
425+
return;
426+
}
427+
428+
cr4_set_bits(X86_CR4_LASS);
429+
}
430+
409431
/* These bits should not change their value after CPU init is finished. */
410432
static const unsigned long cr4_pinned_mask = X86_CR4_SMEP | X86_CR4_SMAP | X86_CR4_UMIP |
411433
X86_CR4_FSGSBASE | X86_CR4_CET | X86_CR4_FRED;
@@ -1026,12 +1048,8 @@ void get_cpu_cap(struct cpuinfo_x86 *c)
10261048
c->x86_capability[CPUID_8000_0001_EDX] = edx;
10271049
}
10281050

1029-
if (c->extended_cpuid_level >= 0x80000007) {
1030-
cpuid(0x80000007, &eax, &ebx, &ecx, &edx);
1031-
1032-
c->x86_capability[CPUID_8000_0007_EBX] = ebx;
1033-
c->x86_power = edx;
1034-
}
1051+
if (c->extended_cpuid_level >= 0x80000007)
1052+
c->x86_power = cpuid_edx(0x80000007);
10351053

10361054
if (c->extended_cpuid_level >= 0x80000008) {
10371055
cpuid(0x80000008, &eax, &ebx, &ecx, &edx);
@@ -2016,10 +2034,10 @@ static void identify_cpu(struct cpuinfo_x86 *c)
20162034
/* Disable the PN if appropriate */
20172035
squash_the_stupid_serial_number(c);
20182036

2019-
/* Set up SMEP/SMAP/UMIP */
20202037
setup_smep(c);
20212038
setup_smap(c);
20222039
setup_umip(c);
2040+
setup_lass(c);
20232041

20242042
/* Enable FSGSBASE instructions if available. */
20252043
if (cpu_has(c, X86_FEATURE_FSGSBASE)) {

arch/x86/kernel/cpu/cpuid-deps.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ static const struct cpuid_dep cpuid_deps[] = {
9191
{ X86_FEATURE_SHSTK, X86_FEATURE_XSAVES },
9292
{ X86_FEATURE_FRED, X86_FEATURE_LKGS },
9393
{ X86_FEATURE_SPEC_CTRL_SSBD, X86_FEATURE_SPEC_CTRL },
94+
{ X86_FEATURE_LASS, X86_FEATURE_SMAP },
9495
{}
9596
};
9697

arch/x86/kernel/cpu/scattered.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ static const struct cpuid_bit cpuid_bits[] = {
4545
{ X86_FEATURE_SGX2, CPUID_EAX, 1, 0x00000012, 0 },
4646
{ X86_FEATURE_SGX_EUPDATESVN, CPUID_EAX, 10, 0x00000012, 0 },
4747
{ X86_FEATURE_SGX_EDECCSSA, CPUID_EAX, 11, 0x00000012, 0 },
48+
{ X86_FEATURE_OVERFLOW_RECOV, CPUID_EBX, 0, 0x80000007, 0 },
49+
{ X86_FEATURE_SUCCOR, CPUID_EBX, 1, 0x80000007, 0 },
50+
{ X86_FEATURE_SMCA, CPUID_EBX, 3, 0x80000007, 0 },
4851
{ X86_FEATURE_HW_PSTATE, CPUID_EDX, 7, 0x80000007, 0 },
4952
{ X86_FEATURE_CPB, CPUID_EDX, 9, 0x80000007, 0 },
5053
{ X86_FEATURE_PROC_FEEDBACK, CPUID_EDX, 11, 0x80000007, 0 },

0 commit comments

Comments
 (0)