Commit 9fb71c2f authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 fixes from Thomas Gleixner:
 "A set of fixes and updates for x86:

   - Address a swiotlb regression which was caused by the recent DMA
     rework and made driver fail because dma_direct_supported() returned
     false

   - Fix a signedness bug in the APIC ID validation which caused invalid
     APIC IDs to be detected as valid thereby bloating the CPU possible
     space.

   - Fix inconsisten config dependcy/select magic for the MFD_CS5535
     driver.

   - Fix a corruption of the physical address space bits when encryption
     has reduced the address space and late cpuinfo updates overwrite
     the reduced bit information with the original value.

   - Dominiks syscall rework which consolidates the architecture
     specific syscall functions so all syscalls can be wrapped with the
     same macros. This allows to switch x86/64 to struct pt_regs based
     syscalls. Extend the clearing of user space controlled registers in
     the entry patch to the lower registers"

* 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/apic: Fix signedness bug in APIC ID validity checks
  x86/cpu: Prevent cpuinfo_x86::x86_phys_bits adjustment corruption
  x86/olpc: Fix inconsistent MFD_CS5535 configuration
  swiotlb: Use dma_direct_supported() for swiotlb_ops
  syscalls/x86: Adapt syscall_wrapper.h to the new syscall stub naming convention
  syscalls/core, syscalls/x86: Rename struct pt_regs-based sys_*() to __x64_sys_*()
  syscalls/core, syscalls/x86: Clean up compat syscall stub naming convention
  syscalls/core, syscalls/x86: Clean up syscall stub naming convention
  syscalls/x86: Extend register clearing on syscall entry to lower registers
  syscalls/x86: Unconditionally enable 'struct pt_regs' based syscalls on x86_64
  syscalls/x86: Use 'struct pt_regs' based syscall calling for IA32_EMULATION and x32
  syscalls/core: Prepare CONFIG_ARCH_HAS_SYSCALL_WRAPPER=y for compat syscalls
  syscalls/x86: Use 'struct pt_regs' based syscall calling convention for 64-bit syscalls
  syscalls/core: Introduce CONFIG_ARCH_HAS_SYSCALL_WRAPPER=y
  x86/syscalls: Don't pointlessly reload the system call number
  x86/mm: Fix documentation of module mapping range with 4-level paging
  x86/cpuid: Switch to 'static const' specifier
