void sh64_setup_tlb_slot(unsigned long long config_addr, unsigned long eaddr,
			 unsigned long asid, unsigned long paddr)
{
	unsigned long long pteh, ptel;

	pteh = neff_sign_extend(eaddr);
	pteh &= PAGE_MASK;
	pteh |= (asid << PTEH_ASID_SHIFT) | PTEH_VALID;
	ptel = neff_sign_extend(paddr);
	ptel &= PAGE_MASK;
	ptel |= (_PAGE_CACHABLE | _PAGE_READ | _PAGE_WRITE);

	asm volatile("putcfg %0, 1, %1\n\t"
			"putcfg %0, 0, %2\n"
			: : "r" (config_addr), "r" (ptel), "r" (pteh));
}
示例#2
0
static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
                          sigset_t *set, struct pt_regs *regs)
{
    struct rt_sigframe __user *frame;
    int err = 0;
    int signal;

    frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame));

    if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
        goto give_sigsegv;

    signal = current_thread_info()->exec_domain
             && current_thread_info()->exec_domain->signal_invmap
             && sig < 32
             ? current_thread_info()->exec_domain->signal_invmap[sig]
             : sig;

    err |= __put_user(&frame->info, &frame->pinfo);
    err |= __put_user(&frame->uc, &frame->puc);
    err |= copy_siginfo_to_user(&frame->info, info);

    /* Give up earlier as i386, in case */
    if (err)
        goto give_sigsegv;

    /* Create the ucontext.  */
    err |= __put_user(0, &frame->uc.uc_flags);
    err |= __put_user(0, &frame->uc.uc_link);
    err |= __put_user((void *)current->sas_ss_sp,
                      &frame->uc.uc_stack.ss_sp);
    err |= __put_user(sas_ss_flags(regs->regs[REG_SP]),
                      &frame->uc.uc_stack.ss_flags);
    err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
    err |= setup_sigcontext(&frame->uc.uc_mcontext,
                            regs, set->sig[0]);
    err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));

    /* Give up earlier as i386, in case */
    if (err)
        goto give_sigsegv;

    /* Set up to return from userspace.  If provided, use a stub
       already in userspace.  */
    if (ka->sa.sa_flags & SA_RESTORER) {
        /*
         * On SH5 all edited pointers are subject to NEFF
         */
        DEREF_REG_PR = neff_sign_extend((unsigned long)
                                        ka->sa.sa_restorer | 0x1);
    } else {
        /*
         * Different approach on SH5.
             * . Endianness independent asm code gets placed in entry.S .
         *   This is limited to four ASM instructions corresponding
         *   to two long longs in size.
         * . err checking is done on the else branch only
         * . flush_icache_range() is called upon __put_user() only
         * . all edited pointers are subject to NEFF
         * . being code, linker turns ShMedia bit on, always
         *   dereference index -1.
         */
        DEREF_REG_PR = neff_sign_extend((unsigned long)
                                        frame->retcode | 0x01);

        if (__copy_to_user(frame->retcode,
                           (void *)((unsigned long)sa_default_rt_restorer & (~1)), 16) != 0)
            goto give_sigsegv;

        /* Cohere the trampoline with the I-cache. */
        flush_icache_range(DEREF_REG_PR-1, DEREF_REG_PR-1+15);
    }

    /*
     * Set up registers for signal handler.
     * All edited pointers are subject to NEFF.
     */
    regs->regs[REG_SP] = neff_sign_extend((unsigned long)frame);
    regs->regs[REG_ARG1] = signal; /* Arg for signal handler */
    regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->info;
    regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->uc.uc_mcontext;
    regs->pc = neff_sign_extend((unsigned long)ka->sa.sa_handler);

    set_fs(USER_DS);

    pr_debug("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n",
             signal, current->comm, current->pid, frame,
             regs->pc >> 32, regs->pc & 0xffffffff,
             DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff);

    return 0;

give_sigsegv:
    force_sigsegv(sig, current);
    return -EFAULT;
}
示例#3
0
static int setup_frame(int sig, struct k_sigaction *ka,
                       sigset_t *set, struct pt_regs *regs)
{
    struct sigframe __user *frame;
    int err = 0;
    int signal;

    frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame));

    if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
        goto give_sigsegv;

    signal = current_thread_info()->exec_domain
             && current_thread_info()->exec_domain->signal_invmap
             && sig < 32
             ? current_thread_info()->exec_domain->signal_invmap[sig]
             : sig;

    err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);

    /* Give up earlier as i386, in case */
    if (err)
        goto give_sigsegv;

    if (_NSIG_WORDS > 1) {
        err |= __copy_to_user(frame->extramask, &set->sig[1],
                              sizeof(frame->extramask));
    }

    /* Give up earlier as i386, in case */
    if (err)
        goto give_sigsegv;

    /* Set up to return from userspace.  If provided, use a stub
       already in userspace.  */
    if (ka->sa.sa_flags & SA_RESTORER) {
        /*
         * On SH5 all edited pointers are subject to NEFF
         */
        DEREF_REG_PR = neff_sign_extend((unsigned long)
                                        ka->sa.sa_restorer | 0x1);
    } else {
        /*
         * Different approach on SH5.
             * . Endianness independent asm code gets placed in entry.S .
         *   This is limited to four ASM instructions corresponding
         *   to two long longs in size.
         * . err checking is done on the else branch only
         * . flush_icache_range() is called upon __put_user() only
         * . all edited pointers are subject to NEFF
         * . being code, linker turns ShMedia bit on, always
         *   dereference index -1.
         */
        DEREF_REG_PR = neff_sign_extend((unsigned long)
                                        frame->retcode | 0x01);

        if (__copy_to_user(frame->retcode,
                           (void *)((unsigned long)sa_default_restorer & (~1)), 16) != 0)
            goto give_sigsegv;

        /* Cohere the trampoline with the I-cache. */
        flush_cache_sigtramp(DEREF_REG_PR-1);
    }

    /*
     * Set up registers for signal handler.
     * All edited pointers are subject to NEFF.
     */
    regs->regs[REG_SP] = neff_sign_extend((unsigned long)frame);
    regs->regs[REG_ARG1] = signal; /* Arg for signal handler */

    /* FIXME:
       The glibc profiling support for SH-5 needs to be passed a sigcontext
       so it can retrieve the PC.  At some point during 2003 the glibc
       support was changed to receive the sigcontext through the 2nd
       argument, but there are still versions of libc.so in use that use
       the 3rd argument.  Until libc.so is stabilised, pass the sigcontext
       through both 2nd and 3rd arguments.
    */

    regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->sc;
    regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->sc;

    regs->pc = neff_sign_extend((unsigned long)ka->sa.sa_handler);

    set_fs(USER_DS);

    /* Broken %016Lx */
    pr_debug("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n",
             signal, current->comm, current->pid, frame,
             regs->pc >> 32, regs->pc & 0xffffffff,
             DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff);

    return 0;

give_sigsegv:
    force_sigsegv(sig, current);
    return -EFAULT;
}