Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


8c34b681855ee7a857711cee195f9f06c1df53fb
[palacios.git] / palacios / src / palacios / vmm.c
1 /* 
2  * This file is part of the Palacios Virtual Machine Monitor developed
3  * by the V3VEE Project with funding from the United States National 
4  * Science Foundation and the Department of Energy.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
11  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Jack Lange <jarusl@cs.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20 #include <palacios/vmm.h>
21 #include <palacios/vmm_mem.h>
22 #include <palacios/vmm_intr.h>
23 #include <palacios/vmm_config.h>
24 #include <palacios/vm_guest.h>
25 #include <palacios/vmm_ctrl_regs.h>
26 #include <palacios/vmm_lowlevel.h>
27 #include <palacios/vmm_sprintf.h>
28 #include <palacios/vmm_extensions.h>
29 #include <palacios/vmm_timeout.h>
30 #include <palacios/vmm_options.h>
31 #include <palacios/vmm_cpu_mapper.h>
32 #include <palacios/vmm_direct_paging.h>
33 #include <interfaces/vmm_numa.h>
34
35 #ifdef V3_CONFIG_SVM
36 #include <palacios/svm.h>
37 #endif
38 #ifdef V3_CONFIG_VMX
39 #include <palacios/vmx.h>
40 #endif
41
42 #ifdef V3_CONFIG_CHECKPOINT
43 #include <palacios/vmm_checkpoint.h>
44 #endif
45
46
47 v3_cpu_arch_t v3_cpu_types[V3_CONFIG_MAX_CPUS];
48 v3_cpu_arch_t v3_mach_type = V3_INVALID_CPU;
49
50 struct v3_os_hooks * os_hooks = NULL;
51 int v3_dbg_enable = 0;
52
53
54
55 static void init_cpu(void * arg) {
56     uint32_t cpu_id = (uint32_t)(addr_t)arg;
57
58     v3_init_fp();
59
60 #ifdef V3_CONFIG_SVM
61     if (v3_is_svm_capable()) {
62         PrintDebug(VM_NONE, VCORE_NONE, "Machine is SVM Capable\n");
63         v3_init_svm_cpu(cpu_id);
64         
65     } else 
66 #endif
67 #ifdef V3_CONFIG_VMX
68     if (v3_is_vmx_capable()) {
69         PrintDebug(VM_NONE, VCORE_NONE, "Machine is VMX Capable\n");
70         v3_init_vmx_cpu(cpu_id);
71
72     } else 
73 #endif
74     {
75        PrintError(VM_NONE, VCORE_NONE, "CPU has no virtualization Extensions\n");
76     }
77 }
78
79
80 static void deinit_cpu(void * arg) {
81     uint32_t cpu_id = (uint32_t)(addr_t)arg;
82
83
84     switch (v3_cpu_types[cpu_id]) {
85 #ifdef V3_CONFIG_SVM
86         case V3_SVM_CPU:
87         case V3_SVM_REV3_CPU:
88             PrintDebug(VM_NONE, VCORE_NONE, "Deinitializing SVM CPU %d\n", cpu_id);
89             v3_deinit_svm_cpu(cpu_id);
90             break;
91 #endif
92 #ifdef V3_CONFIG_VMX
93         case V3_VMX_CPU:
94         case V3_VMX_EPT_CPU:
95         case V3_VMX_EPT_UG_CPU:
96             PrintDebug(VM_NONE, VCORE_NONE, "Deinitializing VMX CPU %d\n", cpu_id);
97             v3_deinit_vmx_cpu(cpu_id);
98             break;
99 #endif
100         case V3_INVALID_CPU:
101         default:
102             PrintError(VM_NONE, VCORE_NONE, "CPU has no virtualization Extensions\n");
103             break;
104     }
105
106     v3_deinit_fp();
107
108 }
109
110 void Init_V3(struct v3_os_hooks * hooks, char * cpu_mask, int num_cpus, char *options) {
111     int i = 0;
112     int minor = 0;
113     int major = 0;
114
115     V3_Print(VM_NONE, VCORE_NONE, "V3 Print statement to fix a Kitten page fault bug\n");
116
117
118     // Set global variables. 
119     os_hooks = hooks;
120
121     if (num_cpus>V3_CONFIG_MAX_CPUS) { 
122         PrintError(VM_NONE,VCORE_NONE, "Requesting as many as %d cpus, but Palacios is compiled for a maximum of %d.  Only the first %d cpus will be considered\n", num_cpus, V3_CONFIG_MAX_CPUS, V3_CONFIG_MAX_CPUS);
123     }
124
125     // Determine the global machine type
126     v3_mach_type = V3_INVALID_CPU;
127
128     for (i = 0; i < V3_CONFIG_MAX_CPUS; i++) {
129         v3_cpu_types[i] = V3_INVALID_CPU;
130     }
131
132     // Parse host-os defined options into an easily-accessed format.
133     v3_parse_options(options);
134
135     // Memory manager initialization
136     v3_init_mem();
137
138     // Register all the possible device types
139     V3_init_devices();
140
141     // Register all shadow paging handlers
142     V3_init_shdw_paging();
143
144     // Initialize the cpu_mapper framework (must be before extensions)
145     V3_init_cpu_mapper();
146
147     // Initialize the scheduler framework (must be before extensions)
148     V3_init_scheduling();
149  
150     // Register all extensions
151     V3_init_extensions();
152
153     // Enabling cpu_mapper
154     V3_enable_cpu_mapper();
155
156     // Enabling scheduler
157     V3_enable_scheduler();
158
159
160 #ifdef V3_CONFIG_SYMMOD
161     V3_init_symmod();
162 #endif
163
164 #ifdef V3_CONFIG_CHECKPOINT
165     V3_init_checkpoint();
166 #endif
167
168     if ((hooks) && (hooks->call_on_cpu)) {
169
170         for (i = 0; i < num_cpus && i < V3_CONFIG_MAX_CPUS; i++) {
171             major = i / 8;
172             minor = i % 8;
173
174             if ((cpu_mask == NULL) || (*(cpu_mask + major) & (0x1 << minor))) {
175                 V3_Print(VM_NONE, VCORE_NONE, "Initializing VMM extensions on cpu %d\n", i);
176                 hooks->call_on_cpu(i, &init_cpu, (void *)(addr_t)i);
177
178                 if (v3_mach_type == V3_INVALID_CPU) {
179                     v3_mach_type = v3_cpu_types[i];
180                 }   
181             }
182         }
183     }
184 }
185
186
187
188 void Shutdown_V3() {
189     int i;
190
191     // Reverse order of Init_V3
192
193     // bring down CPUs
194
195     if ((os_hooks) && (os_hooks->call_on_cpu)) {
196         for (i = 0; i < V3_CONFIG_MAX_CPUS; i++) {
197             if (v3_cpu_types[i] != V3_INVALID_CPU) {
198                 V3_Call_On_CPU(i, deinit_cpu, (void *)(addr_t)i);
199                 //deinit_cpu((void *)(addr_t)i);
200             }
201         }
202     }
203
204 #ifdef V3_CONFIG_CHECKPOINT
205     V3_deinit_checkpoint();
206 #endif
207
208 #ifdef V3_CONFIG_SYMMOD
209     V3_deinit_symmod();
210 #endif
211
212     V3_disable_scheduler();
213
214     V3_disable_cpu_mapper();
215
216     V3_deinit_extensions();
217
218     V3_deinit_scheduling();
219     
220     V3_deinit_cpu_mapper();
221     
222     V3_deinit_shdw_paging();
223     
224     V3_deinit_devices();
225
226     v3_deinit_mem();
227     
228     v3_deinit_options();
229     
230
231 }
232
233
234 v3_cpu_arch_t v3_get_cpu_type(int cpu_id) {
235     return v3_cpu_types[cpu_id];
236 }
237
238
239 struct v3_vm_info * v3_create_vm(void * cfg, void * priv_data, char * name) {
240     struct v3_vm_info * vm = v3_config_guest(cfg, priv_data);
241
242     if (vm == NULL) {
243         PrintError(VM_NONE, VCORE_NONE, "Could not configure guest\n");
244         return NULL;
245     }
246
247     V3_Print(vm, VCORE_NONE, "CORE 0 RIP=%p\n", (void *)(addr_t)(vm->cores[0].rip));
248
249     if (name == NULL) {
250         name = "[V3_VM]";
251     } else if (strlen(name) >= 128) {
252         PrintError(vm, VCORE_NONE,"VM name is too long. Will be truncated to 128 chars.\n");
253     }
254
255     memset(vm->name, 0, 128);
256     strncpy(vm->name, name, 127);
257
258     if(v3_cpu_mapper_register_vm(vm) == -1) {
259
260         PrintError(vm, VCORE_NONE,"Error registering VM with cpu_mapper\n");
261     }
262
263     /*
264      * Register this VM with the palacios scheduler. It will ask for admission
265      * prior to launch.
266      */
267     if(v3_scheduler_register_vm(vm) == -1) {
268     
269         PrintError(vm, VCORE_NONE,"Error registering VM with scheduler\n");
270     }
271
272     return vm;
273 }
274
275
276
277
278 static int start_core(void * p)
279 {
280     struct guest_info * core = (struct guest_info *)p;
281
282     if (v3_scheduler_register_core(core) == -1){
283         PrintError(core->vm_info, core,"Error initializing scheduling in core %d\n", core->vcpu_id);
284     }
285
286     PrintDebug(core->vm_info,core,"virtual core %u (on logical core %u): in start_core (RIP=%p)\n", 
287                core->vcpu_id, core->pcpu_id, (void *)(addr_t)core->rip);
288
289     switch (v3_mach_type) {
290 #ifdef V3_CONFIG_SVM
291         case V3_SVM_CPU:
292         case V3_SVM_REV3_CPU:
293             return v3_start_svm_guest(core);
294             break;
295 #endif
296 #if V3_CONFIG_VMX
297         case V3_VMX_CPU:
298         case V3_VMX_EPT_CPU:
299         case V3_VMX_EPT_UG_CPU:
300             return v3_start_vmx_guest(core);
301             break;
302 #endif
303         default:
304             PrintError(core->vm_info, core, "Attempting to enter a guest on an invalid CPU\n");
305             return -1;
306     }
307     // should not happen
308     return 0;
309 }
310
311 int v3_start_vm(struct v3_vm_info * vm, unsigned int cpu_mask) {
312
313     uint32_t i,j;
314     uint8_t * core_mask = (uint8_t *)&cpu_mask; // This is to make future expansion easier
315     uint32_t avail_cores = 0;
316     int vcore_id = 0;
317     extern uint64_t v3_mem_block_size;
318
319
320     if (vm->run_state != VM_STOPPED) {
321         PrintError(vm, VCORE_NONE, "VM has already been launched (state=%d)\n", (int)vm->run_state);
322         return -1;
323     }
324
325     
326     // Do not run if any core is using shadow paging and we are out of 4 GB bounds
327     for (i=0;i<vm->num_cores;i++) { 
328         if (vm->cores[i].shdw_pg_mode == SHADOW_PAGING) {
329             for (j=0;j<vm->mem_map.num_base_regions;j++) {
330                 if ((vm->mem_map.base_regions[i].host_addr + v3_mem_block_size)  >= 0x100000000ULL) {
331                     PrintError(vm, VCORE_NONE, "Base memory region %d exceeds 4 GB boundary with shadow paging enabled on core %d.\n",j, i);
332                     PrintError(vm, VCORE_NONE, "Any use of non-64 bit mode in the guest is likely to fail in this configuration.\n");
333                     PrintError(vm, VCORE_NONE, "If you would like to proceed anyway, remove this check and recompile Palacios.\n");
334                     PrintError(vm, VCORE_NONE, "Alternatively, change this VM to use nested paging.\n");
335                     return -1;
336                 }
337             }
338         }
339     }
340     
341     /// CHECK IF WE ARE MULTICORE ENABLED....
342
343     V3_Print(vm, VCORE_NONE, "V3 --  Starting VM (%u cores)\n", vm->num_cores);
344     V3_Print(vm, VCORE_NONE, "CORE 0 RIP=%p\n", (void *)(addr_t)(vm->cores[0].rip));
345
346
347     // Check that enough cores are present in the mask to handle vcores
348     for (i = 0; i < V3_CONFIG_MAX_CPUS; i++) {
349         int major = i / 8;
350         int minor = i % 8;
351         
352         if (core_mask[major] & (0x1 << minor)) {
353             if (v3_cpu_types[i] == V3_INVALID_CPU) {
354                 core_mask[major] &= ~(0x1 << minor);
355             } else {
356                 avail_cores++;
357             }
358         }
359     }
360
361     vm->avail_cores = avail_cores;
362  
363     if (v3_cpu_mapper_admit_vm(vm,cpu_mask) != 0){
364         PrintError(vm, VCORE_NONE,"Error admitting VM %s for mapping", vm->name);
365     }
366
367     if (v3_scheduler_admit_vm(vm) != 0){
368        PrintError(vm, VCORE_NONE,"Error admitting VM %s for scheduling", vm->name);
369     }
370
371     vm->run_state = VM_RUNNING;
372
373
374     for (vcore_id = 0; vcore_id < vm->num_cores; vcore_id++) {
375
376         struct guest_info * core = &(vm->cores[vcore_id]);
377
378         PrintDebug(vm, VCORE_NONE, "Starting virtual core %u on logical core %u\n", 
379                    vcore_id, core->pcpu_id);
380         
381         sprintf(core->exec_name, "%s-%u", vm->name, vcore_id);
382
383         PrintDebug(vm, VCORE_NONE, "run: core=%u, func=0x%p, arg=0x%p, name=%s\n",
384                    core->pcpu_id, start_core, core, core->exec_name);
385
386         core->core_run_state = CORE_STOPPED;  // core zero will turn itself on
387         core->core_thread = V3_CREATE_THREAD_ON_CPU(core->pcpu_id, start_core, core, core->exec_name);
388
389         if (core->core_thread == NULL) {
390             PrintError(vm, VCORE_NONE, "Thread launch failed\n");
391             v3_stop_vm(vm);
392             return -1;
393         }
394     }
395
396     return 0;
397
398 }
399
400
401 int v3_reset_vm_core(struct guest_info * core, addr_t rip) {
402     
403     switch (v3_cpu_types[core->pcpu_id]) {
404 #ifdef V3_CONFIG_SVM
405         case V3_SVM_CPU:
406         case V3_SVM_REV3_CPU:
407             PrintDebug(core->vm_info, core, "Resetting SVM Guest CPU %d\n", core->vcpu_id);
408             return v3_reset_svm_vm_core(core, rip);
409 #endif
410 #ifdef V3_CONFIG_VMX
411         case V3_VMX_CPU:
412         case V3_VMX_EPT_CPU:
413         case V3_VMX_EPT_UG_CPU:
414             PrintDebug(core->vm_info, core, "Resetting VMX Guest CPU %d\n", core->vcpu_id);
415             return v3_reset_vmx_vm_core(core, rip);
416 #endif
417         case V3_INVALID_CPU:
418         default:
419             PrintError(core->vm_info, core, "CPU has no virtualization Extensions\n");
420             break;
421     }
422
423     return -1;
424 }
425
426
427
428 /* move a virtual core to different physical core */
429 int v3_move_vm_core(struct v3_vm_info * vm, int vcore_id, int target_cpu) {
430     struct guest_info * core = NULL;
431
432     if ((vcore_id < 0) || (vcore_id >= vm->num_cores)) {
433         PrintError(vm, VCORE_NONE, "Attempted to migrate invalid virtual core (%d)\n", vcore_id);
434         return -1;
435     }
436
437     core = &(vm->cores[vcore_id]);
438
439     if (target_cpu == core->pcpu_id) {
440         PrintError(vm,  core, "Attempted to migrate to local core (%d)\n", target_cpu);
441         // well that was pointless
442         return 0;
443     }
444
445     if (core->core_thread == NULL) {
446         PrintError(vm, core, "Attempted to migrate a core without a valid thread context\n");
447         return -1;
448     }
449
450     while (v3_raise_barrier(vm, NULL) == -1);
451
452     V3_Print(vm, core, "Performing Migration from %d to %d\n", core->pcpu_id, target_cpu);
453
454     // Double check that we weren't preemptively migrated
455     if (target_cpu != core->pcpu_id) {    
456
457         V3_Print(vm, core, "Moving Core\n");
458
459         if(v3_cpu_mapper_admit_core(vm, vcore_id, target_cpu) == -1){
460                 PrintError(vm, core, "Core %d can not be admitted in cpu %d\n",vcore_id, target_cpu);
461                 return -1;
462         }
463
464
465 #ifdef V3_CONFIG_VMX
466         switch (v3_cpu_types[core->pcpu_id]) {
467             case V3_VMX_CPU:
468             case V3_VMX_EPT_CPU:
469             case V3_VMX_EPT_UG_CPU:
470                 PrintDebug(vm, core, "Flushing VMX Guest CPU %d\n", core->vcpu_id);
471                 V3_Call_On_CPU(core->pcpu_id, (void (*)(void *))v3_flush_vmx_vm_core, (void *)core);
472                 break;
473             default:
474                 break;
475         }
476 #endif
477
478         if (V3_MOVE_THREAD_TO_CPU(target_cpu, core->core_thread) != 0) {
479             PrintError(vm, core, "Failed to move Vcore %d to CPU %d\n", 
480                        core->vcpu_id, target_cpu);
481             v3_lower_barrier(vm);
482             return -1;
483         } 
484         
485         /* There will be a benign race window here:
486            core->pcpu_id will be set to the target core before its fully "migrated"
487            However the core will NEVER run on the old core again, its just in flight to the new core
488         */
489         core->pcpu_id = target_cpu;
490
491         V3_Print(vm, core, "core now at %d\n", core->pcpu_id);  
492     }
493
494     v3_lower_barrier(vm);
495
496     return 0;
497 }
498
499 /* move a memory region to memory with affinity for a specific physical core */
500 int v3_move_vm_mem(struct v3_vm_info * vm, void *gpa, int target_cpu) {
501     int old_node;
502     int new_node;
503     struct v3_mem_region *reg;
504     void *new_hpa;
505     int num_pages;
506     void *old_hpa;
507     int i;
508
509     old_node = v3_numa_gpa_to_node(vm,(addr_t)gpa);
510
511     if (old_node<0) { 
512         PrintError(vm, VCORE_NONE, "Cannot determine current node of gpa %p\n",gpa);
513         return -1;
514     }
515
516     new_node = v3_numa_cpu_to_node(target_cpu);
517
518     if (new_node<0) { 
519         PrintError(vm, VCORE_NONE, "Cannot determine current node of cpu %d\n",target_cpu);
520         return -1;
521     }
522
523     if (new_node==old_node) { 
524         PrintDebug(vm, VCORE_NONE, "Affinity is already established - ignoring request\n");
525         return 0;
526     }
527
528     // We are now going to change the universe, so 
529     // we'll barrier everyone first
530
531     while (v3_raise_barrier(vm, NULL) == -1);
532
533     // get region
534     
535     reg = v3_get_mem_region(vm, V3_MEM_CORE_ANY, (addr_t) gpa);
536
537     if (!reg) { 
538         PrintError(vm, VCORE_NONE, "Attempt to migrate non-existent memory\n");
539         goto out_fail;
540     }
541     
542     if (!(reg->flags.base) || !(reg->flags.alloced)) { 
543         PrintError(vm, VCORE_NONE, "Attempt to migrate invalid region: base=%d alloced=%d\n", reg->flags.base, reg->flags.alloced);
544         goto out_fail;
545     }
546
547     // we now have the allocated base region corresponding to  - and not a copy
548     // we will rewrite this region after moving its contents
549     
550     // first, let's double check that we are in fact changing the numa_id...
551
552     if (reg->numa_id==new_node) { 
553         PrintDebug(vm, VCORE_NONE, "Affinity for this base region is already established - ignoring...\n");
554         goto out_success;
555     }
556
557     // region uses exclusive addressing [guest_start,guest_end)
558     num_pages = (reg->guest_end-reg->guest_start)/PAGE_SIZE;
559
560     // Now we allocate space for the new region with the same constraints as
561     // it originally had
562     new_hpa = V3_AllocPagesExtended(num_pages,
563                                     PAGE_SIZE_4KB,
564                                     new_node,
565                                     reg->flags.limit32 ? V3_ALLOC_PAGES_CONSTRAINT_4GB : 0);
566
567     if (!new_hpa) { 
568         PrintError(vm, VCORE_NONE, "Cannot allocate memory for new base region...\n");
569         goto out_fail;
570     }
571
572     // Note, assumes virtual contiguity in the host OS... 
573     memcpy(V3_VAddr((void*)new_hpa), V3_VAddr((void*)(reg->host_addr)), num_pages*PAGE_SIZE);
574
575     old_hpa = (void*)(reg->host_addr);
576     old_node = (int)(reg->numa_id);
577
578     reg->host_addr = (addr_t)new_hpa;
579     reg->numa_id = v3_numa_hpa_to_node((addr_t)new_hpa);
580
581     // flush all page tables / kill all humans 
582
583     for (i=0;i<vm->num_cores;i++) { 
584         if (vm->cores[i].shdw_pg_mode==SHADOW_PAGING) { 
585             v3_invalidate_shadow_pts(&(vm->cores[i]));
586         } else if (vm->cores[i].shdw_pg_mode==NESTED_PAGING) { 
587             // nested invalidator uses inclusive addressing [start,end], not [start,end)
588             v3_invalidate_nested_addr_range(&(vm->cores[i]),reg->guest_start,reg->guest_end-1);
589         } else {
590             PrintError(vm,VCORE_NONE, "Cannot determine how to invalidate paging structures! Reverting to previous region.\n");
591             // We'll restore things...
592             reg->host_addr = (addr_t) old_hpa;
593             reg->numa_id = old_node;
594             V3_FreePages(new_hpa,num_pages);
595             goto out_fail;
596         }
597     }
598     
599     // Now the old region can go away...
600     V3_FreePages(old_hpa,num_pages);
601     
602     PrintDebug(vm,VCORE_NONE,"Migration of memory complete - new region is %p to %p\n",
603                (void*)(reg->host_addr),(void*)(reg->host_addr+num_pages*PAGE_SIZE-1));
604     
605  out_success:
606     v3_lower_barrier(vm);
607     return 0;
608     
609     
610  out_fail:
611     v3_lower_barrier(vm);
612     return -1;
613 }
614
615 int v3_stop_vm(struct v3_vm_info * vm) {
616
617     struct guest_info * running_core;
618
619     if ((vm->run_state != VM_RUNNING) && 
620         (vm->run_state != VM_SIMULATING)) {
621         PrintError(vm, VCORE_NONE,"Tried to stop VM in invalid runstate (%d)\n", vm->run_state);
622         return -1;
623     }
624
625     vm->run_state = VM_STOPPED;
626
627     // Sanity check to catch any weird execution states
628     if (v3_wait_for_barrier(vm, NULL) == 0) {
629         v3_lower_barrier(vm);
630     }
631     
632     // XXX force exit all cores via a cross call/IPI XXX
633
634     while (1) {
635         int i = 0;
636         int still_running = 0;
637
638         for (i = 0; i < vm->num_cores; i++) {
639             if (vm->cores[i].core_run_state != CORE_STOPPED) {
640                 running_core = &vm->cores[i];
641                 still_running = 1;
642             }
643         }
644
645         if (still_running == 0) {
646             break;
647         }
648
649         v3_scheduler_stop_core(running_core);
650     }
651     
652     V3_Print(vm, VCORE_NONE,"VM stopped. Returning\n");
653
654     return 0;
655 }
656
657
658 int v3_pause_vm(struct v3_vm_info * vm) {
659
660     if (vm->run_state != VM_RUNNING) {
661         PrintError(vm, VCORE_NONE,"Tried to pause a VM that was not running\n");
662         return -1;
663     }
664
665     while (v3_raise_barrier(vm, NULL) == -1);
666
667     vm->run_state = VM_PAUSED;
668
669     return 0;
670 }
671
672
673 int v3_continue_vm(struct v3_vm_info * vm) {
674
675     if (vm->run_state != VM_PAUSED) {
676         PrintError(vm, VCORE_NONE,"Tried to continue a VM that was not paused\n");
677         return -1;
678     }
679
680     vm->run_state = VM_RUNNING;
681
682     v3_lower_barrier(vm);
683
684     return 0;
685 }
686
687
688
689 static int sim_callback(struct guest_info * core, void * private_data) {
690     struct v3_bitmap * timeout_map = private_data;
691
692     v3_bitmap_set(timeout_map, core->vcpu_id);
693     
694     V3_Print(core->vm_info, core, "Simulation callback activated (guest_rip=%p)\n", (void *)core->rip);
695
696     while (v3_bitmap_check(timeout_map, core->vcpu_id) == 1) {
697         // We spin here if there is noone to yield to
698         v3_yield(NULL,-1);
699     }
700
701     return 0;
702 }
703
704
705
706
707 int v3_simulate_vm(struct v3_vm_info * vm, unsigned int msecs) {
708     struct v3_bitmap timeout_map;
709     int i = 0;
710     int all_blocked = 0;
711     uint64_t cycles = 0;
712     uint64_t cpu_khz = V3_CPU_KHZ();
713
714     if (vm->run_state != VM_PAUSED) {
715         PrintError(vm, VCORE_NONE,"VM must be paused before simulation begins\n");
716         return -1;
717     }
718
719     /* AT this point VM is paused */
720     
721     // initialize bitmap
722     v3_bitmap_init(&timeout_map, vm->num_cores);
723
724
725
726
727     // calculate cycles from msecs...
728     // IMPORTANT: Floating point not allowed.
729     cycles = (msecs * cpu_khz);
730     
731
732
733     V3_Print(vm, VCORE_NONE,"Simulating %u msecs (%llu cycles) [CPU_KHZ=%llu]\n", msecs, cycles, cpu_khz);
734
735     // set timeout
736     
737     for (i = 0; i < vm->num_cores; i++) {
738         if (v3_add_core_timeout(&(vm->cores[i]), cycles, sim_callback, &timeout_map) == -1) {
739             PrintError(vm, VCORE_NONE,"Could not register simulation timeout for core %d\n", i);
740             return -1;
741         }
742     }
743
744     V3_Print(vm, VCORE_NONE,"timeouts set on all cores\n ");
745
746     
747     // Run the simulation
748 //    vm->run_state = VM_SIMULATING;
749     vm->run_state = VM_RUNNING;
750     v3_lower_barrier(vm);
751
752
753     V3_Print(vm, VCORE_NONE,"Barrier lowered: We are now Simulating!!\n");
754
755     // block until simulation is complete    
756     while (all_blocked == 0) {
757         all_blocked = 1;
758
759         for (i = 0; i < vm->num_cores; i++) {
760             if (v3_bitmap_check(&timeout_map, i)  == 0) {
761                 all_blocked = 0;
762             }
763         }
764
765         if (all_blocked == 1) {
766             break;
767         }
768         
769         // Intentionally spin if there is no one to yield to
770         v3_yield(NULL,-1);
771     }
772
773
774     V3_Print(vm, VCORE_NONE,"Simulation is complete\n");
775
776     // Simulation is complete
777     // Reset back to PAUSED state
778
779     v3_raise_barrier_nowait(vm, NULL);
780     vm->run_state = VM_PAUSED;
781     
782     v3_bitmap_reset(&timeout_map);
783
784     v3_wait_for_barrier(vm, NULL);
785
786     return 0;
787
788 }
789
790 int v3_get_state_vm(struct v3_vm_info        *vm, 
791                     struct v3_vm_base_state  *base,
792                     struct v3_vm_core_state  *core,
793                     struct v3_vm_mem_state   *mem)
794 {
795     uint32_t i;
796     uint32_t numcores = core->num_vcores > vm->num_cores ? vm->num_cores : core->num_vcores;
797     uint32_t numregions = mem->num_regions > vm->mem_map.num_base_regions ? vm->mem_map.num_base_regions : mem->num_regions;
798     extern uint64_t v3_mem_block_size;
799
800     switch (vm->run_state) { 
801         case VM_INVALID: base->state = V3_VM_INVALID; break;
802         case VM_RUNNING: base->state = V3_VM_RUNNING; break;
803         case VM_STOPPED: base->state = V3_VM_STOPPED; break;
804         case VM_PAUSED: base->state = V3_VM_PAUSED; break;
805         case VM_ERROR: base->state = V3_VM_ERROR; break;
806         case VM_SIMULATING: base->state = V3_VM_SIMULATING; break;
807         default: base->state = V3_VM_UNKNOWN; break;
808     }
809
810     for (i=0;i<numcores;i++) {
811         switch (vm->cores[i].core_run_state) {
812             case CORE_INVALID: core->vcore[i].state = V3_VCORE_INVALID; break;
813             case CORE_RUNNING: core->vcore[i].state = V3_VCORE_RUNNING; break;
814             case CORE_STOPPED: core->vcore[i].state = V3_VCORE_STOPPED; break;
815             default: core->vcore[i].state = V3_VCORE_UNKNOWN; break;
816         }
817         switch (vm->cores[i].cpu_mode) {
818             case REAL: core->vcore[i].cpu_mode = V3_VCORE_CPU_REAL; break;
819             case PROTECTED: core->vcore[i].cpu_mode = V3_VCORE_CPU_PROTECTED; break;
820             case PROTECTED_PAE: core->vcore[i].cpu_mode = V3_VCORE_CPU_PROTECTED_PAE; break;
821             case LONG: core->vcore[i].cpu_mode = V3_VCORE_CPU_LONG; break;
822             case LONG_32_COMPAT: core->vcore[i].cpu_mode = V3_VCORE_CPU_LONG_32_COMPAT; break;
823             case LONG_16_COMPAT: core->vcore[i].cpu_mode = V3_VCORE_CPU_LONG_16_COMPAT; break;
824             default: core->vcore[i].cpu_mode = V3_VCORE_CPU_UNKNOWN; break;
825         }
826         switch (vm->cores[i].shdw_pg_mode) { 
827             case SHADOW_PAGING: core->vcore[i].mem_state = V3_VCORE_MEM_STATE_SHADOW; break;
828             case NESTED_PAGING: core->vcore[i].mem_state = V3_VCORE_MEM_STATE_NESTED; break;
829             default: core->vcore[i].mem_state = V3_VCORE_MEM_STATE_UNKNOWN; break;
830         }
831         switch (vm->cores[i].mem_mode) { 
832             case PHYSICAL_MEM: core->vcore[i].mem_mode = V3_VCORE_MEM_MODE_PHYSICAL; break;
833             case VIRTUAL_MEM: core->vcore[i].mem_mode=V3_VCORE_MEM_MODE_VIRTUAL; break;
834             default: core->vcore[i].mem_mode=V3_VCORE_MEM_MODE_UNKNOWN; break;
835         }
836         
837         core->vcore[i].pcore=vm->cores[i].pcpu_id;
838         core->vcore[i].last_rip=(void*)(vm->cores[i].rip);
839         core->vcore[i].num_exits=vm->cores[i].num_exits;
840     }
841     
842     core->num_vcores=numcores;
843
844     for (i=0;i<vm->mem_map.num_base_regions;i++) {
845         mem->region[i].host_paddr =  (void*)(vm->mem_map.base_regions[i].host_addr);
846         mem->region[i].size = v3_mem_block_size;
847     }
848
849     mem->num_regions=numregions;
850     
851     return 0;
852 }
853
854
855 #ifdef V3_CONFIG_CHECKPOINT
856 #include <palacios/vmm_checkpoint.h>
857
858 int v3_save_vm(struct v3_vm_info * vm, char * store, char * url, v3_chkpt_options_t opts) {
859   return v3_chkpt_save_vm(vm, store, url, opts);
860 }
861
862
863 int v3_load_vm(struct v3_vm_info * vm, char * store, char * url, v3_chkpt_options_t opts) {
864   return v3_chkpt_load_vm(vm, store, url, opts);
865 }
866
867 #ifdef V3_CONFIG_LIVE_MIGRATION
868 int v3_send_vm(struct v3_vm_info * vm, char * store, char * url, v3_chkpt_options_t opts) {
869   return v3_chkpt_send_vm(vm, store, url, opts);
870 }
871
872
873 int v3_receive_vm(struct v3_vm_info * vm, char * store, char * url, v3_chkpt_options_t opts) {
874   return v3_chkpt_receive_vm(vm, store, url, opts);
875 }
876 #endif
877
878 #endif
879
880
881 int v3_free_vm(struct v3_vm_info * vm) {
882     int i = 0;
883     // deinitialize guest (free memory, etc...)
884
885     if ((vm->run_state != VM_STOPPED) &&
886         (vm->run_state != VM_ERROR)) {
887         PrintError(vm, VCORE_NONE,"Tried to Free VM in invalid runstate (%d)\n", vm->run_state);
888         return -1;
889     }
890
891     v3_free_vm_devices(vm);
892
893     // free cores
894     for (i = 0; i < vm->num_cores; i++) {
895         v3_scheduler_free_core(&(vm->cores[i]));
896         v3_free_core(&(vm->cores[i]));
897     }
898
899     // free vm
900     v3_scheduler_free_vm(vm);
901     v3_free_vm_internal(vm);
902
903     v3_free_config(vm);
904
905     V3_Free(vm);
906
907     return 0;
908 }
909
910
911 #ifdef __V3_32BIT__
912
913 v3_cpu_mode_t v3_get_host_cpu_mode() {
914     uint32_t cr4_val;
915     struct cr4_32 * cr4;
916
917     __asm__ (
918              "movl %%cr4, %0; "
919              : "=r"(cr4_val) 
920              );
921
922     
923     cr4 = (struct cr4_32 *)&(cr4_val);
924
925     if (cr4->pae == 1) {
926         return PROTECTED_PAE;
927     } else {
928         return PROTECTED;
929     }
930 }
931
932 #elif __V3_64BIT__
933
934 v3_cpu_mode_t v3_get_host_cpu_mode() {
935     return LONG;
936 }
937
938 #endif 
939
940 void v3_print_cond(const char * fmt, ...) {
941     if (v3_dbg_enable == 1) {
942         char buf[2048];
943         va_list ap;
944
945         va_start(ap, fmt);
946         vsnprintf(buf, 2048, fmt, ap);
947         va_end(ap);
948
949         V3_Print(VM_NONE, VCORE_NONE,"%s", buf);
950     }    
951 }
952
953
954
955 void v3_interrupt_cpu(struct v3_vm_info * vm, int logical_cpu, int vector) {
956     extern struct v3_os_hooks * os_hooks;
957
958     if ((os_hooks) && (os_hooks)->interrupt_cpu) {
959         (os_hooks)->interrupt_cpu(vm, logical_cpu, vector);
960     }
961 }
962
963
964
965 int v3_vm_enter(struct guest_info * info) {
966     switch (v3_mach_type) {
967 #ifdef V3_CONFIG_SVM
968         case V3_SVM_CPU:
969         case V3_SVM_REV3_CPU:
970             return v3_svm_enter(info);
971             break;
972 #endif
973 #if V3_CONFIG_VMX
974         case V3_VMX_CPU:
975         case V3_VMX_EPT_CPU:
976         case V3_VMX_EPT_UG_CPU:
977             return v3_vmx_enter(info);
978             break;
979 #endif
980         default:
981             PrintError(info->vm_info, info, "Attemping to enter a guest on an invalid CPU\n");
982             return -1;
983     }
984 }
985
986
987 void    *v3_get_host_vm(struct v3_vm_info *x)
988 {
989   if (x) { 
990     return x->host_priv_data;
991   } else {
992     return 0;
993   }
994 }
995
996 int v3_get_vcore(struct guest_info *x)
997 {
998   if (x) {
999     return x->vcpu_id;
1000   } else {
1001     return -1;
1002   }
1003 }