sys_machdep.c (02b0a160) sys_machdep.c (05dfa22f)
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

--- 28 unchanged lines hidden (view full) ---

37
38#include <sys/param.h>
39#include <sys/systm.h>
40#include <sys/lock.h>
41#include <sys/malloc.h>
42#include <sys/mutex.h>
43#include <sys/priv.h>
44#include <sys/proc.h>
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

--- 28 unchanged lines hidden (view full) ---

37
38#include <sys/param.h>
39#include <sys/systm.h>
40#include <sys/lock.h>
41#include <sys/malloc.h>
42#include <sys/mutex.h>
43#include <sys/priv.h>
44#include <sys/proc.h>
45#include <sys/refcount.h>
46#include <sys/smp.h>
47#include <sys/sysproto.h>
48
49#include <vm/vm.h>
50#include <vm/pmap.h>
51#include <vm/vm_map.h>
52#include <vm/vm_extern.h>
53

--- 7 unchanged lines hidden (view full) ---

61
62#include <vm/vm_kern.h> /* for kernel_map */
63
64#define MAX_LD 8192
65#define LD_PER_PAGE 512
66#define NEW_MAX_LD(num) ((num + LD_PER_PAGE) & ~(LD_PER_PAGE-1))
67#define SIZE_FROM_LARGEST_LD(num) (NEW_MAX_LD(num) << 3)
68
45#include <sys/smp.h>
46#include <sys/sysproto.h>
47
48#include <vm/vm.h>
49#include <vm/pmap.h>
50#include <vm/vm_map.h>
51#include <vm/vm_extern.h>
52

--- 7 unchanged lines hidden (view full) ---

60
61#include <vm/vm_kern.h> /* for kernel_map */
62
63#define MAX_LD 8192
64#define LD_PER_PAGE 512
65#define NEW_MAX_LD(num) ((num + LD_PER_PAGE) & ~(LD_PER_PAGE-1))
66#define SIZE_FROM_LARGEST_LD(num) (NEW_MAX_LD(num) << 3)
67
68#ifdef SMP
69#define NULL_LDT_BASE ((caddr_t)NULL)
69
70
71static void set_user_ldt_rv(struct vmspace *vmsp);
72#endif
70
71static int i386_set_ldt_data(struct thread *, int start, int num,
72 union descriptor *descs);
73static int i386_ldt_grow(struct thread *td, int len);
73
74static int i386_set_ldt_data(struct thread *, int start, int num,
75 union descriptor *descs);
76static int i386_ldt_grow(struct thread *td, int len);
74#ifdef SMP
75static void set_user_ldt_rv(struct thread *);
76#endif
77
78#ifndef _SYS_SYSPROTO_H_
79struct sysarch_args {
80 int op;
81 char *parms;
82};
83#endif
84

--- 288 unchanged lines hidden (view full) ---

373 lldt(GSEL(GUSERLDT_SEL, SEL_KPL));
374 PCPU_SET(currentldt, GSEL(GUSERLDT_SEL, SEL_KPL));
375 if (dtlocked)
376 mtx_unlock_spin(&dt_lock);
377}
378
379#ifdef SMP
380static void
77
78#ifndef _SYS_SYSPROTO_H_
79struct sysarch_args {
80 int op;
81 char *parms;
82};
83#endif
84

--- 288 unchanged lines hidden (view full) ---

