예제 #1
0
파일: traps.c 프로젝트: CSCLOG/beaglebone
void fixup_BUG(struct pt_regs *regs)
{
	BUG_regs = *regs;

#ifdef CONFIG_DEBUG_BUGVERBOSE
	/*
	 * Fixup the BUG arguments through exception handlers.
	 */
	{
		const struct exception_table_entry *fixup;

		/*
		 * ERP points at the "break 14" + 2, compensate for the 2
		 * bytes.
		 */
		fixup = search_exception_tables(instruction_pointer(regs) - 2);
		if (fixup) {
			/* Adjust the instruction pointer in the stackframe. */
			instruction_pointer(regs) = fixup->fixup;
			arch_fixup(regs);
		}
	}
#else
	/* Dont try to lookup the filename + line, just dump regs.  */
	do_BUG("unknown", 0);
#endif
}
예제 #2
0
파일: trap.c 프로젝트: ivucica/linux
/*
 * We give a *copy* of the faultinfo in the regs to segv.
 * This must be done, since nesting SEGVs could overwrite
 * the info in the regs. A pointer to the info then would
 * give us bad data!
 */
unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc)
{
	struct siginfo si;
	void *catcher;
	int err;
        int is_write = FAULT_WRITE(fi);
        unsigned long address = FAULT_ADDRESS(fi);

        if(!is_user && (address >= start_vm) && (address < end_vm)){
                flush_tlb_kernel_vm();
                return(0);
        }
	else if(current->mm == NULL)
		panic("Segfault with no mm");

	if (SEGV_IS_FIXABLE(&fi) || SEGV_MAYBE_FIXABLE(&fi))
		err = handle_page_fault(address, ip, is_write, is_user, &si.si_code);
	else {
		err = -EFAULT;
		/* A thread accessed NULL, we get a fault, but CR2 is invalid.
		 * This code is used in __do_copy_from_user() of TT mode. */
		address = 0;
	}

	catcher = current->thread.fault_catcher;
	if(!err)
		return(0);
	else if(catcher != NULL){
		current->thread.fault_addr = (void *) address;
		do_longjmp(catcher, 1);
	}
	else if(current->thread.fault_addr != NULL)
		panic("fault_addr set but no fault catcher");
        else if(!is_user && arch_fixup(ip, sc))
		return(0);

 	if(!is_user)
		panic("Kernel mode fault at addr 0x%lx, ip 0x%lx",
		      address, ip);

	if (err == -EACCES) {
		si.si_signo = SIGBUS;
		si.si_errno = 0;
		si.si_code = BUS_ADRERR;
		si.si_addr = (void __user *)address;
                current->thread.arch.faultinfo = fi;
		force_sig_info(SIGBUS, &si, current);
	} else if (err == -ENOMEM) {
		printk("VM: killing process %s\n", current->comm);
		do_exit(SIGKILL);
	} else {
		BUG_ON(err != -EFAULT);
		si.si_signo = SIGSEGV;
		si.si_addr = (void __user *) address;
                current->thread.arch.faultinfo = fi;
		force_sig_info(SIGSEGV, &si, current);
	}
	return(0);
}
예제 #3
0
/* Find fixup code. */
int
find_fixup_code(struct pt_regs *regs)
{
	const struct exception_table_entry *fixup;

	if ((fixup = search_exception_tables(instruction_pointer(regs))) != 0) {
		/* Adjust the instruction pointer in the stackframe. */
		instruction_pointer(regs) = fixup->fixup;
		arch_fixup(regs);
		return 1;
	}

	return 0;
}
예제 #4
0
/* Find fixup code. */
int
find_fixup_code(struct pt_regs *regs)
{
	const struct exception_table_entry *fixup;
	/* in case of delay slot fault (v32) */
	unsigned long ip = (instruction_pointer(regs) & ~0x1);

	fixup = search_exception_tables(ip);
	if (fixup != 0) {
		/* Adjust the instruction pointer in the stackframe. */
		instruction_pointer(regs) = fixup->fixup;
		arch_fixup(regs);
		return 1;
	}

	return 0;
}
예제 #5
0
/*
 * We give a *copy* of the faultinfo in the regs to segv.
 * This must be done, since nesting SEGVs could overwrite
 * the info in the regs. A pointer to the info then would
 * give us bad data!
 */
unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
                   struct uml_pt_regs *regs)
{
    struct siginfo si;
    jmp_buf *catcher;
    int err;
    int is_write = FAULT_WRITE(fi);
    unsigned long address = FAULT_ADDRESS(fi);

    if (!is_user && (address >= start_vm) && (address < end_vm)) {
        flush_tlb_kernel_vm();
        return 0;
    }
    else if (current->mm == NULL) {
        show_regs(container_of(regs, struct pt_regs, regs));
        panic("Segfault with no mm");
    }

    if (SEGV_IS_FIXABLE(&fi) || SEGV_MAYBE_FIXABLE(&fi))
        err = handle_page_fault(address, ip, is_write, is_user,
                                &si.si_code);
    else {
        err = -EFAULT;
        /*
         * A thread accessed NULL, we get a fault, but CR2 is invalid.
         * This code is used in __do_copy_from_user() of TT mode.
         * XXX tt mode is gone, so maybe this isn't needed any more
         */
        address = 0;
    }

    catcher = current->thread.fault_catcher;
    if (!err)
        return 0;
    else if (catcher != NULL) {
        current->thread.fault_addr = (void *) address;
        UML_LONGJMP(catcher, 1);
    }
    else if (current->thread.fault_addr != NULL)
        panic("fault_addr set but no fault catcher");
    else if (!is_user && arch_fixup(ip, regs))
        return 0;

    if (!is_user) {
        show_regs(container_of(regs, struct pt_regs, regs));
        panic("Kernel mode fault at addr 0x%lx, ip 0x%lx",
              address, ip);
    }

    if (err == -EACCES) {
        si.si_signo = SIGBUS;
        si.si_errno = 0;
        si.si_code = BUS_ADRERR;
        si.si_addr = (void __user *)address;
        current->thread.arch.faultinfo = fi;
        force_sig_info(SIGBUS, &si, current);
    } else if (err == -ENOMEM) {
        printk(KERN_INFO "VM: killing process %s\n", current->comm);
        do_exit(SIGKILL);
    } else {
        BUG_ON(err != -EFAULT);
        si.si_signo = SIGSEGV;
        si.si_addr = (void __user *) address;
        current->thread.arch.faultinfo = fi;
        force_sig_info(SIGSEGV, &si, current);
    }
    return 0;
}