Changeset View
Changeset View
Standalone View
Standalone View
sys/amd64/linux/linux_sysvec.c
Show First 20 Lines • Show All 313 Lines • ▼ Show 20 Lines | ||||||||||
* Copied from amd64/amd64/machdep.c | * Copied from amd64/amd64/machdep.c | |||||||||
* | * | |||||||||
* XXX fpu state need? don't think so | * XXX fpu state need? don't think so | |||||||||
*/ | */ | |||||||||
int | int | |||||||||
linux_rt_sigreturn(struct thread *td, struct linux_rt_sigreturn_args *args) | linux_rt_sigreturn(struct thread *td, struct linux_rt_sigreturn_args *args) | |||||||||
{ | { | |||||||||
struct proc *p; | struct proc *p; | |||||||||
struct l_ucontext uc; | struct l_rt_sigframe sf; | |||||||||
struct l_sigcontext *context; | struct l_sigcontext *context; | |||||||||
struct trapframe *regs; | struct trapframe *regs; | |||||||||
mcontext_t mc; | ||||||||||
unsigned long rflags; | unsigned long rflags; | |||||||||
sigset_t bmask; | sigset_t bmask; | |||||||||
int error; | int error, i; | |||||||||
ksiginfo_t ksi; | ksiginfo_t ksi; | |||||||||
regs = td->td_frame; | regs = td->td_frame; | |||||||||
error = copyin((void *)regs->tf_rbx, &uc, sizeof(uc)); | error = copyin((void *)regs->tf_rbx, &sf, sizeof(sf)); | |||||||||
if (error != 0) | if (error != 0) | |||||||||
return (error); | return (error); | |||||||||
p = td->td_proc; | p = td->td_proc; | |||||||||
context = &uc.uc_mcontext; | context = &sf.sf_uc.uc_mcontext; | |||||||||
rflags = context->sc_rflags; | rflags = context->sc_rflags; | |||||||||
/* | /* | |||||||||
* Don't allow users to change privileged or reserved flags. | * Don't allow users to change privileged or reserved flags. | |||||||||
*/ | */ | |||||||||
/* | /* | |||||||||
* XXX do allow users to change the privileged flag PSL_RF. | * XXX do allow users to change the privileged flag PSL_RF. | |||||||||
* The cpu sets PSL_RF in tf_rflags for faults. Debuggers | * The cpu sets PSL_RF in tf_rflags for faults. Debuggers | |||||||||
Show All 22 Lines | if (!CS_SECURE(context->sc_cs)) { | |||||||||
ksi.ksi_signo = SIGBUS; | ksi.ksi_signo = SIGBUS; | |||||||||
ksi.ksi_code = BUS_OBJERR; | ksi.ksi_code = BUS_OBJERR; | |||||||||
ksi.ksi_trapno = T_PROTFLT; | ksi.ksi_trapno = T_PROTFLT; | |||||||||
ksi.ksi_addr = (void *)regs->tf_rip; | ksi.ksi_addr = (void *)regs->tf_rip; | |||||||||
trapsignal(td, &ksi); | trapsignal(td, &ksi); | |||||||||
return (EINVAL); | return (EINVAL); | |||||||||
} | } | |||||||||
linux_to_bsd_sigset(&uc.uc_sigmask, &bmask); | linux_to_bsd_sigset(&sf.sf_uc.uc_sigmask, &bmask); | |||||||||
kern_sigprocmask(td, SIG_SETMASK, &bmask, NULL, 0); | kern_sigprocmask(td, SIG_SETMASK, &bmask, NULL, 0); | |||||||||
regs->tf_rdi = context->sc_rdi; | regs->tf_rdi = context->sc_rdi; | |||||||||
regs->tf_rsi = context->sc_rsi; | regs->tf_rsi = context->sc_rsi; | |||||||||
regs->tf_rdx = context->sc_rdx; | regs->tf_rdx = context->sc_rdx; | |||||||||
regs->tf_rbp = context->sc_rbp; | regs->tf_rbp = context->sc_rbp; | |||||||||
regs->tf_rbx = context->sc_rbx; | regs->tf_rbx = context->sc_rbx; | |||||||||
regs->tf_rcx = context->sc_rcx; | regs->tf_rcx = context->sc_rcx; | |||||||||
regs->tf_rax = context->sc_rax; | regs->tf_rax = context->sc_rax; | |||||||||
regs->tf_rip = context->sc_rip; | regs->tf_rip = context->sc_rip; | |||||||||
regs->tf_rsp = context->sc_rsp; | regs->tf_rsp = context->sc_rsp; | |||||||||
regs->tf_r8 = context->sc_r8; | regs->tf_r8 = context->sc_r8; | |||||||||
regs->tf_r9 = context->sc_r9; | regs->tf_r9 = context->sc_r9; | |||||||||
regs->tf_r10 = context->sc_r10; | regs->tf_r10 = context->sc_r10; | |||||||||
regs->tf_r11 = context->sc_r11; | regs->tf_r11 = context->sc_r11; | |||||||||
regs->tf_r12 = context->sc_r12; | regs->tf_r12 = context->sc_r12; | |||||||||
regs->tf_r13 = context->sc_r13; | regs->tf_r13 = context->sc_r13; | |||||||||
regs->tf_r14 = context->sc_r14; | regs->tf_r14 = context->sc_r14; | |||||||||
regs->tf_r15 = context->sc_r15; | regs->tf_r15 = context->sc_r15; | |||||||||
regs->tf_cs = context->sc_cs; | regs->tf_cs = context->sc_cs; | |||||||||
regs->tf_err = context->sc_err; | regs->tf_err = context->sc_err; | |||||||||
regs->tf_rflags = rflags; | regs->tf_rflags = rflags; | |||||||||
if (sf.sf_uc.uc_mcontext.sc_fpstate != NULL) { | ||||||||||
struct savefpu *svfp = (struct savefpu *)mc.mc_fpstate; | ||||||||||
kibUnsubmitted Not Done Inline Actions
kib: | ||||||||||
bzero(&mc, sizeof(mc)); | ||||||||||
mc.mc_ownedfp = _MC_FPOWNED_FPU; | ||||||||||
mc.mc_fpformat = _MC_FPFMT_XMM; | ||||||||||
Not Done Inline ActionsI mis-remembered my own code. _MX_HASFPXSTATE is wrong there, initialze mc_flags with 0. kib: I mis-remembered my own code. _MX_HASFPXSTATE is wrong there, initialze mc_flags with 0. | ||||||||||
svfp->sv_env.en_cw = sf.sf_fs.cwd; | ||||||||||
svfp->sv_env.en_sw = sf.sf_fs.swd; | ||||||||||
svfp->sv_env.en_tw = sf.sf_fs.twd; | ||||||||||
svfp->sv_env.en_opcode = sf.sf_fs.fop; | ||||||||||
svfp->sv_env.en_rip = sf.sf_fs.rip; | ||||||||||
svfp->sv_env.en_rdp = sf.sf_fs.rdp; | ||||||||||
svfp->sv_env.en_mxcsr = sf.sf_fs.mxcsr; | ||||||||||
svfp->sv_env.en_mxcsr_mask = sf.sf_fs.mxcsr_mask; | ||||||||||
/* FPU registers */ | ||||||||||
for (i = 0; i < nitems(svfp->sv_fp); ++i) | ||||||||||
bcopy(&sf.sf_fs.st[i], svfp->sv_fp[i].fp_acc.fp_bytes, | ||||||||||
Not Done Inline Actionsnitems kib: nitems | ||||||||||
sizeof(svfp->sv_fp[i].fp_acc.fp_bytes)); | ||||||||||
/* SSE registers */ | ||||||||||
for (i = 0; i < nitems(svfp->sv_xmm); ++i) | ||||||||||
bcopy(&sf.sf_fs.xmm[i], svfp->sv_xmm[i].xmm_bytes, | ||||||||||
sizeof(svfp->sv_xmm[i].xmm_bytes)); | ||||||||||
Not Done Inline Actionsnitems kib: nitems | ||||||||||
error = set_fpcontext(td, &mc, NULL, 0); | ||||||||||
if (error != 0) { | ||||||||||
uprintf("pid %d comm %s linux can't restore fpu state %d\n", | ||||||||||
p->p_pid, p->p_comm, error); | ||||||||||
return (error); | ||||||||||
} | ||||||||||
} | ||||||||||
set_pcb_flags(td->td_pcb, PCB_FULL_IRET); | set_pcb_flags(td->td_pcb, PCB_FULL_IRET); | |||||||||
return (EJUSTRETURN); | return (EJUSTRETURN); | |||||||||
} | } | |||||||||
/* | /* | |||||||||
* copied from amd64/amd64/machdep.c | * copied from amd64/amd64/machdep.c | |||||||||
* | * | |||||||||
* Send an interrupt to process. | * Send an interrupt to process. | |||||||||
*/ | */ | |||||||||
static void | static void | |||||||||
linux_rt_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) | linux_rt_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) | |||||||||
{ | { | |||||||||
struct l_rt_sigframe sf, *sfp; | struct l_rt_sigframe sf, *sfp; | |||||||||
struct proc *p; | struct proc *p; | |||||||||
struct thread *td; | struct thread *td; | |||||||||
struct sigacts *psp; | struct sigacts *psp; | |||||||||
caddr_t sp; | caddr_t sp; | |||||||||
struct trapframe *regs; | struct trapframe *regs; | |||||||||
struct savefpu *svfp; | ||||||||||
mcontext_t mc; | ||||||||||
int sig, code; | int sig, code; | |||||||||
int oonstack, issiginfo; | int oonstack, issiginfo, i; | |||||||||
td = curthread; | td = curthread; | |||||||||
p = td->td_proc; | p = td->td_proc; | |||||||||
PROC_LOCK_ASSERT(p, MA_OWNED); | PROC_LOCK_ASSERT(p, MA_OWNED); | |||||||||
sig = linux_translate_traps(ksi->ksi_signo, ksi->ksi_trapno); | sig = linux_translate_traps(ksi->ksi_signo, ksi->ksi_trapno); | |||||||||
psp = p->p_sigacts; | psp = p->p_sigacts; | |||||||||
issiginfo = SIGISMEMBER(psp->ps_siginfo, sig); | issiginfo = SIGISMEMBER(psp->ps_siginfo, sig); | |||||||||
code = ksi->ksi_code; | code = ksi->ksi_code; | |||||||||
Show All 37 Lines | linux_rt_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) | |||||||||
sf.sf_uc.uc_mcontext.sc_trapno = bsd_to_linux_trapcode(code); | sf.sf_uc.uc_mcontext.sc_trapno = bsd_to_linux_trapcode(code); | |||||||||
sf.sf_uc.uc_mcontext.sc_cr2 = (register_t)ksi->ksi_addr; | sf.sf_uc.uc_mcontext.sc_cr2 = (register_t)ksi->ksi_addr; | |||||||||
/* Allocate space for the signal handler context. */ | /* Allocate space for the signal handler context. */ | |||||||||
if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack && | if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack && | |||||||||
SIGISMEMBER(psp->ps_sigonstack, sig)) { | SIGISMEMBER(psp->ps_sigonstack, sig)) { | |||||||||
sp = (caddr_t)td->td_sigstk.ss_sp + td->td_sigstk.ss_size; | sp = (caddr_t)td->td_sigstk.ss_sp + td->td_sigstk.ss_size; | |||||||||
} else | } else | |||||||||
sp = (caddr_t)regs->tf_rsp - 128; | sp = (caddr_t)regs->tf_rsp - 128; | |||||||||
Not Done Inline ActionsI believe the ps_mtx and proc lock can be dropped after this line, there is no point of copying all the stuff under the locks. Even more, the code be re-arranged to do all accesses to lock-protected members earlier. But this is perhaps is not too important. kib: I believe the ps_mtx and proc lock can be dropped after this line, there is no point of copying… | ||||||||||
sp -= sizeof(struct l_rt_sigframe); | sp -= sizeof(struct l_rt_sigframe); | |||||||||
/* Align to 16 bytes. */ | /* Align to 16 bytes. */ | |||||||||
sfp = (struct l_rt_sigframe *)((unsigned long)sp & ~0xFul); | sfp = (struct l_rt_sigframe *)((unsigned long)sp & ~0xFul); | |||||||||
mtx_unlock(&psp->ps_mtx); | mtx_unlock(&psp->ps_mtx); | |||||||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | |||||||||
Not Done Inline Actions
kib: | ||||||||||
get_fpcontext(td, &mc, NULL, NULL); | ||||||||||
KASSERT(mc.mc_fpformat != _MC_FPFMT_NODEV, ("fpu not present")); | ||||||||||
Not Done Inline ActionsThis condition should be always true. Perhaps assert it and unindent the 'then' block. kib: This condition should be always true. Perhaps assert it and unindent the 'then' block. | ||||||||||
svfp = (struct savefpu *)mc.mc_fpstate; | ||||||||||
sf.sf_fs.cwd = svfp->sv_env.en_cw; | ||||||||||
sf.sf_fs.swd = svfp->sv_env.en_sw; | ||||||||||
sf.sf_fs.twd = svfp->sv_env.en_tw; | ||||||||||
sf.sf_fs.fop = svfp->sv_env.en_opcode; | ||||||||||
sf.sf_fs.rip = svfp->sv_env.en_rip; | ||||||||||
sf.sf_fs.rdp = svfp->sv_env.en_rdp; | ||||||||||
sf.sf_fs.mxcsr = svfp->sv_env.en_mxcsr; | ||||||||||
Not Done Inline Actionssizeof(svfp->sv_fp) / sizeof(svfp->sv_fp[0]) is better spelled as nitems(sizeof(svfp->sv_fp)) kib: `sizeof(svfp->sv_fp) / sizeof(svfp->sv_fp[0])` is better spelled as `nitems(sizeof(svfp… | ||||||||||
sf.sf_fs.mxcsr_mask = svfp->sv_env.en_mxcsr_mask; | ||||||||||
Not Done Inline ActionsCould 10 be replaced by some symbolic expression like sizeof()? Same question for 8 and 16, above and below. kib: Could 10 be replaced by some symbolic expression like sizeof()?
Same question for 8 and 16… | ||||||||||
/* FPU registers */ | ||||||||||
for (i = 0; i < nitems(svfp->sv_fp); ++i) | ||||||||||
bcopy(svfp->sv_fp[i].fp_acc.fp_bytes, &sf.sf_fs.st[i], | ||||||||||
sizeof(svfp->sv_fp[i].fp_acc.fp_bytes)); | ||||||||||
Not Done Inline ActionsSame kib: Same | ||||||||||
/* SSE registers */ | ||||||||||
for (i = 0; i < nitems(svfp->sv_xmm); ++i) | ||||||||||
bcopy(svfp->sv_xmm[i].xmm_bytes, &sf.sf_fs.xmm[i], | ||||||||||
sizeof(svfp->sv_xmm[i].xmm_bytes)); | ||||||||||
sf.sf_uc.uc_mcontext.sc_fpstate = (struct l_fpstate *)((caddr_t)sfp + | ||||||||||
offsetof(struct l_rt_sigframe, sf_fs)); | ||||||||||
/* Translate the signal. */ | /* Translate the signal. */ | |||||||||
sig = bsd_to_linux_signal(sig); | sig = bsd_to_linux_signal(sig); | |||||||||
/* Fill in POSIX parts. */ | /* Fill in POSIX parts. */ | |||||||||
siginfo_to_lsiginfo(&ksi->ksi_info, &sf.sf_si, sig); | siginfo_to_lsiginfo(&ksi->ksi_info, &sf.sf_si, sig); | |||||||||
/* Copy the sigframe out to the user's stack. */ | /* Copy the sigframe out to the user's stack. */ | |||||||||
if (copyout(&sf, sfp, sizeof(*sfp)) != 0) { | if (copyout(&sf, sfp, sizeof(*sfp)) != 0) { | |||||||||
uprintf("pid %d comm %s has trashed its stack, killing\n", | uprintf("pid %d comm %s has trashed its stack, killing\n", | |||||||||
p->p_pid, p->p_comm); | p->p_pid, p->p_comm); | |||||||||
PROC_LOCK(p); | PROC_LOCK(p); | |||||||||
sigexit(td, SIGILL); | sigexit(td, SIGILL); | |||||||||
} | } | |||||||||
fpstate_drop(td); | ||||||||||
/* Build the argument list for the signal handler. */ | /* Build the argument list for the signal handler. */ | |||||||||
regs->tf_rdi = sig; /* arg 1 in %rdi */ | regs->tf_rdi = sig; /* arg 1 in %rdi */ | |||||||||
regs->tf_rax = 0; | regs->tf_rax = 0; | |||||||||
if (issiginfo) { | if (issiginfo) { | |||||||||
regs->tf_rsi = (register_t)&sfp->sf_si; /* arg 2 in %rsi */ | regs->tf_rsi = (register_t)&sfp->sf_si; /* arg 2 in %rsi */ | |||||||||
regs->tf_rdx = (register_t)&sfp->sf_uc; /* arg 3 in %rdx */ | regs->tf_rdx = (register_t)&sfp->sf_uc; /* arg 3 in %rdx */ | |||||||||
} else { | } else { | |||||||||
regs->tf_rsi = 0; | regs->tf_rsi = 0; | |||||||||
▲ Show 20 Lines • Show All 349 Lines • Show Last 20 Lines |