diff options
author | Ingo Molnar <mingo@kernel.org> | 2017-04-20 04:07:12 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2017-04-20 04:07:12 -0400 |
commit | afa7a17f3aafb64647ba4cd38e20f3d678c7949b (patch) | |
tree | 7cc16805d61da9670a96e17c25307a4a4972fe67 | |
parent | e720c19e0d5412f45736d62258d21dc7b056c4ad (diff) | |
parent | e9ea1e7f53b852147cbd568b0568c7ad97ec21a3 (diff) |
Merge branch 'WIP.x86/process' into perf/core
-rw-r--r-- | arch/um/include/shared/os.h | 4 | ||||
-rw-r--r-- | arch/x86/entry/syscalls/syscall_32.tbl | 1 | ||||
-rw-r--r-- | arch/x86/include/asm/cpufeatures.h | 1 | ||||
-rw-r--r-- | arch/x86/include/asm/msr-index.h | 11 | ||||
-rw-r--r-- | arch/x86/include/asm/processor.h | 2 | ||||
-rw-r--r-- | arch/x86/include/asm/proto.h | 4 | ||||
-rw-r--r-- | arch/x86/include/asm/thread_info.h | 6 | ||||
-rw-r--r-- | arch/x86/include/asm/tlbflush.h | 10 | ||||
-rw-r--r-- | arch/x86/include/uapi/asm/prctl.h | 11 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/intel.c | 40 | ||||
-rw-r--r-- | arch/x86/kernel/process.c | 151 | ||||
-rw-r--r-- | arch/x86/kernel/process_32.c | 7 | ||||
-rw-r--r-- | arch/x86/kernel/process_64.c | 48 | ||||
-rw-r--r-- | arch/x86/kernel/ptrace.c | 8 | ||||
-rw-r--r-- | arch/x86/um/Makefile | 2 | ||||
-rw-r--r-- | arch/x86/um/asm/ptrace.h | 2 | ||||
-rw-r--r-- | arch/x86/um/os-Linux/prctl.c | 4 | ||||
-rw-r--r-- | arch/x86/um/syscalls_32.c | 7 | ||||
-rw-r--r-- | arch/x86/um/syscalls_64.c | 20 | ||||
-rw-r--r-- | fs/exec.c | 1 | ||||
-rw-r--r-- | include/linux/compat.h | 2 | ||||
-rw-r--r-- | include/linux/thread_info.h | 4 |
22 files changed, 258 insertions, 88 deletions
diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h index de5d572225f3..cd1fa97776c3 100644 --- a/arch/um/include/shared/os.h +++ b/arch/um/include/shared/os.h | |||
@@ -302,8 +302,8 @@ extern int ignore_sigio_fd(int fd); | |||
302 | extern void maybe_sigio_broken(int fd, int read); | 302 | extern void maybe_sigio_broken(int fd, int read); |
303 | extern void sigio_broken(int fd, int read); | 303 | extern void sigio_broken(int fd, int read); |
304 | 304 | ||
305 | /* sys-x86_64/prctl.c */ | 305 | /* prctl.c */ |
306 | extern int os_arch_prctl(int pid, int code, unsigned long *addr); | 306 | extern int os_arch_prctl(int pid, int option, unsigned long *arg2); |
307 | 307 | ||
308 | /* tty.c */ | 308 | /* tty.c */ |
309 | extern int get_pty(void); | 309 | extern int get_pty(void); |
diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl index 9ba050fe47f3..0af59fa789ea 100644 --- a/arch/x86/entry/syscalls/syscall_32.tbl +++ b/arch/x86/entry/syscalls/syscall_32.tbl | |||
@@ -390,3 +390,4 @@ | |||
390 | 381 i386 pkey_alloc sys_pkey_alloc | 390 | 381 i386 pkey_alloc sys_pkey_alloc |
391 | 382 i386 pkey_free sys_pkey_free | 391 | 382 i386 pkey_free sys_pkey_free |
392 | 383 i386 statx sys_statx | 392 | 383 i386 statx sys_statx |
393 | 384 i386 arch_prctl sys_arch_prctl compat_sys_arch_prctl | ||
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h index b04bb6dfed7f..0fe00446f9ca 100644 --- a/arch/x86/include/asm/cpufeatures.h +++ b/arch/x86/include/asm/cpufeatures.h | |||
@@ -187,6 +187,7 @@ | |||
187 | * Reuse free bits when adding new feature flags! | 187 | * Reuse free bits when adding new feature flags! |
188 | */ | 188 | */ |
189 | #define X86_FEATURE_RING3MWAIT ( 7*32+ 0) /* Ring 3 MONITOR/MWAIT */ | 189 | #define X86_FEATURE_RING3MWAIT ( 7*32+ 0) /* Ring 3 MONITOR/MWAIT */ |
190 | #define X86_FEATURE_CPUID_FAULT ( 7*32+ 1) /* Intel CPUID faulting */ | ||
190 | #define X86_FEATURE_CPB ( 7*32+ 2) /* AMD Core Performance Boost */ | 191 | #define X86_FEATURE_CPB ( 7*32+ 2) /* AMD Core Performance Boost */ |
191 | #define X86_FEATURE_EPB ( 7*32+ 3) /* IA32_ENERGY_PERF_BIAS support */ | 192 | #define X86_FEATURE_EPB ( 7*32+ 3) /* IA32_ENERGY_PERF_BIAS support */ |
192 | #define X86_FEATURE_CAT_L3 ( 7*32+ 4) /* Cache Allocation Technology L3 */ | 193 | #define X86_FEATURE_CAT_L3 ( 7*32+ 4) /* Cache Allocation Technology L3 */ |
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index d8b5f8ab8ef9..673f9ac50f6d 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h | |||
@@ -45,6 +45,8 @@ | |||
45 | #define MSR_IA32_PERFCTR1 0x000000c2 | 45 | #define MSR_IA32_PERFCTR1 0x000000c2 |
46 | #define MSR_FSB_FREQ 0x000000cd | 46 | #define MSR_FSB_FREQ 0x000000cd |
47 | #define MSR_PLATFORM_INFO 0x000000ce | 47 | #define MSR_PLATFORM_INFO 0x000000ce |
48 | #define MSR_PLATFORM_INFO_CPUID_FAULT_BIT 31 | ||
49 | #define MSR_PLATFORM_INFO_CPUID_FAULT BIT_ULL(MSR_PLATFORM_INFO_CPUID_FAULT_BIT) | ||
48 | 50 | ||
49 | #define MSR_PKG_CST_CONFIG_CONTROL 0x000000e2 | 51 | #define MSR_PKG_CST_CONFIG_CONTROL 0x000000e2 |
50 | #define NHM_C3_AUTO_DEMOTE (1UL << 25) | 52 | #define NHM_C3_AUTO_DEMOTE (1UL << 25) |
@@ -127,6 +129,7 @@ | |||
127 | 129 | ||
128 | /* DEBUGCTLMSR bits (others vary by model): */ | 130 | /* DEBUGCTLMSR bits (others vary by model): */ |
129 | #define DEBUGCTLMSR_LBR (1UL << 0) /* last branch recording */ | 131 | #define DEBUGCTLMSR_LBR (1UL << 0) /* last branch recording */ |
132 | #define DEBUGCTLMSR_BTF_SHIFT 1 | ||
130 | #define DEBUGCTLMSR_BTF (1UL << 1) /* single-step on branches */ | 133 | #define DEBUGCTLMSR_BTF (1UL << 1) /* single-step on branches */ |
131 | #define DEBUGCTLMSR_TR (1UL << 6) | 134 | #define DEBUGCTLMSR_TR (1UL << 6) |
132 | #define DEBUGCTLMSR_BTS (1UL << 7) | 135 | #define DEBUGCTLMSR_BTS (1UL << 7) |
@@ -552,10 +555,12 @@ | |||
552 | #define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE_BIT 39 | 555 | #define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE_BIT 39 |
553 | #define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE (1ULL << MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE_BIT) | 556 | #define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE (1ULL << MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE_BIT) |
554 | 557 | ||
555 | /* MISC_FEATURE_ENABLES non-architectural features */ | 558 | /* MISC_FEATURES_ENABLES non-architectural features */ |
556 | #define MSR_MISC_FEATURE_ENABLES 0x00000140 | 559 | #define MSR_MISC_FEATURES_ENABLES 0x00000140 |
557 | 560 | ||
558 | #define MSR_MISC_FEATURE_ENABLES_RING3MWAIT_BIT 1 | 561 | #define MSR_MISC_FEATURES_ENABLES_CPUID_FAULT_BIT 0 |
562 | #define MSR_MISC_FEATURES_ENABLES_CPUID_FAULT BIT_ULL(MSR_MISC_FEATURES_ENABLES_CPUID_FAULT_BIT) | ||
563 | #define MSR_MISC_FEATURES_ENABLES_RING3MWAIT_BIT 1 | ||
559 | 564 | ||
560 | #define MSR_IA32_TSC_DEADLINE 0x000006E0 | 565 | #define MSR_IA32_TSC_DEADLINE 0x000006E0 |
561 | 566 | ||
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index f385eca5407a..a80c1b3997ed 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h | |||
@@ -884,6 +884,8 @@ extern void start_thread(struct pt_regs *regs, unsigned long new_ip, | |||
884 | extern int get_tsc_mode(unsigned long adr); | 884 | extern int get_tsc_mode(unsigned long adr); |
885 | extern int set_tsc_mode(unsigned int val); | 885 | extern int set_tsc_mode(unsigned int val); |
886 | 886 | ||
887 | DECLARE_PER_CPU(u64, msr_misc_features_shadow); | ||
888 | |||
887 | /* Register/unregister a process' MPX related resource */ | 889 | /* Register/unregister a process' MPX related resource */ |
888 | #define MPX_ENABLE_MANAGEMENT() mpx_enable_management() | 890 | #define MPX_ENABLE_MANAGEMENT() mpx_enable_management() |
889 | #define MPX_DISABLE_MANAGEMENT() mpx_disable_management() | 891 | #define MPX_DISABLE_MANAGEMENT() mpx_disable_management() |
diff --git a/arch/x86/include/asm/proto.h b/arch/x86/include/asm/proto.h index 9b9b30b19441..8d3964fc5f91 100644 --- a/arch/x86/include/asm/proto.h +++ b/arch/x86/include/asm/proto.h | |||
@@ -9,6 +9,7 @@ void syscall_init(void); | |||
9 | 9 | ||
10 | #ifdef CONFIG_X86_64 | 10 | #ifdef CONFIG_X86_64 |
11 | void entry_SYSCALL_64(void); | 11 | void entry_SYSCALL_64(void); |
12 | long do_arch_prctl_64(struct task_struct *task, int option, unsigned long arg2); | ||
12 | #endif | 13 | #endif |
13 | 14 | ||
14 | #ifdef CONFIG_X86_32 | 15 | #ifdef CONFIG_X86_32 |
@@ -30,6 +31,7 @@ void x86_report_nx(void); | |||
30 | 31 | ||
31 | extern int reboot_force; | 32 | extern int reboot_force; |
32 | 33 | ||
33 | long do_arch_prctl(struct task_struct *task, int code, unsigned long addr); | 34 | long do_arch_prctl_common(struct task_struct *task, int option, |
35 | unsigned long cpuid_enabled); | ||
34 | 36 | ||
35 | #endif /* _ASM_X86_PROTO_H */ | 37 | #endif /* _ASM_X86_PROTO_H */ |
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h index ad6f5eb07a95..9fc44b95f7cb 100644 --- a/arch/x86/include/asm/thread_info.h +++ b/arch/x86/include/asm/thread_info.h | |||
@@ -87,6 +87,7 @@ struct thread_info { | |||
87 | #define TIF_SECCOMP 8 /* secure computing */ | 87 | #define TIF_SECCOMP 8 /* secure computing */ |
88 | #define TIF_USER_RETURN_NOTIFY 11 /* notify kernel of userspace return */ | 88 | #define TIF_USER_RETURN_NOTIFY 11 /* notify kernel of userspace return */ |
89 | #define TIF_UPROBE 12 /* breakpointed or singlestepping */ | 89 | #define TIF_UPROBE 12 /* breakpointed or singlestepping */ |
90 | #define TIF_NOCPUID 15 /* CPUID is not accessible in userland */ | ||
90 | #define TIF_NOTSC 16 /* TSC is not accessible in userland */ | 91 | #define TIF_NOTSC 16 /* TSC is not accessible in userland */ |
91 | #define TIF_IA32 17 /* IA32 compatibility process */ | 92 | #define TIF_IA32 17 /* IA32 compatibility process */ |
92 | #define TIF_NOHZ 19 /* in adaptive nohz mode */ | 93 | #define TIF_NOHZ 19 /* in adaptive nohz mode */ |
@@ -110,6 +111,7 @@ struct thread_info { | |||
110 | #define _TIF_SECCOMP (1 << TIF_SECCOMP) | 111 | #define _TIF_SECCOMP (1 << TIF_SECCOMP) |
111 | #define _TIF_USER_RETURN_NOTIFY (1 << TIF_USER_RETURN_NOTIFY) | 112 | #define _TIF_USER_RETURN_NOTIFY (1 << TIF_USER_RETURN_NOTIFY) |
112 | #define _TIF_UPROBE (1 << TIF_UPROBE) | 113 | #define _TIF_UPROBE (1 << TIF_UPROBE) |
114 | #define _TIF_NOCPUID (1 << TIF_NOCPUID) | ||
113 | #define _TIF_NOTSC (1 << TIF_NOTSC) | 115 | #define _TIF_NOTSC (1 << TIF_NOTSC) |
114 | #define _TIF_IA32 (1 << TIF_IA32) | 116 | #define _TIF_IA32 (1 << TIF_IA32) |
115 | #define _TIF_NOHZ (1 << TIF_NOHZ) | 117 | #define _TIF_NOHZ (1 << TIF_NOHZ) |
@@ -138,7 +140,7 @@ struct thread_info { | |||
138 | 140 | ||
139 | /* flags to check in __switch_to() */ | 141 | /* flags to check in __switch_to() */ |
140 | #define _TIF_WORK_CTXSW \ | 142 | #define _TIF_WORK_CTXSW \ |
141 | (_TIF_IO_BITMAP|_TIF_NOTSC|_TIF_BLOCKSTEP) | 143 | (_TIF_IO_BITMAP|_TIF_NOCPUID|_TIF_NOTSC|_TIF_BLOCKSTEP) |
142 | 144 | ||
143 | #define _TIF_WORK_CTXSW_PREV (_TIF_WORK_CTXSW|_TIF_USER_RETURN_NOTIFY) | 145 | #define _TIF_WORK_CTXSW_PREV (_TIF_WORK_CTXSW|_TIF_USER_RETURN_NOTIFY) |
144 | #define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW) | 146 | #define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW) |
@@ -239,6 +241,8 @@ static inline int arch_within_stack_frames(const void * const stack, | |||
239 | extern void arch_task_cache_init(void); | 241 | extern void arch_task_cache_init(void); |
240 | extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src); | 242 | extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src); |
241 | extern void arch_release_task_struct(struct task_struct *tsk); | 243 | extern void arch_release_task_struct(struct task_struct *tsk); |
244 | extern void arch_setup_new_exec(void); | ||
245 | #define arch_setup_new_exec arch_setup_new_exec | ||
242 | #endif /* !__ASSEMBLY__ */ | 246 | #endif /* !__ASSEMBLY__ */ |
243 | 247 | ||
244 | #endif /* _ASM_X86_THREAD_INFO_H */ | 248 | #endif /* _ASM_X86_THREAD_INFO_H */ |
diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h index fc5abff9b7fd..75d002bdb3f3 100644 --- a/arch/x86/include/asm/tlbflush.h +++ b/arch/x86/include/asm/tlbflush.h | |||
@@ -110,6 +110,16 @@ static inline void cr4_clear_bits(unsigned long mask) | |||
110 | } | 110 | } |
111 | } | 111 | } |
112 | 112 | ||
113 | static inline void cr4_toggle_bits(unsigned long mask) | ||
114 | { | ||
115 | unsigned long cr4; | ||
116 | |||
117 | cr4 = this_cpu_read(cpu_tlbstate.cr4); | ||
118 | cr4 ^= mask; | ||
119 | this_cpu_write(cpu_tlbstate.cr4, cr4); | ||
120 | __write_cr4(cr4); | ||
121 | } | ||
122 | |||
113 | /* Read the CR4 shadow. */ | 123 | /* Read the CR4 shadow. */ |
114 | static inline unsigned long cr4_read_shadow(void) | 124 | static inline unsigned long cr4_read_shadow(void) |
115 | { | 125 | { |
diff --git a/arch/x86/include/uapi/asm/prctl.h b/arch/x86/include/uapi/asm/prctl.h index 835aa51c7f6e..c45765517092 100644 --- a/arch/x86/include/uapi/asm/prctl.h +++ b/arch/x86/include/uapi/asm/prctl.h | |||
@@ -1,10 +1,13 @@ | |||
1 | #ifndef _ASM_X86_PRCTL_H | 1 | #ifndef _ASM_X86_PRCTL_H |
2 | #define _ASM_X86_PRCTL_H | 2 | #define _ASM_X86_PRCTL_H |
3 | 3 | ||
4 | #define ARCH_SET_GS 0x1001 | 4 | #define ARCH_SET_GS 0x1001 |
5 | #define ARCH_SET_FS 0x1002 | 5 | #define ARCH_SET_FS 0x1002 |
6 | #define ARCH_GET_FS 0x1003 | 6 | #define ARCH_GET_FS 0x1003 |
7 | #define ARCH_GET_GS 0x1004 | 7 | #define ARCH_GET_GS 0x1004 |
8 | |||
9 | #define ARCH_GET_CPUID 0x1011 | ||
10 | #define ARCH_SET_CPUID 0x1012 | ||
8 | 11 | ||
9 | #define ARCH_MAP_VDSO_X32 0x2001 | 12 | #define ARCH_MAP_VDSO_X32 0x2001 |
10 | #define ARCH_MAP_VDSO_32 0x2002 | 13 | #define ARCH_MAP_VDSO_32 0x2002 |
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 063197771b8d..dfa90a3a5145 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c | |||
@@ -90,16 +90,12 @@ static void probe_xeon_phi_r3mwait(struct cpuinfo_x86 *c) | |||
90 | return; | 90 | return; |
91 | } | 91 | } |
92 | 92 | ||
93 | if (ring3mwait_disabled) { | 93 | if (ring3mwait_disabled) |
94 | msr_clear_bit(MSR_MISC_FEATURE_ENABLES, | ||
95 | MSR_MISC_FEATURE_ENABLES_RING3MWAIT_BIT); | ||
96 | return; | 94 | return; |
97 | } | ||
98 | |||
99 | msr_set_bit(MSR_MISC_FEATURE_ENABLES, | ||
100 | MSR_MISC_FEATURE_ENABLES_RING3MWAIT_BIT); | ||
101 | 95 | ||
102 | set_cpu_cap(c, X86_FEATURE_RING3MWAIT); | 96 | set_cpu_cap(c, X86_FEATURE_RING3MWAIT); |
97 | this_cpu_or(msr_misc_features_shadow, | ||
98 | 1UL << MSR_MISC_FEATURES_ENABLES_RING3MWAIT_BIT); | ||
103 | 99 | ||
104 | if (c == &boot_cpu_data) | 100 | if (c == &boot_cpu_data) |
105 | ELF_HWCAP2 |= HWCAP2_RING3MWAIT; | 101 | ELF_HWCAP2 |= HWCAP2_RING3MWAIT; |
@@ -488,6 +484,34 @@ static void intel_bsp_resume(struct cpuinfo_x86 *c) | |||
488 | init_intel_energy_perf(c); | 484 | init_intel_energy_perf(c); |
489 | } | 485 | } |
490 | 486 | ||
487 | static void init_cpuid_fault(struct cpuinfo_x86 *c) | ||
488 | { | ||
489 | u64 msr; | ||
490 | |||
491 | if (!rdmsrl_safe(MSR_PLATFORM_INFO, &msr)) { | ||
492 | if (msr & MSR_PLATFORM_INFO_CPUID_FAULT) | ||
493 | set_cpu_cap(c, X86_FEATURE_CPUID_FAULT); | ||
494 | } | ||
495 | } | ||
496 | |||
497 | static void init_intel_misc_features(struct cpuinfo_x86 *c) | ||
498 | { | ||
499 | u64 msr; | ||
500 | |||
501 | if (rdmsrl_safe(MSR_MISC_FEATURES_ENABLES, &msr)) | ||
502 | return; | ||
503 | |||
504 | /* Clear all MISC features */ | ||
505 | this_cpu_write(msr_misc_features_shadow, 0); | ||
506 | |||
507 | /* Check features and update capabilities and shadow control bits */ | ||
508 | init_cpuid_fault(c); | ||
509 | probe_xeon_phi_r3mwait(c); | ||
510 | |||
511 | msr = this_cpu_read(msr_misc_features_shadow); | ||
512 | wrmsrl(MSR_MISC_FEATURES_ENABLES, msr); | ||
513 | } | ||
514 | |||
491 | static void init_intel(struct cpuinfo_x86 *c) | 515 | static void init_intel(struct cpuinfo_x86 *c) |
492 | { | 516 | { |
493 | unsigned int l2 = 0; | 517 | unsigned int l2 = 0; |
@@ -602,7 +626,7 @@ static void init_intel(struct cpuinfo_x86 *c) | |||
602 | 626 | ||
603 | init_intel_energy_perf(c); | 627 | init_intel_energy_perf(c); |
604 | 628 | ||
605 | probe_xeon_phi_r3mwait(c); | 629 | init_intel_misc_features(c); |
606 | } | 630 | } |
607 | 631 | ||
608 | #ifdef CONFIG_X86_32 | 632 | #ifdef CONFIG_X86_32 |
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index f67591561711..0bb88428cbf2 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <asm/vm86.h> | 37 | #include <asm/vm86.h> |
38 | #include <asm/switch_to.h> | 38 | #include <asm/switch_to.h> |
39 | #include <asm/desc.h> | 39 | #include <asm/desc.h> |
40 | #include <asm/prctl.h> | ||
40 | 41 | ||
41 | /* | 42 | /* |
42 | * per-CPU TSS segments. Threads are completely 'soft' on Linux, | 43 | * per-CPU TSS segments. Threads are completely 'soft' on Linux, |
@@ -124,11 +125,6 @@ void flush_thread(void) | |||
124 | fpu__clear(&tsk->thread.fpu); | 125 | fpu__clear(&tsk->thread.fpu); |
125 | } | 126 | } |
126 | 127 | ||
127 | static void hard_disable_TSC(void) | ||
128 | { | ||
129 | cr4_set_bits(X86_CR4_TSD); | ||
130 | } | ||
131 | |||
132 | void disable_TSC(void) | 128 | void disable_TSC(void) |
133 | { | 129 | { |
134 | preempt_disable(); | 130 | preempt_disable(); |
@@ -137,15 +133,10 @@ void disable_TSC(void) | |||
137 | * Must flip the CPU state synchronously with | 133 | * Must flip the CPU state synchronously with |
138 | * TIF_NOTSC in the current running context. | 134 | * TIF_NOTSC in the current running context. |
139 | */ | 135 | */ |
140 | hard_disable_TSC(); | 136 | cr4_set_bits(X86_CR4_TSD); |
141 | preempt_enable(); | 137 | preempt_enable(); |
142 | } | 138 | } |
143 | 139 | ||
144 | static void hard_enable_TSC(void) | ||
145 | { | ||
146 | cr4_clear_bits(X86_CR4_TSD); | ||
147 | } | ||
148 | |||
149 | static void enable_TSC(void) | 140 | static void enable_TSC(void) |
150 | { | 141 | { |
151 | preempt_disable(); | 142 | preempt_disable(); |
@@ -154,7 +145,7 @@ static void enable_TSC(void) | |||
154 | * Must flip the CPU state synchronously with | 145 | * Must flip the CPU state synchronously with |
155 | * TIF_NOTSC in the current running context. | 146 | * TIF_NOTSC in the current running context. |
156 | */ | 147 | */ |
157 | hard_enable_TSC(); | 148 | cr4_clear_bits(X86_CR4_TSD); |
158 | preempt_enable(); | 149 | preempt_enable(); |
159 | } | 150 | } |
160 | 151 | ||
@@ -182,54 +173,129 @@ int set_tsc_mode(unsigned int val) | |||
182 | return 0; | 173 | return 0; |
183 | } | 174 | } |
184 | 175 | ||
185 | void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, | 176 | DEFINE_PER_CPU(u64, msr_misc_features_shadow); |
186 | struct tss_struct *tss) | ||
187 | { | ||
188 | struct thread_struct *prev, *next; | ||
189 | |||
190 | prev = &prev_p->thread; | ||
191 | next = &next_p->thread; | ||
192 | 177 | ||
193 | if (test_tsk_thread_flag(prev_p, TIF_BLOCKSTEP) ^ | 178 | static void set_cpuid_faulting(bool on) |
194 | test_tsk_thread_flag(next_p, TIF_BLOCKSTEP)) { | 179 | { |
195 | unsigned long debugctl = get_debugctlmsr(); | 180 | u64 msrval; |
196 | 181 | ||
197 | debugctl &= ~DEBUGCTLMSR_BTF; | 182 | msrval = this_cpu_read(msr_misc_features_shadow); |
198 | if (test_tsk_thread_flag(next_p, TIF_BLOCKSTEP)) | 183 | msrval &= ~MSR_MISC_FEATURES_ENABLES_CPUID_FAULT; |
199 | debugctl |= DEBUGCTLMSR_BTF; | 184 | msrval |= (on << MSR_MISC_FEATURES_ENABLES_CPUID_FAULT_BIT); |
185 | this_cpu_write(msr_misc_features_shadow, msrval); | ||
186 | wrmsrl(MSR_MISC_FEATURES_ENABLES, msrval); | ||
187 | } | ||
200 | 188 | ||
201 | update_debugctlmsr(debugctl); | 189 | static void disable_cpuid(void) |
190 | { | ||
191 | preempt_disable(); | ||
192 | if (!test_and_set_thread_flag(TIF_NOCPUID)) { | ||
193 | /* | ||
194 | * Must flip the CPU state synchronously with | ||
195 | * TIF_NOCPUID in the current running context. | ||
196 | */ | ||
197 | set_cpuid_faulting(true); | ||
202 | } | 198 | } |
199 | preempt_enable(); | ||
200 | } | ||
203 | 201 | ||
204 | if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^ | 202 | static void enable_cpuid(void) |
205 | test_tsk_thread_flag(next_p, TIF_NOTSC)) { | 203 | { |
206 | /* prev and next are different */ | 204 | preempt_disable(); |
207 | if (test_tsk_thread_flag(next_p, TIF_NOTSC)) | 205 | if (test_and_clear_thread_flag(TIF_NOCPUID)) { |
208 | hard_disable_TSC(); | 206 | /* |
209 | else | 207 | * Must flip the CPU state synchronously with |
210 | hard_enable_TSC(); | 208 | * TIF_NOCPUID in the current running context. |
209 | */ | ||
210 | set_cpuid_faulting(false); | ||
211 | } | 211 | } |
212 | preempt_enable(); | ||
213 | } | ||
214 | |||
215 | static int get_cpuid_mode(void) | ||
216 | { | ||
217 | return !test_thread_flag(TIF_NOCPUID); | ||
218 | } | ||
219 | |||
220 | static int set_cpuid_mode(struct task_struct *task, unsigned long cpuid_enabled) | ||
221 | { | ||
222 | if (!static_cpu_has(X86_FEATURE_CPUID_FAULT)) | ||
223 | return -ENODEV; | ||
224 | |||
225 | if (cpuid_enabled) | ||
226 | enable_cpuid(); | ||
227 | else | ||
228 | disable_cpuid(); | ||
229 | |||
230 | return 0; | ||
231 | } | ||
232 | |||
233 | /* | ||
234 | * Called immediately after a successful exec. | ||
235 | */ | ||
236 | void arch_setup_new_exec(void) | ||
237 | { | ||
238 | /* If cpuid was previously disabled for this task, re-enable it. */ | ||
239 | if (test_thread_flag(TIF_NOCPUID)) | ||
240 | enable_cpuid(); | ||
241 | } | ||
212 | 242 | ||
213 | if (test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) { | 243 | static inline void switch_to_bitmap(struct tss_struct *tss, |
244 | struct thread_struct *prev, | ||
245 | struct thread_struct *next, | ||
246 | unsigned long tifp, unsigned long tifn) | ||
247 | { | ||
248 | if (tifn & _TIF_IO_BITMAP) { | ||
214 | /* | 249 | /* |
215 | * Copy the relevant range of the IO bitmap. | 250 | * Copy the relevant range of the IO bitmap. |
216 | * Normally this is 128 bytes or less: | 251 | * Normally this is 128 bytes or less: |
217 | */ | 252 | */ |
218 | memcpy(tss->io_bitmap, next->io_bitmap_ptr, | 253 | memcpy(tss->io_bitmap, next->io_bitmap_ptr, |
219 | max(prev->io_bitmap_max, next->io_bitmap_max)); | 254 | max(prev->io_bitmap_max, next->io_bitmap_max)); |
220 | |||
221 | /* | 255 | /* |
222 | * Make sure that the TSS limit is correct for the CPU | 256 | * Make sure that the TSS limit is correct for the CPU |
223 | * to notice the IO bitmap. | 257 | * to notice the IO bitmap. |
224 | */ | 258 | */ |
225 | refresh_tss_limit(); | 259 | refresh_tss_limit(); |
226 | } else if (test_tsk_thread_flag(prev_p, TIF_IO_BITMAP)) { | 260 | } else if (tifp & _TIF_IO_BITMAP) { |
227 | /* | 261 | /* |
228 | * Clear any possible leftover bits: | 262 | * Clear any possible leftover bits: |
229 | */ | 263 | */ |
230 | memset(tss->io_bitmap, 0xff, prev->io_bitmap_max); | 264 | memset(tss->io_bitmap, 0xff, prev->io_bitmap_max); |
231 | } | 265 | } |
266 | } | ||
267 | |||
268 | void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, | ||
269 | struct tss_struct *tss) | ||
270 | { | ||
271 | struct thread_struct *prev, *next; | ||
272 | unsigned long tifp, tifn; | ||
273 | |||
274 | prev = &prev_p->thread; | ||
275 | next = &next_p->thread; | ||
276 | |||
277 | tifn = READ_ONCE(task_thread_info(next_p)->flags); | ||
278 | tifp = READ_ONCE(task_thread_info(prev_p)->flags); | ||
279 | switch_to_bitmap(tss, prev, next, tifp, tifn); | ||
280 | |||
232 | propagate_user_return_notify(prev_p, next_p); | 281 | propagate_user_return_notify(prev_p, next_p); |
282 | |||
283 | if ((tifp & _TIF_BLOCKSTEP || tifn & _TIF_BLOCKSTEP) && | ||
284 | arch_has_block_step()) { | ||
285 | unsigned long debugctl, msk; | ||
286 | |||
287 | rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl); | ||
288 | debugctl &= ~DEBUGCTLMSR_BTF; | ||
289 | msk = tifn & _TIF_BLOCKSTEP; | ||
290 | debugctl |= (msk >> TIF_BLOCKSTEP) << DEBUGCTLMSR_BTF_SHIFT; | ||
291 | wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctl); | ||
292 | } | ||
293 | |||
294 | if ((tifp ^ tifn) & _TIF_NOTSC) | ||
295 | cr4_toggle_bits(X86_CR4_TSD); | ||
296 | |||
297 | if ((tifp ^ tifn) & _TIF_NOCPUID) | ||
298 | set_cpuid_faulting(!!(tifn & _TIF_NOCPUID)); | ||
233 | } | 299 | } |
234 | 300 | ||
235 | /* | 301 | /* |
@@ -550,3 +616,16 @@ out: | |||
550 | put_task_stack(p); | 616 | put_task_stack(p); |
551 | return ret; | 617 | return ret; |
552 | } | 618 | } |
619 | |||
620 | long do_arch_prctl_common(struct task_struct *task, int option, | ||
621 | unsigned long cpuid_enabled) | ||
622 | { | ||
623 | switch (option) { | ||
624 | case ARCH_GET_CPUID: | ||
625 | return get_cpuid_mode(); | ||
626 | case ARCH_SET_CPUID: | ||
627 | return set_cpuid_mode(task, cpuid_enabled); | ||
628 | } | ||
629 | |||
630 | return -EINVAL; | ||
631 | } | ||
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 4c818f8bc135..ff40e74c9181 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/uaccess.h> | 37 | #include <linux/uaccess.h> |
38 | #include <linux/io.h> | 38 | #include <linux/io.h> |
39 | #include <linux/kdebug.h> | 39 | #include <linux/kdebug.h> |
40 | #include <linux/syscalls.h> | ||
40 | 41 | ||
41 | #include <asm/pgtable.h> | 42 | #include <asm/pgtable.h> |
42 | #include <asm/ldt.h> | 43 | #include <asm/ldt.h> |
@@ -56,6 +57,7 @@ | |||
56 | #include <asm/switch_to.h> | 57 | #include <asm/switch_to.h> |
57 | #include <asm/vm86.h> | 58 | #include <asm/vm86.h> |
58 | #include <asm/intel_rdt.h> | 59 | #include <asm/intel_rdt.h> |
60 | #include <asm/proto.h> | ||
59 | 61 | ||
60 | void __show_regs(struct pt_regs *regs, int all) | 62 | void __show_regs(struct pt_regs *regs, int all) |
61 | { | 63 | { |
@@ -304,3 +306,8 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) | |||
304 | 306 | ||
305 | return prev_p; | 307 | return prev_p; |
306 | } | 308 | } |
309 | |||
310 | SYSCALL_DEFINE2(arch_prctl, int, option, unsigned long, arg2) | ||
311 | { | ||
312 | return do_arch_prctl_common(current, option, arg2); | ||
313 | } | ||
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index d6b784a5520d..ea1a6180bf39 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/uaccess.h> | 37 | #include <linux/uaccess.h> |
38 | #include <linux/io.h> | 38 | #include <linux/io.h> |
39 | #include <linux/ftrace.h> | 39 | #include <linux/ftrace.h> |
40 | #include <linux/syscalls.h> | ||
40 | 41 | ||
41 | #include <asm/pgtable.h> | 42 | #include <asm/pgtable.h> |
42 | #include <asm/processor.h> | 43 | #include <asm/processor.h> |
@@ -204,7 +205,7 @@ int copy_thread_tls(unsigned long clone_flags, unsigned long sp, | |||
204 | (struct user_desc __user *)tls, 0); | 205 | (struct user_desc __user *)tls, 0); |
205 | else | 206 | else |
206 | #endif | 207 | #endif |
207 | err = do_arch_prctl(p, ARCH_SET_FS, tls); | 208 | err = do_arch_prctl_64(p, ARCH_SET_FS, tls); |
208 | if (err) | 209 | if (err) |
209 | goto out; | 210 | goto out; |
210 | } | 211 | } |
@@ -547,70 +548,72 @@ static long prctl_map_vdso(const struct vdso_image *image, unsigned long addr) | |||
547 | } | 548 | } |
548 | #endif | 549 | #endif |
549 | 550 | ||
550 | long do_arch_prctl(struct task_struct *task, int code, unsigned long addr) | 551 | long do_arch_prctl_64(struct task_struct *task, int option, unsigned long arg2) |
551 | { | 552 | { |
552 | int ret = 0; | 553 | int ret = 0; |
553 | int doit = task == current; | 554 | int doit = task == current; |
554 | int cpu; | 555 | int cpu; |
555 | 556 | ||
556 | switch (code) { | 557 | switch (option) { |
557 | case ARCH_SET_GS: | 558 | case ARCH_SET_GS: |
558 | if (addr >= TASK_SIZE_MAX) | 559 | if (arg2 >= TASK_SIZE_MAX) |
559 | return -EPERM; | 560 | return -EPERM; |
560 | cpu = get_cpu(); | 561 | cpu = get_cpu(); |
561 | task->thread.gsindex = 0; | 562 | task->thread.gsindex = 0; |
562 | task->thread.gsbase = addr; | 563 | task->thread.gsbase = arg2; |
563 | if (doit) { | 564 | if (doit) { |
564 | load_gs_index(0); | 565 | load_gs_index(0); |
565 | ret = wrmsrl_safe(MSR_KERNEL_GS_BASE, addr); | 566 | ret = wrmsrl_safe(MSR_KERNEL_GS_BASE, arg2); |
566 | } | 567 | } |
567 | put_cpu(); | 568 | put_cpu(); |
568 | break; | 569 | break; |
569 | case ARCH_SET_FS: | 570 | case ARCH_SET_FS: |
570 | /* Not strictly needed for fs, but do it for symmetry | 571 | /* Not strictly needed for fs, but do it for symmetry |
571 | with gs */ | 572 | with gs */ |
572 | if (addr >= TASK_SIZE_MAX) | 573 | if (arg2 >= TASK_SIZE_MAX) |
573 | return -EPERM; | 574 | return -EPERM; |
574 | cpu = get_cpu(); | 575 | cpu = get_cpu(); |
575 | task->thread.fsindex = 0; | 576 | task->thread.fsindex = 0; |
576 | task->thread.fsbase = addr; | 577 | task->thread.fsbase = arg2; |
577 | if (doit) { | 578 | if (doit) { |
578 | /* set the selector to 0 to not confuse __switch_to */ | 579 | /* set the selector to 0 to not confuse __switch_to */ |
579 | loadsegment(fs, 0); | 580 | loadsegment(fs, 0); |
580 | ret = wrmsrl_safe(MSR_FS_BASE, addr); | 581 | ret = wrmsrl_safe(MSR_FS_BASE, arg2); |
581 | } | 582 | } |
582 | put_cpu(); | 583 | put_cpu(); |
583 | break; | 584 | break; |
584 | case ARCH_GET_FS: { | 585 | case ARCH_GET_FS: { |
585 | unsigned long base; | 586 | unsigned long base; |
587 | |||
586 | if (doit) | 588 | if (doit) |
587 | rdmsrl(MSR_FS_BASE, base); | 589 | rdmsrl(MSR_FS_BASE, base); |
588 | else | 590 | else |
589 | base = task->thread.fsbase; | 591 | base = task->thread.fsbase; |
590 | ret = put_user(base, (unsigned long __user *)addr); | 592 | ret = put_user(base, (unsigned long __user *)arg2); |
591 | break; | 593 | break; |
592 | } | 594 | } |
593 | case ARCH_GET_GS: { | 595 | case ARCH_GET_GS: { |
594 | unsigned long base; | 596 | unsigned long base; |
597 | |||
595 | if (doit) | 598 | if (doit) |
596 | rdmsrl(MSR_KERNEL_GS_BASE, base); | 599 | rdmsrl(MSR_KERNEL_GS_BASE, base); |
597 | else | 600 | else |
598 | base = task->thread.gsbase; | 601 | base = task->thread.gsbase; |
599 | ret = put_user(base, (unsigned long __user *)addr); | 602 | ret = put_user(base, (unsigned long __user *)arg2); |
600 | break; | 603 | break; |
601 | } | 604 | } |
602 | 605 | ||
603 | #ifdef CONFIG_CHECKPOINT_RESTORE | 606 | #ifdef CONFIG_CHECKPOINT_RESTORE |
604 | # ifdef CONFIG_X86_X32_ABI | 607 | # ifdef CONFIG_X86_X32_ABI |
605 | case ARCH_MAP_VDSO_X32: | 608 | case ARCH_MAP_VDSO_X32: |
606 | return prctl_map_vdso(&vdso_image_x32, addr); | 609 | return prctl_map_vdso(&vdso_image_x32, arg2); |
607 | # endif | 610 | # endif |
608 | # if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION | 611 | # if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION |
609 | case ARCH_MAP_VDSO_32: | 612 | case ARCH_MAP_VDSO_32: |
610 | return prctl_map_vdso(&vdso_image_32, addr); | 613 | return prctl_map_vdso(&vdso_image_32, arg2); |
611 | # endif | 614 | # endif |
612 | case ARCH_MAP_VDSO_64: | 615 | case ARCH_MAP_VDSO_64: |
613 | return prctl_map_vdso(&vdso_image_64, addr); | 616 | return prctl_map_vdso(&vdso_image_64, arg2); |
614 | #endif | 617 | #endif |
615 | 618 | ||
616 | default: | 619 | default: |
@@ -621,10 +624,23 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr) | |||
621 | return ret; | 624 | return ret; |
622 | } | 625 | } |
623 | 626 | ||
624 | long sys_arch_prctl(int code, unsigned long addr) | 627 | SYSCALL_DEFINE2(arch_prctl, int, option, unsigned long, arg2) |
628 | { | ||
629 | long ret; | ||
630 | |||
631 | ret = do_arch_prctl_64(current, option, arg2); | ||
632 | if (ret == -EINVAL) | ||
633 | ret = do_arch_prctl_common(current, option, arg2); | ||
634 | |||
635 | return ret; | ||
636 | } | ||
637 | |||
638 | #ifdef CONFIG_IA32_EMULATION | ||
639 | COMPAT_SYSCALL_DEFINE2(arch_prctl, int, option, unsigned long, arg2) | ||
625 | { | 640 | { |
626 | return do_arch_prctl(current, code, addr); | 641 | return do_arch_prctl_common(current, option, arg2); |
627 | } | 642 | } |
643 | #endif | ||
628 | 644 | ||
629 | unsigned long KSTK_ESP(struct task_struct *task) | 645 | unsigned long KSTK_ESP(struct task_struct *task) |
630 | { | 646 | { |
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index 2364b23ea3e5..f37d18124648 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c | |||
@@ -396,12 +396,12 @@ static int putreg(struct task_struct *child, | |||
396 | if (value >= TASK_SIZE_MAX) | 396 | if (value >= TASK_SIZE_MAX) |
397 | return -EIO; | 397 | return -EIO; |
398 | /* | 398 | /* |
399 | * When changing the segment base, use do_arch_prctl | 399 | * When changing the segment base, use do_arch_prctl_64 |
400 | * to set either thread.fs or thread.fsindex and the | 400 | * to set either thread.fs or thread.fsindex and the |
401 | * corresponding GDT slot. | 401 | * corresponding GDT slot. |
402 | */ | 402 | */ |
403 | if (child->thread.fsbase != value) | 403 | if (child->thread.fsbase != value) |
404 | return do_arch_prctl(child, ARCH_SET_FS, value); | 404 | return do_arch_prctl_64(child, ARCH_SET_FS, value); |
405 | return 0; | 405 | return 0; |
406 | case offsetof(struct user_regs_struct,gs_base): | 406 | case offsetof(struct user_regs_struct,gs_base): |
407 | /* | 407 | /* |
@@ -410,7 +410,7 @@ static int putreg(struct task_struct *child, | |||
410 | if (value >= TASK_SIZE_MAX) | 410 | if (value >= TASK_SIZE_MAX) |
411 | return -EIO; | 411 | return -EIO; |
412 | if (child->thread.gsbase != value) | 412 | if (child->thread.gsbase != value) |
413 | return do_arch_prctl(child, ARCH_SET_GS, value); | 413 | return do_arch_prctl_64(child, ARCH_SET_GS, value); |
414 | return 0; | 414 | return 0; |
415 | #endif | 415 | #endif |
416 | } | 416 | } |
@@ -869,7 +869,7 @@ long arch_ptrace(struct task_struct *child, long request, | |||
869 | Works just like arch_prctl, except that the arguments | 869 | Works just like arch_prctl, except that the arguments |
870 | are reversed. */ | 870 | are reversed. */ |
871 | case PTRACE_ARCH_PRCTL: | 871 | case PTRACE_ARCH_PRCTL: |
872 | ret = do_arch_prctl(child, data, addr); | 872 | ret = do_arch_prctl_64(child, data, addr); |
873 | break; | 873 | break; |
874 | #endif | 874 | #endif |
875 | 875 | ||
diff --git a/arch/x86/um/Makefile b/arch/x86/um/Makefile index e7e7055a8658..69f0827d5f53 100644 --- a/arch/x86/um/Makefile +++ b/arch/x86/um/Makefile | |||
@@ -16,7 +16,7 @@ obj-y = bug.o bugs_$(BITS).o delay.o fault.o ldt.o \ | |||
16 | 16 | ||
17 | ifeq ($(CONFIG_X86_32),y) | 17 | ifeq ($(CONFIG_X86_32),y) |
18 | 18 | ||
19 | obj-y += checksum_32.o | 19 | obj-y += checksum_32.o syscalls_32.o |
20 | obj-$(CONFIG_ELF_CORE) += elfcore.o | 20 | obj-$(CONFIG_ELF_CORE) += elfcore.o |
21 | 21 | ||
22 | subarch-y = ../lib/string_32.o ../lib/atomic64_32.o ../lib/atomic64_cx8_32.o | 22 | subarch-y = ../lib/string_32.o ../lib/atomic64_32.o ../lib/atomic64_cx8_32.o |
diff --git a/arch/x86/um/asm/ptrace.h b/arch/x86/um/asm/ptrace.h index e59eef20647b..b291ca5cf66b 100644 --- a/arch/x86/um/asm/ptrace.h +++ b/arch/x86/um/asm/ptrace.h | |||
@@ -78,7 +78,7 @@ static inline int ptrace_set_thread_area(struct task_struct *child, int idx, | |||
78 | return -ENOSYS; | 78 | return -ENOSYS; |
79 | } | 79 | } |
80 | 80 | ||
81 | extern long arch_prctl(struct task_struct *task, int code, | 81 | extern long arch_prctl(struct task_struct *task, int option, |
82 | unsigned long __user *addr); | 82 | unsigned long __user *addr); |
83 | 83 | ||
84 | #endif | 84 | #endif |
diff --git a/arch/x86/um/os-Linux/prctl.c b/arch/x86/um/os-Linux/prctl.c index 96eb2bd28832..8431e87ac333 100644 --- a/arch/x86/um/os-Linux/prctl.c +++ b/arch/x86/um/os-Linux/prctl.c | |||
@@ -6,7 +6,7 @@ | |||
6 | #include <sys/ptrace.h> | 6 | #include <sys/ptrace.h> |
7 | #include <asm/ptrace.h> | 7 | #include <asm/ptrace.h> |
8 | 8 | ||
9 | int os_arch_prctl(int pid, int code, unsigned long *addr) | 9 | int os_arch_prctl(int pid, int option, unsigned long *arg2) |
10 | { | 10 | { |
11 | return ptrace(PTRACE_ARCH_PRCTL, pid, (unsigned long) addr, code); | 11 | return ptrace(PTRACE_ARCH_PRCTL, pid, (unsigned long) arg2, option); |
12 | } | 12 | } |
diff --git a/arch/x86/um/syscalls_32.c b/arch/x86/um/syscalls_32.c new file mode 100644 index 000000000000..627d68836b16 --- /dev/null +++ b/arch/x86/um/syscalls_32.c | |||
@@ -0,0 +1,7 @@ | |||
1 | #include <linux/syscalls.h> | ||
2 | #include <os.h> | ||
3 | |||
4 | SYSCALL_DEFINE2(arch_prctl, int, option, unsigned long, arg2) | ||
5 | { | ||
6 | return -EINVAL; | ||
7 | } | ||
diff --git a/arch/x86/um/syscalls_64.c b/arch/x86/um/syscalls_64.c index 10d907098c26..81b9fe100f7c 100644 --- a/arch/x86/um/syscalls_64.c +++ b/arch/x86/um/syscalls_64.c | |||
@@ -7,13 +7,15 @@ | |||
7 | 7 | ||
8 | #include <linux/sched.h> | 8 | #include <linux/sched.h> |
9 | #include <linux/sched/mm.h> | 9 | #include <linux/sched/mm.h> |
10 | #include <linux/syscalls.h> | ||
10 | #include <linux/uaccess.h> | 11 | #include <linux/uaccess.h> |
11 | #include <asm/prctl.h> /* XXX This should get the constants from libc */ | 12 | #include <asm/prctl.h> /* XXX This should get the constants from libc */ |
12 | #include <os.h> | 13 | #include <os.h> |
13 | 14 | ||
14 | long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr) | 15 | long arch_prctl(struct task_struct *task, int option) |
16 | unsigned long __user *arg2) | ||
15 | { | 17 | { |
16 | unsigned long *ptr = addr, tmp; | 18 | unsigned long *ptr = arg2, tmp; |
17 | long ret; | 19 | long ret; |
18 | int pid = task->mm->context.id.u.pid; | 20 | int pid = task->mm->context.id.u.pid; |
19 | 21 | ||
@@ -30,7 +32,7 @@ long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr) | |||
30 | * arch_prctl is run on the host, then the registers are read | 32 | * arch_prctl is run on the host, then the registers are read |
31 | * back. | 33 | * back. |
32 | */ | 34 | */ |
33 | switch (code) { | 35 | switch (option) { |
34 | case ARCH_SET_FS: | 36 | case ARCH_SET_FS: |
35 | case ARCH_SET_GS: | 37 | case ARCH_SET_GS: |
36 | ret = restore_registers(pid, ¤t->thread.regs.regs); | 38 | ret = restore_registers(pid, ¤t->thread.regs.regs); |
@@ -50,11 +52,11 @@ long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr) | |||
50 | ptr = &tmp; | 52 | ptr = &tmp; |
51 | } | 53 | } |
52 | 54 | ||
53 | ret = os_arch_prctl(pid, code, ptr); | 55 | ret = os_arch_prctl(pid, option, ptr); |
54 | if (ret) | 56 | if (ret) |
55 | return ret; | 57 | return ret; |
56 | 58 | ||
57 | switch (code) { | 59 | switch (option) { |
58 | case ARCH_SET_FS: | 60 | case ARCH_SET_FS: |
59 | current->thread.arch.fs = (unsigned long) ptr; | 61 | current->thread.arch.fs = (unsigned long) ptr; |
60 | ret = save_registers(pid, ¤t->thread.regs.regs); | 62 | ret = save_registers(pid, ¤t->thread.regs.regs); |
@@ -63,19 +65,19 @@ long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr) | |||
63 | ret = save_registers(pid, ¤t->thread.regs.regs); | 65 | ret = save_registers(pid, ¤t->thread.regs.regs); |
64 | break; | 66 | break; |
65 | case ARCH_GET_FS: | 67 | case ARCH_GET_FS: |
66 | ret = put_user(tmp, addr); | 68 | ret = put_user(tmp, arg2); |
67 | break; | 69 | break; |
68 | case ARCH_GET_GS: | 70 | case ARCH_GET_GS: |
69 | ret = put_user(tmp, addr); | 71 | ret = put_user(tmp, arg2); |
70 | break; | 72 | break; |
71 | } | 73 | } |
72 | 74 | ||
73 | return ret; | 75 | return ret; |
74 | } | 76 | } |
75 | 77 | ||
76 | long sys_arch_prctl(int code, unsigned long addr) | 78 | SYSCALL_DEFINE2(arch_prctl, int, option, unsigned long, arg2) |
77 | { | 79 | { |
78 | return arch_prctl(current, code, (unsigned long __user *) addr); | 80 | return arch_prctl(current, option, (unsigned long __user *) arg2); |
79 | } | 81 | } |
80 | 82 | ||
81 | void arch_switch_to(struct task_struct *to) | 83 | void arch_switch_to(struct task_struct *to) |
@@ -1320,6 +1320,7 @@ void setup_new_exec(struct linux_binprm * bprm) | |||
1320 | else | 1320 | else |
1321 | set_dumpable(current->mm, suid_dumpable); | 1321 | set_dumpable(current->mm, suid_dumpable); |
1322 | 1322 | ||
1323 | arch_setup_new_exec(); | ||
1323 | perf_event_exec(); | 1324 | perf_event_exec(); |
1324 | __set_task_comm(current, kbasename(bprm->filename), true); | 1325 | __set_task_comm(current, kbasename(bprm->filename), true); |
1325 | 1326 | ||
diff --git a/include/linux/compat.h b/include/linux/compat.h index aef47be2a5c1..af9dbc44fd92 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h | |||
@@ -723,6 +723,8 @@ asmlinkage long compat_sys_sched_rr_get_interval(compat_pid_t pid, | |||
723 | asmlinkage long compat_sys_fanotify_mark(int, unsigned int, __u32, __u32, | 723 | asmlinkage long compat_sys_fanotify_mark(int, unsigned int, __u32, __u32, |
724 | int, const char __user *); | 724 | int, const char __user *); |
725 | 725 | ||
726 | asmlinkage long compat_sys_arch_prctl(int option, unsigned long arg2); | ||
727 | |||
726 | /* | 728 | /* |
727 | * For most but not all architectures, "am I in a compat syscall?" and | 729 | * For most but not all architectures, "am I in a compat syscall?" and |
728 | * "am I a compat task?" are the same question. For architectures on which | 730 | * "am I a compat task?" are the same question. For architectures on which |
diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h index 58373875e8ee..55125d674338 100644 --- a/include/linux/thread_info.h +++ b/include/linux/thread_info.h | |||
@@ -101,6 +101,10 @@ static inline void check_object_size(const void *ptr, unsigned long n, | |||
101 | { } | 101 | { } |
102 | #endif /* CONFIG_HARDENED_USERCOPY */ | 102 | #endif /* CONFIG_HARDENED_USERCOPY */ |
103 | 103 | ||
104 | #ifndef arch_setup_new_exec | ||
105 | static inline void arch_setup_new_exec(void) { } | ||
106 | #endif | ||
107 | |||
104 | #endif /* __KERNEL__ */ | 108 | #endif /* __KERNEL__ */ |
105 | 109 | ||
106 | #endif /* _LINUX_THREAD_INFO_H */ | 110 | #endif /* _LINUX_THREAD_INFO_H */ |