Skip to content

Commit 42b682a

Browse files
committed
Merge tag 'x86_asm_for_v5.19_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 asm updates from Borislav Petkov: - A bunch of changes towards streamlining low level asm helpers' calling conventions so that former can be converted to C eventually - Simplify PUSH_AND_CLEAR_REGS so that it can be used at the system call entry paths instead of having opencoded, slightly different variants of it everywhere - Misc other fixes * tag 'x86_asm_for_v5.19_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/entry: Fix register corruption in compat syscall objtool: Fix STACK_FRAME_NON_STANDARD reloc type linkage: Fix issue with missing symbol size x86/entry: Remove skip_r11rcx x86/entry: Use PUSH_AND_CLEAR_REGS for compat x86/entry: Simplify entry_INT80_compat() x86/mm: Simplify RESERVE_BRK() x86/entry: Convert SWAPGS to swapgs and remove the definition of SWAPGS x86/entry: Don't call error_entry() for XENPV x86/entry: Move CLD to the start of the idtentry macro x86/entry: Move PUSH_AND_CLEAR_REGS out of error_entry() x86/entry: Switch the stack after error_entry() returns x86/traps: Use pt_regs directly in fixup_bad_iret()
2 parents c5a3d3c + 036c07c commit 42b682a

File tree

10 files changed

+86
-177
lines changed

10 files changed

+86
-177
lines changed

arch/x86/entry/calling.h

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ For 32-bit we have the following conventions - kernel is built with
6363
* for assembly code:
6464
*/
6565

66-
.macro PUSH_REGS rdx=%rdx rax=%rax save_ret=0
66+
.macro PUSH_REGS rdx=%rdx rcx=%rcx rax=%rax save_ret=0
6767
.if \save_ret
6868
pushq %rsi /* pt_regs->si */
6969
movq 8(%rsp), %rsi /* temporarily store the return address in %rsi */
@@ -73,7 +73,7 @@ For 32-bit we have the following conventions - kernel is built with
7373
pushq %rsi /* pt_regs->si */
7474
.endif
7575
pushq \rdx /* pt_regs->dx */
76-
pushq %rcx /* pt_regs->cx */
76+
pushq \rcx /* pt_regs->cx */
7777
pushq \rax /* pt_regs->ax */
7878
pushq %r8 /* pt_regs->r8 */
7979
pushq %r9 /* pt_regs->r9 */
@@ -99,6 +99,7 @@ For 32-bit we have the following conventions - kernel is built with
9999
* well before they could be put to use in a speculative execution
100100
* gadget.
101101
*/
102+
xorl %esi, %esi /* nospec si */
102103
xorl %edx, %edx /* nospec dx */
103104
xorl %ecx, %ecx /* nospec cx */
104105
xorl %r8d, %r8d /* nospec r8 */
@@ -114,32 +115,24 @@ For 32-bit we have the following conventions - kernel is built with
114115

115116
.endm
116117

117-
.macro PUSH_AND_CLEAR_REGS rdx=%rdx rax=%rax save_ret=0
118-
PUSH_REGS rdx=\rdx, rax=\rax, save_ret=\save_ret
118+
.macro PUSH_AND_CLEAR_REGS rdx=%rdx rcx=%rcx rax=%rax save_ret=0
119+
PUSH_REGS rdx=\rdx, rcx=\rcx, rax=\rax, save_ret=\save_ret
119120
CLEAR_REGS
120121
.endm
121122

122-
.macro POP_REGS pop_rdi=1 skip_r11rcx=0
123+
.macro POP_REGS pop_rdi=1
123124
popq %r15
124125
popq %r14
125126
popq %r13
126127
popq %r12
127128
popq %rbp
128129
popq %rbx
129-
.if \skip_r11rcx
130-
popq %rsi
131-
.else
132130
popq %r11
133-
.endif
134131
popq %r10
135132
popq %r9
136133
popq %r8
137134
popq %rax
138-
.if \skip_r11rcx
139-
popq %rsi
140-
.else
141135
popq %rcx
142-
.endif
143136
popq %rdx
144137
popq %rsi
145138
.if \pop_rdi

