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

嵌入式Linux

开发平台:

Unix_Linux

  1. #include <linux/init.h>
  2. #include <linux/types.h>
  3. #include <linux/kernel.h>
  4. #include <linux/sched.h>
  5. #include <asm/processor.h> 
  6. #include <asm/msr.h>
  7. static int mce_disabled __initdata = 0;
  8. /*
  9.  * Machine Check Handler For PII/PIII
  10.  */
  11. static int banks;
  12. static void intel_machine_check(struct pt_regs * regs, long error_code)
  13. {
  14. int recover=1;
  15. u32 alow, ahigh, high, low;
  16. u32 mcgstl, mcgsth;
  17. int i;
  18. rdmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth);
  19. if(mcgstl&(1<<0)) /* Recoverable ? */
  20. recover=0;
  21. printk(KERN_EMERG "CPU %d: Machine Check Exception: %08x%08xn", smp_processor_id(), mcgsth, mcgstl);
  22. for(i=0;i<banks;i++)
  23. {
  24. rdmsr(MSR_IA32_MC0_STATUS+i*4,low, high);
  25. if(high&(1<<31))
  26. {
  27. if(high&(1<<29))
  28. recover|=1;
  29. if(high&(1<<25))
  30. recover|=2;
  31. printk(KERN_EMERG "Bank %d: %08x%08x", i, high, low);
  32. high&=~(1<<31);
  33. if(high&(1<<27))
  34. {
  35. rdmsr(MSR_IA32_MC0_MISC+i*4, alow, ahigh);
  36. printk("[%08x%08x]", alow, ahigh);
  37. }
  38. if(high&(1<<26))
  39. {
  40. rdmsr(MSR_IA32_MC0_ADDR+i*4, alow, ahigh);
  41. printk(" at %08x%08x", 
  42. high, low);
  43. }
  44. printk("n");
  45. /* Clear it */
  46. wrmsr(MSR_IA32_MC0_STATUS+i*4, 0UL, 0UL);
  47. /* Serialize */
  48. wmb();
  49. }
  50. }
  51. if(recover&2)
  52. panic("CPU context corrupt");
  53. if(recover&1)
  54. panic("Unable to continue");
  55. printk(KERN_EMERG "Attempting to continue.n");
  56. mcgstl&=~(1<<2);
  57. wrmsr(MSR_IA32_MCG_STATUS,mcgstl, mcgsth);
  58. }
  59. /*
  60.  * Machine check handler for Pentium class Intel
  61.  */
  62.  
  63. static void pentium_machine_check(struct pt_regs * regs, long error_code)
  64. {
  65. u32 loaddr, hi, lotype;
  66. rdmsr(MSR_IA32_P5_MC_ADDR, loaddr, hi);
  67. rdmsr(MSR_IA32_P5_MC_TYPE, lotype, hi);
  68. printk(KERN_EMERG "CPU#%d: Machine Check Exception:  0x%8X (type 0x%8X).n", smp_processor_id(), loaddr, lotype);
  69. if(lotype&(1<<5))
  70. printk(KERN_EMERG "CPU#%d: Possible thermal failure (CPU on fire ?).n", smp_processor_id());
  71. }
  72. /*
  73.  * Machine check handler for WinChip C6
  74.  */
  75.  
  76. static void winchip_machine_check(struct pt_regs * regs, long error_code)
  77. {
  78. printk(KERN_EMERG "CPU#%d: Machine Check Exception.n", smp_processor_id());
  79. }
  80. /*
  81.  * Handle unconfigured int18 (should never happen)
  82.  */
  83. static void unexpected_machine_check(struct pt_regs * regs, long error_code)
  84. {
  85. printk(KERN_ERR "CPU#%d: Unexpected int18 (Machine Check).n", smp_processor_id());
  86. }
  87. /*
  88.  * Call the installed machine check handler for this CPU setup.
  89.  */
  90. static void (*machine_check_vector)(struct pt_regs *, long error_code) = unexpected_machine_check;
  91. asmlinkage void do_machine_check(struct pt_regs * regs, long error_code)
  92. {
  93. machine_check_vector(regs, error_code);
  94. }
  95. /*
  96.  * Set up machine check reporting for Intel processors
  97.  */
  98. static void __init intel_mcheck_init(struct cpuinfo_x86 *c)
  99. {
  100. u32 l, h;
  101. int i;
  102. static int done;
  103. /*
  104.  * Check for MCE support
  105.  */
  106. if( !test_bit(X86_FEATURE_MCE, &c->x86_capability) )
  107. return;
  108. /*
  109.  * Pentium machine check
  110.  */
  111. if(c->x86 == 5)
  112. {
  113. /* Default P5 to off as its often misconnected */
  114. if(mce_disabled != -1)
  115. return;
  116. machine_check_vector = pentium_machine_check;
  117. wmb();
  118. /* Read registers before enabling */
  119. rdmsr(MSR_IA32_P5_MC_ADDR, l, h);
  120. rdmsr(MSR_IA32_P5_MC_TYPE, l, h);
  121. if(done==0)
  122. printk(KERN_INFO "Intel old style machine check architecture supported.n");
  123.   /* Enable MCE */
  124. set_in_cr4(X86_CR4_MCE);
  125. printk(KERN_INFO "Intel old style machine check reporting enabled on CPU#%d.n", smp_processor_id());
  126. return;
  127. }
  128. /*
  129.  * Check for PPro style MCA
  130.  */
  131.  
  132. if( !test_bit(X86_FEATURE_MCA, &c->x86_capability) )
  133. return;
  134. /* Ok machine check is available */
  135. machine_check_vector = intel_machine_check;
  136. wmb();
  137. if(done==0)
  138. printk(KERN_INFO "Intel machine check architecture supported.n");
  139. rdmsr(MSR_IA32_MCG_CAP, l, h);
  140. if(l&(1<<8))
  141. wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff);
  142. banks = l&0xff;
  143. for(i=1;i<banks;i++)
  144. {
  145. wrmsr(MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff);
  146. }
  147. for(i=0;i<banks;i++)
  148. {
  149. wrmsr(MSR_IA32_MC0_STATUS+4*i, 0x0, 0x0);
  150. }
  151. set_in_cr4(X86_CR4_MCE);
  152. printk(KERN_INFO "Intel machine check reporting enabled on CPU#%d.n", smp_processor_id());
  153. done=1;
  154. }
  155. /*
  156.  * Set up machine check reporting on the Winchip C6 series
  157.  */
  158.  
  159. static void __init winchip_mcheck_init(struct cpuinfo_x86 *c)
  160. {
  161. u32 lo, hi;
  162. /* Not supported on C3 */
  163. if(c->x86 != 5)
  164. return;
  165. /* Winchip C6 */
  166. machine_check_vector = winchip_machine_check;
  167. wmb();
  168. rdmsr(MSR_IDT_FCR1, lo, hi);
  169. lo|= (1<<2); /* Enable EIERRINT (int 18 MCE) */
  170. lo&= ~(1<<4); /* Enable MCE */
  171. wrmsr(MSR_IDT_FCR1, lo, hi);
  172. set_in_cr4(X86_CR4_MCE);
  173. printk(KERN_INFO "Winchip machine check reporting enabled on CPU#%d.n", smp_processor_id());
  174. }
  175. /*
  176.  * This has to be run for each processor
  177.  */
  178. void __init mcheck_init(struct cpuinfo_x86 *c)
  179. {
  180. if(mce_disabled==1)
  181. return;
  182. switch(c->x86_vendor)
  183. {
  184. case X86_VENDOR_AMD:
  185. /*
  186.  * AMD K7 machine check is Intel like
  187.  */
  188. if(c->x86 == 6)
  189. intel_mcheck_init(c);
  190. break;
  191. case X86_VENDOR_INTEL:
  192. intel_mcheck_init(c);
  193. break;
  194. case X86_VENDOR_CENTAUR:
  195. winchip_mcheck_init(c);
  196. break;
  197. default:
  198. break;
  199. }
  200. }
  201. static int __init mcheck_disable(char *str)
  202. {
  203. mce_disabled = 1;
  204. return 0;
  205. }
  206. static int __init mcheck_enable(char *str)
  207. {
  208. mce_disabled = -1;
  209. return 0;
  210. }
  211. __setup("nomce", mcheck_disable);
  212. __setup("mce", mcheck_enable);