373 lldt(GSEL(GUSERLDT_SEL, SEL_KPL));
374 PCPU_SET(currentldt, GSEL(GUSERLDT_SEL, SEL_KPL));
375 if (dtlocked)
376 mtx_unlock_spin(&dt_lock);
377}
378
379#ifdef SMP
380static void
381set_user_ldt_rv(struct thread *td)
381set_user_ldt_rv(struct vmspace *vmsp)
382{
382{
383 struct thread *td;
383
384
384 if (td->td_proc != curthread->td_proc)
385 td = curthread;
386 if (vmsp != td->td_proc->p_vmspace)
385 return;
386
387 set_user_ldt(&td->td_proc->p_md);
388}
389#endif
390
391/*
392 * dt_lock must be held. Returns with dt_lock held.

--- 10 unchanged lines hidden (view full) ---

403
404 new_ldt->ldt_len = len = NEW_MAX_LD(len);
405 new_ldt->ldt_base = (caddr_t)kmem_alloc(kernel_map,
406 len * sizeof(union descriptor));
407 if (new_ldt->ldt_base == NULL) {
408 FREE(new_ldt, M_SUBPROC);
409 return NULL;
410 }
387 return;
388
389 set_user_ldt(&td->td_proc->p_md);
390}
391#endif
392
393/*
394 * dt_lock must be held. Returns with dt_lock held.

--- 10 unchanged lines hidden (view full) ---

405
406 new_ldt->ldt_len = len = NEW_MAX_LD(len);
407 new_ldt->ldt_base = (caddr_t)kmem_alloc(kernel_map,
408 len * sizeof(union descriptor));
409 if (new_ldt->ldt_base == NULL) {
410 FREE(new_ldt, M_SUBPROC);
411 return NULL;
412 }
411 refcount_init(&new_ldt->ldt_refcnt, 1);
413 new_ldt->ldt_refcnt = 1;
412 new_ldt->ldt_active = 0;
413
414 mtx_lock_spin(&dt_lock);
415 gdt_segs[GUSERLDT_SEL].ssd_base = (unsigned)new_ldt->ldt_base;
416 gdt_segs[GUSERLDT_SEL].ssd_limit = len * sizeof(union descriptor) - 1;
417 ssdtosd(&gdt_segs[GUSERLDT_SEL], &new_ldt->ldt_sd);
418
419 if ((pldt = mdp->md_ldt) != NULL) {

--- 21 unchanged lines hidden (view full) ---

441 return;
442
443 if (td == PCPU_GET(curthread)) {
444 lldt(_default_ldt);
445 PCPU_SET(currentldt, _default_ldt);
446 }
447
448 mdp->md_ldt = NULL;
414 new_ldt->ldt_active = 0;
415
416 mtx_lock_spin(&dt_lock);
417 gdt_segs[GUSERLDT_SEL].ssd_base = (unsigned)new_ldt->ldt_base;
418 gdt_segs[GUSERLDT_SEL].ssd_limit = len * sizeof(union descriptor) - 1;
419 ssdtosd(&gdt_segs[GUSERLDT_SEL], &new_ldt->ldt_sd);
420
421 if ((pldt = mdp->md_ldt) != NULL) {

--- 21 unchanged lines hidden (view full) ---

443 return;
444
445 if (td == PCPU_GET(curthread)) {
446 lldt(_default_ldt);
447 PCPU_SET(currentldt, _default_ldt);
448 }
449
450 mdp->md_ldt = NULL;
449 mtx_unlock_spin(&dt_lock);
450 if (refcount_release(&pldt->ldt_refcnt)) {
451 if (--pldt->ldt_refcnt == 0) {
452 mtx_unlock_spin(&dt_lock);
451 kmem_free(kernel_map, (vm_offset_t)pldt->ldt_base,
452 pldt->ldt_len * sizeof(union descriptor));
453 FREE(pldt, M_SUBPROC);
453 kmem_free(kernel_map, (vm_offset_t)pldt->ldt_base,
454 pldt->ldt_len * sizeof(union descriptor));
455 FREE(pldt, M_SUBPROC);
454 }
456 } else
457 mtx_unlock_spin(&dt_lock);
455}
456
457/*
458 * Note for the authors of compat layers (linux, etc): copyout() in
459 * the function below is not a problem since it presents data in
460 * arch-specific format (i.e. i386-specific in this case), not in
461 * the OS-specific one.
462 */

--- 222 unchanged lines hidden (view full) ---

685 num * sizeof(union descriptor));
686 return (0);
687}
688
689static int
690i386_ldt_grow(struct thread *td, int len)
691{
692 struct mdproc *mdp = &td->td_proc->p_md;
458}
459
460/*
461 * Note for the authors of compat layers (linux, etc): copyout() in
462 * the function below is not a problem since it presents data in
463 * arch-specific format (i.e. i386-specific in this case), not in
464 * the OS-specific one.
465 */

--- 222 unchanged lines hidden (view full) ---

