Remove MWAIT functionality from the VM guest.
authorGan Shun <ganshun@gmail.com>
Tue, 11 Jul 2017 21:14:04 +0000 (14:14 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Wed, 12 Jul 2017 15:51:36 +0000 (11:51 -0400)
Turns out linux uses MONITOR/MWAIT to wake up AP cores when they have
work. We don't support proper MONITOR/MWAIT for VM guests so our only
solution right now is to turn it off.

Turns out this is the reason SMP VM guests were slow. The issue wasn't
the timer at all, but my old implementation of the timer covered up the
bug as I rammed every core with timer interrupts. That masked the fact
that guest cores were waiting on some address that we never actually
monitored.

Signed-off-by: Gan Shun <ganshun@gmail.com>
Change-Id: Ie21f8137aa2ec2312f907b8fd4b6c9685fdf5a9d
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/arch/x86/trap.c
user/vmm/vmexit.c

index 6b365d5..1bbe3c1 100644 (file)
@@ -892,6 +892,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;
                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);
                        /* Unset the vmx capability bit so that the guest does not try
                         * to turn it on. */
                        ecx &= ~(1 << 5);
@@ -917,6 +920,12 @@ static bool handle_vmexit_cpuid(struct vm_trapframe *tf)
                        ecx = 0x564b4d56;
                        edx = 0x0000004d;
                        break;
                        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;
        }
                default:
                        break;
        }
index fa61c80..0b97f96 100644 (file)
@@ -300,18 +300,6 @@ static bool handle_halt(struct guest_thread *gth)
        return TRUE;
 }
 
        return TRUE;
 }
 
-static bool handle_mwait(struct guest_thread *gth)
-{
-       struct vm_trapframe *vm_tf = gth_to_vmtf(gth);
-
-       /* TODO: we need to handle the actual monitor part of mwait.  This just
-        * implements the power management / halting.  Likewise, it's possible IRQs
-        * are disabled (as with halt). */
-       sleep_til_irq(gth);
-       vm_tf->tf_rip += 3;
-       return TRUE;
-}
-
 /* Is this a vmm specific thing?  or generic?
  *
  * what do we do when we want to kill the vm?  what are our other options? */
 /* Is this a vmm specific thing?  or generic?
  *
  * what do we do when we want to kill the vm?  what are our other options? */
@@ -335,8 +323,6 @@ bool handle_vmexit(struct guest_thread *gth)
                return handle_apic_access(gth);
        case EXIT_REASON_HLT:
                return handle_halt(gth);
                return handle_apic_access(gth);
        case EXIT_REASON_HLT:
                return handle_halt(gth);
-       case EXIT_REASON_MWAIT_INSTRUCTION:
-               return handle_mwait(gth);
        case EXIT_REASON_EXTERNAL_INTERRUPT:
        case EXIT_REASON_APIC_WRITE:
                /* TODO: just ignore these? */
        case EXIT_REASON_EXTERNAL_INTERRUPT:
        case EXIT_REASON_APIC_WRITE:
                /* TODO: just ignore these? */