Blame view
arch/um/sys-i386/ldt.c
11.6 KB
1da177e4c Linux-2.6.12-rc2 |
1 |
/* |
ba180fd43 uml: style fixes ... |
2 |
* Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
1da177e4c Linux-2.6.12-rc2 |
3 4 |
* Licensed under the GPL */ |
8192ab42b uml: header untan... |
5 6 |
#include <linux/mm.h> #include <linux/sched.h> |
5a0e3ad6a include cleanup: ... |
7 |
#include <linux/slab.h> |
8192ab42b uml: header untan... |
8 |
#include <asm/unistd.h> |
12919aa6e [PATCH] uml: move... |
9 |
#include "os.h" |
ba180fd43 uml: style fixes ... |
10 |
#include "proc_mm.h" |
858259cf7 [PATCH] uml: main... |
11 12 |
#include "skas.h" #include "skas_ptrace.h" |
ba180fd43 uml: style fixes ... |
13 14 15 |
#include "sysdep/tls.h" extern int modify_ldt(int func, void *ptr, unsigned long bytecount); |
858259cf7 [PATCH] uml: main... |
16 |
|
99764fa4c UML: make several... |
17 18 |
static long write_ldt_entry(struct mm_id *mm_idp, int func, struct user_desc *desc, void **addr, int done) |
858259cf7 [PATCH] uml: main... |
19 20 |
{ long res; |
ba180fd43 uml: style fixes ... |
21 22 23 |
if (proc_mm) { /* * This is a special handling for the case, that the mm to |
858259cf7 [PATCH] uml: main... |
24 25 26 |
* modify isn't current->active_mm. * If this is called directly by modify_ldt, * (current->active_mm->context.skas.u == mm_idp) |
77bf44003 uml: remove code ... |
27 |
* will be true. So no call to __switch_mm(mm_idp) is done. |
858259cf7 [PATCH] uml: main... |
28 29 30 31 32 |
* If this is called in case of init_new_ldt or PTRACE_LDT, * mm_idp won't belong to current->active_mm, but child->mm. * So we need to switch child's mm into our userspace, then * later switch back. * |
07f4e2c61 [PATCH] uml: fix ... |
33 |
* Note: I'm unsure: should interrupts be disabled here? |
858259cf7 [PATCH] uml: main... |
34 |
*/ |
ba180fd43 uml: style fixes ... |
35 |
if (!current->active_mm || current->active_mm == &init_mm || |
6c738ffa9 uml: fold mmu_con... |
36 |
mm_idp != ¤t->active_mm->context.id) |
77bf44003 uml: remove code ... |
37 |
__switch_mm(mm_idp); |
858259cf7 [PATCH] uml: main... |
38 |
} |
ba180fd43 uml: style fixes ... |
39 |
if (ptrace_ldt) { |
858259cf7 [PATCH] uml: main... |
40 41 42 43 44 45 |
struct ptrace_ldt ldt_op = (struct ptrace_ldt) { .func = func, .ptr = desc, .bytecount = sizeof(*desc)}; u32 cpu; int pid; |
ba180fd43 uml: style fixes ... |
46 |
if (!proc_mm) |
858259cf7 [PATCH] uml: main... |
47 48 49 50 51 |
pid = mm_idp->u.pid; else { cpu = get_cpu(); pid = userspace_pid[cpu]; } |
07f4e2c61 [PATCH] uml: fix ... |
52 |
res = os_ptrace_ldt(pid, 0, (unsigned long) &ldt_op); |
858259cf7 [PATCH] uml: main... |
53 |
|
ba180fd43 uml: style fixes ... |
54 |
if (proc_mm) |
858259cf7 [PATCH] uml: main... |
55 56 57 58 59 60 61 62 |
put_cpu(); } else { void *stub_addr; res = syscall_stub_data(mm_idp, (unsigned long *)desc, (sizeof(*desc) + sizeof(long) - 1) & ~(sizeof(long) - 1), addr, &stub_addr); |
ba180fd43 uml: style fixes ... |
63 |
if (!res) { |
858259cf7 [PATCH] uml: main... |
64 65 66 67 68 69 70 71 |
unsigned long args[] = { func, (unsigned long)stub_addr, sizeof(*desc), 0, 0, 0 }; res = run_syscall_stub(mm_idp, __NR_modify_ldt, args, 0, addr, done); } } |
ba180fd43 uml: style fixes ... |
72 73 74 |
if (proc_mm) { /* * This is the second part of special handling, that makes |
858259cf7 [PATCH] uml: main... |
75 76 |
* PTRACE_LDT possible to implement. */ |
ba180fd43 uml: style fixes ... |
77 |
if (current->active_mm && current->active_mm != &init_mm && |
6c738ffa9 uml: fold mmu_con... |
78 79 |
mm_idp != ¤t->active_mm->context.id) __switch_mm(¤t->active_mm->context.id); |
858259cf7 [PATCH] uml: main... |
80 81 82 83 84 85 86 87 88 89 90 |
} return res; } static long read_ldt_from_host(void __user * ptr, unsigned long bytecount) { int res, n; struct ptrace_ldt ptrace_ldt = (struct ptrace_ldt) { .func = 0, .bytecount = bytecount, |
5cbded585 [PATCH] getting r... |
91 |
.ptr = kmalloc(bytecount, GFP_KERNEL)}; |
858259cf7 [PATCH] uml: main... |
92 |
u32 cpu; |
ba180fd43 uml: style fixes ... |
93 |
if (ptrace_ldt.ptr == NULL) |
858259cf7 [PATCH] uml: main... |
94 |
return -ENOMEM; |
ba180fd43 uml: style fixes ... |
95 96 |
/* * This is called from sys_modify_ldt only, so userspace_pid gives |
858259cf7 [PATCH] uml: main... |
97 98 99 100 |
* us the right number */ cpu = get_cpu(); |
07f4e2c61 [PATCH] uml: fix ... |
101 |
res = os_ptrace_ldt(userspace_pid[cpu], 0, (unsigned long) &ptrace_ldt); |
858259cf7 [PATCH] uml: main... |
102 |
put_cpu(); |
ba180fd43 uml: style fixes ... |
103 |
if (res < 0) |
858259cf7 [PATCH] uml: main... |
104 105 106 |
goto out; n = copy_to_user(ptr, ptrace_ldt.ptr, res); |
ba180fd43 uml: style fixes ... |
107 |
if (n != 0) |
858259cf7 [PATCH] uml: main... |
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
res = -EFAULT; out: kfree(ptrace_ldt.ptr); return res; } /* * In skas mode, we hold our own ldt data in UML. * Thus, the code implementing sys_modify_ldt_skas * is very similar to (and mostly stolen from) sys_modify_ldt * for arch/i386/kernel/ldt.c * The routines copied and modified in part are: * - read_ldt * - read_default_ldt * - write_ldt * - sys_modify_ldt_skas */ static int read_ldt(void __user * ptr, unsigned long bytecount) { int i, err = 0; unsigned long size; |
6c738ffa9 uml: fold mmu_con... |
132 |
uml_ldt_t * ldt = ¤t->mm->context.ldt; |
858259cf7 [PATCH] uml: main... |
133 |
|
ba180fd43 uml: style fixes ... |
134 |
if (!ldt->entry_count) |
858259cf7 [PATCH] uml: main... |
135 |
goto out; |
ba180fd43 uml: style fixes ... |
136 |
if (bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES) |
858259cf7 [PATCH] uml: main... |
137 138 |
bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES; err = bytecount; |
ba180fd43 uml: style fixes ... |
139 |
if (ptrace_ldt) |
858259cf7 [PATCH] uml: main... |
140 |
return read_ldt_from_host(ptr, bytecount); |
858259cf7 [PATCH] uml: main... |
141 |
|
01ac835fd uml: LDT mutex co... |
142 |
mutex_lock(&ldt->lock); |
ba180fd43 uml: style fixes ... |
143 |
if (ldt->entry_count <= LDT_DIRECT_ENTRIES) { |
858259cf7 [PATCH] uml: main... |
144 |
size = LDT_ENTRY_SIZE*LDT_DIRECT_ENTRIES; |
ba180fd43 uml: style fixes ... |
145 |
if (size > bytecount) |
858259cf7 [PATCH] uml: main... |
146 |
size = bytecount; |
ba180fd43 uml: style fixes ... |
147 |
if (copy_to_user(ptr, ldt->u.entries, size)) |
858259cf7 [PATCH] uml: main... |
148 149 150 151 152 |
err = -EFAULT; bytecount -= size; ptr += size; } else { |
ba180fd43 uml: style fixes ... |
153 154 |
for (i=0; i<ldt->entry_count/LDT_ENTRIES_PER_PAGE && bytecount; i++) { |
858259cf7 [PATCH] uml: main... |
155 |
size = PAGE_SIZE; |
ba180fd43 uml: style fixes ... |
156 |
if (size > bytecount) |
858259cf7 [PATCH] uml: main... |
157 |
size = bytecount; |
ba180fd43 uml: style fixes ... |
158 |
if (copy_to_user(ptr, ldt->u.pages[i], size)) { |
858259cf7 [PATCH] uml: main... |
159 160 161 162 163 164 165 |
err = -EFAULT; break; } bytecount -= size; ptr += size; } } |
01ac835fd uml: LDT mutex co... |
166 |
mutex_unlock(&ldt->lock); |
858259cf7 [PATCH] uml: main... |
167 |
|
ba180fd43 uml: style fixes ... |
168 |
if (bytecount == 0 || err == -EFAULT) |
858259cf7 [PATCH] uml: main... |
169 |
goto out; |
ba180fd43 uml: style fixes ... |
170 |
if (clear_user(ptr, bytecount)) |
858259cf7 [PATCH] uml: main... |
171 172 173 174 175 176 177 178 179 |
err = -EFAULT; out: return err; } static int read_default_ldt(void __user * ptr, unsigned long bytecount) { int err; |
ba180fd43 uml: style fixes ... |
180 |
if (bytecount > 5*LDT_ENTRY_SIZE) |
858259cf7 [PATCH] uml: main... |
181 182 183 |
bytecount = 5*LDT_ENTRY_SIZE; err = bytecount; |
ba180fd43 uml: style fixes ... |
184 185 |
/* * UML doesn't support lcall7 and lcall27. |
858259cf7 [PATCH] uml: main... |
186 187 188 |
* So, we don't really have a default ldt, but emulate * an empty ldt of common host default ldt size. */ |
ba180fd43 uml: style fixes ... |
189 |
if (clear_user(ptr, bytecount)) |
858259cf7 [PATCH] uml: main... |
190 191 192 193 194 195 196 |
err = -EFAULT; return err; } static int write_ldt(void __user * ptr, unsigned long bytecount, int func) { |
6c738ffa9 uml: fold mmu_con... |
197 198 |
uml_ldt_t * ldt = ¤t->mm->context.ldt; struct mm_id * mm_idp = ¤t->mm->context.id; |
858259cf7 [PATCH] uml: main... |
199 200 201 202 203 204 |
int i, err; struct user_desc ldt_info; struct ldt_entry entry0, *ldt_p; void *addr = NULL; err = -EINVAL; |
ba180fd43 uml: style fixes ... |
205 |
if (bytecount != sizeof(ldt_info)) |
858259cf7 [PATCH] uml: main... |
206 207 |
goto out; err = -EFAULT; |
ba180fd43 uml: style fixes ... |
208 |
if (copy_from_user(&ldt_info, ptr, sizeof(ldt_info))) |
858259cf7 [PATCH] uml: main... |
209 210 211 |
goto out; err = -EINVAL; |
ba180fd43 uml: style fixes ... |
212 |
if (ldt_info.entry_number >= LDT_ENTRIES) |
858259cf7 [PATCH] uml: main... |
213 |
goto out; |
ba180fd43 uml: style fixes ... |
214 |
if (ldt_info.contents == 3) { |
858259cf7 [PATCH] uml: main... |
215 216 217 218 219 |
if (func == 1) goto out; if (ldt_info.seg_not_present == 0) goto out; } |
ba180fd43 uml: style fixes ... |
220 |
if (!ptrace_ldt) |
01ac835fd uml: LDT mutex co... |
221 |
mutex_lock(&ldt->lock); |
858259cf7 [PATCH] uml: main... |
222 223 |
err = write_ldt_entry(mm_idp, func, &ldt_info, &addr, 1); |
ba180fd43 uml: style fixes ... |
224 |
if (err) |
858259cf7 [PATCH] uml: main... |
225 |
goto out_unlock; |
ba180fd43 uml: style fixes ... |
226 227 228 229 230 231 232 233 234 235 236 237 |
else if (ptrace_ldt) { /* With PTRACE_LDT available, this is used as a flag only */ ldt->entry_count = 1; goto out; } if (ldt_info.entry_number >= ldt->entry_count && ldt_info.entry_number >= LDT_DIRECT_ENTRIES) { for (i=ldt->entry_count/LDT_ENTRIES_PER_PAGE; i*LDT_ENTRIES_PER_PAGE <= ldt_info.entry_number; i++) { if (i == 0) |
e23181dee [PATCH] uml: elim... |
238 239 240 241 |
memcpy(&entry0, ldt->u.entries, sizeof(entry0)); ldt->u.pages[i] = (struct ldt_entry *) __get_free_page(GFP_KERNEL|__GFP_ZERO); |
ba180fd43 uml: style fixes ... |
242 |
if (!ldt->u.pages[i]) { |
858259cf7 [PATCH] uml: main... |
243 244 245 246 247 248 |
err = -ENOMEM; /* Undo the change in host */ memset(&ldt_info, 0, sizeof(ldt_info)); write_ldt_entry(mm_idp, 1, &ldt_info, &addr, 1); goto out_unlock; } |
ba180fd43 uml: style fixes ... |
249 |
if (i == 0) { |
e23181dee [PATCH] uml: elim... |
250 251 252 |
memcpy(ldt->u.pages[0], &entry0, sizeof(entry0)); memcpy(ldt->u.pages[0]+1, ldt->u.entries+1, |
858259cf7 [PATCH] uml: main... |
253 254 255 256 257 |
sizeof(entry0)*(LDT_DIRECT_ENTRIES-1)); } ldt->entry_count = (i + 1) * LDT_ENTRIES_PER_PAGE; } } |
ba180fd43 uml: style fixes ... |
258 |
if (ldt->entry_count <= ldt_info.entry_number) |
858259cf7 [PATCH] uml: main... |
259 |
ldt->entry_count = ldt_info.entry_number + 1; |
ba180fd43 uml: style fixes ... |
260 |
if (ldt->entry_count <= LDT_DIRECT_ENTRIES) |
e23181dee [PATCH] uml: elim... |
261 |
ldt_p = ldt->u.entries + ldt_info.entry_number; |
858259cf7 [PATCH] uml: main... |
262 |
else |
e23181dee [PATCH] uml: elim... |
263 |
ldt_p = ldt->u.pages[ldt_info.entry_number/LDT_ENTRIES_PER_PAGE] + |
858259cf7 [PATCH] uml: main... |
264 |
ldt_info.entry_number%LDT_ENTRIES_PER_PAGE; |
ba180fd43 uml: style fixes ... |
265 266 |
if (ldt_info.base_addr == 0 && ldt_info.limit == 0 && (func == 1 || LDT_empty(&ldt_info))) { |
858259cf7 [PATCH] uml: main... |
267 268 269 270 271 272 273 274 275 276 277 278 |
ldt_p->a = 0; ldt_p->b = 0; } else{ if (func == 1) ldt_info.useable = 0; ldt_p->a = LDT_entry_a(&ldt_info); ldt_p->b = LDT_entry_b(&ldt_info); } err = 0; out_unlock: |
01ac835fd uml: LDT mutex co... |
279 |
mutex_unlock(&ldt->lock); |
858259cf7 [PATCH] uml: main... |
280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 |
out: return err; } static long do_modify_ldt_skas(int func, void __user *ptr, unsigned long bytecount) { int ret = -ENOSYS; switch (func) { case 0: ret = read_ldt(ptr, bytecount); break; case 1: case 0x11: ret = write_ldt(ptr, bytecount, func); break; case 2: ret = read_default_ldt(ptr, bytecount); break; } return ret; } |
af7279022 [PATCH] uml: fix ... |
303 304 305 |
static DEFINE_SPINLOCK(host_ldt_lock); static short dummy_list[9] = {0, -1}; static short * host_ldt_entries = NULL; |
858259cf7 [PATCH] uml: main... |
306 |
|
af7279022 [PATCH] uml: fix ... |
307 |
static void ldt_get_host_info(void) |
858259cf7 [PATCH] uml: main... |
308 309 |
{ long ret; |
622e69693 [PATCH] uml: fix ... |
310 311 |
struct ldt_entry * ldt; short *tmp; |
858259cf7 [PATCH] uml: main... |
312 |
int i, size, k, order; |
af7279022 [PATCH] uml: fix ... |
313 |
spin_lock(&host_ldt_lock); |
ba180fd43 uml: style fixes ... |
314 |
if (host_ldt_entries != NULL) { |
af7279022 [PATCH] uml: fix ... |
315 316 317 |
spin_unlock(&host_ldt_lock); return; } |
858259cf7 [PATCH] uml: main... |
318 |
host_ldt_entries = dummy_list+1; |
af7279022 [PATCH] uml: fix ... |
319 |
spin_unlock(&host_ldt_lock); |
ba180fd43 uml: style fixes ... |
320 321 |
for (i = LDT_PAGES_MAX-1, order=0; i; i>>=1, order++) ; |
858259cf7 [PATCH] uml: main... |
322 323 324 |
ldt = (struct ldt_entry *) __get_free_pages(GFP_KERNEL|__GFP_ZERO, order); |
ba180fd43 uml: style fixes ... |
325 326 327 328 |
if (ldt == NULL) { printk(KERN_ERR "ldt_get_host_info: couldn't allocate buffer " "for host ldt "); |
858259cf7 [PATCH] uml: main... |
329 330 331 332 |
return; } ret = modify_ldt(0, ldt, (1<<order)*PAGE_SIZE); |
ba180fd43 uml: style fixes ... |
333 334 335 |
if (ret < 0) { printk(KERN_ERR "ldt_get_host_info: couldn't read host ldt "); |
858259cf7 [PATCH] uml: main... |
336 337 |
goto out_free; } |
ba180fd43 uml: style fixes ... |
338 |
if (ret == 0) { |
858259cf7 [PATCH] uml: main... |
339 340 341 342 |
/* default_ldt is active, simply write an empty entry 0 */ host_ldt_entries = dummy_list; goto out_free; } |
ba180fd43 uml: style fixes ... |
343 344 |
for (i=0, size=0; i<ret/LDT_ENTRY_SIZE; i++) { if (ldt[i].a != 0 || ldt[i].b != 0) |
858259cf7 [PATCH] uml: main... |
345 346 |
size++; } |
ba180fd43 uml: style fixes ... |
347 |
if (size < ARRAY_SIZE(dummy_list)) |
858259cf7 [PATCH] uml: main... |
348 |
host_ldt_entries = dummy_list; |
858259cf7 [PATCH] uml: main... |
349 350 |
else { size = (size + 1) * sizeof(dummy_list[0]); |
af7279022 [PATCH] uml: fix ... |
351 |
tmp = kmalloc(size, GFP_KERNEL); |
ba180fd43 uml: style fixes ... |
352 353 354 355 |
if (tmp == NULL) { printk(KERN_ERR "ldt_get_host_info: couldn't allocate " "host ldt list "); |
858259cf7 [PATCH] uml: main... |
356 357 |
goto out_free; } |
af7279022 [PATCH] uml: fix ... |
358 |
host_ldt_entries = tmp; |
858259cf7 [PATCH] uml: main... |
359 |
} |
ba180fd43 uml: style fixes ... |
360 361 |
for (i=0, k=0; i<ret/LDT_ENTRY_SIZE; i++) { if (ldt[i].a != 0 || ldt[i].b != 0) |
858259cf7 [PATCH] uml: main... |
362 |
host_ldt_entries[k++] = i; |
858259cf7 [PATCH] uml: main... |
363 364 365 366 367 368 |
} host_ldt_entries[k] = -1; out_free: free_pages((unsigned long)ldt, order); } |
6c738ffa9 uml: fold mmu_con... |
369 |
long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm) |
858259cf7 [PATCH] uml: main... |
370 371 372 373 374 375 |
{ struct user_desc desc; short * num_p; int i; long page, err=0; void *addr = NULL; |
12919aa6e [PATCH] uml: move... |
376 |
struct proc_mm_op copy; |
858259cf7 [PATCH] uml: main... |
377 |
|
858259cf7 [PATCH] uml: main... |
378 |
|
ba180fd43 uml: style fixes ... |
379 |
if (!ptrace_ldt) |
01ac835fd uml: LDT mutex co... |
380 |
mutex_init(&new_mm->ldt.lock); |
858259cf7 [PATCH] uml: main... |
381 |
|
ba180fd43 uml: style fixes ... |
382 |
if (!from_mm) { |
12919aa6e [PATCH] uml: move... |
383 |
memset(&desc, 0, sizeof(desc)); |
858259cf7 [PATCH] uml: main... |
384 385 386 |
/* * We have to initialize a clean ldt. */ |
ba180fd43 uml: style fixes ... |
387 |
if (proc_mm) { |
858259cf7 [PATCH] uml: main... |
388 389 390 391 392 393 394 |
/* * If the new mm was created using proc_mm, host's * default-ldt currently is assigned, which normally * contains the call-gates for lcall7 and lcall27. * To remove these gates, we simply write an empty * entry as number 0 to the host. */ |
ba180fd43 uml: style fixes ... |
395 |
err = write_ldt_entry(&new_mm->id, 1, &desc, &addr, 1); |
858259cf7 [PATCH] uml: main... |
396 397 398 399 400 401 402 |
} else{ /* * Now we try to retrieve info about the ldt, we * inherited from the host. All ldt-entries found * will be reset in the following loop */ |
af7279022 [PATCH] uml: fix ... |
403 |
ldt_get_host_info(); |
ba180fd43 uml: style fixes ... |
404 |
for (num_p=host_ldt_entries; *num_p != -1; num_p++) { |
858259cf7 [PATCH] uml: main... |
405 406 407 |
desc.entry_number = *num_p; err = write_ldt_entry(&new_mm->id, 1, &desc, &addr, *(num_p + 1) == -1); |
ba180fd43 uml: style fixes ... |
408 |
if (err) |
858259cf7 [PATCH] uml: main... |
409 410 411 412 |
break; } } new_mm->ldt.entry_count = 0; |
12919aa6e [PATCH] uml: move... |
413 414 |
goto out; |
858259cf7 [PATCH] uml: main... |
415 |
} |
12919aa6e [PATCH] uml: move... |
416 |
|
ba180fd43 uml: style fixes ... |
417 418 419 |
if (proc_mm) { /* * We have a valid from_mm, so we now have to copy the LDT of |
12919aa6e [PATCH] uml: move... |
420 421 422 423 424 425 426 |
* from_mm to new_mm, because using proc_mm an new mm with * an empty/default LDT was created in new_mm() */ copy = ((struct proc_mm_op) { .op = MM_COPY_SEGMENTS, .u = { .copy_segments = from_mm->id.u.mm_fd } } ); |
a6ea4ccee uml: rename os_{r... |
427 |
i = os_write_file(new_mm->id.u.mm_fd, ©, sizeof(copy)); |
ba180fd43 uml: style fixes ... |
428 429 430 431 |
if (i != sizeof(copy)) printk(KERN_ERR "new_mm : /proc/mm copy_segments " "failed, err = %d ", -i); |
12919aa6e [PATCH] uml: move... |
432 |
} |
ba180fd43 uml: style fixes ... |
433 434 435 |
if (!ptrace_ldt) { /* * Our local LDT is used to supply the data for |
858259cf7 [PATCH] uml: main... |
436 437 438 439 |
* modify_ldt(READLDT), if PTRACE_LDT isn't available, * i.e., we have to use the stub for modify_ldt, which * can't handle the big read buffer of up to 64kB. */ |
01ac835fd uml: LDT mutex co... |
440 |
mutex_lock(&from_mm->ldt.lock); |
ba180fd43 uml: style fixes ... |
441 |
if (from_mm->ldt.entry_count <= LDT_DIRECT_ENTRIES) |
e23181dee [PATCH] uml: elim... |
442 443 |
memcpy(new_mm->ldt.u.entries, from_mm->ldt.u.entries, sizeof(new_mm->ldt.u.entries)); |
ba180fd43 uml: style fixes ... |
444 |
else { |
858259cf7 [PATCH] uml: main... |
445 |
i = from_mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE; |
ba180fd43 uml: style fixes ... |
446 |
while (i-->0) { |
858259cf7 [PATCH] uml: main... |
447 |
page = __get_free_page(GFP_KERNEL|__GFP_ZERO); |
ba180fd43 uml: style fixes ... |
448 |
if (!page) { |
858259cf7 [PATCH] uml: main... |
449 450 451 |
err = -ENOMEM; break; } |
e23181dee [PATCH] uml: elim... |
452 453 454 455 |
new_mm->ldt.u.pages[i] = (struct ldt_entry *) page; memcpy(new_mm->ldt.u.pages[i], from_mm->ldt.u.pages[i], PAGE_SIZE); |
858259cf7 [PATCH] uml: main... |
456 457 458 |
} } new_mm->ldt.entry_count = from_mm->ldt.entry_count; |
01ac835fd uml: LDT mutex co... |
459 |
mutex_unlock(&from_mm->ldt.lock); |
858259cf7 [PATCH] uml: main... |
460 |
} |
12919aa6e [PATCH] uml: move... |
461 |
out: |
858259cf7 [PATCH] uml: main... |
462 463 |
return err; } |
6c738ffa9 uml: fold mmu_con... |
464 |
void free_ldt(struct mm_context *mm) |
858259cf7 [PATCH] uml: main... |
465 466 |
{ int i; |
ba180fd43 uml: style fixes ... |
467 |
if (!ptrace_ldt && mm->ldt.entry_count > LDT_DIRECT_ENTRIES) { |
858259cf7 [PATCH] uml: main... |
468 |
i = mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE; |
ba180fd43 uml: style fixes ... |
469 470 |
while (i-- > 0) free_page((long) mm->ldt.u.pages[i]); |
858259cf7 [PATCH] uml: main... |
471 472 473 |
} mm->ldt.entry_count = 0; } |
858259cf7 [PATCH] uml: main... |
474 475 476 |
int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount) { |
6aa802ce6 uml: throw out CH... |
477 |
return do_modify_ldt_skas(func, ptr, bytecount); |
858259cf7 [PATCH] uml: main... |
478 |
} |