Skip to content

Commit 909489b

Browse files
committed
Merge tag 'x86-asm-2021-06-28' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 asm updates from Ingo Molnar: - Micro-optimize and standardize the do_syscall_64() calling convention - Make syscall entry flags clearing more conservative - Clean up syscall table handling - Clean up & standardize assembly macros, in preparation of FRED - Misc cleanups and fixes * tag 'x86-asm-2021-06-28' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/asm: Make <asm/asm.h> valid on cross-builds as well x86/regs: Syscall_get_nr() returns -1 for a non-system call x86/entry: Split PUSH_AND_CLEAR_REGS into two submacros x86/syscall: Maximize MSR_SYSCALL_MASK x86/syscall: Unconditionally prototype {ia32,x32}_sys_call_table[] x86/entry: Reverse arguments to do_syscall_64() x86/entry: Unify definitions from <asm/calling.h> and <asm/ptrace-abi.h> x86/asm: Use _ASM_BYTES() in <asm/nops.h> x86/asm: Add _ASM_BYTES() macro for a .byte ... opcode sequence x86/asm: Have the __ASM_FORM macros handle commas in arguments
2 parents e5a0fc4 + 41f45fb commit 909489b

12 files changed

Lines changed: 262 additions & 94 deletions

File tree

arch/x86/entry/calling.h

Lines changed: 9 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <asm/percpu.h>
77
#include <asm/asm-offsets.h>
88
#include <asm/processor-flags.h>
9+
#include <asm/ptrace-abi.h>
910

1011
/*
1112
@@ -62,42 +63,7 @@ For 32-bit we have the following conventions - kernel is built with
6263
* for assembly code:
6364
*/
6465

65-
/* The layout forms the "struct pt_regs" on the stack: */
66-
/*
67-
* C ABI says these regs are callee-preserved. They aren't saved on kernel entry
68-
* unless syscall needs a complete, fully filled "struct pt_regs".
69-
*/
70-
#define R15 0*8
71-
#define R14 1*8
72-
#define R13 2*8
73-
#define R12 3*8
74-
#define RBP 4*8
75-
#define RBX 5*8
76-
/* These regs are callee-clobbered. Always saved on kernel entry. */
77-
#define R11 6*8
78-
#define R10 7*8
79-
#define R9 8*8
80-
#define R8 9*8
81-
#define RAX 10*8
82-
#define RCX 11*8
83-
#define RDX 12*8
84-
#define RSI 13*8
85-
#define RDI 14*8
86-
/*
87-
* On syscall entry, this is syscall#. On CPU exception, this is error code.
88-
* On hw interrupt, it's IRQ number:
89-
*/
90-
#define ORIG_RAX 15*8
91-
/* Return frame for iretq */
92-
#define RIP 16*8
93-
#define CS 17*8
94-
#define EFLAGS 18*8
95-
#define RSP 19*8
96-
#define SS 20*8
97-
98-
#define SIZEOF_PTREGS 21*8
99-
100-
.macro PUSH_AND_CLEAR_REGS rdx=%rdx rax=%rax save_ret=0
66+
.macro PUSH_REGS rdx=%rdx rax=%rax save_ret=0
10167
.if \save_ret
10268
pushq %rsi /* pt_regs->si */
10369
movq 8(%rsp), %rsi /* temporarily store the return address in %rsi */
@@ -124,7 +90,9 @@ For 32-bit we have the following conventions - kernel is built with
12490
.if \save_ret
12591
pushq %rsi /* return address on top of stack */
12692
.endif
93+
.endm
12794

95+
.macro CLEAR_REGS
12896
/*
12997
* Sanitize registers of values that a speculation attack might
13098
* otherwise want to exploit. The lower registers are likely clobbered
@@ -146,6 +114,11 @@ For 32-bit we have the following conventions - kernel is built with
146114

147115
.endm
148116

117+
.macro PUSH_AND_CLEAR_REGS rdx=%rdx rax=%rax save_ret=0
118+
PUSH_REGS rdx=\rdx, rax=\rax, save_ret=\save_ret
119+
CLEAR_REGS
120+
.endm
121+
149122
.macro POP_REGS pop_rdi=1 skip_r11rcx=0
150123
popq %r15
151124
popq %r14

arch/x86/entry/common.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
#include <asm/irq_stack.h>
3737

3838
#ifdef CONFIG_X86_64
39-
__visible noinstr void do_syscall_64(unsigned long nr, struct pt_regs *regs)
39+
__visible noinstr void do_syscall_64(struct pt_regs *regs, unsigned long nr)
4040
{
4141
add_random_kstack_offset();
4242
nr = syscall_enter_from_user_mode(regs, nr);

arch/x86/entry/entry_64.S

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,8 @@ SYM_INNER_LABEL(entry_SYSCALL_64_after_hwframe, SYM_L_GLOBAL)
107107
PUSH_AND_CLEAR_REGS rax=$-ENOSYS
108108

109109
/* IRQs are off. */
110-
movq %rax, %rdi
111-
movq %rsp, %rsi
110+
movq %rsp, %rdi
111+
movq %rax, %rsi
112112
call do_syscall_64 /* returns with IRQs disabled */
113113

