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

Commit 5d750b9e authored by Bernd Schmidt's avatar Bernd Schmidt Committed by Bryan Wu
Browse files

[Blackfin] arch: Remove the circular buffering mechanism for exceptions



Remove the circular buffering mechanism for exceptions.  Instead, point RETX
at a safe location from which to fetch three NOPs.

This safe location is now in the fixed code area, and also used for certain
anomaly workarounds, to ensure that user space can find a valid ICPLB when
things are built with CONFIG_MPU.

Also, save I/DCPLB_FAULT_ADDRESS when lowering to level 5, since the hardware
reg is valid only at exception level.

Signed-off-by: default avatarBernd Schmidt <bernds_cb1@t-online.de>
Signed-off-by: default avatarBryan Wu <cooloney@kernel.org>
parent 00d205a1
Loading
Loading
Loading
Loading
+7 −8
Original line number Original line Diff line number Diff line
@@ -67,6 +67,8 @@ void __init trap_init(void)
	CSYNC();
	CSYNC();
}
}


void *saved_icplb_fault_addr, *saved_dcplb_fault_addr;

int kstack_depth_to_print = 48;
int kstack_depth_to_print = 48;


static void decode_address(char *buf, unsigned long address)
static void decode_address(char *buf, unsigned long address)
@@ -703,10 +705,7 @@ void dump_bfin_mem(struct pt_regs *fp)
	unsigned short *addr, *erraddr, val = 0, err = 0;
	unsigned short *addr, *erraddr, val = 0, err = 0;
	char sti = 0, buf[6];
	char sti = 0, buf[6];


	if (unlikely((fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR))
	erraddr = (void *)fp->pc;
	erraddr = (void *)fp->pc;
	else
		erraddr = (void *)fp->retx;


	printk(KERN_NOTICE "return address: [0x%p]; contents of:", erraddr);
	printk(KERN_NOTICE "return address: [0x%p]; contents of:", erraddr);


@@ -830,9 +829,9 @@ void show_regs(struct pt_regs *fp)


	if (((long)fp->seqstat &  SEQSTAT_EXCAUSE) &&
	if (((long)fp->seqstat &  SEQSTAT_EXCAUSE) &&
	    (((long)fp->seqstat & SEQSTAT_EXCAUSE) != VEC_HWERR)) {
	    (((long)fp->seqstat & SEQSTAT_EXCAUSE) != VEC_HWERR)) {
		decode_address(buf, bfin_read_DCPLB_FAULT_ADDR());
		decode_address(buf, saved_dcplb_fault_addr);
		printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf);
		printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf);
		decode_address(buf, bfin_read_ICPLB_FAULT_ADDR());
		decode_address(buf, saved_icplb_fault_addr);
		printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf);
		printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf);
	}
	}


@@ -940,8 +939,8 @@ void panic_cplb_error(int cplb_panic, struct pt_regs *fp)


	oops_in_progress = 1;
	oops_in_progress = 1;


	printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", (void *)bfin_read_DCPLB_FAULT_ADDR());
	printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", saved_dcplb_fault_addr);
	printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", (void *)bfin_read_ICPLB_FAULT_ADDR());
	printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", saved_icplb_fault_addr);
	dump_bfin_process(fp);
	dump_bfin_process(fp);
	dump_bfin_mem(fp);
	dump_bfin_mem(fp);
	show_regs(fp);
	show_regs(fp);
+33 −88
Original line number Original line Diff line number Diff line
@@ -38,6 +38,7 @@
#include <linux/unistd.h>
#include <linux/unistd.h>
#include <asm/blackfin.h>
#include <asm/blackfin.h>
#include <asm/errno.h>
#include <asm/errno.h>
#include <asm/fixed_code.h>
#include <asm/thread_info.h>  /* TIF_NEED_RESCHED */
#include <asm/thread_info.h>  /* TIF_NEED_RESCHED */
#include <asm/asm-offsets.h>
#include <asm/asm-offsets.h>
#include <asm/trace.h>
#include <asm/trace.h>
@@ -52,15 +53,6 @@
# define EX_SCRATCH_REG CYCLES
# define EX_SCRATCH_REG CYCLES
#endif
#endif


