Changeset View
Changeset View
Standalone View
Standalone View
sys/arm/linux/linux_sysvec.c
Context not available. | |||||
#include <vm/vm_param.h> | #include <vm/vm_param.h> | ||||
#include <machine/cpu.h> | #include <machine/cpu.h> | ||||
#include <machine/cputypes.h> | |||||
#include <machine/md_var.h> | #include <machine/md_var.h> | ||||
#include <machine/pcb.h> | #include <machine/pcb.h> | ||||
Context not available. | |||||
#include <compat/linux/linux_util.h> | #include <compat/linux/linux_util.h> | ||||
#include <compat/linux/linux_vdso.h> | #include <compat/linux/linux_vdso.h> | ||||
extern const char *linux_syscallnames[]; | |||||
#define ARM_NR_BASE 400 | |||||
MODULE_VERSION(linux, 1); | MODULE_VERSION(linux, 1); | ||||
#if BYTE_ORDER == LITTLE_ENDIAN | #if BYTE_ORDER == LITTLE_ENDIAN | ||||
Context not available. | |||||
LINUX_VDSO_SYM_INTPTR(linux_rt_sigcode); | LINUX_VDSO_SYM_INTPTR(linux_rt_sigcode); | ||||
LINUX_VDSO_SYM_INTPTR(linux_vsyscall); | LINUX_VDSO_SYM_INTPTR(linux_vsyscall); | ||||
/* | |||||
* If FreeBSD & Linux have a difference of opinion about what a trap | |||||
* means, deal with it here. | |||||
* | |||||
* MPSAFE | |||||
*/ | |||||
static int | static int | ||||
translate_traps(int signal, int trap_code) | translate_traps(int signal, int trap_code) | ||||
{ | { | ||||
if (signal != SIGBUS) | |||||
return (signal); | return (signal); | ||||
switch (trap_code) { | |||||
case T_PROTFLT: | |||||
case T_TSSFLT: | |||||
case T_DOUBLEFLT: | |||||
case T_PAGEFLT: | |||||
return (SIGSEGV); | |||||
default: | |||||
return (signal); | |||||
} | |||||
} | } | ||||
static int | static int | ||||
Context not available. | |||||
Elf32_Addr *uplatform; | Elf32_Addr *uplatform; | ||||
struct ps_strings *arginfo; | struct ps_strings *arginfo; | ||||
register_t *pos; | register_t *pos; | ||||
int issetugid; | |||||
KASSERT(curthread->td_proc == imgp->proc, | KASSERT(curthread->td_proc == imgp->proc, | ||||
("unsafe elf_linux_fixup(), should be curproc")); | ("unsafe elf_linux_fixup(), should be curproc")); | ||||
p = imgp->proc; | p = imgp->proc; | ||||
issetugid = imgp->proc->p_flag & P_SUGID ? 1 : 0; | |||||
arginfo = (struct ps_strings *)p->p_sysent->sv_psstrings; | arginfo = (struct ps_strings *)p->p_sysent->sv_psstrings; | ||||
uplatform = (Elf32_Addr *)((caddr_t)arginfo - linux_szplatform); | uplatform = (Elf32_Addr *)((caddr_t)arginfo - linux_szplatform); | ||||
args = (Elf32_Auxargs *)imgp->auxargs; | args = (Elf32_Auxargs *)imgp->auxargs; | ||||
Context not available. | |||||
AUXARGS_ENTRY(pos, LINUX_AT_SYSINFO_EHDR, | AUXARGS_ENTRY(pos, LINUX_AT_SYSINFO_EHDR, | ||||
imgp->proc->p_sysent->sv_shared_page_base); | imgp->proc->p_sysent->sv_shared_page_base); | ||||
AUXARGS_ENTRY(pos, LINUX_AT_SYSINFO, linux_vsyscall); | AUXARGS_ENTRY(pos, LINUX_AT_SYSINFO, linux_vsyscall); | ||||
AUXARGS_ENTRY(pos, LINUX_AT_HWCAP, cpu_feature); | |||||
/* | /* | ||||
* Do not export AT_CLKTCK when emulating Linux kernel prior to 2.4.0, | * Do not export AT_CLKTCK when emulating Linux kernel prior to 2.4.0, | ||||
Context not available. | |||||
AUXARGS_ENTRY(pos, AT_FLAGS, args->flags); | AUXARGS_ENTRY(pos, AT_FLAGS, args->flags); | ||||
AUXARGS_ENTRY(pos, AT_ENTRY, args->entry); | AUXARGS_ENTRY(pos, AT_ENTRY, args->entry); | ||||
AUXARGS_ENTRY(pos, AT_BASE, args->base); | AUXARGS_ENTRY(pos, AT_BASE, args->base); | ||||
AUXARGS_ENTRY(pos, LINUX_AT_SECURE, issetugid); | AUXARGS_ENTRY(pos, LINUX_AT_SECURE, 0); | ||||
AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_ucred->cr_ruid); | AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_ucred->cr_ruid); | ||||
AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid); | AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid); | ||||
AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_ucred->cr_rgid); | AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_ucred->cr_rgid); | ||||
Context not available. | |||||
psp = p->p_sigacts; | psp = p->p_sigacts; | ||||
mtx_assert(&psp->ps_mtx, MA_OWNED); | mtx_assert(&psp->ps_mtx, MA_OWNED); | ||||
regs = td->td_frame; | regs = td->td_frame; | ||||
oonstack = sigonstack(regs->tf_esp); | oonstack = sigonstack(regs->tf_r13); | ||||
#ifdef DEBUG | #ifdef DEBUG | ||||
if (ldebug(rt_sendsig)) | if (ldebug(rt_sendsig)) | ||||
Context not available. | |||||
fp = (struct l_rt_sigframe *)((uintptr_t)td->td_sigstk.ss_sp + | fp = (struct l_rt_sigframe *)((uintptr_t)td->td_sigstk.ss_sp + | ||||
td->td_sigstk.ss_size - sizeof(struct l_rt_sigframe)); | td->td_sigstk.ss_size - sizeof(struct l_rt_sigframe)); | ||||
} else | } else | ||||
fp = (struct l_rt_sigframe *)regs->tf_esp - 1; | fp = (struct l_rt_sigframe *)regs->tf_r13 - 1; | ||||
mtx_unlock(&psp->ps_mtx); | mtx_unlock(&psp->ps_mtx); | ||||
/* | /* | ||||
Context not available. | |||||
bzero(&frame, sizeof(frame)); | bzero(&frame, sizeof(frame)); | ||||
frame.sf_handler = catcher; | frame.sf_handler = (l_handler_t)catcher; | ||||
frame.sf_sig = sig; | frame.sf_sig = sig; | ||||
frame.sf_siginfo = &fp->sf_si; | frame.sf_siginfo = &fp->sf_si; | ||||
frame.sf_ucontext = &fp->sf_sc; | frame.sf_ucontext = &fp->sf_sc; | ||||
Context not available. | |||||
* Build the signal context to be used by sigreturn. | * Build the signal context to be used by sigreturn. | ||||
*/ | */ | ||||
frame.sf_sc.uc_flags = 0; /* XXX ??? */ | frame.sf_sc.uc_flags = 0; /* XXX ??? */ | ||||
frame.sf_sc.uc_link = NULL; /* XXX ??? */ | frame.sf_sc.uc_link = (l_uintptr_t)NULL; /* XXX ??? */ | ||||
frame.sf_sc.uc_stack.ss_sp = td->td_sigstk.ss_sp; | frame.sf_sc.uc_stack.ss_sp = td->td_sigstk.ss_sp; | ||||
frame.sf_sc.uc_stack.ss_size = td->td_sigstk.ss_size; | frame.sf_sc.uc_stack.ss_size = td->td_sigstk.ss_size; | ||||
Context not available. | |||||
bsd_to_linux_sigset(mask, &frame.sf_sc.uc_sigmask); | bsd_to_linux_sigset(mask, &frame.sf_sc.uc_sigmask); | ||||
frame.sf_sc.uc_mcontext.sc_mask = frame.sf_sc.uc_sigmask.__mask; | frame.sf_sc.uc_mcontext.oldmask = frame.sf_sc.uc_sigmask.__mask; | ||||
frame.sf_sc.uc_mcontext.sc_gs = rgs(); | frame.sf_sc.uc_mcontext.fault_address = (register_t)ksi->ksi_addr; | ||||
frame.sf_sc.uc_mcontext.sc_fs = regs->tf_fs; | frame.sf_sc.uc_mcontext.arm_r0 = regs->tf_r0; | ||||
frame.sf_sc.uc_mcontext.sc_es = regs->tf_es; | frame.sf_sc.uc_mcontext.arm_r1 = regs->tf_r1; | ||||
frame.sf_sc.uc_mcontext.sc_ds = regs->tf_ds; | frame.sf_sc.uc_mcontext.arm_r2 = regs->tf_r2; | ||||
frame.sf_sc.uc_mcontext.sc_edi = regs->tf_edi; | frame.sf_sc.uc_mcontext.arm_r3 = regs->tf_r3; | ||||
frame.sf_sc.uc_mcontext.sc_esi = regs->tf_esi; | frame.sf_sc.uc_mcontext.arm_r4 = regs->tf_r4; | ||||
frame.sf_sc.uc_mcontext.sc_ebp = regs->tf_ebp; | frame.sf_sc.uc_mcontext.arm_r5 = regs->tf_r5; | ||||
frame.sf_sc.uc_mcontext.sc_ebx = regs->tf_ebx; | frame.sf_sc.uc_mcontext.arm_r6 = regs->tf_r6; | ||||
frame.sf_sc.uc_mcontext.sc_esp = regs->tf_esp; | frame.sf_sc.uc_mcontext.arm_r7 = regs->tf_r7; | ||||
frame.sf_sc.uc_mcontext.sc_edx = regs->tf_edx; | frame.sf_sc.uc_mcontext.arm_r8 = regs->tf_r8; | ||||
frame.sf_sc.uc_mcontext.sc_ecx = regs->tf_ecx; | frame.sf_sc.uc_mcontext.arm_r9 = regs->tf_r9; | ||||
frame.sf_sc.uc_mcontext.sc_eax = regs->tf_eax; | frame.sf_sc.uc_mcontext.arm_r10 = regs->tf_r10; | ||||
frame.sf_sc.uc_mcontext.sc_eip = regs->tf_eip; | frame.sf_sc.uc_mcontext.arm_fp = regs->tf_r11; | ||||
frame.sf_sc.uc_mcontext.sc_cs = regs->tf_cs; | frame.sf_sc.uc_mcontext.arm_ip = regs->tf_r12; | ||||
frame.sf_sc.uc_mcontext.sc_eflags = regs->tf_eflags; | frame.sf_sc.uc_mcontext.arm_sp = regs->tf_r13; | ||||
frame.sf_sc.uc_mcontext.sc_esp_at_signal = regs->tf_esp; | frame.sf_sc.uc_mcontext.arm_lr = regs->tf_r14; | ||||
frame.sf_sc.uc_mcontext.sc_ss = regs->tf_ss; | frame.sf_sc.uc_mcontext.arm_pc = regs->tf_r15; | ||||
frame.sf_sc.uc_mcontext.sc_err = regs->tf_err; | frame.sf_sc.uc_mcontext.arm_cpsr = regs->tf_spsr; | ||||
frame.sf_sc.uc_mcontext.sc_cr2 = (register_t)ksi->ksi_addr; | frame.sf_sc.uc_mcontext.error_code = 0; | ||||
frame.sf_sc.uc_mcontext.sc_trapno = bsd_to_linux_trapcode(code); | frame.sf_sc.uc_mcontext.trap_no = bsd_to_linux_trapcode(code); | ||||
#ifdef DEBUG | #ifdef DEBUG | ||||
if (ldebug(rt_sendsig)) | if (ldebug(rt_sendsig)) | ||||
printf(LMSG("rt_sendsig flags: 0x%x, sp: %p, ss: 0x%x, mask: 0x%x"), | printf(LMSG("rt_sendsig flags: 0x%x, sp: %p, ss: 0x%x, mask: 0x%x"), | ||||
frame.sf_sc.uc_stack.ss_flags, td->td_sigstk.ss_sp, | frame.sf_sc.uc_stack.ss_flags, td->td_sigstk.ss_sp, | ||||
td->td_sigstk.ss_size, frame.sf_sc.uc_mcontext.sc_mask); | td->td_sigstk.ss_size, (unsigned int)frame.sf_sc.uc_mcontext.arm_cpsr); | ||||
#endif | #endif | ||||
if (copyout(&frame, fp, sizeof(frame)) != 0) { | if (copyout(&frame, fp, sizeof(frame)) != 0) { | ||||
Context not available. | |||||
/* | /* | ||||
* Build context to run handler in. | * Build context to run handler in. | ||||
*/ | */ | ||||
regs->tf_esp = (int)fp; | regs->tf_r0 = (int)sig; | ||||
regs->tf_eip = linux_rt_sigcode; | regs->tf_r1 = (int)catcher; | ||||
regs->tf_eflags &= ~(PSL_T | PSL_VM | PSL_D); | regs->tf_r13 = (int)fp; | ||||
regs->tf_cs = _ucodesel; | regs->tf_r15 = linux_rt_sigcode; | ||||
regs->tf_ds = _udatasel; | |||||
regs->tf_es = _udatasel; | |||||
regs->tf_fs = _udatasel; | |||||
regs->tf_ss = _udatasel; | |||||
PROC_LOCK(p); | PROC_LOCK(p); | ||||
mtx_lock(&psp->ps_mtx); | mtx_lock(&psp->ps_mtx); | ||||
} | } | ||||
/* | /* | ||||
* Send an interrupt to process. | * Send an interrupt to process. | ||||
* | * | ||||
Context not available. | |||||
return; | return; | ||||
} | } | ||||
regs = td->td_frame; | regs = td->td_frame; | ||||
oonstack = sigonstack(regs->tf_esp); | oonstack = sigonstack(regs->tf_r13); | ||||
#ifdef DEBUG | #ifdef DEBUG | ||||
if (ldebug(sendsig)) | if (ldebug(sendsig)) | ||||
Context not available. | |||||
fp = (struct l_sigframe *)((uintptr_t)td->td_sigstk.ss_sp + | fp = (struct l_sigframe *)((uintptr_t)td->td_sigstk.ss_sp + | ||||
td->td_sigstk.ss_size - sizeof(struct l_sigframe)); | td->td_sigstk.ss_size - sizeof(struct l_sigframe)); | ||||
} else | } else | ||||
fp = (struct l_sigframe *)regs->tf_esp - 1; | fp = (struct l_sigframe *)regs->tf_r13 - 1; | ||||
mtx_unlock(&psp->ps_mtx); | mtx_unlock(&psp->ps_mtx); | ||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
Context not available. | |||||
bzero(&frame, sizeof(frame)); | bzero(&frame, sizeof(frame)); | ||||
frame.sf_handler = catcher; | frame.sf_handler = (l_handler_t)catcher; | ||||
frame.sf_sig = sig; | frame.sf_sig = sig; | ||||
bsd_to_linux_sigset(mask, &lmask); | bsd_to_linux_sigset(mask, &lmask); | ||||
Context not available. | |||||
/* | /* | ||||
* Build the signal context to be used by sigreturn. | * Build the signal context to be used by sigreturn. | ||||
*/ | */ | ||||
frame.sf_sc.sc_mask = lmask.__mask; | frame.sf_sc.oldmask = lmask.__mask; | ||||
frame.sf_sc.sc_gs = rgs(); | frame.sf_sc.fault_address = (register_t)ksi->ksi_addr; | ||||
frame.sf_sc.sc_fs = regs->tf_fs; | frame.sf_sc.arm_r0 = regs->tf_r0; | ||||
frame.sf_sc.sc_es = regs->tf_es; | frame.sf_sc.arm_r1 = regs->tf_r1; | ||||
frame.sf_sc.sc_ds = regs->tf_ds; | frame.sf_sc.arm_r2 = regs->tf_r2; | ||||
frame.sf_sc.sc_edi = regs->tf_edi; | frame.sf_sc.arm_r3 = regs->tf_r3; | ||||
frame.sf_sc.sc_esi = regs->tf_esi; | frame.sf_sc.arm_r4 = regs->tf_r4; | ||||
frame.sf_sc.sc_ebp = regs->tf_ebp; | frame.sf_sc.arm_r5 = regs->tf_r5; | ||||
frame.sf_sc.sc_ebx = regs->tf_ebx; | frame.sf_sc.arm_r6 = regs->tf_r6; | ||||
frame.sf_sc.sc_esp = regs->tf_esp; | frame.sf_sc.arm_r7 = regs->tf_r7; | ||||
frame.sf_sc.sc_edx = regs->tf_edx; | frame.sf_sc.arm_r8 = regs->tf_r8; | ||||
frame.sf_sc.sc_ecx = regs->tf_ecx; | frame.sf_sc.arm_r9 = regs->tf_r9; | ||||
frame.sf_sc.sc_eax = regs->tf_eax; | frame.sf_sc.arm_r10 = regs->tf_r10; | ||||
frame.sf_sc.sc_eip = regs->tf_eip; | frame.sf_sc.arm_fp = regs->tf_r11; | ||||
frame.sf_sc.sc_cs = regs->tf_cs; | frame.sf_sc.arm_ip = regs->tf_r12; | ||||
frame.sf_sc.sc_eflags = regs->tf_eflags; | frame.sf_sc.arm_sp = regs->tf_r13; | ||||
frame.sf_sc.sc_esp_at_signal = regs->tf_esp; | frame.sf_sc.arm_lr = regs->tf_r14; | ||||
frame.sf_sc.sc_ss = regs->tf_ss; | frame.sf_sc.arm_pc = regs->tf_r15; | ||||
frame.sf_sc.sc_err = regs->tf_err; | frame.sf_sc.arm_cpsr = regs->tf_spsr; | ||||
frame.sf_sc.sc_cr2 = (register_t)ksi->ksi_addr; | frame.sf_sc.error_code = 0; | ||||
frame.sf_sc.sc_trapno = bsd_to_linux_trapcode(ksi->ksi_trapno); | frame.sf_sc.trap_no = bsd_to_linux_trapcode(code); | ||||
frame.sf_extramask[0] = lmask.__mask; | frame.sf_extramask[0] = lmask.__mask; | ||||
Context not available. | |||||
/* | /* | ||||
* Build context to run handler in. | * Build context to run handler in. | ||||
*/ | */ | ||||
regs->tf_esp = (int)fp; | regs->tf_r0 = (int)sig; | ||||
regs->tf_eip = linux_sigcode; | regs->tf_r1 = (int)catcher; | ||||
regs->tf_eflags &= ~(PSL_T | PSL_VM | PSL_D); | regs->tf_r13 = (int)fp; | ||||
regs->tf_cs = _ucodesel; | regs->tf_r15 = linux_sigcode; | ||||
regs->tf_ds = _udatasel; | |||||
regs->tf_es = _udatasel; | |||||
regs->tf_fs = _udatasel; | |||||
regs->tf_ss = _udatasel; | |||||
PROC_LOCK(p); | PROC_LOCK(p); | ||||
mtx_lock(&psp->ps_mtx); | mtx_lock(&psp->ps_mtx); | ||||
} | } | ||||
Context not available. | |||||
struct trapframe *regs; | struct trapframe *regs; | ||||
l_sigset_t lmask; | l_sigset_t lmask; | ||||
sigset_t bmask; | sigset_t bmask; | ||||
int eflags; | |||||
ksiginfo_t ksi; | |||||
regs = td->td_frame; | regs = td->td_frame; | ||||
Context not available. | |||||
if (copyin(args->sfp, &frame, sizeof(frame)) != 0) | if (copyin(args->sfp, &frame, sizeof(frame)) != 0) | ||||
return (EFAULT); | return (EFAULT); | ||||
/* | lmask.__mask = frame.sf_sc.oldmask; | ||||
* Check for security violations. | |||||
*/ | |||||
#define EFLAGS_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0) | |||||
eflags = frame.sf_sc.sc_eflags; | |||||
if (!EFLAGS_SECURE(eflags, regs->tf_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. | |||||
*/ | |||||
#define CS_SECURE(cs) (ISPL(cs) == SEL_UPL) | |||||
if (!CS_SECURE(frame.sf_sc.sc_cs)) { | |||||
ksiginfo_init_trap(&ksi); | |||||
ksi.ksi_signo = SIGBUS; | |||||
ksi.ksi_code = BUS_OBJERR; | |||||
ksi.ksi_trapno = T_PROTFLT; | |||||
ksi.ksi_addr = (void *)regs->tf_eip; | |||||
trapsignal(td, &ksi); | |||||
return (EINVAL); | |||||
} | |||||
lmask.__mask = frame.sf_sc.sc_mask; | |||||
linux_to_bsd_sigset(&lmask, &bmask); | linux_to_bsd_sigset(&lmask, &bmask); | ||||
kern_sigprocmask(td, SIG_SETMASK, &bmask, NULL, 0); | kern_sigprocmask(td, SIG_SETMASK, &bmask, NULL, 0); | ||||
/* | /* | ||||
* Restore signal context. | * Restore signal context. | ||||
*/ | */ | ||||
/* %gs was restored by the trampoline. */ | regs->tf_r0 = frame.sf_sc.arm_r0 ; | ||||
regs->tf_fs = frame.sf_sc.sc_fs; | regs->tf_r1 = frame.sf_sc.arm_r1 ; | ||||
regs->tf_es = frame.sf_sc.sc_es; | regs->tf_r2 = frame.sf_sc.arm_r2 ; | ||||
regs->tf_ds = frame.sf_sc.sc_ds; | regs->tf_r3 = frame.sf_sc.arm_r3 ; | ||||
regs->tf_edi = frame.sf_sc.sc_edi; | regs->tf_r4 = frame.sf_sc.arm_r4 ; | ||||
regs->tf_esi = frame.sf_sc.sc_esi; | regs->tf_r5 = frame.sf_sc.arm_r5 ; | ||||
regs->tf_ebp = frame.sf_sc.sc_ebp; | regs->tf_r6 = frame.sf_sc.arm_r6 ; | ||||
regs->tf_ebx = frame.sf_sc.sc_ebx; | regs->tf_r7 = frame.sf_sc.arm_r7 ; | ||||
regs->tf_edx = frame.sf_sc.sc_edx; | regs->tf_r8 = frame.sf_sc.arm_r8 ; | ||||
regs->tf_ecx = frame.sf_sc.sc_ecx; | regs->tf_r9 = frame.sf_sc.arm_r9 ; | ||||
regs->tf_eax = frame.sf_sc.sc_eax; | regs->tf_r10 = frame.sf_sc.arm_r10 ; | ||||
regs->tf_eip = frame.sf_sc.sc_eip; | regs->tf_r11 = frame.sf_sc.arm_fp ; | ||||
regs->tf_cs = frame.sf_sc.sc_cs; | regs->tf_r12 = frame.sf_sc.arm_ip ; | ||||
regs->tf_eflags = eflags; | regs->tf_r13 = frame.sf_sc.arm_sp ; | ||||
regs->tf_esp = frame.sf_sc.sc_esp_at_signal; | regs->tf_r14 = frame.sf_sc.arm_lr ; | ||||
regs->tf_ss = frame.sf_sc.sc_ss; | regs->tf_r15 = frame.sf_sc.arm_pc ; | ||||
regs->tf_spsr = frame.sf_sc.arm_cpsr; | |||||
return (EJUSTRETURN); | return (EJUSTRETURN); | ||||
} | } | ||||
Context not available. | |||||
l_stack_t *lss; | l_stack_t *lss; | ||||
stack_t ss; | stack_t ss; | ||||
struct trapframe *regs; | struct trapframe *regs; | ||||
int eflags; | |||||
ksiginfo_t ksi; | |||||
regs = td->td_frame; | regs = td->td_frame; | ||||
Context not available. | |||||
context = &uc.uc_mcontext; | context = &uc.uc_mcontext; | ||||
/* | |||||
* Check for security violations. | |||||
*/ | |||||
#define EFLAGS_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0) | |||||
eflags = context->sc_eflags; | |||||
if (!EFLAGS_SECURE(eflags, regs->tf_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. | |||||
*/ | |||||
#define CS_SECURE(cs) (ISPL(cs) == SEL_UPL) | |||||
if (!CS_SECURE(context->sc_cs)) { | |||||
ksiginfo_init_trap(&ksi); | |||||
ksi.ksi_signo = SIGBUS; | |||||
ksi.ksi_code = BUS_OBJERR; | |||||
ksi.ksi_trapno = T_PROTFLT; | |||||
ksi.ksi_addr = (void *)regs->tf_eip; | |||||
trapsignal(td, &ksi); | |||||
return (EINVAL); | |||||
} | |||||
linux_to_bsd_sigset(&uc.uc_sigmask, &bmask); | linux_to_bsd_sigset(&uc.uc_sigmask, &bmask); | ||||
kern_sigprocmask(td, SIG_SETMASK, &bmask, NULL, 0); | kern_sigprocmask(td, SIG_SETMASK, &bmask, NULL, 0); | ||||
Context not available. | |||||
* Restore signal context | * Restore signal context | ||||
*/ | */ | ||||
/* %gs was restored by the trampoline. */ | /* %gs was restored by the trampoline. */ | ||||
regs->tf_fs = context->sc_fs; | regs->tf_r0 = context->arm_r0 ; | ||||
regs->tf_es = context->sc_es; | regs->tf_r1 = context->arm_r1 ; | ||||
regs->tf_ds = context->sc_ds; | regs->tf_r2 = context->arm_r2 ; | ||||
regs->tf_edi = context->sc_edi; | regs->tf_r3 = context->arm_r3 ; | ||||
regs->tf_esi = context->sc_esi; | regs->tf_r4 = context->arm_r4 ; | ||||
regs->tf_ebp = context->sc_ebp; | regs->tf_r5 = context->arm_r5 ; | ||||
regs->tf_ebx = context->sc_ebx; | regs->tf_r6 = context->arm_r6 ; | ||||
regs->tf_edx = context->sc_edx; | regs->tf_r7 = context->arm_r7 ; | ||||
regs->tf_ecx = context->sc_ecx; | regs->tf_r8 = context->arm_r8 ; | ||||
regs->tf_eax = context->sc_eax; | regs->tf_r9 = context->arm_r9 ; | ||||
regs->tf_eip = context->sc_eip; | regs->tf_r10 = context->arm_r10 ; | ||||
regs->tf_cs = context->sc_cs; | regs->tf_r11 = context->arm_fp ; | ||||
regs->tf_eflags = eflags; | regs->tf_r12 = context->arm_ip ; | ||||
regs->tf_esp = context->sc_esp_at_signal; | regs->tf_r13 = context->arm_sp ; | ||||
regs->tf_ss = context->sc_ss; | regs->tf_r14 = context->arm_lr ; | ||||
regs->tf_r15 = context->arm_pc ; | |||||
regs->tf_spsr = context->arm_cpsr; | |||||
/* | /* | ||||
* call sigaltstack & ignore results.. | * call sigaltstack & ignore results.. | ||||
*/ | */ | ||||
lss = &uc.uc_stack; | lss = &uc.uc_stack; | ||||
ss.ss_sp = lss->ss_sp; | ss.ss_sp = (char*)lss->ss_sp; | ||||
ss.ss_size = lss->ss_size; | ss.ss_size = lss->ss_size; | ||||
ss.ss_flags = linux_to_bsd_sigaltstack(lss->ss_flags); | ss.ss_flags = linux_to_bsd_sigaltstack(lss->ss_flags); | ||||
#ifdef DEBUG | #ifdef DEBUG | ||||
if (ldebug(rt_sigreturn)) | if (ldebug(rt_sigreturn)) | ||||
printf(LMSG("rt_sigret flags: 0x%x, sp: %p, ss: 0x%x, mask: 0x%x"), | printf(LMSG("rt_sigret flags: 0x%x, sp: %p, ss: 0x%x, mask: 0x%x"), | ||||
ss.ss_flags, ss.ss_sp, ss.ss_size, context->sc_mask); | ss.ss_flags, ss.ss_sp, ss.ss_size, (unsigned int)context->arm_cpsr); | ||||
#endif | #endif | ||||
(void)kern_sigaltstack(td, &ss, NULL); | (void)kern_sigaltstack(td, &ss, NULL); | ||||
Context not available. | |||||
p = td->td_proc; | p = td->td_proc; | ||||
frame = td->td_frame; | frame = td->td_frame; | ||||
sa->code = frame->tf_eax; | sa->code = frame->tf_r7; | ||||
sa->args[0] = frame->tf_ebx; | sa->args[0] = frame->tf_r0; | ||||
sa->args[1] = frame->tf_ecx; | sa->args[1] = frame->tf_r1; | ||||
sa->args[2] = frame->tf_edx; | sa->args[2] = frame->tf_r2; | ||||
sa->args[3] = frame->tf_esi; | sa->args[3] = frame->tf_r3; | ||||
sa->args[4] = frame->tf_edi; | sa->args[4] = frame->tf_r4; | ||||
sa->args[5] = frame->tf_ebp; /* Unconfirmed */ | sa->args[5] = frame->tf_r5; /* Unconfirmed */ | ||||
/* | |||||
* ARM syscall | |||||
* First ARM syscall in syscalls.master is @ ARM_NR_BASE | |||||
*/ | |||||
if ((sa->code >> 16) == 0x0f) | |||||
{ | |||||
sa->code &= 0xffff; | |||||
sa->code += ARM_NR_BASE; | |||||
} | |||||
if (sa->code >= p->p_sysent->sv_size) | if (sa->code >= p->p_sysent->sv_size) | ||||
/* nosys */ | /* nosys */ | ||||
Context not available. | |||||
sa->narg = sa->callp->sy_narg; | sa->narg = sa->callp->sy_narg; | ||||
td->td_retval[0] = 0; | td->td_retval[0] = 0; | ||||
td->td_retval[1] = frame->tf_edx; | td->td_retval[1] = frame->tf_r1; | ||||
return (0); | return (0); | ||||
} | } | ||||
Context not available. | |||||
static void | static void | ||||
exec_linux_setregs(struct thread *td, struct image_params *imgp, u_long stack) | exec_linux_setregs(struct thread *td, struct image_params *imgp, u_long stack) | ||||
{ | { | ||||
struct pcb *pcb = td->td_pcb; | |||||
exec_setregs(td, imgp, stack); | exec_setregs(td, imgp, stack); | ||||
/* Linux sets %gs to 0, we default to _udatasel */ | |||||
pcb->pcb_gs = 0; | |||||
load_gs(0); | |||||
pcb->pcb_initial_npxcw = __LINUX_NPXCW__; | |||||
} | } | ||||
static void | static void | ||||
linux_get_machine(const char **dst) | linux_get_machine(const char **dst) | ||||
{ | { | ||||
switch (cpu_class) { | *dst = "arm"; | ||||
case CPUCLASS_686: | |||||
*dst = "i686"; | |||||
break; | |||||
case CPUCLASS_586: | |||||
*dst = "i586"; | |||||
break; | |||||
case CPUCLASS_486: | |||||
*dst = "i486"; | |||||
break; | |||||
default: | |||||
*dst = "i386"; | |||||
} | |||||
} | } | ||||
struct sysentvec linux_sysvec = { | struct sysentvec linux_sysvec = { | ||||
Context not available. | |||||
.sv_flags = SV_ABI_LINUX | SV_AOUT | SV_IA32 | SV_ILP32, | .sv_flags = SV_ABI_LINUX | SV_AOUT | SV_IA32 | SV_ILP32, | ||||
.sv_set_syscall_retval = cpu_set_syscall_retval, | .sv_set_syscall_retval = cpu_set_syscall_retval, | ||||
.sv_fetch_syscall_args = linux_fetch_syscall_args, | .sv_fetch_syscall_args = linux_fetch_syscall_args, | ||||
.sv_syscallnames = NULL, | .sv_syscallnames = linux_syscallnames, | ||||
.sv_shared_page_base = LINUX_SHAREDPAGE, | .sv_shared_page_base = LINUX_SHAREDPAGE, | ||||
.sv_shared_page_len = PAGE_SIZE, | .sv_shared_page_len = PAGE_SIZE, | ||||
.sv_schedtail = linux_schedtail, | .sv_schedtail = linux_schedtail, | ||||
Context not available. | |||||
.sv_flags = SV_ABI_LINUX | SV_IA32 | SV_ILP32 | SV_SHP, | .sv_flags = SV_ABI_LINUX | SV_IA32 | SV_ILP32 | SV_SHP, | ||||
.sv_set_syscall_retval = cpu_set_syscall_retval, | .sv_set_syscall_retval = cpu_set_syscall_retval, | ||||
.sv_fetch_syscall_args = linux_fetch_syscall_args, | .sv_fetch_syscall_args = linux_fetch_syscall_args, | ||||
.sv_syscallnames = NULL, | .sv_syscallnames = linux_syscallnames, | ||||
.sv_shared_page_base = LINUX_SHAREDPAGE, | .sv_shared_page_base = LINUX_SHAREDPAGE, | ||||
.sv_shared_page_len = PAGE_SIZE, | .sv_shared_page_len = PAGE_SIZE, | ||||
.sv_schedtail = linux_schedtail, | .sv_schedtail = linux_schedtail, | ||||
Context not available. | |||||
static Elf32_Brandinfo linux_brand = { | static Elf32_Brandinfo linux_brand = { | ||||
.brand = ELFOSABI_LINUX, | .brand = ELFOSABI_LINUX, | ||||
.machine = EM_386, | .machine = EM_ARM, | ||||
.compat_3_brand = "Linux", | .compat_3_brand = "Linux", | ||||
.emul_path = "/compat/linux", | .emul_path = "/compat/linux", | ||||
.interp_path = "/lib/ld-linux.so.1", | .interp_path = "/lib/ld-linux.so.1", | ||||
Context not available. | |||||
static Elf32_Brandinfo linux_glibc2brand = { | static Elf32_Brandinfo linux_glibc2brand = { | ||||
.brand = ELFOSABI_LINUX, | .brand = ELFOSABI_LINUX, | ||||
.machine = EM_386, | .machine = EM_ARM, | ||||
.compat_3_brand = "Linux", | .compat_3_brand = "Linux", | ||||
.emul_path = "/compat/linux", | .emul_path = "/compat/linux", | ||||
.interp_path = "/lib/ld-linux.so.2", | .interp_path = "/lib/ld-linux.so.2", | ||||
Context not available. |