Skip to content

Commit e0f4c59

Browse files
committed
Merge tag 'x86_cpu_for_v5.16_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 cpu updates from Borislav Petkov: - Start checking a CPUID bit on AMD Zen3 which states that the CPU clears the segment base when a null selector is written. Do the explicit detection on older CPUs, zen2 and hygon specifically, which have the functionality but do not advertize the CPUID bit. Factor in the presence of a hypervisor underneath the kernel and avoid doing the explicit check there which the HV might've decided to not advertize for migration safety reasons, or similar. - Add support for a new X86 CPU vendor: VORTEX. Needed for whitelisting those CPUs in the hardware vulnerabilities detection - Force the compiler to use rIP-relative addressing in the fallback path of static_cpu_has(), in order to avoid unnecessary register pressure * tag 'x86_cpu_for_v5.16_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/cpu: Fix migration safety with X86_BUG_NULL_SEL x86/CPU: Add support for Vortex CPUs x86/umip: Downgrade warning messages to debug loglevel x86/asm: Avoid adding register pressure for the init case in static_cpu_has() x86/asm: Add _ASM_RIP() macro for x86-64 (%rip) suffix
2 parents 18398bb + 415de44 commit e0f4c59

File tree

11 files changed

+117
-16
lines changed

11 files changed

+117
-16
lines changed

arch/x86/Kconfig.cpu

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,3 +508,16 @@ config CPU_SUP_ZHAOXIN
508508
CPU might render the kernel unbootable.
509509

510510
If unsure, say N.
511+
512+
config CPU_SUP_VORTEX_32
513+
default y
514+
bool "Support Vortex processors" if PROCESSOR_SELECT
515+
depends on X86_32
516+
help
517+
This enables detection, tunings and quirks for Vortex processors
518+
519+
You need this enabled if you want your kernel to run on a
520+
Vortex CPU. Disabling this option on other types of CPUs
521+
makes the kernel a tiny bit smaller.
522+
523+
If unsure, say N.

arch/x86/include/asm/asm.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@
66
# define __ASM_FORM(x, ...) x,## __VA_ARGS__
77
# define __ASM_FORM_RAW(x, ...) x,## __VA_ARGS__
88
# define __ASM_FORM_COMMA(x, ...) x,## __VA_ARGS__,
9+
# define __ASM_REGPFX %
910
#else
1011
#include <linux/stringify.h>
1112
# define __ASM_FORM(x, ...) " " __stringify(x,##__VA_ARGS__) " "
1213
# define __ASM_FORM_RAW(x, ...) __stringify(x,##__VA_ARGS__)
1314
# define __ASM_FORM_COMMA(x, ...) " " __stringify(x,##__VA_ARGS__) ","
15+
# define __ASM_REGPFX %%
1416
#endif
1517

1618
#define _ASM_BYTES(x, ...) __ASM_FORM(.byte x,##__VA_ARGS__ ;)
@@ -49,6 +51,9 @@
4951
#define _ASM_SI __ASM_REG(si)
5052
#define _ASM_DI __ASM_REG(di)
5153

54+
/* Adds a (%rip) suffix on 64 bits only; for immediate memory references */
55+
#define _ASM_RIP(x) __ASM_SEL_RAW(x, x (__ASM_REGPFX rip))
56+
5257
#ifndef __x86_64__
5358
/* 32 bit */
5459

