Changes for per-process/user settable LDT and full sigcontexts

This commit is contained in:
brezak 1993-09-19 19:00:44 +00:00
parent 90add535c9
commit 42f1476a71
5 changed files with 370 additions and 62 deletions

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)genassym.c 5.11 (Berkeley) 5/10/91
* $Id: genassym.c,v 1.8 1993/09/16 03:24:13 brezak Exp $
* genassym.c,v 1.7 1993/08/03 06:33:55 mycroft Exp
*/
#include "sys/param.h"
@ -65,6 +65,7 @@ main()
pmap_t pmap = (pmap_t)0;
struct pcb *pcb = (struct pcb *)0;
struct trapframe *tf = (struct trapframe *)0;
struct sigframe *sigf = (struct sigframe *)0;
register unsigned i;
printf("#define\tI386_CR3PAT %d\n", I386_CR3PAT);
@ -132,6 +133,7 @@ main()
printf("#define\tPCB_FS %d\n", &pcb->pcb_tss.tss_fs);
printf("#define\tPCB_GS %d\n", &pcb->pcb_tss.tss_gs);
printf("#define\tPCB_LDT %d\n", &pcb->pcb_tss.tss_ldt);
printf("#define\tPCB_USERLDT %d\n", &pcb->pcb_ldt);
printf("#define\tPCB_IOOPT %d\n", &pcb->pcb_tss.tss_ioopt);
printf("#define\tNKMEMCLUSTERS %d\n", NKMEMCLUSTERS);
printf("#define\tU_PROF %d\n", &up->u_stats.p_prof);
@ -167,6 +169,12 @@ main()
printf("#define\tTF_ESP %d\n", &tf->tf_esp);
printf("#define\tTF_SS %d\n", &tf->tf_ss);
printf("#define\tSIGF_SIGNUM %d\n", &sigf->sf_signum);
printf("#define\tSIGF_CODE %d\n", &sigf->sf_code);
printf("#define\tSIGF_SCP %d\n", &sigf->sf_scp);
printf("#define\tSIGF_HANDLER %d\n", &sigf->sf_handler);
printf("#define\tSIGF_SC %d\n", &sigf->sf_sc);
printf("#define\tB_READ %d\n", B_READ);
printf("#define\tENOENT %d\n", ENOENT);
printf("#define\tEFAULT %d\n", EFAULT);

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)locore.s 7.3 (Berkeley) 5/13/91
* $Id: locore.s,v 1.30 1993/09/16 03:24:19 brezak Exp $
* locore.s,v 1.29 1993/09/11 00:12:56 jtc Exp
*/
@ -514,22 +514,10 @@ eicode:
_szicode:
.long eicode-_icode
#if 0 /* before bde */
.globl _sigcode,_esigcode
_sigcode:
movl 12(%esp),%eax # unsure if call will dec stack 1st
call %eax
xorl %eax,%eax # smaller movl $103,%eax
movb $103,%al # sigreturn()
LCALL(0x7,0) # enter kernel with args on stack
hlt # never gets here
_esigcode:
#else /* anno bde */
ENTRY(sigcode)
call 12(%esp)
lea 28(%esp),%eax # scp (the call may have clobbered the
call SIGF_HANDLER(%esp)
lea SIGF_SC(%esp),%eax # scp (the call may have clobbered the
# copy at 8(%esp))
# XXX - use genassym
pushl %eax
pushl %eax # junk to fake return address
movl $103,%eax # sigreturn()
@ -538,7 +526,6 @@ ENTRY(sigcode)
.globl _esigcode
_esigcode:
#endif
/*
* Support routines for GCC
@ -1574,6 +1561,15 @@ ENTRY(swtch)
movl %ebp,PCB_EBP(%ecx)
movl %esi,PCB_ESI(%ecx)
movl %edi,PCB_EDI(%ecx)
#ifdef USER_LDT
xorl %eax,%eax
movw %es,%ax
movl %eax,PCB_ES(%ecx)
movw %fs,%ax
movl %eax,PCB_FS(%ecx)
movw %gs,%ax
movl %eax,PCB_GS(%ecx)
#endif
#if NNPX > 0
/* have we used fp, and need a save? */
@ -1656,6 +1652,14 @@ swfnd:
movl PCB_EBP(%edx),%ebp
movl PCB_ESI(%edx),%esi
movl PCB_EDI(%edx),%edi
#ifdef USER_LDT
movl PCB_ES(%edx),%eax
movw %ax,%es
movl PCB_FS(%edx),%eax
movw %ax,%fs
movl PCB_GS(%edx),%eax
movw %ax,%gs
#endif
movl PCB_EIP(%edx),%eax
movl %eax,(%esp)
@ -1665,6 +1669,20 @@ swfnd:
movl %ecx,_curproc # into next process
movl %edx,_curpcb
#ifdef USER_LDT
cmpl $0, PCB_USERLDT(%edx)
jne 1f
movl __default_ldt,%eax
cmpl _currentldt,%eax
je 2f
lldt __default_ldt
movl %eax,_currentldt
jmp 2f
1: pushl %edx
call _set_user_ldt
popl %edx
2:
#endif
sti # splx() doesn't do an sti/cli
SHOW_STI
@ -1714,6 +1732,15 @@ ENTRY(savectx)
movl %ebp,PCB_EBP(%ecx)
movl %esi,PCB_ESI(%ecx)
movl %edi,PCB_EDI(%ecx)
#ifdef USER_LDT
xorl %eax,%eax
movw %es,%ax
movl %eax,PCB_ES(%ecx)
movw %fs,%ax
movl %eax,PCB_FS(%ecx)
movw %gs,%ax
movl %eax,PCB_GS(%ecx)
#endif
#if NNPX > 0
/*
@ -2002,6 +2029,10 @@ bpttraps:
/*
* Call gate entry for syscall
*
* The stack frame is made to be the same as a trap frame. Setting
* The call gate to "copy" 1 argument, leave a hole in the right
* place to put the eflags to make it look like a trap frame.
*/
SUPERALIGN_TEXT