arch/x86/entry/entry_64.S

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,7 @@ SYM_INNER_LABEL(entry_SYSCALL_64_after_hwframe, SYM_L_GLOBAL)
191191
* perf profiles. Nothing jumps here.
192192
*/
193193
syscall_return_via_sysret:
194-
/* rcx and r11 are already restored (see code above) */
195-
POP_REGS pop_rdi=0 skip_r11rcx=1
194+
POP_REGS pop_rdi=0
196195

197196
/*
198197
* Now all regs are restored except RSP and RDI.
@@ -323,14 +322,36 @@ SYM_CODE_END(ret_from_fork)
323322
#endif
324323
.endm
325324

325+
/* Save all registers in pt_regs */
326+
SYM_CODE_START_LOCAL(push_and_clear_regs)
327+
UNWIND_HINT_FUNC
328+
PUSH_AND_CLEAR_REGS save_ret=1
329+
ENCODE_FRAME_POINTER 8
330+
RET
331+
SYM_CODE_END(push_and_clear_regs)
332+
326333
/**
327334
* idtentry_body - Macro to emit code calling the C function
328335
* @cfunc: C function to be called
329336
* @has_error_code: Hardware pushed error code on stack
330337
*/
331338
.macro idtentry_body cfunc has_error_code:req
332339

333-
call error_entry
340+
call push_and_clear_regs
341+
UNWIND_HINT_REGS
342+
343+
/*
344+
* Call error_entry() and switch to the task stack if from userspace.
345+
*
346+
* When in XENPV, it is already in the task stack, and it can't fault
347+
* for native_iret() nor native_load_gs_index() since XENPV uses its
348+
* own pvops for IRET and load_gs_index(). And it doesn't need to
349+
* switch the CR3. So it can skip invoking error_entry().
350+
*/
351+
ALTERNATIVE "call error_entry; movq %rax, %rsp", \
352+
"", X86_FEATURE_XENPV
353+
354+
ENCODE_FRAME_POINTER
334355
UNWIND_HINT_REGS
335356

336357
movq %rsp, %rdi /* pt_regs pointer into 1st argument*/
@@ -363,6 +384,7 @@ SYM_CODE_START(\asmsym)
363384
UNWIND_HINT_IRET_REGS offset=\has_error_code*8
364385
ENDBR
365386
ASM_CLAC
387+
cld
366388

367389
.if \has_error_code == 0
368390
pushq $-1 /* ORIG_RAX: no syscall to restart */
@@ -431,6 +453,7 @@ SYM_CODE_START(\asmsym)
431453
UNWIND_HINT_IRET_REGS
432454
ENDBR
433455
ASM_CLAC
456+
cld
434457

435458
pushq $-1 /* ORIG_RAX: no syscall to restart */
436459

@@ -487,6 +510,7 @@ SYM_CODE_START(\asmsym)
487510
UNWIND_HINT_IRET_REGS
488511
ENDBR
489512
ASM_CLAC
513+
cld
490514

491515
/*
492516
* If the entry is from userspace, switch stacks and treat it as
@@ -550,6 +574,7 @@ SYM_CODE_START(\asmsym)
550574
UNWIND_HINT_IRET_REGS offset=8
551575
ENDBR
552576
ASM_CLAC
577+
cld
553578

554579
/* paranoid_entry returns GS information for paranoid_exit in EBX. */
555580
call paranoid_entry
@@ -875,7 +900,6 @@ SYM_CODE_END(xen_failsafe_callback)
875900
*/
876901
SYM_CODE_START_LOCAL(paranoid_entry)
877902
UNWIND_HINT_FUNC
878-
cld
879903
PUSH_AND_CLEAR_REGS save_ret=1
880904
ENCODE_FRAME_POINTER 8
881905

@@ -989,33 +1013,26 @@ SYM_CODE_START_LOCAL(paranoid_exit)
9891013
SYM_CODE_END(paranoid_exit)
9901014

9911015
/*
992-
* Save all registers in pt_regs, and switch GS if needed.
1016+
* Switch GS and CR3 if needed.
9931017
*/
9941018
SYM_CODE_START_LOCAL(error_entry)
9951019
UNWIND_HINT_FUNC
996-
cld
997-
PUSH_AND_CLEAR_REGS save_ret=1
998-
ENCODE_FRAME_POINTER 8
9991020
testb $3, CS+8(%rsp)
10001021
jz .Lerror_kernelspace
10011022

