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.


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