diff options
Diffstat (limited to 'arch/x86/kernel')
25 files changed, 160 insertions, 147 deletions
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 04105574c8e..82f2912155a 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -17,19 +17,6 @@ CFLAGS_REMOVE_ftrace.o = -pg  CFLAGS_REMOVE_early_printk.o = -pg  endif -# -# vsyscalls (which work on the user stack) should have -# no stack-protector checks: -# -nostackp := $(call cc-option, -fno-stack-protector) -CFLAGS_vsyscall_64.o	:= $(PROFILING) -g0 $(nostackp) -CFLAGS_hpet.o		:= $(nostackp) -CFLAGS_paravirt.o	:= $(nostackp) -GCOV_PROFILE_vsyscall_64.o	:= n -GCOV_PROFILE_hpet.o		:= n -GCOV_PROFILE_tsc.o		:= n -GCOV_PROFILE_paravirt.o		:= n -  obj-y			:= process_$(BITS).o signal.o entry_$(BITS).o  obj-y			+= traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o  obj-y			+= time.o ioport.o ldt.o dumpstack.o diff --git a/arch/x86/kernel/acpi/cstate.c b/arch/x86/kernel/acpi/cstate.c index 5812404a0d4..f50e7fb2a20 100644 --- a/arch/x86/kernel/acpi/cstate.c +++ b/arch/x86/kernel/acpi/cstate.c @@ -149,6 +149,29 @@ int acpi_processor_ffh_cstate_probe(unsigned int cpu,  }  EXPORT_SYMBOL_GPL(acpi_processor_ffh_cstate_probe); +/* + * This uses new MONITOR/MWAIT instructions on P4 processors with PNI, + * which can obviate IPI to trigger checking of need_resched. + * We execute MONITOR against need_resched and enter optimized wait state + * through MWAIT. Whenever someone changes need_resched, we would be woken + * up from MWAIT (without an IPI). + * + * New with Core Duo processors, MWAIT can take some hints based on CPU + * capability. + */ +void mwait_idle_with_hints(unsigned long ax, unsigned long cx) +{ +	if (!need_resched()) { +		if (this_cpu_has(X86_FEATURE_CLFLUSH_MONITOR)) +			clflush((void *)¤t_thread_info()->flags); + +		__monitor((void *)¤t_thread_info()->flags, 0, 0); +		smp_mb(); +		if (!need_resched()) +			__mwait(ax, cx); +	} +} +  void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx *cx)  {  	unsigned int cpu = smp_processor_id(); diff --git a/arch/x86/kernel/amd_gart_64.c b/arch/x86/kernel/amd_gart_64.c index b117efd24f7..8a439d364b9 100644 --- a/arch/x86/kernel/amd_gart_64.c +++ b/arch/x86/kernel/amd_gart_64.c @@ -30,7 +30,7 @@  #include <linux/syscore_ops.h>  #include <linux/io.h>  #include <linux/gfp.h> -#include <asm/atomic.h> +#include <linux/atomic.h>  #include <asm/mtrr.h>  #include <asm/pgtable.h>  #include <asm/proto.h> diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index b24be38c8cf..52fa56399a5 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -38,7 +38,7 @@  #include <asm/perf_event.h>  #include <asm/x86_init.h>  #include <asm/pgalloc.h> -#include <asm/atomic.h> +#include <linux/atomic.h>  #include <asm/mpspec.h>  #include <asm/i8259.h>  #include <asm/proto.h> diff --git a/arch/x86/kernel/apic/es7000_32.c b/arch/x86/kernel/apic/es7000_32.c index 9536b3fe43f..5d513bc47b6 100644 --- a/arch/x86/kernel/apic/es7000_32.c +++ b/arch/x86/kernel/apic/es7000_32.c @@ -48,7 +48,7 @@  #include <linux/io.h>  #include <asm/apicdef.h> -#include <asm/atomic.h> +#include <linux/atomic.h>  #include <asm/fixmap.h>  #include <asm/mpspec.h>  #include <asm/setup.h> diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index adc66c3a1fe..34b18594e72 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c @@ -207,7 +207,6 @@ static int __cpuinit uv_wakeup_secondary(int phys_apicid, unsigned long start_ri  	    ((start_rip << UVH_IPI_INT_VECTOR_SHFT) >> 12) |  	    APIC_DM_INIT;  	uv_write_global_mmr64(pnode, UVH_IPI_INT, val); -	mdelay(10);  	val = (1UL << UVH_IPI_INT_SEND_SHFT) |  	    (phys_apicid << UVH_IPI_INT_APIC_ID_SHFT) | diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 22a073d7fbf..62184390a60 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -21,7 +21,7 @@  #include <linux/topology.h>  #include <linux/cpumask.h>  #include <asm/pgtable.h> -#include <asm/atomic.h> +#include <linux/atomic.h>  #include <asm/proto.h>  #include <asm/setup.h>  #include <asm/apic.h> diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index 08119a37e53..6b96110bb0c 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -149,7 +149,6 @@ struct set_mtrr_data {   */  static int mtrr_rendezvous_handler(void *info)  { -#ifdef CONFIG_SMP  	struct set_mtrr_data *data = info;  	/* @@ -171,7 +170,6 @@ static int mtrr_rendezvous_handler(void *info)  	} else if (mtrr_aps_delayed_init || !cpu_online(smp_processor_id())) {  		mtrr_if->set_all();  	} -#endif  	return 0;  } diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 4ee3abf20ed..cfa62ec090e 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -1900,6 +1900,9 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)  	perf_callchain_store(entry, regs->ip); +	if (!current->mm) +		return; +  	if (perf_callchain_user32(regs, entry))  		return; diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 45fbb8f7f54..f88af2c2a56 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -1590,6 +1590,7 @@ static __init int intel_pmu_init(void)  		break;  	case 42: /* SandyBridge */ +	case 45: /* SandyBridge, "Romely-EP" */  		memcpy(hw_cache_event_ids, snb_hw_cache_event_ids,  		       sizeof(hw_cache_event_ids)); diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index 5c1a9197491..f3f6f534400 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S @@ -54,6 +54,7 @@  #include <asm/ftrace.h>  #include <asm/irq_vectors.h>  #include <asm/cpufeature.h> +#include <asm/alternative-asm.h>  /* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this.  */  #include <linux/elf-em.h> @@ -873,12 +874,7 @@ ENTRY(simd_coprocessor_error)  661:	pushl_cfi $do_general_protection  662:  .section .altinstructions,"a" -	.balign 4 -	.long 661b -	.long 663f -	.word X86_FEATURE_XMM -	.byte 662b-661b -	.byte 664f-663f +	altinstruction_entry 661b, 663f, X86_FEATURE_XMM, 662b-661b, 664f-663f  .previous  .section .altinstr_replacement,"ax"  663:	pushl $do_simd_coprocessor_error diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index e13329d800c..6419bb05ecd 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S @@ -1111,7 +1111,6 @@ zeroentry spurious_interrupt_bug do_spurious_interrupt_bug  zeroentry coprocessor_error do_coprocessor_error  errorentry alignment_check do_alignment_check  zeroentry simd_coprocessor_error do_simd_coprocessor_error -zeroentry emulate_vsyscall do_emulate_vsyscall  	/* Reload gs selector with exception handling */ diff --git a/arch/x86/kernel/i8259.c b/arch/x86/kernel/i8259.c index 65b8f5c2eeb..610485223bd 100644 --- a/arch/x86/kernel/i8259.c +++ b/arch/x86/kernel/i8259.c @@ -14,7 +14,7 @@  #include <linux/io.h>  #include <linux/delay.h> -#include <asm/atomic.h> +#include <linux/atomic.h>  #include <asm/system.h>  #include <asm/timer.h>  #include <asm/hw_irq.h> diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c index f09d4bbe2d2..b3300e6bace 100644 --- a/arch/x86/kernel/irqinit.c +++ b/arch/x86/kernel/irqinit.c @@ -15,7 +15,7 @@  #include <linux/io.h>  #include <linux/delay.h> -#include <asm/atomic.h> +#include <linux/atomic.h>  #include <asm/system.h>  #include <asm/timer.h>  #include <asm/hw_irq.h> diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index 613a7931ecc..d90272e6bc4 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c @@ -307,6 +307,10 @@ struct pv_info pv_info = {  	.paravirt_enabled = 0,  	.kernel_rpl = 0,  	.shared_kernel_pmd = 1,	/* Only used when CONFIG_X86_PAE is set */ + +#ifdef CONFIG_X86_64 +	.extra_user_64bit_cs = __USER_CS, +#endif  };  struct pv_init_ops pv_init_ops = { diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index e1ba8cb24e4..e7e3b019c43 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -438,29 +438,6 @@ void cpu_idle_wait(void)  }  EXPORT_SYMBOL_GPL(cpu_idle_wait); -/* - * This uses new MONITOR/MWAIT instructions on P4 processors with PNI, - * which can obviate IPI to trigger checking of need_resched. - * We execute MONITOR against need_resched and enter optimized wait state - * through MWAIT. Whenever someone changes need_resched, we would be woken - * up from MWAIT (without an IPI). - * - * New with Core Duo processors, MWAIT can take some hints based on CPU - * capability. - */ -void mwait_idle_with_hints(unsigned long ax, unsigned long cx) -{ -	if (!need_resched()) { -		if (this_cpu_has(X86_FEATURE_CLFLUSH_MONITOR)) -			clflush((void *)¤t_thread_info()->flags); - -		__monitor((void *)¤t_thread_info()->flags, 0, 0); -		smp_mb(); -		if (!need_resched()) -			__mwait(ax, cx); -	} -} -  /* Default MONITOR/MWAIT with no hints, used for default C1 state */  static void mwait_idle(void)  { diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index a069c0c1e2f..2196c703c5e 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -38,6 +38,7 @@  #include <linux/uaccess.h>  #include <linux/io.h>  #include <linux/kdebug.h> +#include <linux/cpuidle.h>  #include <asm/pgtable.h>  #include <asm/system.h> @@ -109,7 +110,8 @@ void cpu_idle(void)  			local_irq_disable();  			/* Don't trace irqs off for idle */  			stop_critical_timings(); -			pm_idle(); +			if (cpuidle_idle_call()) +				pm_idle();  			start_critical_timings();  		}  		tick_nohz_restart_sched_tick(); diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index ca6f7ab8df3..f693e44e1bf 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -37,6 +37,7 @@  #include <linux/uaccess.h>  #include <linux/io.h>  #include <linux/ftrace.h> +#include <linux/cpuidle.h>  #include <asm/pgtable.h>  #include <asm/system.h> @@ -136,7 +137,8 @@ void cpu_idle(void)  			enter_idle();  			/* Don't trace irqs off for idle */  			stop_critical_timings(); -			pm_idle(); +			if (cpuidle_idle_call()) +				pm_idle();  			start_critical_timings();  			/* In many cases the interrupt that ended idle diff --git a/arch/x86/kernel/step.c b/arch/x86/kernel/step.c index 7977f0cfe33..c346d116148 100644 --- a/arch/x86/kernel/step.c +++ b/arch/x86/kernel/step.c @@ -74,7 +74,7 @@ static int is_setting_trap_flag(struct task_struct *child, struct pt_regs *regs)  #ifdef CONFIG_X86_64  		case 0x40 ... 0x4f: -			if (regs->cs != __USER_CS) +			if (!user_64bit_mode(regs))  				/* 32-bit mode: register increment */  				return 0;  			/* 64-bit mode: REX prefix */ diff --git a/arch/x86/kernel/syscall_table_32.S b/arch/x86/kernel/syscall_table_32.S index fbb0a045a1a..bc19be332bc 100644 --- a/arch/x86/kernel/syscall_table_32.S +++ b/arch/x86/kernel/syscall_table_32.S @@ -168,7 +168,7 @@ ENTRY(sys_call_table)  	.long ptregs_vm86  	.long sys_ni_syscall	/* Old sys_query_module */  	.long sys_poll -	.long sys_nfsservctl +	.long sys_ni_syscall	/* Old nfsservctl */  	.long sys_setresgid16	/* 170 */  	.long sys_getresgid16  	.long sys_prctl diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index fbc097a085c..6913369c234 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -49,7 +49,7 @@  #include <asm/stacktrace.h>  #include <asm/processor.h>  #include <asm/debugreg.h> -#include <asm/atomic.h> +#include <linux/atomic.h>  #include <asm/system.h>  #include <asm/traps.h>  #include <asm/desc.h> @@ -872,12 +872,6 @@ void __init trap_init(void)  	set_bit(SYSCALL_VECTOR, used_vectors);  #endif -#ifdef CONFIG_X86_64 -	BUG_ON(test_bit(VSYSCALL_EMU_VECTOR, used_vectors)); -	set_system_intr_gate(VSYSCALL_EMU_VECTOR, &emulate_vsyscall); -	set_bit(VSYSCALL_EMU_VECTOR, used_vectors); -#endif -  	/*  	 * Should be a barrier for any external CPU state:  	 */ diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S index 4aa9c54a9b7..0f703f10901 100644 --- a/arch/x86/kernel/vmlinux.lds.S +++ b/arch/x86/kernel/vmlinux.lds.S @@ -71,7 +71,6 @@ PHDRS {  	text PT_LOAD FLAGS(5);          /* R_E */  	data PT_LOAD FLAGS(6);          /* RW_ */  #ifdef CONFIG_X86_64 -	user PT_LOAD FLAGS(5);          /* R_E */  #ifdef CONFIG_SMP  	percpu PT_LOAD FLAGS(6);        /* RW_ */  #endif @@ -154,44 +153,16 @@ SECTIONS  #ifdef CONFIG_X86_64 -#define VSYSCALL_ADDR (-10*1024*1024) - -#define VLOAD_OFFSET (VSYSCALL_ADDR - __vsyscall_0 + LOAD_OFFSET) -#define VLOAD(x) (ADDR(x) - VLOAD_OFFSET) - -#define VVIRT_OFFSET (VSYSCALL_ADDR - __vsyscall_0) -#define VVIRT(x) (ADDR(x) - VVIRT_OFFSET) - -	. = ALIGN(4096); -	__vsyscall_0 = .; - -	. = VSYSCALL_ADDR; -	.vsyscall : AT(VLOAD(.vsyscall)) { -		*(.vsyscall_0) - -		. = 1024; -		*(.vsyscall_1) - -		. = 2048; -		*(.vsyscall_2) - -		. = 4096;  /* Pad the whole page. */ -	} :user =0xcc -	. = ALIGN(__vsyscall_0 + PAGE_SIZE, PAGE_SIZE); - -#undef VSYSCALL_ADDR -#undef VLOAD_OFFSET -#undef VLOAD -#undef VVIRT_OFFSET -#undef VVIRT - +	. = ALIGN(PAGE_SIZE);  	__vvar_page = .;  	.vvar : AT(ADDR(.vvar) - LOAD_OFFSET) { +		/* work around gold bug 13023 */ +		__vvar_beginning_hack = .; -	      /* Place all vvars at the offsets in asm/vvar.h. */ -#define EMIT_VVAR(name, offset) 		\ -		. = offset;		\ +		/* Place all vvars at the offsets in asm/vvar.h. */ +#define EMIT_VVAR(name, offset) 			\ +		. = __vvar_beginning_hack + offset;	\  		*(.vvar_ ## name)  #define __VVAR_KERNEL_LDS  #include <asm/vvar.h> diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c index dda7dff9cef..18ae83dd1cd 100644 --- a/arch/x86/kernel/vsyscall_64.c +++ b/arch/x86/kernel/vsyscall_64.c @@ -18,9 +18,6 @@   *  use the vDSO.   */ -/* Disable profiling for userspace code: */ -#define DISABLE_BRANCH_PROFILING -  #include <linux/time.h>  #include <linux/init.h>  #include <linux/kernel.h> @@ -50,12 +47,36 @@  #include <asm/vgtod.h>  #include <asm/traps.h> +#define CREATE_TRACE_POINTS +#include "vsyscall_trace.h" +  DEFINE_VVAR(int, vgetcpu_mode);  DEFINE_VVAR(struct vsyscall_gtod_data, vsyscall_gtod_data) =  {  	.lock = __SEQLOCK_UNLOCKED(__vsyscall_gtod_data.lock),  }; +static enum { EMULATE, NATIVE, NONE } vsyscall_mode = EMULATE; + +static int __init vsyscall_setup(char *str) +{ +	if (str) { +		if (!strcmp("emulate", str)) +			vsyscall_mode = EMULATE; +		else if (!strcmp("native", str)) +			vsyscall_mode = NATIVE; +		else if (!strcmp("none", str)) +			vsyscall_mode = NONE; +		else +			return -EINVAL; + +		return 0; +	} + +	return -EINVAL; +} +early_param("vsyscall", vsyscall_setup); +  void update_vsyscall_tz(void)  {  	unsigned long flags; @@ -100,7 +121,7 @@ static void warn_bad_vsyscall(const char *level, struct pt_regs *regs,  	printk("%s%s[%d] %s ip:%lx cs:%lx sp:%lx ax:%lx si:%lx di:%lx\n",  	       level, tsk->comm, task_pid_nr(tsk), -	       message, regs->ip - 2, regs->cs, +	       message, regs->ip, regs->cs,  	       regs->sp, regs->ax, regs->si, regs->di);  } @@ -118,46 +139,39 @@ static int addr_to_vsyscall_nr(unsigned long addr)  	return nr;  } -void dotraplinkage do_emulate_vsyscall(struct pt_regs *regs, long error_code) +bool emulate_vsyscall(struct pt_regs *regs, unsigned long address)  {  	struct task_struct *tsk;  	unsigned long caller;  	int vsyscall_nr;  	long ret; -	local_irq_enable(); -  	/* -	 * Real 64-bit user mode code has cs == __USER_CS.  Anything else -	 * is bogus. +	 * No point in checking CS -- the only way to get here is a user mode +	 * trap to a high address, which means that we're in 64-bit user code.  	 */ -	if (regs->cs != __USER_CS) { -		/* -		 * If we trapped from kernel mode, we might as well OOPS now -		 * instead of returning to some random address and OOPSing -		 * then. -		 */ -		BUG_ON(!user_mode(regs)); -		/* Compat mode and non-compat 32-bit CS should both segfault. */ -		warn_bad_vsyscall(KERN_WARNING, regs, -				  "illegal int 0xcc from 32-bit mode"); -		goto sigsegv; +	WARN_ON_ONCE(address != regs->ip); + +	if (vsyscall_mode == NONE) { +		warn_bad_vsyscall(KERN_INFO, regs, +				  "vsyscall attempted with vsyscall=none"); +		return false;  	} -	/* -	 * x86-ism here: regs->ip points to the instruction after the int 0xcc, -	 * and int 0xcc is two bytes long. -	 */ -	vsyscall_nr = addr_to_vsyscall_nr(regs->ip - 2); +	vsyscall_nr = addr_to_vsyscall_nr(address); + +	trace_emulate_vsyscall(vsyscall_nr); +  	if (vsyscall_nr < 0) {  		warn_bad_vsyscall(KERN_WARNING, regs, -				  "illegal int 0xcc (exploit attempt?)"); +				  "misaligned vsyscall (exploit attempt or buggy program) -- look up the vsyscall kernel parameter if you need a workaround");  		goto sigsegv;  	}  	if (get_user(caller, (unsigned long __user *)regs->sp) != 0) { -		warn_bad_vsyscall(KERN_WARNING, regs, "int 0xcc with bad stack (exploit attempt?)"); +		warn_bad_vsyscall(KERN_WARNING, regs, +				  "vsyscall with bad stack (exploit attempt?)");  		goto sigsegv;  	} @@ -202,13 +216,11 @@ void dotraplinkage do_emulate_vsyscall(struct pt_regs *regs, long error_code)  	regs->ip = caller;  	regs->sp += 8; -	local_irq_disable(); -	return; +	return true;  sigsegv: -	regs->ip -= 2;  /* The faulting instruction should be the int 0xcc. */  	force_sig(SIGSEGV, current); -	local_irq_disable(); +	return true;  }  /* @@ -256,15 +268,21 @@ cpu_vsyscall_notifier(struct notifier_block *n, unsigned long action, void *arg)  void __init map_vsyscall(void)  { -	extern char __vsyscall_0; -	unsigned long physaddr_page0 = __pa_symbol(&__vsyscall_0); +	extern char __vsyscall_page; +	unsigned long physaddr_vsyscall = __pa_symbol(&__vsyscall_page);  	extern char __vvar_page;  	unsigned long physaddr_vvar_page = __pa_symbol(&__vvar_page); -	/* Note that VSYSCALL_MAPPED_PAGES must agree with the code below. */ -	__set_fixmap(VSYSCALL_FIRST_PAGE, physaddr_page0, PAGE_KERNEL_VSYSCALL); +	__set_fixmap(VSYSCALL_FIRST_PAGE, physaddr_vsyscall, +		     vsyscall_mode == NATIVE +		     ? PAGE_KERNEL_VSYSCALL +		     : PAGE_KERNEL_VVAR); +	BUILD_BUG_ON((unsigned long)__fix_to_virt(VSYSCALL_FIRST_PAGE) != +		     (unsigned long)VSYSCALL_START); +  	__set_fixmap(VVAR_PAGE, physaddr_vvar_page, PAGE_KERNEL_VVAR); -	BUILD_BUG_ON((unsigned long)__fix_to_virt(VVAR_PAGE) != (unsigned long)VVAR_ADDRESS); +	BUILD_BUG_ON((unsigned long)__fix_to_virt(VVAR_PAGE) != +		     (unsigned long)VVAR_ADDRESS);  }  static int __init vsyscall_init(void) diff --git a/arch/x86/kernel/vsyscall_emu_64.S b/arch/x86/kernel/vsyscall_emu_64.S index ffa845eae5c..c9596a9af15 100644 --- a/arch/x86/kernel/vsyscall_emu_64.S +++ b/arch/x86/kernel/vsyscall_emu_64.S @@ -7,21 +7,31 @@   */  #include <linux/linkage.h> +  #include <asm/irq_vectors.h> +#include <asm/page_types.h> +#include <asm/unistd_64.h> + +__PAGE_ALIGNED_DATA +	.globl __vsyscall_page +	.balign PAGE_SIZE, 0xcc +	.type __vsyscall_page, @object +__vsyscall_page: + +	mov $__NR_gettimeofday, %rax +	syscall +	ret -/* The unused parts of the page are filled with 0xcc by the linker script. */ +	.balign 1024, 0xcc +	mov $__NR_time, %rax +	syscall +	ret -.section .vsyscall_0, "a" -ENTRY(vsyscall_0) -	int $VSYSCALL_EMU_VECTOR -END(vsyscall_0) +	.balign 1024, 0xcc +	mov $__NR_getcpu, %rax +	syscall +	ret -.section .vsyscall_1, "a" -ENTRY(vsyscall_1) -	int $VSYSCALL_EMU_VECTOR -END(vsyscall_1) +	.balign 4096, 0xcc -.section .vsyscall_2, "a" -ENTRY(vsyscall_2) -	int $VSYSCALL_EMU_VECTOR -END(vsyscall_2) +	.size __vsyscall_page, 4096 diff --git a/arch/x86/kernel/vsyscall_trace.h b/arch/x86/kernel/vsyscall_trace.h new file mode 100644 index 00000000000..a8b2edec54f --- /dev/null +++ b/arch/x86/kernel/vsyscall_trace.h @@ -0,0 +1,29 @@ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM vsyscall + +#if !defined(__VSYSCALL_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) +#define __VSYSCALL_TRACE_H + +#include <linux/tracepoint.h> + +TRACE_EVENT(emulate_vsyscall, + +	    TP_PROTO(int nr), + +	    TP_ARGS(nr), + +	    TP_STRUCT__entry(__field(int, nr)), + +	    TP_fast_assign( +			   __entry->nr = nr; +			   ), + +	    TP_printk("nr = %d", __entry->nr) +); + +#endif + +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH ../../arch/x86/kernel +#define TRACE_INCLUDE_FILE vsyscall_trace +#include <trace/define_trace.h>  |