parents 6b0a02e8 ef389b73
...@@ -360,7 +360,7 @@ First, the entry in ``arch/x86/entry/syscalls/syscall_32.tbl`` gets an extra ...@@ -360,7 +360,7 @@ First, the entry in ``arch/x86/entry/syscalls/syscall_32.tbl`` gets an extra
column to indicate that a 32-bit userspace program running on a 64-bit kernel column to indicate that a 32-bit userspace program running on a 64-bit kernel
should hit the compat entry point:: should hit the compat entry point::
380 i386 xyzzy sys_xyzzy compat_sys_xyzzy 380 i386 xyzzy sys_xyzzy __ia32_compat_sys_xyzzy
Second, you need to figure out what should happen for the x32 ABI version of Second, you need to figure out what should happen for the x32 ABI version of
the new system call. There's a choice here: the layout of the arguments the new system call. There's a choice here: the layout of the arguments
...@@ -373,7 +373,7 @@ the compatibility wrapper:: ...@@ -373,7 +373,7 @@ the compatibility wrapper::
333 64 xyzzy sys_xyzzy 333 64 xyzzy sys_xyzzy
... ...
555 x32 xyzzy compat_sys_xyzzy 555 x32 xyzzy __x32_compat_sys_xyzzy
If no pointers are involved, then it is preferable to re-use the 64-bit system If no pointers are involved, then it is preferable to re-use the 64-bit system
call for the x32 ABI (and consequently the entry in call for the x32 ABI (and consequently the entry in
......
...@@ -20,7 +20,7 @@ ffffff0000000000 - ffffff7fffffffff (=39 bits) %esp fixup stacks ...@@ -20,7 +20,7 @@ ffffff0000000000 - ffffff7fffffffff (=39 bits) %esp fixup stacks
ffffffef00000000 - fffffffeffffffff (=64 GB) EFI region mapping space ffffffef00000000 - fffffffeffffffff (=64 GB) EFI region mapping space
... unused hole ... ... unused hole ...
ffffffff80000000 - ffffffff9fffffff (=512 MB) kernel text mapping, from phys 0 ffffffff80000000 - ffffffff9fffffff (=512 MB) kernel text mapping, from phys 0
ffffffffa0000000 - [fixmap start] (~1526 MB) module mapping space (variable) ffffffffa0000000 - fffffffffeffffff (1520 MB) module mapping space
[fixmap start] - ffffffffff5fffff kernel-internal fixmap range [fixmap start] - ffffffffff5fffff kernel-internal fixmap range
ffffffffff600000 - ffffffffff600fff (=4 kB) legacy vsyscall ABI ffffffffff600000 - ffffffffff600fff (=4 kB) legacy vsyscall ABI
ffffffffffe00000 - ffffffffffffffff (=2 MB) unused hole ffffffffffe00000 - ffffffffffffffff (=2 MB) unused hole
......
...@@ -29,6 +29,7 @@ config X86_64 ...@@ -29,6 +29,7 @@ config X86_64
select HAVE_ARCH_SOFT_DIRTY select HAVE_ARCH_SOFT_DIRTY
select MODULES_USE_ELF_RELA select MODULES_USE_ELF_RELA
select X86_DEV_DMA_OPS select X86_DEV_DMA_OPS
select ARCH_HAS_SYSCALL_WRAPPER
# #
# Arch settings # Arch settings
...@@ -2763,11 +2764,9 @@ config OLPC_XO1_RTC ...@@ -2763,11 +2764,9 @@ config OLPC_XO1_RTC
config OLPC_XO1_SCI config OLPC_XO1_SCI
bool "OLPC XO-1 SCI extras" bool "OLPC XO-1 SCI extras"
depends on OLPC && OLPC_XO1_PM depends on OLPC && OLPC_XO1_PM && GPIO_CS5535=y
depends on INPUT=y depends on INPUT=y
select POWER_SUPPLY select POWER_SUPPLY
select GPIO_CS5535
select MFD_CORE
---help--- ---help---
Add support for SCI-based features of the OLPC XO-1 laptop: Add support for SCI-based features of the OLPC XO-1 laptop:
- EC-driven system wakeups - EC-driven system wakeups
......
...@@ -114,7 +114,9 @@ For 32-bit we have the following conventions - kernel is built with ...@@ -114,7 +114,9 @@ For 32-bit we have the following conventions - kernel is built with
pushq %rsi /* pt_regs->si */ pushq %rsi /* pt_regs->si */
.endif .endif
pushq \rdx /* pt_regs->dx */ pushq \rdx /* pt_regs->dx */
xorl %edx, %edx /* nospec dx */
pushq %rcx /* pt_regs->cx */ pushq %rcx /* pt_regs->cx */
xorl %ecx, %ecx /* nospec cx */
pushq \rax /* pt_regs->ax */ pushq \rax /* pt_regs->ax */
pushq %r8 /* pt_regs->r8 */ pushq %r8 /* pt_regs->r8 */
xorl %r8d, %r8d /* nospec r8 */ xorl %r8d, %r8d /* nospec r8 */
......
...@@ -266,14 +266,13 @@ __visible inline void syscall_return_slowpath(struct pt_regs *regs) ...@@ -266,14 +266,13 @@ __visible inline void syscall_return_slowpath(struct pt_regs *regs)
} }
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
__visible void do_syscall_64(struct pt_regs *regs) __visible void do_syscall_64(unsigned long nr, struct pt_regs *regs)
{ {
struct thread_info *ti = current_thread_info(); struct thread_info *ti;
unsigned long nr = regs->orig_ax;
enter_from_user_mode(); enter_from_user_mode();
local_irq_enable(); local_irq_enable();
ti = current_thread_info();
if (READ_ONCE(ti->flags) & _TIF_WORK_SYSCALL_ENTRY) if (READ_ONCE(ti->flags) & _TIF_WORK_SYSCALL_ENTRY)
nr = syscall_trace_enter(regs); nr = syscall_trace_enter(regs);
...@@ -282,11 +281,10 @@ __visible void do_syscall_64(struct pt_regs *regs) ...@@ -282,11 +281,10 @@ __visible void do_syscall_64(struct pt_regs *regs)
* table. The only functional difference is the x32 bit in * table. The only functional difference is the x32 bit in
* regs->orig_ax, which changes the behavior of some syscalls. * regs->orig_ax, which changes the behavior of some syscalls.
*/ */
if (likely((nr & __SYSCALL_MASK) < NR_syscalls)) { nr &= __SYSCALL_MASK;
nr = array_index_nospec(nr & __SYSCALL_MASK, NR_syscalls); if (likely(nr < NR_syscalls)) {
regs->ax = sys_call_table[nr]( nr = array_index_nospec(nr, NR_syscalls);
regs->di, regs->si, regs->dx, regs->ax = sys_call_table[nr](regs);
regs->r10, regs->r8, regs->r9);
} }
syscall_return_slowpath(regs); syscall_return_slowpath(regs);
...@@ -321,6 +319,9 @@ static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs) ...@@ -321,6 +319,9 @@ static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs)
if (likely(nr < IA32_NR_syscalls)) { if (likely(nr < IA32_NR_syscalls)) {
nr = array_index_nospec(nr, IA32_NR_syscalls); nr = array_index_nospec(nr, IA32_NR_syscalls);
#ifdef CONFIG_IA32_EMULATION
regs->ax = ia32_sys_call_table[nr](regs);
#else
/* /*
* It's possible that a 32-bit syscall implementation * It's possible that a 32-bit syscall implementation
* takes a 64-bit parameter but nonetheless assumes that * takes a 64-bit parameter but nonetheless assumes that
...@@ -331,6 +332,7 @@ static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs) ...@@ -331,6 +332,7 @@ static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs)
(unsigned int)regs->bx, (unsigned int)regs->cx, (unsigned int)regs->bx, (unsigned int)regs->cx,
(unsigned int)regs->dx, (unsigned int)regs->si, (unsigned int)regs->dx, (unsigned int)regs->si,
(unsigned int)regs->di, (unsigned int)regs->bp); (unsigned int)regs->di, (unsigned int)regs->bp);
#endif /* CONFIG_IA32_EMULATION */
} }
syscall_return_slowpath(regs); syscall_return_slowpath(regs);
......
...@@ -233,7 +233,8 @@ GLOBAL(entry_SYSCALL_64_after_hwframe) ...@@ -233,7 +233,8 @@ GLOBAL(entry_SYSCALL_64_after_hwframe)
TRACE_IRQS_OFF TRACE_IRQS_OFF
/* IRQs are off. */ /* IRQs are off. */
movq %rsp, %rdi movq %rax, %rdi
movq %rsp, %rsi
call do_syscall_64 /* returns with IRQs disabled */ call do_syscall_64 /* returns with IRQs disabled */
TRACE_IRQS_IRETQ /* we're about to change IF */ TRACE_IRQS_IRETQ /* we're about to change IF */
......
...@@ -220,8 +220,11 @@ GLOBAL(entry_SYSCALL_compat_after_hwframe) ...@@ -220,8 +220,11 @@ GLOBAL(entry_SYSCALL_compat_after_hwframe)
pushq %rax /* pt_regs->orig_ax */ pushq %rax /* pt_regs->orig_ax */
pushq %rdi /* pt_regs->di */ pushq %rdi /* pt_regs->di */
pushq %rsi /* pt_regs->si */ pushq %rsi /* pt_regs->si */
xorl %esi, %esi /* nospec si */
pushq %rdx /* pt_regs->dx */ pushq %rdx /* pt_regs->dx */
xorl %edx, %edx /* nospec dx */
pushq %rbp /* pt_regs->cx (stashed in bp) */ pushq %rbp /* pt_regs->cx (stashed in bp) */
xorl %ecx, %ecx /* nospec cx */
pushq $-ENOSYS /* pt_regs->ax */ pushq $-ENOSYS /* pt_regs->ax */
pushq $0 /* pt_regs->r8 = 0 */ pushq $0 /* pt_regs->r8 = 0 */
xorl %r8d, %r8d /* nospec r8 */ xorl %r8d, %r8d /* nospec r8 */
...@@ -365,8 +368,11 @@ ENTRY(entry_INT80_compat) ...@@ -365,8 +368,11 @@ ENTRY(entry_INT80_compat)
pushq (%rdi) /* pt_regs->di */ pushq (%rdi) /* pt_regs->di */
pushq %rsi /* pt_regs->si */ pushq %rsi /* pt_regs->si */
xorl %esi, %esi /* nospec si */
pushq %rdx /* pt_regs->dx */ pushq %rdx /* pt_regs->dx */
xorl %edx, %edx /* nospec dx */
pushq %rcx /* pt_regs->cx */ pushq %rcx /* pt_regs->cx */
xorl %ecx, %ecx /* nospec cx */
pushq $-ENOSYS /* pt_regs->ax */ pushq $-ENOSYS /* pt_regs->ax */
pushq $0 /* pt_regs->r8 = 0 */ pushq $0 /* pt_regs->r8 = 0 */
xorl %r8d, %r8d /* nospec r8 */ xorl %r8d, %r8d /* nospec r8 */
......
...@@ -7,14 +7,23 @@ ...@@ -7,14 +7,23 @@
#include <asm/asm-offsets.h> #include <asm/asm-offsets.h>
#include <asm/syscall.h> #include <asm/syscall.h>
#define __SYSCALL_I386(nr, sym, qual) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ; #ifdef CONFIG_IA32_EMULATION
/* On X86_64, we use struct pt_regs * to pass parameters to syscalls */
#define __SYSCALL_I386(nr, sym, qual) extern asmlinkage long sym(const struct pt_regs *);
/* this is a lie, but it does not hurt as sys_ni_syscall just returns -EINVAL */
extern asmlinkage long sys_ni_syscall(const struct pt_regs *);
#else /* CONFIG_IA32_EMULATION */
#define __SYSCALL_I386(nr, sym, qual) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
extern asmlinkage long sys_ni_syscall(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
#endif /* CONFIG_IA32_EMULATION */
#include <asm/syscalls_32.h> #include <asm/syscalls_32.h>
#undef __SYSCALL_I386 #undef __SYSCALL_I386
#define __SYSCALL_I386(nr, sym, qual) [nr] = sym, #define __SYSCALL_I386(nr, sym, qual) [nr] = sym,
extern asmlinkage long sys_ni_syscall(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
__visible const sys_call_ptr_t ia32_sys_call_table[__NR_syscall_compat_max+1] = { __visible const sys_call_ptr_t ia32_sys_call_table[__NR_syscall_compat_max+1] = {
/* /*
* Smells like a compiler bug -- it doesn't work * Smells like a compiler bug -- it doesn't work
......
...@@ -7,14 +7,14 @@ ...@@ -7,14 +7,14 @@
#include <asm/asm-offsets.h> #include <asm/asm-offsets.h>
#include <asm/syscall.h> #include <asm/syscall.h>
#define __SYSCALL_64(nr, sym, qual) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long); /* this is a lie, but it does not hurt as sys_ni_syscall just returns -EINVAL */
extern asmlinkage long sys_ni_syscall(const struct pt_regs *);
#define __SYSCALL_64(nr, sym, qual) extern asmlinkage long sym(const struct pt_regs *);
#include <asm/syscalls_64.h> #include <asm/syscalls_64.h>
#undef __SYSCALL_64 #undef __SYSCALL_64
#define __SYSCALL_64(nr, sym, qual) [nr] = sym, #define __SYSCALL_64(nr, sym, qual) [nr] = sym,
extern long sys_ni_syscall(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
asmlinkage const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = { asmlinkage const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = {
/* /*
* Smells like a compiler bug -- it doesn't work * Smells like a compiler bug -- it doesn't work
......
This diff is collapsed.
This diff is collapsed.
...@@ -25,15 +25,27 @@ emit() { ...@@ -25,15 +25,27 @@ emit() {
nr="$2" nr="$2"
entry="$3" entry="$3"
compat="$4" compat="$4"
umlentry=""
if [ "$abi" = "64" -a -n "$compat" ]; then if [ "$abi" = "64" -a -n "$compat" ]; then
echo "a compat entry for a 64-bit syscall makes no sense" >&2 echo "a compat entry for a 64-bit syscall makes no sense" >&2
exit 1 exit 1
fi fi
# For CONFIG_UML, we need to strip the __x64_sys prefix
if [ "$abi" = "64" -a "${entry}" != "${entry#__x64_sys}" ]; then
umlentry="sys${entry#__x64_sys}"
fi
if [ -z "$compat" ]; then if [ -z "$compat" ]; then
if [ -n "$entry" ]; then if [ -n "$entry" -a -z "$umlentry" ]; then
syscall_macro "$abi" "$nr" "$entry" syscall_macro "$abi" "$nr" "$entry"
elif [ -n "$umlentry" ]; then # implies -n "$entry"
echo "#ifdef CONFIG_X86"
syscall_macro "$abi" "$nr" "$entry"
echo "#else /* CONFIG_UML */"
syscall_macro "$abi" "$nr" "$umlentry"
echo "#endif"
fi fi
else else
echo "#ifdef CONFIG_X86_32" echo "#ifdef CONFIG_X86_32"
......
...@@ -127,6 +127,7 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address) ...@@ -127,6 +127,7 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address)
int vsyscall_nr, syscall_nr, tmp; int vsyscall_nr, syscall_nr, tmp;
int prev_sig_on_uaccess_err; int prev_sig_on_uaccess_err;
long ret; long ret;
unsigned long orig_dx;
/* /*
* No point in checking CS -- the only way to get here is a user mode * No point in checking CS -- the only way to get here is a user mode
...@@ -227,19 +228,22 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address) ...@@ -227,19 +228,22 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address)
ret = -EFAULT; ret = -EFAULT;
switch (vsyscall_nr) { switch (vsyscall_nr) {
case 0: case 0:
ret = sys_gettimeofday( /* this decodes regs->di and regs->si on its own */
(struct timeval __user *)regs->di, ret = __x64_sys_gettimeofday(regs);
(struct timezone __user *)regs->si);
break; break;
case 1: case 1:
ret = sys_time((time_t __user *)regs->di); /* this decodes regs->di on its own */
ret = __x64_sys_time(regs);
break; break;
case 2: case 2:
ret = sys_getcpu((unsigned __user *)regs->di, /* while we could clobber regs->dx, we didn't in the past... */
(unsigned __user *)regs->si, orig_dx = regs->dx;
NULL); regs->dx = 0;
/* this decodes regs->di, regs->si and regs->dx on its own */
ret = __x64_sys_getcpu(regs);
regs->dx = orig_dx;
break; break;
} }
......
...@@ -313,7 +313,7 @@ struct apic { ...@@ -313,7 +313,7 @@ struct apic {
/* Probe, setup and smpboot functions */ /* Probe, setup and smpboot functions */
int (*probe)(void); int (*probe)(void);
int (*acpi_madt_oem_check)(char *oem_id, char *oem_table_id); int (*acpi_madt_oem_check)(char *oem_id, char *oem_table_id);
int (*apic_id_valid)(int apicid); int (*apic_id_valid)(u32 apicid);
int (*apic_id_registered)(void); int (*apic_id_registered)(void);
bool (*check_apicid_used)(physid_mask_t *map, int apicid); bool (*check_apicid_used)(physid_mask_t *map, int apicid);
...@@ -486,7 +486,7 @@ static inline unsigned int read_apic_id(void) ...@@ -486,7 +486,7 @@ static inline unsigned int read_apic_id(void)
return apic->get_apic_id(reg); return apic->get_apic_id(reg);
} }
extern int default_apic_id_valid(int apicid); extern int default_apic_id_valid(u32 apicid);
extern int default_acpi_madt_oem_check(char *, char *); extern int default_acpi_madt_oem_check(char *, char *);
extern void default_setup_apic_routing(void); extern void default_setup_apic_routing(void);
......
...@@ -20,9 +20,13 @@ ...@@ -20,9 +20,13 @@
#include <asm/thread_info.h> /* for TS_COMPAT */ #include <asm/thread_info.h> /* for TS_COMPAT */
#include <asm/unistd.h> #include <asm/unistd.h>
#ifdef CONFIG_X86_64
typedef asmlinkage long (*sys_call_ptr_t)(const struct pt_regs *);
#else
typedef asmlinkage long (*sys_call_ptr_t)(unsigned long, unsigned long, typedef asmlinkage long (*sys_call_ptr_t)(unsigned long, unsigned long,
unsigned long, unsigned long, unsigned long, unsigned long,
unsigned long, unsigned long); unsigned long, unsigned long);
#endif /* CONFIG_X86_64 */
extern const sys_call_ptr_t sys_call_table[]; extern const sys_call_ptr_t sys_call_table[];
#if defined(CONFIG_X86_32) #if defined(CONFIG_X86_32)
......
/* SPDX-License-Identifier: GPL-2.0 */
/*
* syscall_wrapper.h - x86 specific wrappers to syscall definitions
*/
#ifndef _ASM_X86_SYSCALL_WRAPPER_H
#define _ASM_X86_SYSCALL_WRAPPER_H
/* Mapping of registers to parameters for syscalls on x86-64 and x32 */
#define SC_X86_64_REGS_TO_ARGS(x, ...) \
__MAP(x,__SC_ARGS \
,,regs->di,,regs->si,,regs->dx \
,,regs->r10,,regs->r8,,regs->r9) \
/* Mapping of registers to parameters for syscalls on i386 */
#define SC_IA32_REGS_TO_ARGS(x, ...) \
__MAP(x,__SC_ARGS \
,,(unsigned int)regs->bx,,(unsigned int)regs->cx \
,,(unsigned int)regs->dx,,(unsigned int)regs->si \
,,(unsigned int)regs->di,,(unsigned int)regs->bp)
#ifdef CONFIG_IA32_EMULATION
/*
* For IA32 emulation, we need to handle "compat" syscalls *and* create
* additional wrappers (aptly named __ia32_sys_xyzzy) which decode the
* ia32 regs in the proper order for shared or "common" syscalls. As some
* syscalls may not be implemented, we need to expand COND_SYSCALL in
* kernel/sys_ni.c and SYS_NI in kernel/time/posix-stubs.c to cover this
* case as well.
*/
#define __IA32_COMPAT_SYS_STUBx(x, name, ...) \
asmlinkage long __ia32_compat_sys##name(const struct pt_regs *regs);\
ALLOW_ERROR_INJECTION(__ia32_compat_sys##name, ERRNO); \
asmlinkage long __ia32_compat_sys##name(const struct pt_regs *regs)\
{ \
return __se_compat_sys##name(SC_IA32_REGS_TO_ARGS(x,__VA_ARGS__));\
} \
#define __IA32_SYS_STUBx(x, name, ...) \
asmlinkage long __ia32_sys##name(const struct pt_regs *regs); \
ALLOW_ERROR_INJECTION(__ia32_sys##name, ERRNO); \
asmlinkage long __ia32_sys##name(const struct pt_regs *regs) \
{ \
return __se_sys##name(SC_IA32_REGS_TO_ARGS(x,__VA_ARGS__));\
}
/*
* To keep the naming coherent, re-define SYSCALL_DEFINE0 to create an alias
* named __ia32_sys_*()
*/
#define SYSCALL_DEFINE0(sname) \
SYSCALL_METADATA(_##sname, 0); \
asmlinkage long __x64_sys_##sname(void); \
ALLOW_ERROR_INJECTION(__x64_sys_##sname, ERRNO); \
SYSCALL_ALIAS(__ia32_sys_##sname, __x64_sys_##sname); \
asmlinkage long __x64_sys_##sname(void)
#define COND_SYSCALL(name) \
cond_syscall(__x64_sys_##name); \
cond_syscall(__ia32_sys_##name)
#define SYS_NI(name) \
SYSCALL_ALIAS(__x64_sys_##name, sys_ni_posix_timers); \
SYSCALL_ALIAS(__ia32_sys_##name, sys_ni_posix_timers)
#else /* CONFIG_IA32_EMULATION */
#define __IA32_COMPAT_SYS_STUBx(x, name, ...)
#define __IA32_SYS_STUBx(x, fullname, name, ...)
#endif /* CONFIG_IA32_EMULATION */
#ifdef CONFIG_X86_X32
/*
* For the x32 ABI, we need to create a stub for compat_sys_*() which is aware
* of the x86-64-style parameter ordering of x32 syscalls. The syscalls common
* with x86_64 obviously do not need such care.
*/
#define __X32_COMPAT_SYS_STUBx(x, name, ...) \
asmlinkage long __x32_compat_sys##name(const struct pt_regs *regs);\
ALLOW_ERROR_INJECTION(__x32_compat_sys##name, ERRNO); \
asmlinkage long __x32_compat_sys##name(const struct pt_regs *regs)\
{ \
return __se_compat_sys##name(SC_X86_64_REGS_TO_ARGS(x,__VA_ARGS__));\
} \
#else /* CONFIG_X86_X32 */
#define __X32_COMPAT_SYS_STUBx(x, name, ...)
#endif /* CONFIG_X86_X32 */
#ifdef CONFIG_COMPAT
/*
* Compat means IA32_EMULATION and/or X86_X32. As they use a different
* mapping of registers to parameters, we need to generate stubs for each
* of them.
*/
#define COMPAT_SYSCALL_DEFINEx(x, name, ...) \
static long __se_compat_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \
static inline long __do_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\
__IA32_COMPAT_SYS_STUBx(x, name, __VA_ARGS__) \
__X32_COMPAT_SYS_STUBx(x, name, __VA_ARGS__) \
static long __se_compat_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \
{ \
return __do_compat_sys##name(__MAP(x,__SC_DELOUSE,__VA_ARGS__));\
} \
static inline long __do_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))
/*
* As some compat syscalls may not be implemented, we need to expand
* COND_SYSCALL_COMPAT in kernel/sys_ni.c and COMPAT_SYS_NI in
* kernel/time/posix-stubs.c to cover this case as well.
*/
#define COND_SYSCALL_COMPAT(name) \
cond_syscall(__ia32_compat_sys_##name); \
cond_syscall(__x32_compat_sys_##name)
#define COMPAT_SYS_NI(name) \
SYSCALL_ALIAS(__ia32_compat_sys_##name, sys_ni_posix_timers); \
SYSCALL_ALIAS(__x32_compat_sys_##name, sys_ni_posix_timers)
#endif /* CONFIG_COMPAT */
/*
* Instead of the generic __SYSCALL_DEFINEx() definition, this macro takes
* struct pt_regs *regs as the only argument of the syscall stub named
* __x64_sys_*(). It decodes just the registers it needs and passes them on to
* the __se_sys_*() wrapper performing sign extension and then to the
* __do_sys_*() function doing the actual job. These wrappers and functions
* are inlined (at least in very most cases), meaning that the assembly looks
* as follows (slightly re-ordered for better readability):
*
* <__x64_sys_recv>: <-- syscall with 4 parameters
* callq <__fentry__>
*
* mov 0x70(%rdi),%rdi <-- decode regs->di
* mov 0x68(%rdi),%rsi <-- decode regs->si
* mov 0x60(%rdi),%rdx <-- decode regs->dx
* mov 0x38(%rdi),%rcx <-- decode regs->r10
*
* xor %r9d,%r9d <-- clear %r9
* xor %r8d,%r8d <-- clear %r8
*
* callq __sys_recvfrom <-- do the actual work in __sys_recvfrom()
* which takes 6 arguments
*
* cltq <-- extend return value to 64-bit
* retq <-- return
*
* This approach avoids leaking random user-provided register content down
* the call chain.
*
* If IA32_EMULATION is enabled, this macro generates an additional wrapper
* named __ia32_sys_*() which decodes the struct pt_regs *regs according
* to the i386 calling convention (bx, cx, dx, si, di, bp).
*/
#define __SYSCALL_DEFINEx(x, name, ...) \
asmlinkage long __x64_sys##name(const struct pt_regs *regs); \
ALLOW_ERROR_INJECTION(__x64_sys##name, ERRNO); \
static long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \
static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\
asmlinkage long __x64_sys##name(const struct pt_regs *regs) \
{ \
return __se_sys##name(SC_X86_64_REGS_TO_ARGS(x,__VA_ARGS__));\
} \
__IA32_SYS_STUBx(x, name, __VA_ARGS__) \
static long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \
{ \
long ret = __do_sys##name(__MAP(x,__SC_CAST,__VA_ARGS__));\
__MAP(x,__SC_TEST,__VA_ARGS__); \
__PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__)); \
return ret; \
} \
static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))
/*
* As the generic SYSCALL_DEFINE0() macro does not decode any parameters for
* obvious reasons, and passing struct pt_regs *regs to it in %rdi does not
* hurt, we only need to re-define it here to keep the naming congruent to
* SYSCALL_DEFINEx() -- which is essential for the COND_SYSCALL() and SYS_NI()
* macros to work correctly.
*/
#ifndef SYSCALL_DEFINE0
#define SYSCALL_DEFINE0(sname) \
SYSCALL_METADATA(_##sname, 0); \
asmlinkage long __x64_sys_##sname(void); \
ALLOW_ERROR_INJECTION(__x64_sys_##sname, ERRNO); \
asmlinkage long __x64_sys_##sname(void)
#endif
#ifndef COND_SYSCALL
#define COND_SYSCALL(name) cond_syscall(__x64_sys_##name)
#endif
#ifndef SYS_NI
#define SYS_NI(name) SYSCALL_ALIAS(__x64_sys_##name, sys_ni_posix_timers);
#endif
/*
* For VSYSCALLS, we need to declare these three syscalls with the new
* pt_regs-based calling convention for in-kernel use.
*/
struct pt_regs;
asmlinkage long __x64_sys_getcpu(const struct pt_regs *regs);
asmlinkage long __x64_sys_gettimeofday(const struct pt_regs *regs);
asmlinkage long __x64_sys_time(const struct pt_regs *regs);
#endif /* _ASM_X86_SYSCALL_WRAPPER_H */
...@@ -18,6 +18,12 @@ ...@@ -18,6 +18,12 @@
/* Common in X86_32 and X86_64 */ /* Common in X86_32 and X86_64 */
/* kernel/ioport.c */ /* kernel/ioport.c */
long ksys_ioperm(unsigned long from, unsigned long num, int turn_on); long ksys_ioperm(unsigned long from, unsigned long num, int turn_on);
#ifdef CONFIG_X86_32
/*
* These definitions are only valid on pure 32-bit systems; x86-64 uses a
* different syscall calling convention
*/
asmlinkage long sys_ioperm(unsigned long, unsigned long, int); asmlinkage long sys_ioperm(unsigned long, unsigned long, int);
asmlinkage long sys_iopl(unsigned int); asmlinkage long sys_iopl(unsigned int);
...@@ -32,7 +38,6 @@ asmlinkage long sys_set_thread_area(struct user_desc __user *); ...@@ -32,7 +38,6 @@ asmlinkage long sys_set_thread_area(struct user_desc __user *);
asmlinkage long sys_get_thread_area(struct user_desc __user *); asmlinkage long sys_get_thread_area(struct user_desc __user *);
/* X86_32 only */ /* X86_32 only */
#ifdef CONFIG_X86_32
/* kernel/signal.c */ /* kernel/signal.c */
asmlinkage long sys_sigreturn(void); asmlinkage long sys_sigreturn(void);
...@@ -42,15 +47,5 @@ struct vm86_struct; ...@@ -42,15 +47,5 @@ struct vm86_struct;
asmlinkage long sys_vm86old(struct vm86_struct __user *); asmlinkage long sys_vm86old(struct vm86_struct __user *);
asmlinkage long sys_vm86(unsigned long, unsigned long); asmlinkage long sys_vm86(unsigned long, unsigned long);
#else /* CONFIG_X86_32 */
/* X86_64 only */
/* kernel/process_64.c */
asmlinkage long sys_arch_prctl(int, unsigned long);
/* kernel/sys_x86_64.c */
asmlinkage long sys_mmap(unsigned long, unsigned long, unsigned long,
unsigned long, unsigned long, unsigned long);
#endif /* CONFIG_X86_32 */ #endif /* CONFIG_X86_32 */
#endif /* _ASM_X86_SYSCALLS_H */ #endif /* _ASM_X86_SYSCALLS_H */
...@@ -200,7 +200,7 @@ acpi_parse_x2apic(struct acpi_subtable_header *header, const unsigned long end) ...@@ -200,7 +200,7 @@ acpi_parse_x2apic(struct acpi_subtable_header *header, const unsigned long end)
{ {
struct acpi_madt_local_x2apic *processor = NULL; struct acpi_madt_local_x2apic *processor = NULL;
#ifdef CONFIG_X86_X2APIC #ifdef CONFIG_X86_X2APIC
int apic_id; u32 apic_id;
u8 enabled; u8 enabled;
#endif #endif
...@@ -222,10 +222,13 @@ acpi_parse_x2apic(struct acpi_subtable_header *header, const unsigned long end) ...@@ -222,10 +222,13 @@ acpi_parse_x2apic(struct acpi_subtable_header *header, const unsigned long end)
* to not preallocating memory for all NR_CPUS * to not preallocating memory for all NR_CPUS
* when we use CPU hotplug. * when we use CPU hotplug.
*/ */
if (!apic->apic_id_valid(apic_id) && enabled) if (!apic->apic_id_valid(apic_id)) {
printk(KERN_WARNING PREFIX "x2apic entry ignored\n"); if (enabled)
else pr_warn(PREFIX "x2apic entry ignored\n");
acpi_register_lapic(apic_id, processor->uid, enabled); return 0;
}
acpi_register_lapic(apic_id, processor->uid, enabled);
#else #else
printk(KERN_WARNING PREFIX "x2apic entry ignored\n"); printk(KERN_WARNING PREFIX "x2apic entry ignored\n");
#endif #endif
......
...@@ -40,7 +40,7 @@ int default_check_phys_apicid_present(int phys_apicid) ...@@ -40,7 +40,7 @@ int default_check_phys_apicid_present(int phys_apicid)
return physid_isset(phys_apicid, phys_cpu_present_map); return physid_isset(phys_apicid, phys_cpu_present_map);
} }
int default_apic_id_valid(int apicid) int default_apic_id_valid(u32 apicid)
{ {
return (apicid < 255); return (apicid < 255);
} }
...@@ -56,7 +56,7 @@ static u32 numachip2_set_apic_id(unsigned int id) ...@@ -56,7 +56,7 @@ static u32 numachip2_set_apic_id(unsigned int id)
return id << 24; return id << 24;
} }
static int numachip_apic_id_valid(int apicid) static int numachip_apic_id_valid(u32 apicid)
{ {
/* Trust what bootloader passes in MADT */ /* Trust what bootloader passes in MADT */
return 1; return 1;
......
/* Common bits for X2APIC cluster/physical modes. */ /* Common bits for X2APIC cluster/physical modes. */
int x2apic_apic_id_valid(int apicid); int x2apic_apic_id_valid(u32 apicid);
int x2apic_apic_id_registered(void); int x2apic_apic_id_registered(void);
void __x2apic_send_IPI_dest(unsigned int apicid, int vector, unsigned int dest); void __x2apic_send_IPI_dest(unsigned int apicid, int vector, unsigned int dest);
unsigned int x2apic_get_apic_id(unsigned long id); unsigned int x2apic_get_apic_id(unsigned long id);
......
...@@ -101,7 +101,7 @@ static int x2apic_phys_probe(void) ...@@ -101,7 +101,7 @@ static int x2apic_phys_probe(void)
} }
/* Common x2apic functions, also used by x2apic_cluster */ /* Common x2apic functions, also used by x2apic_cluster */
int x2apic_apic_id_valid(int apicid) int x2apic_apic_id_valid(u32 apicid)
{ {
return 1; return 1;
} }
......
...@@ -557,7 +557,7 @@ static void uv_send_IPI_all(int vector) ...@@ -557,7 +557,7 @@ static void uv_send_IPI_all(int vector)
uv_send_IPI_mask(cpu_online_mask, vector); uv_send_IPI_mask(cpu_online_mask, vector);
} }
static int uv_apic_id_valid(int apicid) static int uv_apic_id_valid(u32 apicid)
{ {
return 1; return 1;
} }
......
...@@ -848,18 +848,6 @@ void get_cpu_cap(struct cpuinfo_x86 *c) ...@@ -848,18 +848,6 @@ void get_cpu_cap(struct cpuinfo_x86 *c)
c->x86_power = edx; c->x86_power = edx;
} }
if (c->extended_cpuid_level >= 0x80000008) {
cpuid(0x80000008, &eax, &ebx, &ecx, &edx);
c->x86_virt_bits = (eax >> 8) & 0xff;
c->x86_phys_bits = eax & 0xff;
c->x86_capability[CPUID_8000_0008_EBX] = ebx;
}
#ifdef CONFIG_X86_32
else if (cpu_has(c, X86_FEATURE_PAE) || cpu_has(c, X86_FEATURE_PSE36))
c->x86_phys_bits = 36;
#endif
if (c->extended_cpuid_level >= 0x8000000a) if (c->extended_cpuid_level >= 0x8000000a)
c->x86_capability[CPUID_8000_000A_EDX] = cpuid_edx(0x8000000a); c->x86_capability[CPUID_8000_000A_EDX] = cpuid_edx(0x8000000a);
...@@ -874,6 +862,23 @@ void get_cpu_cap(struct cpuinfo_x86 *c) ...@@ -874,6 +862,23 @@ void get_cpu_cap(struct cpuinfo_x86 *c)
apply_forced_caps(c); apply_forced_caps(c);
} }
static void get_cpu_address_sizes(struct cpuinfo_x86 *c)
{
u32 eax, ebx, ecx, edx;
if (c->extended_cpuid_level >= 0x80000008) {
cpuid(0x80000008, &eax, &ebx, &ecx, &edx);
c->x86_virt_bits = (eax >> 8) & 0xff;
c->x86_phys_bits = eax & 0xff;
c->x86_capability[CPUID_8000_0008_EBX] = ebx;
}
#ifdef CONFIG_X86_32
else if (cpu_has(c, X86_FEATURE_PAE) || cpu_has(c, X86_FEATURE_PSE36))
c->x86_phys_bits = 36;
#endif
}
static void identify_cpu_without_cpuid(struct cpuinfo_x86 *c) static void identify_cpu_without_cpuid(struct cpuinfo_x86 *c)
{ {
#ifdef CONFIG_X86_32 #ifdef CONFIG_X86_32
...@@ -965,6 +970,7 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c) ...@@ -965,6 +970,7 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)
cpu_detect(c); cpu_detect(c);
get_cpu_vendor(c); get_cpu_vendor(c);
get_cpu_cap(c); get_cpu_cap(c);
get_cpu_address_sizes(c);
setup_force_cpu_cap(X86_FEATURE_CPUID); setup_force_cpu_cap(X86_FEATURE_CPUID);
if (this_cpu->c_early_init) if (this_cpu->c_early_init)
...@@ -1097,6 +1103,8 @@ static void generic_identify(struct cpuinfo_x86 *c) ...@@ -1097,6 +1103,8 @@ static void generic_identify(struct cpuinfo_x86 *c)
get_cpu_cap(c); get_cpu_cap(c);
get_cpu_address_sizes(c);
if (c->cpuid_level >= 0x00000001) { if (c->cpuid_level >= 0x00000001) {
c->initial_apicid = (cpuid_ebx(1) >> 24) & 0xFF; c->initial_apicid = (cpuid_ebx(1) >> 24) & 0xFF;
#ifdef CONFIG_X86_32 #ifdef CONFIG_X86_32
......
...@@ -19,7 +19,7 @@ struct cpuid_dep { ...@@ -19,7 +19,7 @@ struct cpuid_dep {
* called from cpu hotplug. It shouldn't do anything in this case, * called from cpu hotplug. It shouldn't do anything in this case,
* but it's difficult to tell that to the init reference checker. * but it's difficult to tell that to the init reference checker.
*/ */
const static struct cpuid_dep cpuid_deps[] = { static const struct cpuid_dep cpuid_deps[] = {
{ X86_FEATURE_XSAVEOPT, X86_FEATURE_XSAVE }, { X86_FEATURE_XSAVEOPT, X86_FEATURE_XSAVE },
{ X86_FEATURE_XSAVEC, X86_FEATURE_XSAVE }, { X86_FEATURE_XSAVEC, X86_FEATURE_XSAVE },
{ X86_FEATURE_XSAVES, X86_FEATURE_XSAVE }, { X86_FEATURE_XSAVES, X86_FEATURE_XSAVE },
......
...@@ -112,7 +112,7 @@ static int xen_madt_oem_check(char *oem_id, char *oem_table_id) ...@@ -112,7 +112,7 @@ static int xen_madt_oem_check(char *oem_id, char *oem_table_id)
return xen_pv_domain(); return xen_pv_domain();
} }
static int xen_id_always_valid(int apicid) static int xen_id_always_valid(u32 apicid)
{ {
return 1; return 1;
} }
......
...@@ -24,6 +24,17 @@ ...@@ -24,6 +24,17 @@
#include <asm/siginfo.h> #include <asm/siginfo.h>
#include <asm/signal.h> #include <asm/signal.h>
#ifdef CONFIG_ARCH_HAS_SYSCALL_WRAPPER
/*
* It may be useful for an architecture to override the definitions of the
* COMPAT_SYSCALL_DEFINE0 and COMPAT_SYSCALL_DEFINEx() macros, in particular
* to use a different calling convention for syscalls. To allow for that,
+ the prototypes for the compat_sys_*() functions below will *not* be included
* if CONFIG_ARCH_HAS_SYSCALL_WRAPPER is enabled.
*/
#include <asm/syscall_wrapper.h>
#endif /* CONFIG_ARCH_HAS_SYSCALL_WRAPPER */
#ifndef COMPAT_USE_64BIT_TIME #ifndef COMPAT_USE_64BIT_TIME
#define COMPAT_USE_64BIT_TIME 0 #define COMPAT_USE_64BIT_TIME 0
#endif #endif
...@@ -32,10 +43,12 @@ ...@@ -32,10 +43,12 @@
#define __SC_DELOUSE(t,v) ((__force t)(unsigned long)(v)) #define __SC_DELOUSE(t,v) ((__force t)(unsigned long)(v))
#endif #endif
#ifndef COMPAT_SYSCALL_DEFINE0
#define COMPAT_SYSCALL_DEFINE0(name) \ #define COMPAT_SYSCALL_DEFINE0(name) \
asmlinkage long compat_sys_##name(void); \ asmlinkage long compat_sys_##name(void); \
ALLOW_ERROR_INJECTION(compat_sys_##name, ERRNO); \ ALLOW_ERROR_INJECTION(compat_sys_##name, ERRNO); \
asmlinkage long compat_sys_##name(void) asmlinkage long compat_sys_##name(void)
#endif /* COMPAT_SYSCALL_DEFINE0 */
#define COMPAT_SYSCALL_DEFINE1(name, ...) \ #define COMPAT_SYSCALL_DEFINE1(name, ...) \
COMPAT_SYSCALL_DEFINEx(1, _##name, __VA_ARGS__) COMPAT_SYSCALL_DEFINEx(1, _##name, __VA_ARGS__)
...@@ -50,18 +63,25 @@ ...@@ -50,18 +63,25 @@
#define COMPAT_SYSCALL_DEFINE6(name, ...) \ #define COMPAT_SYSCALL_DEFINE6(name, ...) \
COMPAT_SYSCALL_DEFINEx(6, _##name, __VA_ARGS__) COMPAT_SYSCALL_DEFINEx(6, _##name, __VA_ARGS__)
#define COMPAT_SYSCALL_DEFINEx(x, name, ...) \ /*
asmlinkage long compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\ * The asmlinkage stub is aliased to a function named __se_compat_sys_*() which
asmlinkage long compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))\ * sign-extends 32-bit ints to longs whenever needed. The actual work is
__attribute__((alias(__stringify(compat_SyS##name)))); \ * done within __do_compat_sys_*().
ALLOW_ERROR_INJECTION(compat_sys##name, ERRNO); \ */
static inline long C_SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__));\ #ifndef COMPAT_SYSCALL_DEFINEx
asmlinkage long compat_SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__));\ #define COMPAT_SYSCALL_DEFINEx(x, name, ...) \
asmlinkage long compat_SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__))\ asmlinkage long compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \
{ \ asmlinkage long compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) \
return C_SYSC##name(__MAP(x,__SC_DELOUSE,__VA_ARGS__)); \ __attribute__((alias(__stringify(__se_compat_sys##name)))); \
} \ ALLOW_ERROR_INJECTION(compat_sys##name, ERRNO); \
static inline long C_SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__)) static inline long __do_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\
asmlinkage long __se_compat_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \
asmlinkage long __se_compat_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \
{ \
return __do_compat_sys##name(__MAP(x,__SC_DELOUSE,__VA_ARGS__));\
} \
static inline long __do_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))
#endif /* COMPAT_SYSCALL_DEFINEx */
#ifndef compat_user_stack_pointer #ifndef compat_user_stack_pointer
#define compat_user_stack_pointer() current_user_stack_pointer() #define compat_user_stack_pointer() current_user_stack_pointer()
...@@ -519,7 +539,12 @@ int __compat_save_altstack(compat_stack_t __user *, unsigned long); ...@@ -519,7 +539,12 @@ int __compat_save_altstack(compat_stack_t __user *, unsigned long);
* Please note that these prototypes here are only provided for information * Please note that these prototypes here are only provided for information
* purposes, for static analysis, and for linking from the syscall table. * purposes, for static analysis, and for linking from the syscall table.
* These functions should not be called elsewhere from kernel code. * These functions should not be called elsewhere from kernel code.
*
* As the syscall calling convention may be different from the default
* for architectures overriding the syscall calling convention, do not
* include the prototypes if CONFIG_ARCH_HAS_SYSCALL_WRAPPER is enabled.
*/ */
#ifndef CONFIG_ARCH_HAS_SYSCALL_WRAPPER
asmlinkage long compat_sys_io_setup(unsigned nr_reqs, u32 __user *ctx32p); asmlinkage long compat_sys_io_setup(unsigned nr_reqs, u32 __user *ctx32p);
asmlinkage long compat_sys_io_submit(compat_aio_context_t ctx_id, int nr, asmlinkage long compat_sys_io_submit(compat_aio_context_t ctx_id, int nr,
u32 __user *iocb); u32 __user *iocb);
...@@ -957,6 +982,8 @@ asmlinkage long compat_sys_stime(compat_time_t __user *tptr); ...@@ -957,6 +982,8 @@ asmlinkage long compat_sys_stime(compat_time_t __user *tptr);
/* obsolete: net/socket.c */ /* obsolete: net/socket.c */
asmlinkage long compat_sys_socketcall(int call, u32 __user *args); asmlinkage long compat_sys_socketcall(int call, u32 __user *args);
#endif /* CONFIG_ARCH_HAS_SYSCALL_WRAPPER */
/* /*
* For most but not all architectures, "am I in a compat syscall?" and * For most but not all architectures, "am I in a compat syscall?" and
......
...@@ -81,6 +81,17 @@ union bpf_attr; ...@@ -81,6 +81,17 @@ union bpf_attr;
#include <linux/key.h> #include <linux/key.h>
#include <trace/syscall.h> #include <trace/syscall.h>
#ifdef CONFIG_ARCH_HAS_SYSCALL_WRAPPER
/*
* It may be useful for an architecture to override the definitions of the
* SYSCALL_DEFINE0() and __SYSCALL_DEFINEx() macros, in particular to use a
* different calling convention for syscalls. To allow for that, the prototypes
* for the sys_*() functions below will *not* be included if
* CONFIG_ARCH_HAS_SYSCALL_WRAPPER is enabled.
*/
#include <asm/syscall_wrapper.h>
#endif /* CONFIG_ARCH_HAS_SYSCALL_WRAPPER */
/* /*
* __MAP - apply a macro to syscall arguments * __MAP - apply a macro to syscall arguments
* __MAP(n, m, t1, a1, t2, a2, ..., tn, an) will expand to * __MAP(n, m, t1, a1, t2, a2, ..., tn, an) will expand to
...@@ -91,7 +102,7 @@ union bpf_attr; ...@@ -91,7 +102,7 @@ union bpf_attr;
* for SYSCALL_DEFINE<n>/COMPAT_SYSCALL_DEFINE<n> * for SYSCALL_DEFINE<n>/COMPAT_SYSCALL_DEFINE<n>
*/ */
#define __MAP0(m,...) #define __MAP0(m,...)
#define __MAP1(m,t,a) m(t,a) #define __MAP1(m,t,a,...) m(t,a)
#define __MAP2(m,t,a,...) m(t,a), __MAP1(m,__VA_ARGS__) #define __MAP2(m,t,a,...) m(t,a), __MAP1(m,__VA_ARGS__)
#define __MAP3(m,t,a,...) m(t,a), __MAP2(m,__VA_ARGS__) #define __MAP3(m,t,a,...) m(t,a), __MAP2(m,__VA_ARGS__)
#define __MAP4(m,t,a,...) m(t,a), __MAP3(m,__VA_ARGS__) #define __MAP4(m,t,a,...) m(t,a), __MAP3(m,__VA_ARGS__)
...@@ -189,11 +200,13 @@ static inline int is_syscall_trace_event(struct trace_event_call *tp_event) ...@@ -189,11 +200,13 @@ static inline int is_syscall_trace_event(struct trace_event_call *tp_event)
} }
#endif #endif
#ifndef SYSCALL_DEFINE0
#define SYSCALL_DEFINE0(sname) \ #define SYSCALL_DEFINE0(sname) \
SYSCALL_METADATA(_##sname, 0); \ SYSCALL_METADATA(_##sname, 0); \
asmlinkage long sys_##sname(void); \ asmlinkage long sys_##sname(void); \
ALLOW_ERROR_INJECTION(sys_##sname, ERRNO); \ ALLOW_ERROR_INJECTION(sys_##sname, ERRNO); \
asmlinkage long sys_##sname(void) asmlinkage long sys_##sname(void)
#endif /* SYSCALL_DEFINE0 */
#define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__) #define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE2(name, ...) SYSCALL_DEFINEx(2, _##name, __VA_ARGS__) #define SYSCALL_DEFINE2(name, ...) SYSCALL_DEFINEx(2, _##name, __VA_ARGS__)
...@@ -209,20 +222,28 @@ static inline int is_syscall_trace_event(struct trace_event_call *tp_event) ...@@ -209,20 +222,28 @@ static inline int is_syscall_trace_event(struct trace_event_call *tp_event)
__SYSCALL_DEFINEx(x, sname, __VA_ARGS__) __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
#define __PROTECT(...) asmlinkage_protect(__VA_ARGS__) #define __PROTECT(...) asmlinkage_protect(__VA_ARGS__)
/*
* The asmlinkage stub is aliased to a function named __se_sys_*() which
* sign-extends 32-bit ints to longs whenever needed. The actual work is
* done within __do_sys_*().
*/
#ifndef __SYSCALL_DEFINEx
#define __SYSCALL_DEFINEx(x, name, ...) \ #define __SYSCALL_DEFINEx(x, name, ...) \
asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) \ asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) \
__attribute__((alias(__stringify(SyS##name)))); \ __attribute__((alias(__stringify(__se_sys##name)))); \
ALLOW_ERROR_INJECTION(sys##name, ERRNO); \ ALLOW_ERROR_INJECTION(sys##name, ERRNO); \
static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \ static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\
asmlinkage long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \ asmlinkage long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \
asmlinkage long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \ asmlinkage long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \
{ \ { \
long ret = SYSC##name(__MAP(x,__SC_CAST,__VA_ARGS__)); \ long ret = __do_sys##name(__MAP(x,__SC_CAST,__VA_ARGS__));\
__MAP(x,__SC_TEST,__VA_ARGS__); \ __MAP(x,__SC_TEST,__VA_ARGS__); \
__PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__)); \ __PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__)); \
return ret; \ return ret; \
} \ } \
static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__)) static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))
#endif /* __SYSCALL_DEFINEx */
/* /*
* Called before coming back to user-mode. Returning to user-mode with an * Called before coming back to user-mode. Returning to user-mode with an
...@@ -252,7 +273,12 @@ static inline void addr_limit_user_check(void) ...@@ -252,7 +273,12 @@ static inline void addr_limit_user_check(void)
* Please note that these prototypes here are only provided for information * Please note that these prototypes here are only provided for information
* purposes, for static analysis, and for linking from the syscall table. * purposes, for static analysis, and for linking from the syscall table.
* These functions should not be called elsewhere from kernel code. * These functions should not be called elsewhere from kernel code.
*
* As the syscall calling convention may be different from the default
* for architectures overriding the syscall calling convention, do not
* include the prototypes if CONFIG_ARCH_HAS_SYSCALL_WRAPPER is enabled.
*/ */
#ifndef CONFIG_ARCH_HAS_SYSCALL_WRAPPER
asmlinkage long sys_io_setup(unsigned nr_reqs, aio_context_t __user *ctx); asmlinkage long sys_io_setup(unsigned nr_reqs, aio_context_t __user *ctx);
asmlinkage long sys_io_destroy(aio_context_t ctx); asmlinkage long sys_io_destroy(aio_context_t ctx);
asmlinkage long sys_io_submit(aio_context_t, long, asmlinkage long sys_io_submit(aio_context_t, long,
...@@ -1076,6 +1102,8 @@ asmlinkage long sys_old_mmap(struct mmap_arg_struct __user *arg); ...@@ -1076,6 +1102,8 @@ asmlinkage long sys_old_mmap(struct mmap_arg_struct __user *arg);
*/ */
asmlinkage long sys_ni_syscall(void); asmlinkage long sys_ni_syscall(void);
#endif /* CONFIG_ARCH_HAS_SYSCALL_WRAPPER */
/* /*
* Kernel code should not call syscalls (i.e., sys_xyzyyz()) directly. * Kernel code should not call syscalls (i.e., sys_xyzyyz()) directly.
......
...@@ -1923,3 +1923,13 @@ source "kernel/Kconfig.locks" ...@@ -1923,3 +1923,13 @@ source "kernel/Kconfig.locks"
config ARCH_HAS_SYNC_CORE_BEFORE_USERMODE config ARCH_HAS_SYNC_CORE_BEFORE_USERMODE
bool bool
# It may be useful for an architecture to override the definitions of the
# SYSCALL_DEFINE() and __SYSCALL_DEFINEx() macros in <linux/syscalls.h>
# and the COMPAT_ variants in <linux/compat.h>, in particular to use a
# different calling convention for syscalls. They can also override the
# macros for not-implemented syscalls in kernel/sys_ni.c and
# kernel/time/posix-stubs.c. All these overrides need to be available in
# <asm/syscall_wrapper.h>.
config ARCH_HAS_SYSCALL_WRAPPER
def_bool n
...@@ -5,6 +5,11 @@ ...@@ -5,6 +5,11 @@
#include <asm/unistd.h> #include <asm/unistd.h>
#ifdef CONFIG_ARCH_HAS_SYSCALL_WRAPPER
/* Architectures may override COND_SYSCALL and COND_SYSCALL_COMPAT */
#include <asm/syscall_wrapper.h>
#endif /* CONFIG_ARCH_HAS_SYSCALL_WRAPPER */
/* we can't #include <linux/syscalls.h> here, /* we can't #include <linux/syscalls.h> here,
but tell gcc to not warn with -Wmissing-prototypes */ but tell gcc to not warn with -Wmissing-prototypes */
asmlinkage long sys_ni_syscall(void); asmlinkage long sys_ni_syscall(void);
...@@ -17,8 +22,13 @@ asmlinkage long sys_ni_syscall(void) ...@@ -17,8 +22,13 @@ asmlinkage long sys_ni_syscall(void)
return -ENOSYS; return -ENOSYS;
} }
#ifndef COND_SYSCALL
#define COND_SYSCALL(name) cond_syscall(sys_##name) #define COND_SYSCALL(name) cond_syscall(sys_##name)
#endif /* COND_SYSCALL */
#ifndef COND_SYSCALL_COMPAT
#define COND_SYSCALL_COMPAT(name) cond_syscall(compat_sys_##name) #define COND_SYSCALL_COMPAT(name) cond_syscall(compat_sys_##name)
#endif /* COND_SYSCALL_COMPAT */
/* /*
* This list is kept in the same order as include/uapi/asm-generic/unistd.h. * This list is kept in the same order as include/uapi/asm-generic/unistd.h.
......
...@@ -19,6 +19,11 @@ ...@@ -19,6 +19,11 @@
#include <linux/posix-timers.h> #include <linux/posix-timers.h>
#include <linux/compat.h> #include <linux/compat.h>
#ifdef CONFIG_ARCH_HAS_SYSCALL_WRAPPER
/* Architectures may override SYS_NI and COMPAT_SYS_NI */
#include <asm/syscall_wrapper.h>
#endif
asmlinkage long sys_ni_posix_timers(void) asmlinkage long sys_ni_posix_timers(void)
{ {
pr_err_once("process %d (%s) attempted a POSIX timer syscall " pr_err_once("process %d (%s) attempted a POSIX timer syscall "
...@@ -27,8 +32,13 @@ asmlinkage long sys_ni_posix_timers(void) ...@@ -27,8 +32,13 @@ asmlinkage long sys_ni_posix_timers(void)
return -ENOSYS; return -ENOSYS;
} }
#ifndef SYS_NI
#define SYS_NI(name) SYSCALL_ALIAS(sys_##name, sys_ni_posix_timers) #define SYS_NI(name) SYSCALL_ALIAS(sys_##name, sys_ni_posix_timers)
#endif
#ifndef COMPAT_SYS_NI
#define COMPAT_SYS_NI(name) SYSCALL_ALIAS(compat_sys_##name, sys_ni_posix_timers) #define COMPAT_SYS_NI(name) SYSCALL_ALIAS(compat_sys_##name, sys_ni_posix_timers)
#endif
SYS_NI(timer_create); SYS_NI(timer_create);
SYS_NI(timer_gettime); SYS_NI(timer_gettime);
......
...@@ -1087,6 +1087,6 @@ const struct dma_map_ops swiotlb_dma_ops = { ...@@ -1087,6 +1087,6 @@ const struct dma_map_ops swiotlb_dma_ops = {
.unmap_sg = swiotlb_unmap_sg_attrs, .unmap_sg = swiotlb_unmap_sg_attrs,
.map_page = swiotlb_map_page, .map_page = swiotlb_map_page,
.unmap_page = swiotlb_unmap_page, .unmap_page = swiotlb_unmap_page,
.dma_supported = swiotlb_dma_supported, .dma_supported = dma_direct_supported,
}; };
#endif /* CONFIG_DMA_DIRECT_OPS */ #endif /* CONFIG_DMA_DIRECT_OPS */
...@@ -30,8 +30,8 @@ def getsizes(file, format): ...@@ -30,8 +30,8 @@ def getsizes(file, format):
if type in format: if type in format:
# strip generated symbols # strip generated symbols
if name.startswith("__mod_"): continue if name.startswith("__mod_"): continue
if name.startswith("SyS_"): continue if name.startswith("__se_sys"): continue
if name.startswith("compat_SyS_"): continue if name.startswith("__se_compat_sys"): continue
if name == "linux_banner": continue if name == "linux_banner": continue
# statics and some other optimizations adds random .NUMBER # statics and some other optimizations adds random .NUMBER
name = re_NUMBER.sub('', name) name = re_NUMBER.sub('', name)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment