Skip to content

Commit d5f744f

Browse files
committed
Merge tag 'x86-entry-2020-03-30' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 entry code updates from Thomas Gleixner: - Convert the 32bit syscalls to be pt_regs based which removes the requirement to push all 6 potential arguments onto the stack and consolidates the interface with the 64bit variant - The first small portion of the exception and syscall related entry code consolidation which aims to address the recently discovered issues vs. RCU, int3, NMI and some other exceptions which can interrupt any context. The bulk of the changes is still work in progress and aimed for 5.8. - A few lockdep namespace cleanups which have been applied into this branch to keep the prerequisites for the ongoing work confined. * tag 'x86-entry-2020-03-30' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (35 commits) x86/entry: Fix build error x86 with !CONFIG_POSIX_TIMERS lockdep: Rename trace_{hard,soft}{irq_context,irqs_enabled}() lockdep: Rename trace_softirqs_{on,off}() lockdep: Rename trace_hardirq_{enter,exit}() x86/entry: Rename ___preempt_schedule x86: Remove unneeded includes x86/entry: Drop asmlinkage from syscalls x86/entry/32: Enable pt_regs based syscalls x86/entry/32: Use IA32-specific wrappers for syscalls taking 64-bit arguments x86/entry/32: Rename 32-bit specific syscalls x86/entry/32: Clean up syscall_32.tbl x86/entry: Remove ABI prefixes from functions in syscall tables x86/entry/64: Add __SYSCALL_COMMON() x86/entry: Remove syscall qualifier support x86/entry/64: Remove ptregs qualifier from syscall table x86/entry: Move max syscall number calculation to syscallhdr.sh x86/entry/64: Split X32 syscall table into its own file x86/entry/64: Move sys_ni_syscall stub to common.c x86/entry/64: Use syscall wrappers for x32_rt_sigreturn x86/entry: Refactor SYS_NI macros ...
2 parents dbb381b + 290a447 commit d5f744f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+1209
-1304
lines changed

arch/x86/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ config X86_64
3030
select MODULES_USE_ELF_RELA
3131
select NEED_DMA_MAP_STATE
3232
select SWIOTLB
33-
select ARCH_HAS_SYSCALL_WRAPPER
3433

3534
config FORCE_DYNAMIC_FTRACE
3635
def_bool y
@@ -79,6 +78,7 @@ config X86
7978
select ARCH_HAS_STRICT_KERNEL_RWX
8079
select ARCH_HAS_STRICT_MODULE_RWX
8180
select ARCH_HAS_SYNC_CORE_BEFORE_USERMODE
81+
select ARCH_HAS_SYSCALL_WRAPPER
8282
select ARCH_HAS_UBSAN_SANITIZE_ALL
8383
select ARCH_HAVE_NMI_SAFE_CMPXCHG
8484
select ARCH_MIGHT_HAVE_ACPI_PDC if ACPI

arch/x86/entry/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@ obj-y += vdso/
1414
obj-y += vsyscall/
1515

1616
obj-$(CONFIG_IA32_EMULATION) += entry_64_compat.o syscall_32.o
17+
obj-$(CONFIG_X86_X32_ABI) += syscall_x32.o
1718

arch/x86/entry/common.c

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -333,20 +333,7 @@ static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs)
333333

334334
if (likely(nr < IA32_NR_syscalls)) {
335335
nr = array_index_nospec(nr, IA32_NR_syscalls);
336-
#ifdef CONFIG_IA32_EMULATION
337336
regs->ax = ia32_sys_call_table[nr](regs);
338-
#else
339-
/*
340-
* It's possible that a 32-bit syscall implementation
341-
* takes a 64-bit parameter but nonetheless assumes that
342-
* the high bits are zero. Make sure we zero-extend all
343-
* of the args.
344-
*/
345-
regs->ax = ia32_sys_call_table[nr](
346-
(unsigned int)regs->bx, (unsigned int)regs->cx,
347-
(unsigned int)regs->dx, (unsigned int)regs->si,
348-
(unsigned int)regs->di, (unsigned int)regs->bp);
349-
#endif /* CONFIG_IA32_EMULATION */
350337
}
351338

352339
syscall_return_slowpath(regs);
@@ -438,3 +425,8 @@ __visible long do_fast_syscall_32(struct pt_regs *regs)
438425
#endif
439426
}
440427
#endif
428+
429+
SYSCALL_DEFINE0(ni_syscall)
430+
{
431+
return -ENOSYS;
432+
}

arch/x86/entry/entry_32.S

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,10 +1088,10 @@ SYM_FUNC_START(entry_INT80_32)
10881088
STACKLEAK_ERASE
10891089

10901090
restore_all:
1091-
TRACE_IRQS_IRET
1091+
TRACE_IRQS_ON
10921092
SWITCH_TO_ENTRY_STACK
10931093
CHECK_AND_APPLY_ESPFIX
1094-
.Lrestore_nocheck:
1094+
10951095
/* Switch back to user CR3 */
10961096
SWITCH_TO_USER_CR3 scratch_reg=%eax
10971097

@@ -1290,7 +1290,7 @@ SYM_CODE_END(simd_coprocessor_error)
12901290

12911291
SYM_CODE_START(device_not_available)
12921292
ASM_CLAC
1293-
pushl $-1 # mark this as an int
1293+
pushl $0
12941294
pushl $do_device_not_available
12951295
jmp common_exception
12961296
SYM_CODE_END(device_not_available)
@@ -1365,7 +1365,7 @@ SYM_CODE_END(divide_error)
13651365
SYM_CODE_START(machine_check)
13661366
ASM_CLAC
13671367
pushl $0
1368-
pushl machine_check_vector
1368+
pushl $do_mce
13691369
jmp common_exception
13701370
SYM_CODE_END(machine_check)
13711371
#endif
@@ -1531,7 +1531,7 @@ SYM_CODE_START(debug)
15311531
* Entry from sysenter is now handled in common_exception
15321532
*/
15331533
ASM_CLAC
1534-
pushl $-1 # mark this as an int
1534+
pushl $0
15351535
pushl $do_debug
15361536
jmp common_exception
15371537
SYM_CODE_END(debug)
@@ -1682,18 +1682,13 @@ SYM_CODE_END(nmi)
16821682

16831683
SYM_CODE_START(int3)
16841684
ASM_CLAC
1685-
pushl $-1 # mark this as an int
1686-
1687-
SAVE_ALL switch_stacks=1
1688-
ENCODE_FRAME_POINTER
1689-
TRACE_IRQS_OFF
1690-
xorl %edx, %edx # zero error code
1691-
movl %esp, %eax # pt_regs pointer
1692-
call do_int3
1693-
jmp ret_from_exception
1685+
pushl $0
1686+
pushl $do_int3
1687+
jmp common_exception
16941688
SYM_CODE_END(int3)
16951689

16961690
SYM_CODE_START(general_protection)
1691+
ASM_CLAC
16971692
pushl $do_general_protection
16981693
jmp common_exception
16991694
SYM_CODE_END(general_protection)

arch/x86/entry/entry_64.S

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ SYM_INNER_LABEL(entry_SYSCALL_64_after_hwframe, SYM_L_GLOBAL)
174174
movq %rsp, %rsi
175175
call do_syscall_64 /* returns with IRQs disabled */
176176

177-
TRACE_IRQS_IRETQ /* we're about to change IF */
177+
TRACE_IRQS_ON /* return enables interrupts */
178178

179179
/*
180180
* Try to use SYSRET instead of IRET if we're returning to
@@ -619,7 +619,7 @@ ret_from_intr:
619619
.Lretint_user:
620620
mov %rsp,%rdi
621621
call prepare_exit_to_usermode
622-
TRACE_IRQS_IRETQ
622+
TRACE_IRQS_ON
623623

624624
SYM_INNER_LABEL(swapgs_restore_regs_and_return_to_usermode, SYM_L_GLOBAL)
625625
#ifdef CONFIG_DEBUG_ENTRY

arch/x86/entry/syscall_32.c

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,22 @@
44
#include <linux/linkage.h>
55
#include <linux/sys.h>
66
#include <linux/cache.h>
7-
#include <asm/asm-offsets.h>
7+
#include <linux/syscalls.h>
8+
#include <asm/unistd.h>
89
#include <asm/syscall.h>
910

10-
#ifdef CONFIG_IA32_EMULATION
11-
/* On X86_64, we use struct pt_regs * to pass parameters to syscalls */
12-
#define __SYSCALL_I386(nr, sym, qual) extern asmlinkage long sym(const struct pt_regs *);
13-
#define __sys_ni_syscall __ia32_sys_ni_syscall
14-
#else /* CONFIG_IA32_EMULATION */
15-
#define __SYSCALL_I386(nr, sym, qual) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
16-
extern asmlinkage long sys_ni_syscall(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
17-
#define __sys_ni_syscall sys_ni_syscall
18-
#endif /* CONFIG_IA32_EMULATION */
11+
#define __SYSCALL_I386(nr, sym) extern long __ia32_##sym(const struct pt_regs *);
1912

2013
#include <asm/syscalls_32.h>
2114
#undef __SYSCALL_I386
2215

23-
#define __SYSCALL_I386(nr, sym, qual) [nr] = sym,
16+
#define __SYSCALL_I386(nr, sym) [nr] = __ia32_##sym,
2417

25-
__visible const sys_call_ptr_t ia32_sys_call_table[__NR_syscall_compat_max+1] = {
18+
__visible const sys_call_ptr_t ia32_sys_call_table[__NR_ia32_syscall_max+1] = {
2619
/*
2720
* Smells like a compiler bug -- it doesn't work
2821
* when the & below is removed.
2922
*/
30-
[0 ... __NR_syscall_compat_max] = &__sys_ni_syscall,
23+
[0 ... __NR_ia32_syscall_max] = &__ia32_sys_ni_syscall,
3124
#include <asm/syscalls_32.h>
3225
};

arch/x86/entry/syscall_64.c

Lines changed: 5 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,17 @@
55
#include <linux/sys.h>
66
#include <linux/cache.h>
77
#include <linux/syscalls.h>
8-
#include <asm/asm-offsets.h>
8+
#include <asm/unistd.h>
99
#include <asm/syscall.h>
1010

11-
extern asmlinkage long sys_ni_syscall(void);
11+
#define __SYSCALL_X32(nr, sym)
12+
#define __SYSCALL_COMMON(nr, sym) __SYSCALL_64(nr, sym)
1213

13-
SYSCALL_DEFINE0(ni_syscall)
14-
{
15-
return sys_ni_syscall();
16-
}
17-
18-
#define __SYSCALL_64(nr, sym, qual) extern asmlinkage long sym(const struct pt_regs *);
19-
#define __SYSCALL_X32(nr, sym, qual) __SYSCALL_64(nr, sym, qual)
14+
#define __SYSCALL_64(nr, sym) extern long __x64_##sym(const struct pt_regs *);
2015
#include <asm/syscalls_64.h>
2116
#undef __SYSCALL_64
22-
#undef __SYSCALL_X32
2317

24-
#define __SYSCALL_64(nr, sym, qual) [nr] = sym,
25-
#define __SYSCALL_X32(nr, sym, qual)
18+
#define __SYSCALL_64(nr, sym) [nr] = __x64_##sym,
2619

2720
asmlinkage const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = {
2821
/*
@@ -32,25 +25,3 @@ asmlinkage const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = {
3225
[0 ... __NR_syscall_max] = &__x64_sys_ni_syscall,
3326
#include <asm/syscalls_64.h>
3427
};
35-
36-
#undef __SYSCALL_64
37-
#undef __SYSCALL_X32
38-
39-
#ifdef CONFIG_X86_X32_ABI
40-
41-
#define __SYSCALL_64(nr, sym, qual)
42-
#define __SYSCALL_X32(nr, sym, qual) [nr] = sym,
43-
44-
asmlinkage const sys_call_ptr_t x32_sys_call_table[__NR_syscall_x32_max+1] = {
45-
/*
46-
* Smells like a compiler bug -- it doesn't work
47-
* when the & below is removed.
48-
*/
49-
[0 ... __NR_syscall_x32_max] = &__x64_sys_ni_syscall,
50-
#include <asm/syscalls_64.h>
51-
};
52-
53-
#undef __SYSCALL_64
54-
#undef __SYSCALL_X32
55-
56-
#endif

arch/x86/entry/syscall_x32.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* System call table for x32 ABI. */
3+
4+
#include <linux/linkage.h>
5+
#include <linux/sys.h>
6+
#include <linux/cache.h>
7+
#include <linux/syscalls.h>
8+
#include <asm/unistd.h>
9+
#include <asm/syscall.h>
10+
11+
#define __SYSCALL_64(nr, sym)
12+
13+
#define __SYSCALL_X32(nr, sym) extern long __x32_##sym(const struct pt_regs *);
14+
#define __SYSCALL_COMMON(nr, sym) extern long __x64_##sym(const struct pt_regs *);
15+
#include <asm/syscalls_64.h>
16+
#undef __SYSCALL_X32
17+
#undef __SYSCALL_COMMON
18+
19+
#define __SYSCALL_X32(nr, sym) [nr] = __x32_##sym,
20+
#define __SYSCALL_COMMON(nr, sym) [nr] = __x64_##sym,
21+
22+
asmlinkage const sys_call_ptr_t x32_sys_call_table[__NR_x32_syscall_max+1] = {
23+
/*
24+
* Smells like a compiler bug -- it doesn't work
25+
* when the & below is removed.
26+
*/
27+
[0 ... __NR_x32_syscall_max] = &__x64_sys_ni_syscall,
28+
#include <asm/syscalls_64.h>
29+
};

0 commit comments

Comments
 (0)