X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fpalacios%2Fvmm.c;h=de772773c2fa8477d70bf604516ba743220e0fc8;hb=e0de615834461da95407a446d5883be3a45257a0;hp=1bd489b3bad1321b059858c73fc981b950bc5dda;hpb=1c000bda0560742ad6be011722fa226771b656ff;p=palacios.git diff --git a/palacios/src/palacios/vmm.c b/palacios/src/palacios/vmm.c index 1bd489b..de77277 100644 --- a/palacios/src/palacios/vmm.c +++ b/palacios/src/palacios/vmm.c @@ -255,6 +255,28 @@ int v3_start_vm(struct v3_vm_info * vm, unsigned int cpu_mask) { uint32_t avail_cores = 0; int vcore_id = 0; + + if (vm->run_state != VM_STOPPED) { + PrintError("VM has already been launched (state=%d)\n", (int)vm->run_state); + return -1; + } + + + // Do not run if any core is using shadow paging and we are out of 4 GB bounds + for (i=0;inum_cores;i++) { + if (vm->cores[i].shdw_pg_mode == SHADOW_PAGING) { + if ((vm->mem_map.base_region.host_addr + vm->mem_size ) >= 0x100000000ULL) { + PrintError("Base memory region exceeds 4 GB boundary with shadow paging enabled on core %d.\n",i); + PrintError("Any use of non-64 bit mode in the guest is likely to fail in this configuration.\n"); + PrintError("If you would like to proceed anyway, remove this check and recompile Palacios.\n"); + PrintError("Alternatively, change this VM to use nested paging.\n"); + return -1; + } + } + } + + + /// CHECK IF WE ARE MULTICORE ENABLED.... V3_Print("V3 -- Starting VM (%u cores)\n", vm->num_cores); @@ -451,6 +473,12 @@ int v3_move_vm_core(struct v3_vm_info * vm, int vcore_id, int target_cpu) { int v3_stop_vm(struct v3_vm_info * vm) { + if ((vm->run_state != VM_RUNNING) && + (vm->run_state != VM_SIMULATING)) { + PrintError("Tried to stop VM in invalid runstate (%d)\n", vm->run_state); + return -1; + } + vm->run_state = VM_STOPPED; // Sanity check to catch any weird execution states @@ -474,7 +502,7 @@ int v3_stop_vm(struct v3_vm_info * vm) { break; } - v3_yield(NULL); + v3_yield(NULL,-1); } V3_Print("VM stopped. Returning\n"); @@ -522,7 +550,7 @@ static int sim_callback(struct guest_info * core, void * private_data) { V3_Print("Simulation callback activated (guest_rip=%p)\n", (void *)core->rip); while (v3_bitmap_check(timeout_map, core->vcpu_id) == 1) { - v3_yield(NULL); + v3_yield(NULL,-1); } return 0; @@ -593,7 +621,7 @@ int v3_simulate_vm(struct v3_vm_info * vm, unsigned int msecs) { break; } - v3_yield(NULL); + v3_yield(NULL,-1); } @@ -624,6 +652,18 @@ int v3_save_vm(struct v3_vm_info * vm, char * store, char * url) { int v3_load_vm(struct v3_vm_info * vm, char * store, char * url) { return v3_chkpt_load_vm(vm, store, url); } + +#ifdef V3_CONFIG_LIVE_MIGRATION +int v3_send_vm(struct v3_vm_info * vm, char * store, char * url) { + return v3_chkpt_send_vm(vm, store, url); +} + + +int v3_receive_vm(struct v3_vm_info * vm, char * store, char * url) { + return v3_chkpt_receive_vm(vm, store, url); +} +#endif + #endif @@ -631,6 +671,12 @@ int v3_free_vm(struct v3_vm_info * vm) { int i = 0; // deinitialize guest (free memory, etc...) + if ((vm->run_state != VM_STOPPED) && + (vm->run_state != VM_ERROR)) { + PrintError("Tried to Free VM in invalid runstate (%d)\n", vm->run_state); + return -1; + } + v3_free_vm_devices(vm); // free cores @@ -682,7 +728,7 @@ v3_cpu_mode_t v3_get_host_cpu_mode() { -void v3_yield_cond(struct guest_info * info) { +void v3_yield_cond(struct guest_info * info, int usec) { uint64_t cur_cycle; cur_cycle = v3_get_host_time(&info->time_state); @@ -691,19 +737,31 @@ void v3_yield_cond(struct guest_info * info) { // (void *)cur_cycle, (void *)info->yield_start_cycle, // (void *)info->yield_cycle_period); - V3_Yield(); + if (usec < 0) { + V3_Yield(); + } else { + V3_Sleep(usec); + } + info->yield_start_cycle += info->vm_info->yield_cycle_period; } } - + /* * unconditional cpu yield * if the yielding thread is a guest context, the guest quantum is reset on resumption * Non guest context threads should call this function with a NULL argument - */ -void v3_yield(struct guest_info * info) { - V3_Yield(); + * + * usec <0 => the non-timed yield is used + * usec >=0 => the timed yield is used, which also usually implies interruptible + */ +void v3_yield(struct guest_info * info, int usec) { + if (usec < 0) { + V3_Yield(); + } else { + V3_Sleep(usec); + } if (info) { info->yield_start_cycle += info->vm_info->yield_cycle_period; @@ -711,18 +769,6 @@ void v3_yield(struct guest_info * info) { } -/* - * unconditional cpu yield for a period of time - * Otherwise identical to v3_yield - */ -void v3_yield_timed(struct guest_info *info, unsigned int usec) -{ - V3_Yield_Timed(usec); - - if (info) { - info->yield_start_cycle += info->vm_info->yield_cycle_period; - } -} void v3_print_cond(const char * fmt, ...) {