Coverage Report

Created: 2017-10-25 09:10

/root/src/xen/xen/arch/x86/cpu/mcheck/mce_amd.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * common MCA implementation for AMD CPUs.
3
 * Copyright (c) 2012-2014 Advanced Micro Devices, Inc.
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; If not, see <http://www.gnu.org/licenses/>.
17
 */
18
19
/* K8 common MCA documentation published at
20
 *
21
 * AMD64 Architecture Programmer's Manual Volume 2:
22
 * System Programming
23
 * Publication # 24593 Revision: 3.24
24
 * Issue Date: October 2013
25
 *
26
 * URL:
27
 * http://support.amd.com/TechDocs/24593.pdf 
28
 */
29
30
/* The related documentation for K8 Revisions A - E is:
31
 *
32
 * BIOS and Kernel Developer's Guide for
33
 * AMD Athlon 64 and AMD Opteron Processors
34
 * Publication # 26094 Revision: 3.30
35
 * Issue Date: February 2006
36
 *
37
 * URL:
38
 * http://support.amd.com/TechDocs/26094.PDF 
39
 */
40
41
/* The related documentation for K8 Revisions F - G is:
42
 *
43
 * BIOS and Kernel Developer's Guide for
44
 * AMD NPT Family 0Fh Processors
45
 * Publication # 32559 Revision: 3.08
46
 * Issue Date: July 2007
47
 *
48
 * URL:
49
 * http://support.amd.com/TechDocs/32559.pdf 
50
 */
51
52
/* Family10 MCA documentation published at
53
 *
54
 * BIOS and Kernel Developer's Guide
55
 * For AMD Family 10h Processors
56
 * Publication # 31116 Revision: 3.62
57
 * Isse Date: January 11, 2013
58
 *
59
 * URL:
60
 * http://support.amd.com/TechDocs/31116.pdf 
61
 */
