diff options
Diffstat (limited to 'lib_ppc/extable.c')
| -rw-r--r-- | lib_ppc/extable.c | 29 | 
1 files changed, 23 insertions, 6 deletions
| diff --git a/lib_ppc/extable.c b/lib_ppc/extable.c index d92f14270..b14d661bb 100644 --- a/lib_ppc/extable.c +++ b/lib_ppc/extable.c @@ -37,6 +37,8 @@   * on our cache or tlb entries.   */ +DECLARE_GLOBAL_DATA_PTR; +  struct exception_table_entry  {  	unsigned long insn, fixup; @@ -55,13 +57,25 @@ search_one_table(const struct exception_table_entry *first,  		long diff;  		mid = (last - first) / 2 + first; -		diff = mid->insn - value; -		if (diff == 0) -			return mid->fixup; -		else if (diff < 0) -			first = mid+1; +		if ((ulong) mid > CFG_MONITOR_BASE) { +			/* exception occurs in FLASH, before u-boot relocation. +			 * No relocation offset is needed. +			 */ +			diff = mid->insn - value; +			if (diff == 0) +				return mid->fixup; +		} else { +			/* exception occurs in RAM, after u-boot relocation. +			 * A relocation offset should be added. +			 */ +			diff = (mid->insn + gd->reloc_off) - value; +			if (diff == 0) +				return (mid->fixup + gd->reloc_off); +		} +		if (diff < 0) +			first = mid + 1;  		else -			last = mid-1; +			last = mid - 1;  	}  	return 0;  } @@ -75,8 +89,11 @@ search_exception_table(unsigned long addr)  	/* There is only the kernel to search.  */  	ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr); +	/* if the serial port does not hang in exception, printf can be used */ +#if !defined(CFG_SERIAL_HANG_IN_EXCEPTION)  	if (ex_tab_message)  		printf("Bus Fault @ 0x%08lx, fixup 0x%08lx\n", addr, ret); +#endif  	if (ret) return ret;  	return 0; |