Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * linux/arch/i386/kernel/sysenter.c | |
3 | * | |
4 | * (C) Copyright 2002 Linus Torvalds | |
5 | * | |
6 | * This file contains the needed initializations to support sysenter. | |
7 | */ | |
8 | ||
9 | #include <linux/init.h> | |
10 | #include <linux/smp.h> | |
11 | #include <linux/thread_info.h> | |
12 | #include <linux/sched.h> | |
13 | #include <linux/gfp.h> | |
14 | #include <linux/string.h> | |
15 | #include <linux/elf.h> | |
16 | ||
17 | #include <asm/cpufeature.h> | |
18 | #include <asm/msr.h> | |
19 | #include <asm/pgtable.h> | |
20 | #include <asm/unistd.h> | |
21 | ||
22 | extern asmlinkage void sysenter_entry(void); | |
23 | ||
6fe940d6 | 24 | void enable_sep_cpu(void) |
1da177e4 LT |
25 | { |
26 | int cpu = get_cpu(); | |
27 | struct tss_struct *tss = &per_cpu(init_tss, cpu); | |
28 | ||
6fe940d6 LS |
29 | if (!boot_cpu_has(X86_FEATURE_SEP)) { |
30 | put_cpu(); | |
31 | return; | |
32 | } | |
33 | ||
1da177e4 LT |
34 | tss->ss1 = __KERNEL_CS; |
35 | tss->esp1 = sizeof(struct tss_struct) + (unsigned long) tss; | |
36 | wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0); | |
37 | wrmsr(MSR_IA32_SYSENTER_ESP, tss->esp1, 0); | |
38 | wrmsr(MSR_IA32_SYSENTER_EIP, (unsigned long) sysenter_entry, 0); | |
39 | put_cpu(); | |
40 | } | |
41 | ||
42 | /* | |
43 | * These symbols are defined by vsyscall.o to mark the bounds | |
44 | * of the ELF DSO images included therein. | |
45 | */ | |
46 | extern const char vsyscall_int80_start, vsyscall_int80_end; | |
47 | extern const char vsyscall_sysenter_start, vsyscall_sysenter_end; | |
48 | ||
6fe940d6 | 49 | int __init sysenter_setup(void) |
1da177e4 LT |
50 | { |
51 | void *page = (void *)get_zeroed_page(GFP_ATOMIC); | |
52 | ||
53 | __set_fixmap(FIX_VSYSCALL, __pa(page), PAGE_READONLY_EXEC); | |
54 | ||
55 | if (!boot_cpu_has(X86_FEATURE_SEP)) { | |
56 | memcpy(page, | |
57 | &vsyscall_int80_start, | |
58 | &vsyscall_int80_end - &vsyscall_int80_start); | |
59 | return 0; | |
60 | } | |
61 | ||
62 | memcpy(page, | |
63 | &vsyscall_sysenter_start, | |
64 | &vsyscall_sysenter_end - &vsyscall_sysenter_start); | |
65 | ||
1da177e4 LT |
66 | return 0; |
67 | } |