62
63
#include <xen/init.h>
64
#include <xen/types.h>
65
66
#include <asm/msr.h>
67
#include <asm/processor.h>
68
69
#include "mce.h"
70
#include "x86_mca.h"
71
#include "mce_amd.h"
72
#include "mcaction.h"
73
#include "mce_quirks.h"
74
#include "vmce.h"
75
76
0
#define ANY -1
77
78
static const struct mce_quirkdata mce_amd_quirks[] = {
79
    { 0xf /* cpu family */, ANY /* all models */, ANY /* all steppings */,
80
      MCEQUIRK_K8_GART },
81
    { 0x10 /* cpu family */, ANY /* all models */, ANY /* all steppings */,
82
      MCEQUIRK_F10_GART },
83
};
84
85
/* Error Code Types */
86
enum mc_ec_type {
87
    MC_EC_TLB_TYPE = 0x0010,
88
    MC_EC_MEM_TYPE = 0x0100,
89
    MC_EC_BUS_TYPE = 0x0800,
90
};
91
92
enum mc_ec_type
93
mc_ec2type(uint16_t errorcode)
94
0
{
95
0
    if ( errorcode & MC_EC_BUS_TYPE )
96
0
        return MC_EC_BUS_TYPE;
97
0
    if ( errorcode & MC_EC_MEM_TYPE )
98
0
        return MC_EC_MEM_TYPE;
99
0
    if ( errorcode & MC_EC_TLB_TYPE )
100
0
        return MC_EC_TLB_TYPE;
101
0
    /* Unreached */
102
0
    BUG();
103
0
    return 0;
104
0
}
105
106
bool mc_amd_recoverable_scan(uint64_t status)
107
0
{
108
0
    bool ret = false;
109
0
    enum mc_ec_type ectype;
110
0
    uint16_t errorcode;
111
0
112
0
    if ( !(status & MCi_STATUS_UC) )
113
0
        return true;
114
0
115
0
    errorcode = status & (MCi_STATUS_MCA | MCi_STATUS_MSEC);
116
0
    ectype = mc_ec2type(errorcode);
117
0
118
0
    switch ( ectype )
119
0
    {
120
0
    case MC_EC_BUS_TYPE: /* value in addr MSR is physical */
121
0
        /* should run cpu offline action */
122
0
        break;
123
0
124
0
    case MC_EC_MEM_TYPE: /* value in addr MSR is physical */
125
0
        ret = true; /* run memory page offline action */
126
0
        break;
127
0
128
0
    case MC_EC_TLB_TYPE: /* value in addr MSR is virtual */
129
0
        /* should run tlb flush action and retry */
130
0
        break;
131
0
    }
132
0
133
0
    return ret;
134
0
}
135
136
bool mc_amd_addrcheck(uint64_t status, uint64_t misc, int addrtype)
137
0
{
138
0
    enum mc_ec_type ectype;
139
0
    uint16_t errorcode;
140
0
141
0
    errorcode = status & (MCi_STATUS_MCA | MCi_STATUS_MSEC);
142
0
    ectype = mc_ec2type(errorcode);
143
0
144
0
    switch ( ectype )
145
0
    {
146
0
    case MC_EC_BUS_TYPE: /* value in addr MSR is physical */
147
0
    case MC_EC_MEM_TYPE: /* value in addr MSR is physical */
148
0
        return (addrtype == MC_ADDR_PHYSICAL);
149
0
150
0
    case MC_EC_TLB_TYPE: /* value in addr MSR is virtual */
151
0
        return (addrtype == MC_ADDR_VIRTUAL);
152
0
    }
153
0
154
0
    /* unreached */
155
0
    BUG();
156
0
    return false;
157
0
}
158
159
/* MC quirks */
160
enum mcequirk_amd_flags
161
mcequirk_lookup_amd_quirkdata(struct cpuinfo_x86 *c)
162
0
{
163
0
    int i;
164
0
165
0
    BUG_ON(c->x86_vendor != X86_VENDOR_AMD);
166
0
167
0
    for ( i = 0; i < ARRAY_SIZE(mce_amd_quirks); i++ )
168
0
    {
169
0
        if ( c->x86 != mce_amd_quirks[i].cpu_family )
170
0
            continue;
171
0
        if ( (mce_amd_quirks[i].cpu_model != ANY) &&
172
0
             (mce_amd_quirks[i].cpu_model != c->x86_model) )
173
0
            continue;
174
0
        if ( (mce_amd_quirks[i].cpu_stepping != ANY) &&
175
0
             (mce_amd_quirks[i].cpu_stepping != c->x86_mask) )
176
0
                continue;
177
0
        return mce_amd_quirks[i].quirk;
178
0
    }
179
0
    return 0;
180
0
}
181
182
int mcequirk_amd_apply(enum mcequirk_amd_flags flags)
183
0
{
184
0
    uint64_t val;
185
0
186
0
    switch ( flags )
187
0
    {
188
0
    case MCEQUIRK_K8_GART:
189
0
        /*
190
0
         * Enable error reporting for all errors except for GART
191
0
         * TBL walk error reporting, which trips off incorrectly
192
0
         * with AGP GART & 3ware & Cerberus.
193
0
         */
194
0
        wrmsrl(MSR_IA32_MCx_CTL(4), ~(1ULL << 10));
195
0
        wrmsrl(MSR_IA32_MCx_STATUS(4), 0ULL);
196
0
        break;
197
0
198
0
    case MCEQUIRK_F10_GART:
199
0
        if ( rdmsr_safe(MSR_AMD64_MCx_MASK(4), val) == 0 )
200
0
                wrmsr_safe(MSR_AMD64_MCx_MASK(4), val | (1 << 10));
201
0
        break;
202
0
    }
203
0
204
0
    return 0;
205
0
}
206
207
static struct mcinfo_extended *
208
amd_f10_handler(struct mc_info *mi, uint16_t bank, uint64_t status)
209
0
{
210
0
    struct mcinfo_extended *mc_ext;
211
0
212
0
    /* Family 0x10 introduced additional MSR that belong to the
213
0
     * northbridge bank (4). */
214
0
    if ( mi == NULL || bank != 4 )
215
0
        return NULL;
216
0
217
0
    if ( !(status & MCi_STATUS_VAL) )
218
0
        return NULL;
219
0
220
0
    if ( !(status & MCi_STATUS_MISCV) )
221
0
        return NULL;
222
0
223
0
    mc_ext = x86_mcinfo_reserve(mi, sizeof(*mc_ext), MC_TYPE_EXTENDED);
224
0
    if ( !mc_ext )
225
0
    {
226
0
        mi->flags |= MCINFO_FLAGS_UNCOMPLETE;
227
0
        return NULL;
228
0
    }
229
0
230
0
    mc_ext->mc_msrs = 3;
231
0
232
0
    mc_ext->mc_msr[0].reg = MSR_F10_MC4_MISC1;
233
0
    mc_ext->mc_msr[1].reg = MSR_F10_MC4_MISC2;
234
0
    mc_ext->mc_msr[2].reg = MSR_F10_MC4_MISC3;
235
0
236
0
    mc_ext->mc_msr[0].value = mca_rdmsr(MSR_F10_MC4_MISC1);
237
0
    mc_ext->mc_msr[1].value = mca_rdmsr(MSR_F10_MC4_MISC2);
238
0
    mc_ext->mc_msr[2].value = mca_rdmsr(MSR_F10_MC4_MISC3);
239
0
240
0
    return mc_ext;
241
0
}
242
243
static bool amd_need_clearbank_scan(enum mca_source who, uint64_t status)
244
0
{
245
0
    if ( who != MCA_MCE_SCAN )
246
0
        return true;
247
0
248
0
    /*
249
0
     * For fatal error, it shouldn't be cleared so that sticky bank
250
0
     * have a chance to be handled after reboot by polling.
251
0
     */
252
0
    if ( (status & MCi_STATUS_UC) && (status & MCi_STATUS_PCC) )
253
0
        return false;
254
0
255
0
    return true;
256
0
}
257
258
/* AMD specific MCA MSR */
259
int vmce_amd_wrmsr(struct vcpu *v, uint32_t msr, uint64_t val)
260
0
{
261
0
    /* Do nothing as we don't emulate this MC bank currently */
262
0
    mce_printk(MCE_VERBOSE, "MCE: wr msr %#"PRIx64"\n", val);
263
0
    return 1;
264
0
}
265
266
int vmce_amd_rdmsr(const struct vcpu *v, uint32_t msr, uint64_t *val)
267
0
{
268
0
    /* Assign '0' as we don't emulate this MC bank currently */
269
0
    *val = 0;
270
0
    return 1;
271
0
}
272
273
enum mcheck_type
274
amd_mcheck_init(struct cpuinfo_x86 *ci)
275
0
{
276
0
    uint32_t i;
277
0
    enum mcequirk_amd_flags quirkflag = mcequirk_lookup_amd_quirkdata(ci);
278
0
279
0
    /* Assume that machine check support is available.
280
0
     * The minimum provided support is at least the K8. */
281
0
    mce_handler_init();
282
0
    x86_mce_vector_register(mcheck_cmn_handler);
283
0
    mce_need_clearbank_register(amd_need_clearbank_scan);
284
0
285
0
    for ( i = 0; i < nr_mce_banks; i++ )
286
0
    {
287
0
        if ( quirkflag == MCEQUIRK_K8_GART && i == 4 )
288
0
            mcequirk_amd_apply(quirkflag);
289
0
        else
290
0
        {
291
0
            /* Enable error reporting of all errors */
292
0
            wrmsrl(MSR_IA32_MCx_CTL(i), 0xffffffffffffffffULL);
293
0
            wrmsrl(MSR_IA32_MCx_STATUS(i), 0x0ULL);
294
0
        }
295
0
    }
296
0
297
0
    if ( ci->x86 == 0xf )
298
0
        return mcheck_amd_k8;
299
0
300
0
    if ( quirkflag == MCEQUIRK_F10_GART )
301
0
        mcequirk_amd_apply(quirkflag);
302
0
303
0
    x86_mce_callback_register(amd_f10_handler);
304
0
    mce_recoverable_register(mc_amd_recoverable_scan);
305
0
    mce_register_addrcheck(mc_amd_addrcheck);
306
0
307
0
    return mcheck_amd_famXX;
308
0
}