2 * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL
7 #include "linux/sched.h"
8 #include "linux/slab.h"
9 #include "asm/pgalloc.h"
10 #include "asm/pgtable.h"
11 #include "as-layout.h"
15 extern int __syscall_stub_start
;
17 static int init_stub_pte(struct mm_struct
*mm
, unsigned long proc
,
25 pgd
= pgd_offset(mm
, proc
);
26 pud
= pud_alloc(mm
, pgd
, proc
);
30 pmd
= pmd_alloc(mm
, pud
, proc
);
34 pte
= pte_alloc_map(mm
, NULL
, pmd
, proc
);
38 *pte
= mk_pte(virt_to_page(kernel
), __pgprot(_PAGE_PRESENT
));
39 *pte
= pte_mkread(*pte
);
50 int init_new_context(struct task_struct
*task
, struct mm_struct
*mm
)
52 struct mm_context
*from_mm
= NULL
;
53 struct mm_context
*to_mm
= &mm
->context
;
54 unsigned long stack
= 0;
57 if (skas_needs_stub
) {
58 stack
= get_zeroed_page(GFP_KERNEL
);
63 to_mm
->id
.stack
= stack
;
64 if (current
->mm
!= NULL
&& current
->mm
!= &init_mm
)
65 from_mm
= ¤t
->mm
->context
;
70 printk(KERN_ERR
"init_new_context_skas - "
71 "new_mm failed, errno = %d\n", ret
);
74 to_mm
->id
.u
.mm_fd
= ret
;
78 to_mm
->id
.u
.pid
= copy_context_skas0(stack
,
80 else to_mm
->id
.u
.pid
= start_userspace(stack
);
82 if (to_mm
->id
.u
.pid
< 0) {
83 ret
= to_mm
->id
.u
.pid
;
88 ret
= init_new_ldt(to_mm
, from_mm
);
90 printk(KERN_ERR
"init_new_context_skas - init_ldt"
91 " failed, errno = %d\n", ret
);
95 to_mm
->stub_pages
= NULL
;
100 if (to_mm
->id
.stack
!= 0)
101 free_page(to_mm
->id
.stack
);
106 void arch_dup_mmap(struct mm_struct
*oldmm
, struct mm_struct
*mm
)
111 if (!skas_needs_stub
)
114 ret
= init_stub_pte(mm
, STUB_CODE
,
115 (unsigned long) &__syscall_stub_start
);
119 ret
= init_stub_pte(mm
, STUB_DATA
, mm
->context
.id
.stack
);
123 pages
= kmalloc(2 * sizeof(struct page
*), GFP_KERNEL
);
125 printk(KERN_ERR
"arch_dup_mmap failed to allocate 2 page "
130 pages
[0] = virt_to_page(&__syscall_stub_start
);
131 pages
[1] = virt_to_page(mm
->context
.id
.stack
);
132 mm
->context
.stub_pages
= pages
;
134 /* dup_mmap already holds mmap_sem */
135 err
= install_special_mapping(mm
, STUB_START
, STUB_END
- STUB_START
,
136 VM_READ
| VM_MAYREAD
| VM_EXEC
|
137 VM_MAYEXEC
| VM_DONTCOPY
, pages
);
139 printk(KERN_ERR
"install_special_mapping returned %d\n", err
);
147 force_sigsegv(SIGSEGV
, current
);
150 void arch_exit_mmap(struct mm_struct
*mm
)
154 if (mm
->context
.stub_pages
!= NULL
)
155 kfree(mm
->context
.stub_pages
);
156 pte
= virt_to_pte(mm
, STUB_CODE
);
158 pte_clear(mm
, STUB_CODE
, pte
);
160 pte
= virt_to_pte(mm
, STUB_DATA
);
164 pte_clear(mm
, STUB_DATA
, pte
);
167 void destroy_context(struct mm_struct
*mm
)
169 struct mm_context
*mmu
= &mm
->context
;
172 os_close_file(mmu
->id
.u
.mm_fd
);
175 * If init_new_context wasn't called, this will be
176 * zero, resulting in a kill(0), which will result in the
177 * whole UML suddenly dying. Also, cover negative and
178 * 1 cases, since they shouldn't happen either.
180 if (mmu
->id
.u
.pid
< 2) {
181 printk(KERN_ERR
"corrupt mm_context - pid = %d\n",
185 os_kill_ptraced_process(mmu
->id
.u
.pid
, 1);
189 free_page(mmu
->id
.stack
);