vmm: vmexit speed tests

There's a corresponding kernel module, vmexit_speed, in our linux-guest
repo.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
diff --git a/kern/arch/x86/trap.c b/kern/arch/x86/trap.c
index d21f0b2..4adc07b 100644
--- a/kern/arch/x86/trap.c
+++ b/kern/arch/x86/trap.c
@@ -38,6 +38,8 @@
 struct irq_handler *irq_handlers[NUM_IRQS];
 spinlock_t irq_handler_wlock = SPINLOCK_INITIALIZER_IRQSAVE;
 
+static void x86_finalize_vmtf(struct vm_trapframe *tf);
+
 static bool try_handle_exception_fixup(struct hw_trapframe *hw_tf)
 {
 	if (in_kernel(hw_tf)) {
@@ -1052,6 +1054,17 @@
 	 * do it for external IRQs - the irq_dispatch code will handle it. */
 	switch (tf->tf_exit_reason) {
 	case EXIT_REASON_VMCALL:
+		if (tf->tf_rdi == 0x1338) {
+			tf->tf_rip += 3;
+			handled = TRUE;
+			break;
+		}
+		if (tf->tf_rdi == 0x1339) {
+			tf->tf_rip += 3;
+			x86_finalize_vmtf(tf);
+			handled = TRUE;
+			break;
+		}
 		if (current->vmm.flags & VMM_VMCALL_PRINTF) {
 			printk("%c", tf->tf_rdi);
 			tf->tf_rip += 3;
diff --git a/kern/arch/x86/trapentry64.S b/kern/arch/x86/trapentry64.S
index e7aa859..4d531c0 100644
--- a/kern/arch/x86/trapentry64.S
+++ b/kern/arch/x86/trapentry64.S
@@ -914,6 +914,31 @@
 .globl vmexit_handler;
 .type vmexit_handler, @function;
 vmexit_handler:
+
+# This is part of why i don't use enums.  need #defines for asm.
+#define VM_EXIT_REASON                  0x00004402
+#define EXIT_REASON_VMCALL              18
+#define GUEST_RIP                       0x0000681e
+	pushq %rdx
+	pushq %rax
+	movq $VM_EXIT_REASON, %rdx
+	vmread %rdx, %rax
+	cmp $EXIT_REASON_VMCALL, %rax
+	jne normal_vmexit
+	cmp $0x1337, %rdi
+	jne normal_vmexit
+	# advance RIP by 3 (sizeof vmcall)
+	movq $GUEST_RIP, %rdx
+	vmread %rdx, %rax
+	add $3, %rax
+	vmwrite %rax, %rdx
+	popq %rax
+	popq %rdx
+	vmresume
+normal_vmexit:
+	popq %rax
+	popq %rdx
+
 	# rflags has all flags = 0, so cli and cld already.
 	# HOST_GS_BASE and RSP is set by the hardware
 	# Set default values.  Most of these will be set in C later.
diff --git a/user/vmm/vmexit.c b/user/vmm/vmexit.c
index 3e8700b..9d0bd65 100644
--- a/user/vmm/vmexit.c
+++ b/user/vmm/vmexit.c
@@ -126,6 +126,10 @@
 	struct vm_trapframe *vm_tf = gth_to_vmtf(gth);
 	uint8_t byte;
 
+	if (vm_tf->tf_rdi == 0x1340) {
+		vm_tf->tf_rip += 3;
+		return TRUE;
+	}
 	if (gth->vmcall)
 		return gth->vmcall(gth, vm_tf);
 	byte = vm_tf->tf_rdi;