114114
/*

arch/x86/include/asm/asm.h

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,26 @@
33
#define _ASM_X86_ASM_H
44

55
#ifdef __ASSEMBLY__
6-
# define __ASM_FORM(x) x
7-
# define __ASM_FORM_RAW(x) x
8-
# define __ASM_FORM_COMMA(x) x,
6+
# define __ASM_FORM(x, ...) x,## __VA_ARGS__
7+
# define __ASM_FORM_RAW(x, ...) x,## __VA_ARGS__
8+
# define __ASM_FORM_COMMA(x, ...) x,## __VA_ARGS__,
99
#else
1010
#include <linux/stringify.h>
11-
12-
# define __ASM_FORM(x) " " __stringify(x) " "
13-
# define __ASM_FORM_RAW(x) __stringify(x)
14-
# define __ASM_FORM_COMMA(x) " " __stringify(x) ","
11+
# define __ASM_FORM(x, ...) " " __stringify(x,##__VA_ARGS__) " "
12+
# define __ASM_FORM_RAW(x, ...) __stringify(x,##__VA_ARGS__)
13+
# define __ASM_FORM_COMMA(x, ...) " " __stringify(x,##__VA_ARGS__) ","
1514
#endif
1615

16+
#define _ASM_BYTES(x, ...) __ASM_FORM(.byte x,##__VA_ARGS__ ;)
17+
1718
#ifndef __x86_64__
1819
/* 32 bit */
19-
# define __ASM_SEL(a,b) __ASM_FORM(a)
20-
# define __ASM_SEL_RAW(a,b) __ASM_FORM_RAW(a)
20+
# define __ASM_SEL(a,b) __ASM_FORM(a)
21+
# define __ASM_SEL_RAW(a,b) __ASM_FORM_RAW(a)
2122
#else
2223
/* 64 bit */
23-
# define __ASM_SEL(a,b) __ASM_FORM(b)
24-
# define __ASM_SEL_RAW(a,b) __ASM_FORM_RAW(b)
24+
# define __ASM_SEL(a,b) __ASM_FORM(b)
25+
# define __ASM_SEL_RAW(a,b) __ASM_FORM_RAW(b)
2526
#endif
2627

2728
#define __ASM_SIZE(inst, ...) __ASM_SEL(inst##l##__VA_ARGS__, \
@@ -119,6 +120,8 @@
119120
# define CC_OUT(c) [_cc_ ## c] "=qm"
120121
#endif
121122

123+
#ifdef __KERNEL__
124+
122125
/* Exception table entry */
123126
#ifdef __ASSEMBLY__
124127
# define _ASM_EXTABLE_HANDLE(from, to, handler) \
@@ -185,4 +188,6 @@ register unsigned long current_stack_pointer asm(_ASM_SP);
185188
#define ASM_CALL_CONSTRAINT "+r" (current_stack_pointer)
186189
#endif /* __ASSEMBLY__ */
187190

191+
#endif /* __KERNEL__ */
192+
188193
#endif /* _ASM_X86_ASM_H */

arch/x86/include/asm/nops.h

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
#ifndef _ASM_X86_NOPS_H
33
#define _ASM_X86_NOPS_H
44

5+
#include <asm/asm.h>
6+
57
/*
68
* Define nops for use with alternative() and for tracing.
79
*/
@@ -57,20 +59,14 @@
5759

5860
#endif /* CONFIG_64BIT */
5961

60-
#ifdef __ASSEMBLY__
61-
#define _ASM_MK_NOP(x) .byte x
62-
#else
63-
#define _ASM_MK_NOP(x) ".byte " __stringify(x) "\n"
64-
#endif
65-
66-
#define ASM_NOP1 _ASM_MK_NOP(BYTES_NOP1)
67-
#define ASM_NOP2 _ASM_MK_NOP(BYTES_NOP2)
68-
#define ASM_NOP3 _ASM_MK_NOP(BYTES_NOP3)
69-
#define ASM_NOP4 _ASM_MK_NOP(BYTES_NOP4)
70-
#define ASM_NOP5 _ASM_MK_NOP(BYTES_NOP5)
71-
#define ASM_NOP6 _ASM_MK_NOP(BYTES_NOP6)
72-
#define ASM_NOP7 _ASM_MK_NOP(BYTES_NOP7)
73-
#define ASM_NOP8 _ASM_MK_NOP(BYTES_NOP8)
62+
#define ASM_NOP1 _ASM_BYTES(BYTES_NOP1)
63+
#define ASM_NOP2 _ASM_BYTES(BYTES_NOP2)
64+
#define ASM_NOP3 _ASM_BYTES(BYTES_NOP3)
65+
#define ASM_NOP4 _ASM_BYTES(BYTES_NOP4)
66+
#define ASM_NOP5 _ASM_BYTES(BYTES_NOP5)
67+
#define ASM_NOP6 _ASM_BYTES(BYTES_NOP6)
68+
#define ASM_NOP7 _ASM_BYTES(BYTES_NOP7)
69+
#define ASM_NOP8 _ASM_BYTES(BYTES_NOP8)
7470

