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.


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