arch/x86/include/asm/cpufeature.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -173,20 +173,25 @@ extern void clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int bit);
173173
* means that the boot_cpu_has() variant is already fast enough for the
174174
* majority of cases and you should stick to using it as it is generally
175175
* only two instructions: a RIP-relative MOV and a TEST.
176+
*
177+
* Do not use an "m" constraint for [cap_byte] here: gcc doesn't know
178+
* that this is only used on a fallback path and will sometimes cause
179+
* it to manifest the address of boot_cpu_data in a register, fouling
180+
* the mainline (post-initialization) code.
176181
*/
177182
static __always_inline bool _static_cpu_has(u16 bit)
178183
{
179184
asm_volatile_goto(
180185
ALTERNATIVE_TERNARY("jmp 6f", %P[feature], "", "jmp %l[t_no]")
181-
".section .altinstr_aux,\"ax\"\n"
186+
".pushsection .altinstr_aux,\"ax\"\n"
182187
"6:\n"
183-
" testb %[bitnum],%[cap_byte]\n"
188+
" testb %[bitnum]," _ASM_RIP(%P[cap_byte]) "\n"
184189
" jnz %l[t_yes]\n"
185190
" jmp %l[t_no]\n"
186-
".previous\n"
191+
".popsection\n"
187192
: : [feature] "i" (bit),
188193
[bitnum] "i" (1 << (bit & 7)),
189-
[cap_byte] "m" (((const char *)boot_cpu_data.x86_capability)[bit >> 3])
194+
[cap_byte] "i" (&((const char *)boot_cpu_data.x86_capability)[bit >> 3])
190195
: : t_yes, t_no);
191196
t_yes:
192197
return true;

arch/x86/include/asm/processor.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,8 @@ enum cpuid_regs_idx {
164164
#define X86_VENDOR_NSC 8
165165
#define X86_VENDOR_HYGON 9
166166
#define X86_VENDOR_ZHAOXIN 10
167-
#define X86_VENDOR_NUM 11
167+
#define X86_VENDOR_VORTEX 11
168+
#define X86_VENDOR_NUM 12
168169

169170
#define X86_VENDOR_UNKNOWN 0xff
170171

arch/x86/kernel/cpu/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ obj-$(CONFIG_CPU_SUP_CENTAUR) += centaur.o
4343
obj-$(CONFIG_CPU_SUP_TRANSMETA_32) += transmeta.o
4444
obj-$(CONFIG_CPU_SUP_UMC_32) += umc.o
4545
obj-$(CONFIG_CPU_SUP_ZHAOXIN) += zhaoxin.o
46+
obj-$(CONFIG_CPU_SUP_VORTEX_32) += vortex.o
4647

4748
obj-$(CONFIG_X86_MCE) += mce/
4849
obj-$(CONFIG_MTRR) += mtrr/

arch/x86/kernel/cpu/amd.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -989,6 +989,8 @@ static void init_amd(struct cpuinfo_x86 *c)
989989
if (cpu_has(c, X86_FEATURE_IRPERF) &&
990990
!cpu_has_amd_erratum(c, amd_erratum_1054))
991991
msr_set_bit(MSR_K7_HWCR, MSR_K7_HWCR_IRPERF_EN_BIT);
992+
993+
check_null_seg_clears_base(c);
992994
}
993995

994996
#ifdef CONFIG_X86_32

arch/x86/kernel/cpu/common.c

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1048,6 +1048,8 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = {
10481048
VULNWL(CENTAUR, 5, X86_MODEL_ANY, NO_SPECULATION),
10491049
VULNWL(INTEL, 5, X86_MODEL_ANY, NO_SPECULATION),
10501050
VULNWL(NSC, 5, X86_MODEL_ANY, NO_SPECULATION),
1051+
VULNWL(VORTEX, 5, X86_MODEL_ANY, NO_SPECULATION),
1052+
VULNWL(VORTEX, 6, X86_MODEL_ANY, NO_SPECULATION),
10511053

10521054
/* Intel Family 6 */
10531055
VULNWL_INTEL(ATOM_SALTWELL, NO_SPECULATION | NO_ITLB_MULTIHIT),
@@ -1399,9 +1401,8 @@ void __init early_cpu_init(void)
13991401
early_identify_cpu(&boot_cpu_data);
14001402
}
14011403

1402-
static void detect_null_seg_behavior(struct cpuinfo_x86 *c)
1404+
static bool detect_null_seg_behavior(void)
14031405
{
1404-
#ifdef CONFIG_X86_64
14051406
/*
14061407
* Empirically, writing zero to a segment selector on AMD does
14071408
* not clear the base, whereas writing zero to a segment
@@ -1422,10 +1423,43 @@ static void detect_null_seg_behavior(struct cpuinfo_x86 *c)
14221423
wrmsrl(MSR_FS_BASE, 1);
14231424
loadsegment(fs, 0);
14241425
rdmsrl(MSR_FS_BASE, tmp);
1425-
if (tmp != 0)
1426-
set_cpu_bug(c, X86_BUG_NULL_SEG);
14271426
wrmsrl(MSR_FS_BASE, old_base);
1428-
#endif
1427+
return tmp == 0;
1428+
}
1429+
1430+
void check_null_seg_clears_base(struct cpuinfo_x86 *c)
1431+
{
1432+
/* BUG_NULL_SEG is only relevant with 64bit userspace */
1433+
if (!IS_ENABLED(CONFIG_X86_64))
1434+
return;
1435+
1436+
/* Zen3 CPUs advertise Null Selector Clears Base in CPUID. */
1437+
if (c->extended_cpuid_level >= 0x80000021 &&
1438+
cpuid_eax(0x80000021) & BIT(6))
1439+
return;
1440+
1441+
/*
1442+
* CPUID bit above wasn't set. If this kernel is still running
1443+
* as a HV guest, then the HV has decided not to advertize
1444+
* that CPUID bit for whatever reason. For example, one
1445+
* member of the migration pool might be vulnerable. Which
1446+
* means, the bug is present: set the BUG flag and return.
1447+
*/
1448+
if (cpu_has(c, X86_FEATURE_HYPERVISOR)) {
1449+
set_cpu_bug(c, X86_BUG_NULL_SEG);
1450+
return;
1451+
}
1452+
1453+
/*
1454+
* Zen2 CPUs also have this behaviour, but no CPUID bit.
1455+
* 0x18 is the respective family for Hygon.
1456+
*/
1457+
if ((c->x86 == 0x17 || c->x86 == 0x18) &&
1458+
detect_null_seg_behavior())
1459+
return;
1460+
1461+
/* All the remaining ones are affected */
1462+
set_cpu_bug(c, X86_BUG_NULL_SEG);
14291463
}
14301464

14311465
static void generic_identify(struct cpuinfo_x86 *c)
@@ -1461,8 +1495,6 @@ static void generic_identify(struct cpuinfo_x86 *c)
14611495

14621496
get_model_name(c); /* Default name */
14631497

1464-
detect_null_seg_behavior(c);
1465-
14661498
/*
14671499
* ESPFIX is a strange bug. All real CPUs have it. Paravirt
14681500
* systems that run Linux at CPL > 0 may or may not have the

arch/x86/kernel/cpu/cpu.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ extern int detect_extended_topology_early(struct cpuinfo_x86 *c);
7575
extern int detect_extended_topology(struct cpuinfo_x86 *c);
7676
extern int detect_ht_early(struct cpuinfo_x86 *c);
7777
extern void detect_ht(struct cpuinfo_x86 *c);
78+
extern void check_null_seg_clears_base(struct cpuinfo_x86 *c);
7879

7980
unsigned int aperfmperf_get_khz(int cpu);
8081

arch/x86/kernel/cpu/hygon.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,8 @@ static void init_hygon(struct cpuinfo_x86 *c)
335335
/* Hygon CPUs don't reset SS attributes on SYSRET, Xen does. */
336336
if (!cpu_has(c, X86_FEATURE_XENPV))
337337
set_cpu_bug(c, X86_BUG_SYSRET_SS_ATTRS);
338+
339+
check_null_seg_clears_base(c);
338340
}
339341