688 num * sizeof(union descriptor));
689 return (0);
690}
691
692static int
693i386_ldt_grow(struct thread *td, int len)
694{
695 struct mdproc *mdp = &td->td_proc->p_md;
693 struct proc_ldt *pldt;
694 caddr_t old_ldt_base;
695 int old_ldt_len;
696 struct proc_ldt *new_ldt, *pldt;
697 caddr_t old_ldt_base = NULL_LDT_BASE;
698 int old_ldt_len = 0;
696
697 mtx_assert(&dt_lock, MA_OWNED);
698
699 if (len > MAX_LD)
700 return (ENOMEM);
701 if (len < NLDT + 1)
702 len = NLDT + 1;
703
704 /* Allocate a user ldt. */
705 if ((pldt = mdp->md_ldt) == NULL || len > pldt->ldt_len) {
699
700 mtx_assert(&dt_lock, MA_OWNED);
701
702 if (len > MAX_LD)
703 return (ENOMEM);
704 if (len < NLDT + 1)
705 len = NLDT + 1;
706
707 /* Allocate a user ldt. */
708 if ((pldt = mdp->md_ldt) == NULL || len > pldt->ldt_len) {
706 struct proc_ldt *new_ldt;
707
708 new_ldt = user_ldt_alloc(mdp, len);
709 if (new_ldt == NULL)
710 return (ENOMEM);
711 pldt = mdp->md_ldt;
712
713 if (pldt != NULL) {
709 new_ldt = user_ldt_alloc(mdp, len);
710 if (new_ldt == NULL)
711 return (ENOMEM);
712 pldt = mdp->md_ldt;
713
714 if (pldt != NULL) {
714 if (new_ldt->ldt_len > pldt->ldt_len) {
715 old_ldt_base = pldt->ldt_base;
716 old_ldt_len = pldt->ldt_len;
717 pldt->ldt_sd = new_ldt->ldt_sd;
718 pldt->ldt_base = new_ldt->ldt_base;
719 pldt->ldt_len = new_ldt->ldt_len;
720 mtx_unlock_spin(&dt_lock);
721 kmem_free(kernel_map, (vm_offset_t)old_ldt_base,
722 old_ldt_len * sizeof(union descriptor));
723 FREE(new_ldt, M_SUBPROC);
724 mtx_lock_spin(&dt_lock);
725 } else {
715 if (new_ldt->ldt_len <= pldt->ldt_len) {
726 /*
716 /*
727 * If other threads already did the work,
728 * do nothing.
717 * We just lost the race for allocation, so
718 * free the new object and return.
729 */
730 mtx_unlock_spin(&dt_lock);
731 kmem_free(kernel_map,
732 (vm_offset_t)new_ldt->ldt_base,
733 new_ldt->ldt_len * sizeof(union descriptor));
734 FREE(new_ldt, M_SUBPROC);
735 mtx_lock_spin(&dt_lock);
736 return (0);
737 }
719 */
720 mtx_unlock_spin(&dt_lock);
721 kmem_free(kernel_map,
722 (vm_offset_t)new_ldt->ldt_base,
723 new_ldt->ldt_len * sizeof(union descriptor));
724 FREE(new_ldt, M_SUBPROC);
725 mtx_lock_spin(&dt_lock);
726 return (0);
727 }
728
729 /*
730 * We have to substitute the current LDT entry for
731 * curproc with the new one since its size grew.
732 */
733 old_ldt_base = pldt->ldt_base;
734 old_ldt_len = pldt->ldt_len;
735 pldt->ldt_sd = new_ldt->ldt_sd;
736 pldt->ldt_base = new_ldt->ldt_base;
737 pldt->ldt_len = new_ldt->ldt_len;
738 } else
739 mdp->md_ldt = pldt = new_ldt;
740#ifdef SMP
741 /*
742 * Signal other cpus to reload ldt. We need to unlock dt_lock
743 * here because other CPU will contest on it since their
744 * curthreads won't hold the lock and will block when trying
745 * to acquire it.
746 */
747 mtx_unlock_spin(&dt_lock);
748 smp_rendezvous(NULL, (void (*)(void *))set_user_ldt_rv,
738 } else
739 mdp->md_ldt = pldt = new_ldt;
740#ifdef SMP
741 /*
742 * Signal other cpus to reload ldt. We need to unlock dt_lock
743 * here because other CPU will contest on it since their
744 * curthreads won't hold the lock and will block when trying
745 * to acquire it.
746 */
747 mtx_unlock_spin(&dt_lock);
748 smp_rendezvous(NULL, (void (*)(void *))set_user_ldt_rv,
749 NULL, td);
750 mtx_lock_spin(&dt_lock);
749 NULL, td->td_proc->p_vmspace);
751#else
750#else
752 set_user_ldt(mdp);
751 set_user_ldt(td);
752 mtx_unlock_spin(&dt_lock);
753#endif
753#endif
754 if (old_ldt_base != NULL_LDT_BASE) {
755 kmem_free(kernel_map, (vm_offset_t)old_ldt_base,
756 old_ldt_len * sizeof(union descriptor));
757 FREE(new_ldt, M_SUBPROC);
758 }
759 mtx_lock_spin(&dt_lock);
754 }
755 return (0);
756}
760 }
761 return (0);
762}