Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


51605ae1b42bfba4ae6adf5b546839845456eae4
[palacios.git] / palacios / src / extensions / ext_mcheck.c
1 /*
2  * This file is part of the Palacios Virtual Machine Monitor developed
3  * by the V3VEE Project with funding from the United States National
4  * Science Foundation and the Department of Energy.
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
11  * All rights reserved.
12  *
13  * Copyright (c) 2008, Philip Soltero <psoltero@cs.unm.edu>
14  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
15  * All rights reserved.
16  *
17  * Author: Philip Soltero <psoltero@cs.unm.edu>
18  *
19  * This is free software.  You are permitted to use,
20  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
21  */
22
23 /**
24  * @file Virtualized machine-check architecture.
25  *
26  * @author <a HREF="mailto:psoltero@cs.unm.edu.us">Philip Soltero</a>
27  */
28
29 // TODO: CPUID field add failure.
30 // IF adding CPUID fields fails on the second hook there is no way to back out of the first add.
31
32 #include <palacios/vm_guest.h>
33 #include <palacios/vmm.h>
34 #include <palacios/vmm_cpuid.h>
35 #include <palacios/vmm_excp.h>
36 #include <palacios/vmm_extensions.h>
37 #include <palacios/vmm_lowlevel.h>
38 #include <palacios/vmm_msr.h>
39 #include <palacios/vmm_string.h>
40
41 #ifndef V3_CONFIG_DEGUB_EXT_MACH_CHECK
42 #undef PrintDebug
43 #define PrintDebug(fmt, args...)
44 #endif
45
46 #define MCHECK "MCHECK"
47
48 #define CPUID_0000_0001 0x00000001
49 #define CPUID_8000_0001 0x80000001
50
51 // Bit 7 - MCE availability.  Bit 14 - MCA availability.
52 #define CPUID_FIELDS 0x00004080
53
54 // 6 error reporting banks. This may be configurable in the future.
55 #define MC_REG_BANKS 6
56 #define MCE_INTERRUPT 18
57
58 #define MSG_PRE MCHECK": "
59
60 #define MCG_CAP  0x0179
61 #define MCG_STAT 0x017A
62 #define MCG_CTRL  0x017B
63
64
65
66 /* I have no idea what Intel was thinking (or maybe they just weren't)
67  * but the MCi registers are completely non-standard across Intel's platforms and are a total mess.
68  * Any derivative of the pentium-M (i.e. all Core CPU lines) completely disregard the
69  * architectural standard that Intel itself created...
70  * For these CPUs: the MC4 MSRs switch locations with the MC3s,
71  * also every MCi below MC3 (including MC4) does not have a MCi_MISC MSR.
72  *
73  * So for now, screw it, we'll use AMD's standard
74  */
75
76 /* AMD MC Banks:
77    Bank 0 : Data Cache.
78    Bank 1 : Instruction Cache.
79    Bank 2 : Bus Unit.
80    Bank 3 : Load Store Unit.
81    Bank 4 : Northbridge and DRAM.
82 */
83
84 static const uint32_t amd_mci_bases[] = {0x0400, 0x0404, 0x0408, 0x040c, 0x0410, 0x0414};
85 static const uint32_t pentium_6_mci_bases[] = {0x0400, 0x0404, 0x0408, 0x040c, 0x0410, 0x0414};
86 static const uint32_t pentium_m_mci_bases[] = {0x0400, 0x0404, 0x0408, 0x0410, 0x040c, 0x0414};
87 static const uint32_t ia32_mci_bases[] = { 0x0400, 0x0404, 0x0408, 0x040c,
88                        0x0410, 0x0414, 0x0418, 0x041c,
89                        0x0420, 0x0424, 0x0428, 0x042c,
90                        0x0430, 0x0434, 0x0438, 0x043c,
91                        0x0440, 0x0444, 0x0448, 0x044c,
92                        0x0450, 0x0454 };
93 #define MCi_MASK  0xfffffffc
94 #define MCi_CTRL  0x00
95 #define MCi_STAT  0x01
96 #define MCi_ADDR  0x02
97 #define MCi_MISC  0x03
98
99
100
101
102 /**
103  * MCA status low and high registers, MC4_STAT, MSR0000_0411.
104  */
105 struct mc4_stat_msr {
106      union {
107         uint64_t value;
108         struct {
109         uint_t syndrome            : 8;
110         uint_t reserved            : 3;
111         uint_t error_code_ext      : 5;
112         uint_t error_code          : 16;
113         uint_t err_cpu             : 4;
114         uint_t ltd_link            : 4;
115         uint_t scrub               : 1;
116         uint_t sublink             : 1;
117         uint_t mca_stat_sub_cache  : 2;
118         uint_t reserved_01         : 1;
119         uint_t uecc                : 1;
120         uint_t cecc                : 1;
121         uint_t syndrome2           : 8;
122         uint_t reserved_02         : 1;
123         uint_t err_cpu_val         : 1;
124         uint_t pcc                 : 1;
125         uint_t addr_v              : 1;
126         uint_t misc_v              : 1;
127         uint_t en                  : 1;
128         uint_t uc                  : 1;
129         uint_t over                : 1;
130         uint_t val                 : 1;
131         }__attribute__((packed));
132      }__attribute__((packed));
133 } __attribute__((packed));
134
135 /**
136  * MCA address low and high registers, MC4_ADDR, MSR0000_0412.
137  */
138 struct mc4_addr_msr {
139     union {
140         uint64_t value;
141
142         struct {
143         uint64_t addr32    : 36;
144         uint32_t reserved  : 28;
145         } __attribute__((packed));
146
147     uint64_t addr64;
148     } __attribute__((packed));
149 } __attribute__((packed));
150
151 /**
152  * Global machine-check capabilities register, MCG_CAP.
153  */
154 struct mcg_cap_msr {
155     union {
156         uint64_t value;
157         struct {
158             uint32_t count            : 8;
159             uint32_t mcg_ctl_p        : 1;  // CTRL Present
160             uint64_t reserved         : 55;
161         } __attribute__((packed));
162     } __attribute__((packed));
163 } __attribute__((packed));
164
165 /**
166  * Global machine-check status register, MCG_STAT.
167  */
168 struct mcg_stat_msr {
169     union {
170         uint64_t value;
171         struct {
172             uint32_t ripv             : 1;
173             uint32_t eipv             : 1;
174             uint32_t mcip             : 1; // Machine-check in progress.
175             uint64_t reserved         : 61;
176         } __attribute__((packed));
177     } __attribute__((packed));
178 } __attribute__((packed));
179
180 /**
181  * Global machine-check control register, MCG_CTRL.
182  */
183 struct mcg_ctl_msr {
184     union {
185         uint64_t value;
186         struct {
187             uint32_t dce          : 1; // Data cache register bank enable
188             uint32_t ice          : 1; // Instruction cache register bank enable
189             uint32_t bue          : 1; // Bus unit register bank enable
190             uint32_t lse          : 1; // Load-store register bank enable
191             uint32_t nbe          : 1; // Northbridge register bank enable
192             uint32_t fre          : 1; // Fixed issue reorder buffer register bank enable
193             uint64_t unused       : 58;
194         } __attribute__((packed));
195     } __attribute__((packed));
196 } __attribute__((packed));
197
198 /**
199  * A temporary structure for unimplemented machine-check error reporting banks.
200  */
201 struct mci_bank {
202     uint32_t base;
203     struct v3_msr ctl;
204     struct v3_msr stat;
205     struct v3_msr addr;
206     struct v3_msr misc;
207 };
208
209 struct mcheck_state {
210     struct mcg_cap_msr mcg_cap;
211     struct mcg_stat_msr mcg_stat;
212     struct mcg_ctl_msr mcg_ctl;
213
214     /* Note that these are in logical order not MSR order */
215     /* So MC4 is always at mci_regs[4] even if the MSR is before MC3's */
216     struct mci_bank mci_regs[MC_REG_BANKS];
217 };
218
219
220 static inline
221 void init_state(struct mcheck_state * const state) {
222     int i = 0;
223
224     memset(state, 0, sizeof(struct mcheck_state));
225
226     // Set the initial MCI reg base values to the current architecture
227     for (i = 0; i < MC_REG_BANKS; i++) {
228     state->mci_regs[i].base = amd_mci_bases[i];
229     }
230 }
231
232 /**
233  * Handles guest writes to MCG MSRs.
234  */
235 static
236 int mcg_write_handler(struct guest_info * core, uint32_t msr, struct v3_msr src, void * priv_data) {
237     struct mcheck_state * state = (struct mcheck_state *)priv_data;
238
239     switch (msr) {
240     case MCG_CAP:
241         PrintDebug(MSG_PRE "Ignoring write to MCG_CAP MSR.\n");
242         break;
243
244     case MCG_STAT:
245         state->mcg_stat.value = 0;
246         break;
247
248     case MCG_CTRL:
249         if (!state->mcg_cap.mcg_ctl_p) {
250         PrintDebug(MSG_PRE "Ignoring write to control MSR '0x%x'. Control MSRs not supported.\n", msr);
251         break;
252         }
253
254         // The upper 58 bits are unused and read-only.
255         state->mcg_ctl.value &= ~0x3f;
256         state->mcg_ctl.value |= src.value & 0x3f;
257
258         break;
259
260     default:
261          PrintError(MSG_PRE "Reading from invalid MSR: %x\n", msr);
262          return -1;
263     }
264
265     return 0;
266 }
267
268
269 /**
270  * Handles guest reads to MCG MSRs.
271  */
272 static
273 int mcg_read_handler(struct guest_info * core, uint32_t msr, struct v3_msr * dst, void * priv_data) {
274     struct mcheck_state * state = (struct mcheck_state *)priv_data;
275
276      switch(msr) {
277     case MCG_CAP:
278         dst->value = state->mcg_cap.value;
279         break;
280
281     case MCG_STAT:
282         dst->value = state->mcg_stat.value;
283         break;
284
285     case MCG_CTRL:
286         if (!state->mcg_cap.mcg_ctl_p) {
287         PrintDebug(MSG_PRE "Ignoring read of control MSR '0x%x'. Control MSRs not supported.\n", msr);
288         break;
289         }
290
291         dst->value = state->mcg_ctl.value;
292         break;
293
294      default:
295          PrintError(MSG_PRE "Reading from invalid MSR: %x\n", msr);
296          return -1;
297      }
298
299      return 0;
300 }
301
302 static struct mci_bank * get_mci_reg(struct mcheck_state * state, uint32_t msr) {
303     int i = 0;
304
305     for (i = 0; i < MC_REG_BANKS; i++) {
306     if (state->mci_regs[i].base == (msr & MCi_MASK)) {
307         return &(state->mci_regs[i]);
308     }
309     }
310
311     return NULL;
312 }
313
314
315 /**
316  * Handles guest reads to MCi MSRs.
317  */
318 static
319 int mci_read_handler(struct guest_info * const core,
320                      const uint32_t msr,
321                      struct v3_msr * const dst,
322                      void * const priv_data) {
323     struct mcheck_state * const state = (struct mcheck_state *)priv_data;
324     struct mci_bank * mci = get_mci_reg(state, msr);
325
326     PrintDebug(MSG_PRE "Reading value '0x%llx' for MSR '0x%x'.\n", dst->value, msr);
327
328     if (mci == NULL) {
329     PrintError(MSG_PRE " MSR read for invalid MCI register 0x%x\n", msr);
330     return -1;
331     }
332
333     switch (msr & ~MCi_MASK) {
334     case MCi_CTRL:
335         if (!state->mcg_cap.mcg_ctl_p) {
336         PrintDebug(MSG_PRE "Ignoring read of control MSR '0x%x'. Control MSRs not supported.\n", msr);
337         break;
338         }
339
340         dst->value = mci->ctl.value;
341         break;
342
343     case MCi_STAT:
344         dst->value = mci->stat.value;
345         break;
346
347     case MCi_ADDR:
348         dst->value = mci->addr.value;
349         break;
350
351     case MCi_MISC:
352         dst->value = mci->misc.value;
353         break;
354
355     default:
356         PrintError(MSG_PRE "Ignoring read of unhooked MSR '0x%x'. This is a bug.\n", msr);
357         break;
358     }
359
360     return 0;
361 }
362
363 /**
364  * Handles guest writes to MCi MSRs.
365  */
366 static
367 int mci_write_handler(struct guest_info * const core,
368               const uint_t msr,
369               const struct v3_msr src,
370               void * const priv_data) {
371     struct mcheck_state * const state = (struct mcheck_state *)priv_data;
372     struct mci_bank * mci = get_mci_reg(state, msr);
373
374     PrintDebug(MSG_PRE "Writing value '0x%llx' for MSR '0x%x'.\n", src.value, msr);
375
376     switch (msr & ~MCi_MASK) {
377     case MCi_CTRL:
378         if (!state->mcg_cap.mcg_ctl_p) {
379         PrintDebug(MSG_PRE "Ignoring read of control MSR '0x%x'. Control MSRs not supported.\n", msr);
380         break;
381         }
382
383         mci->ctl.value = src.value;
384         break;
385
386     case MCi_STAT:
387         if (src.value != 0) {
388         // Should be a GPF.
389         PrintError(MSG_PRE "Ignoring write of illegal value '0x%llx'.\n", src.value);
390         return -1;
391         }
392
393         mci->stat.value = 0;
394         break;
395
396     case MCi_ADDR:
397         mci->addr.value = src.value;
398         break;
399
400     case MCi_MISC:
401         V3_Print(MSG_PRE "Ignoring write to read only miscellaneous MSR '0x%x'.\n", msr);
402         break;
403
404     default:
405         PrintError(MSG_PRE "Ignoring write of unhooked MSR '0x%x'. This is a bug.\n", msr);
406         break;
407     }
408
409     return 0;
410 }
411
412 /**
413  * Add machine-check-related CPUID fields for CPUID functions 0000_0001 and 8000_0001.
414  *
415  * @return 0 for success and -1 for failure.
416  */
417 static inline
418 int add_cpuid_fields(struct v3_vm_info * const vm,
419         struct mcheck_state * const state) {
420     int ret = 0;
421
422     ret = v3_cpuid_add_fields(vm, CPUID_0000_0001,
423                               0, 0,
424                               0, 0,
425                               0, 0,
426                               CPUID_FIELDS, CPUID_FIELDS);
427
428     if (ret == -1) {
429     PrintError(MSG_PRE "Failed to add CPUID fields for function 0000_0001.\n");
430     return -1;
431     }
432
433     // Add bit 7, MCE availability, and bit 14, MCE availability.
434     ret = v3_cpuid_add_fields(vm, CPUID_8000_0001,
435                               0, 0,
436                               0, 0,
437                               0, 0,
438                               CPUID_FIELDS, CPUID_FIELDS);
439
440     if (ret == -1) {
441     PrintError(MSG_PRE "Failed to add CPUID fileds for function 8000_0001.\n");
442     return -1;
443     }
444
445     return 0;
446 }
447
448
449 static int deinit_mcheck(struct v3_vm_info * vm, void * priv_data) {
450     struct mcheck_state * state = (struct mcheck_state *)v3_get_extension_state(vm, priv_data);
451     if (state == NULL) {
452         PrintError(MSG_PRE "Failed to get machine-check architecture extension state.\n");
453         return -1;
454     }
455
456     V3_Free(state);
457     return 0;
458 }
459
460 static int init_mcheck(struct v3_vm_info * vm, v3_cfg_tree_t * cfg, void ** priv_data) {
461     struct mcheck_state * state = NULL;
462     int ret = 0;
463     int i = 0;
464
465     state = (struct mcheck_state *)V3_Malloc(sizeof(struct mcheck_state));
466
467     if (state == NULL) {
468     PrintError(MSG_PRE "Failed to allocate machine-check architecture state.\n");
469     return -1;
470     }
471
472
473     init_state(state);
474
475     state->mcg_cap.count = MC_REG_BANKS;
476     state->mcg_cap.mcg_ctl_p = 1;
477
478     ret |= add_cpuid_fields(vm, state);
479
480     /* Hook the MSRs */
481     ret |= v3_hook_msr(vm, MCG_CAP, mcg_read_handler, mcg_write_handler, state);
482     ret |= v3_hook_msr(vm, MCG_STAT, mcg_read_handler, mcg_write_handler, state);
483     ret |= v3_hook_msr(vm, MCG_CTRL, mcg_read_handler, mcg_write_handler, state);
484
485     for (i = 0; i < MC_REG_BANKS; i++) {
486     ret |= v3_hook_msr(vm, state->mci_regs[i].base, mci_read_handler, mci_write_handler, state);
487     ret |= v3_hook_msr(vm, state->mci_regs[i].base + 1, mci_read_handler, mci_write_handler, state);
488     ret |= v3_hook_msr(vm, state->mci_regs[i].base + 2, mci_read_handler, mci_write_handler, state);
489     ret |= v3_hook_msr(vm, state->mci_regs[i].base + 3, mci_read_handler, mci_write_handler, state);
490     }
491
492     if (ret == -1) {
493     PrintError(MSG_PRE "Error hooking machine-check architecture resources.\n");
494     V3_Free(state);
495     return -1;
496     }
497
498     *priv_data = state;
499
500     PrintDebug(MSG_PRE "Initialized machine-check architecture.\n");
501
502     return 0;
503 }
504
505 int v3_mcheck_inject_nb_mce(struct v3_vm_info * const vm, const uint32_t cpu,
506                 const struct mc4_stat_msr stat,
507                 const struct mc4_addr_msr addr) {
508     struct mcheck_state * state = (struct mcheck_state *)v3_get_extension_state(vm, MCHECK);
509     int ret;
510
511     if (state == NULL) {
512     PrintError(MSG_PRE "Machine-check architecture extension state not found.\n");
513     return -1;
514     }
515
516     // For now only MCE injection on cpu 0 is supported.
517     if (cpu != 0) {
518     PrintError(MSG_PRE "Injecting MCE on cpu %u not supported.\n", cpu);
519     return -1;
520     }
521
522     // Is the Northbridge bank enabled?
523     if (state->mcg_ctl.nbe != 1) {
524     PrintDebug(MSG_PRE "Northbridge register bank disabled. Ignoring Northbridge MCE.\n");
525     return 0;
526     }
527
528     state->mci_regs[4].stat.value = stat.value;
529     state->mci_regs[4].addr.value = addr.value;
530
531     state->mcg_stat.value = 0;
532     state->mcg_stat.ripv = 1;
533     state->mcg_stat.mcip = 1;
534
535     PrintDebug(MSG_PRE "Injecting NB MCE on core %u.\n", 0);
536
537     // Raise on core 0.
538     ret = v3_raise_exception(&(vm->cores[0]), MCE_INTERRUPT);
539
540     if (ret == -1) {
541     PrintError(MSG_PRE "Failed to raise MCE.\n");
542     return -1;
543     }
544
545     return 0;
546 }
547
548 static struct v3_extension_impl mcheck_impl = {
549     .name = MCHECK,
550     .init = init_mcheck,
551     .deinit = deinit_mcheck,
552     .core_init = NULL,
553     .core_deinit = NULL,
554     .on_entry = NULL,
555     .on_exit = NULL
556 };
557
558 register_extension(&mcheck_impl);