View File

@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* from: @(#)machdep.c 7.4 (Berkeley) 6/3/91
* $Id: machdep.c,v 1.48 1993/09/16 03:24:29 brezak Exp $
* machdep.c,v 1.47 1993/09/05 03:54:11 sef Exp
*/
#include "npx.h"
@ -86,6 +86,7 @@ static unsigned int avail_remaining;
#include "machine/reg.h"
#include "machine/psl.h"
#include "machine/specialreg.h"
#include "machine/sysarch.h"
#include "i386/isa/isa.h"
#include "i386/isa/rtc.h"
@ -410,17 +411,6 @@ vmtime(otime, olbolt, oicr)
}
#endif
struct sigframe {
int sf_signum;
int sf_code;
struct sigcontext *sf_scp;
sig_t sf_handler;
int sf_eax;
int sf_edx;
int sf_ecx;
struct sigcontext sf_sc;
} ;
extern int kstack[];
/*
@ -489,22 +479,37 @@ sendsig(catcher, sig, mask, code)
fp->sf_scp = &fp->sf_sc;
fp->sf_handler = catcher;
/* save scratch registers */
fp->sf_eax = regs[tEAX];
fp->sf_edx = regs[tEDX];
fp->sf_ecx = regs[tECX];
/*
* Build the signal context to be used by sigreturn.
*/
fp->sf_sc.sc_onstack = oonstack;
fp->sf_sc.sc_mask = mask;
fp->sf_sc.sc_sp = regs[tESP];
fp->sf_sc.sc_fp = regs[tEBP];
fp->sf_sc.sc_pc = regs[tEIP];
fp->sf_sc.sc_ps = regs[tEFLAGS];
fp->sf_sc.sc_isp = regs[tISP];
fp->sf_sc.sc_esp = regs[tESP];
fp->sf_sc.sc_ebp = regs[tEBP];
fp->sf_sc.sc_eip = regs[tEIP];
fp->sf_sc.sc_efl = regs[tEFLAGS];
fp->sf_sc.sc_eax = regs[tEAX];
fp->sf_sc.sc_ebx = regs[tEBX];
fp->sf_sc.sc_ecx = regs[tECX];
fp->sf_sc.sc_edx = regs[tEDX];
fp->sf_sc.sc_esi = regs[tESI];
fp->sf_sc.sc_edi = regs[tEDI];
fp->sf_sc.sc_cs = regs[tCS];
fp->sf_sc.sc_ds = regs[tDS];
fp->sf_sc.sc_es = regs[tES];
fp->sf_sc.sc_ss = regs[tSS];
/*
* Build context to run handler in.
*/
regs[tESP] = (int)fp;
regs[tEIP] = (int)(((char *)PS_STRINGS) - (esigcode - sigcode));
regs[tEFLAGS] &= ~PSL_VM;
regs[tCS] = _ucodesel;
regs[tDS] = _udatasel;
regs[tES] = _udatasel;
regs[tSS] = _udatasel;
}
/*
@ -529,6 +534,8 @@ sigreturn(p, uap, retval)
register struct sigcontext *scp;
register struct sigframe *fp;
register int *regs = p->p_regs;
int iopl = regs[tEFLAGS] & PSL_IOPL;
int vm86 = regs[tEFLAGS] & PSL_VM;
/*
* (XXX old comment) regs[tESP] points to the return address.
@ -543,11 +550,6 @@ sigreturn(p, uap, retval)
if (useracc((caddr_t)fp, sizeof (*fp), 0) == 0)
return(EINVAL);
/* restore scratch registers */
regs[tEAX] = fp->sf_eax ;
regs[tEDX] = fp->sf_edx ;
regs[tECX] = fp->sf_ecx ;
if (useracc((caddr_t)scp, sizeof (*scp), 0) == 0)
return(EINVAL);
#ifdef notyet
@ -558,10 +560,33 @@ sigreturn(p, uap, retval)
p->p_sigacts->ps_onstack = scp->sc_onstack & 01;
p->p_sigmask = scp->sc_mask &~
(sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP));
regs[tEBP] = scp->sc_fp;
regs[tESP] = scp->sc_sp;
regs[tEIP] = scp->sc_pc;
regs[tEFLAGS] = scp->sc_ps;
/*
* Restore signal context
*/
regs[tEBP] = scp->sc_ebp;
regs[tESP] = scp->sc_esp;
regs[tISP] = scp->sc_isp;
regs[tEIP] = scp->sc_eip;
regs[tEFLAGS] = scp->sc_efl;
regs[tEAX] = scp->sc_eax;
regs[tEDX] = scp->sc_edx;
regs[tECX] = scp->sc_ecx;
regs[tEBX] = scp->sc_ebx;
regs[tESI] = scp->sc_esi;
regs[tEDI] = scp->sc_edi;
regs[tCS] = scp->sc_cs;
regs[tSS] = scp->sc_ss;
regs[tDS] = scp->sc_ds;
regs[tES] = scp->sc_es;
/* Be sure user doesn't try something funny */
if (!iopl)
regs[tEFLAGS] &= ~PSL_IOPL;
if (!vm86)
regs[tEFLAGS] &= ~PSL_VM;
regs[tEFLAGS] |= PSL_I;
return(EJUSTRETURN);
}
@ -794,15 +819,15 @@ setregs(p, entry, stack, retval)
#define GTGATE_SEL 4 /* Process task switch gate */
#define GPANIC_SEL 5 /* Task state to consider panic from */
#define GPROC0_SEL 6 /* Task state process slot zero and up */
#define NGDT GPROC0_SEL+1
#define GUSERLDT_SEL 7 /* User LDT */
#define NGDT GUSERLDT_SEL+1
union descriptor gdt[GPROC0_SEL+1];
union descriptor gdt[NGDT];
/* interrupt descriptor table */
struct gate_descriptor idt[NIDT];
/* local descriptor table */
union descriptor ldt[5];
#define LSYS5CALLS_SEL 0 /* forced by intel BCS */
#define LSYS5SIGR_SEL 1
@ -811,6 +836,11 @@ union descriptor ldt[5];
#define LUDATA_SEL 4
/* seperate stack, es,fs,gs sels ? */
/* #define LPOSIXCALLS_SEL 5 /* notyet */
#define NLDT LUDATA_SEL+1
union descriptor ldt[NLDT];
int _default_ldt, currentldt;
struct i386tss tss, panic_tss;
@ -880,7 +910,17 @@ struct soft_segment_descriptor gdt_segs[] = {
1, /* segment descriptor present */
0, 0,
0, /* unused - default 32 vs 16 bit size */
0 /* limit granularity (byte/page units)*/ }};
0 /* limit granularity (byte/page units)*/ },
/* User LDT Descriptor per process */
{ (int) ldt, /* segment base address */
(512 * sizeof(union descriptor)-1), /* length */
SDT_SYSLDT, /* segment type */
0, /* segment descriptor priority level */
1, /* segment descriptor present */
0, 0,
0, /* unused - default 32 vs 16 bit size */
0 /* limit granularity (byte/page units)*/ },
};
struct soft_segment_descriptor ldt_segs[] = {
/* Null Descriptor - overwritten by call gate */
@ -990,7 +1030,7 @@ init386(first_avail)
ldt_segs[LUCODE_SEL].ssd_limit = btoc(VM_MAXUSER_ADDRESS) - 1;
ldt_segs[LUDATA_SEL].ssd_limit = btoc(VM_MAXUSER_ADDRESS) - 1;
/* Note. eventually want private ldts per process */
for (x=0; x < 5; x++) ssdtosd(ldt_segs+x, ldt+x);
for (x=0; x < NLDT; x++) ssdtosd(ldt_segs+x, ldt+x);
/* exceptions */
setidt(0, &IDTVEC(div), SDT_SYS386TGT, SEL_KPL);
@ -1035,7 +1075,9 @@ init386(first_avail)
r_idt.rd_limit = sizeof(idt)-1;
r_idt.rd_base = (int) idt;
lidt(&r_idt);
lldt(GSEL(GLDT_SEL, SEL_KPL));
_default_ldt = GSEL(GLDT_SEL, SEL_KPL);
lldt(_default_ldt);
currentldt = _default_ldt;
#ifdef DDB
ddb_init();
@ -1561,3 +1603,214 @@ ptrace_setregs (struct proc *p, unsigned int *addr) {
tp->tf_ss = regs.r_ss;
return 0;
}
#ifdef USER_LDT
void
set_user_ldt(struct pcb *pcb)
{
gdt_segs[GUSERLDT_SEL].ssd_base = (unsigned)pcb->pcb_ldt;
gdt_segs[GUSERLDT_SEL].ssd_limit = (pcb->pcb_ldt_len * sizeof(union descriptor)) - 1;
ssdtosd(gdt_segs+GUSERLDT_SEL, gdt+GUSERLDT_SEL);
lldt(GSEL(GUSERLDT_SEL, SEL_KPL));
currentldt = GSEL(GUSERLDT_SEL, SEL_KPL);
}
struct i386_get_ldt_args {
int start;
union descriptor *desc;
int num;
};
i386_get_ldt(p, args, retval)
struct proc *p;
char *args;
int *retval;
{
int error = 0;
struct pcb *pcb = (struct pcb *)p->p_addr;
int nldt, num;
union descriptor *lp;
int s;
struct i386_get_ldt_args ua, *uap;
if ((error = copyin(args, &ua, sizeof(struct i386_get_ldt_args))) < 0)
return(error);
uap = &ua;
#ifdef DEBUG
printf("i386_get_ldt: start=%d num=%d descs=%x\n", uap->start, uap->num, uap->desc);
#endif
if (uap->start < 0 || uap->num < 0)
return(EINVAL);
s = splhigh();
if (pcb->pcb_ldt) {
nldt = pcb->pcb_ldt_len;
num = min(uap->num, nldt);
lp = &((union descriptor *)(pcb->pcb_ldt))[uap->start];
}
else {
nldt = sizeof(ldt)/sizeof(ldt[0]);
num = min(uap->num, nldt);
lp = &ldt[uap->start];
}
if (uap->start > nldt) {
splx(s);
return(EINVAL);
}
error = copyout(lp, uap->desc, num * sizeof(union descriptor));
if (!error)
*retval = num;
splx(s);
return(error);
}
struct i386_set_ldt_args {
int start;
union descriptor *desc;
int num;
};
i386_set_ldt(p, args, retval)
struct proc *p;
char *args;
int *retval;
{
int error = 0, i, n;
struct pcb *pcb = (struct pcb *)p->p_addr;
union descriptor *lp;
int s;
struct i386_set_ldt_args ua, *uap;
if ((error = copyin(args, &ua, sizeof(struct i386_set_ldt_args))) < 0)
return(error);
uap = &ua;
#ifdef DEBUG
printf("i386_set_ldt: start=%d num=%d descs=%x\n", uap->start, uap->num, uap->desc);
#endif
if (uap->start < 0 || uap->num < 0)
return(EINVAL);
/* XXX Should be 8192 ! */
if (uap->start > 512 ||
(uap->start + uap->num) > 512)
return(EINVAL);
/* allocate user ldt */
if (!pcb->pcb_ldt) {
union descriptor *new_ldt =
(union descriptor *)kmem_alloc(kernel_map, 512*sizeof(union descriptor));
bcopy(ldt, new_ldt, sizeof(ldt));
pcb->pcb_ldt = (caddr_t)new_ldt;
pcb->pcb_ldt_len = 512; /* XXX need to grow */
#ifdef DEBUG
printf("i386_set_ldt(%d): new_ldt=%x\n", p->p_pid, new_ldt);
#endif
}
/* Check descriptors for access violations */
for (i = 0, n = uap->start; i < uap->num; i++, n++) {
union descriptor desc, *dp;
dp = &uap->desc[i];
error = copyin(dp, &desc, sizeof(union descriptor));
if (error)
return(error);
/* Only user (ring-3) descriptors */
if (desc.sd.sd_dpl != SEL_UPL)
return(EACCES);
/* Must be "present" */
if (desc.sd.sd_p == 0)
return(EACCES);
switch (desc.sd.sd_type) {
case SDT_SYSNULL:
case SDT_SYS286CGT:
case SDT_SYS386CGT:
break;
case SDT_MEMRO:
case SDT_MEMROA:
case SDT_MEMRW:
case SDT_MEMRWA:
case SDT_MEMROD:
case SDT_MEMRODA:
case SDT_MEME:
case SDT_MEMEA:
case SDT_MEMER:
case SDT_MEMERA:
case SDT_MEMEC:
case SDT_MEMEAC:
case SDT_MEMERC:
case SDT_MEMERAC: {
#if 0
unsigned long base = (desc.sd.sd_hibase << 24)&0xFF000000;
base |= (desc.sd.sd_lobase&0x00FFFFFF);
if (base >= KERNBASE)
return(EACCES);
#endif
break;
}
default:
return(EACCES);
/*NOTREACHED*/
}
}
s = splhigh();
/* Fill in range */
for (i = 0, n = uap->start; i < uap->num && !error; i++, n++) {
union descriptor desc, *dp;
dp = &uap->desc[i];
lp = &((union descriptor *)(pcb->pcb_ldt))[n];
#ifdef DEBUG
printf("i386_set_ldt(%d): ldtp=%x\n", p->p_pid, lp);
#endif
error = copyin(dp, lp, sizeof(union descriptor));
}
if (!error) {
*retval = uap->start;
need_resched();
}
splx(s);
return(error);
}
#endif /* USER_LDT */
struct sysarch_args {
int op;
char *parms;
};
sysarch(p, uap, retval)
struct proc *p;
register struct sysarch_args *uap;
int *retval;
{
int error = 0;
switch(uap->op) {
#ifdef USER_LDT
case I386_GET_LDT:
error = i386_get_ldt(p, uap->parms, retval);
break;
case I386_SET_LDT:
error = i386_set_ldt(p, uap->parms, retval);
break;
#endif
default:
error = EINVAL;
break;
}
return(error);
}

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)trap.c 7.4 (Berkeley) 5/13/91
* $Id: trap.c,v 1.15 1993/09/16 03:24:24 brezak Exp $
* $Id: trap.c,v 1.16 1993/09/19 19:00:51 brezak Exp $
*/
/*
@ -43,6 +43,7 @@
#include "npx.h"
#include "signal.h"
#include "machine/cpu.h"
#include "machine/psl.h"
#include "machine/reg.h"

View File

@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* from: @(#)vm_machdep.c 7.3 (Berkeley) 5/13/91
* $Id: vm_machdep.c,v 1.7 1993/08/02 23:20:55 mycroft Exp $
* vm_machdep.c,v 1.7 1993/08/02 23:20:55 mycroft Exp
*/
/*
@ -166,9 +166,16 @@ void
cpu_exit(p)
register struct proc *p;
{
extern int _default_ldt, currentldt;
#if NNPX > 0
npxexit(p);
#endif
#ifdef USER_LDT
if (((struct pcb *)p->p_addr)->pcb_ldt && (currentldt != _default_ldt)) {
lldt(_default_ldt);
currentldt = _default_ldt;
}
#endif
splclock();
swtch();
@ -179,9 +186,17 @@ void
cpu_wait(p)
struct proc *p;
{
struct pcb *pcb = (struct pcb *)p->p_addr;
/* drop per-process resources */
vmspace_free(p->p_vmspace);
#ifdef USER_LDT
if (pcb->pcb_ldt) {
kmem_free(kernel_map, (vm_offset_t)pcb->pcb_ldt,
(pcb->pcb_ldt_len * sizeof(union descriptor)));
pcb->pcb_ldt = NULL;
}
#endif
kmem_free(kernel_map, (vm_offset_t)p->p_addr, ctob(UPAGES));
}
#endif