10021023
/*
10031024
* We entered from user mode or we're pretending to have entered
10041025
* from user mode due to an IRET fault.
10051026
*/
1006-
SWAPGS
1027+
swapgs
10071028
FENCE_SWAPGS_USER_ENTRY
10081029
/* We have user CR3. Change to kernel CR3. */
10091030
SWITCH_TO_KERNEL_CR3 scratch_reg=%rax
10101031

1032+
leaq 8(%rsp), %rdi /* arg0 = pt_regs pointer */
10111033
.Lerror_entry_from_usermode_after_swapgs:
10121034
/* Put us onto the real thread stack. */
1013-
popq %r12 /* save return addr in %12 */
1014-
movq %rsp, %rdi /* arg0 = pt_regs pointer */
10151035
call sync_regs
1016-
movq %rax, %rsp /* switch stack */
1017-
ENCODE_FRAME_POINTER
1018-
pushq %r12
10191036
RET
10201037

10211038
/*
@@ -1039,14 +1056,15 @@ SYM_CODE_START_LOCAL(error_entry)
10391056
* gsbase and proceed. We'll fix up the exception and land in
10401057
* .Lgs_change's error handler with kernel gsbase.
10411058
*/
1042-
SWAPGS
1059+
swapgs
10431060

10441061
/*
10451062
* Issue an LFENCE to prevent GS speculation, regardless of whether it is a
10461063
* kernel or user gsbase.
10471064
*/
10481065
.Lerror_entry_done_lfence:
10491066
FENCE_SWAPGS_KERNEL_ENTRY
1067+
leaq 8(%rsp), %rax /* return pt_regs pointer */
10501068
RET
10511069

10521070
.Lbstep_iret:
@@ -1059,17 +1077,17 @@ SYM_CODE_START_LOCAL(error_entry)
10591077
* We came from an IRET to user mode, so we have user
10601078
* gsbase and CR3. Switch to kernel gsbase and CR3:
10611079
*/
1062-
SWAPGS
1080+
swapgs
10631081
FENCE_SWAPGS_USER_ENTRY
10641082
SWITCH_TO_KERNEL_CR3 scratch_reg=%rax
10651083

10661084
/*
10671085
* Pretend that the exception came from user mode: set up pt_regs
10681086
* as if we faulted immediately after IRET.
10691087
*/
1070-
mov %rsp, %rdi
1088+
leaq 8(%rsp), %rdi /* arg0 = pt_regs pointer */
10711089
call fixup_bad_iret
1072-
mov %rax, %rsp
1090+
mov %rax, %rdi
10731091
jmp .Lerror_entry_from_usermode_after_swapgs
10741092
SYM_CODE_END(error_entry)
10751093

@@ -1132,6 +1150,7 @@ SYM_CODE_START(asm_exc_nmi)
11321150
*/
11331151

11341152
ASM_CLAC
1153+
cld
11351154

11361155
/* Use %rdx as our temp variable throughout */
11371156
pushq %rdx
@@ -1151,7 +1170,6 @@ SYM_CODE_START(asm_exc_nmi)
11511170
*/
11521171

11531172
swapgs
1154-
cld
11551173
FENCE_SWAPGS_USER_ENTRY
11561174
SWITCH_TO_KERNEL_CR3 scratch_reg=%rdx
11571175
movq %rsp, %rdx

arch/x86/entry/entry_64_compat.S

Lines changed: 12 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ SYM_CODE_START(entry_SYSENTER_compat)
5050
UNWIND_HINT_EMPTY
5151
ENDBR
5252
/* Interrupts are off on entry. */
53-
SWAPGS
53+
swapgs
5454

5555
pushq %rax
5656
SWITCH_TO_KERNEL_CR3 scratch_reg=%rax
@@ -83,32 +83,7 @@ SYM_INNER_LABEL(entry_SYSENTER_compat_after_hwframe, SYM_L_GLOBAL)
8383
movl %eax, %eax
8484