7571
#define ASM_NOP_MAX 8
7672

arch/x86/include/asm/syscall.h

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,12 @@ extern const sys_call_ptr_t sys_call_table[];
2121

2222
#if defined(CONFIG_X86_32)
2323
#define ia32_sys_call_table sys_call_table
24-
#endif
25-
26-
#if defined(CONFIG_IA32_EMULATION)
24+
#else
25+
/*
26+
* These may not exist, but still put the prototypes in so we
27+
* can use IS_ENABLED().
28+
*/
2729
extern const sys_call_ptr_t ia32_sys_call_table[];
28-
#endif
29-
30-
#ifdef CONFIG_X86_X32_ABI
3130
extern const sys_call_ptr_t x32_sys_call_table[];
3231
#endif
3332

@@ -160,7 +159,7 @@ static inline int syscall_get_arch(struct task_struct *task)
160159
? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64;
161160
}
162161

163-
void do_syscall_64(unsigned long nr, struct pt_regs *regs);
162+
void do_syscall_64(struct pt_regs *regs, unsigned long nr);
164163
void do_int80_syscall_32(struct pt_regs *regs);
165164
long do_fast_syscall_32(struct pt_regs *regs);
166165

arch/x86/kernel/cpu/common.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1773,10 +1773,16 @@ void syscall_init(void)
17731773
wrmsrl_safe(MSR_IA32_SYSENTER_EIP, 0ULL);
17741774
#endif
17751775

1776-
/* Flags to clear on syscall */
1776+
/*
1777+
* Flags to clear on syscall; clear as much as possible
1778+
* to minimize user space-kernel interference.
1779+
*/
17771780
wrmsrl(MSR_SYSCALL_MASK,
1778-
X86_EFLAGS_TF|X86_EFLAGS_DF|X86_EFLAGS_IF|
1779-
X86_EFLAGS_IOPL|X86_EFLAGS_AC|X86_EFLAGS_NT);
1781+
X86_EFLAGS_CF|X86_EFLAGS_PF|X86_EFLAGS_AF|
1782+
X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_TF|
1783+
X86_EFLAGS_IF|X86_EFLAGS_DF|X86_EFLAGS_OF|
1784+
X86_EFLAGS_IOPL|X86_EFLAGS_NT|X86_EFLAGS_RF|
1785+
X86_EFLAGS_AC|X86_EFLAGS_ID);
17801786
}
17811787

17821788
#else /* CONFIG_X86_64 */

arch/x86/kernel/head_64.S

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ SYM_CODE_START_NOALIGN(startup_64)
6262
*/
6363

6464
/* Set up the stack for verify_cpu(), similar to initial_stack below */
65-
leaq (__end_init_task - SIZEOF_PTREGS)(%rip), %rsp
65+
leaq (__end_init_task - FRAME_SIZE)(%rip), %rsp
6666

6767
leaq _text(%rip), %rdi
6868
pushq %rsi
@@ -343,10 +343,10 @@ SYM_DATA(initial_vc_handler, .quad handle_vc_boot_ghcb)
343343
#endif
344344

345345
/*
346-
* The SIZEOF_PTREGS gap is a convention which helps the in-kernel unwinder
346+
* The FRAME_SIZE gap is a convention which helps the in-kernel unwinder
347347
* reliably detect the end of the stack.
348348
*/
349-
SYM_DATA(initial_stack, .quad init_thread_union + THREAD_SIZE - SIZEOF_PTREGS)
349+
SYM_DATA(initial_stack, .quad init_thread_union + THREAD_SIZE - FRAME_SIZE)
350350
__FINITDATA
351351

352352
__INIT

arch/x86/kernel/ptrace.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -911,7 +911,7 @@ static int putreg32(struct task_struct *child, unsigned regno, u32 value)
911911
* syscall with TS_COMPAT still set.
912912
*/
913913
regs->orig_ax = value;
914-
if (syscall_get_nr(child, regs) >= 0)
914+
if (syscall_get_nr(child, regs) != -1)
915915
child->thread_info.status |= TS_I386_REGS_POKED;
916916
break;
917917

arch/x86/kernel/signal.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -713,7 +713,7 @@ handle_signal(struct ksignal *ksig, struct pt_regs *regs)
713713
save_v86_state((struct kernel_vm86_regs *) regs, VM86_SIGNAL);
714714

715715
/* Are we from a system call? */
716-
if (syscall_get_nr(current, regs) >= 0) {
716+
if (syscall_get_nr(current, regs) != -1) {
717717
/* If so, check system call restarting.. */
718718
switch (syscall_get_error(current, regs)) {
719719
case -ERESTART_RESTARTBLOCK:
@@ -793,7 +793,7 @@ void arch_do_signal_or_restart(struct pt_regs *regs, bool has_signal)
793793
}
794794

795795
/* Did we come from a system call? */
796-
if (syscall_get_nr(current, regs) >= 0) {
796+
if (syscall_get_nr(current, regs) != -1) {
797797
/* Restart the system call - no handlers present */
798798
switch (syscall_get_error(current, regs)) {
799799
case -ERESTARTNOHAND:

0 commit comments

Comments
 (0)