15 #include <linux/sched.h>
16 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/reboot.h>
21 #include <linux/ptrace.h>
23 #include <asm/traps.h>
24 #include <asm/setup.h>
27 #include <arch/spr_def.h>
37 static int __init setup_unaligned_fixup(
char *
str)
48 pr_info(
"Fixups for unaligned data accesses are %s\n",
51 "completely disabled");
54 __setup(
"unaligned_fixup=", setup_unaligned_fixup);
56 #if CHIP_HAS_TILE_DMA()
58 static int dma_disabled;
62 pr_info(
"User-space DMA is disabled\n");
69 #define IRET_ERROR (1U << 31)
70 #define MT_ERROR (1U << 30)
71 #define MF_ERROR (1U << 29)
72 #define SPR_INDEX ((1U << 15) - 1)
73 #define SPR_MPL_SHIFT 9
79 static int retry_gpv(
unsigned int gpv_reason)
83 if (gpv_reason & IRET_ERROR)
86 BUG_ON((gpv_reason & (MT_ERROR|MF_ERROR)) == 0);
87 mpl = (gpv_reason & SPR_INDEX) >> SPR_MPL_SHIFT;
93 current->thread.tile_dma_state.enabled = 1;
104 #define bundle_bits tilegx_bundle_bits
106 #define bundle_bits tile_bundle_bits
111 asm(
".pushsection .rodata.bpt_code,\"a\";"
114 ".size bpt_code,.-bpt_code;"
117 static int special_ill(
bundle_bits bundle,
int *sigp,
int *codep)
121 if (bundle == bpt_code) {
149 if (get_Dest_X1(bundle) != 29 || get_SrcA_X1(bundle) != 37)
168 sig = get_Imm16_X0(bundle) & 0x3f;
188 code = (get_Imm16_X0(bundle) >> 6) & 0xf;
198 static const char *
const int_name[] = {
200 [
INT_ILL] =
"Illegal instruction",
201 [
INT_GPV] =
"General protection violation",
236 if (fault_num >= 0 &&
237 fault_num <
sizeof(int_name)/
sizeof(int_name[0]) &&
238 int_name[fault_num] !=
NULL)
239 name = int_name[fault_num];
241 name =
"Unknown interrupt";
242 pr_alert(
"Kernel took bad trap %d (%s) at PC %#lx\n",
243 fault_num, name, regs->
pc);
245 pr_alert(
"GPV_REASON is %#lx\n", reason);
259 pr_err(
"Unreadable instruction for INT_ILL:"
260 " %#lx\n", regs->
pc);
264 if (!special_ill(instr, &signo, &code)) {
271 #if CHIP_HAS_TILE_DMA()
272 if (retry_gpv(reason))
336 panic(
"Unexpected do_trap interrupt number %d", fault_num);
342 info.si_addr = (
void __user *)address;
344 info.si_trapno = fault_num;
353 pr_emerg(
"Double fault: exiting\n");