8585
pushq %rax /* pt_regs->orig_ax */
86-
pushq %rdi /* pt_regs->di */
87-
pushq %rsi /* pt_regs->si */
88-
pushq %rdx /* pt_regs->dx */
89-
pushq %rcx /* pt_regs->cx */
90-
pushq $-ENOSYS /* pt_regs->ax */
91-
pushq $0 /* pt_regs->r8 = 0 */
92-
xorl %r8d, %r8d /* nospec r8 */
93-
pushq $0 /* pt_regs->r9 = 0 */
94-
xorl %r9d, %r9d /* nospec r9 */
95-
pushq $0 /* pt_regs->r10 = 0 */
96-
xorl %r10d, %r10d /* nospec r10 */
97-
pushq $0 /* pt_regs->r11 = 0 */
98-
xorl %r11d, %r11d /* nospec r11 */
99-
pushq %rbx /* pt_regs->rbx */
100-
xorl %ebx, %ebx /* nospec rbx */
101-
pushq %rbp /* pt_regs->rbp (will be overwritten) */
102-
xorl %ebp, %ebp /* nospec rbp */
103-
pushq $0 /* pt_regs->r12 = 0 */
104-
xorl %r12d, %r12d /* nospec r12 */
105-
pushq $0 /* pt_regs->r13 = 0 */
106-
xorl %r13d, %r13d /* nospec r13 */
107-
pushq $0 /* pt_regs->r14 = 0 */
108-
xorl %r14d, %r14d /* nospec r14 */
109-
pushq $0 /* pt_regs->r15 = 0 */
110-
xorl %r15d, %r15d /* nospec r15 */
111-
86+
PUSH_AND_CLEAR_REGS rax=$-ENOSYS
11287
UNWIND_HINT_REGS
11388

11489
cld
@@ -225,35 +200,7 @@ SYM_INNER_LABEL(entry_SYSCALL_compat_safe_stack, SYM_L_GLOBAL)
225200
SYM_INNER_LABEL(entry_SYSCALL_compat_after_hwframe, SYM_L_GLOBAL)
226201
movl %eax, %eax /* discard orig_ax high bits */
227202
pushq %rax /* pt_regs->orig_ax */
228-
pushq %rdi /* pt_regs->di */
229-
pushq %rsi /* pt_regs->si */
230-
xorl %esi, %esi /* nospec si */
231-
pushq %rdx /* pt_regs->dx */
232-
xorl %edx, %edx /* nospec dx */
233-
pushq %rbp /* pt_regs->cx (stashed in bp) */
234-
xorl %ecx, %ecx /* nospec cx */
235-
pushq $-ENOSYS /* pt_regs->ax */
236-
pushq $0 /* pt_regs->r8 = 0 */
237-
xorl %r8d, %r8d /* nospec r8 */
238-
pushq $0 /* pt_regs->r9 = 0 */
239-
xorl %r9d, %r9d /* nospec r9 */
240-
pushq $0 /* pt_regs->r10 = 0 */
241-
xorl %r10d, %r10d /* nospec r10 */
242-
pushq $0 /* pt_regs->r11 = 0 */
243-
xorl %r11d, %r11d /* nospec r11 */
244-
pushq %rbx /* pt_regs->rbx */
245-
xorl %ebx, %ebx /* nospec rbx */
246-
pushq %rbp /* pt_regs->rbp (will be overwritten) */
247-
xorl %ebp, %ebp /* nospec rbp */
248-
pushq $0 /* pt_regs->r12 = 0 */
249-
xorl %r12d, %r12d /* nospec r12 */
250-
pushq $0 /* pt_regs->r13 = 0 */
251-
xorl %r13d, %r13d /* nospec r13 */
252-
pushq $0 /* pt_regs->r14 = 0 */
253-
xorl %r14d, %r14d /* nospec r14 */
254-
pushq $0 /* pt_regs->r15 = 0 */
255-
xorl %r15d, %r15d /* nospec r15 */
256-
203+
PUSH_AND_CLEAR_REGS rcx=%rbp rax=$-ENOSYS
257204
UNWIND_HINT_REGS
258205