#if ANOMALY_05000281
ENTRY(_safe_speculative_execution)
	NOP;
	NOP;
	NOP;
	jump _safe_speculative_execution;
ENDPROC(_safe_speculative_execution)
#endif

#ifdef CONFIG_EXCPT_IRQ_SYSC_L1
#ifdef CONFIG_EXCPT_IRQ_SYSC_L1
.section .l1.text
.section .l1.text
#else
#else
@@ -230,6 +222,26 @@ ENTRY(_ex_trap_c)
	[p4] = p5;
	[p4] = p5;
	csync;
	csync;


	p4.l = lo(DCPLB_FAULT_ADDR);
	p4.h = hi(DCPLB_FAULT_ADDR);
	r7 = [p4];
	p5.h = _saved_dcplb_fault_addr;
	p5.l = _saved_dcplb_fault_addr;
	[p5] = r7;

	r7 = [p4 + (ICPLB_FAULT_ADDR - DCPLB_FAULT_ADDR)];
	p5.h = _saved_icplb_fault_addr;
	p5.l = _saved_icplb_fault_addr;
	[p5] = r7;

	p4.l = __retx;
	p4.h = __retx;
	r6 = retx;
	[p4] = r6;
	p4.l = lo(SAFE_USER_INSTRUCTION);
	p4.h = hi(SAFE_USER_INSTRUCTION);
	retx = p4;

	/* Disable all interrupts, but make sure level 5 is enabled so
	/* Disable all interrupts, but make sure level 5 is enabled so
	 * we can switch to that level.  Save the old mask.  */
	 * we can switch to that level.  Save the old mask.  */
	cli r6;
	cli r6;
@@ -239,23 +251,6 @@ ENTRY(_ex_trap_c)
	r6 = 0x3f;
	r6 = 0x3f;
	sti r6;
	sti r6;


	/* Save the excause into a circular buffer, in case the instruction
	 * which caused this excecptions causes others.
	 */
	P5.l = _in_ptr_excause;
	P5.h = _in_ptr_excause;
	R7 = [P5];
	R7 += 4;
	R6 = 0xF;
	R7 = R7 & R6;
	[P5] = R7;
	R6.l = _excause_circ_buf;
	R6.h = _excause_circ_buf;
	R7 = R7 + R6;
	p5 = R7;
	R6 = SEQSTAT;
	[P5] = R6;

	(R7:6,P5:4) = [sp++];
	(R7:6,P5:4) = [sp++];
	ASTAT = [sp++];
	ASTAT = [sp++];
	SP = EX_SCRATCH_REG;
	SP = EX_SCRATCH_REG;
@@ -312,6 +307,11 @@ ENDPROC(_double_fault)
ENTRY(_exception_to_level5)
ENTRY(_exception_to_level5)
	SAVE_ALL_SYS
	SAVE_ALL_SYS


	p4.l = __retx;
	p4.h = __retx;
	r6 = [p4];
	[sp + PT_PC] = r6;

	/* Restore interrupt mask.  We haven't pushed RETI, so this
	/* Restore interrupt mask.  We haven't pushed RETI, so this
	 * doesn't enable interrupts until we return from this handler.  */
	 * doesn't enable interrupts until we return from this handler.  */
	p4.l = _excpt_saved_imask;
	p4.l = _excpt_saved_imask;
@@ -333,42 +333,11 @@ ENTRY(_exception_to_level5)
	r0 = [p2];              /* Read current IPEND */
	r0 = [p2];              /* Read current IPEND */
	[sp + PT_IPEND] = r0;   /* Store IPEND */
	[sp + PT_IPEND] = r0;   /* Store IPEND */


	/* Pop the excause from the circular buffer and push it on the stack
	 * (in the right place - if you change the location of SEQSTAT, you
	 * must change this offset.
	 */
