ia64/xen-unstable

view linux-2.6-xen-sparse/arch/i386/kernel/sysenter.c @ 13487:e7eb9b7613bb

[linux] remove gratuitous differences with plain linux.

Signed-off-by: Christian Limpach <Christian.Limpach@xensource.com>
author Christian Limpach <Christian.Limpach@xensource.com>
date Thu Jan 18 15:33:59 2007 +0000 (2007-01-18)
parents 44caba9460af
children 3c8bb086025e
line source
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 */
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 #include <linux/mm.h>
18 #include <asm/cpufeature.h>
19 #include <asm/msr.h>
20 #include <asm/pgtable.h>
21 #include <asm/unistd.h>
23 #ifdef CONFIG_XEN
24 #include <xen/interface/callback.h>
25 #endif
27 extern asmlinkage void sysenter_entry(void);
29 void enable_sep_cpu(void)
30 {
31 #ifndef CONFIG_X86_NO_TSS
32 int cpu = get_cpu();
33 struct tss_struct *tss = &per_cpu(init_tss, cpu);
35 if (!boot_cpu_has(X86_FEATURE_SEP)) {
36 put_cpu();
37 return;
38 }
40 tss->ss1 = __KERNEL_CS;
41 tss->esp1 = sizeof(struct tss_struct) + (unsigned long) tss;
42 wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0);
43 wrmsr(MSR_IA32_SYSENTER_ESP, tss->esp1, 0);
44 wrmsr(MSR_IA32_SYSENTER_EIP, (unsigned long) sysenter_entry, 0);
45 put_cpu();
46 #endif
47 }
49 /*
50 * These symbols are defined by vsyscall.o to mark the bounds
51 * of the ELF DSO images included therein.
52 */
53 extern const char vsyscall_int80_start, vsyscall_int80_end;
54 extern const char vsyscall_sysenter_start, vsyscall_sysenter_end;
55 static void *syscall_page;
57 int __init sysenter_setup(void)
58 {
59 void *page = (void *)get_zeroed_page(GFP_ATOMIC);
61 syscall_page = page;
63 #ifdef CONFIG_XEN
64 if (boot_cpu_has(X86_FEATURE_SEP)) {
65 static struct callback_register __initdata sysenter = {
66 .type = CALLBACKTYPE_sysenter,
67 .address = { __KERNEL_CS, (unsigned long)sysenter_entry },
68 };
70 if (HYPERVISOR_callback_op(CALLBACKOP_register, &sysenter) < 0)
71 clear_bit(X86_FEATURE_SEP, boot_cpu_data.x86_capability);
72 }
73 #endif
75 if (!boot_cpu_has(X86_FEATURE_SEP)) {
76 memcpy(page,
77 &vsyscall_int80_start,
78 &vsyscall_int80_end - &vsyscall_int80_start);
79 return 0;
80 }
82 memcpy(page,
83 &vsyscall_sysenter_start,
84 &vsyscall_sysenter_end - &vsyscall_sysenter_start);
86 return 0;
87 }
89 static struct page*
90 syscall_nopage(struct vm_area_struct *vma, unsigned long adr, int *type)
91 {
92 struct page *p = virt_to_page(adr - vma->vm_start + syscall_page);
93 get_page(p);
94 return p;
95 }
97 /* Prevent VMA merging */
98 static void syscall_vma_close(struct vm_area_struct *vma)
99 {
100 }
102 static struct vm_operations_struct syscall_vm_ops = {
103 .close = syscall_vma_close,
104 .nopage = syscall_nopage,
105 };
107 /* Setup a VMA at program startup for the vsyscall page */
108 int arch_setup_additional_pages(struct linux_binprm *bprm, int exstack)
109 {
110 struct vm_area_struct *vma;
111 struct mm_struct *mm = current->mm;
112 int ret;
114 vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
115 if (!vma)
116 return -ENOMEM;
118 memset(vma, 0, sizeof(struct vm_area_struct));
119 /* Could randomize here */
120 vma->vm_start = VSYSCALL_BASE;
121 vma->vm_end = VSYSCALL_BASE + PAGE_SIZE;
122 /* MAYWRITE to allow gdb to COW and set breakpoints */
123 vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYEXEC|VM_MAYWRITE;
124 vma->vm_flags |= mm->def_flags;
125 vma->vm_page_prot = protection_map[vma->vm_flags & 7];
126 vma->vm_ops = &syscall_vm_ops;
127 vma->vm_mm = mm;
129 down_write(&mm->mmap_sem);
130 if ((ret = insert_vm_struct(mm, vma))) {
131 up_write(&mm->mmap_sem);
132 kmem_cache_free(vm_area_cachep, vma);
133 return ret;
134 }
135 mm->total_vm++;
136 up_write(&mm->mmap_sem);
137 return 0;
138 }
140 struct vm_area_struct *get_gate_vma(struct task_struct *tsk)
141 {
142 return NULL;
143 }
145 int in_gate_area(struct task_struct *task, unsigned long addr)
146 {
147 return 0;
148 }
150 int in_gate_area_no_task(unsigned long addr)
151 {
152 return 0;
153 }