x86: vmm: Track state for handling vmexits as KERNEL
[akaros.git] / kern / arch / x86 / trap.c
index 6b365d5..9f168fa 100644 (file)
@@ -580,13 +580,8 @@ static void trap_dispatch(struct hw_trapframe *hw_tf)
                            *(uint8_t*)(ip + 1) == 0x01,
                            *(uint8_t*)(ip + 2) == 0xf9) {
                                x86_fake_rdtscp(hw_tf);
-                               pcpui->__lock_checking_enabled++;       /* for print debugging */
                                handled = TRUE;
-                               break;
                        }
-                       enable_irq();
-                       monitor(hw_tf);
-                       disable_irq();
                        pcpui->__lock_checking_enabled++;               /* for print debugging */
                        break;
                }
@@ -892,6 +887,9 @@ static bool handle_vmexit_cpuid(struct vm_trapframe *tf)
                case 0x01:
                        /* Set the hypervisor bit to let the guest know it is virtualized */
                        ecx |= 1 << 31;
+                       /* Unset the monitor capability bit so that the guest does not try
+                        * to use monitor/mwait. */
+                       ecx &= ~(1 << 3);
                        /* Unset the vmx capability bit so that the guest does not try
                         * to turn it on. */
                        ecx &= ~(1 << 5);
@@ -917,6 +915,12 @@ static bool handle_vmexit_cpuid(struct vm_trapframe *tf)
                        ecx = 0x564b4d56;
                        edx = 0x0000004d;
                        break;
+               /* Hypervisor Features. */
+               case 0x40000003:
+                       /* Unset the monitor capability bit so that the guest does not try
+                        * to use monitor/mwait. */
+                       edx &= ~(1 << 0);
+                       break;
                default:
                        break;
        }
@@ -937,11 +941,14 @@ static bool handle_vmexit_ept_fault(struct vm_trapframe *tf)
        prot |= tf->tf_exit_qual & VMX_EPT_FAULT_WRITE ? PROT_WRITE : 0;
        prot |= tf->tf_exit_qual & VMX_EPT_FAULT_INS ? PROT_EXEC : 0;
        ret = handle_page_fault(current, tf->tf_guest_pa, prot);
-       if (ret) {
-               /* TODO: maybe put ret in the TF somewhere */
-               return FALSE;
-       }
-       return TRUE;
+       if (ret == 0)
+               return TRUE;
+
+       //Mirror behavior in uthreads, tell userspace to try again.
+       if (ret == -EAGAIN)
+               tf->tf_flags |= VMCTX_FL_EPT_VMR_BACKED;
+
+       return FALSE;
 }
 
 /* Regarding NMI blocking,
@@ -1123,6 +1130,7 @@ void handle_vmexit(struct vm_trapframe *tf)
        tf->tf_guest_pa = vmcs_read(GUEST_PHYSICAL_ADDRESS);
 
        set_current_ctx_vm(pcpui, tf);
+       __set_cpu_state(pcpui, CPU_STATE_KERNEL);
        tf = &pcpui->cur_ctx->tf.vm_tf;
        vmexit_dispatch(tf);
        /* We're either restarting a partial VM ctx (vmcs was launched, loaded on