.L_excep_to_5_again:
	P5.l = _out_ptr_excause;
	P5.h = _out_ptr_excause;
	R7 = [P5];
	R7 += 4;
	R6 = 0xF;
	R7 = R7 & R6;
	[P5] = R7;
	R6.l = _excause_circ_buf;
	R6.h = _excause_circ_buf;
	R7 = R7 + R6;
	P5 = R7;
	R1 = [P5];
	[SP + PT_SEQSTAT] = r1;

	r0 = sp; 	/* stack frame pt_regs pointer argument ==> r0 */
	r0 = sp; 	/* stack frame pt_regs pointer argument ==> r0 */
	SP += -12;
	SP += -12;
	call _trap_c;
	call _trap_c;
	SP += 12;
	SP += 12;


	/* See if anything else is in the exception buffer
	 * if there is, process it
	 */
	P5.l = _out_ptr_excause;
	P5.h = _out_ptr_excause;
	P4.l = _in_ptr_excause;
	P4.h = _in_ptr_excause;
	R6 = [P5];
	R7 = [P4];
	CC = R6 == R7;
	if ! CC JUMP .L_excep_to_5_again

	call _ret_from_exception;
	call _ret_from_exception;
	RESTORE_ALL_SYS
	RESTORE_ALL_SYS
	rti;
	rti;
@@ -732,8 +701,8 @@ ENTRY(_return_from_int)
	[p0] = p1;
	[p0] = p1;
	csync;
	csync;
#if ANOMALY_05000281
#if ANOMALY_05000281
	r0.l = _safe_speculative_execution;
	r0.l = lo(SAFE_USER_INSTRUCTION);
	r0.h = _safe_speculative_execution;
	r0.h = hi(SAFE_USER_INSTRUCTION);
	reti = r0;
	reti = r0;
#endif
#endif
	r0 = 0x801f (z);
	r0 = 0x801f (z);
@@ -746,8 +715,8 @@ ENDPROC(_return_from_int)


ENTRY(_lower_to_irq14)
ENTRY(_lower_to_irq14)
#if ANOMALY_05000281
#if ANOMALY_05000281
	r0.l = _safe_speculative_execution;
	r0.l = lo(SAFE_USER_INSTRUCTION);
	r0.h = _safe_speculative_execution;
	r0.h = hi(SAFE_USER_INSTRUCTION);
	reti = r0;
	reti = r0;
#endif
#endif
	r0 = 0x401f;
	r0 = 0x401f;
@@ -814,20 +783,6 @@ _schedule_and_signal:
	rti;
	rti;
ENDPROC(_lower_to_irq14)
ENDPROC(_lower_to_irq14)


/* Make sure when we start, that the circular buffer is initialized properly
 * R0 and P0 are call clobbered, so we can use them here.
 */
ENTRY(_init_exception_buff)
	r0 = 0;
	p0.h = _in_ptr_excause;
	p0.l = _in_ptr_excause;
	[p0] = r0;
	p0.h = _out_ptr_excause;
	p0.l = _out_ptr_excause;
	[p0] = r0;
	rts;
ENDPROC(_init_exception_buff)

/* We handle this 100% in exception space - to reduce overhead
/* We handle this 100% in exception space - to reduce overhead
 * Only potiential problem is if the software buffer gets swapped out of the
 * Only potiential problem is if the software buffer gets swapped out of the
 * CPLB table - then double fault. - so we don't let this happen in other places
 * CPLB table - then double fault. - so we don't let this happen in other places
@@ -1403,17 +1358,7 @@ _exception_stack_top:
_last_cplb_fault_retx:
_last_cplb_fault_retx:
	.long 0;
	.long 0;
#endif
#endif
/*
	/* Used to save the real RETX when temporarily storing a safe
 * Single instructions can have multiple faults, which need to be
	 * return address.  */
 * handled by traps.c, in irq5. We store the exception cause to ensure
__retx:
 * we don't miss a double fault condition
 */
ENTRY(_in_ptr_excause)
	.long 0;
ENTRY(_out_ptr_excause)
	.long 0;
	.long 0;
ALIGN
ENTRY(_excause_circ_buf)
	.rept 4
	.long 0
	.endr
+0 −2
Original line number Original line Diff line number Diff line
@@ -939,8 +939,6 @@ int __init init_arch_irq(void)


	local_irq_disable();
	local_irq_disable();


	init_exception_buff();

#ifdef CONFIG_BF54x
#ifdef CONFIG_BF54x
# ifdef CONFIG_PINTx_REASSIGN
# ifdef CONFIG_PINTx_REASSIGN
	pint[0]->assign = CONFIG_PINT0_ASSIGN;
	pint[0]->assign = CONFIG_PINT0_ASSIGN;