msm_fault_handlers.c 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. /*
  2. * Copyright (C) 1995 Linus Torvalds
  3. * Modifications for ARM processor (c) 1995-2004 Russell King
  4. * Copyright (c) 2010, The Linux Foundation. All rights reserved.
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation.
  9. */
  10. #include <linux/kernel.h>
  11. #include <linux/init.h>
  12. #include <linux/signal.h>
  13. #include <linux/cpumask.h>
  14. #include "acpuclock.h"
  15. #define __str(x) #x
  16. #define MRC(x, v1, v2, v4, v5, v6) do { \
  17. unsigned int __##x; \
  18. asm("mrc " __str(v1) ", " __str(v2) ", %0, " __str(v4) ", " \
  19. __str(v5) ", " __str(v6) "\n" \
  20. : "=r" (__##x)); \
  21. pr_info("%s: %s = 0x%.8x\n", __func__, #x, __##x); \
  22. } while (0)
  23. static int msm_imp_ext_abort(unsigned long addr, unsigned int fsr,
  24. struct pt_regs *regs)
  25. {
  26. int cpu;
  27. unsigned int regval;
  28. static unsigned char flush_toggle;
  29. asm("mrc p15, 7, %0, c15, c0, 1\n" /* read EFSR for fault status */
  30. : "=r" (regval));
  31. if (regval == 0x2) {
  32. /* Fault was caused by icache parity error. Alternate
  33. * simply retrying the access and flushing the icache. */
  34. flush_toggle ^= 1;
  35. if (flush_toggle)
  36. asm("mcr p15, 0, %0, c7, c5, 0\n"
  37. :
  38. : "r" (regval)); /* input value is ignored */
  39. /* Clear fault in EFSR. */
  40. asm("mcr p15, 7, %0, c15, c0, 1\n"
  41. :
  42. : "r" (regval));
  43. /* Clear fault in ADFSR. */
  44. regval = 0;
  45. asm("mcr p15, 0, %0, c5, c1, 0\n"
  46. :
  47. : "r" (regval));
  48. return 0;
  49. }
  50. MRC(ADFSR, p15, 0, c5, c1, 0);
  51. MRC(DFSR, p15, 0, c5, c0, 0);
  52. MRC(ACTLR, p15, 0, c1, c0, 1);
  53. MRC(EFSR, p15, 7, c15, c0, 1);
  54. MRC(L2SR, p15, 3, c15, c1, 0);
  55. MRC(L2CR0, p15, 3, c15, c0, 1);
  56. MRC(L2CPUESR, p15, 3, c15, c1, 1);
  57. MRC(L2CPUCR, p15, 3, c15, c0, 2);
  58. MRC(SPESR, p15, 1, c9, c7, 0);
  59. MRC(SPCR, p15, 0, c9, c7, 0);
  60. MRC(DMACHSR, p15, 1, c11, c0, 0);
  61. MRC(DMACHESR, p15, 1, c11, c0, 1);
  62. MRC(DMACHCR, p15, 0, c11, c0, 2);
  63. for_each_online_cpu(cpu)
  64. pr_info("cpu %d, acpuclk rate: %lu kHz\n", cpu,
  65. acpuclk_get_rate(cpu));
  66. return 1;
  67. }
  68. static int __init msm_register_fault_handlers(void)
  69. {
  70. /* hook in our handler for imprecise abort for when we get
  71. i-cache parity errors */
  72. hook_fault_code(22, msm_imp_ext_abort, SIGBUS, 0,
  73. "imprecise external abort");
  74. return 0;
  75. }
  76. arch_initcall(msm_register_fault_handlers);