x86: Handle buggy user_contexts (XCC)
[akaros.git] / kern / arch / x86 / vmm / vmm.c
1 /* Copyright 2015 Google Inc.
2  *
3  * See LICENSE for details.
4  */
5
6 /* We're not going to falll into the trap of only compiling support
7  * for AMD OR Intel for an image. It all gets compiled in, and which
8  * one you use depends on on cpuinfo, not a compile-time
9  * switch. That's proven to be the best strategy.  Conditionally
10  * compiling in support is the path to hell.
11  */
12 #include <assert.h>
13 #include <pmap.h>
14 #include <smp.h>
15 #include <kmalloc.h>
16
17 #include <ros/vmm.h>
18 #include "intel/vmx.h"
19 #include "vmm.h"
20 #include <trap.h>
21 #include <umem.h>
22
23 #include <arch/x86.h>
24 #include <ros/procinfo.h>
25
26
27 /* TODO: have better cpuid info storage and checks */
28 bool x86_supports_vmx = FALSE;
29
30 /* Figure out what kind of CPU we are on, and if it supports any reasonable
31  * virtualization. For now, if we're not some sort of newer intel, don't
32  * bother. This does all cores. Again, note, we make these decisions at runtime,
33  * to avoid getting into the problems that compile-time decisions can cause.
34  * At this point, of course, it's still all intel.
35  */
36 void vmm_init(void)
37 {
38         int ret;
39         /* Check first for intel capabilities. This is hence two back-to-back
40          * implementationd-dependent checks. That's ok, it's all msr dependent.
41          */
42         ret = intel_vmm_init();
43         if (! ret) {
44                 x86_supports_vmx = TRUE;
45                 return;
46         }
47
48         /* TODO: AMD. Will we ever care? It's not clear. */
49         printk("vmm_init failed, ret %d\n", ret);
50         return;
51 }
52
53 void vmm_pcpu_init(void)
54 {
55         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
56
57         pcpui->guest_pcoreid = -1;
58         if (!x86_supports_vmx)
59                 return;
60         if (! intel_vmm_pcpu_init()) {
61                 printd("vmm_pcpu_init worked\n");
62                 return;
63         }
64         /* TODO: AMD. Will we ever care? It's not clear. */
65         printk("vmm_pcpu_init failed\n");
66 }
67
68 /* Ensures a process is ready to run virtual machines, though it may have no
69  * guest pcores yet.  Typically, this is called by other vmm functions.  Caller
70  * holds the qlock.  Throws on error. */
71 void __vmm_struct_init(struct proc *p)
72 {
73         struct vmm *vmm = &p->vmm;
74
75         if (vmm->vmmcp)
76                 return;
77         if (!x86_supports_vmx)
78                 error(ENODEV, "This CPU does not support VMX");
79         vmm->vmmcp = TRUE;
80         vmm->amd = 0;
81         vmx_setup_vmx_vmm(&vmm->vmx);
82         for (int i = 0; i < VMM_VMEXIT_NR_TYPES; i++)
83                 vmm->vmexits[i] = 0;
84         vmm->nr_guest_pcores = 0;
85         vmm->guest_pcores = NULL;
86         vmm->gpc_array_elem = 0;
87 }
88
89 /* Helper, grows the array of guest_pcores in vmm.  Concurrent readers
90  * (lookup_guest_pcore) need to use a seq-lock-style of concurrency.  They could
91  * read the old array even after we free it. */
92 static void __vmm_grow_gpc_array(struct vmm *vmm, unsigned int new_nr_gpcs)
93 {
94         struct guest_pcore **new_array, **old_array;
95         size_t new_nr_elem;
96
97         if (new_nr_gpcs <= vmm->gpc_array_elem)
98                 return;
99         /* TODO: (RCU) we could defer the free, maybe with an RCU-safe krealloc. */
100         old_array = vmm->guest_pcores;
101         new_nr_elem = MAX(vmm->gpc_array_elem * 2, new_nr_gpcs);
102         new_array = kzmalloc(new_nr_elem * sizeof(void*), MEM_WAIT);
103         memcpy(new_array, vmm->guest_pcores,
104                sizeof(void*) * vmm->nr_guest_pcores);
105         wmb();  /* all elements written before changing pointer */
106         vmm->guest_pcores = new_array;
107         wmb();  /* ptr written before potentially clobbering it. */
108         kfree(old_array);
109 }
110
111 /* Adds gpcs to the VMM.  Caller holds the qlock; throws on error. */
112 void __vmm_add_gpcs(struct proc *p, unsigned int nr_more_gpcs,
113                     struct vmm_gpcore_init *u_gpcis)
114 {
115         struct vmm *vmm = &p->vmm;
116         struct vmm_gpcore_init gpci;
117         unsigned int new_nr_gpcs;
118
119         if (!nr_more_gpcs)
120                 return;
121         new_nr_gpcs = vmm->nr_guest_pcores + nr_more_gpcs;
122         if ((new_nr_gpcs < vmm->nr_guest_pcores) || (new_nr_gpcs > 10000))
123                 error(EINVAL, "Can't add %u new gpcs", new_nr_gpcs);
124         __vmm_grow_gpc_array(vmm, new_nr_gpcs);
125         for (int i = 0; i < nr_more_gpcs; i++) {
126                 if (copy_from_user(&gpci, &u_gpcis[i], sizeof(struct vmm_gpcore_init)))
127                         error(EINVAL, "Bad pointer %p for gps", u_gpcis);
128                 vmm->guest_pcores[vmm->nr_guest_pcores] = create_guest_pcore(p, &gpci);
129                 wmb();  /* concurrent readers will check nr_guest_pcores first */
130                 vmm->nr_guest_pcores++;
131         }
132 }
133
134 /* Has no concurrency protection - only call this when you know you have the
135  * only ref to vmm.  For instance, from __proc_free, where there is only one ref
136  * to the proc (and thus proc.vmm). */
137 void __vmm_struct_cleanup(struct proc *p)
138 {
139         struct vmm *vmm = &p->vmm;
140         if (!vmm->vmmcp)
141                 return;
142         for (int i = 0; i < vmm->nr_guest_pcores; i++) {
143                 if (vmm->guest_pcores[i])
144                         destroy_guest_pcore(vmm->guest_pcores[i]);
145         }
146         kfree(vmm->guest_pcores);
147         ept_flush(p->env_pgdir.eptp);
148         vmm->vmmcp = FALSE;
149 }
150
151 int vmm_poke_guest(struct proc *p, int guest_pcoreid)
152 {
153         struct guest_pcore *gpc;
154         int pcoreid;
155
156         gpc = lookup_guest_pcore(p, guest_pcoreid);
157         if (!gpc) {
158                 set_error(ENOENT, "Bad guest_pcoreid %d", guest_pcoreid);
159                 return -1;
160         }
161         /* We're doing an unlocked peek; it could change immediately.  This is a
162          * best effort service. */
163         pcoreid = ACCESS_ONCE(gpc->cpu);
164         if (pcoreid == -1) {
165                 /* So we know that we'll miss the poke for the posted IRQ.  We could
166                  * return an error.  However, error handling for this case isn't
167                  * particularly helpful (yet).  The absence of the error does not mean
168                  * the IRQ was posted.  We'll still return 0, meaning "the user didn't
169                  * mess up; we tried." */
170                 return 0;
171         }
172         send_ipi(pcoreid, I_POKE_GUEST);
173         return 0;
174 }
175
176 struct guest_pcore *lookup_guest_pcore(struct proc *p, int guest_pcoreid)
177 {
178         struct guest_pcore **array;
179         struct guest_pcore *ret;
180
181         if (guest_pcoreid < 0)
182                 return NULL;
183         /* nr_guest_pcores is written once at setup and never changed */
184         if (guest_pcoreid >= p->vmm.nr_guest_pcores)
185                 return NULL;
186         /* TODO: (RCU) Synchronizing with __vmm_grow_gpc_array() */
187         do {
188                 array = ACCESS_ONCE(p->vmm.guest_pcores);
189                 ret = array[guest_pcoreid];
190                 rmb();  /* read ret before rereading array pointer */
191         } while (array != ACCESS_ONCE(p->vmm.guest_pcores));
192         return ret;
193 }
194
195 struct guest_pcore *load_guest_pcore(struct proc *p, int guest_pcoreid)
196 {
197         struct guest_pcore *gpc;
198         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
199
200         gpc = lookup_guest_pcore(p, guest_pcoreid);
201         if (!gpc)
202                 return 0;
203         assert(pcpui->guest_pcoreid == -1);
204         spin_lock(&p->vmm.lock);
205         if (gpc->cpu != -1) {
206                 spin_unlock(&p->vmm.lock);
207                 return 0;
208         }
209         gpc->cpu = core_id();
210         spin_unlock(&p->vmm.lock);
211         /* We've got dibs on the gpc; we don't need to hold the lock any longer. */
212         pcpui->guest_pcoreid = guest_pcoreid;
213         vmx_load_guest_pcore(gpc);
214         /* Load guest's xcr0 */
215         lxcr0(gpc->xcr0);
216
217         /* Manual MSR save/restore */
218         write_kern_gsbase(gpc->msr_kern_gs_base);
219         if (gpc->msr_star != AKAROS_MSR_STAR)
220                 write_msr(MSR_STAR, gpc->msr_star);
221         if (gpc->msr_lstar != AKAROS_MSR_LSTAR)
222                 write_msr(MSR_LSTAR, gpc->msr_lstar);
223         if (gpc->msr_sfmask != AKAROS_MSR_SFMASK)
224                 write_msr(MSR_SFMASK, gpc->msr_sfmask);
225
226         return gpc;
227 }
228
229 void unload_guest_pcore(struct proc *p, int guest_pcoreid)
230 {
231         struct guest_pcore *gpc;
232         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
233
234         gpc = lookup_guest_pcore(p, guest_pcoreid);
235         assert(gpc);
236         spin_lock(&p->vmm.lock);
237         assert(gpc->cpu != -1);
238         vmx_unload_guest_pcore(gpc);
239         gpc->cpu = -1;
240
241         /* Save guest's xcr0 and restore Akaros's default. */
242         gpc->xcr0 = rxcr0();
243         lxcr0(__proc_global_info.x86_default_xcr0);
244
245         /* We manage these MSRs manually. */
246         gpc->msr_kern_gs_base = read_kern_gsbase();
247         gpc->msr_star = read_msr(MSR_STAR);
248         gpc->msr_lstar = read_msr(MSR_LSTAR);
249         gpc->msr_sfmask = read_msr(MSR_SFMASK);
250
251         write_kern_gsbase((uint64_t)pcpui);
252         if (gpc->msr_star != AKAROS_MSR_STAR)
253                 write_msr(MSR_STAR, AKAROS_MSR_STAR);
254         if (gpc->msr_lstar != AKAROS_MSR_LSTAR)
255                 write_msr(MSR_LSTAR, AKAROS_MSR_LSTAR);
256         if (gpc->msr_sfmask, AKAROS_MSR_SFMASK)
257                 write_msr(MSR_SFMASK, AKAROS_MSR_SFMASK);
258
259         /* As soon as we unlock, this gpc can be started on another core */
260         spin_unlock(&p->vmm.lock);
261         pcpui->guest_pcoreid = -1;
262 }
263
264 /* emulated msr. For now, an msr value and a pointer to a helper that
265  * performs the requested operation.
266  */
267 struct emmsr {
268         uint32_t reg;
269         char *name;
270         bool (*f)(struct emmsr *msr, struct vm_trapframe *vm_tf,
271                   uint32_t opcode);
272         bool written;
273         uint32_t edx, eax;
274 };
275
276 static bool emsr_miscenable(struct emmsr *msr, struct vm_trapframe *vm_tf,
277                             uint32_t opcode);
278 static bool emsr_readonly(struct emmsr *msr, struct vm_trapframe *vm_tf,
279                           uint32_t opcode);
280 static bool emsr_readzero(struct emmsr *msr, struct vm_trapframe *vm_tf,
281                           uint32_t opcode);
282 static bool emsr_fakewrite(struct emmsr *msr, struct vm_trapframe *vm_tf,
283                            uint32_t opcode);
284 static bool emsr_ok(struct emmsr *msr, struct vm_trapframe *vm_tf,
285                     uint32_t opcode);
286 static bool emsr_fake_apicbase(struct emmsr *msr, struct vm_trapframe *vm_tf,
287                                uint32_t opcode);
288 static bool emsr_lapic_icr(struct emmsr *msr, struct vm_trapframe *vm_tf,
289                            uint32_t opcode);
290
291 struct emmsr emmsrs[] = {
292         {MSR_LAPIC_ICR, "MSR_LAPIC_ICR", emsr_lapic_icr},
293         {MSR_IA32_MISC_ENABLE, "MSR_IA32_MISC_ENABLE", emsr_miscenable},
294         {MSR_IA32_SYSENTER_CS, "MSR_IA32_SYSENTER_CS", emsr_ok},
295         {MSR_IA32_SYSENTER_EIP, "MSR_IA32_SYSENTER_EIP", emsr_ok},
296         {MSR_IA32_SYSENTER_ESP, "MSR_IA32_SYSENTER_ESP", emsr_ok},
297         {MSR_IA32_UCODE_REV, "MSR_IA32_UCODE_REV", emsr_fakewrite},
298         {MSR_CSTAR, "MSR_CSTAR", emsr_fakewrite},
299         {MSR_IA32_VMX_BASIC_MSR, "MSR_IA32_VMX_BASIC_MSR", emsr_fakewrite},
300         {MSR_IA32_VMX_PINBASED_CTLS_MSR, "MSR_IA32_VMX_PINBASED_CTLS_MSR",
301          emsr_fakewrite},
302         {MSR_IA32_VMX_PROCBASED_CTLS_MSR, "MSR_IA32_VMX_PROCBASED_CTLS_MSR",
303          emsr_fakewrite},
304         {MSR_IA32_VMX_PROCBASED_CTLS2, "MSR_IA32_VMX_PROCBASED_CTLS2",
305          emsr_fakewrite},
306         {MSR_IA32_VMX_EXIT_CTLS_MSR, "MSR_IA32_VMX_EXIT_CTLS_MSR",
307          emsr_fakewrite},
308         {MSR_IA32_VMX_ENTRY_CTLS_MSR, "MSR_IA32_VMX_ENTRY_CTLS_MSR",
309          emsr_fakewrite},
310         {MSR_IA32_ENERGY_PERF_BIAS, "MSR_IA32_ENERGY_PERF_BIAS",
311          emsr_fakewrite},
312         {MSR_LBR_SELECT, "MSR_LBR_SELECT", emsr_ok},
313         {MSR_LBR_TOS, "MSR_LBR_TOS", emsr_ok},
314         {MSR_LBR_NHM_FROM, "MSR_LBR_NHM_FROM", emsr_ok},
315         {MSR_LBR_NHM_TO, "MSR_LBR_NHM_TO", emsr_ok},
316         {MSR_LBR_CORE_FROM, "MSR_LBR_CORE_FROM", emsr_ok},
317         {MSR_LBR_CORE_TO, "MSR_LBR_CORE_TO", emsr_ok},
318
319         // grumble.
320         {MSR_OFFCORE_RSP_0, "MSR_OFFCORE_RSP_0", emsr_ok},
321         {MSR_OFFCORE_RSP_1, "MSR_OFFCORE_RSP_1", emsr_ok},
322         // louder.
323         {MSR_PEBS_LD_LAT_THRESHOLD, "MSR_PEBS_LD_LAT_THRESHOLD", emsr_ok},
324         // aaaaaahhhhhhhhhhhhhhhhhhhhh
325         {MSR_ARCH_PERFMON_EVENTSEL0, "MSR_ARCH_PERFMON_EVENTSEL0", emsr_ok},
326         {MSR_ARCH_PERFMON_EVENTSEL1, "MSR_ARCH_PERFMON_EVENTSEL1", emsr_ok},
327         {MSR_IA32_PERF_CAPABILITIES, "MSR_IA32_PERF_CAPABILITIES", emsr_readzero},
328         // unsafe.
329         {MSR_IA32_APICBASE, "MSR_IA32_APICBASE", emsr_fake_apicbase},
330
331         // mostly harmless.
332         {MSR_TSC_AUX, "MSR_TSC_AUX", emsr_fakewrite},
333         {MSR_RAPL_POWER_UNIT, "MSR_RAPL_POWER_UNIT", emsr_readzero},
334         {MSR_IA32_MCG_CAP, "MSR_IA32_MCG_CAP", emsr_readzero},
335         {MSR_IA32_DEBUGCTLMSR, "MSR_IA32_DEBUGCTLMSR", emsr_fakewrite},
336
337         // TBD
338         {MSR_IA32_TSC_DEADLINE, "MSR_IA32_TSC_DEADLINE", emsr_fakewrite},
339 };
340
341 /* Here are the rules for IPI injection:
342  * 1) The guest can't sleep if notif is set.
343  * 2) Userspace must wake the guest if notif is set, unconditionally
344  * 3) Whoever sets notif must make sure the interrupt gets injected.
345  *
346  * This allows the kernel to set notif and possibly lose a race with a
347  * concurrently halting / vmexiting guest.
348  *
349  * Guest sleeping happens in userspace in the halt/mwait vmexit handler.  If
350  * userspace (vmm_interrupt_guest() sees notif set, it must try to wake the
351  * guest - even if the user didn't set notif.  If the kernel sets notif, it
352  * might be able to know the guest is running.  But if that fails, we have to
353  * kick it back to userspace (return false here).  In that case, even though
354  * userspace didn't set notif, it must attempt to wake the guest.
355  *
356  * For 3, the kernel can often know if the guest is running.  Then it can send
357  * the posted IPI, then reconfirm the guest is running.  If that fails, or if it
358  * *might* have failed, the guest still needs to get the IRQ.  The next time the
359  * guest runs after notif was set, the interrupt will be injected.  If the
360  * kernel kicks it back to userspace, the guest will wake or will fail to halt
361  * (due to notif being set), and the next time it runs, the kernel will inject
362  * the IPI (when we pop the vmtf).
363  *
364  * There's another case: the kernel sets notif, reads the coreid, sends the IPI,
365  * and then sees the coreid is changed.  If the coreid is -1, the GPC isn't
366  * loaded/running, and we kick back to userspace (as above).  If the coreid is
367  * not -1, it is running somewhere else.  It might have missed the IPI, but
368  * since the guest was popped on a core after notif was set, the IRQ was
369  * posted/injected. */
370 static bool emsr_lapic_icr_write(struct emmsr *msr, struct vm_trapframe *tf)
371 {
372         uint32_t destination = tf->tf_rdx & 0xffffffff;
373         uint8_t vector = tf->tf_rax & 0xff;
374         uint8_t type = (tf->tf_rax >> 8) & 0x7;
375         struct guest_pcore *gpc;
376         int target_coreid;
377
378         if (type != 0 || destination == 0xffffffff)
379                 return false;
380         gpc = lookup_guest_pcore(current, destination);
381         if (!gpc)
382                 return false;
383         SET_BITMASK_BIT_ATOMIC((void*)gpc->posted_irq_desc, vector);
384         cmb();  /* atomic does the MB, order set write before test read */
385         /* We got lucky and squeezed our IRQ in with someone else's */
386         if (test_bit(VMX_POSTED_OUTSTANDING_NOTIF, (void*)gpc->posted_irq_desc))
387                 return true;
388         SET_BITMASK_BIT_ATOMIC((void*)gpc->posted_irq_desc,
389                                VMX_POSTED_OUTSTANDING_NOTIF);
390         cmb();  /* atomic does the MB, order set write before read of cpu */
391         target_coreid = ACCESS_ONCE(gpc->cpu);
392         if (target_coreid == -1)
393                 return false;
394         /* If it's us, we'll send_ipi when we restart the VMTF.  Note this is rare:
395          * the guest will usually use the self_ipi virtualization. */
396         if (target_coreid != core_id())
397                 send_ipi(target_coreid, I_POKE_GUEST);
398         /* No MBs needed here: only that it happens after setting notif */
399         if (ACCESS_ONCE(gpc->cpu) == -1)
400                 return false;
401         return true;
402 }
403
404 static bool emsr_lapic_icr(struct emmsr *msr, struct vm_trapframe *tf,
405                            uint32_t opcode)
406 {
407         if (opcode == VMM_MSR_EMU_READ)
408                 return false;
409         return emsr_lapic_icr_write(msr, tf);
410 }
411
412 /* this may be the only register that needs special handling.
413  * If there others then we might want to extend the emmsr struct.
414  */
415 bool emsr_miscenable(struct emmsr *msr, struct vm_trapframe *vm_tf,
416                      uint32_t opcode)
417 {
418         uint64_t val;
419         uint32_t eax, edx;
420
421         if (read_msr_safe(msr->reg, &val))
422                 return FALSE;
423         eax = low32(val);
424         eax |= MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL;
425         edx = high32(val);
426         /* we just let them read the misc msr for now. */
427         if (opcode == VMM_MSR_EMU_READ) {
428                 vm_tf->tf_rax = eax;
429                 vm_tf->tf_rdx = edx;
430                 return TRUE;
431         } else {
432                 /* if they are writing what is already written, that's ok. */
433                 if (((uint32_t) vm_tf->tf_rax == eax)
434                     && ((uint32_t) vm_tf->tf_rdx == edx))
435                         return TRUE;
436         }
437         printk("%s: Wanted to write 0x%x%x, but could not; value was 0x%x%x\n",
438                msr->name, (uint32_t) vm_tf->tf_rdx, (uint32_t) vm_tf->tf_rax,
439                edx, eax);
440         return FALSE;
441 }
442
443 bool emsr_readonly(struct emmsr *msr, struct vm_trapframe *vm_tf,
444                    uint32_t opcode)
445 {
446         uint64_t val;
447
448         if (read_msr_safe(msr->reg, &val))
449                 return FALSE;
450         if (opcode == VMM_MSR_EMU_READ) {
451                 vm_tf->tf_rax = low32(val);
452                 vm_tf->tf_rdx = high32(val);
453                 return TRUE;
454         }
455
456         printk("%s: Tried to write a readonly register\n", msr->name);
457         return FALSE;
458 }
459
460 bool emsr_readzero(struct emmsr *msr, struct vm_trapframe *vm_tf,
461                    uint32_t opcode)
462 {
463         if (opcode == VMM_MSR_EMU_READ) {
464                 vm_tf->tf_rax = 0;
465                 vm_tf->tf_rdx = 0;
466                 return TRUE;
467         }
468
469         printk("%s: Tried to write a readonly register\n", msr->name);
470         return FALSE;
471 }
472
473 /* pretend to write it, but don't write it. */
474 bool emsr_fakewrite(struct emmsr *msr, struct vm_trapframe *vm_tf,
475                     uint32_t opcode)
476 {
477         uint32_t eax, edx;
478         uint64_t val;
479
480         if (!msr->written) {
481                 if (read_msr_safe(msr->reg, &val))
482                         return FALSE;
483                 eax = low32(val);
484                 edx = high32(val);
485         } else {
486                 eax = msr->eax;
487                 edx = msr->edx;
488         }
489         /* we just let them read the misc msr for now. */
490         if (opcode == VMM_MSR_EMU_READ) {
491                 vm_tf->tf_rax = eax;
492                 vm_tf->tf_rdx = edx;
493                 return TRUE;
494         } else {
495                 msr->edx = vm_tf->tf_rdx;
496                 msr->eax = vm_tf->tf_rax;
497                 msr->written = TRUE;
498         }
499         return TRUE;
500 }
501
502 bool emsr_ok(struct emmsr *msr, struct vm_trapframe *vm_tf,
503              uint32_t opcode)
504 {
505         uint64_t val;
506
507         if (opcode == VMM_MSR_EMU_READ) {
508                 if (read_msr_safe(msr->reg, &val))
509                         return FALSE;
510                 vm_tf->tf_rax = low32(val);
511                 vm_tf->tf_rdx = high32(val);
512         } else {
513                 val = (vm_tf->tf_rdx << 32) | (vm_tf->tf_rax & 0xffffffff);
514                 if (write_msr_safe(msr->reg, val))
515                         return FALSE;
516         }
517         return TRUE;
518 }
519
520 /* pretend to write it, but don't write it. */
521 bool emsr_fake_apicbase(struct emmsr *msr, struct vm_trapframe *vm_tf,
522                         uint32_t opcode)
523 {
524         uint32_t eax, edx;
525
526         if (!msr->written) {
527                 /* TODO: tightly coupled to the addr in vmrunkernel.  We want this func
528                  * to return the val that vmrunkernel put into the VMCS. */
529                 eax = 0xfee00d00;
530                 if (vm_tf->tf_guest_pcoreid != 0) {
531                         // Remove BSP bit if not core 0
532                         eax = 0xfee00c00;
533                 }
534                 edx = 0;
535         } else {
536                 edx = msr->edx;
537                 eax = msr->eax;
538         }
539         /* we just let them read the misc msr for now. */
540         if (opcode == VMM_MSR_EMU_READ) {
541                 vm_tf->tf_rax = eax;
542                 vm_tf->tf_rdx = edx;
543                 return TRUE;
544         } else {
545                 /* if they are writing what is already written, that's ok. */
546                 if (((uint32_t) vm_tf->tf_rax == eax)
547                     && ((uint32_t) vm_tf->tf_rdx == edx))
548                         return 0;
549                 msr->edx = vm_tf->tf_rdx;
550                 msr->eax = vm_tf->tf_rax;
551                 msr->written = TRUE;
552         }
553         return TRUE;
554 }
555
556 bool vmm_emulate_msr(struct vm_trapframe *vm_tf, int op)
557 {
558         for (int i = 0; i < ARRAY_SIZE(emmsrs); i++) {
559                 if (emmsrs[i].reg != vm_tf->tf_rcx)
560                         continue;
561                 return emmsrs[i].f(&emmsrs[i], vm_tf, op);
562         }
563         return FALSE;
564 }