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.


Cleanup based on cppcheck pass (Core)
[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 #include <interfaces/vmm_file.h>
35
36 #ifdef V3_CONFIG_SVM
37 #include <palacios/svm.h>
38 #endif
39 #ifdef V3_CONFIG_VMX
40 #include <palacios/vmx.h>
41 #endif
42
43 #ifdef V3_CONFIG_CHECKPOINT
44 #include <palacios/vmm_checkpoint.h>
45 #endif
46
47
48 v3_cpu_arch_t v3_cpu_types[V3_CONFIG_MAX_CPUS];
49 v3_cpu_arch_t v3_mach_type = V3_INVALID_CPU;
50
51 struct v3_os_hooks * os_hooks = NULL;
52 int v3_dbg_enable = 0;
53
54
55
56 static void init_cpu(void * arg) {
57     uint32_t cpu_id = (uint32_t)(addr_t)arg;
58
59     v3_init_fp();
60
61 #ifdef V3_CONFIG_SVM
62     if (v3_is_svm_capable()) {
63         PrintDebug(VM_NONE, VCORE_NONE, "Machine is SVM Capable\n");
64         v3_init_svm_cpu(cpu_id);
65         
66     } else 
67 #endif
68 #ifdef V3_CONFIG_VMX
69     if (v3_is_vmx_capable()) {
70         PrintDebug(VM_NONE, VCORE_NONE, "Machine is VMX Capable\n");
71         v3_init_vmx_cpu(cpu_id);
72
73     } else 
74 #endif
75     {
76        PrintError(VM_NONE, VCORE_NONE, "CPU has no virtualization Extensions\n");
77     }
78 }
79
80
81 static void deinit_cpu(void * arg) {
82     uint32_t cpu_id = (uint32_t)(addr_t)arg;
83
84
85     switch (v3_cpu_types[cpu_id]) {
86 #ifdef V3_CONFIG_SVM
87         case V3_SVM_CPU:
88         case V3_SVM_REV3_CPU:
89             PrintDebug(VM_NONE, VCORE_NONE, "Deinitializing SVM CPU %d\n", cpu_id);
90             v3_deinit_svm_cpu(cpu_id);
91             break;
92 #endif
93 #ifdef V3_CONFIG_VMX
94         case V3_VMX_CPU:
95         case V3_VMX_EPT_CPU:
96         case V3_VMX_EPT_UG_CPU:
97             PrintDebug(VM_NONE, VCORE_NONE, "Deinitializing VMX CPU %d\n", cpu_id);
98             v3_deinit_vmx_cpu(cpu_id);
99             break;
100 #endif
101         case V3_INVALID_CPU:
102         default:
103             PrintError(VM_NONE, VCORE_NONE, "CPU has no virtualization Extensions\n");
104             break;
105     }
106
107     v3_deinit_fp();
108
109 }
110
111
112 static int in_long_mode()
113 {
114   uint32_t high, low;
115
116   v3_get_msr(0xc0000080,&high,&low); // EFER
117   
118   return ((low & 0x500)== 0x500);  // LMA and LME set
119 }
120   
121
122 void Init_V3(struct v3_os_hooks * hooks, char * cpu_mask, int num_cpus, char *options) {
123     int i = 0;
124     int minor = 0;
125     int major = 0;
126
127     V3_Print(VM_NONE, VCORE_NONE, "V3 Print statement to fix a Kitten page fault bug\n");
128
129
130
131 #ifndef __V3_64BIT__
132 #error Palacios does not support compilation for a 32 bit host OS!!!!
133 #else
134     if (!in_long_mode()) { 
135       PrintError(VM_NONE,VCORE_NONE,"Palacios supports execution only in long mode (64 bit).\n");
136       return;
137     }
138 #endif
139
140     // Set global variables. 
141     os_hooks = hooks;
142
143     if (num_cpus>V3_CONFIG_MAX_CPUS) { 
144         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);
145     }
146
147     // Determine the global machine type
148     v3_mach_type = V3_INVALID_CPU;
149
150     for (i = 0; i < V3_CONFIG_MAX_CPUS; i++) {
151         v3_cpu_types[i] = V3_INVALID_CPU;
152     }
153
154     // Parse host-os defined options into an easily-accessed format.
155     v3_parse_options(options);
156
157 #ifdef V3_CONFIG_MULTIBOOT
158     v3_init_multiboot();
159 #endif
160
161 #ifdef V3_CONFIG_HVM
162     v3_init_hvm();
163 #endif
164
165     // Memory manager initialization
166     v3_init_mem();
167
168     // Register all the possible device types
169     V3_init_devices();
170
171     // Register all shadow paging handlers
172     V3_init_shdw_paging();
173
174 #ifdef V3_CONFIG_SWAPPING
175     v3_init_swapping();
176 #endif
177
178     // Initialize the cpu_mapper framework (must be before extensions)
179     V3_init_cpu_mapper();
180
181     // Initialize the scheduler framework (must be before extensions)
182     V3_init_scheduling();
183  
184     // Register all extensions
185     V3_init_extensions();
186
187     // Enabling cpu_mapper
188     V3_enable_cpu_mapper();
189
190     // Enabling scheduler
191     V3_enable_scheduler();
192
193
194 #ifdef V3_CONFIG_SYMMOD
195     V3_init_symmod();
196 #endif
197
198 #ifdef V3_CONFIG_CHECKPOINT
199     V3_init_checkpoint();
200 #endif
201
202     if ((hooks) && (hooks->call_on_cpu)) {
203
204         for (i = 0; i < num_cpus && i < V3_CONFIG_MAX_CPUS; i++) {
205             major = i / 8;
206             minor = i % 8;
207
208             if ((cpu_mask == NULL) || (*(cpu_mask + major) & (0x1 << minor))) {
209                 V3_Print(VM_NONE, VCORE_NONE, "Initializing VMM extensions on cpu %d\n", i);
210                 hooks->call_on_cpu(i, &init_cpu, (void *)(addr_t)i);
211
212                 if (v3_mach_type == V3_INVALID_CPU) {
213                     v3_mach_type = v3_cpu_types[i];
214                 }   
215             }
216         }
217     }
218 }
219
220
221
222 void Shutdown_V3() {
223     int i;
224
225     // Reverse order of Init_V3
226
227     // bring down CPUs
228
229     if ((os_hooks) && (os_hooks->call_on_cpu)) {
230         for (i = 0; i < V3_CONFIG_MAX_CPUS; i++) {
231             if (v3_cpu_types[i] != V3_INVALID_CPU) {
232                 V3_Call_On_CPU(i, deinit_cpu, (void *)(addr_t)i);
233                 //deinit_cpu((void *)(addr_t)i);
234             }
235         }
236     }
237
238 #ifdef V3_CONFIG_CHECKPOINT
239     V3_deinit_checkpoint();
240 #endif
241
242 #ifdef V3_CONFIG_SYMMOD
243     V3_deinit_symmod();
244 #endif
245
246     V3_disable_scheduler();
247
248     V3_disable_cpu_mapper();
249
250     V3_deinit_extensions();
251
252     V3_deinit_scheduling();
253     
254     V3_deinit_cpu_mapper();
255
256 #ifdef V3_CONFIG_SWAPPING
257     v3_deinit_swapping();
258 #endif
259     
260     V3_deinit_shdw_paging();
261     
262     V3_deinit_devices();
263
264     v3_deinit_mem();
265     
266 #ifdef V3_CONFIG_HVM
267     v3_deinit_hvm();
268 #endif
269
270 #ifdef V3_CONFIG_MULTIBOOT
271     v3_deinit_multiboot();
272 #endif
273
274     v3_deinit_options();
275     
276
277 }
278
279
280 v3_cpu_arch_t v3_get_cpu_type(int cpu_id) {
281     return v3_cpu_types[cpu_id];
282 }
283
284 static int start_core(void * p)
285 {
286     struct guest_info * core = (struct guest_info *)p;
287
288     if (v3_scheduler_register_core(core) == -1){
289         PrintError(core->vm_info, core,"Error initializing scheduling in core %d\n", core->vcpu_id);
290     }
291
292     PrintDebug(core->vm_info,core,"virtual core %u (on logical core %u): in start_core (RIP=%p)\n",
293                core->vcpu_id, core->pcpu_id, (void *)(addr_t)core->rip);
294
295     switch (v3_mach_type) {
296 #ifdef V3_CONFIG_SVM
297         case V3_SVM_CPU:
298         case V3_SVM_REV3_CPU:
299             return v3_start_svm_guest(core);
300             break;
301 #endif
302 #if V3_CONFIG_VMX
303         case V3_VMX_CPU:
304         case V3_VMX_EPT_CPU:
305         case V3_VMX_EPT_UG_CPU:
306             return v3_start_vmx_guest(core);
307             break;
308 #endif
309         default:
310             PrintError(core->vm_info, core, "Attempting to enter a guest on an invalid CPU\n");
311             return -1;
312     }
313     // should not happen
314     return 0;
315 }
316
317 struct v3_vm_info * v3_create_vm(void * cfg, void * priv_data, char * name, unsigned int cpu_mask) {
318     struct v3_vm_info * vm = v3_config_guest(cfg, priv_data);
319     int vcore_id = 0;
320
321     if (vm == NULL) {
322         PrintError(VM_NONE, VCORE_NONE, "Could not configure guest\n");
323         return NULL;
324     }
325
326     V3_Print(vm, VCORE_NONE, "CORE 0 RIP=%p\n", (void *)(addr_t)(vm->cores[0].rip));
327
328     if (name == NULL) {
329         name = "[V3_VM]";
330     } else if (strlen(name) >= 128) {
331         PrintError(vm, VCORE_NONE,"VM name is too long. Will be truncated to 128 chars.\n");
332     }
333
334     memset(vm->name, 0, 128);
335     strncpy(vm->name, name, 127);
336
337     if(v3_cpu_mapper_register_vm(vm) == -1) {
338
339         PrintError(vm, VCORE_NONE,"Error registering VM with cpu_mapper\n");
340     }
341
342     /*
343      * Register this VM with the palacios scheduler. It will ask for admission
344      * prior to launch.
345      */
346     if(v3_scheduler_register_vm(vm) == -1) {
347     
348         PrintError(vm, VCORE_NONE,"Error registering VM with scheduler\n");
349     }
350
351     if (v3_cpu_mapper_admit_vm(vm,cpu_mask) != 0){
352         PrintError(vm, VCORE_NONE,"Error admitting VM %s for mapping", vm->name);
353     }
354
355     for (vcore_id = 0; vcore_id < vm->num_cores; vcore_id++) {
356
357         struct guest_info * core = &(vm->cores[vcore_id]);
358
359         PrintDebug(vm, VCORE_NONE, "Creating virtual core %u on logical core %u\n",
360                    vcore_id, core->pcpu_id);
361
362         sprintf(core->exec_name, "%s-%d", vm->name, vcore_id);
363
364         PrintDebug(vm, VCORE_NONE, "run: core=%u, func=0x%p, arg=0x%p, name=%s\n",
365                    core->pcpu_id, start_core, core, core->exec_name);
366
367         core->core_thread = V3_CREATE_THREAD_ON_CPU(core->pcpu_id, start_core, core, core->exec_name);
368
369         if (core->core_thread == NULL) {
370             PrintError(vm, VCORE_NONE, "Thread creation failed\n");
371             v3_stop_vm(vm);
372             return NULL;
373         }
374
375     }
376     return vm;
377 }
378
379 int v3_start_vm(struct v3_vm_info * vm, unsigned int cpu_mask) {
380
381     uint32_t i;
382     uint8_t * core_mask = (uint8_t *)&cpu_mask; // This is to make future expansion easier
383     uint32_t avail_cores = 0;
384     int vcore_id = 0;
385
386     if (!vm) { 
387         PrintError(VM_NONE, VCORE_NONE, "Asked to start nonexistent VM\n");
388         return -1;
389     }
390
391     if (vm->run_state != VM_STOPPED) {
392         PrintError(vm, VCORE_NONE, "VM has already been launched (state=%d)\n", (int)vm->run_state);
393         return -1;
394     }
395
396 #if V3_CONFIG_MULTIBOOT
397     if (v3_setup_multiboot_vm_for_boot(vm)) { 
398         PrintError(vm, VCORE_NONE, "Multiboot setup for boot failed\n");
399         return -1;
400     }
401 #endif
402 #if V3_CONFIG_HVM
403     if (v3_setup_hvm_vm_for_boot(vm)) { 
404         PrintError(vm, VCORE_NONE, "HVM setup for boot failed\n");
405         return -1;
406     }
407 #endif
408
409     /// CHECK IF WE ARE MULTICORE ENABLED....
410
411     V3_Print(vm, VCORE_NONE, "V3 --  Starting VM (%u cores)\n", vm->num_cores);
412     V3_Print(vm, VCORE_NONE, "CORE 0 RIP=%p\n", (void *)(addr_t)(vm->cores[0].rip));
413
414
415     // Check that enough cores are present in the mask to handle vcores
416     for (i = 0; i < V3_CONFIG_MAX_CPUS; i++) {
417         int major = i / 8;
418         int minor = i % 8;
419         
420         if (core_mask[major] & (0x1 << minor)) {
421             if (v3_cpu_types[i] == V3_INVALID_CPU) {
422                 core_mask[major] &= ~(0x1 << minor);
423             } else {
424                 avail_cores++;
425             }
426         }
427     }
428
429     vm->avail_cores = avail_cores;
430
431     if (v3_scheduler_admit_vm(vm) != 0){
432        PrintError(vm, VCORE_NONE,"Error admitting VM %s for scheduling", vm->name);
433     }
434
435     vm->run_state = VM_RUNNING;
436
437     for (vcore_id = 0; vcore_id < vm->num_cores; vcore_id++) {
438
439         struct guest_info * core = &(vm->cores[vcore_id]);
440
441         PrintDebug(vm, VCORE_NONE, "Starting virtual core %u on logical core %u\n", 
442                    vcore_id, core->pcpu_id);
443
444         if (core->core_run_state==CORE_INVALID) {
445           // launch of a fresh VM
446           core->core_run_state = CORE_STOPPED;
447           // core zero will turn itself on
448         } else {
449           // this is a resume - use whatever its current run_state is
450         }
451
452         V3_START_THREAD(core->core_thread);
453
454     }
455
456     return 0;
457
458 }
459
460
461 int v3_reset_vm_core(struct guest_info * core, addr_t rip) {
462     
463     switch (v3_cpu_types[core->pcpu_id]) {
464 #ifdef V3_CONFIG_SVM
465         case V3_SVM_CPU:
466         case V3_SVM_REV3_CPU:
467             PrintDebug(core->vm_info, core, "Resetting SVM Guest CPU %d\n", core->vcpu_id);
468             return v3_reset_svm_vm_core(core, rip);
469 #endif
470 #ifdef V3_CONFIG_VMX
471         case V3_VMX_CPU:
472         case V3_VMX_EPT_CPU:
473         case V3_VMX_EPT_UG_CPU:
474             PrintDebug(core->vm_info, core, "Resetting VMX Guest CPU %d\n", core->vcpu_id);
475             return v3_reset_vmx_vm_core(core, rip);
476 #endif
477         case V3_INVALID_CPU:
478         default:
479             PrintError(core->vm_info, core, "CPU has no virtualization Extensions\n");
480             break;
481     }
482
483     return -1;
484 }
485
486
487 // resets the whole VM (non-HVM) or the ROS (HVM) 
488 int v3_reset_vm(struct v3_vm_info *vm)
489 {
490 #ifdef V3_CONFIG_HVM
491     if (vm->hvm_state.is_hvm) { 
492         return v3_reset_vm_extended(vm,V3_VM_RESET_ROS,0);
493     } else {
494         return v3_reset_vm_extended(vm,V3_VM_RESET_ALL,0);
495     }
496 #else
497     return v3_reset_vm_extended(vm,V3_VM_RESET_ALL,0);
498 #endif
499 }
500
501 int v3_reset_vm_extended(struct v3_vm_info *vm, v3_vm_reset_type t, void *data)
502 {
503     uint32_t start, end, i;
504     uint32_t newcount;
505
506     if (vm->run_state != VM_RUNNING) { 
507         PrintError(vm,VCORE_NONE,"Attempt to reset VM in state %d (must be in running state)\n",vm->run_state);
508         return -1;
509     }
510         
511
512     switch (t) { 
513         case V3_VM_RESET_ALL:
514 #ifdef V3_CONFIG_HVM
515             if (vm->hvm_state.is_hvm) { 
516                 PrintError(vm,VCORE_NONE,"Attempt to do ALL reset of HVM (not allowed)\n");
517                 return -1;
518             }
519 #endif
520             start=0; end=vm->num_cores-1;
521             break;
522 #ifdef V3_CONFIG_HVM
523         case V3_VM_RESET_HRT:
524         case V3_VM_RESET_ROS:
525             if (vm->hvm_state.is_hvm) { 
526                 if (t==V3_VM_RESET_HRT) { 
527                     start = vm->hvm_state.first_hrt_core;
528                     end = vm->num_cores-1;
529                 } else {
530                     start = 0;
531                     end = vm->hvm_state.first_hrt_core-1;
532                 }
533             } else {
534                 PrintError(vm,VCORE_NONE,"This is not an HVM and so HVM-specific resets do not apply\n");
535                 return -1;
536             }
537 #endif
538             break;
539         case V3_VM_RESET_CORE_RANGE:
540             if (data) { 
541                 start = ((uint32_t*)data)[0];
542                 end = ((uint32_t*)data)[1];
543             } else {
544                 return -1;
545             }
546             break;
547         default:
548             PrintError(vm,VCORE_NONE,"Unsupported reset type %d for this VM\n",t);
549             return -1;
550             break;
551     }
552
553     PrintDebug(vm,VCORE_NONE,"Resetting cores %d through %d\n",start,end);
554
555     newcount = end-start+1;
556     
557     for (i=start;i<=end;i++) { 
558         if (!(vm->cores[i].core_run_state == CORE_RUNNING || vm->cores[i].core_run_state == CORE_STOPPED)) {
559             PrintError(vm,VCORE_NONE,"Cannot reset VM as core %u is in state %d (must be running or stopped)\n",i,vm->cores[i].core_run_state);
560             return -1;
561         }
562     }
563
564
565     // This had better be the only thread using the barrier at this point...
566     v3_init_counting_barrier(&vm->reset_barrier,newcount);
567
568     // OK, I am the reseter, tell the relevant cores what to do
569     // each will atomically decrement the reset countdown and then
570     // spin waiting for it to hit zero.
571
572     for (i=start;i<=end;i++) { 
573         vm->cores[i].core_run_state = CORE_RESETTING;
574         // force exit of core
575         v3_interrupt_cpu(vm, vm->cores[i].pcpu_id, 0);
576     }
577     
578     // we don't wait for reset to finish
579     // because reset could have been initiated by a core
580
581     return 0;
582 }
583
584
585 /* move a virtual core to different physical core */
586 int v3_move_vm_core(struct v3_vm_info * vm, int vcore_id, int target_cpu) {
587     struct guest_info * core = NULL;
588
589     if (!vm) { 
590         PrintError(VM_NONE, VCORE_NONE, "Asked to move core of nonexistent VM\n");
591         return -1;
592     }
593
594     if ((vcore_id < 0) || (vcore_id >= vm->num_cores)) {
595         PrintError(vm, VCORE_NONE, "Attempted to migrate invalid virtual core (%d)\n", vcore_id);
596         return -1;
597     }
598
599     core = &(vm->cores[vcore_id]);
600
601     if (target_cpu == core->pcpu_id) {
602         PrintError(vm,  core, "Attempted to migrate to local core (%d)\n", target_cpu);
603         // well that was pointless
604         return 0;
605     }
606
607     if (core->core_thread == NULL) {
608         PrintError(vm, core, "Attempted to migrate a core without a valid thread context\n");
609         return -1;
610     }
611
612     while (v3_raise_barrier(vm, NULL) == -1);
613
614     V3_Print(vm, core, "Performing Migration from %d to %d\n", core->pcpu_id, target_cpu);
615
616     // Double check that we weren't preemptively migrated
617     if (target_cpu != core->pcpu_id) {    
618
619         V3_Print(vm, core, "Moving Core\n");
620
621         if(v3_cpu_mapper_admit_core(vm, vcore_id, target_cpu) == -1){
622                 PrintError(vm, core, "Core %d can not be admitted in cpu %d\n",vcore_id, target_cpu);
623                 return -1;
624         }
625
626
627 #ifdef V3_CONFIG_VMX
628         switch (v3_cpu_types[core->pcpu_id]) {
629             case V3_VMX_CPU:
630             case V3_VMX_EPT_CPU:
631             case V3_VMX_EPT_UG_CPU:
632                 PrintDebug(vm, core, "Flushing VMX Guest CPU %d\n", core->vcpu_id);
633                 V3_Call_On_CPU(core->pcpu_id, (void (*)(void *))v3_flush_vmx_vm_core, (void *)core);
634                 break;
635             default:
636                 break;
637         }
638 #endif
639
640         if (V3_MOVE_THREAD_TO_CPU(target_cpu, core->core_thread) != 0) {
641             PrintError(vm, core, "Failed to move Vcore %d to CPU %d\n", 
642                        core->vcpu_id, target_cpu);
643             v3_lower_barrier(vm);
644             return -1;
645         } 
646         
647         /* There will be a benign race window here:
648            core->pcpu_id will be set to the target core before its fully "migrated"
649            However the core will NEVER run on the old core again, its just in flight to the new core
650         */
651         core->pcpu_id = target_cpu;
652
653         V3_Print(vm, core, "core now at %d\n", core->pcpu_id);  
654     }
655
656     v3_lower_barrier(vm);
657
658     return 0;
659 }
660
661 /* move a memory region to memory with affinity for a specific physical core */
662 int v3_move_vm_mem(struct v3_vm_info * vm, void *gpa, int target_cpu) {
663     int old_node;
664     int new_node;
665     struct v3_mem_region *reg;
666     void *new_hpa;
667     int num_pages;
668     void *old_hpa;
669     int i;
670
671     if (!vm) { 
672         PrintError(VM_NONE, VCORE_NONE, "Asked to move memory of nonexistent VM\n");
673         return -1;
674     }
675
676     old_node = v3_numa_gpa_to_node(vm,(addr_t)gpa);
677
678     if (old_node<0) { 
679         PrintError(vm, VCORE_NONE, "Cannot determine current node of gpa %p\n",gpa);
680         return -1;
681     }
682
683     new_node = v3_numa_cpu_to_node(target_cpu);
684
685     if (new_node<0) { 
686         PrintError(vm, VCORE_NONE, "Cannot determine current node of cpu %d\n",target_cpu);
687         return -1;
688     }
689
690     if (new_node==old_node) { 
691         PrintDebug(vm, VCORE_NONE, "Affinity is already established - ignoring request\n");
692         return 0;
693     }
694
695     // We are now going to change the universe, so 
696     // we'll barrier everyone first
697
698     while (v3_raise_barrier(vm, NULL) == -1);
699
700     // get region
701     
702     reg = v3_get_mem_region(vm, V3_MEM_CORE_ANY, (addr_t) gpa);
703
704     if (!reg) { 
705         PrintError(vm, VCORE_NONE, "Attempt to migrate non-existent memory\n");
706         goto out_fail;
707     }
708     
709     if (!(reg->flags.base) || !(reg->flags.alloced)) { 
710         PrintError(vm, VCORE_NONE, "Attempt to migrate invalid region: base=%d alloced=%d\n", reg->flags.base, reg->flags.alloced);
711         goto out_fail;
712     }
713
714     // we now have the allocated base region corresponding to  - and not a copy
715     // we will rewrite this region after moving its contents
716     
717     // first, let's double check that we are in fact changing the numa_id...
718
719     if (reg->numa_id==new_node) { 
720         PrintDebug(vm, VCORE_NONE, "Affinity for this base region is already established - ignoring...\n");
721         goto out_success;
722     }
723
724     // region uses exclusive addressing [guest_start,guest_end)
725     num_pages = (reg->guest_end-reg->guest_start)/PAGE_SIZE;
726
727     new_hpa = V3_AllocPagesExtended(num_pages,
728                                     PAGE_SIZE_4KB,
729                                     new_node,
730                                     0, 0);  // no constraints given new shadow pager impl
731
732     if (!new_hpa) { 
733         PrintError(vm, VCORE_NONE, "Cannot allocate memory for new base region...\n");
734         goto out_fail;
735     }
736
737     // Note, assumes virtual contiguity in the host OS... 
738     memcpy(V3_VAddr((void*)new_hpa), V3_VAddr((void*)(reg->host_addr)), num_pages*PAGE_SIZE);
739
740     old_hpa = (void*)(reg->host_addr);
741     old_node = (int)(reg->numa_id);
742
743     reg->host_addr = (addr_t)new_hpa;
744     reg->numa_id = v3_numa_hpa_to_node((addr_t)new_hpa);
745
746     // flush all page tables / kill all humans 
747
748     for (i=0;i<vm->num_cores;i++) { 
749         if (vm->cores[i].shdw_pg_mode==SHADOW_PAGING) { 
750             v3_invalidate_shadow_pts(&(vm->cores[i]));
751         } else if (vm->cores[i].shdw_pg_mode==NESTED_PAGING) { 
752             // nested invalidator uses inclusive addressing [start,end], not [start,end)
753           v3_invalidate_nested_addr_range(&(vm->cores[i]),reg->guest_start,reg->guest_end-1,NULL,NULL);
754         } else {
755             PrintError(vm,VCORE_NONE, "Cannot determine how to invalidate paging structures! Reverting to previous region.\n");
756             // We'll restore things...
757             reg->host_addr = (addr_t) old_hpa;
758             reg->numa_id = old_node;
759             V3_FreePages(new_hpa,num_pages);
760             goto out_fail;
761         }
762     }
763     
764     // Now the old region can go away...
765     V3_FreePages(old_hpa,num_pages);
766     
767     PrintDebug(vm,VCORE_NONE,"Migration of memory complete - new region is %p to %p\n",
768                (void*)(reg->host_addr),(void*)(reg->host_addr+num_pages*PAGE_SIZE-1));
769     
770  out_success:
771     v3_lower_barrier(vm);
772     return 0;
773     
774     
775  out_fail:
776     v3_lower_barrier(vm);
777     return -1;
778 }
779
780 int v3_stop_vm(struct v3_vm_info * vm) {
781
782     struct guest_info * running_core;
783
784     if (!vm) { 
785         PrintError(VM_NONE, VCORE_NONE, "Asked to stop nonexistent VM\n");
786         return -1;
787     }
788
789     if ((vm->run_state != VM_RUNNING) && 
790         (vm->run_state != VM_SIMULATING)) {
791         PrintError(vm, VCORE_NONE,"Tried to stop VM in invalid runstate (%d)\n", vm->run_state);
792         return -1;
793     }
794
795     vm->run_state = VM_STOPPED;
796
797     // Sanity check to catch any weird execution states
798     if (v3_wait_for_barrier(vm, NULL) == 0) {
799         v3_lower_barrier(vm);
800     }
801     
802     // XXX force exit all cores via a cross call/IPI XXX
803
804     while (1) {
805         int i = 0;
806         int still_running = 0;
807
808         for (i = 0; i < vm->num_cores; i++) {
809             if (vm->cores[i].core_run_state != CORE_STOPPED) {
810                 running_core = &vm->cores[i];
811                 still_running = 1;
812             }
813         }
814
815         if (still_running == 0) {
816             break;
817         }
818
819         v3_scheduler_stop_core(running_core);
820     }
821     
822     V3_Print(vm, VCORE_NONE,"VM stopped. Returning\n");
823
824     return 0;
825 }
826
827
828 int v3_pause_vm(struct v3_vm_info * vm) {
829
830     if (!vm) { 
831         PrintError(VM_NONE, VCORE_NONE, "Asked to pause nonexistent VM\n");
832         return -1;
833     }
834
835     if (vm->run_state != VM_RUNNING) {
836         PrintError(vm, VCORE_NONE,"Tried to pause a VM that was not running\n");
837         return -1;
838     }
839
840     while (v3_raise_barrier(vm, NULL) == -1);
841
842     vm->run_state = VM_PAUSED;
843
844     return 0;
845 }
846
847
848 int v3_continue_vm(struct v3_vm_info * vm) {
849
850     if (!vm) { 
851         PrintError(VM_NONE, VCORE_NONE, "Asked to continue nonexistent VM\n");
852         return -1;
853     }
854
855     if (vm->run_state != VM_PAUSED) {
856         PrintError(vm, VCORE_NONE,"Tried to continue a VM that was not paused\n");
857         return -1;
858     }
859
860     vm->run_state = VM_RUNNING;
861
862     v3_lower_barrier(vm);
863
864     return 0;
865 }
866
867
868
869 static int sim_callback(struct guest_info * core, void * private_data) {
870     struct v3_bitmap * timeout_map = private_data;
871
872     v3_bitmap_set(timeout_map, core->vcpu_id);
873     
874     V3_Print(core->vm_info, core, "Simulation callback activated (guest_rip=%p)\n", (void *)core->rip);
875
876     while (v3_bitmap_check(timeout_map, core->vcpu_id) == 1) {
877         // We spin here if there is noone to yield to
878         v3_yield(NULL,-1);
879     }
880
881     return 0;
882 }
883
884
885
886
887 int v3_simulate_vm(struct v3_vm_info * vm, unsigned int msecs) {
888     struct v3_bitmap timeout_map;
889     int i = 0;
890     int all_blocked = 0;
891     uint64_t cycles = 0;
892     uint64_t cpu_khz = V3_CPU_KHZ();
893
894     if (!vm) { 
895         PrintError(VM_NONE, VCORE_NONE, "Asked to simulate nonexistent VM\n");
896         return -1;
897     }
898
899     if (vm->run_state != VM_PAUSED) {
900         PrintError(vm, VCORE_NONE,"VM must be paused before simulation begins\n");
901         return -1;
902     }
903
904     /* AT this point VM is paused */
905     
906     // initialize bitmap
907     v3_bitmap_init(&timeout_map, vm->num_cores);
908
909
910
911
912     // calculate cycles from msecs...
913     // IMPORTANT: Floating point not allowed.
914     cycles = (msecs * cpu_khz);
915     
916
917
918     V3_Print(vm, VCORE_NONE,"Simulating %u msecs (%llu cycles) [CPU_KHZ=%llu]\n", msecs, cycles, cpu_khz);
919
920     // set timeout
921     
922     for (i = 0; i < vm->num_cores; i++) {
923         if (v3_add_core_timeout(&(vm->cores[i]), cycles, sim_callback, &timeout_map) == -1) {
924             PrintError(vm, VCORE_NONE,"Could not register simulation timeout for core %d\n", i);
925             return -1;
926         }
927     }
928
929     V3_Print(vm, VCORE_NONE,"timeouts set on all cores\n ");
930
931     
932     // Run the simulation
933 //    vm->run_state = VM_SIMULATING;
934     vm->run_state = VM_RUNNING;
935     v3_lower_barrier(vm);
936
937
938     V3_Print(vm, VCORE_NONE,"Barrier lowered: We are now Simulating!!\n");
939
940     // block until simulation is complete    
941     while (all_blocked == 0) {
942         all_blocked = 1;
943
944         for (i = 0; i < vm->num_cores; i++) {
945             if (v3_bitmap_check(&timeout_map, i)  == 0) {
946                 all_blocked = 0;
947             }
948         }
949
950         if (all_blocked == 1) {
951             break;
952         }
953         
954         // Intentionally spin if there is no one to yield to
955         v3_yield(NULL,-1);
956     }
957
958
959     V3_Print(vm, VCORE_NONE,"Simulation is complete\n");
960
961     // Simulation is complete
962     // Reset back to PAUSED state
963
964     v3_raise_barrier_nowait(vm, NULL);
965     vm->run_state = VM_PAUSED;
966     
967     v3_bitmap_reset(&timeout_map);
968
969     v3_wait_for_barrier(vm, NULL);
970
971     return 0;
972
973 }
974
975 int v3_get_state_vm(struct v3_vm_info        *vm, 
976                     struct v3_vm_base_state  *base,
977                     struct v3_vm_core_state  *core,
978                     struct v3_vm_mem_state   *mem)
979 {
980     uint32_t i;
981     uint32_t numcores;
982     uint32_t numregions; 
983     extern uint64_t v3_mem_block_size;
984     void     *cur_gpa;
985
986     if (!vm || !base || !core || !mem)  { 
987         PrintError(VM_NONE, VCORE_NONE, "Invalid request to v3_get_state_vm\n");
988         return -1;
989     }
990
991     numcores = core->num_vcores > vm->num_cores ? vm->num_cores : core->num_vcores;
992     numregions = mem->num_regions > vm->mem_map.num_base_regions ? vm->mem_map.num_base_regions : mem->num_regions;
993
994     switch (vm->run_state) { 
995         case VM_INVALID: base->state = V3_VM_INVALID; break;
996         case VM_RUNNING: base->state = V3_VM_RUNNING; break;
997         case VM_STOPPED: base->state = V3_VM_STOPPED; break;
998         case VM_PAUSED: base->state = V3_VM_PAUSED; break;
999         case VM_ERROR: base->state = V3_VM_ERROR; break;
1000         case VM_SIMULATING: base->state = V3_VM_SIMULATING; break;
1001         case VM_RESETTING: base->state = V3_VM_RESETTING; break;
1002         default: base->state = V3_VM_UNKNOWN; break;
1003     }
1004
1005     base->vm_type = V3_VM_GENERAL;
1006
1007 #ifdef V3_CONFIG_HVM
1008     if (vm->hvm_state.is_hvm) { 
1009         base->vm_type = V3_VM_HVM;
1010     } 
1011 #endif
1012
1013     for (i=0;i<numcores;i++) {
1014         switch (vm->cores[i].core_run_state) {
1015             case CORE_INVALID: core->vcore[i].state = V3_VCORE_INVALID; break;
1016             case CORE_RUNNING: core->vcore[i].state = V3_VCORE_RUNNING; break;
1017             case CORE_STOPPED: core->vcore[i].state = V3_VCORE_STOPPED; break;
1018             case CORE_RESETTING: core->vcore[i].state = V3_VCORE_RESETTING; break;
1019             default: core->vcore[i].state = V3_VCORE_UNKNOWN; break;
1020         }
1021         switch (vm->cores[i].cpu_mode) {
1022             case REAL: core->vcore[i].cpu_mode = V3_VCORE_CPU_REAL; break;
1023             case PROTECTED: core->vcore[i].cpu_mode = V3_VCORE_CPU_PROTECTED; break;
1024             case PROTECTED_PAE: core->vcore[i].cpu_mode = V3_VCORE_CPU_PROTECTED_PAE; break;
1025             case LONG: core->vcore[i].cpu_mode = V3_VCORE_CPU_LONG; break;
1026             case LONG_32_COMPAT: core->vcore[i].cpu_mode = V3_VCORE_CPU_LONG_32_COMPAT; break;
1027             case LONG_16_COMPAT: core->vcore[i].cpu_mode = V3_VCORE_CPU_LONG_16_COMPAT; break;
1028             default: core->vcore[i].cpu_mode = V3_VCORE_CPU_UNKNOWN; break;
1029         }
1030         switch (vm->cores[i].shdw_pg_mode) { 
1031             case SHADOW_PAGING: core->vcore[i].mem_state = V3_VCORE_MEM_STATE_SHADOW; break;
1032             case NESTED_PAGING: core->vcore[i].mem_state = V3_VCORE_MEM_STATE_NESTED; break;
1033             default: core->vcore[i].mem_state = V3_VCORE_MEM_STATE_UNKNOWN; break;
1034         }
1035         switch (vm->cores[i].mem_mode) { 
1036             case PHYSICAL_MEM: core->vcore[i].mem_mode = V3_VCORE_MEM_MODE_PHYSICAL; break;
1037             case VIRTUAL_MEM: core->vcore[i].mem_mode=V3_VCORE_MEM_MODE_VIRTUAL; break;
1038             default: core->vcore[i].mem_mode=V3_VCORE_MEM_MODE_UNKNOWN; break;
1039         }
1040
1041         core->vcore[i].vcore_type = V3_VCORE_GENERAL;
1042
1043 #ifdef V3_CONFIG_HVM
1044         if (vm->hvm_state.is_hvm) { 
1045             if (v3_is_hvm_ros_core(&vm->cores[i])) { 
1046                 core->vcore[i].vcore_type = V3_VCORE_ROS;
1047             } else {
1048                 core->vcore[i].vcore_type = V3_VCORE_HRT;
1049             }
1050         }
1051 #endif
1052         
1053         core->vcore[i].pcore=vm->cores[i].pcpu_id;
1054         core->vcore[i].last_rip=(void*)(vm->cores[i].rip);
1055         core->vcore[i].num_exits=vm->cores[i].num_exits;
1056     }
1057     
1058     core->num_vcores=numcores;
1059
1060     cur_gpa=0;
1061
1062     for (i=0;i<numregions;i++) {
1063         mem->region[i].guest_paddr = cur_gpa;
1064         mem->region[i].host_paddr =  (void*)(vm->mem_map.base_regions[i].host_addr);
1065         mem->region[i].size = v3_mem_block_size;
1066 #ifdef V3_CONFIG_SWAPPING
1067         mem->region[i].swapped = vm->mem_map.base_regions[i].flags.swapped;
1068         mem->region[i].pinned = vm->mem_map.base_regions[i].flags.pinned;
1069 #else
1070         mem->region[i].swapped = 0;
1071         mem->region[i].pinned = 0;
1072 #endif
1073
1074         cur_gpa += mem->region[i].size;
1075     }
1076
1077     mem->num_regions=numregions;
1078
1079
1080     mem->mem_size=vm->mem_size;
1081     mem->ros_mem_size=vm->mem_size;
1082
1083 #ifdef V3_CONFIG_HVM
1084     if (vm->hvm_state.is_hvm) { 
1085         mem->ros_mem_size=v3_get_hvm_ros_memsize(vm);
1086     }
1087 #endif
1088
1089     return 0;
1090 }
1091
1092 int v3_get_state_sizes_vm(struct v3_vm_info        *vm, 
1093                           unsigned long long       *num_vcores, 
1094                           unsigned long long       *num_regions)
1095 {
1096     if (!vm || !num_vcores || !num_regions) {
1097         PrintError(VM_NONE, VCORE_NONE, "Invalid request to v3_get_state_sizes\n");
1098         return -1;
1099     }
1100
1101     *num_vcores = vm->num_cores;
1102     *num_regions = vm->mem_map.num_base_regions;
1103     
1104     return 0;
1105 }
1106
1107
1108 #ifdef V3_CONFIG_CHECKPOINT
1109 #include <palacios/vmm_checkpoint.h>
1110
1111 int v3_save_vm(struct v3_vm_info * vm, char * store, char * url, v3_chkpt_options_t opts) {
1112     if (!vm || !store || !url) {
1113         PrintError(VM_NONE,VCORE_NONE, "Incorrect arguemnts for v3_save_vm\n");
1114         return -1;
1115     }
1116     return v3_chkpt_save_vm(vm, store, url, opts);
1117 }
1118
1119
1120 int v3_load_vm(struct v3_vm_info * vm, char * store, char * url, v3_chkpt_options_t opts) {
1121     if (!vm || !store || !url) {
1122         PrintError(VM_NONE,VCORE_NONE, "Incorrect arguemnts for v3_load_vm\n");
1123         return -1;
1124     }
1125     return v3_chkpt_load_vm(vm, store, url, opts);
1126 }
1127
1128 #ifdef V3_CONFIG_LIVE_MIGRATION
1129 int v3_send_vm(struct v3_vm_info * vm, char * store, char * url, v3_chkpt_options_t opts) {
1130     if (!vm || !store || !url) {
1131         PrintError(VM_NONE,VCORE_NONE, "Incorrect arguemnts for v3_send_vm\n");
1132         return -1;
1133     }
1134     return v3_chkpt_send_vm(vm, store, url, opts);
1135 }
1136
1137
1138 int v3_receive_vm(struct v3_vm_info * vm, char * store, char * url, v3_chkpt_options_t opts) {
1139     if (!vm || !store || !url) {
1140         PrintError(VM_NONE,VCORE_NONE, "Incorrect arguemnts for v3_receive_vm\n");
1141         return -1;
1142     }
1143     return v3_chkpt_receive_vm(vm, store, url, opts);
1144 }
1145 #endif
1146
1147 #endif
1148
1149
1150 int v3_free_vm(struct v3_vm_info * vm) {
1151     int i = 0;
1152     // deinitialize guest (free memory, etc...)
1153
1154     if (!vm) { 
1155         PrintError(VM_NONE, VCORE_NONE, "Asked to free nonexistent VM\n");
1156         return -1;
1157     }
1158
1159     if ((vm->run_state != VM_STOPPED) &&
1160         (vm->run_state != VM_ERROR)) {
1161         PrintError(vm, VCORE_NONE,"Tried to Free VM in invalid runstate (%d)\n", vm->run_state);
1162         return -1;
1163     }
1164
1165     v3_free_vm_devices(vm);
1166
1167     // free cores
1168     for (i = 0; i < vm->num_cores; i++) {
1169         v3_scheduler_free_core(&(vm->cores[i]));
1170         v3_free_core(&(vm->cores[i]));
1171     }
1172
1173     // free vm
1174     v3_scheduler_free_vm(vm);
1175     v3_free_vm_internal(vm);
1176
1177     v3_free_config(vm);
1178
1179     V3_Free(vm);
1180
1181     return 0;
1182 }
1183
1184
1185 #ifdef __V3_32BIT__
1186
1187 v3_cpu_mode_t v3_get_host_cpu_mode() {
1188     uint32_t cr4_val;
1189     struct cr4_32 * cr4;
1190
1191     __asm__ (
1192              "movl %%cr4, %0; "
1193              : "=r"(cr4_val) 
1194              );
1195
1196     
1197     cr4 = (struct cr4_32 *)&(cr4_val);
1198
1199     if (cr4->pae == 1) {
1200         return PROTECTED_PAE;
1201     } else {
1202         return PROTECTED;
1203     }
1204 }
1205
1206 #elif __V3_64BIT__
1207
1208 v3_cpu_mode_t v3_get_host_cpu_mode() {
1209     return LONG;
1210 }
1211
1212 #endif 
1213
1214 void v3_print_cond(const char * fmt, ...) {
1215     if (v3_dbg_enable == 1) {
1216         char buf[2048];
1217         va_list ap;
1218
1219         va_start(ap, fmt);
1220         vsnprintf(buf, 2048, fmt, ap);
1221         va_end(ap);
1222
1223         V3_Print(VM_NONE, VCORE_NONE,"%s", buf);
1224     }    
1225 }
1226
1227
1228
1229 void v3_interrupt_cpu(struct v3_vm_info * vm, int logical_cpu, int vector) {
1230     extern struct v3_os_hooks * os_hooks;
1231
1232     if ((os_hooks) && (os_hooks)->interrupt_cpu) {
1233         (os_hooks)->interrupt_cpu(vm, logical_cpu, vector);
1234     }
1235 }
1236
1237
1238
1239 int v3_vm_enter(struct guest_info * info) {
1240     switch (v3_mach_type) {
1241 #ifdef V3_CONFIG_SVM
1242         case V3_SVM_CPU:
1243         case V3_SVM_REV3_CPU:
1244             return v3_svm_enter(info);
1245             break;
1246 #endif
1247 #if V3_CONFIG_VMX
1248         case V3_VMX_CPU:
1249         case V3_VMX_EPT_CPU:
1250         case V3_VMX_EPT_UG_CPU:
1251             return v3_vmx_enter(info);
1252             break;
1253 #endif
1254         default:
1255             PrintError(info->vm_info, info, "Attemping to enter a guest on an invalid CPU\n");
1256             return -1;
1257     }
1258 }
1259
1260
1261 void    *v3_get_host_vm(struct v3_vm_info *x)
1262 {
1263   if (x) { 
1264     return x->host_priv_data;
1265   } else {
1266     return 0;
1267   }
1268 }
1269
1270 int v3_get_vcore(struct guest_info *x)
1271 {
1272   if (x) {
1273     return x->vcpu_id;
1274   } else {
1275     return -1;
1276   }
1277 }