Skip to content

Commit a141fd5

Browse files
committed
Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 fixes from Ingo Molnar: "Another round of CR3/PCID related fixes (I think this addresses all but one of the known problems with PCID support), an objtool fix plus a Clang fix that (finally) solves all Clang quirks to build a bootable x86 kernel as-is" * 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/asm: Fix inline asm call constraints for Clang objtool: Handle another GCC stack pointer adjustment bug x86/mm/32: Load a sane CR3 before cpu_init() on secondary CPUs x86/mm/32: Move setup_clear_cpu_cap(X86_FEATURE_PCID) earlier x86/mm/64: Stop using CR3.PCID == 0 in ASID-aware code x86/mm: Factor out CR3-building code
2 parents 16528a3 + f5caf62 commit a141fd5

File tree

20 files changed

+122
-86
lines changed

20 files changed

+122
-86
lines changed

arch/x86/include/asm/alternative.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,10 +218,9 @@ static inline int alternatives_text_reserved(void *start, void *end)
218218
#define alternative_call_2(oldfunc, newfunc1, feature1, newfunc2, feature2, \
219219
output, input...) \
220220
{ \
221-
register void *__sp asm(_ASM_SP); \
222221
asm volatile (ALTERNATIVE_2("call %P[old]", "call %P[new1]", feature1,\
223222
"call %P[new2]", feature2) \
224-
: output, "+r" (__sp) \
223+
: output, ASM_CALL_CONSTRAINT \
225224
: [old] "i" (oldfunc), [new1] "i" (newfunc1), \
226225
[new2] "i" (newfunc2), ## input); \
227226
}

arch/x86/include/asm/asm.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,4 +132,15 @@
132132
/* For C file, we already have NOKPROBE_SYMBOL macro */
133133
#endif
134134

135+
#ifndef __ASSEMBLY__
136+
/*
137+
* This output constraint should be used for any inline asm which has a "call"
138+
* instruction. Otherwise the asm may be inserted before the frame pointer
139+
* gets set up by the containing function. If you forget to do this, objtool
140+
* may print a "call without frame pointer save/setup" warning.
141+
*/
142+
register unsigned int __asm_call_sp asm("esp");
143+
#define ASM_CALL_CONSTRAINT "+r" (__asm_call_sp)
144+
#endif
145+
135146
#endif /* _ASM_X86_ASM_H */

arch/x86/include/asm/mmu_context.h

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,32 @@ static inline bool arch_vma_access_permitted(struct vm_area_struct *vma,
286286
return __pkru_allows_pkey(vma_pkey(vma), write);
287287
}
288288

289+
/*
290+
* If PCID is on, ASID-aware code paths put the ASID+1 into the PCID
291+
* bits. This serves two purposes. It prevents a nasty situation in
292+
* which PCID-unaware code saves CR3, loads some other value (with PCID
293+
* == 0), and then restores CR3, thus corrupting the TLB for ASID 0 if
294+
* the saved ASID was nonzero. It also means that any bugs involving
295+
* loading a PCID-enabled CR3 with CR4.PCIDE off will trigger
296+
* deterministically.
297+
*/
298+
299+
static inline unsigned long build_cr3(struct mm_struct *mm, u16 asid)
300+
{
301+
if (static_cpu_has(X86_FEATURE_PCID)) {
302+
VM_WARN_ON_ONCE(asid > 4094);
303+
return __sme_pa(mm->pgd) | (asid + 1);
304+
} else {
305+
VM_WARN_ON_ONCE(asid != 0);
306+
return __sme_pa(mm->pgd);
307+
}
308+
}
309+
310+
static inline unsigned long build_cr3_noflush(struct mm_struct *mm, u16 asid)
311+
{
312+
VM_WARN_ON_ONCE(asid > 4094);
313+
return __sme_pa(mm->pgd) | (asid + 1) | CR3_NOFLUSH;
314+
}
289315

290316
/*
291317
* This can be used from process context to figure out what the value of
@@ -296,10 +322,8 @@ static inline bool arch_vma_access_permitted(struct vm_area_struct *vma,
296322
*/
297323
static inline unsigned long __get_current_cr3_fast(void)
298324
{
299-
unsigned long cr3 = __pa(this_cpu_read(cpu_tlbstate.loaded_mm)->pgd);
300-
301-
if (static_cpu_has(X86_FEATURE_PCID))
302-
cr3 |= this_cpu_read(cpu_tlbstate.loaded_mm_asid);
325+
unsigned long cr3 = build_cr3(this_cpu_read(cpu_tlbstate.loaded_mm),
326+
this_cpu_read(cpu_tlbstate.loaded_mm_asid));
303327

304328
/* For now, be very restrictive about when this can be called. */
305329
VM_WARN_ON(in_nmi() || preemptible());

arch/x86/include/asm/mshyperv.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -179,15 +179,14 @@ static inline u64 hv_do_hypercall(u64 control, void *input, void *output)
179179
u64 input_address = input ? virt_to_phys(input) : 0;
180180
u64 output_address = output ? virt_to_phys(output) : 0;
181181
u64 hv_status;
182-
register void *__sp asm(_ASM_SP);
183182

184183
#ifdef CONFIG_X86_64
185184
if (!hv_hypercall_pg)
186185
return U64_MAX;
187186

188187
__asm__ __volatile__("mov %4, %%r8\n"
189188
"call *%5"
190-
: "=a" (hv_status), "+r" (__sp),
189+
: "=a" (hv_status), ASM_CALL_CONSTRAINT,
191190
"+c" (control), "+d" (input_address)
192191
: "r" (output_address), "m" (hv_hypercall_pg)
193192
: "cc", "memory", "r8", "r9", "r10", "r11");
@@ -202,7 +201,7 @@ static inline u64 hv_do_hypercall(u64 control, void *input, void *output)
202201

203202
__asm__ __volatile__("call *%7"
204203
: "=A" (hv_status),
205-
"+c" (input_address_lo), "+r" (__sp)
204+
"+c" (input_address_lo), ASM_CALL_CONSTRAINT
206205
: "A" (control),
207206
"b" (input_address_hi),
208207
"D"(output_address_hi), "S"(output_address_lo),
@@ -224,12 +223,11 @@ static inline u64 hv_do_hypercall(u64 control, void *input, void *output)
224223
static inline u64 hv_do_fast_hypercall8(u16 code, u64 input1)
225224
{
226225
u64 hv_status, control = (u64)code | HV_HYPERCALL_FAST_BIT;
227-
register void *__sp asm(_ASM_SP);
228226

229227
#ifdef CONFIG_X86_64
230228
{
231229
__asm__ __volatile__("call *%4"
232-
: "=a" (hv_status), "+r" (__sp),
230+
: "=a" (hv_status), ASM_CALL_CONSTRAINT,
233231
"+c" (control), "+d" (input1)
234232
: "m" (hv_hypercall_pg)
235233
: "cc", "r8", "r9", "r10", "r11");
@@ -242,7 +240,7 @@ static inline u64 hv_do_fast_hypercall8(u16 code, u64 input1)
242240
__asm__ __volatile__ ("call *%5"
243241
: "=A"(hv_status),
244242
"+c"(input1_lo),
245-
"+r"(__sp)
243+
ASM_CALL_CONSTRAINT
246244
: "A" (control),
247245
"b" (input1_hi),
248246
"m" (hv_hypercall_pg)

arch/x86/include/asm/paravirt_types.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -459,8 +459,8 @@ int paravirt_disable_iospace(void);
459459
*/
460460
#ifdef CONFIG_X86_32
461461
#define PVOP_VCALL_ARGS \
462-
unsigned long __eax = __eax, __edx = __edx, __ecx = __ecx; \
463-
register void *__sp asm("esp")
462+
unsigned long __eax = __eax, __edx = __edx, __ecx = __ecx;
463+
464464
#define PVOP_CALL_ARGS PVOP_VCALL_ARGS
465465

466466
#define PVOP_CALL_ARG1(x) "a" ((unsigned long)(x))
@@ -480,8 +480,8 @@ int paravirt_disable_iospace(void);
480480
/* [re]ax isn't an arg, but the return val */
481481
#define PVOP_VCALL_ARGS \
482482
unsigned long __edi = __edi, __esi = __esi, \
483-
__edx = __edx, __ecx = __ecx, __eax = __eax; \
484-
register void *__sp asm("rsp")
483+
__edx = __edx, __ecx = __ecx, __eax = __eax;
484+
485485
#define PVOP_CALL_ARGS PVOP_VCALL_ARGS
486486

487487
#define PVOP_CALL_ARG1(x) "D" ((unsigned long)(x))
@@ -532,7 +532,7 @@ int paravirt_disable_iospace(void);
532532
asm volatile(pre \
533533
paravirt_alt(PARAVIRT_CALL) \
534534
post \
535-
: call_clbr, "+r" (__sp) \
535+
: call_clbr, ASM_CALL_CONSTRAINT \
536536
: paravirt_type(op), \
537537
paravirt_clobber(clbr), \
538538
##__VA_ARGS__ \
@@ -542,7 +542,7 @@ int paravirt_disable_iospace(void);
542542
asm volatile(pre \
543543
paravirt_alt(PARAVIRT_CALL) \
544544
post \
545-
: call_clbr, "+r" (__sp) \
545+
: call_clbr, ASM_CALL_CONSTRAINT \
546546
: paravirt_type(op), \
547547
paravirt_clobber(clbr), \
548548
##__VA_ARGS__ \
@@ -569,7 +569,7 @@ int paravirt_disable_iospace(void);
569569
asm volatile(pre \
570570
paravirt_alt(PARAVIRT_CALL) \
571571
post \
572-
: call_clbr, "+r" (__sp) \
572+
: call_clbr, ASM_CALL_CONSTRAINT \
573573
: paravirt_type(op), \
574574
paravirt_clobber(clbr), \
575575
##__VA_ARGS__ \

arch/x86/include/asm/preempt.h

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -100,19 +100,14 @@ static __always_inline bool should_resched(int preempt_offset)
100100

101101
#ifdef CONFIG_PREEMPT
102102
extern asmlinkage void ___preempt_schedule(void);
103-
# define __preempt_schedule() \
104-
({ \
105-
register void *__sp asm(_ASM_SP); \
106-
asm volatile ("call ___preempt_schedule" : "+r"(__sp)); \
107-
})
103+
# define __preempt_schedule() \
104+
asm volatile ("call ___preempt_schedule" : ASM_CALL_CONSTRAINT)
108105

109106
extern asmlinkage void preempt_schedule(void);
110107
extern asmlinkage void ___preempt_schedule_notrace(void);
111-
# define __preempt_schedule_notrace() \
112-
({ \
113-
register void *__sp asm(_ASM_SP); \
114-
asm volatile ("call ___preempt_schedule_notrace" : "+r"(__sp)); \
115-
})
108+
# define __preempt_schedule_notrace() \
109+
asm volatile ("call ___preempt_schedule_notrace" : ASM_CALL_CONSTRAINT)
110+
116111
extern asmlinkage void preempt_schedule_notrace(void);
117112
#endif
118113

arch/x86/include/asm/processor.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -677,16 +677,14 @@ static inline void sync_core(void)
677677
* Like all of Linux's memory ordering operations, this is a
678678
* compiler barrier as well.
679679
*/
680-
register void *__sp asm(_ASM_SP);
681-
682680
#ifdef CONFIG_X86_32
683681
asm volatile (
684682
"pushfl\n\t"
685683
"pushl %%cs\n\t"
686684
"pushl $1f\n\t"
687685
"iret\n\t"
688686
"1:"
689-
: "+r" (__sp) : : "memory");
687+
: ASM_CALL_CONSTRAINT : : "memory");
690688
#else
691689
unsigned int tmp;
692690

@@ -703,7 +701,7 @@ static inline void sync_core(void)
703701
"iretq\n\t"
704702
UNWIND_HINT_RESTORE
705703
"1:"
706-
: "=&r" (tmp), "+r" (__sp) : : "cc", "memory");
704+
: "=&r" (tmp), ASM_CALL_CONSTRAINT : : "cc", "memory");
707705
#endif
708706
}
709707

arch/x86/include/asm/rwsem.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,6 @@ static inline bool __down_read_trylock(struct rw_semaphore *sem)
103103
({ \
104104
long tmp; \
105105
struct rw_semaphore* ret; \
106-
register void *__sp asm(_ASM_SP); \
107106
\
108107
asm volatile("# beginning down_write\n\t" \
109108
LOCK_PREFIX " xadd %1,(%4)\n\t" \
@@ -114,7 +113,8 @@ static inline bool __down_read_trylock(struct rw_semaphore *sem)
114113
" call " slow_path "\n" \
115114
"1:\n" \
116115
"# ending down_write" \
117-
: "+m" (sem->count), "=d" (tmp), "=a" (ret), "+r" (__sp) \
116+
: "+m" (sem->count), "=d" (tmp), \
117+
"=a" (ret), ASM_CALL_CONSTRAINT \
118118
: "a" (sem), "1" (RWSEM_ACTIVE_WRITE_BIAS) \
119119
: "memory", "cc"); \
120120
ret; \

arch/x86/include/asm/uaccess.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,11 +166,11 @@ __typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL))
166166
({ \
167167
int __ret_gu; \
168168
register __inttype(*(ptr)) __val_gu asm("%"_ASM_DX); \
169-
register void *__sp asm(_ASM_SP); \
170169
__chk_user_ptr(ptr); \
171170
might_fault(); \
172171
asm volatile("call __get_user_%P4" \
173-
: "=a" (__ret_gu), "=r" (__val_gu), "+r" (__sp) \
172+
: "=a" (__ret_gu), "=r" (__val_gu), \
173+
ASM_CALL_CONSTRAINT \
174174
: "0" (ptr), "i" (sizeof(*(ptr)))); \
175175
(x) = (__force __typeof__(*(ptr))) __val_gu; \
176176
__builtin_expect(__ret_gu, 0); \

arch/x86/include/asm/xen/hypercall.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,9 @@ extern struct { char _entry[32]; } hypercall_page[];
113113
register unsigned long __arg2 asm(__HYPERCALL_ARG2REG) = __arg2; \
114114
register unsigned long __arg3 asm(__HYPERCALL_ARG3REG) = __arg3; \
115115
register unsigned long __arg4 asm(__HYPERCALL_ARG4REG) = __arg4; \
116-
register unsigned long __arg5 asm(__HYPERCALL_ARG5REG) = __arg5; \
117-
register void *__sp asm(_ASM_SP);
116+
register unsigned long __arg5 asm(__HYPERCALL_ARG5REG) = __arg5;
118117

119-
#define __HYPERCALL_0PARAM "=r" (__res), "+r" (__sp)
118+
#define __HYPERCALL_0PARAM "=r" (__res), ASM_CALL_CONSTRAINT
120119
#define __HYPERCALL_1PARAM __HYPERCALL_0PARAM, "+r" (__arg1)
121120
#define __HYPERCALL_2PARAM __HYPERCALL_1PARAM, "+r" (__arg2)
122121
#define __HYPERCALL_3PARAM __HYPERCALL_2PARAM, "+r" (__arg3)

arch/x86/kernel/cpu/bugs.c

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,6 @@
2121

2222
void __init check_bugs(void)
2323
{
24-
#ifdef CONFIG_X86_32
25-
/*
26-
* Regardless of whether PCID is enumerated, the SDM says
27-
* that it can't be enabled in 32-bit mode.
28-
*/
29-
setup_clear_cpu_cap(X86_FEATURE_PCID);
30-
#endif
31-
3224
identify_boot_cpu();
3325

3426
if (!IS_ENABLED(CONFIG_SMP)) {

arch/x86/kernel/cpu/common.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -904,6 +904,14 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)
904904

905905
setup_force_cpu_cap(X86_FEATURE_ALWAYS);
906906
fpu__init_system(c);
907+
908+
#ifdef CONFIG_X86_32
909+
/*
910+
* Regardless of whether PCID is enumerated, the SDM says
911+
* that it can't be enabled in 32-bit mode.
912+
*/
913+
setup_clear_cpu_cap(X86_FEATURE_PCID);
914+
#endif
907915
}
908916

909917
void __init early_cpu_init(void)

arch/x86/kernel/smpboot.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -232,19 +232,20 @@ static void notrace start_secondary(void *unused)
232232
*/
233233
if (boot_cpu_has(X86_FEATURE_PCID))
234234
__write_cr4(__read_cr4() | X86_CR4_PCIDE);
235-
cpu_init();
236-
x86_cpuinit.early_percpu_clock_init();
237-
preempt_disable();
238-
smp_callin();
239-
240-
enable_start_cpu0 = 0;
241235

242236
#ifdef CONFIG_X86_32
243237
/* switch away from the initial page table */
244238
load_cr3(swapper_pg_dir);
245239
__flush_tlb_all();
246240
#endif
247241

242+
cpu_init();
243+
x86_cpuinit.early_percpu_clock_init();
244+
preempt_disable();
245+
smp_callin();
246+
247+
enable_start_cpu0 = 0;
248+
248249
/* otherwise gcc will move up smp_processor_id before the cpu_init */
249250
barrier();
250251
/*

arch/x86/kvm/emulate.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5298,15 +5298,14 @@ static void fetch_possible_mmx_operand(struct x86_emulate_ctxt *ctxt,
52985298

52995299
static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *))
53005300
{
5301-
register void *__sp asm(_ASM_SP);
53025301
ulong flags = (ctxt->eflags & EFLAGS_MASK) | X86_EFLAGS_IF;
53035302

53045303
if (!(ctxt->d & ByteOp))
53055304
fop += __ffs(ctxt->dst.bytes) * FASTOP_SIZE;
53065305

53075306
asm("push %[flags]; popf; call *%[fastop]; pushf; pop %[flags]\n"
53085307
: "+a"(ctxt->dst.val), "+d"(ctxt->src.val), [flags]"+D"(flags),
5309-
[fastop]"+S"(fop), "+r"(__sp)
5308+
[fastop]"+S"(fop), ASM_CALL_CONSTRAINT
53105309
: "c"(ctxt->src2.val));
53115310

53125311
ctxt->eflags = (ctxt->eflags & ~EFLAGS_MASK) | (flags & EFLAGS_MASK);

arch/x86/kvm/vmx.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9045,7 +9045,6 @@ static void vmx_complete_atomic_exit(struct vcpu_vmx *vmx)
90459045
static void vmx_handle_external_intr(struct kvm_vcpu *vcpu)
90469046
{
90479047
u32 exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
9048-
register void *__sp asm(_ASM_SP);
90499048

90509049
if ((exit_intr_info & (INTR_INFO_VALID_MASK | INTR_INFO_INTR_TYPE_MASK))
90519050
== (INTR_INFO_VALID_MASK | INTR_TYPE_EXT_INTR)) {
@@ -9074,7 +9073,7 @@ static void vmx_handle_external_intr(struct kvm_vcpu *vcpu)
90749073
#ifdef CONFIG_X86_64
90759074
[sp]"=&r"(tmp),
90769075
#endif
9077-
"+r"(__sp)
9076+
ASM_CALL_CONSTRAINT
90789077
:
90799078
[entry]"r"(entry),
90809079
[ss]"i"(__KERNEL_DS),

arch/x86/mm/fault.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -806,7 +806,6 @@ no_context(struct pt_regs *regs, unsigned long error_code,
806806
if (is_vmalloc_addr((void *)address) &&
807807
(((unsigned long)tsk->stack - 1 - address < PAGE_SIZE) ||
808808
address - ((unsigned long)tsk->stack + THREAD_SIZE) < PAGE_SIZE)) {
809-
register void *__sp asm("rsp");
810809
unsigned long stack = this_cpu_read(orig_ist.ist[DOUBLEFAULT_STACK]) - sizeof(void *);
811810
/*
812811
* We're likely to be running with very little stack space
@@ -821,7 +820,7 @@ no_context(struct pt_regs *regs, unsigned long error_code,
821820
asm volatile ("movq %[stack], %%rsp\n\t"
822821
"call handle_stack_overflow\n\t"
823822
"1: jmp 1b"
824-
: "+r" (__sp)
823+
: ASM_CALL_CONSTRAINT
825824
: "D" ("kernel stack overflow (page fault)"),
826825
"S" (regs), "d" (address),
827826
[stack] "rm" (stack));

0 commit comments

Comments
 (0)