traps.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:18k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *  arch/s390/kernel/traps.c
  3.  *
  4.  *  S390 version
  5.  *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  6.  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  7.  *               Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
  8.  *
  9.  *  Derived from "arch/i386/kernel/traps.c"
  10.  *    Copyright (C) 1991, 1992 Linus Torvalds
  11.  */
  12. /*
  13.  * 'Traps.c' handles hardware traps and faults after we have saved some
  14.  * state in 'asm.s'.
  15.  */
  16. #include <linux/config.h>
  17. #include <linux/sched.h>
  18. #include <linux/kernel.h>
  19. #include <linux/string.h>
  20. #include <linux/errno.h>
  21. #include <linux/ptrace.h>
  22. #include <linux/timer.h>
  23. #include <linux/mm.h>
  24. #include <linux/smp.h>
  25. #include <linux/smp_lock.h>
  26. #include <linux/init.h>
  27. #include <linux/delay.h>
  28. #include <linux/module.h>
  29. #include <asm/system.h>
  30. #include <asm/uaccess.h>
  31. #include <asm/io.h>
  32. #include <asm/atomic.h>
  33. #include <asm/mathemu.h>
  34. #include <asm/cpcmd.h>
  35. #include <asm/s390_ext.h>
  36. /* Called from entry.S only */
  37. extern void handle_per_exception(struct pt_regs *regs);
  38. typedef void pgm_check_handler_t(struct pt_regs *, long);
  39. pgm_check_handler_t *pgm_check_table[128];
  40. #ifdef CONFIG_SYSCTL
  41. #ifdef CONFIG_PROCESS_DEBUG
  42. int sysctl_userprocess_debug = 1;
  43. #else
  44. int sysctl_userprocess_debug = 0;
  45. #endif
  46. #endif
  47. extern pgm_check_handler_t do_page_fault;
  48. extern pgm_check_handler_t do_pseudo_page_fault;
  49. #ifdef CONFIG_PFAULT
  50. extern int pfault_init(void);
  51. extern void pfault_fini(void);
  52. extern void pfault_interrupt(struct pt_regs *regs, __u16 error_code);
  53. #endif
  54. int kstack_depth_to_print = 12;
  55. /*
  56.  * If the address is either in the .text section of the
  57.  * kernel, or in the vmalloc'ed module regions, it *may* 
  58.  * be the address of a calling routine
  59.  */
  60. extern char _stext, _etext;
  61. #ifdef CONFIG_MODULES
  62. extern struct module *module_list;
  63. extern struct module kernel_module;
  64. static inline int kernel_text_address(unsigned long addr)
  65. {
  66. int retval = 0;
  67. struct module *mod;
  68. if (addr >= (unsigned long) &_stext &&
  69.     addr <= (unsigned long) &_etext)
  70. return 1;
  71. for (mod = module_list; mod != &kernel_module; mod = mod->next) {
  72. /* mod_bound tests for addr being inside the vmalloc'ed
  73.  * module area. Of course it'd be better to test only
  74.  * for the .text subset... */
  75. if (mod_bound(addr, 0, mod)) {
  76. retval = 1;
  77. break;
  78. }
  79. }
  80. return retval;
  81. }
  82. #else
  83. static inline int kernel_text_address(unsigned long addr)
  84. {
  85. return (addr >= (unsigned long) &_stext &&
  86. addr <= (unsigned long) &_etext);
  87. }
  88. #endif
  89. void show_trace(unsigned long * stack)
  90. {
  91. unsigned long backchain, low_addr, high_addr, ret_addr;
  92. int i;
  93. if (!stack)
  94. stack = (unsigned long*)&stack;
  95. printk("Call Trace: ");
  96. low_addr = ((unsigned long) stack) & PSW_ADDR_MASK;
  97. high_addr = (low_addr & (-THREAD_SIZE)) + THREAD_SIZE;
  98. /* Skip the first frame (biased stack) */
  99. backchain = *((unsigned long *) low_addr) & PSW_ADDR_MASK;
  100. /* Print up to 8 lines */
  101. for (i = 0; i < 8; i++) {
  102. if (backchain < low_addr || backchain >= high_addr)
  103. break;
  104. ret_addr = *((unsigned long *) (backchain+56)) & PSW_ADDR_MASK;
  105. if (!kernel_text_address(ret_addr))
  106. break;
  107. if (i && ((i % 6) == 0))
  108. printk("n   ");
  109. printk("[<%08lx>] ", ret_addr);
  110. low_addr = backchain;
  111. backchain = *((unsigned long *) backchain) & PSW_ADDR_MASK;
  112. }
  113. printk("n");
  114. }
  115. void show_trace_task(struct task_struct *tsk)
  116. {
  117. /*
  118.  * We can't print the backtrace of a running process. It is
  119.  * unreliable at best and can cause kernel oopses.
  120.  */
  121. if (task_has_cpu(tsk))
  122. return;
  123. show_trace((unsigned long *) tsk->thread.ksp);
  124. }
  125. void show_stack(unsigned long *sp)
  126. {
  127. unsigned long *stack;
  128. int i;
  129. // debugging aid: "show_stack(NULL);" prints the
  130. // back trace for this cpu.
  131. if(sp == NULL)
  132. sp = (unsigned long*) &sp;
  133. stack = sp;
  134. for (i = 0; i < kstack_depth_to_print; i++) {
  135. if (((addr_t) stack & (THREAD_SIZE-1)) == 0)
  136. break;
  137. if (i && ((i % 8) == 0))
  138. printk("n       ");
  139. printk("%08lx ", *stack++);
  140. }
  141. printk("n");
  142. show_trace(sp);
  143. }
  144. void show_registers(struct pt_regs *regs)
  145. {
  146. mm_segment_t old_fs;
  147. char *mode;
  148. int i;
  149. mode = (regs->psw.mask & PSW_PROBLEM_STATE) ? "User" : "Krnl";
  150. printk("%s PSW : %08lx %08lxn",
  151.        mode, (unsigned long) regs->psw.mask,
  152.        (unsigned long) regs->psw.addr);
  153. printk("%s GPRS: %08x %08x %08x %08xn", mode,
  154.        regs->gprs[0], regs->gprs[1], regs->gprs[2], regs->gprs[3]);
  155. printk("           %08x %08x %08x %08xn",
  156.        regs->gprs[4], regs->gprs[5], regs->gprs[6], regs->gprs[7]);
  157. printk("           %08x %08x %08x %08xn",
  158.        regs->gprs[8], regs->gprs[9], regs->gprs[10], regs->gprs[11]);
  159. printk("           %08x %08x %08x %08xn",
  160.        regs->gprs[12], regs->gprs[13], regs->gprs[14], regs->gprs[15]);
  161. printk("%s ACRS: %08x %08x %08x %08xn", mode,
  162.        regs->acrs[0], regs->acrs[1], regs->acrs[2], regs->acrs[3]);
  163. printk("           %08x %08x %08x %08xn",
  164.        regs->acrs[4], regs->acrs[5], regs->acrs[6], regs->acrs[7]);
  165. printk("           %08x %08x %08x %08xn",
  166.        regs->acrs[8], regs->acrs[9], regs->acrs[10], regs->acrs[11]);
  167. printk("           %08x %08x %08x %08xn",
  168.        regs->acrs[12], regs->acrs[13], regs->acrs[14], regs->acrs[15]);
  169. /*
  170.  * Print the first 20 byte of the instruction stream at the
  171.  * time of the fault.
  172.  */
  173. old_fs = get_fs();
  174. if (regs->psw.mask & PSW_PROBLEM_STATE)
  175. set_fs(USER_DS);
  176. else
  177. set_fs(KERNEL_DS);
  178. printk("%s Code: ", mode);
  179. for (i = 0; i < 20; i++) {
  180. unsigned char c;
  181. if (__get_user(c, (char *)(regs->psw.addr + i))) {
  182. printk(" Bad PSW.");
  183. break;
  184. }
  185. printk("%02x ", c);
  186. }
  187. set_fs(old_fs);
  188. printk("n");
  189. }
  190. /* This is called from fs/proc/array.c */
  191. char *task_show_regs(struct task_struct *task, char *buffer)
  192. {
  193. struct pt_regs *regs;
  194. regs = __KSTK_PTREGS(task);
  195. buffer += sprintf(buffer, "task: %08lx, ksp: %08xn",
  196.   (unsigned long) task, task->thread.ksp);
  197. buffer += sprintf(buffer, "User PSW : %08lx %08lxn",
  198.   (unsigned long) regs->psw.mask, 
  199.   (unsigned long) regs->psw.addr);
  200. buffer += sprintf(buffer, "User GPRS: %08x %08x %08x %08xn",
  201.   regs->gprs[0], regs->gprs[1],
  202.   regs->gprs[2], regs->gprs[3]);
  203. buffer += sprintf(buffer, "           %08x %08x %08x %08xn",
  204.   regs->gprs[4], regs->gprs[5],
  205.   regs->gprs[6], regs->gprs[7]);
  206. buffer += sprintf(buffer, "           %08x %08x %08x %08xn",
  207.   regs->gprs[8], regs->gprs[9],
  208.   regs->gprs[10], regs->gprs[11]);
  209. buffer += sprintf(buffer, "           %08x %08x %08x %08xn",
  210.   regs->gprs[12], regs->gprs[13],
  211.   regs->gprs[14], regs->gprs[15]);
  212. buffer += sprintf(buffer, "User ACRS: %08x %08x %08x %08xn",
  213.   regs->acrs[0], regs->acrs[1],
  214.   regs->acrs[2], regs->acrs[3]);
  215. buffer += sprintf(buffer, "           %08x %08x %08x %08xn",
  216.   regs->acrs[4], regs->acrs[5],
  217.   regs->acrs[6], regs->acrs[7]);
  218. buffer += sprintf(buffer, "           %08x %08x %08x %08xn",
  219.   regs->acrs[8], regs->acrs[9],
  220.   regs->acrs[10], regs->acrs[11]);
  221. buffer += sprintf(buffer, "           %08x %08x %08x %08xn",
  222.   regs->acrs[12], regs->acrs[13],
  223.   regs->acrs[14], regs->acrs[15]);
  224. return buffer;
  225. }
  226. spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
  227. void die(const char * str, struct pt_regs * regs, long err)
  228. {
  229.         console_verbose();
  230.         spin_lock_irq(&die_lock);
  231. bust_spinlocks(1);
  232.         printk("%s: %04lxn", str, err & 0xffff);
  233.         show_regs(regs);
  234. bust_spinlocks(0);
  235.         spin_unlock_irq(&die_lock);
  236.         do_exit(SIGSEGV);
  237. }
  238. #define DO_ERROR(signr, str, name) 
  239. asmlinkage void name(struct pt_regs * regs, long interruption_code) 
  240. do_trap(interruption_code, signr, str, regs, NULL); 
  241. }
  242. #define DO_ERROR_INFO(signr, str, name, sicode, siaddr) 
  243. asmlinkage void name(struct pt_regs * regs, long interruption_code) 
  244.         siginfo_t info; 
  245.         info.si_signo = signr; 
  246.         info.si_errno = 0; 
  247.         info.si_code = sicode; 
  248.         info.si_addr = (void *)siaddr; 
  249.         do_trap(interruption_code, signr, str, regs, &info); 
  250. }
  251. static void inline do_trap(long interruption_code, int signr, char *str,
  252.                            struct pt_regs *regs, siginfo_t *info)
  253. {
  254. /*
  255.  * We got all needed information from the lowcore and can
  256.  * now safely switch on interrupts.
  257.  */
  258.         if (regs->psw.mask & PSW_PROBLEM_STATE)
  259. __sti();
  260.         if (regs->psw.mask & PSW_PROBLEM_STATE) {
  261.                 struct task_struct *tsk = current;
  262.                 tsk->thread.trap_no = interruption_code;
  263. if (info)
  264. force_sig_info(signr, info, tsk);
  265. else
  266.                  force_sig(signr, tsk);
  267. #ifndef CONFIG_SYSCTL
  268. #ifdef CONFIG_PROCESS_DEBUG
  269.                 printk("User process fault: interruption code 0x%lXn",
  270.                        interruption_code);
  271.                 show_regs(regs);
  272. #endif
  273. #else
  274. if (sysctl_userprocess_debug) {
  275. printk("User process fault: interruption code 0x%lXn",
  276.        interruption_code);
  277. show_regs(regs);
  278. }
  279. #endif
  280.         } else {
  281.                 unsigned long fixup = search_exception_table(regs->psw.addr);
  282.                 if (fixup)
  283.                         regs->psw.addr = fixup;
  284.                 else
  285.                         die(str, regs, interruption_code);
  286.         }
  287. }
  288. int do_debugger_trap(struct pt_regs *regs,int signal)
  289. {
  290. if(regs->psw.mask&PSW_PROBLEM_STATE)
  291. {
  292. if(current->ptrace & PT_PTRACED)
  293. force_sig(signal,current);
  294. else
  295. return 1;
  296. }
  297. else
  298. {
  299. #if CONFIG_REMOTE_DEBUG
  300. if(gdb_stub_initialised)
  301. {
  302. gdb_stub_handle_exception(regs, signal);
  303. return 0;
  304. }
  305. #endif
  306. return 1;
  307. }
  308. return 0;
  309. }
  310. DO_ERROR(SIGSEGV, "Unknown program exception", default_trap_handler)
  311. DO_ERROR(SIGILL,  "privileged operation", privileged_op)
  312. DO_ERROR(SIGILL,  "execute exception", execute_exception)
  313. DO_ERROR(SIGSEGV, "addressing exception", addressing_exception)
  314. DO_ERROR(SIGFPE,  "fixpoint divide exception", divide_exception)
  315. DO_ERROR(SIGILL,  "translation exception", translation_exception)
  316. DO_ERROR(SIGILL,  "special operand exception", special_op_exception)
  317. DO_ERROR(SIGILL,  "operand exception", operand_exception)
  318. asmlinkage void illegal_op(struct pt_regs * regs, long interruption_code)
  319. {
  320.         __u8 opcode[6];
  321. __u16 *location;
  322. int signal = 0;
  323. location = (__u16 *)(regs->psw.addr-S390_lowcore.pgm_ilc);
  324. /*
  325.  * We got all needed information from the lowcore and can
  326.  * now safely switch on interrupts.
  327.  */
  328. if (regs->psw.mask & PSW_PROBLEM_STATE)
  329. __sti();
  330. if (regs->psw.mask & PSW_PROBLEM_STATE)
  331. get_user(*((__u16 *) opcode), location);
  332. else
  333. *((__u16 *)opcode)=*((__u16 *)location);
  334. if (*((__u16 *)opcode)==S390_BREAKPOINT_U16)
  335.         {
  336. if(do_debugger_trap(regs,SIGTRAP))
  337. signal = SIGILL;
  338. }
  339. #ifdef CONFIG_MATHEMU
  340.         else if (regs->psw.mask & PSW_PROBLEM_STATE)
  341. {
  342. if (opcode[0] == 0xb3) {
  343. get_user(*((__u16 *) (opcode+2)), location+1);
  344. signal = math_emu_b3(opcode, regs);
  345.                 } else if (opcode[0] == 0xed) {
  346. get_user(*((__u32 *) (opcode+2)),
  347.  (__u32 *)(location+1));
  348. signal = math_emu_ed(opcode, regs);
  349. } else if (*((__u16 *) opcode) == 0xb299) {
  350. get_user(*((__u16 *) (opcode+2)), location+1);
  351. signal = math_emu_srnm(opcode, regs);
  352. } else if (*((__u16 *) opcode) == 0xb29c) {
  353. get_user(*((__u16 *) (opcode+2)), location+1);
  354. signal = math_emu_stfpc(opcode, regs);
  355. } else if (*((__u16 *) opcode) == 0xb29d) {
  356. get_user(*((__u16 *) (opcode+2)), location+1);
  357. signal = math_emu_lfpc(opcode, regs);
  358. } else
  359. signal = SIGILL;
  360.         }
  361. #endif 
  362. else
  363. signal = SIGILL;
  364.         if (signal == SIGFPE) {
  365. current->thread.ieee_instruction_pointer = (addr_t) location;
  366. do_trap(interruption_code, signal,
  367. "floating point exception", regs, NULL);
  368.         } else if (signal)
  369. do_trap(interruption_code, signal,
  370. "illegal operation", regs, NULL);
  371. }
  372. #ifdef CONFIG_MATHEMU
  373. asmlinkage void 
  374. specification_exception(struct pt_regs * regs, long interruption_code)
  375. {
  376.         __u8 opcode[6];
  377. __u16 *location = NULL;
  378. int signal = 0;
  379. location = (__u16 *)(regs->psw.addr-S390_lowcore.pgm_ilc);
  380. /*
  381.  * We got all needed information from the lowcore and can
  382.  * now safely switch on interrupts.
  383.  */
  384. if (regs->psw.mask & PSW_PROBLEM_STATE)
  385. __sti();
  386.         if (regs->psw.mask & PSW_PROBLEM_STATE) {
  387. get_user(*((__u16 *) opcode), location);
  388. switch (opcode[0]) {
  389. case 0x28: /* LDR Rx,Ry   */
  390. signal = math_emu_ldr(opcode);
  391. break;
  392. case 0x38: /* LER Rx,Ry   */
  393. signal = math_emu_ler(opcode);
  394. break;
  395. case 0x60: /* STD R,D(X,B) */
  396. get_user(*((__u16 *) (opcode+2)), location+1);
  397. signal = math_emu_std(opcode, regs);
  398. break;
  399. case 0x68: /* LD R,D(X,B) */
  400. get_user(*((__u16 *) (opcode+2)), location+1);
  401. signal = math_emu_ld(opcode, regs);
  402. break;
  403. case 0x70: /* STE R,D(X,B) */
  404. get_user(*((__u16 *) (opcode+2)), location+1);
  405. signal = math_emu_ste(opcode, regs);
  406. break;
  407. case 0x78: /* LE R,D(X,B) */
  408. get_user(*((__u16 *) (opcode+2)), location+1);
  409. signal = math_emu_le(opcode, regs);
  410. break;
  411. default:
  412. signal = SIGILL;
  413. break;
  414.                 }
  415.         } else
  416. signal = SIGILL;
  417.         if (signal == SIGFPE) {
  418. current->thread.ieee_instruction_pointer = (addr_t) location;
  419. do_trap(interruption_code, signal,
  420. "floating point exception", regs, NULL);
  421.         } else if (signal)
  422.                 do_trap(interruption_code, signal,
  423. "specification exception", regs, NULL);
  424. }
  425. #else
  426. DO_ERROR(SIGILL, "specification exception", specification_exception)
  427. #endif
  428. asmlinkage void data_exception(struct pt_regs * regs, long interruption_code)
  429. {
  430.         __u8 opcode[6];
  431. __u16 *location;
  432. int signal = 0;
  433. location = (__u16 *)(regs->psw.addr-S390_lowcore.pgm_ilc);
  434. /*
  435.  * We got all needed information from the lowcore and can
  436.  * now safely switch on interrupts.
  437.  */
  438. if (regs->psw.mask & PSW_PROBLEM_STATE)
  439. __sti();
  440. if (MACHINE_HAS_IEEE)
  441. __asm__ volatile ("stfpc %0nt" 
  442.   : "=m" (current->thread.fp_regs.fpc));
  443. #ifdef CONFIG_MATHEMU
  444.         else if (regs->psw.mask & PSW_PROBLEM_STATE) {
  445. get_user(*((__u16 *) opcode), location);
  446. switch (opcode[0]) {
  447. case 0x28: /* LDR Rx,Ry   */
  448. signal = math_emu_ldr(opcode);
  449. break;
  450. case 0x38: /* LER Rx,Ry   */
  451. signal = math_emu_ler(opcode);
  452. break;
  453. case 0x60: /* STD R,D(X,B) */
  454. get_user(*((__u16 *) (opcode+2)), location+1);
  455. signal = math_emu_std(opcode, regs);
  456. break;
  457. case 0x68: /* LD R,D(X,B) */
  458. get_user(*((__u16 *) (opcode+2)), location+1);
  459. signal = math_emu_ld(opcode, regs);
  460. break;
  461. case 0x70: /* STE R,D(X,B) */
  462. get_user(*((__u16 *) (opcode+2)), location+1);
  463. signal = math_emu_ste(opcode, regs);
  464. break;
  465. case 0x78: /* LE R,D(X,B) */
  466. get_user(*((__u16 *) (opcode+2)), location+1);
  467. signal = math_emu_le(opcode, regs);
  468. break;
  469. case 0xb3:
  470. get_user(*((__u16 *) (opcode+2)), location+1);
  471. signal = math_emu_b3(opcode, regs);
  472. break;
  473.                 case 0xed:
  474. get_user(*((__u32 *) (opcode+2)),
  475.  (__u32 *)(location+1));
  476. signal = math_emu_ed(opcode, regs);
  477. break;
  478.         case 0xb2:
  479. if (opcode[1] == 0x99) {
  480. get_user(*((__u16 *) (opcode+2)), location+1);
  481. signal = math_emu_srnm(opcode, regs);
  482. } else if (opcode[1] == 0x9c) {
  483. get_user(*((__u16 *) (opcode+2)), location+1);
  484. signal = math_emu_stfpc(opcode, regs);
  485. } else if (opcode[1] == 0x9d) {
  486. get_user(*((__u16 *) (opcode+2)), location+1);
  487. signal = math_emu_lfpc(opcode, regs);
  488. } else
  489. signal = SIGILL;
  490. break;
  491. default:
  492. signal = SIGILL;
  493. break;
  494.                 }
  495.         }
  496. #endif 
  497. if (current->thread.fp_regs.fpc & FPC_DXC_MASK)
  498. signal = SIGFPE;
  499. else
  500. signal = SIGILL;
  501.         if (signal == SIGFPE) {
  502. current->thread.ieee_instruction_pointer = (addr_t) location;
  503. do_trap(interruption_code, signal,
  504. "floating point exception", regs, NULL);
  505. } else if (signal) 
  506.                 do_trap(interruption_code, signal,
  507. "data exception", regs, NULL);
  508. }
  509. /* init is done in lowcore.S and head.S */
  510. void __init trap_init(void)
  511. {
  512.         int i;
  513.         for (i = 0; i < 128; i++)
  514.           pgm_check_table[i] = &default_trap_handler;
  515.         pgm_check_table[1] = &illegal_op;
  516.         pgm_check_table[2] = &privileged_op;
  517.         pgm_check_table[3] = &execute_exception;
  518.         pgm_check_table[4] = &do_page_fault;
  519.         pgm_check_table[5] = &addressing_exception;
  520.         pgm_check_table[6] = &specification_exception;
  521.         pgm_check_table[7] = &data_exception;
  522.         pgm_check_table[9] = &divide_exception;
  523.         pgm_check_table[0x10] = &do_page_fault;
  524.         pgm_check_table[0x11] = &do_page_fault;
  525.         pgm_check_table[0x12] = &translation_exception;
  526.         pgm_check_table[0x13] = &special_op_exception;
  527.   pgm_check_table[0x14] = &do_pseudo_page_fault;
  528.         pgm_check_table[0x15] = &operand_exception;
  529.         pgm_check_table[0x1C] = &privileged_op;
  530. #ifdef CONFIG_PFAULT
  531. if (MACHINE_IS_VM) {
  532. /* request the 0x2603 external interrupt */
  533. if (register_external_interrupt(0x2603, pfault_interrupt) != 0)
  534. panic("Couldn't request external interrupt 0x2603");
  535. /*
  536.  * First try to get pfault pseudo page faults going.
  537.  * If this isn't available turn on pagex page faults.
  538.  */
  539. if (pfault_init() != 0) {
  540. /* Tough luck, no pfault. */
  541. unregister_external_interrupt(0x2603,
  542.       pfault_interrupt);
  543. cpcmd("SET PAGEX ON", NULL, 0);
  544. }
  545. }
  546. #else
  547. if (MACHINE_IS_VM)
  548. cpcmd("SET PAGEX ON", NULL, 0);
  549. #endif
  550. }
  551. void handle_per_exception(struct pt_regs *regs)
  552. {
  553. if(regs->psw.mask&PSW_PROBLEM_STATE)
  554. {
  555. per_struct *per_info=&current->thread.per_info;
  556. per_info->lowcore.words.perc_atmid=S390_lowcore.per_perc_atmid;
  557. per_info->lowcore.words.address=S390_lowcore.per_address;
  558. per_info->lowcore.words.access_id=S390_lowcore.per_access_id;
  559. }
  560. if(do_debugger_trap(regs,SIGTRAP))
  561. {
  562. /* I've seen this possibly a task structure being reused ? */
  563. printk("Spurious per exception detectedn");
  564. printk("switching off per tracing for this task.n");
  565. show_regs(regs);
  566. /* Hopefully switching off per tracing will help us survive */
  567. regs->psw.mask &= ~PSW_PER_MASK;
  568. }
  569. }