259206
movq %rsp, %rdi
@@ -367,54 +314,25 @@ SYM_CODE_START(entry_INT80_compat)
367314

368315
/* switch to thread stack expects orig_ax and rdi to be pushed */
369316
pushq %rax /* pt_regs->orig_ax */
370-
pushq %rdi /* pt_regs->di */
371317

372318
/* Need to switch before accessing the thread stack. */
373-
SWITCH_TO_KERNEL_CR3 scratch_reg=%rdi
319+
SWITCH_TO_KERNEL_CR3 scratch_reg=%rax
374320

375321
/* In the Xen PV case we already run on the thread stack. */
376322
ALTERNATIVE "", "jmp .Lint80_keep_stack", X86_FEATURE_XENPV
377323

378-
movq %rsp, %rdi
324+
movq %rsp, %rax
379325
movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
380326

381-
pushq 6*8(%rdi) /* regs->ss */
382-
pushq 5*8(%rdi) /* regs->rsp */
383-
pushq 4*8(%rdi) /* regs->eflags */
384-
pushq 3*8(%rdi) /* regs->cs */
385-
pushq 2*8(%rdi) /* regs->ip */
386-
pushq 1*8(%rdi) /* regs->orig_ax */
387-
pushq (%rdi) /* pt_regs->di */
327+
pushq 5*8(%rax) /* regs->ss */
328+
pushq 4*8(%rax) /* regs->rsp */
329+
pushq 3*8(%rax) /* regs->eflags */
330+
pushq 2*8(%rax) /* regs->cs */
331+
pushq 1*8(%rax) /* regs->ip */
332+
pushq 0*8(%rax) /* regs->orig_ax */
388333
.Lint80_keep_stack:
389334

390-
pushq %rsi /* pt_regs->si */
391-
xorl %esi, %esi /* nospec si */
392-
pushq %rdx /* pt_regs->dx */
393-
xorl %edx, %edx /* nospec dx */
394-
pushq %rcx /* pt_regs->cx */
395-
xorl %ecx, %ecx /* nospec cx */
396-
pushq $-ENOSYS /* pt_regs->ax */
397-
pushq %r8 /* pt_regs->r8 */
398-
xorl %r8d, %r8d /* nospec r8 */
399-
pushq %r9 /* pt_regs->r9 */
400-
xorl %r9d, %r9d /* nospec r9 */
401-
pushq %r10 /* pt_regs->r10*/
402-
xorl %r10d, %r10d /* nospec r10 */
403-
pushq %r11 /* pt_regs->r11 */
404-
xorl %r11d, %r11d /* nospec r11 */
405-
pushq %rbx /* pt_regs->rbx */
406-
xorl %ebx, %ebx /* nospec rbx */
407-
pushq %rbp /* pt_regs->rbp */
408-
xorl %ebp, %ebp /* nospec rbp */
409-
pushq %r12 /* pt_regs->r12 */
410-
xorl %r12d, %r12d /* nospec r12 */
411-
pushq %r13 /* pt_regs->r13 */
412-
xorl %r13d, %r13d /* nospec r13 */
413-
pushq %r14 /* pt_regs->r14 */
414-
xorl %r14d, %r14d /* nospec r14 */
415-
pushq %r15 /* pt_regs->r15 */
416-
xorl %r15d, %r15d /* nospec r15 */
417-
335+
PUSH_AND_CLEAR_REGS rax=$-ENOSYS
418336
UNWIND_HINT_REGS
419337

420338
cld

arch/x86/include/asm/irqflags.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -137,14 +137,6 @@ static __always_inline void arch_local_irq_restore(unsigned long flags)
137137
if (!arch_irqs_disabled_flags(flags))
138138
arch_local_irq_enable();
139139
}
140-
#else
141-
#ifdef CONFIG_X86_64
142-
#ifdef CONFIG_XEN_PV
143-
#define SWAPGS ALTERNATIVE "swapgs", "", X86_FEATURE_XENPV
144-
#else
145-
#define SWAPGS swapgs
146-
#endif
147-
#endif
148140
#endif /* !__ASSEMBLY__ */
149141

150142
#endif

0 commit comments

Comments
 (0)