From 5b9f6cc4be80527177ee4b19a289116490881da0 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Wed, 1 Apr 2009 17:57:01 -0700 Subject: [PATCH] AMD64 - Make signals operational, fix reg mappings, fix %fs management, trace Adjust sigframe, trapframe, mcontext, ucontext, and regs. Add tf_xflags too all structures. Reorder struct regs to match the register layout in the other structures. Implement the commented out signaling code. Signals now work, or at least do not crash programs. Theoretically the FP state is also saved and restored. The exec() code failed to adjust gd_user_fs and gd_user_gs when setting the msr registers for the user %fs and %gs, causing %fs to unexpectedly change in running user programs. Implement trace/debug support functions to set %rip and to single-step. Define the missing vkernel flag FP_SOFTFP. --- sys/cpu/amd64/include/asmacros.h | 2 +- sys/cpu/amd64/include/frame.h | 5 +- sys/cpu/amd64/include/pmap.h | 14 ++ sys/cpu/amd64/include/psl.h | 2 +- sys/cpu/amd64/include/reg.h | 23 +-- sys/cpu/amd64/include/signal.h | 1 + sys/cpu/amd64/include/ucontext.h | 4 + sys/platform/pc64/amd64/exception.S | 5 +- sys/platform/pc64/amd64/genassym.c | 1 + sys/platform/pc64/amd64/ipl.s | 1 + sys/platform/pc64/amd64/machdep.c | 249 ++++++++++------------------ sys/platform/pc64/amd64/support.s | 2 +- sys/platform/pc64/amd64/swtch.s | 1 + sys/platform/pc64/amd64/trap.c | 3 + sys/platform/pc64/icu/icu_vector.s | 3 +- sys/platform/pc64/include/pcb.h | 1 + 16 files changed, 132 insertions(+), 185 deletions(-) diff --git a/sys/cpu/amd64/include/asmacros.h b/sys/cpu/amd64/include/asmacros.h index 3f5ec08eb8..d012719ba1 100644 --- a/sys/cpu/amd64/include/asmacros.h +++ b/sys/cpu/amd64/include/asmacros.h @@ -191,7 +191,7 @@ jz 1f ; /* keep kernel GS.base */ \ cli ; \ swapgs ; \ -1: addq $TF_RIP,%rsp /* skip over tf_err, tf_trapno */ +1: addq $TF_RIP,%rsp /* skip over tf_err, tf_trapno, tf_xflags */ /* * Access per-CPU data. diff --git a/sys/cpu/amd64/include/frame.h b/sys/cpu/amd64/include/frame.h index ee389dd83d..59cfd00dcf 100644 --- a/sys/cpu/amd64/include/frame.h +++ b/sys/cpu/amd64/include/frame.h @@ -58,9 +58,7 @@ */ struct trapframe { - /* fs XXX */ - /* es XXX */ - /* ds XXX */ + /* note: tf_rdi matches mc_rdi in mcontext */ register_t tf_rdi; register_t tf_rsi; register_t tf_rdx; @@ -76,6 +74,7 @@ struct trapframe { register_t tf_r13; register_t tf_r14; register_t tf_r15; + register_t tf_xflags; register_t tf_trapno; register_t tf_addr; register_t tf_flags; diff --git a/sys/cpu/amd64/include/pmap.h b/sys/cpu/amd64/include/pmap.h index cbed116ce7..5c5d0b8b21 100644 --- a/sys/cpu/amd64/include/pmap.h +++ b/sys/cpu/amd64/include/pmap.h @@ -94,4 +94,18 @@ #define PGEX_RSV 0x08 /* reserved PTE field is non-zero */ #define PGEX_I 0x10 /* during an instruction fetch */ +/* + * Virtual kernel bits, managed by software. Stored in tf_xflags. + * + * PGEX_FPFAULT - Force the FP unit to generate a T_DNA fault if an + * emulated user process tried to use it. This bit is + * only used by vmspace_ctl(). + * + * PGEX_MAILBOX - Set in xflags by signal code to indicate that a mailbox + * signal was pending. Remerged on signal return. This + * bit is only used in a signal vector frame. + */ +#define PGEX_MAILBOX 0x40 +#define PGEX_FPFAULT 0x80 + #endif /* !_CPU_PMAP_H_ */ diff --git a/sys/cpu/amd64/include/psl.h b/sys/cpu/amd64/include/psl.h index eaacaeae2c..7fddf8497b 100644 --- a/sys/cpu/amd64/include/psl.h +++ b/sys/cpu/amd64/include/psl.h @@ -56,7 +56,7 @@ #define PSL_IOPL 0x00003000 /* i/o privilege level */ #define PSL_NT 0x00004000 /* nested task bit */ #define PSL_RF 0x00010000 /* resume flag bit */ -/* #define PSL_VM 0x00020000 */ /* virtual 8086 mode bit */ +#define PSL_VM_UNSUPP 0x00020000 /* virtual 8086 mode bit */ #define PSL_AC 0x00040000 /* alignment checking */ /* #define PSL_VIF 0x00080000 */ /* virtual interrupt enable */ /* #define PSL_VIP 0x00100000 */ /* virtual interrupt pending */ diff --git a/sys/cpu/amd64/include/reg.h b/sys/cpu/amd64/include/reg.h index 58ad151926..1289d4a899 100644 --- a/sys/cpu/amd64/include/reg.h +++ b/sys/cpu/amd64/include/reg.h @@ -42,22 +42,25 @@ * Register set accessible via /proc/$pid/regs and PT_{SET,GET}REGS. */ struct reg { - register_t r_r15; - register_t r_r14; - register_t r_r13; - register_t r_r12; - register_t r_r11; - register_t r_r10; - register_t r_r9; - register_t r_r8; register_t r_rdi; register_t r_rsi; - register_t r_rbp; - register_t r_rbx; register_t r_rdx; register_t r_rcx; + register_t r_r8; + register_t r_r9; register_t r_rax; + register_t r_rbx; + register_t r_rbp; + register_t r_r10; + register_t r_r11; + register_t r_r12; + register_t r_r13; + register_t r_r14; + register_t r_r15; + register_t r_xflags; register_t r_trapno; + register_t r_addr; + register_t r_flags; register_t r_err; register_t r_rip; register_t r_cs; diff --git a/sys/cpu/amd64/include/signal.h b/sys/cpu/amd64/include/signal.h index 5dbc973f05..8cdad1e503 100644 --- a/sys/cpu/amd64/include/signal.h +++ b/sys/cpu/amd64/include/signal.h @@ -132,6 +132,7 @@ struct sigcontext { long sc_r13; long sc_r14; long sc_r15; + long sc_xflags; long sc_trapno; long sc_addr; long sc_flags; diff --git a/sys/cpu/amd64/include/ucontext.h b/sys/cpu/amd64/include/ucontext.h index b53c769e8d..396dd622a4 100644 --- a/sys/cpu/amd64/include/ucontext.h +++ b/sys/cpu/amd64/include/ucontext.h @@ -39,6 +39,9 @@ typedef struct __mcontext { * The first 20 fields must match the definition of * sigcontext. So that we can support sigcontext * and ucontext_t at the same time. + * + * NOTE: bcopy in sendsig copies trapframe to this + * structure as of mc_rdi. */ __register_t mc_onstack; /* XXX - sigcontext compat. */ __register_t mc_rdi; @@ -56,6 +59,7 @@ typedef struct __mcontext { __register_t mc_r13; __register_t mc_r14; __register_t mc_r15; + __register_t mc_xflags; __register_t mc_trapno; __register_t mc_addr; __register_t mc_flags; diff --git a/sys/platform/pc64/amd64/exception.S b/sys/platform/pc64/amd64/exception.S index ae9c540eeb..e469fec2c8 100644 --- a/sys/platform/pc64/amd64/exception.S +++ b/sys/platform/pc64/amd64/exception.S @@ -84,6 +84,7 @@ MCOUNT_LABEL(btrap) /* Traps that we leave interrupts disabled for.. */ #define TRAP_NOEN(a) \ subq $TF_RIP,%rsp; \ + movq $0,TF_XFLAGS(%rsp) ; \ movq $(a),TF_TRAPNO(%rsp) ; \ movq $0,TF_ADDR(%rsp) ; \ movq $0,TF_ERR(%rsp) ; \ @@ -96,6 +97,7 @@ IDTVEC(bpt) /* Regular traps; The cpu does not supply tf_err for these. */ #define TRAP(a) \ subq $TF_RIP,%rsp; \ + movq $0,TF_XFLAGS(%rsp) ; \ movq $(a),TF_TRAPNO(%rsp) ; \ movq $0,TF_ADDR(%rsp) ; \ movq $0,TF_ERR(%rsp) ; \ @@ -463,9 +465,6 @@ pmsg4: .asciz "fork_trampoline mpcount %d after calling %p" * * trapframe is at the top of the stack. */ -#if JG - pushl $0 /* cpl to restore */ -#endif MEXITCOUNT jmp doreti diff --git a/sys/platform/pc64/amd64/genassym.c b/sys/platform/pc64/amd64/genassym.c index df64c124f4..64cb85e0b6 100644 --- a/sys/platform/pc64/amd64/genassym.c +++ b/sys/platform/pc64/amd64/genassym.c @@ -150,6 +150,7 @@ ASSYM(TF_RCX, offsetof(struct trapframe, tf_rcx)); ASSYM(TF_RAX, offsetof(struct trapframe, tf_rax)); ASSYM(TF_TRAPNO, offsetof(struct trapframe, tf_trapno)); +ASSYM(TF_XFLAGS, offsetof(struct trapframe, tf_xflags)); ASSYM(TF_ADDR, offsetof(struct trapframe, tf_addr)); ASSYM(TF_ERR, offsetof(struct trapframe, tf_err)); ASSYM(TF_FLAGS, offsetof(struct trapframe, tf_flags)); diff --git a/sys/platform/pc64/amd64/ipl.s b/sys/platform/pc64/amd64/ipl.s index d5ac7b4a8e..d63fcaa588 100644 --- a/sys/platform/pc64/amd64/ipl.s +++ b/sys/platform/pc64/amd64/ipl.s @@ -505,6 +505,7 @@ splz_ipiq: pushq %rax ; /* phys int frame / cs */ \ pushq 3*8(%rsp) ; /* original caller eip */ \ subq $TF_RIP,%rsp ; /* trap frame */ \ + movq $0,TF_XFLAGS(%rsp) ; /* extras */ \ movq $0,TF_TRAPNO(%rsp) ; /* extras */ \ movq $0,TF_ADDR(%rsp) ; /* extras */ \ movq $0,TF_FLAGS(%rsp) ; /* extras */ \ diff --git a/sys/platform/pc64/amd64/machdep.c b/sys/platform/pc64/amd64/machdep.c index ef52eccd7b..390fa00ef5 100644 --- a/sys/platform/pc64/amd64/machdep.c +++ b/sys/platform/pc64/amd64/machdep.c @@ -299,7 +299,8 @@ cpu_startup(void *dummy) #ifdef PERFMON perfmon_init(); #endif - kprintf("real memory = %llu (%lluK bytes)\n", ptoa(Maxmem), ptoa(Maxmem) / 1024); + kprintf("real memory = %llu (%lluK bytes)\n", + (long long)ptoa(Maxmem), (long long)ptoa(Maxmem) / 1024); /* * Display any holes after the first chunk of extended memory. */ @@ -311,8 +312,10 @@ cpu_startup(void *dummy) vm_paddr_t size1 = phys_avail[indx + 1] - phys_avail[indx]; kprintf("0x%08llx - 0x%08llx, %llu bytes (%llu pages)\n", - phys_avail[indx], phys_avail[indx + 1] - 1, size1, - size1 / PAGE_SIZE); + (long long)phys_avail[indx], + (long long)phys_avail[indx + 1] - 1, + (long long)size1, + (long long)(size1 / PAGE_SIZE)); } } @@ -415,8 +418,9 @@ again: cninit(); /* the preferred console may have changed */ #endif - kprintf("avail memory = %u (%uK bytes)\n", ptoa(vmstats.v_free_count), - ptoa(vmstats.v_free_count) / 1024); + kprintf("avail memory = %lu (%luK bytes)\n", + ptoa(vmstats.v_free_count), + ptoa(vmstats.v_free_count) / 1024); /* * Set up buffers, so they can be used to read disk labels. @@ -463,18 +467,15 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) sf.sf_uc.uc_sigmask = *mask; sf.sf_uc.uc_stack = lp->lwp_sigstk; sf.sf_uc.uc_mcontext.mc_onstack = oonstack; -#if JG - bcopy(regs, &sf.sf_uc.uc_mcontext.mc_gs, sizeof(struct trapframe)); -#endif + KKASSERT(__offsetof(struct trapframe, tf_rdi) == 0); + bcopy(regs, &sf.sf_uc.uc_mcontext.mc_rdi, sizeof(struct trapframe)); /* make the size of the saved context visible to userland */ sf.sf_uc.uc_mcontext.mc_len = sizeof(sf.sf_uc.uc_mcontext); /* save mailbox pending state for syscall interlock semantics */ -#if JG if (p->p_flag & P_MAILBOX) sf.sf_uc.uc_mcontext.mc_xflags |= PGEX_MAILBOX; -#endif /* Allocate and validate space for the signal handler context. */ if ((lp->lwp_flag & LWP_ALTSTACK) != 0 && !oonstack && @@ -483,9 +484,7 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) lp->lwp_sigstk.ss_size - sizeof(struct sigframe)); lp->lwp_sigstk.ss_flags |= SS_ONSTACK; } else { -#if JG - sfp = (struct sigframe *)regs->tf_esp - 1; -#endif + sfp = (struct sigframe *)regs->tf_rsp - 1; } /* Translate the signal is appropriate */ @@ -548,9 +547,7 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) /* * Save the FPU state and reinit the FP unit */ -#if JG npxpush(&sf.sf_uc.uc_mcontext); -#endif /* * Copy the sigframe out to the user's stack. @@ -563,39 +560,21 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) sigexit(lp, SIGILL); } -#if JG - regs->tf_esp = (int)sfp; - regs->tf_eip = PS_STRINGS - *(p->p_sysent->sv_szsigcode); -#endif + regs->tf_rsp = (register_t)sfp; + regs->tf_rip = PS_STRINGS - *(p->p_sysent->sv_szsigcode); /* * i386 abi specifies that the direction flag must be cleared * on function entry */ -#if JG - regs->tf_eflags &= ~(PSL_T|PSL_D); -#endif + regs->tf_rflags &= ~(PSL_T|PSL_D); regs->tf_cs = _ucodesel; -#if JG - regs->tf_ds = _udatasel; - regs->tf_es = _udatasel; -#endif + /* no DS or ES */ /* - * Allow the signal handler to inherit %fs in addition to %gs as - * the userland program might be using both. - * - * However, if a T_PROTFLT occured the segment registers could be - * totally broken. They must be reset in order to be able to - * return to userland. + * Set a degenerate SS. We don't have to worry about %fs or %gs? */ - if (regs->tf_trapno == T_PROTFLT) { -#if JG - regs->tf_fs = _udatasel; - regs->tf_gs = _udatasel; -#endif - } regs->tf_ss = _udatasel; } @@ -612,19 +591,11 @@ cpu_sanitize_frame(struct trapframe *frame) { kprintf0("cpu_sanitize_frame\n"); frame->tf_cs = _ucodesel; -#if JG - frame->tf_ds = _udatasel; - frame->tf_es = _udatasel; /* XXX allow userland this one too? */ -#endif -#if 0 - frame->tf_fs = _udatasel; - frame->tf_gs = _udatasel; -#endif frame->tf_ss = _udatasel; -#if JG - frame->tf_eflags &= (PSL_RF | PSL_USERCHANGE); - frame->tf_eflags |= PSL_RESERVED_DEFAULT | PSL_I; -#endif + /* XXX VM (8086) mode not supported? */ + frame->tf_rflags &= (PSL_RF | PSL_USERCHANGE | PSL_VM_UNSUPP); + frame->tf_rflags |= PSL_RESERVED_DEFAULT | PSL_I; + return(0); } @@ -660,8 +631,8 @@ sys_sigreturn(struct sigreturn_args *uap) struct trapframe *regs; ucontext_t uc; ucontext_t *ucp; + register_t rflags; int cs; - int eflags; int error; /* @@ -673,9 +644,10 @@ sys_sigreturn(struct sigreturn_args *uap) if (error) return (error); ucp = &uc; -#if JG - eflags = ucp->uc_mcontext.mc_eflags; -#endif + rflags = ucp->uc_mcontext.mc_rflags; + + /* VM (8086) mode not supported */ + rflags &= ~PSL_VM_UNSUPP; #if JG if (eflags & PSL_VM) { @@ -697,32 +669,26 @@ sys_sigreturn(struct sigreturn_args *uap) trapsignal(lp, SIGBUS, 0); if (vm86->vm86_has_vme) { -#if JG eflags = (tf->tf_eflags & ~VME_USERCHANGE) | (eflags & VME_USERCHANGE) | PSL_VM; -#endif } else { -#if JG vm86->vm86_eflags = eflags; /* save VIF, VIP */ eflags = (tf->tf_eflags & ~VM_USERCHANGE) | (eflags & VM_USERCHANGE) | PSL_VM; -#endif } -#if JG bcopy(&ucp->uc_mcontext.mc_gs, tf, sizeof(struct trapframe)); tf->tf_eflags = eflags; -#endif 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 = tf->tf_gs; tf->tf_ds = _udatasel; tf->tf_es = _udatasel; -#if 0 tf->tf_fs = _udatasel; tf->tf_gs = _udatasel; + } else #endif - } else { + { /* * Don't allow users to change privileged or reserved flags. */ @@ -736,12 +702,10 @@ sys_sigreturn(struct sigreturn_args *uap) * Corruption of the PSL_RF bit at worst causes one more or * one less debugger trap, so allowing it is fairly harmless. */ -#if JG - if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF)) { - kprintf("sigreturn: eflags = 0x%x\n", eflags); + if (!EFL_SECURE(rflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF)) { + kprintf("sigreturn: rflags = 0x%lx\n", (long)rflags); return(EINVAL); } -#endif /* * Don't allow users to load a valid privileged %cs. Let the @@ -754,27 +718,20 @@ sys_sigreturn(struct sigreturn_args *uap) trapsignal(lp, SIGBUS, T_PROTFLT); return(EINVAL); } -#if JG - bcopy(&ucp->uc_mcontext.mc_gs, regs, sizeof(struct trapframe)); -#endif + bcopy(&ucp->uc_mcontext.mc_rdi, regs, sizeof(struct trapframe)); } -#endif /* * Restore the FPU state from the frame */ -#if JG npxpop(&ucp->uc_mcontext); -#endif /* * Merge saved signal mailbox pending flag to maintain interlock * semantics against system calls. */ -#if JG if (ucp->uc_mcontext.mc_xflags & PGEX_MAILBOX) p->p_flag |= P_MAILBOX; -#endif if (ucp->uc_mcontext.mc_onstack & 1) lp->lwp_sigstk.ss_flags |= SS_ONSTACK; @@ -787,14 +744,14 @@ sys_sigreturn(struct sigreturn_args *uap) } /* - * Stack frame on entry to function. %eax will contain the function vector, - * %ecx will contain the function data. flags, ecx, and eax will have + * Stack frame on entry to function. %rax will contain the function vector, + * %rcx will contain the function data. flags, rcx, and rax will have * already been pushed on the stack. */ struct upc_frame { - register_t eax; - register_t ecx; - register_t edx; + register_t rax; + register_t rcx; + register_t rdx; register_t flags; register_t oldip; }; @@ -863,23 +820,21 @@ sendupcall(struct vmupcall *vu, int morepending) * Construct a stack frame and issue the upcall */ regs = lp->lwp_md.md_regs; -#if JG - upc_frame.eax = regs->tf_eax; - upc_frame.ecx = regs->tf_ecx; - upc_frame.edx = regs->tf_edx; - upc_frame.flags = regs->tf_eflags; - upc_frame.oldip = regs->tf_eip; - if (copyout(&upc_frame, (void *)(regs->tf_esp - sizeof(upc_frame)), + upc_frame.rax = regs->tf_rax; + upc_frame.rcx = regs->tf_rcx; + upc_frame.rdx = regs->tf_rdx; + upc_frame.flags = regs->tf_rflags; + upc_frame.oldip = regs->tf_rip; + if (copyout(&upc_frame, (void *)(regs->tf_rsp - sizeof(upc_frame)), sizeof(upc_frame)) != 0) { kprintf("bad stack on upcall\n"); } else { - regs->tf_eax = (register_t)vu->vu_func; - regs->tf_ecx = (register_t)vu->vu_data; - regs->tf_edx = (register_t)lp->lwp_upcall; - regs->tf_eip = (register_t)vu->vu_ctx; - regs->tf_esp -= sizeof(upc_frame); + regs->tf_rax = (register_t)vu->vu_func; + regs->tf_rcx = (register_t)vu->vu_data; + regs->tf_rdx = (register_t)lp->lwp_upcall; + regs->tf_rip = (register_t)vu->vu_ctx; + regs->tf_rsp -= sizeof(upc_frame); } -#endif } /* @@ -916,27 +871,23 @@ fetchupcall(struct vmupcall *vu, int morepending, void *rsp) crit_count += TDPRI_CRIT; if (error == 0) error = copyout(&crit_count, (char *)upcall.upc_uthread + upcall.upc_critoff, sizeof(int)); -#if JG - regs->tf_eax = (register_t)vu->vu_func; - regs->tf_ecx = (register_t)vu->vu_data; - regs->tf_edx = (register_t)lp->lwp_upcall; - regs->tf_eip = (register_t)vu->vu_ctx; - regs->tf_esp = (register_t)rsp; -#endif + regs->tf_rax = (register_t)vu->vu_func; + regs->tf_rcx = (register_t)vu->vu_data; + regs->tf_rdx = (register_t)lp->lwp_upcall; + regs->tf_rip = (register_t)vu->vu_ctx; + regs->tf_rsp = (register_t)rsp; } else { /* * This returns us to the originally interrupted code. */ error = copyin(rsp, &upc_frame, sizeof(upc_frame)); -#if JG - regs->tf_eax = upc_frame.eax; - regs->tf_ecx = upc_frame.ecx; - regs->tf_edx = upc_frame.edx; - regs->tf_eflags = (regs->tf_eflags & ~PSL_USERCHANGE) | + regs->tf_rax = upc_frame.rax; + regs->tf_rcx = upc_frame.rcx; + regs->tf_rdx = upc_frame.rdx; + regs->tf_rflags = (regs->tf_rflags & ~PSL_USERCHANGE) | (upc_frame.flags & PSL_USERCHANGE); - regs->tf_eip = upc_frame.oldip; - regs->tf_esp = (register_t)((char *)rsp + sizeof(upc_frame)); -#endif + regs->tf_rip = upc_frame.oldip; + regs->tf_rsp = (register_t)((char *)rsp + sizeof(upc_frame)); } } if (error == 0) @@ -1121,22 +1072,27 @@ exec_setregs(u_long entry, u_long stack, u_long ps_strings) * traps to the emulator (if it is done at all) mainly because * emulators don't provide an entry point for initialization. */ -#if JG pcb->pcb_flags &= ~FP_SOFTFP; -#endif /* - * note: do not set CR0_TS here. npxinit() must do it after clearing - * gd_npxthread. Otherwise a preemptive interrupt thread may panic - * in npxdna(). + * NOTE: do not set CR0_TS here. npxinit() must do it after clearing + * gd_npxthread. Otherwise a preemptive interrupt thread + * may panic in npxdna(). */ crit_enter(); load_cr0(rcr0() | CR0_MP); - wrmsr(MSR_FSBASE, 0); - wrmsr(MSR_KGSBASE, 0); /* User value while we're in the kernel */ - pcb->pcb_fsbase = 0; + /* + * NOTE: The MSR values must be correct so we can return to + * userland. gd_user_fs/gs must be correct so the switch + * code knows what the current MSR values are. + */ + pcb->pcb_fsbase = 0; /* Values loaded from PCB on switch */ pcb->pcb_gsbase = 0; + mdcpu->gd_user_fs = 0; /* Cache of current MSR values */ + mdcpu->gd_user_gs = 0; + wrmsr(MSR_FSBASE, 0); /* Set MSR values for return to userland */ + wrmsr(MSR_KGSBASE, 0); #if NNPX > 0 /* Initialize the npx (if any) for the current process. */ @@ -1700,7 +1656,10 @@ u_int64_t hammer_time(u_int64_t modulep, u_int64_t physfree) { caddr_t kmdp; - int gsel_tss, metadata_missing, off, x; + int gsel_tss, x; +#if JG + int metadata_missing, off; +#endif struct mdglobaldata *gd; u_int64_t msr; char *env; @@ -1850,8 +1809,9 @@ hammer_time(u_int64_t modulep, u_int64_t physfree) initializecpu(); /* Initialize CPU registers */ /* make an initial tss so cpu can get interrupt stack on syscall! */ - gd->gd_common_tss.tss_rsp0 = thread0.td_kstack + \ - KSTACK_PAGES * PAGE_SIZE - sizeof(struct pcb); + gd->gd_common_tss.tss_rsp0 = + (register_t)(thread0.td_kstack + + KSTACK_PAGES * PAGE_SIZE - sizeof(struct pcb)); /* Ensure the stack is aligned to 16 bytes */ gd->gd_common_tss.tss_rsp0 &= ~0xFul; gd->gd_rsp0 = gd->gd_common_tss.tss_rsp0; @@ -1998,18 +1958,14 @@ f00f_hack(void *unused) int ptrace_set_pc(struct lwp *lp, unsigned long addr) { -#if JG - lp->lwp_md.md_regs->tf_eip = addr; -#endif + lp->lwp_md.md_regs->tf_rip = addr; return (0); } int ptrace_single_step(struct lwp *lp) { -#if JG - lp->lwp_md.md_regs->tf_eflags |= PSL_T; -#endif + lp->lwp_md.md_regs->tf_rflags |= PSL_T; return (0); } @@ -2020,26 +1976,8 @@ fill_regs(struct lwp *lp, struct reg *regs) struct trapframe *tp; tp = lp->lwp_md.md_regs; -#if JG - regs->r_gs = tp->tf_gs; - regs->r_fs = tp->tf_fs; - regs->r_es = tp->tf_es; - regs->r_ds = tp->tf_ds; - regs->r_edi = tp->tf_edi; - regs->r_esi = tp->tf_esi; - regs->r_ebp = tp->tf_ebp; - regs->r_ebx = tp->tf_ebx; - regs->r_edx = tp->tf_edx; - regs->r_ecx = tp->tf_ecx; - regs->r_eax = tp->tf_eax; - regs->r_eip = tp->tf_eip; -#endif - regs->r_cs = tp->tf_cs; -#if JG - regs->r_eflags = tp->tf_eflags; - regs->r_esp = tp->tf_esp; -#endif - regs->r_ss = tp->tf_ss; + bcopy(&tp->tf_rdi, ®s->r_rdi, sizeof(*regs)); + pcb = lp->lwp_thread->td_pcb; return (0); } @@ -2051,29 +1989,10 @@ set_regs(struct lwp *lp, struct reg *regs) struct trapframe *tp; tp = lp->lwp_md.md_regs; -#if JG - if (!EFL_SECURE(regs->r_eflags, tp->tf_eflags) || + if (!EFL_SECURE(regs->r_rflags, tp->tf_rflags) || !CS_SECURE(regs->r_cs)) return (EINVAL); - tp->tf_gs = regs->r_gs; - tp->tf_fs = regs->r_fs; - tp->tf_es = regs->r_es; - tp->tf_ds = regs->r_ds; - tp->tf_edi = regs->r_edi; - tp->tf_esi = regs->r_esi; - tp->tf_ebp = regs->r_ebp; - tp->tf_ebx = regs->r_ebx; - tp->tf_edx = regs->r_edx; - tp->tf_ecx = regs->r_ecx; - tp->tf_eax = regs->r_eax; - tp->tf_eip = regs->r_eip; -#endif - tp->tf_cs = regs->r_cs; -#if JG - tp->tf_eflags = regs->r_eflags; - tp->tf_esp = regs->r_esp; -#endif - tp->tf_ss = regs->r_ss; + bcopy(®s->r_rdi, &tp->tf_rdi, sizeof(*regs)); pcb = lp->lwp_thread->td_pcb; return (0); } diff --git a/sys/platform/pc64/amd64/support.s b/sys/platform/pc64/amd64/support.s index b19e4e3307..6995903682 100644 --- a/sys/platform/pc64/amd64/support.s +++ b/sys/platform/pc64/amd64/support.s @@ -669,7 +669,7 @@ ENTRY(lgdt) movl %eax,%ds movl %eax,%es movl %eax,%fs /* Beware, use wrmsr to set 64 bit base */ - movl %eax,%gs + movl %eax,%gs /* Beware, use wrmsr to set 64 bit base */ movl %eax,%ss /* reload code selector by turning return into intersegmental return */ diff --git a/sys/platform/pc64/amd64/swtch.s b/sys/platform/pc64/amd64/swtch.s index 3a5b07edb5..2b10dd68c3 100644 --- a/sys/platform/pc64/amd64/swtch.s +++ b/sys/platform/pc64/amd64/swtch.s @@ -318,6 +318,7 @@ ENTRY(cpu_heavy_restore) * already have been set before we set it above, check? YYY */ #if JG +#error x movq %cr3,%rsi movq PCB_CR3(%rdx),%rcx cmpq %rsi,%rcx diff --git a/sys/platform/pc64/amd64/trap.c b/sys/platform/pc64/amd64/trap.c index dc8c6035e1..04fc9aee61 100644 --- a/sys/platform/pc64/amd64/trap.c +++ b/sys/platform/pc64/amd64/trap.c @@ -898,6 +898,9 @@ nogo: * NOTE: on amd64 we have a tf_addr field in the trapframe, no * kludge is needed to pass the fault address to signal handlers. */ + kprintf("seg-fault accessing address %p ip=%p\n", + va, frame->tf_rip); + Debugger("seg-fault"); return((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV); } diff --git a/sys/platform/pc64/icu/icu_vector.s b/sys/platform/pc64/icu/icu_vector.s index b0b18e1223..63ef84d05c 100644 --- a/sys/platform/pc64/icu/icu_vector.s +++ b/sys/platform/pc64/icu/icu_vector.s @@ -89,7 +89,8 @@ * Macro helpers */ #define ICU_PUSH_FRAME \ - PUSH_FRAME ; /* 15 regs + space for 4 extras */ \ + PUSH_FRAME ; /* 15 regs + space for 5 extras */ \ + movl $0,TF_XFLAGS(%rsp) ; \ movl $0,TF_TRAPNO(%rsp) ; \ movl $0,TF_ADDR(%rsp) ; \ movl $0,TF_FLAGS(%rsp) ; \ diff --git a/sys/platform/pc64/include/pcb.h b/sys/platform/pc64/include/pcb.h index 4656a9d604..7dd01519ee 100644 --- a/sys/platform/pc64/include/pcb.h +++ b/sys/platform/pc64/include/pcb.h @@ -81,6 +81,7 @@ struct pcb { #define PCB_DBREGS 0x02 /* process using debug registers */ #define PCB_FPUINITDONE 0x08 /* fpu state is initialized */ #define PCB_FULLCTX 0x80 /* full context restore on sysret */ +#define FP_SOFTFP 0x01 /* process using software fltng pnt emulator */ #define FP_VIRTFP 0x04 /* virtual kernel wants exception */ caddr_t pcb_onfault; /* copyin/out fault recovery */ int pcb_unused; -- 2.41.0