VMM: Make put_cpu actually put the cpu

And various fixes / temp hacks.

(git-fu'd by brho)
diff --git a/kern/arch/x86/vmm/intel/vmx.c b/kern/arch/x86/vmm/intel/vmx.c
index b409bbe..6a1fb7c 100644
--- a/kern/arch/x86/vmm/intel/vmx.c
+++ b/kern/arch/x86/vmm/intel/vmx.c
@@ -129,7 +129,7 @@
  * either a failed vm startup or an exit for lots of many reasons.
  *
  */
-void monitor(void *);
+
 /* basically: only rename those globals that might conflict
  * with existing names. Leave all else the same.
  * this code is more modern than the other code, yet still
@@ -165,6 +165,18 @@
  */
 static bool has_vmx = FALSE;
 
+/*
+ * Keep MSR_STAR at the end, as setup_msrs() will try to optimize it
+ * away by decrementing the array size.
+ */
+static const uint32_t vmx_msr_index[] = {
+#ifdef CONFIG_X86_64
+	MSR_SYSCALL_MASK, MSR_LSTAR, MSR_CSTAR,
+#endif
+	MSR_EFER, MSR_TSC_AUX, MSR_STAR,
+};
+#define NR_VMX_MSR ARRAY_SIZE(vmx_msr_index)
+
 /* TEMPORARY TEST HACK EPT */
 void *ept;
 uint64_t eptp;
@@ -395,10 +407,6 @@
 {
 	printk("vmwrite error: reg %lx value %lx (err %d)\n",
 	       field, value, vmcs_read32(VM_INSTRUCTION_ERROR));
-	/* not available so ...
-	dump_stack();
-	*/
-	monitor(NULL);
 }
 
 void vmcs_writel(unsigned long field, unsigned long value)
@@ -424,13 +432,8 @@
 static void vmcs_write64(unsigned long field, uint64_t value)
 {
 	vmcs_writel(field, value);
-#ifndef CONFIG_X86_64
-	asm volatile ("");
-	vmcs_writel(field+1, value >> 32);
-#endif
 }
 
-
 static int adjust_vmx_controls(uint32_t ctl_min, uint32_t ctl_opt,
 				      uint32_t msr, uint32_t *result)
 {
@@ -684,15 +687,10 @@
 	vmcs_write16(HOST_GS_SELECTOR, 0);            /* 22.2.4 */
 
 	/* TODO: This (at least gs) is per cpu */
-#ifdef CONFIG_X86_64
 	rdmsrl(MSR_FS_BASE, tmpl);
 	vmcs_writel(HOST_FS_BASE, tmpl); /* 22.2.4 */
 	rdmsrl(MSR_GS_BASE, tmpl);
 	vmcs_writel(HOST_GS_BASE, tmpl); /* 22.2.4 */
-#else
-	vmcs_writel(HOST_FS_BASE, 0); /* 22.2.4 */
-	vmcs_writel(HOST_GS_BASE, 0); /* 22.2.4 */
-#endif
 }
 
 static inline uint16_t vmx_read_ldt(void)
@@ -786,22 +784,19 @@
 	int cur_cpu = core_id();
 	handler_wrapper_t *w;
 
-	//printk("currentcpu->local_vcpu %p vcpu %p\n",
-		//currentcpu->local_vcpu, vcpu);
+	if (currentcpu->local_vcpu)
+		panic("get_cpu: currentcpu->localvcpu was non-NULL");
 	if (currentcpu->local_vcpu != vcpu) {
 		currentcpu->local_vcpu = vcpu;
 
 		if (vcpu->cpu != cur_cpu) {
 			if (vcpu->cpu >= 0) {
-				smp_call_function_single(vcpu->cpu,
-							 __vmx_get_cpu_helper, (void *) vcpu, &w);
-				if (smp_call_wait(w))
-					printk("litevm_init. smp_call_wait failed. Expect a panic.\n");
+				panic("vcpu->cpu is not -1, it's %d\n", vcpu->cpu);
 			} else
 				vmcs_clear(vcpu->vmcs);
 
-//			vpid_sync_context(vcpu->vpid);
-//			ept_sync_context(current->vmm->
+			vpid_sync_context(vcpu->vpid);
+			ept_sync_context(eptp);
 
 			vcpu->launched = 0;
 			vmcs_load(vcpu->vmcs);
@@ -819,6 +814,19 @@
  */
 static void vmx_put_cpu(struct vmx_vcpu *vcpu)
 {
+	if (core_id() != vcpu->cpu)
+		panic("%s: core_id() %d != vcpu->cpu %d\n",
+		      __func__, core_id(), vcpu->cpu);
+
+	if (currentcpu->local_vcpu != vcpu)
+		panic("vmx_put_cpu: asked to clear something not ours");
+
+
+	vpid_sync_context(vcpu->vpid);
+	ept_sync_context(eptp);
+	vmcs_clear(vcpu->vmcs);
+	vcpu->cpu = -1;
+	currentcpu->local_vcpu = NULL;
 	//put_cpu();
 }
 
@@ -826,7 +834,7 @@
 {
 	struct vmx_vcpu *vcpu = ptr;
 
-//	ept_sync_context(current);
+	ept_sync_context(eptp);
 }
 
 struct sync_addr_args {
@@ -1127,16 +1135,19 @@
 		/* Keep arch.pat sync with GUEST_IA32_PAT */
 		vmx->vcpu.arch.pat = host_pat;
 	}
-
-	for (i = 0; i < NR_VMX_MSR; ++i) {
+#endif
+#if 0
+	for (int i = 0; i < NR_VMX_MSR; ++i) {
 		uint32_t index = vmx_msr_index[i];
 		uint32_t data_low, data_high;
 		int j = vmx->nmsrs;
-
+		// TODO we should have read/writemsr_safe
+#if 0
 		if (rdmsr_safe(index, &data_low, &data_high) < 0)
 			continue;
 		if (wrmsr_safe(index, data_low, data_high) < 0)
 			continue;
+#endif
 		vmx->guest_msrs[j].index = i;
 		vmx->guest_msrs[j].data = 0;
 		vmx->guest_msrs[j].mask = -1ull;
@@ -1247,11 +1258,9 @@
  */
 void vmx_destroy_vcpu(struct vmx_vcpu *vcpu)
 {
-	// needs to be done when we tear down the gv. vmx_destroy_ept(vcpu->gv);
 	vmx_get_cpu(vcpu);
-//	ept_sync_context
-	vmcs_clear(vcpu->vmcs);
-	currentcpu->local_vcpu = NULL;
+	ept_sync_context(eptp);
+	memset(ept, 0, PGSIZE);
 	vmx_put_cpu(vcpu);
 	vmx_free_vpid(vcpu);
 	vmx_free_vmcs(vcpu->vmcs);
@@ -1357,8 +1366,7 @@
 
 		"pop  %%rbp; pop  %%rdx \n\t"
 		"setbe %c[fail](%0) \n\t"
-
-		"mov $" /*__stringify(GD_UD) */"16"", %%rax \n\t"
+		"mov $" STRINGIFY(GD_UD) ", %%rax \n\t"
 		"mov %%rax, %%ds \n\t"
 		"mov %%rax, %%es \n\t"
 	      : : "c"(vcpu), "d"((unsigned long)HOST_RSP),
@@ -1394,7 +1402,6 @@
 	/* FIXME: do we need to set up other flags? */
 	vcpu->regs.tf_rflags = (vmcs_readl(GUEST_RFLAGS) & 0xFF) |
 		      X86_EFLAGS_IF | 0x2;
-	//monitor(NULL);
 
 	vcpu->regs.tf_cs = GD_UT;
 	vcpu->regs.tf_ss = GD_UD;
@@ -1584,15 +1591,10 @@
 		disable_irq();
 		ret = vmx_run_vcpu(vcpu);
 		enable_irq();
-
-		if (ret == EXIT_REASON_VMCALL ||
-		    ret == EXIT_REASON_CPUID) {
-			vmx_step_instruction();
-		}
-
 		vmx_put_cpu(vcpu);
 
 		if (ret == EXIT_REASON_VMCALL) {
+			vcpu->shutdown = SHUTDOWN_UNHANDLED_EXIT_REASON;
 			printk("system call! WTF\n");
 		} else if (ret == EXIT_REASON_CPUID)
 			vmx_handle_cpuid(vcpu);
@@ -1621,7 +1623,6 @@
 
 	printk("RETURN. ip %016lx sp %016lx\n",
 		vcpu->regs.tf_rip, vcpu->regs.tf_rsp);
-	monitor(NULL);
 	current->virtinfo = NULL;
 
 	/*
diff --git a/kern/drivers/dev/cons.c b/kern/drivers/dev/cons.c
index 16ae518..a6aea1d 100644
--- a/kern/drivers/dev/cons.c
+++ b/kern/drivers/dev/cons.c
@@ -1038,14 +1038,9 @@
 					rip =  strtoul(cb->f[1], NULL, 0);
 					rsp =  strtoul(cb->f[2], NULL, 0);
 					cr3 =  strtoul(cb->f[3], NULL, 0);
-					disable_irq();
 					ret = vm_run(rip, rsp, cr3);
-					enable_irq();
 					printk("vm_run returns %d\n", ret);
-					return ret;
-	
-					ip = strtoul(cb->f[1], 0, 0);
-					//			vm_run(ip);
+					n = ret;
 					break;
 			}
 			poperror();
diff --git a/tests/vmmcp.c b/tests/vmmcp.c
index acd67d3..d083baa 100644
--- a/tests/vmmcp.c
+++ b/tests/vmmcp.c
@@ -1,4 +1,5 @@
 #include <stdio.h> 
+#include <pthread.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
@@ -10,23 +11,91 @@
 #include <string.h>
 #include <ros/syscall.h>
 
-unsigned long stack[1024];
+unsigned long long stack[1024];
+volatile int shared = 0;
+int mcp = 1;
+#define V(x, t) (*((volatile t*)(x)))
 
-static void fail(void)
+static void *fail(void*arg)
 {
-	__asm__ __volatile__("mov $0xdeadbeef, %rbx; mov 5, %rax\n");
+
+	if (mcp)
+	while (V(&shared, int) < 31) {
+		if (! (V(&shared, int) & 1))
+			V(&shared, int) = V(&shared, int) + 1;
+//		cpu_relax();
+	}
+	V(&shared, int) = 55;
+
+	__asm__ __volatile__("vmcall\n");
+	__asm__ __volatile__("mov $0xdeadbeef, %rbx; mov 5, %rax\n");	
 }
 
 unsigned long long *p512, *p1, *p2m;
 
+void *talk_thread(void *arg)
+{
+	printf("talk thread ..\n");
+	for(; V(&shared, int) < 32; ){
+		if (V(&shared, int) & 1) {
+			printf("shared %d\n", V(&shared, int) );
+			V(&shared, int) = V(&shared, int) + 1;
+		}
+		cpu_relax();
+	}
+	printf("All done\n");
+	return NULL;
+}
+
+pthread_t *my_threads;
+void **my_retvals;
+int nr_threads = 2;
+
 int main(int argc, char **argv)
 {
 	int fd = open("#c/sysctl", O_RDWR), ret;
+	void * x;
 	static char cmd[512];
 	if (fd < 0) {
 		perror("#c/sysctl");
 		exit(1);
 	}
+
+	mcp = 1; //argc - 1;
+	if (mcp) {
+		my_threads = malloc(sizeof(pthread_t) * nr_threads);
+		my_retvals = malloc(sizeof(void*) * nr_threads);
+		if (!(my_retvals && my_threads))
+			perror("Init threads/malloc");
+
+		pthread_can_vcore_request(FALSE);	/* 2LS won't manage vcores */
+		pthread_need_tls(FALSE);
+		pthread_lib_init();					/* gives us one vcore */
+		vcore_request(nr_threads - 1);		/* ghetto incremental interface */
+		for (int i = 0; i < nr_threads; i++) {
+			x = __procinfo.vcoremap;
+			printf("%p\n", __procinfo.vcoremap);
+			printf("Vcore %d mapped to pcore %d\n", i,
+			    	__procinfo.vcoremap[i].pcoreid);
+		}
+	}
+
+	if (mcp) {
+		if (pthread_create(&my_threads[0], NULL, &talk_thread, NULL))
+			perror("pth_create failed");
+//		if (pthread_create(&my_threads[1], NULL, &fail, NULL))
+//			perror("pth_create failed");
+	}
+	printf("threads started\n");
+
+	if (0) for (int i = 0; i < nr_threads-1; i++) {
+		int ret;
+		if (pthread_join(my_threads[i], &my_retvals[i]))
+			perror("pth_join failed");
+		printf("%d %d\n", i, ret);
+	}
+	
+
 	ret = syscall(33, 1);
 	if (ret < 0) {
 		perror("vm setup");
@@ -47,12 +116,13 @@
 	p2m[3] = 0x600000 | 0x87;
 
 	printf("p512 %p p512[0] is 0x%lx p1 %p p1[0] is 0x%x\n", p512, p512[0], p1, p1[0]);
-	sprintf(cmd, "V 0x%x 0x%x 0x%x", (unsigned long long)fail, (unsigned long long) stack, (unsigned long long) p512);
+	sprintf(cmd, "V 0x%x 0x%x 0x%x", (unsigned long long)fail, (unsigned long long) &stack[1024], (unsigned long long) p512);
 	printf("Writing command :%s:\n", cmd);
 	ret = write(fd, cmd, strlen(cmd));
 	if (ret != strlen(cmd)) {
 		perror(cmd);
 	}
-	
+	printf("shared is %d\n", shared);
+
 	return 0;
 }