Index: sys/arm/linux/linux_sysvec.c =================================================================== --- sys/arm/linux/linux_sysvec.c +++ sys/arm/linux/linux_sysvec.c @@ -59,7 +59,6 @@ #include #include -#include #include #include @@ -74,6 +73,10 @@ #include #include +extern const char *linux_syscallnames[]; + +#define ARM_NR_BASE 400 + MODULE_VERSION(linux, 1); #if BYTE_ORDER == LITTLE_ENDIAN @@ -192,26 +195,11 @@ LINUX_VDSO_SYM_INTPTR(linux_rt_sigcode); 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 translate_traps(int signal, int trap_code) { - if (signal != SIGBUS) - return (signal); - switch (trap_code) { - case T_PROTFLT: - case T_TSSFLT: - case T_DOUBLEFLT: - case T_PAGEFLT: - return (SIGSEGV); - default: - return (signal); - } + + return (signal); } static int @@ -238,13 +226,11 @@ Elf32_Addr *uplatform; struct ps_strings *arginfo; register_t *pos; - int issetugid; KASSERT(curthread->td_proc == imgp->proc, ("unsafe elf_linux_fixup(), should be curproc")); p = imgp->proc; - issetugid = imgp->proc->p_flag & P_SUGID ? 1 : 0; arginfo = (struct ps_strings *)p->p_sysent->sv_psstrings; uplatform = (Elf32_Addr *)((caddr_t)arginfo - linux_szplatform); args = (Elf32_Auxargs *)imgp->auxargs; @@ -253,7 +239,6 @@ AUXARGS_ENTRY(pos, LINUX_AT_SYSINFO_EHDR, imgp->proc->p_sysent->sv_shared_page_base); 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, @@ -272,7 +257,7 @@ AUXARGS_ENTRY(pos, AT_FLAGS, args->flags); AUXARGS_ENTRY(pos, AT_ENTRY, args->entry); 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_EUID, imgp->proc->p_ucred->cr_svuid); AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_ucred->cr_rgid); @@ -439,7 +424,7 @@ psp = p->p_sigacts; mtx_assert(&psp->ps_mtx, MA_OWNED); regs = td->td_frame; - oonstack = sigonstack(regs->tf_esp); + oonstack = sigonstack(regs->tf_r13); #ifdef DEBUG if (ldebug(rt_sendsig)) @@ -454,7 +439,7 @@ fp = (struct l_rt_sigframe *)((uintptr_t)td->td_sigstk.ss_sp + td->td_sigstk.ss_size - sizeof(struct l_rt_sigframe)); } else - fp = (struct l_rt_sigframe *)regs->tf_esp - 1; + fp = (struct l_rt_sigframe *)regs->tf_r13 - 1; mtx_unlock(&psp->ps_mtx); /* @@ -464,7 +449,7 @@ bzero(&frame, sizeof(frame)); - frame.sf_handler = catcher; + frame.sf_handler = (l_handler_t)catcher; frame.sf_sig = sig; frame.sf_siginfo = &fp->sf_si; frame.sf_ucontext = &fp->sf_sc; @@ -476,7 +461,7 @@ * Build the signal context to be used by sigreturn. */ 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_size = td->td_sigstk.ss_size; @@ -486,33 +471,33 @@ 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.sc_gs = rgs(); - frame.sf_sc.uc_mcontext.sc_fs = regs->tf_fs; - frame.sf_sc.uc_mcontext.sc_es = regs->tf_es; - frame.sf_sc.uc_mcontext.sc_ds = regs->tf_ds; - frame.sf_sc.uc_mcontext.sc_edi = regs->tf_edi; - frame.sf_sc.uc_mcontext.sc_esi = regs->tf_esi; - frame.sf_sc.uc_mcontext.sc_ebp = regs->tf_ebp; - frame.sf_sc.uc_mcontext.sc_ebx = regs->tf_ebx; - frame.sf_sc.uc_mcontext.sc_esp = regs->tf_esp; - frame.sf_sc.uc_mcontext.sc_edx = regs->tf_edx; - frame.sf_sc.uc_mcontext.sc_ecx = regs->tf_ecx; - frame.sf_sc.uc_mcontext.sc_eax = regs->tf_eax; - frame.sf_sc.uc_mcontext.sc_eip = regs->tf_eip; - frame.sf_sc.uc_mcontext.sc_cs = regs->tf_cs; - frame.sf_sc.uc_mcontext.sc_eflags = regs->tf_eflags; - frame.sf_sc.uc_mcontext.sc_esp_at_signal = regs->tf_esp; - frame.sf_sc.uc_mcontext.sc_ss = regs->tf_ss; - frame.sf_sc.uc_mcontext.sc_err = regs->tf_err; - frame.sf_sc.uc_mcontext.sc_cr2 = (register_t)ksi->ksi_addr; - frame.sf_sc.uc_mcontext.sc_trapno = bsd_to_linux_trapcode(code); + frame.sf_sc.uc_mcontext.oldmask = frame.sf_sc.uc_sigmask.__mask; + frame.sf_sc.uc_mcontext.fault_address = (register_t)ksi->ksi_addr; + frame.sf_sc.uc_mcontext.arm_r0 = regs->tf_r0; + frame.sf_sc.uc_mcontext.arm_r1 = regs->tf_r1; + frame.sf_sc.uc_mcontext.arm_r2 = regs->tf_r2; + frame.sf_sc.uc_mcontext.arm_r3 = regs->tf_r3; + frame.sf_sc.uc_mcontext.arm_r4 = regs->tf_r4; + frame.sf_sc.uc_mcontext.arm_r5 = regs->tf_r5; + frame.sf_sc.uc_mcontext.arm_r6 = regs->tf_r6; + frame.sf_sc.uc_mcontext.arm_r7 = regs->tf_r7; + frame.sf_sc.uc_mcontext.arm_r8 = regs->tf_r8; + frame.sf_sc.uc_mcontext.arm_r9 = regs->tf_r9; + frame.sf_sc.uc_mcontext.arm_r10 = regs->tf_r10; + frame.sf_sc.uc_mcontext.arm_fp = regs->tf_r11; + frame.sf_sc.uc_mcontext.arm_ip = regs->tf_r12; + frame.sf_sc.uc_mcontext.arm_sp = regs->tf_r13; + frame.sf_sc.uc_mcontext.arm_lr = regs->tf_r14; + frame.sf_sc.uc_mcontext.arm_pc = regs->tf_r15; + frame.sf_sc.uc_mcontext.arm_cpsr = regs->tf_spsr; + frame.sf_sc.uc_mcontext.error_code = 0; + frame.sf_sc.uc_mcontext.trap_no = bsd_to_linux_trapcode(code); #ifdef DEBUG if (ldebug(rt_sendsig)) 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, - 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 if (copyout(&frame, fp, sizeof(frame)) != 0) { @@ -532,19 +517,14 @@ /* * Build context to run handler in. */ - regs->tf_esp = (int)fp; - regs->tf_eip = linux_rt_sigcode; - regs->tf_eflags &= ~(PSL_T | PSL_VM | PSL_D); - regs->tf_cs = _ucodesel; - regs->tf_ds = _udatasel; - regs->tf_es = _udatasel; - regs->tf_fs = _udatasel; - regs->tf_ss = _udatasel; + regs->tf_r0 = (int)sig; + regs->tf_r1 = (int)catcher; + regs->tf_r13 = (int)fp; + regs->tf_r15 = linux_rt_sigcode; PROC_LOCK(p); mtx_lock(&psp->ps_mtx); } - /* * Send an interrupt to process. * @@ -578,7 +558,7 @@ return; } regs = td->td_frame; - oonstack = sigonstack(regs->tf_esp); + oonstack = sigonstack(regs->tf_r13); #ifdef DEBUG if (ldebug(sendsig)) @@ -594,7 +574,7 @@ fp = (struct l_sigframe *)((uintptr_t)td->td_sigstk.ss_sp + td->td_sigstk.ss_size - sizeof(struct l_sigframe)); } else - fp = (struct l_sigframe *)regs->tf_esp - 1; + fp = (struct l_sigframe *)regs->tf_r13 - 1; mtx_unlock(&psp->ps_mtx); PROC_UNLOCK(p); @@ -605,7 +585,7 @@ bzero(&frame, sizeof(frame)); - frame.sf_handler = catcher; + frame.sf_handler = (l_handler_t)catcher; frame.sf_sig = sig; bsd_to_linux_sigset(mask, &lmask); @@ -613,27 +593,27 @@ /* * Build the signal context to be used by sigreturn. */ - frame.sf_sc.sc_mask = lmask.__mask; - frame.sf_sc.sc_gs = rgs(); - frame.sf_sc.sc_fs = regs->tf_fs; - frame.sf_sc.sc_es = regs->tf_es; - frame.sf_sc.sc_ds = regs->tf_ds; - frame.sf_sc.sc_edi = regs->tf_edi; - frame.sf_sc.sc_esi = regs->tf_esi; - frame.sf_sc.sc_ebp = regs->tf_ebp; - frame.sf_sc.sc_ebx = regs->tf_ebx; - frame.sf_sc.sc_esp = regs->tf_esp; - frame.sf_sc.sc_edx = regs->tf_edx; - frame.sf_sc.sc_ecx = regs->tf_ecx; - frame.sf_sc.sc_eax = regs->tf_eax; - frame.sf_sc.sc_eip = regs->tf_eip; - frame.sf_sc.sc_cs = regs->tf_cs; - frame.sf_sc.sc_eflags = regs->tf_eflags; - frame.sf_sc.sc_esp_at_signal = regs->tf_esp; - frame.sf_sc.sc_ss = regs->tf_ss; - frame.sf_sc.sc_err = regs->tf_err; - frame.sf_sc.sc_cr2 = (register_t)ksi->ksi_addr; - frame.sf_sc.sc_trapno = bsd_to_linux_trapcode(ksi->ksi_trapno); + frame.sf_sc.oldmask = lmask.__mask; + frame.sf_sc.fault_address = (register_t)ksi->ksi_addr; + frame.sf_sc.arm_r0 = regs->tf_r0; + frame.sf_sc.arm_r1 = regs->tf_r1; + frame.sf_sc.arm_r2 = regs->tf_r2; + frame.sf_sc.arm_r3 = regs->tf_r3; + frame.sf_sc.arm_r4 = regs->tf_r4; + frame.sf_sc.arm_r5 = regs->tf_r5; + frame.sf_sc.arm_r6 = regs->tf_r6; + frame.sf_sc.arm_r7 = regs->tf_r7; + frame.sf_sc.arm_r8 = regs->tf_r8; + frame.sf_sc.arm_r9 = regs->tf_r9; + frame.sf_sc.arm_r10 = regs->tf_r10; + frame.sf_sc.arm_fp = regs->tf_r11; + frame.sf_sc.arm_ip = regs->tf_r12; + frame.sf_sc.arm_sp = regs->tf_r13; + frame.sf_sc.arm_lr = regs->tf_r14; + frame.sf_sc.arm_pc = regs->tf_r15; + frame.sf_sc.arm_cpsr = regs->tf_spsr; + frame.sf_sc.error_code = 0; + frame.sf_sc.trap_no = bsd_to_linux_trapcode(code); frame.sf_extramask[0] = lmask.__mask; @@ -649,14 +629,10 @@ /* * Build context to run handler in. */ - regs->tf_esp = (int)fp; - regs->tf_eip = linux_sigcode; - regs->tf_eflags &= ~(PSL_T | PSL_VM | PSL_D); - regs->tf_cs = _ucodesel; - regs->tf_ds = _udatasel; - regs->tf_es = _udatasel; - regs->tf_fs = _udatasel; - regs->tf_ss = _udatasel; + regs->tf_r0 = (int)sig; + regs->tf_r1 = (int)catcher; + regs->tf_r13 = (int)fp; + regs->tf_r15 = linux_sigcode; PROC_LOCK(p); mtx_lock(&psp->ps_mtx); } @@ -678,8 +654,6 @@ struct trapframe *regs; l_sigset_t lmask; sigset_t bmask; - int eflags; - ksiginfo_t ksi; regs = td->td_frame; @@ -695,53 +669,30 @@ if (copyin(args->sfp, &frame, sizeof(frame)) != 0) return (EFAULT); - /* - * 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; + lmask.__mask = frame.sf_sc.oldmask; linux_to_bsd_sigset(&lmask, &bmask); kern_sigprocmask(td, SIG_SETMASK, &bmask, NULL, 0); /* * Restore signal context. */ - /* %gs was restored by the trampoline. */ - regs->tf_fs = frame.sf_sc.sc_fs; - regs->tf_es = frame.sf_sc.sc_es; - regs->tf_ds = frame.sf_sc.sc_ds; - regs->tf_edi = frame.sf_sc.sc_edi; - regs->tf_esi = frame.sf_sc.sc_esi; - regs->tf_ebp = frame.sf_sc.sc_ebp; - regs->tf_ebx = frame.sf_sc.sc_ebx; - regs->tf_edx = frame.sf_sc.sc_edx; - regs->tf_ecx = frame.sf_sc.sc_ecx; - regs->tf_eax = frame.sf_sc.sc_eax; - regs->tf_eip = frame.sf_sc.sc_eip; - regs->tf_cs = frame.sf_sc.sc_cs; - regs->tf_eflags = eflags; - regs->tf_esp = frame.sf_sc.sc_esp_at_signal; - regs->tf_ss = frame.sf_sc.sc_ss; + regs->tf_r0 = frame.sf_sc.arm_r0 ; + regs->tf_r1 = frame.sf_sc.arm_r1 ; + regs->tf_r2 = frame.sf_sc.arm_r2 ; + regs->tf_r3 = frame.sf_sc.arm_r3 ; + regs->tf_r4 = frame.sf_sc.arm_r4 ; + regs->tf_r5 = frame.sf_sc.arm_r5 ; + regs->tf_r6 = frame.sf_sc.arm_r6 ; + regs->tf_r7 = frame.sf_sc.arm_r7 ; + regs->tf_r8 = frame.sf_sc.arm_r8 ; + regs->tf_r9 = frame.sf_sc.arm_r9 ; + regs->tf_r10 = frame.sf_sc.arm_r10 ; + regs->tf_r11 = frame.sf_sc.arm_fp ; + regs->tf_r12 = frame.sf_sc.arm_ip ; + regs->tf_r13 = frame.sf_sc.arm_sp ; + regs->tf_r14 = frame.sf_sc.arm_lr ; + regs->tf_r15 = frame.sf_sc.arm_pc ; + regs->tf_spsr = frame.sf_sc.arm_cpsr; return (EJUSTRETURN); } @@ -765,8 +716,6 @@ l_stack_t *lss; stack_t ss; struct trapframe *regs; - int eflags; - ksiginfo_t ksi; regs = td->td_frame; @@ -784,30 +733,6 @@ 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); kern_sigprocmask(td, SIG_SETMASK, &bmask, NULL, 0); @@ -815,34 +740,36 @@ * Restore signal context */ /* %gs was restored by the trampoline. */ - regs->tf_fs = context->sc_fs; - regs->tf_es = context->sc_es; - regs->tf_ds = context->sc_ds; - regs->tf_edi = context->sc_edi; - regs->tf_esi = context->sc_esi; - regs->tf_ebp = context->sc_ebp; - regs->tf_ebx = context->sc_ebx; - regs->tf_edx = context->sc_edx; - regs->tf_ecx = context->sc_ecx; - regs->tf_eax = context->sc_eax; - regs->tf_eip = context->sc_eip; - regs->tf_cs = context->sc_cs; - regs->tf_eflags = eflags; - regs->tf_esp = context->sc_esp_at_signal; - regs->tf_ss = context->sc_ss; + regs->tf_r0 = context->arm_r0 ; + regs->tf_r1 = context->arm_r1 ; + regs->tf_r2 = context->arm_r2 ; + regs->tf_r3 = context->arm_r3 ; + regs->tf_r4 = context->arm_r4 ; + regs->tf_r5 = context->arm_r5 ; + regs->tf_r6 = context->arm_r6 ; + regs->tf_r7 = context->arm_r7 ; + regs->tf_r8 = context->arm_r8 ; + regs->tf_r9 = context->arm_r9 ; + regs->tf_r10 = context->arm_r10 ; + regs->tf_r11 = context->arm_fp ; + regs->tf_r12 = context->arm_ip ; + regs->tf_r13 = context->arm_sp ; + regs->tf_r14 = context->arm_lr ; + regs->tf_r15 = context->arm_pc ; + regs->tf_spsr = context->arm_cpsr; /* * call sigaltstack & ignore results.. */ 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_flags = linux_to_bsd_sigaltstack(lss->ss_flags); #ifdef DEBUG if (ldebug(rt_sigreturn)) 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 (void)kern_sigaltstack(td, &ss, NULL); @@ -858,13 +785,23 @@ p = td->td_proc; frame = td->td_frame; - sa->code = frame->tf_eax; - sa->args[0] = frame->tf_ebx; - sa->args[1] = frame->tf_ecx; - sa->args[2] = frame->tf_edx; - sa->args[3] = frame->tf_esi; - sa->args[4] = frame->tf_edi; - sa->args[5] = frame->tf_ebp; /* Unconfirmed */ + sa->code = frame->tf_r7; + sa->args[0] = frame->tf_r0; + sa->args[1] = frame->tf_r1; + sa->args[2] = frame->tf_r2; + sa->args[3] = frame->tf_r3; + sa->args[4] = frame->tf_r4; + 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) /* nosys */ @@ -874,7 +811,7 @@ sa->narg = sa->callp->sy_narg; td->td_retval[0] = 0; - td->td_retval[1] = frame->tf_edx; + td->td_retval[1] = frame->tf_r1; return (0); } @@ -924,34 +861,15 @@ static void exec_linux_setregs(struct thread *td, struct image_params *imgp, u_long stack) { - struct pcb *pcb = td->td_pcb; 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 linux_get_machine(const char **dst) { - switch (cpu_class) { - case CPUCLASS_686: - *dst = "i686"; - break; - case CPUCLASS_586: - *dst = "i586"; - break; - case CPUCLASS_486: - *dst = "i486"; - break; - default: - *dst = "i386"; - } + *dst = "arm"; } struct sysentvec linux_sysvec = { @@ -982,7 +900,7 @@ .sv_flags = SV_ABI_LINUX | SV_AOUT | SV_IA32 | SV_ILP32, .sv_set_syscall_retval = cpu_set_syscall_retval, .sv_fetch_syscall_args = linux_fetch_syscall_args, - .sv_syscallnames = NULL, + .sv_syscallnames = linux_syscallnames, .sv_shared_page_base = LINUX_SHAREDPAGE, .sv_shared_page_len = PAGE_SIZE, .sv_schedtail = linux_schedtail, @@ -1019,7 +937,7 @@ .sv_flags = SV_ABI_LINUX | SV_IA32 | SV_ILP32 | SV_SHP, .sv_set_syscall_retval = cpu_set_syscall_retval, .sv_fetch_syscall_args = linux_fetch_syscall_args, - .sv_syscallnames = NULL, + .sv_syscallnames = linux_syscallnames, .sv_shared_page_base = LINUX_SHAREDPAGE, .sv_shared_page_len = PAGE_SIZE, .sv_schedtail = linux_schedtail, @@ -1096,7 +1014,7 @@ static Elf32_Brandinfo linux_brand = { .brand = ELFOSABI_LINUX, - .machine = EM_386, + .machine = EM_ARM, .compat_3_brand = "Linux", .emul_path = "/compat/linux", .interp_path = "/lib/ld-linux.so.1", @@ -1108,7 +1026,7 @@ static Elf32_Brandinfo linux_glibc2brand = { .brand = ELFOSABI_LINUX, - .machine = EM_386, + .machine = EM_ARM, .compat_3_brand = "Linux", .emul_path = "/compat/linux", .interp_path = "/lib/ld-linux.so.2",