All of lore.kernel.org
 help / color / mirror / Atom feed
* compute_return_epc
@ 2002-12-17 12:43 Ralf Baechle
  2002-12-17 13:54 ` compute_return_epc Maciej W. Rozycki
  0 siblings, 1 reply; 3+ messages in thread
From: Ralf Baechle @ 2002-12-17 12:43 UTC (permalink / raw)
  To: linux-mips

The current kernel code is calling compute_return_epc() in most exception
handlers for skipping over the instruction.  We're doing thins in practically
all cases.  To my knowledge we're the only MIPS UNIX flavor doing that
which my result in software portabilitiy problems.  It also means that
debuggers and signal handlers in such a case will only ever see the new
program counter but never a pointer to the actually faulting instruction.

So I'd like to apply the following patch which limits the use of
compute_return_epc to those cases where we actually did some sort of
instruction emulation.  Comments?

  Ralf

Index: arch/mips/kernel/traps.c
===================================================================
RCS file: /home/cvs/linux/arch/mips/kernel/traps.c,v
retrieving revision 1.99.2.36
diff -u -r1.99.2.36 traps.c
--- arch/mips/kernel/traps.c	17 Dec 2002 01:43:05 -0000	1.99.2.36
+++ arch/mips/kernel/traps.c	17 Dec 2002 12:07:48 -0000
@@ -96,7 +96,7 @@
 
 static struct task_struct *ll_task = NULL;
 
-static inline void simulate_ll(struct pt_regs *regp, unsigned int opcode)
+static inline void simulate_ll(struct pt_regs *regs, unsigned int opcode)
 {
 	unsigned long value, *vaddr;
 	long offset;
@@ -112,32 +112,37 @@
 	offset <<= 16;
 	offset >>= 16;
 
-	vaddr = (unsigned long *)((long)(regp->regs[(opcode & BASE) >> 21]) + offset);
+	vaddr = (unsigned long *)((long)(regs->regs[(opcode & BASE) >> 21]) + offset);
 
 #ifdef CONFIG_PROC_FS
 	ll_ops++;
 #endif
 
-	if ((unsigned long)vaddr & 3)
+	if ((unsigned long)vaddr & 3) {
 		signal = SIGBUS;
-	else if (get_user(value, vaddr))
+		goto sig;
+	}
+	if (get_user(value, vaddr)) {
 		signal = SIGSEGV;
-	else {
-		if (ll_task == NULL || ll_task == current) {
-			ll_bit = 1;
-		} else {
-			ll_bit = 0;
-		}
-		ll_task = current;
-		regp->regs[(opcode & RT) >> 16] = value;
+		goto sig;
 	}
-	if (compute_return_epc(regp))
-		return;
-	if (signal)
-		send_sig(signal, current, 1);
+
+	if (ll_task == NULL || ll_task == current) {
+		ll_bit = 1;
+	} else {
+		ll_bit = 0;
+	}
+	ll_task = current;
+	regs->regs[(opcode & RT) >> 16] = value;
+
+	compute_return_epc(regs);
+	return;
+
+sig:
+	send_sig(signal, current, 1);
 }
 
-static inline void simulate_sc(struct pt_regs *regp, unsigned int opcode)
+static inline void simulate_sc(struct pt_regs *regs, unsigned int opcode)
 {
 	unsigned long *vaddr, reg;
 	long offset;
@@ -153,25 +158,32 @@
 	offset <<= 16;
 	offset >>= 16;
 
-	vaddr = (unsigned long *)((long)(regp->regs[(opcode & BASE) >> 21]) + offset);
+	vaddr = (unsigned long *)((long)(regs->regs[(opcode & BASE) >> 21]) + offset);
 	reg = (opcode & RT) >> 16;
 
 #ifdef CONFIG_PROC_FS
 	sc_ops++;
 #endif
 
-	if ((unsigned long)vaddr & 3)
+	if ((unsigned long)vaddr & 3) {
 		signal = SIGBUS;
-	else if (ll_bit == 0 || ll_task != current)
-		regp->regs[reg] = 0;
-	else if (put_user(regp->regs[reg], vaddr))
+		goto sig;
+	}
+	if (ll_bit == 0 || ll_task != current) {
+		regs->regs[reg] = 0;
+		goto sig;
+	}
+
+	if (put_user(regs->regs[reg], vaddr))
 		signal = SIGSEGV;
 	else
-		regp->regs[reg] = 1;
-	if (compute_return_epc(regp))
-		return;
-	if (signal)
-		send_sig(signal, current, 1);
+		regs->regs[reg] = 1;
+
+	compute_return_epc(regs);
+	return;
+
+sig:
+	send_sig(signal, current, 1);
 }
 
 /*
@@ -489,9 +501,6 @@
 {
 	siginfo_t info;
 
-	if (compute_return_epc(regs))
-		return;
-
 	info.si_code = FPE_INTOVF;
 	info.si_signo = SIGFPE;
 	info.si_errno = 0;
@@ -534,20 +543,11 @@
 
 		/* If something went wrong, signal */
 		if (sig)
-		{
-			/*
-			 * Return EPC is not calculated in the FPU emulator,
-			 * if a signal is being send. So we calculate it here.
-			 */
-			compute_return_epc(regs);
 			force_sig(sig, current);
-		}
 
 		return;
 	}
 
-	if (compute_return_epc(regs))
-		return;
 	force_sig(SIGFPE, current);
 }
 
@@ -670,8 +670,6 @@
 	}
 #endif /* CONFIG_CPU_HAS_LLSC */
 
-	if (compute_return_epc(regs))
-		return;
 	force_sig(SIGILL, current);
 }
 
@@ -695,14 +693,8 @@
 
 	if (!(mips_cpu.options & MIPS_CPU_FPU)) {
 		int sig = fpu_emulator_cop1Handler(0, regs, &current->thread.fpu.soft);
-		if (sig) {
-			/*
-		 	 * Return EPC is not calculated in the FPU emulator, if
-		   	 * a signal is being send. So we calculate it here.
-		 	 */
-			compute_return_epc(regs);
+		if (sig)
 			force_sig(sig, current);
-		}
 	}
 
 	return;
@@ -716,7 +708,6 @@
 		return;
 	}
 #endif
-	compute_return_epc(regs);
 	force_sig(SIGILL, current);
 }
 
@@ -823,28 +814,28 @@
  */
 void ejtag_exception_handler(struct pt_regs *regs)
 {
-        unsigned long depc, old_epc;
-        unsigned int debug;
+	unsigned long depc, old_epc;
+	unsigned int debug;
 
-        printk("SDBBP EJTAG debug exception - not handled yet, just ignored!\n");
-        depc = read_c0_depc();
-        debug = read_c0_debug();
-        printk("c0_depc = %08lx, DEBUG = %08x\n", depc, debug);
-        if (debug & 0x80000000) {
-                /*
-                 * In branch delay slot.
-                 * We cheat a little bit here and use EPC to calculate the
-                 * debug return address (DEPC). EPC is restored after the
-                 * calculation.
-                 */
-                old_epc = regs->cp0_epc;
-                regs->cp0_epc = depc;
-                __compute_return_epc(regs);
-                depc = regs->cp0_epc;
-                regs->cp0_epc = old_epc;
-        } else
-                depc += 4;
-        write_c0_depc(depc);
+	printk("SDBBP EJTAG debug exception - not handled yet, just ignored!\n");
+	depc = read_c0_depc();
+	debug = read_c0_debug();
+	printk("c0_depc = %08lx, DEBUG = %08x\n", depc, debug);
+	if (debug & 0x80000000) {
+		/*
+		 * In branch delay slot.
+		 * We cheat a little bit here and use EPC to calculate the
+		 * debug return address (DEPC). EPC is restored after the
+		 * calculation.
+		 */
+		old_epc = regs->cp0_epc;
+		regs->cp0_epc = depc;
+		__compute_return_epc(regs);
+		depc = regs->cp0_epc;
+		regs->cp0_epc = old_epc;
+	} else
+		depc += 4;
+	write_c0_depc(depc);
 
 #if 0
 	printk("\n\n----- Enable EJTAG single stepping ----\n\n");
Index: arch/mips/kernel/unaligned.c
===================================================================
RCS file: /home/cvs/linux/arch/mips/kernel/unaligned.c,v
retrieving revision 1.15.2.9
diff -u -r1.15.2.9 unaligned.c
--- arch/mips/kernel/unaligned.c	7 Dec 2002 17:46:47 -0000	1.15.2.9
+++ arch/mips/kernel/unaligned.c	17 Dec 2002 12:07:48 -0000
@@ -88,6 +88,10 @@
 #define STR(x)  __STR(x)
 #define __STR(x)  #x
 
+#ifdef CONFIG_PROC_FS
+unsigned long unaligned_instructions;
+#endif
+
 static inline int emulate_load_store_insn(struct pt_regs *regs,
 	unsigned long addr, unsigned long pc)
 {
@@ -447,6 +451,13 @@
 		 */
 		goto sigill;
 	}
+
+	compute_return_epc(regs);
+
+#ifdef CONFIG_PROC_FS
+	unaligned_instructions++;
+#endif
+
 	return 0;
 
 fault:
@@ -479,10 +490,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_PROC_FS
-unsigned long unaligned_instructions;
-#endif
-
 asmlinkage void do_ade(struct pt_regs *regs)
 {
 	unsigned long pc;
@@ -516,12 +523,7 @@
 	 * Do branch emulation only if we didn't forward the exception.
 	 * This is all so but ugly ...
 	 */
-	if (!emulate_load_store_insn(regs, regs->cp0_badvaddr, pc))
-		compute_return_epc(regs);
-
-#ifdef CONFIG_PROC_FS
-	unaligned_instructions++;
-#endif
+	emulate_load_store_insn(regs, regs->cp0_badvaddr, pc);
 
 	return;
 
Index: arch/mips64/kernel/traps.c
===================================================================
RCS file: /home/cvs/linux/arch/mips64/kernel/traps.c,v
retrieving revision 1.30.2.39
diff -u -r1.30.2.39 traps.c
--- arch/mips64/kernel/traps.c	17 Dec 2002 01:43:05 -0000	1.30.2.39
+++ arch/mips64/kernel/traps.c	17 Dec 2002 12:07:49 -0000
@@ -400,9 +400,6 @@
 {
 	siginfo_t info;
 
-	if (compute_return_epc(regs))
-		return;
-
 	info.si_code = FPE_INTOVF;
 	info.si_signo = SIGFPE;
 	info.si_errno = 0;
@@ -445,20 +442,11 @@
 
 		/* If something went wrong, signal */
 		if (sig)
-		{
-			/*
-			 * Return EPC is not calculated in the FPU emulator,
-			 * if a signal is being send. So we calculate it here.
-			 */
-			compute_return_epc(regs);
 			force_sig(sig, current);
-		}
 
 		return;
 	}
 
-	if (compute_return_epc(regs))
-		return;
 	force_sig(SIGFPE, current);
 }
 
@@ -552,9 +540,6 @@
 {
 	die_if_kernel("Reserved instruction in kernel code", regs);
 
-	if (compute_return_epc(regs))
-		return;
-
 	force_sig(SIGILL, current);
 }
 
@@ -578,20 +563,13 @@
 
 	if (!(mips_cpu.options & MIPS_CPU_FPU)) {
 		int sig = fpu_emulator_cop1Handler(0, regs, &current->thread.fpu.soft);
-		if (sig) {
-			/*
-			 * Return EPC is not calculated in the FPU emulator, if
-			 * a signal is being send. So we calculate it here.
-			 */
-			compute_return_epc(regs);
+		if (sig)
 			force_sig(sig, current);
-		}
 	}
 
 	return;
 
 bad_cid:
-	compute_return_epc(regs);
 	force_sig(SIGILL, current);
 }
 
Index: arch/mips64/kernel/unaligned.c
===================================================================
RCS file: /home/cvs/linux/arch/mips64/kernel/unaligned.c,v
retrieving revision 1.6.2.8
diff -u -r1.6.2.8 unaligned.c
--- arch/mips64/kernel/unaligned.c	7 Dec 2002 17:46:47 -0000	1.6.2.8
+++ arch/mips64/kernel/unaligned.c	17 Dec 2002 12:07:50 -0000
@@ -88,6 +88,10 @@
 #define STR(x)  __STR(x)
 #define __STR(x)  #x
 
+#ifdef CONFIG_PROC_FS
+unsigned long unaligned_instructions;
+#endif
+
 static inline int emulate_load_store_insn(struct pt_regs *regs,
 	unsigned long addr, unsigned long pc)
 {
@@ -447,6 +451,13 @@
 		 */
 		goto sigill;
 	}
+
+	compute_return_epc(regs);
+
+#ifdef CONFIG_PROC_FS
+	unaligned_instructions++;
+#endif
+
 	return 0;
 
 fault:
@@ -479,10 +490,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_PROC_FS
-unsigned long unaligned_instructions;
-#endif
-
 asmlinkage void do_ade(struct pt_regs *regs)
 {
 	unsigned long pc;
@@ -516,12 +523,7 @@
 	 * Do branch emulation only if we didn't forward the exception.
 	 * This is all so but ugly ...
 	 */
-	if (!emulate_load_store_insn(regs, regs->cp0_badvaddr, pc))
-		compute_return_epc(regs);
-
-#ifdef CONFIG_PROC_FS
-	unaligned_instructions++;
-#endif
+	emulate_load_store_insn(regs, regs->cp0_badvaddr, pc);
 
 	return;
 

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: compute_return_epc
  2002-12-17 12:43 compute_return_epc Ralf Baechle
@ 2002-12-17 13:54 ` Maciej W. Rozycki
  2002-12-17 23:50   ` compute_return_epc Ralf Baechle
  0 siblings, 1 reply; 3+ messages in thread
From: Maciej W. Rozycki @ 2002-12-17 13:54 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

On Tue, 17 Dec 2002, Ralf Baechle wrote:

> So I'd like to apply the following patch which limits the use of
> compute_return_epc to those cases where we actually did some sort of
> instruction emulation.  Comments?

 Ah, finally!  Thanks for offloading the task from me. ;-) 

-- 
+  Maciej W. Rozycki, Technical University of Gdansk, Poland   +
+--------------------------------------------------------------+
+        e-mail: macro@ds2.pg.gda.pl, PGP key available        +

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: compute_return_epc
  2002-12-17 13:54 ` compute_return_epc Maciej W. Rozycki
@ 2002-12-17 23:50   ` Ralf Baechle
  0 siblings, 0 replies; 3+ messages in thread
From: Ralf Baechle @ 2002-12-17 23:50 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: linux-mips

On Tue, Dec 17, 2002 at 02:54:45PM +0100, Maciej W. Rozycki wrote:

> > So I'd like to apply the following patch which limits the use of
> > compute_return_epc to those cases where we actually did some sort of
> > instruction emulation.  Comments?
> 
>  Ah, finally!  Thanks for offloading the task from me. ;-) 

Wonderful :-)

  Ralf

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2002-12-17 23:50 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-12-17 12:43 compute_return_epc Ralf Baechle
2002-12-17 13:54 ` compute_return_epc Maciej W. Rozycki
2002-12-17 23:50   ` compute_return_epc Ralf Baechle

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.