PERFORCE change 28113 for review
Peter Wemm
peter at FreeBSD.org
Fri Apr 4 18:01:17 PST 2003
http://perforce.freebsd.org/chv.cgi?CH=28113
Change 28113 by peter at peter_daintree on 2003/04/04 18:01:12
Steer well clear of user LDT, debug regs, and 4.x hammer binaries.
Affected files ...
.. //depot/projects/hammer/sys/x86_64/x86_64/machdep.c#31 edit
Differences ...
==== //depot/projects/hammer/sys/x86_64/x86_64/machdep.c#31 (text+ko) ====
@@ -179,11 +179,6 @@
int cold = 1;
-#ifdef COMPAT_FREEBSD4
-static void freebsd4_sendsig(sig_t catcher, int sig, sigset_t *mask,
- u_long code);
-#endif
-
long Maxmem = 0;
vm_paddr_t phys_avail[10];
@@ -258,127 +253,6 @@
* frame pointer, it returns to the user
* specified pc, psl.
*/
-#ifdef COMPAT_FREEBSD4
-static void
-freebsd4_sendsig(catcher, sig, mask, code)
- sig_t catcher;
- int sig;
- sigset_t *mask;
- u_long code;
-{
- struct sigframe4 sf, *sfp;
- struct proc *p;
- struct thread *td;
- struct sigacts *psp;
- struct trapframe *regs;
- int oonstack;
-
- td = curthread;
- p = td->td_proc;
- PROC_LOCK_ASSERT(p, MA_OWNED);
- psp = p->p_sigacts;
- regs = td->td_frame;
- oonstack = sigonstack(regs->tf_esp);
-
- /* Save user context. */
- bzero(&sf, sizeof(sf));
- sf.sf_uc.uc_sigmask = *mask;
- sf.sf_uc.uc_stack = p->p_sigstk;
- sf.sf_uc.uc_stack.ss_flags = (p->p_flag & P_ALTSTACK)
- ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
- sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
- sf.sf_uc.uc_mcontext.mc_gs = rgs();
- bcopy(regs, &sf.sf_uc.uc_mcontext.mc_fs, sizeof(*regs));
-
- /* Allocate space for the signal handler context. */
- if ((p->p_flag & P_ALTSTACK) != 0 && !oonstack &&
- SIGISMEMBER(psp->ps_sigonstack, sig)) {
- sfp = (struct sigframe4 *)(p->p_sigstk.ss_sp +
- p->p_sigstk.ss_size - sizeof(struct sigframe4));
-#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
- p->p_sigstk.ss_flags |= SS_ONSTACK;
-#endif
- } else
- sfp = (struct sigframe4 *)regs->tf_esp - 1;
- PROC_UNLOCK(p);
-
- /* Translate the signal if appropriate. */
- if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
- sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
-
- /* Build the argument list for the signal handler. */
- sf.sf_signum = sig;
- sf.sf_ucontext = (register_t)&sfp->sf_uc;
- PROC_LOCK(p);
- if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) {
- /* Signal handler installed with SA_SIGINFO. */
- sf.sf_siginfo = (register_t)&sfp->sf_si;
- sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher;
-
- /* Fill in POSIX parts */
- sf.sf_si.si_signo = sig;
- sf.sf_si.si_code = code;
- sf.sf_si.si_addr = (void *)regs->tf_err;
- } else {
- /* Old FreeBSD-style arguments. */
- sf.sf_siginfo = code;
- sf.sf_addr = regs->tf_err;
- sf.sf_ahu.sf_handler = catcher;
- }
- PROC_UNLOCK(p);
-
- /*
- * If we're a vm86 process, we want to save the segment registers.
- * We also change eflags to be our emulated eflags, not the actual
- * eflags.
- */
- if (regs->tf_eflags & PSL_VM) {
- struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs;
- struct vm86_kernel *vm86 = &td->td_pcb->pcb_ext->ext_vm86;
-
- sf.sf_uc.uc_mcontext.mc_gs = tf->tf_vm86_gs;
- sf.sf_uc.uc_mcontext.mc_fs = tf->tf_vm86_fs;
- sf.sf_uc.uc_mcontext.mc_es = tf->tf_vm86_es;
- sf.sf_uc.uc_mcontext.mc_ds = tf->tf_vm86_ds;
-
- if (vm86->vm86_has_vme == 0)
- sf.sf_uc.uc_mcontext.mc_eflags =
- (tf->tf_eflags & ~(PSL_VIF | PSL_VIP)) |
- (vm86->vm86_eflags & (PSL_VIF | PSL_VIP));
-
- /*
- * Clear PSL_NT to inhibit T_TSSFLT faults on return from
- * syscalls made by the signal handler. This just avoids
- * wasting time for our lazy fixup of such faults. PSL_NT
- * does nothing in vm86 mode, but vm86 programs can set it
- * almost legitimately in probes for old cpu types.
- */
- tf->tf_eflags &= ~(PSL_VM | PSL_NT | PSL_VIF | PSL_VIP);
- }
-
- /*
- * Copy the sigframe out to the user's stack.
- */
- if (copyout(&sf, sfp, sizeof(*sfp)) != 0) {
-#ifdef DEBUG
- printf("process %ld has trashed its stack\n", (long)p->p_pid);
-#endif
- PROC_LOCK(p);
- sigexit(td, SIGILL);
- }
-
- regs->tf_esp = (int)sfp;
- regs->tf_eip = PS_STRINGS - szfreebsd4_sigcode;
- regs->tf_eflags &= ~PSL_T;
- regs->tf_cs = _ucodesel;
- regs->tf_ds = _udatasel;
- regs->tf_es = _udatasel;
- regs->tf_fs = _udatasel;
- regs->tf_ss = _udatasel;
- PROC_LOCK(p);
-}
-#endif /* COMPAT_FREEBSD4 */
-
void
sendsig(catcher, sig, mask, code)
sig_t catcher;
@@ -398,12 +272,6 @@
p = td->td_proc;
PROC_LOCK_ASSERT(p, MA_OWNED);
psp = p->p_sigacts;
-#ifdef COMPAT_FREEBSD4
- if (SIGISMEMBER(psp->ps_freebsd4, sig)) {
- freebsd4_sendsig(catcher, sig, mask, code);
- return;
- }
-#endif
regs = td->td_frame;
oonstack = sigonstack(regs->tf_esp);
@@ -492,117 +360,6 @@
*
* MPSAFE
*/
-#ifdef COMPAT_FREEBSD4
-/*
- * MPSAFE
- */
-int
-freebsd4_sigreturn(td, uap)
- struct thread *td;
- struct freebsd4_sigreturn_args /* {
- const ucontext4 *sigcntxp;
- } */ *uap;
-{
- struct ucontext4 uc;
- struct proc *p = td->td_proc;
- struct trapframe *regs;
- const struct ucontext4 *ucp;
- int cs, eflags, error;
-
- error = copyin(uap->sigcntxp, &uc, sizeof(uc));
- if (error != 0)
- return (error);
- ucp = &uc;
- regs = td->td_frame;
- eflags = ucp->uc_mcontext.mc_eflags;
- if (eflags & PSL_VM) {
- struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs;
- struct vm86_kernel *vm86;
-
- /*
- * if pcb_ext == 0 or vm86_inited == 0, the user hasn't
- * set up the vm86 area, and we can't enter vm86 mode.
- */
- if (td->td_pcb->pcb_ext == 0)
- return (EINVAL);
- vm86 = &td->td_pcb->pcb_ext->ext_vm86;
- if (vm86->vm86_inited == 0)
- return (EINVAL);
-
- /* Go back to user mode if both flags are set. */
- if ((eflags & PSL_VIP) && (eflags & PSL_VIF))
- trapsignal(td, SIGBUS, 0);
-
- if (vm86->vm86_has_vme) {
- eflags = (tf->tf_eflags & ~VME_USERCHANGE) |
- (eflags & VME_USERCHANGE) | PSL_VM;
- } else {
- vm86->vm86_eflags = eflags; /* save VIF, VIP */
- eflags = (tf->tf_eflags & ~VM_USERCHANGE) |
- (eflags & VM_USERCHANGE) | PSL_VM;
- }
- bcopy(&ucp->uc_mcontext.mc_fs, tf, sizeof(struct trapframe));
- tf->tf_eflags = eflags;
- tf->tf_vm86_ds = tf->tf_ds;
- tf->tf_vm86_es = tf->tf_es;
- tf->tf_vm86_fs = tf->tf_fs;
- tf->tf_vm86_gs = ucp->uc_mcontext.mc_gs;
- tf->tf_ds = _udatasel;
- tf->tf_es = _udatasel;
- tf->tf_fs = _udatasel;
- } else {
- /*
- * Don't allow users to change privileged or reserved flags.
- */
- /*
- * XXX do allow users to change the privileged flag PSL_RF.
- * The cpu sets PSL_RF in tf_eflags for faults. Debuggers
- * should sometimes set it there too. tf_eflags is kept in
- * the signal context during signal handling and there is no
- * other place to remember it, so the PSL_RF bit may be
- * corrupted by the signal handler without us knowing.
- * Corruption of the PSL_RF bit at worst causes one more or
- * one less debugger trap, so allowing it is fairly harmless.
- */
- if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF)) {
- printf("freebsd4_sigreturn: eflags = 0x%x\n", eflags);
- return (EINVAL);
- }
-
- /*
- * Don't allow users to load a valid privileged %cs. Let the
- * hardware check for invalid selectors, excess privilege in
- * other selectors, invalid %eip's and invalid %esp's.
- */
- cs = ucp->uc_mcontext.mc_cs;
- if (!CS_SECURE(cs)) {
- printf("freebsd4_sigreturn: cs = 0x%x\n", cs);
- trapsignal(td, SIGBUS, T_PROTFLT);
- return (EINVAL);
- }
-
- bcopy(&ucp->uc_mcontext.mc_fs, regs, sizeof(*regs));
- }
-
- PROC_LOCK(p);
-#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
- if (ucp->uc_mcontext.mc_onstack & 1)
- p->p_sigstk.ss_flags |= SS_ONSTACK;
- else
- p->p_sigstk.ss_flags &= ~SS_ONSTACK;
-#endif
-
- td->td_sigmask = ucp->uc_sigmask;
- SIG_CANTMASK(td->td_sigmask);
- signotify(td);
- PROC_UNLOCK(p);
- return (EJUSTRETURN);
-}
-#endif /* COMPAT_FREEBSD4 */
-
-/*
- * MPSAFE
- */
int
sigreturn(td, uap)
struct thread *td;
@@ -759,9 +516,6 @@
pcb->pcb_gs = _udatasel;
load_gs(_udatasel);
- if (td->td_proc->p_md.md_ldt)
- user_ldt_free(td);
-
bzero((char *)regs, sizeof(struct trapframe));
regs->tf_eip = entry;
regs->tf_esp = stack;
@@ -775,28 +529,6 @@
/* PS_STRINGS value for BSD/OS binaries. It is 0 for non-BSD/OS. */
regs->tf_ebx = ps_strings;
- /*
- * Reset the hardware debug registers if they were in use.
- * They won't have any meaning for the newly exec'd process.
- */
- if (pcb->pcb_flags & PCB_DBREGS) {
- pcb->pcb_dr0 = 0;
- pcb->pcb_dr1 = 0;
- pcb->pcb_dr2 = 0;
- pcb->pcb_dr3 = 0;
- pcb->pcb_dr6 = 0;
- pcb->pcb_dr7 = 0;
- if (pcb == PCPU_GET(curpcb)) {
- /*
- * Clear the debug registers on the running
- * CPU, otherwise they will end up affecting
- * the next process we switch to.
- */
- reset_dbregs();
- }
- pcb->pcb_flags &= ~PCB_DBREGS;
- }
-
/*
* Initialize the math emulator (if any) for the current process.
* Actually, just clear the bit that says that the emulator has
@@ -1932,185 +1664,17 @@
int
fill_dbregs(struct thread *td, struct dbreg *dbregs)
{
- struct pcb *pcb;
- if (td == NULL) {
- dbregs->dr[0] = rdr0();
- dbregs->dr[1] = rdr1();
- dbregs->dr[2] = rdr2();
- dbregs->dr[3] = rdr3();
- dbregs->dr[4] = rdr4();
- dbregs->dr[5] = rdr5();
- dbregs->dr[6] = rdr6();
- dbregs->dr[7] = rdr7();
- } else {
- pcb = td->td_pcb;
- dbregs->dr[0] = pcb->pcb_dr0;
- dbregs->dr[1] = pcb->pcb_dr1;
- dbregs->dr[2] = pcb->pcb_dr2;
- dbregs->dr[3] = pcb->pcb_dr3;
- dbregs->dr[4] = 0;
- dbregs->dr[5] = 0;
- dbregs->dr[6] = pcb->pcb_dr6;
- dbregs->dr[7] = pcb->pcb_dr7;
- }
return (0);
}
int
set_dbregs(struct thread *td, struct dbreg *dbregs)
{
- struct pcb *pcb;
- int i;
- u_int32_t mask1, mask2;
-
- if (td == NULL) {
- load_dr0(dbregs->dr[0]);
- load_dr1(dbregs->dr[1]);
- load_dr2(dbregs->dr[2]);
- load_dr3(dbregs->dr[3]);
- load_dr4(dbregs->dr[4]);
- load_dr5(dbregs->dr[5]);
- load_dr6(dbregs->dr[6]);
- load_dr7(dbregs->dr[7]);
- } else {
- /*
- * Don't let an illegal value for dr7 get set. Specifically,
- * check for undefined settings. Setting these bit patterns
- * result in undefined behaviour and can lead to an unexpected
- * TRCTRAP.
- */
- for (i = 0, mask1 = 0x3<<16, mask2 = 0x2<<16; i < 8;
- i++, mask1 <<= 2, mask2 <<= 2)
- if ((dbregs->dr[7] & mask1) == mask2)
- return (EINVAL);
-
- pcb = td->td_pcb;
-
- /*
- * Don't let a process set a breakpoint that is not within the
- * process's address space. If a process could do this, it
- * could halt the system by setting a breakpoint in the kernel
- * (if ddb was enabled). Thus, we need to check to make sure
- * that no breakpoints are being enabled for addresses outside
- * process's address space, unless, perhaps, we were called by
- * uid 0.
- *
- * XXX - what about when the watched area of the user's
- * address space is written into from within the kernel
- * ... wouldn't that still cause a breakpoint to be generated
- * from within kernel mode?
- */
- if (suser(td) != 0) {
- if (dbregs->dr[7] & 0x3) {
- /* dr0 is enabled */
- if (dbregs->dr[0] >= VM_MAXUSER_ADDRESS)
- return (EINVAL);
- }
-
- if (dbregs->dr[7] & (0x3<<2)) {
- /* dr1 is enabled */
- if (dbregs->dr[1] >= VM_MAXUSER_ADDRESS)
- return (EINVAL);
- }
-
- if (dbregs->dr[7] & (0x3<<4)) {
- /* dr2 is enabled */
- if (dbregs->dr[2] >= VM_MAXUSER_ADDRESS)
- return (EINVAL);
- }
-
- if (dbregs->dr[7] & (0x3<<6)) {
- /* dr3 is enabled */
- if (dbregs->dr[3] >= VM_MAXUSER_ADDRESS)
- return (EINVAL);
- }
- }
-
- pcb->pcb_dr0 = dbregs->dr[0];
- pcb->pcb_dr1 = dbregs->dr[1];
- pcb->pcb_dr2 = dbregs->dr[2];
- pcb->pcb_dr3 = dbregs->dr[3];
- pcb->pcb_dr6 = dbregs->dr[6];
- pcb->pcb_dr7 = dbregs->dr[7];
-
- pcb->pcb_flags |= PCB_DBREGS;
- }
-
return (0);
}
-/*
- * Return > 0 if a hardware breakpoint has been hit, and the
- * breakpoint was in user space. Return 0, otherwise.
- */
-int
-user_dbreg_trap(void)
-{
- u_int32_t dr7, dr6; /* debug registers dr6 and dr7 */
- u_int32_t bp; /* breakpoint bits extracted from dr6 */
- int nbp; /* number of breakpoints that triggered */
- caddr_t addr[4]; /* breakpoint addresses */
- int i;
-
- dr7 = rdr7();
- if ((dr7 & 0x000000ff) == 0) {
- /*
- * all GE and LE bits in the dr7 register are zero,
- * thus the trap couldn't have been caused by the
- * hardware debug registers
- */
- return 0;
- }
-
- nbp = 0;
- dr6 = rdr6();
- bp = dr6 & 0x0000000f;
-
- if (!bp) {
- /*
- * None of the breakpoint bits are set meaning this
- * trap was not caused by any of the debug registers
- */
- return 0;
- }
-
- /*
- * at least one of the breakpoints were hit, check to see
- * which ones and if any of them are user space addresses
- */
-
- if (bp & 0x01) {
- addr[nbp++] = (caddr_t)rdr0();
- }
- if (bp & 0x02) {
- addr[nbp++] = (caddr_t)rdr1();
- }
- if (bp & 0x04) {
- addr[nbp++] = (caddr_t)rdr2();
- }
- if (bp & 0x08) {
- addr[nbp++] = (caddr_t)rdr3();
- }
-
- for (i=0; i<nbp; i++) {
- if (addr[i] <
- (caddr_t)VM_MAXUSER_ADDRESS) {
- /*
- * addr[i] is in user space
- */
- return nbp;
- }
- }
-
- /*
- * None of the breakpoints are in user space.
- */
- return 0;
-}
-
-
#ifndef DDB
void
Debugger(const char *msg)
More information about the p4-projects
mailing list