Coverage Report

Created: 2017-10-25 09:10

/root/src/xen/xen/arch/x86/cpu/mcheck/non-fatal.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Non Fatal Machine Check Exception Reporting
3
 *
4
 * (C) Copyright 2002 Dave Jones. <davej@codemonkey.org.uk>
5
 *
6
 * This file contains routines to check for non-fatal MCEs every 15s
7
 *
8
 */
9
10
#include <xen/init.h>
11
#include <xen/types.h>
12
#include <xen/kernel.h>
13
#include <xen/smp.h>
14
#include <xen/timer.h>
15
#include <xen/errno.h>
16
#include <xen/event.h>
17
#include <xen/sched.h>
18
#include <asm/processor.h> 
19
#include <asm/system.h>
20
#include <asm/msr.h>
21
22
#include "mce.h"
23
#include "vmce.h"
24
25
static struct timer mce_timer;
26
27
1
#define MCE_PERIOD MILLISECS(8000)
28
6
#define MCE_PERIOD_MIN MILLISECS(2000)
29
11
#define MCE_PERIOD_MAX MILLISECS(16000)
30
31
static uint64_t period = MCE_PERIOD;
32
static int adjust = 0;
33
static int variable_period = 1;
34
35
static void mce_checkregs (void *info)
36
44
{
37
44
  mctelem_cookie_t mctc;
38
44
  struct mca_summary bs;
39
44
  static uint64_t dumpcount = 0;
40
44
41
44
  mctc = mcheck_mca_logout(MCA_POLLER, __get_cpu_var(poll_bankmask), &bs, NULL);
42
44
43
44
  if (bs.errcnt && mctc != NULL) {
44
0
    adjust++;
45
0
46
0
    /* If Dom0 enabled the VIRQ_MCA event, then notify it.
47
0
     * Otherwise, if dom0 has had plenty of time to register
48
0
     * the virq handler but still hasn't then dump telemetry
49
0
     * to the Xen console.  The call count may be incremented
50
0
     * on multiple cpus at once and is indicative only - just
51
0
     * a simple-minded attempt to avoid spamming the console
52
0
     * for corrected errors in early startup.
53
0
     */
54
0
55
0
    if (dom0_vmce_enabled()) {
56
0
      mctelem_commit(mctc);
57
0
      send_global_virq(VIRQ_MCA);
58
0
    } else if (++dumpcount >= 10) {
59
0
      x86_mcinfo_dump((struct mc_info *)mctelem_dataptr(mctc));
60
0
      mctelem_dismiss(mctc);
61
0
    } else {
62
0
      mctelem_dismiss(mctc);
63
0
    }
64
44
  } else if (mctc != NULL) {
65
0
    mctelem_dismiss(mctc);
66
0
  }
67
44
}
68
69
static void mce_work_fn(void *data)
70
6
{ 
71
6
  on_each_cpu(mce_checkregs, NULL, 1);
72
6
73
6
  if (variable_period) {
74
6
    if (adjust)
75
0
      period /= (adjust + 1);
76
6
    else
77
6
      period *= 2;
78
6
    if (period > MCE_PERIOD_MAX)
79
5
      period = MCE_PERIOD_MAX;
80
6
    if (period < MCE_PERIOD_MIN)
81
0
      period = MCE_PERIOD_MIN;
82
6
  }
83
6
84
6
  set_timer(&mce_timer, NOW() + period);
85
6
  adjust = 0;
86
6
}
87
88
static int __init init_nonfatal_mce_checker(void)
89
1
{
90
1
  struct cpuinfo_x86 *c = &boot_cpu_data;
91
1
92
1
  /* Check for MCE support */
93
1
  if (!opt_mce || !mce_available(c))
94
0
    return -ENODEV;
95
1
96
1
  if (__get_cpu_var(poll_bankmask) == NULL)
97
0
    return -EINVAL;
98
1
99
1
  /*
100
1
   * Check for non-fatal errors every MCE_RATE s
101
1
   */
102
1
  switch (c->x86_vendor) {
103
0
  case X86_VENDOR_AMD:
104
0
    /* Assume we are on K8 or newer AMD CPU here */
105
0
    amd_nonfatal_mcheck_init(c);
106
0
    break;
107
0
108
1
  case X86_VENDOR_INTEL:
109
1
    init_timer(&mce_timer, mce_work_fn, NULL, 0);
110
1
    set_timer(&mce_timer, NOW() + MCE_PERIOD);
111
1
    break;
112
1
  }
113
1
114
1
  printk(KERN_INFO "mcheck_poll: Machine check polling timer started.\n");
115
1
  return 0;
116
1
}
117
__initcall(init_nonfatal_mce_checker);