sys_machdep.c (52121) | sys_machdep.c (54188) |
---|---|
1/*- 2 * Copyright (c) 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 17 unchanged lines hidden (view full) --- 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * from: @(#)sys_machdep.c 5.5 (Berkeley) 1/19/91 | 1/*- 2 * Copyright (c) 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 17 unchanged lines hidden (view full) --- 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * from: @(#)sys_machdep.c 5.5 (Berkeley) 1/19/91 |
34 * $FreeBSD: head/sys/amd64/amd64/sys_machdep.c 52121 1999-10-11 14:50:03Z peter $ | 34 * $FreeBSD: head/sys/amd64/amd64/sys_machdep.c 54188 1999-12-06 04:53:08Z luoqi $ |
35 * 36 */ 37 38#include "opt_user_ldt.h" 39#include "opt_smp.h" 40 41#include <sys/param.h> 42#include <sys/systm.h> 43#include <sys/sysproto.h> | 35 * 36 */ 37 38#include "opt_user_ldt.h" 39#include "opt_smp.h" 40 41#include <sys/param.h> 42#include <sys/systm.h> 43#include <sys/sysproto.h> |
44#include <sys/malloc.h> |
|
44#include <sys/proc.h> 45 46#include <vm/vm.h> 47#include <sys/lock.h> 48#include <vm/pmap.h> 49#include <vm/vm_map.h> 50#include <vm/vm_extern.h> 51 --- 8 unchanged lines hidden (view full) --- 60#define MAX_LD 8192 61#define LD_PER_PAGE 512 62#define NEW_MAX_LD(num) ((num + LD_PER_PAGE) & ~(LD_PER_PAGE-1)) 63#define SIZE_FROM_LARGEST_LD(num) (NEW_MAX_LD(num) << 3) 64 65 66 67#ifdef USER_LDT | 45#include <sys/proc.h> 46 47#include <vm/vm.h> 48#include <sys/lock.h> 49#include <vm/pmap.h> 50#include <vm/vm_map.h> 51#include <vm/vm_extern.h> 52 --- 8 unchanged lines hidden (view full) --- 61#define MAX_LD 8192 62#define LD_PER_PAGE 512 63#define NEW_MAX_LD(num) ((num + LD_PER_PAGE) & ~(LD_PER_PAGE-1)) 64#define SIZE_FROM_LARGEST_LD(num) (NEW_MAX_LD(num) << 3) 65 66 67 68#ifdef USER_LDT |
68void set_user_ldt __P((struct pcb *pcb)); | |
69static int i386_get_ldt __P((struct proc *, char *)); 70static int i386_set_ldt __P((struct proc *, char *)); 71#endif 72static int i386_get_ioperm __P((struct proc *, char *)); 73static int i386_set_ioperm __P((struct proc *, char *)); 74int i386_extend_pcb __P((struct proc *)); 75 76#ifndef _SYS_SYSPROTO_H_ --- 54 unchanged lines hidden (view full) --- 131 }; 132 133 ext = (struct pcb_ext *)kmem_alloc(kernel_map, ctob(IOPAGES+1)); 134 if (ext == 0) 135 return (ENOMEM); 136 p->p_addr->u_pcb.pcb_ext = ext; 137 bzero(ext, sizeof(struct pcb_ext)); 138 ext->ext_tss.tss_esp0 = (unsigned)p->p_addr + ctob(UPAGES) - 16; | 69static int i386_get_ldt __P((struct proc *, char *)); 70static int i386_set_ldt __P((struct proc *, char *)); 71#endif 72static int i386_get_ioperm __P((struct proc *, char *)); 73static int i386_set_ioperm __P((struct proc *, char *)); 74int i386_extend_pcb __P((struct proc *)); 75 76#ifndef _SYS_SYSPROTO_H_ --- 54 unchanged lines hidden (view full) --- 131 }; 132 133 ext = (struct pcb_ext *)kmem_alloc(kernel_map, ctob(IOPAGES+1)); 134 if (ext == 0) 135 return (ENOMEM); 136 p->p_addr->u_pcb.pcb_ext = ext; 137 bzero(ext, sizeof(struct pcb_ext)); 138 ext->ext_tss.tss_esp0 = (unsigned)p->p_addr + ctob(UPAGES) - 16; |
139 ext->ext_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL); | 139 ext->ext_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL); |
140 /* 141 * The last byte of the i/o map must be followed by an 0xff byte. 142 * We arbitrarily allocate 16 bytes here, to keep the starting 143 * address on a doubleword boundary. 144 */ 145 offset = PAGE_SIZE - 16; 146 ext->ext_tss.tss_ioopt = 147 (offset - ((unsigned)&ext->ext_tss - (unsigned)ext)) << 16; --- 21 unchanged lines hidden (view full) --- 169{ 170 int i, error; 171 struct i386_ioperm_args ua; 172 char *iomap; 173 174 if ((error = copyin(args, &ua, sizeof(struct i386_ioperm_args))) != 0) 175 return (error); 176 | 140 /* 141 * The last byte of the i/o map must be followed by an 0xff byte. 142 * We arbitrarily allocate 16 bytes here, to keep the starting 143 * address on a doubleword boundary. 144 */ 145 offset = PAGE_SIZE - 16; 146 ext->ext_tss.tss_ioopt = 147 (offset - ((unsigned)&ext->ext_tss - (unsigned)ext)) << 16; --- 21 unchanged lines hidden (view full) --- 169{ 170 int i, error; 171 struct i386_ioperm_args ua; 172 char *iomap; 173 174 if ((error = copyin(args, &ua, sizeof(struct i386_ioperm_args))) != 0) 175 return (error); 176 |
177 if ((error = suser(p)) != 0) 178 return (error); | 177 if ((error = suser(p)) != 0) 178 return (error); |
179 if (securelevel > 0) 180 return (EPERM); 181 /* 182 * XXX 183 * While this is restricted to root, we should probably figure out 184 * whether any other driver is using this i/o address, as so not to 185 * cause confusion. This probably requires a global 'usage registry'. 186 */ --- 55 unchanged lines hidden (view full) --- 242#ifdef USER_LDT 243/* 244 * Update the GDT entry pointing to the LDT to point to the LDT of the 245 * current process. Do not staticize. 246 */ 247void 248set_user_ldt(struct pcb *pcb) 249{ | 179 if (securelevel > 0) 180 return (EPERM); 181 /* 182 * XXX 183 * While this is restricted to root, we should probably figure out 184 * whether any other driver is using this i/o address, as so not to 185 * cause confusion. This probably requires a global 'usage registry'. 186 */ --- 55 unchanged lines hidden (view full) --- 242#ifdef USER_LDT 243/* 244 * Update the GDT entry pointing to the LDT to point to the LDT of the 245 * current process. Do not staticize. 246 */ 247void 248set_user_ldt(struct pcb *pcb) 249{ |
250 gdt_segs[GUSERLDT_SEL].ssd_base = (unsigned)pcb->pcb_ldt; 251 gdt_segs[GUSERLDT_SEL].ssd_limit = (pcb->pcb_ldt_len * sizeof(union descriptor)) - 1; | 250 struct pcb_ldt *pcb_ldt; 251 252 if (pcb != curpcb) 253 return; 254 255 pcb_ldt = pcb->pcb_ldt; |
252#ifdef SMP | 256#ifdef SMP |
253 ssdtosd(&gdt_segs[GUSERLDT_SEL], &gdt[cpuid * NGDT + GUSERLDT_SEL].sd); | 257 gdt[cpuid * NGDT + GUSERLDT_SEL].sd = pcb_ldt->ldt_sd; |
254#else | 258#else |
255 ssdtosd(&gdt_segs[GUSERLDT_SEL], &gdt[GUSERLDT_SEL].sd); | 259 gdt[GUSERLDT_SEL].sd = pcb_ldt->ldt_sd; |
256#endif 257 lldt(GSEL(GUSERLDT_SEL, SEL_KPL)); 258 currentldt = GSEL(GUSERLDT_SEL, SEL_KPL); 259} 260 | 260#endif 261 lldt(GSEL(GUSERLDT_SEL, SEL_KPL)); 262 currentldt = GSEL(GUSERLDT_SEL, SEL_KPL); 263} 264 |
265struct pcb_ldt * 266user_ldt_alloc(struct pcb *pcb, int len) 267{ 268 struct pcb_ldt *pcb_ldt, *new_ldt; 269 270 MALLOC(new_ldt, struct pcb_ldt *, sizeof(struct pcb_ldt), 271 M_SUBPROC, M_WAITOK); 272 if (new_ldt == NULL) 273 return NULL; 274 275 new_ldt->ldt_len = len = NEW_MAX_LD(len); 276 new_ldt->ldt_base = (caddr_t)kmem_alloc(kernel_map, 277 len * sizeof(union descriptor)); 278 if (new_ldt->ldt_base == NULL) { 279 FREE(new_ldt, M_SUBPROC); 280 return NULL; 281 } 282 new_ldt->ldt_refcnt = 1; 283 new_ldt->ldt_active = 0; 284 285 gdt_segs[GUSERLDT_SEL].ssd_base = (unsigned)new_ldt->ldt_base; 286 gdt_segs[GUSERLDT_SEL].ssd_limit = len * sizeof(union descriptor) - 1; 287 ssdtosd(&gdt_segs[GUSERLDT_SEL], &new_ldt->ldt_sd); 288 289 if ((pcb_ldt = pcb->pcb_ldt)) { 290 if (len > pcb_ldt->ldt_len) 291 len = pcb_ldt->ldt_len; 292 bcopy(pcb_ldt->ldt_base, new_ldt->ldt_base, 293 len * sizeof(union descriptor)); 294 } else { 295 bcopy(ldt, new_ldt->ldt_base, sizeof(ldt)); 296 } 297 return new_ldt; 298} 299 300void 301user_ldt_free(struct pcb *pcb) 302{ 303 struct pcb_ldt *pcb_ldt = pcb->pcb_ldt; 304 305 if (pcb_ldt == NULL) 306 return; 307 308 if (pcb == curpcb) { 309 lldt(_default_ldt); 310 currentldt = _default_ldt; 311 } 312 313 if (--pcb_ldt->ldt_refcnt == 0) { 314 kmem_free(kernel_map, (vm_offset_t)pcb_ldt->ldt_base, 315 pcb_ldt->ldt_len * sizeof(union descriptor)); 316 FREE(pcb_ldt, M_SUBPROC); 317 } 318 pcb->pcb_ldt = NULL; 319} 320 |
|
261static int 262i386_get_ldt(p, args) 263 struct proc *p; 264 char *args; 265{ 266 int error = 0; 267 struct pcb *pcb = &p->p_addr->u_pcb; | 321static int 322i386_get_ldt(p, args) 323 struct proc *p; 324 char *args; 325{ 326 int error = 0; 327 struct pcb *pcb = &p->p_addr->u_pcb; |
328 struct pcb_ldt *pcb_ldt = pcb->pcb_ldt; |
|
268 int nldt, num; 269 union descriptor *lp; 270 int s; 271 struct i386_ldt_args ua, *uap = &ua; 272 273 if ((error = copyin(args, uap, sizeof(struct i386_ldt_args))) < 0) 274 return(error); 275 276#ifdef DEBUG 277 printf("i386_get_ldt: start=%d num=%d descs=%p\n", 278 uap->start, uap->num, (void *)uap->descs); 279#endif 280 281 /* verify range of LDTs exist */ 282 if ((uap->start < 0) || (uap->num <= 0)) 283 return(EINVAL); 284 285 s = splhigh(); 286 | 329 int nldt, num; 330 union descriptor *lp; 331 int s; 332 struct i386_ldt_args ua, *uap = &ua; 333 334 if ((error = copyin(args, uap, sizeof(struct i386_ldt_args))) < 0) 335 return(error); 336 337#ifdef DEBUG 338 printf("i386_get_ldt: start=%d num=%d descs=%p\n", 339 uap->start, uap->num, (void *)uap->descs); 340#endif 341 342 /* verify range of LDTs exist */ 343 if ((uap->start < 0) || (uap->num <= 0)) 344 return(EINVAL); 345 346 s = splhigh(); 347 |
287 if (pcb->pcb_ldt) { 288 nldt = pcb->pcb_ldt_len; | 348 if (pcb_ldt) { 349 nldt = pcb_ldt->ldt_len; |
289 num = min(uap->num, nldt); | 350 num = min(uap->num, nldt); |
290 lp = &((union descriptor *)(pcb->pcb_ldt))[uap->start]; | 351 lp = &((union descriptor *)(pcb_ldt->ldt_base))[uap->start]; |
291 } else { 292 nldt = sizeof(ldt)/sizeof(ldt[0]); 293 num = min(uap->num, nldt); 294 lp = &ldt[uap->start]; 295 } 296 if (uap->start > nldt) { 297 splx(s); 298 return(EINVAL); --- 8 unchanged lines hidden (view full) --- 307} 308 309static int 310i386_set_ldt(p, args) 311 struct proc *p; 312 char *args; 313{ 314 int error = 0, i, n; | 352 } else { 353 nldt = sizeof(ldt)/sizeof(ldt[0]); 354 num = min(uap->num, nldt); 355 lp = &ldt[uap->start]; 356 } 357 if (uap->start > nldt) { 358 splx(s); 359 return(EINVAL); --- 8 unchanged lines hidden (view full) --- 368} 369 370static int 371i386_set_ldt(p, args) 372 struct proc *p; 373 char *args; 374{ 375 int error = 0, i, n; |
315 int largest_ld; | 376 int largest_ld; |
316 struct pcb *pcb = &p->p_addr->u_pcb; | 377 struct pcb *pcb = &p->p_addr->u_pcb; |
378 struct pcb_ldt *pcb_ldt = pcb->pcb_ldt; |
|
317 int s; 318 struct i386_ldt_args ua, *uap = &ua; 319 320 if ((error = copyin(args, uap, sizeof(struct i386_ldt_args))) < 0) 321 return(error); 322 323#ifdef DEBUG 324 printf("i386_set_ldt: start=%d num=%d descs=%p\n", 325 uap->start, uap->num, (void *)uap->descs); 326#endif 327 | 379 int s; 380 struct i386_ldt_args ua, *uap = &ua; 381 382 if ((error = copyin(args, uap, sizeof(struct i386_ldt_args))) < 0) 383 return(error); 384 385#ifdef DEBUG 386 printf("i386_set_ldt: start=%d num=%d descs=%p\n", 387 uap->start, uap->num, (void *)uap->descs); 388#endif 389 |
328 /* verify range of descriptors to modify */ 329 if ((uap->start < 0) || (uap->start >= MAX_LD) || (uap->num < 0) || 330 (uap->num > MAX_LD)) 331 { 332 return(EINVAL); 333 } 334 largest_ld = uap->start + uap->num - 1; 335 if (largest_ld >= MAX_LD) 336 return(EINVAL); 337 338 /* allocate user ldt */ 339 if (!pcb->pcb_ldt || (largest_ld >= pcb->pcb_ldt_len)) { 340 union descriptor *new_ldt = (union descriptor *)kmem_alloc( 341 kernel_map, SIZE_FROM_LARGEST_LD(largest_ld)); 342 if (new_ldt == NULL) { 343 return ENOMEM; 344 } 345 if (pcb->pcb_ldt) { 346 bcopy(pcb->pcb_ldt, new_ldt, pcb->pcb_ldt_len 347 * sizeof(union descriptor)); 348 kmem_free(kernel_map, (vm_offset_t)pcb->pcb_ldt, 349 pcb->pcb_ldt_len * sizeof(union descriptor)); 350 } else { 351 bcopy(ldt, new_ldt, sizeof(ldt)); 352 } 353 pcb->pcb_ldt = (caddr_t)new_ldt; 354 pcb->pcb_ldt_len = NEW_MAX_LD(largest_ld); 355 if (pcb == curpcb) 356 set_user_ldt(pcb); 357 } | 390 /* verify range of descriptors to modify */ 391 if ((uap->start < 0) || (uap->start >= MAX_LD) || (uap->num < 0) || 392 (uap->num > MAX_LD)) 393 { 394 return(EINVAL); 395 } 396 largest_ld = uap->start + uap->num - 1; 397 if (largest_ld >= MAX_LD) 398 return(EINVAL); |
358 | 399 |
400 /* allocate user ldt */ 401 if (!pcb_ldt || largest_ld >= pcb_ldt->ldt_len) { 402 struct pcb_ldt *new_ldt = user_ldt_alloc(pcb, largest_ld); 403 if (new_ldt == NULL) 404 return ENOMEM; 405 if (pcb_ldt) { 406 pcb_ldt->ldt_sd = new_ldt->ldt_sd; 407 kmem_free(kernel_map, (vm_offset_t)pcb_ldt->ldt_base, 408 pcb_ldt->ldt_len * sizeof(union descriptor)); 409 pcb_ldt->ldt_base = new_ldt->ldt_base; 410 pcb_ldt->ldt_len = new_ldt->ldt_len; 411 FREE(new_ldt, M_SUBPROC); 412 } else 413 pcb->pcb_ldt = pcb_ldt = new_ldt; 414#ifdef SMP 415 /* signal other cpus to reload ldt */ 416 smp_rendezvous(NULL, (void (*)(void *))set_user_ldt, NULL, pcb); 417#else 418 set_user_ldt(pcb); 419#endif 420 } 421 |
|
359 /* Check descriptors for access violations */ 360 for (i = 0, n = uap->start; i < uap->num; i++, n++) { 361 union descriptor desc, *dp; 362 dp = &uap->descs[i]; 363 error = copyin(dp, &desc, sizeof(union descriptor)); 364 if (error) 365 return(error); 366 367 switch (desc.sd.sd_type) { | 422 /* Check descriptors for access violations */ 423 for (i = 0, n = uap->start; i < uap->num; i++, n++) { 424 union descriptor desc, *dp; 425 dp = &uap->descs[i]; 426 error = copyin(dp, &desc, sizeof(union descriptor)); 427 if (error) 428 return(error); 429 430 switch (desc.sd.sd_type) { |
368 case SDT_SYSNULL: /* system null */ 369 desc.sd.sd_p = 0; 370 break; 371 case SDT_SYS286TSS: /* system 286 TSS available */ 372 case SDT_SYSLDT: /* system local descriptor table */ 373 case SDT_SYS286BSY: /* system 286 TSS busy */ 374 case SDT_SYSTASKGT: /* system task gate */ 375 case SDT_SYS286IGT: /* system 286 interrupt gate */ 376 case SDT_SYS286TGT: /* system 286 trap gate */ 377 case SDT_SYSNULL2: /* undefined by Intel */ 378 case SDT_SYS386TSS: /* system 386 TSS available */ 379 case SDT_SYSNULL3: /* undefined by Intel */ 380 case SDT_SYS386BSY: /* system 386 TSS busy */ 381 case SDT_SYSNULL4: /* undefined by Intel */ 382 case SDT_SYS386IGT: /* system 386 interrupt gate */ 383 case SDT_SYS386TGT: /* system 386 trap gate */ 384 case SDT_SYS286CGT: /* system 286 call gate */ 385 case SDT_SYS386CGT: /* system 386 call gate */ 386 /* I can't think of any reason to allow a user proc 387 * to create a segment of these types. They are 388 * for OS use only. 389 */ 390 return EACCES; 391 392 /* memory segment types */ 393 case SDT_MEMEC: /* memory execute only conforming */ 394 case SDT_MEMEAC: /* memory execute only accessed conforming */ 395 case SDT_MEMERC: /* memory execute read conforming */ 396 case SDT_MEMERAC: /* memory execute read accessed conforming */ 397 /* Must be "present" if executable and conforming. */ 398 if (desc.sd.sd_p == 0) 399 return (EACCES); 400 break; 401 case SDT_MEMRO: /* memory read only */ 402 case SDT_MEMROA: /* memory read only accessed */ 403 case SDT_MEMRW: /* memory read write */ 404 case SDT_MEMRWA: /* memory read write accessed */ 405 case SDT_MEMROD: /* memory read only expand dwn limit */ 406 case SDT_MEMRODA: /* memory read only expand dwn lim accessed */ 407 case SDT_MEMRWD: /* memory read write expand dwn limit */ 408 case SDT_MEMRWDA: /* memory read write expand dwn lim acessed */ 409 case SDT_MEME: /* memory execute only */ 410 case SDT_MEMEA: /* memory execute only accessed */ 411 case SDT_MEMER: /* memory execute read */ 412 case SDT_MEMERA: /* memory execute read accessed */ | 431 case SDT_SYSNULL: /* system null */ 432 desc.sd.sd_p = 0; |
413 break; | 433 break; |
434 case SDT_SYS286TSS: /* system 286 TSS available */ 435 case SDT_SYSLDT: /* system local descriptor table */ 436 case SDT_SYS286BSY: /* system 286 TSS busy */ 437 case SDT_SYSTASKGT: /* system task gate */ 438 case SDT_SYS286IGT: /* system 286 interrupt gate */ 439 case SDT_SYS286TGT: /* system 286 trap gate */ 440 case SDT_SYSNULL2: /* undefined by Intel */ 441 case SDT_SYS386TSS: /* system 386 TSS available */ 442 case SDT_SYSNULL3: /* undefined by Intel */ 443 case SDT_SYS386BSY: /* system 386 TSS busy */ 444 case SDT_SYSNULL4: /* undefined by Intel */ 445 case SDT_SYS386IGT: /* system 386 interrupt gate */ 446 case SDT_SYS386TGT: /* system 386 trap gate */ 447 case SDT_SYS286CGT: /* system 286 call gate */ 448 case SDT_SYS386CGT: /* system 386 call gate */ 449 /* I can't think of any reason to allow a user proc 450 * to create a segment of these types. They are 451 * for OS use only. 452 */ 453 return EACCES; 454 455 /* memory segment types */ 456 case SDT_MEMEC: /* memory execute only conforming */ 457 case SDT_MEMEAC: /* memory execute only accessed conforming */ 458 case SDT_MEMERC: /* memory execute read conforming */ 459 case SDT_MEMERAC: /* memory execute read accessed conforming */ 460 /* Must be "present" if executable and conforming. */ 461 if (desc.sd.sd_p == 0) 462 return (EACCES); 463 break; 464 case SDT_MEMRO: /* memory read only */ 465 case SDT_MEMROA: /* memory read only accessed */ 466 case SDT_MEMRW: /* memory read write */ 467 case SDT_MEMRWA: /* memory read write accessed */ 468 case SDT_MEMROD: /* memory read only expand dwn limit */ 469 case SDT_MEMRODA: /* memory read only expand dwn lim accessed */ 470 case SDT_MEMRWD: /* memory read write expand dwn limit */ 471 case SDT_MEMRWDA: /* memory read write expand dwn lim acessed */ 472 case SDT_MEME: /* memory execute only */ 473 case SDT_MEMEA: /* memory execute only accessed */ 474 case SDT_MEMER: /* memory execute read */ 475 case SDT_MEMERA: /* memory execute read accessed */ 476 break; |
|
414 default: 415 return(EINVAL); 416 /*NOTREACHED*/ 417 } | 477 default: 478 return(EINVAL); 479 /*NOTREACHED*/ 480 } |
418 419 /* Only user (ring-3) descriptors may be present. */ 420 if ((desc.sd.sd_p != 0) && (desc.sd.sd_dpl != SEL_UPL)) 421 return (EACCES); | 481 482 /* Only user (ring-3) descriptors may be present. */ 483 if ((desc.sd.sd_p != 0) && (desc.sd.sd_dpl != SEL_UPL)) 484 return (EACCES); |
422 } 423 424 s = splhigh(); 425 426 /* Fill in range */ | 485 } 486 487 s = splhigh(); 488 489 /* Fill in range */ |
427 error = copyin(uap->descs, 428 &((union descriptor *)(pcb->pcb_ldt))[uap->start], 429 uap->num * sizeof(union descriptor)); 430 if (!error) 431 p->p_retval[0] = uap->start; | 490 error = copyin(uap->descs, 491 &((union descriptor *)(pcb_ldt->ldt_base))[uap->start], 492 uap->num * sizeof(union descriptor)); 493 if (!error) 494 p->p_retval[0] = uap->start; |
432 433 splx(s); 434 return(error); 435} 436#endif /* USER_LDT */ | 495 496 splx(s); 497 return(error); 498} 499#endif /* USER_LDT */ |