1/**
2 * \file
3 * \brief x86 machine check architecture initialisation / "driver"
4 */
5
6/*
7 * Copyright (c) 2010, ETH Zurich.
8 * All rights reserved.
9 *
10 * This file is distributed under the terms in the attached LICENSE file.
11 * If you do not find this file, copies can be found by writing to:
12 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
13 */
14
15#include <kernel.h>
16#include <x86.h>
17#include <arch/x86/mcheck.h>
18#include <dev/ia32_dev.h>
19#include <dev/amd64_dev.h>
20
21/*
22 * The Intel Xeon Phi coprocessor does not support MCA as defined by the Intel
23 * Pentium Pro and later Intel processors. However, MCEs on the Intel Xeon Phi
24 * coprocessor are compatible with the Intel Pentium processor.
25 *
26 * TODO: There are additional MCE registers on the SBOXs
27 */
28
29/**
30 * \brief Enable machine check reporting for the Intel Xeon Phi
31 */
32void
33mcheck_init(void)
34{
35    // use CPUID to check for support and get processor family
36    uint32_t eax, edx;
37    cpuid(1, &eax, NULL, NULL, &edx);
38
39    uint8_t proc_family = (eax >> 8) & 0xf;
40
41    /*
42     *
43     * While the Intel Xeon Phi coprocessor does support MCA and MCE
44     * capabilities, the CPUID feature bits used to identify the processor
45     * supports for these features are not set on the Intel Xeon Phi coprocessor.
46     */
47
48    // if MCE unsupported, skip this entirely
49    debug(SUBSYS_STARTUP, "Machine-check exceptions supported\n");
50
51    debug(SUBSYS_STARTUP, "Machine-check architecture supported, "
52          "family 0x%x\n",
53          proc_family);
54
55    // if the ctl register is present, enable all MCA features
56    ia32_mcg_cap_t mcg_cap = ia32_mcg_cap_rd(NULL);
57
58    /*
59     * The Intel Xeon Phi coprocessor provides three MC MSR banks.
60     */
61    int num_banks = ia32_mcg_cap_count_extract(mcg_cap);
62
63    assert(num_banks == 3);
64
65    if (ia32_mcg_cap_ctl_p_extract(mcg_cap)) {
66        ia32_mcg_ctl_wr(NULL, ia32_mc_enable);
67    }
68
69    for (int i = 0; i < num_banks; i++) {
70        ia32_mc_ctl_wr(NULL, i, ia32_mc_enable);
71    }
72
73    // clear all errors
74    for (int i = 0; i < num_banks; i++) {
75        ia32_mc_status_wr(NULL, i, 0UL);
76    }
77
78    // enable machine-check exceptions
79    amd64_cr4_mce_wrf(NULL, 1);
80}
81