340342
static void cpu_detect_tlb_hygon(struct cpuinfo_x86 *c)

arch/x86/kernel/cpu/vortex.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
#include <linux/kernel.h>
3+
#include <asm/processor.h>
4+
#include "cpu.h"
5+
6+
/*
7+
* No special init required for Vortex processors.
8+
*/
9+
10+
static const struct cpu_dev vortex_cpu_dev = {
11+
.c_vendor = "Vortex",
12+
.c_ident = { "Vortex86 SoC" },
13+
.legacy_models = {
14+
{
15+
.family = 5,
16+
.model_names = {
17+
[2] = "Vortex86DX",
18+
[8] = "Vortex86MX",
19+
},
20+
},
21+
{
22+
.family = 6,
23+
.model_names = {
24+
/*
25+
* Both the Vortex86EX and the Vortex86EX2
26+
* have the same family and model id.
27+
*
28+
* However, the -EX2 supports the product name
29+
* CPUID call, so this name will only be used
30+
* for the -EX, which does not.
31+
*/
32+
[0] = "Vortex86EX",
33+
},
34+
},
35+
},
36+
.c_x86_vendor = X86_VENDOR_VORTEX,
37+
};
38+
39+
cpu_dev_register(vortex_cpu_dev);

0 commit comments

Comments
 (0)