Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5d86456d authored by Jeff Dike's avatar Jeff Dike Committed by Linus Torvalds
Browse files

uml: tidy fault code



Tidying in preparation for the segfault register dumping patch which follows.

void * pointers are changed to union uml_pt_regs *.  This makes the types
match reality, except in arch_fixup, which is changed to operate on a union
uml_pt_regs.  This fixes a bug in the call from segv_handler, which passes a
union uml_pt_regs, to segv, which expects to pass a struct sigcontext to
arch_fixup.

Whitespace and other style fixes.

There's also a errno printk fix.

Signed-off-by: default avatarJeff Dike <jdike@linux.intel.com>
Cc: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent ccdddb57
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -9,7 +9,7 @@
#include "sysdep/ptrace.h"

extern void arch_check_bugs(void);
extern int arch_fixup(unsigned long address, void *sc_ptr);
extern int arch_fixup(unsigned long address, union uml_pt_regs *regs);
extern int arch_handle_signal(int sig, union uml_pt_regs *regs);

#endif
+1 −1
Original line number Diff line number Diff line
@@ -44,7 +44,7 @@ extern unsigned long alloc_stack(int order, int atomic);
extern int do_signal(void);
extern int is_stack_fault(unsigned long sp);
extern unsigned long segv(struct faultinfo fi, unsigned long ip,
			  int is_user, void *sc);
			  int is_user, union uml_pt_regs *regs);
extern int handle_page_fault(unsigned long address, unsigned long ip,
			     int is_write, int is_user, int *code_out);
extern void syscall_ready(void);
+18 −17
Original line number Diff line number Diff line
@@ -157,7 +157,8 @@ static void segv_handler(int sig, union uml_pt_regs *regs)
 * 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)
unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
		   union uml_pt_regs *regs)
{
	struct siginfo si;
	void *catcher;
@@ -167,7 +168,7 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc)

	if(!is_user && (address >= start_vm) && (address < end_vm)){
		flush_tlb_kernel_vm();
                return(0);
		return 0;
	}
	else if(current->mm == NULL)
		panic("Segfault with no mm");
@@ -183,15 +184,15 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc)

	catcher = current->thread.fault_catcher;
	if(!err)
		return(0);
		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);
	else if(!is_user && arch_fixup(ip, regs))
		return 0;

	if(!is_user)
		panic("Kernel mode fault at addr 0x%lx, ip 0x%lx",
@@ -214,7 +215,7 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc)
		current->thread.arch.faultinfo = fi;
		force_sig_info(SIGSEGV, &si, current);
	}
	return(0);
	return 0;
}

void relay_signal(int sig, union uml_pt_regs *regs)
+8 −9
Original line number Diff line number Diff line
@@ -18,10 +18,9 @@
void sig_handler_common_skas(int sig, void *sc_ptr)
{
	struct sigcontext *sc = sc_ptr;
	struct skas_regs *r;
	union uml_pt_regs *r;
	void (*handler)(int, union uml_pt_regs *);
	int save_errno = errno;
	int save_user;
	int save_user, save_errno = errno;

	/* This is done because to allow SIGSEGV to be delivered inside a SEGV
	 * handler.  This can happen in copy_user, and if SEGV is disabled,
@@ -31,13 +30,13 @@ void sig_handler_common_skas(int sig, void *sc_ptr)
	if(sig == SIGSEGV)
		change_sig(SIGSEGV, 1);

	r = &TASK_REGS(get_current())->skas;
	save_user = r->is_user;
	r->is_user = 0;
	r = TASK_REGS(get_current());
	save_user = r->skas.is_user;
	r->skas.is_user = 0;
	if ( sig == SIGFPE || sig == SIGSEGV ||
	     sig == SIGBUS || sig == SIGILL ||
	     sig == SIGTRAP ) {
		GET_FAULTINFO_FROM_SC(r->faultinfo, sc);
		GET_FAULTINFO_FROM_SC(r->skas.faultinfo, sc);
	}

	change_sig(SIGUSR1, 1);
@@ -49,10 +48,10 @@ void sig_handler_common_skas(int sig, void *sc_ptr)
	    sig != SIGVTALRM && sig != SIGALRM)
		unblock_signals();

	handler(sig, (union uml_pt_regs *) r);
	handler(sig, r);

	errno = save_errno;
	r->is_user = save_user;
	r->skas.is_user = save_user;
}

extern int ptrace_faultinfo;
+2 −16
Original line number Diff line number Diff line
@@ -3,9 +3,7 @@
 * Licensed under the GPL
 */

#include <signal.h>
#include "sysdep/ptrace.h"
#include "sysdep/sigcontext.h"

/* These two are from asm-um/uaccess.h and linux/module.h, check them. */
struct exception_table_entry
@@ -17,26 +15,14 @@ struct exception_table_entry
const struct exception_table_entry *search_exception_tables(unsigned long add);

/* Compare this to arch/i386/mm/extable.c:fixup_exception() */
int arch_fixup(unsigned long address, void *sc_ptr)
int arch_fixup(unsigned long address, union uml_pt_regs *regs)
{
	struct sigcontext *sc = sc_ptr;
	const struct exception_table_entry *fixup;

	fixup = search_exception_tables(address);
	if(fixup != 0){
		sc->eip = fixup->fixup;
		UPT_IP(regs) = fixup->fixup;
		return(1);
	}
	return(0);
}

/*
 * Overrides for Emacs so that we follow Linus's tabbing style.
 * Emacs will notice this stuff at the end of the file and automatically
 * adjust the settings for this buffer only.  This must remain at the end
 * of the file.
 * ---------------------------------------------------------------------------
 * Local variables:
 * c-file-style: "linux"
 * End:
 */
Loading