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.


Expose HVM state to host + Linux host /proc additions for it
[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-%u", 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             start = ((uint32_t*)data)[0];
541             end = ((uint32_t*)data)[1];
542             break;
543         default:
544             PrintError(vm,VCORE_NONE,"Unsupported reset type %d for this VM\n",t);
545             return -1;
546             break;
547     }
548
549     PrintDebug(vm,VCORE_NONE,"Resetting cores %d through %d\n",start,end);
550
551     newcount = end-start+1;
552     
553     for (i=start;i<=end;i++) { 
554         if (!(vm->cores[i].core_run_state == CORE_RUNNING || vm->cores[i].core_run_state == CORE_STOPPED)) {
555             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);
556             return -1;
557         }
558     }
559
560
561     // This had better be the only thread using the barrier at this point...
562     v3_init_counting_barrier(&vm->reset_barrier,newcount);
563
564     // OK, I am the reseter, tell the relevant cores what to do
565     // each will atomically decrement the reset countdown and then
566     // spin waiting for it to hit zero.
567
568     for (i=start;i<=end;i++) { 
569         vm->cores[i].core_run_state = CORE_RESETTING;
570         // force exit of core
571         v3_interrupt_cpu(vm, vm->cores[i].pcpu_id, 0);
572     }
573     
574     // we don't wait for reset to finish
575     // because reset could have been initiated by a core
576
577     return 0;
578 }
579
580
581 /* move a virtual core to different physical core */
582 int v3_move_vm_core(struct v3_vm_info * vm, int vcore_id, int target_cpu) {
583     struct guest_info * core = NULL;
584
585     if (!vm) { 
586         PrintError(VM_NONE, VCORE_NONE, "Asked to move core of nonexistent VM\n");
587         return -1;
588     }
589
590     if ((vcore_id < 0) || (vcore_id >= vm->num_cores)) {
591         PrintError(vm, VCORE_NONE, "Attempted to migrate invalid virtual core (%d)\n", vcore_id);
592         return -1;
593     }
594
595     core = &(vm->cores[vcore_id]);
596
597     if (target_cpu == core->pcpu_id) {
598         PrintError(vm,  core, "Attempted to migrate to local core (%d)\n", target_cpu);
599         // well that was pointless
600         return 0;
601     }
602
603     if (core->core_thread == NULL) {
604         PrintError(vm, core, "Attempted to migrate a core without a valid thread context\n");
605         return -1;
606     }
607
608     while (v3_raise_barrier(vm, NULL) == -1);
609
610     V3_Print(vm, core, "Performing Migration from %d to %d\n", core->pcpu_id, target_cpu);
611
612     // Double check that we weren't preemptively migrated
613     if (target_cpu != core->pcpu_id) {    
614
615         V3_Print(vm, core, "Moving Core\n");
616
617         if(v3_cpu_mapper_admit_core(vm, vcore_id, target_cpu) == -1){
618                 PrintError(vm, core, "Core %d can not be admitted in cpu %d\n",vcore_id, target_cpu);
619                 return -1;
620         }
621
622
623 #ifdef V3_CONFIG_VMX
624         switch (v3_cpu_types[core->pcpu_id]) {
625             case V3_VMX_CPU:
626             case V3_VMX_EPT_CPU:
627             case V3_VMX_EPT_UG_CPU:
628                 PrintDebug(vm, core, "Flushing VMX Guest CPU %d\n", core->vcpu_id);
629                 V3_Call_On_CPU(core->pcpu_id, (void (*)(void *))v3_flush_vmx_vm_core, (void *)core);
630                 break;
631             default:
632                 break;
633         }
634 #endif
635
636         if (V3_MOVE_THREAD_TO_CPU(target_cpu, core->core_thread) != 0) {
637             PrintError(vm, core, "Failed to move Vcore %d to CPU %d\n", 
638                        core->vcpu_id, target_cpu);
639             v3_lower_barrier(vm);
640             return -1;
641         } 
642         
643         /* There will be a benign race window here:
644            core->pcpu_id will be set to the target core before its fully "migrated"
645            However the core will NEVER run on the old core again, its just in flight to the new core
646         */
647         core->pcpu_id = target_cpu;
648
649         V3_Print(vm, core, "core now at %d\n", core->pcpu_id);  
650     }
651
652     v3_lower_barrier(vm);
653
654     return 0;
655 }
656
657 /* move a memory region to memory with affinity for a specific physical core */
658 int v3_move_vm_mem(struct v3_vm_info * vm, void *gpa, int target_cpu) {
659     int old_node;
660     int new_node;
661     struct v3_mem_region *reg;
662     void *new_hpa;
663     int num_pages;
664     void *old_hpa;
665     int i;
666
667     if (!vm) { 
668         PrintError(VM_NONE, VCORE_NONE, "Asked to move memory of nonexistent VM\n");
669         return -1;
670     }
671
672     old_node = v3_numa_gpa_to_node(vm,(addr_t)gpa);
673
674     if (old_node<0) { 
675         PrintError(vm, VCORE_NONE, "Cannot determine current node of gpa %p\n",gpa);
676         return -1;
677     }
678
679     new_node = v3_numa_cpu_to_node(target_cpu);
680
681     if (new_node<0) { 
682         PrintError(vm, VCORE_NONE, "Cannot determine current node of cpu %d\n",target_cpu);
683         return -1;
684     }
685
686     if (new_node==old_node) { 
687         PrintDebug(vm, VCORE_NONE, "Affinity is already established - ignoring request\n");
688         return 0;
689     }
690
691     // We are now going to change the universe, so 
692     // we'll barrier everyone first
693
694     while (v3_raise_barrier(vm, NULL) == -1);
695
696     // get region
697     
698     reg = v3_get_mem_region(vm, V3_MEM_CORE_ANY, (addr_t) gpa);
699
700     if (!reg) { 
701         PrintError(vm, VCORE_NONE, "Attempt to migrate non-existent memory\n");
702         goto out_fail;
703     }
704     
705     if (!(reg->flags.base) || !(reg->flags.alloced)) { 
706         PrintError(vm, VCORE_NONE, "Attempt to migrate invalid region: base=%d alloced=%d\n", reg->flags.base, reg->flags.alloced);
707         goto out_fail;
708     }
709
710     // we now have the allocated base region corresponding to  - and not a copy
711     // we will rewrite this region after moving its contents
712     
713     // first, let's double check that we are in fact changing the numa_id...
714
715     if (reg->numa_id==new_node) { 
716         PrintDebug(vm, VCORE_NONE, "Affinity for this base region is already established - ignoring...\n");
717         goto out_success;
718     }
719
720     // region uses exclusive addressing [guest_start,guest_end)
721     num_pages = (reg->guest_end-reg->guest_start)/PAGE_SIZE;
722
723     new_hpa = V3_AllocPagesExtended(num_pages,
724                                     PAGE_SIZE_4KB,
725                                     new_node,
726                                     0, 0);  // no constraints given new shadow pager impl
727
728     if (!new_hpa) { 
729         PrintError(vm, VCORE_NONE, "Cannot allocate memory for new base region...\n");
730         goto out_fail;
731     }
732
733     // Note, assumes virtual contiguity in the host OS... 
734     memcpy(V3_VAddr((void*)new_hpa), V3_VAddr((void*)(reg->host_addr)), num_pages*PAGE_SIZE);
735
736     old_hpa = (void*)(reg->host_addr);
737     old_node = (int)(reg->numa_id);
738
739     reg->host_addr = (addr_t)new_hpa;
740     reg->numa_id = v3_numa_hpa_to_node((addr_t)new_hpa);
741
742     // flush all page tables / kill all humans 
743
744     for (i=0;i<vm->num_cores;i++) { 
745         if (vm->cores[i].shdw_pg_mode==SHADOW_PAGING) { 
746             v3_invalidate_shadow_pts(&(vm->cores[i]));
747         } else if (vm->cores[i].shdw_pg_mode==NESTED_PAGING) { 
748             // nested invalidator uses inclusive addressing [start,end], not [start,end)
749           v3_invalidate_nested_addr_range(&(vm->cores[i]),reg->guest_start,reg->guest_end-1,NULL,NULL);
750         } else {
751             PrintError(vm,VCORE_NONE, "Cannot determine how to invalidate paging structures! Reverting to previous region.\n");
752             // We'll restore things...
753             reg->host_addr = (addr_t) old_hpa;
754             reg->numa_id = old_node;
755             V3_FreePages(new_hpa,num_pages);
756             goto out_fail;
757         }
758     }
759     
760     // Now the old region can go away...
761     V3_FreePages(old_hpa,num_pages);
762     
763     PrintDebug(vm,VCORE_NONE,"Migration of memory complete - new region is %p to %p\n",
764                (void*)(reg->host_addr),(void*)(reg->host_addr+num_pages*PAGE_SIZE-1));
765     
766  out_success:
767     v3_lower_barrier(vm);
768     return 0;
769     
770     
771  out_fail:
772     v3_lower_barrier(vm);
773     return -1;
774 }
775
776 int v3_stop_vm(struct v3_vm_info * vm) {
777
778     struct guest_info * running_core;
779
780     if (!vm) { 
781         PrintError(VM_NONE, VCORE_NONE, "Asked to stop nonexistent VM\n");
782         return -1;
783     }
784
785     if ((vm->run_state != VM_RUNNING) && 
786         (vm->run_state != VM_SIMULATING)) {
787         PrintError(vm, VCORE_NONE,"Tried to stop VM in invalid runstate (%d)\n", vm->run_state);
788         return -1;
789     }
790
791     vm->run_state = VM_STOPPED;
792
793     // Sanity check to catch any weird execution states
794     if (v3_wait_for_barrier(vm, NULL) == 0) {
795         v3_lower_barrier(vm);
796     }
797     
798     // XXX force exit all cores via a cross call/IPI XXX
799
800     while (1) {
801         int i = 0;
802         int still_running = 0;
803
804         for (i = 0; i < vm->num_cores; i++) {
805             if (vm->cores[i].core_run_state != CORE_STOPPED) {
806                 running_core = &vm->cores[i];
807                 still_running = 1;
808             }
809         }
810
811         if (still_running == 0) {
812             break;
813         }
814
815         v3_scheduler_stop_core(running_core);
816     }
817     
818     V3_Print(vm, VCORE_NONE,"VM stopped. Returning\n");
819
820     return 0;
821 }
822
823
824 int v3_pause_vm(struct v3_vm_info * vm) {
825
826     if (!vm) { 
827         PrintError(VM_NONE, VCORE_NONE, "Asked to pause nonexistent VM\n");
828         return -1;
829     }
830
831     if (vm->run_state != VM_RUNNING) {
832         PrintError(vm, VCORE_NONE,"Tried to pause a VM that was not running\n");
833         return -1;
834     }
835
836     while (v3_raise_barrier(vm, NULL) == -1);
837
838     vm->run_state = VM_PAUSED;
839
840     return 0;
841 }
842
843
844 int v3_continue_vm(struct v3_vm_info * vm) {
845
846     if (!vm) { 
847         PrintError(VM_NONE, VCORE_NONE, "Asked to continue nonexistent VM\n");
848         return -1;
849     }
850
851     if (vm->run_state != VM_PAUSED) {
852         PrintError(vm, VCORE_NONE,"Tried to continue a VM that was not paused\n");
853         return -1;
854     }
855
856     vm->run_state = VM_RUNNING;
857
858     v3_lower_barrier(vm);
859
860     return 0;
861 }
862
863
864
865 static int sim_callback(struct guest_info * core, void * private_data) {
866     struct v3_bitmap * timeout_map = private_data;
867
868     v3_bitmap_set(timeout_map, core->vcpu_id);
869     
870     V3_Print(core->vm_info, core, "Simulation callback activated (guest_rip=%p)\n", (void *)core->rip);
871
872     while (v3_bitmap_check(timeout_map, core->vcpu_id) == 1) {
873         // We spin here if there is noone to yield to
874         v3_yield(NULL,-1);
875     }
876
877     return 0;
878 }
879
880
881
882
883 int v3_simulate_vm(struct v3_vm_info * vm, unsigned int msecs) {
884     struct v3_bitmap timeout_map;
885     int i = 0;
886     int all_blocked = 0;
887     uint64_t cycles = 0;
888     uint64_t cpu_khz = V3_CPU_KHZ();
889
890     if (!vm) { 
891         PrintError(VM_NONE, VCORE_NONE, "Asked to simulate nonexistent VM\n");
892         return -1;
893     }
894
895     if (vm->run_state != VM_PAUSED) {
896         PrintError(vm, VCORE_NONE,"VM must be paused before simulation begins\n");
897         return -1;
898     }
899
900     /* AT this point VM is paused */
901     
902     // initialize bitmap
903     v3_bitmap_init(&timeout_map, vm->num_cores);
904
905
906
907
908     // calculate cycles from msecs...
909     // IMPORTANT: Floating point not allowed.
910     cycles = (msecs * cpu_khz);
911     
912
913
914     V3_Print(vm, VCORE_NONE,"Simulating %u msecs (%llu cycles) [CPU_KHZ=%llu]\n", msecs, cycles, cpu_khz);
915
916     // set timeout
917     
918     for (i = 0; i < vm->num_cores; i++) {
919         if (v3_add_core_timeout(&(vm->cores[i]), cycles, sim_callback, &timeout_map) == -1) {
920             PrintError(vm, VCORE_NONE,"Could not register simulation timeout for core %d\n", i);
921             return -1;
922         }
923     }
924
925     V3_Print(vm, VCORE_NONE,"timeouts set on all cores\n ");
926
927     
928     // Run the simulation
929 //    vm->run_state = VM_SIMULATING;
930     vm->run_state = VM_RUNNING;
931     v3_lower_barrier(vm);
932
933
934     V3_Print(vm, VCORE_NONE,"Barrier lowered: We are now Simulating!!\n");
935
936     // block until simulation is complete    
937     while (all_blocked == 0) {
938         all_blocked = 1;
939
940         for (i = 0; i < vm->num_cores; i++) {
941             if (v3_bitmap_check(&timeout_map, i)  == 0) {
942                 all_blocked = 0;
943             }
944         }
945
946         if (all_blocked == 1) {
947             break;
948         }
949         
950         // Intentionally spin if there is no one to yield to
951         v3_yield(NULL,-1);
952     }
953
954
955     V3_Print(vm, VCORE_NONE,"Simulation is complete\n");
956
957     // Simulation is complete
958     // Reset back to PAUSED state
959
960     v3_raise_barrier_nowait(vm, NULL);
961     vm->run_state = VM_PAUSED;
962     
963     v3_bitmap_reset(&timeout_map);
964
965     v3_wait_for_barrier(vm, NULL);
966
967     return 0;
968
969 }
970
971 int v3_get_state_vm(struct v3_vm_info        *vm, 
972                     struct v3_vm_base_state  *base,
973                     struct v3_vm_core_state  *core,
974                     struct v3_vm_mem_state   *mem)
975 {
976     uint32_t i;
977     uint32_t numcores;
978     uint32_t numregions; 
979     extern uint64_t v3_mem_block_size;
980     void     *cur_gpa;
981
982     if (!vm || !base || !core || !mem)  { 
983         PrintError(VM_NONE, VCORE_NONE, "Invalid request to v3_get_state_vm\n");
984         return -1;
985     }
986
987     numcores = core->num_vcores > vm->num_cores ? vm->num_cores : core->num_vcores;
988     numregions = mem->num_regions > vm->mem_map.num_base_regions ? vm->mem_map.num_base_regions : mem->num_regions;
989
990     switch (vm->run_state) { 
991         case VM_INVALID: base->state = V3_VM_INVALID; break;
992         case VM_RUNNING: base->state = V3_VM_RUNNING; break;
993         case VM_STOPPED: base->state = V3_VM_STOPPED; break;
994         case VM_PAUSED: base->state = V3_VM_PAUSED; break;
995         case VM_ERROR: base->state = V3_VM_ERROR; break;
996         case VM_SIMULATING: base->state = V3_VM_SIMULATING; break;
997         case VM_RESETTING: base->state = V3_VM_RESETTING; break;
998         default: base->state = V3_VM_UNKNOWN; break;
999     }
1000
1001     base->vm_type = V3_VM_GENERAL;
1002
1003 #ifdef V3_CONFIG_HVM
1004     if (vm->hvm_state.is_hvm) { 
1005         base->vm_type = V3_VM_HVM;
1006     } 
1007 #endif
1008
1009     for (i=0;i<numcores;i++) {
1010         switch (vm->cores[i].core_run_state) {
1011             case CORE_INVALID: core->vcore[i].state = V3_VCORE_INVALID; break;
1012             case CORE_RUNNING: core->vcore[i].state = V3_VCORE_RUNNING; break;
1013             case CORE_STOPPED: core->vcore[i].state = V3_VCORE_STOPPED; break;
1014             case CORE_RESETTING: core->vcore[i].state = V3_VCORE_RESETTING; break;
1015             default: core->vcore[i].state = V3_VCORE_UNKNOWN; break;
1016         }
1017         switch (vm->cores[i].cpu_mode) {
1018             case REAL: core->vcore[i].cpu_mode = V3_VCORE_CPU_REAL; break;
1019             case PROTECTED: core->vcore[i].cpu_mode = V3_VCORE_CPU_PROTECTED; break;
1020             case PROTECTED_PAE: core->vcore[i].cpu_mode = V3_VCORE_CPU_PROTECTED_PAE; break;
1021             case LONG: core->vcore[i].cpu_mode = V3_VCORE_CPU_LONG; break;
1022             case LONG_32_COMPAT: core->vcore[i].cpu_mode = V3_VCORE_CPU_LONG_32_COMPAT; break;
1023             case LONG_16_COMPAT: core->vcore[i].cpu_mode = V3_VCORE_CPU_LONG_16_COMPAT; break;
1024             default: core->vcore[i].cpu_mode = V3_VCORE_CPU_UNKNOWN; break;
1025         }
1026         switch (vm->cores[i].shdw_pg_mode) { 
1027             case SHADOW_PAGING: core->vcore[i].mem_state = V3_VCORE_MEM_STATE_SHADOW; break;
1028             case NESTED_PAGING: core->vcore[i].mem_state = V3_VCORE_MEM_STATE_NESTED; break;
1029             default: core->vcore[i].mem_state = V3_VCORE_MEM_STATE_UNKNOWN; break;
1030         }
1031         switch (vm->cores[i].mem_mode) { 
1032             case PHYSICAL_MEM: core->vcore[i].mem_mode = V3_VCORE_MEM_MODE_PHYSICAL; break;
1033             case VIRTUAL_MEM: core->vcore[i].mem_mode=V3_VCORE_MEM_MODE_VIRTUAL; break;
1034             default: core->vcore[i].mem_mode=V3_VCORE_MEM_MODE_UNKNOWN; break;
1035         }
1036
1037         core->vcore[i].vcore_type = V3_VCORE_GENERAL;
1038
1039 #ifdef V3_CONFIG_HVM
1040         if (vm->hvm_state.is_hvm) { 
1041             if (v3_is_hvm_ros_core(&vm->cores[i])) { 
1042                 core->vcore[i].vcore_type = V3_VCORE_ROS;
1043             } else {
1044                 core->vcore[i].vcore_type = V3_VCORE_HRT;
1045             }
1046         }
1047 #endif
1048         
1049         core->vcore[i].pcore=vm->cores[i].pcpu_id;
1050         core->vcore[i].last_rip=(void*)(vm->cores[i].rip);
1051         core->vcore[i].num_exits=vm->cores[i].num_exits;
1052     }
1053     
1054     core->num_vcores=numcores;
1055
1056     cur_gpa=0;
1057
1058     for (i=0;i<numregions;i++) {
1059         mem->region[i].guest_paddr = cur_gpa;
1060         mem->region[i].host_paddr =  (void*)(vm->mem_map.base_regions[i].host_addr);
1061         mem->region[i].size = v3_mem_block_size;
1062 #ifdef V3_CONFIG_SWAPPING
1063         mem->region[i].swapped = vm->mem_map.base_regions[i].flags.swapped;
1064         mem->region[i].pinned = vm->mem_map.base_regions[i].flags.pinned;
1065 #else
1066         mem->region[i].swapped = 0;
1067         mem->region[i].pinned = 0;
1068 #endif
1069
1070         cur_gpa += mem->region[i].size;
1071     }
1072
1073     mem->num_regions=numregions;
1074
1075
1076     mem->mem_size=vm->mem_size;
1077     mem->ros_mem_size=vm->mem_size;
1078
1079 #ifdef V3_CONFIG_HVM
1080     if (vm->hvm_state.is_hvm) { 
1081         mem->ros_mem_size=v3_get_hvm_ros_memsize(vm);
1082     }
1083 #endif
1084
1085     return 0;
1086 }
1087
1088 int v3_get_state_sizes_vm(struct v3_vm_info        *vm, 
1089                           unsigned long long       *num_vcores, 
1090                           unsigned long long       *num_regions)
1091 {
1092     if (!vm || !num_vcores || !num_regions) {
1093         PrintError(VM_NONE, VCORE_NONE, "Invalid request to v3_get_state_sizes\n");
1094         return -1;
1095     }
1096
1097     *num_vcores = vm->num_cores;
1098     *num_regions = vm->mem_map.num_base_regions;
1099     
1100     return 0;
1101 }
1102
1103
1104 #ifdef V3_CONFIG_CHECKPOINT
1105 #include <palacios/vmm_checkpoint.h>
1106
1107 int v3_save_vm(struct v3_vm_info * vm, char * store, char * url, v3_chkpt_options_t opts) {
1108     if (!vm || !store || !url) {
1109         PrintError(VM_NONE,VCORE_NONE, "Incorrect arguemnts for v3_save_vm\n");
1110         return -1;
1111     }
1112     return v3_chkpt_save_vm(vm, store, url, opts);
1113 }
1114
1115
1116 int v3_load_vm(struct v3_vm_info * vm, char * store, char * url, v3_chkpt_options_t opts) {
1117     if (!vm || !store || !url) {
1118         PrintError(VM_NONE,VCORE_NONE, "Incorrect arguemnts for v3_load_vm\n");
1119         return -1;
1120     }
1121     return v3_chkpt_load_vm(vm, store, url, opts);
1122 }
1123
1124 #ifdef V3_CONFIG_LIVE_MIGRATION
1125 int v3_send_vm(struct v3_vm_info * vm, char * store, char * url, v3_chkpt_options_t opts) {
1126     if (!vm || !store || !url) {
1127         PrintError(VM_NONE,VCORE_NONE, "Incorrect arguemnts for v3_send_vm\n");
1128         return -1;
1129     }
1130     return v3_chkpt_send_vm(vm, store, url, opts);
1131 }
1132
1133
1134 int v3_receive_vm(struct v3_vm_info * vm, char * store, char * url, v3_chkpt_options_t opts) {
1135     if (!vm || !store || !url) {
1136         PrintError(VM_NONE,VCORE_NONE, "Incorrect arguemnts for v3_receive_vm\n");
1137         return -1;
1138     }
1139     return v3_chkpt_receive_vm(vm, store, url, opts);
1140 }
1141 #endif
1142
1143 #endif
1144
1145
1146 int v3_free_vm(struct v3_vm_info * vm) {
1147     int i = 0;
1148     // deinitialize guest (free memory, etc...)
1149
1150     if (!vm) { 
1151         PrintError(VM_NONE, VCORE_NONE, "Asked to free nonexistent VM\n");
1152         return -1;
1153     }
1154
1155     if ((vm->run_state != VM_STOPPED) &&
1156         (vm->run_state != VM_ERROR)) {
1157         PrintError(vm, VCORE_NONE,"Tried to Free VM in invalid runstate (%d)\n", vm->run_state);
1158         return -1;
1159     }
1160
1161     v3_free_vm_devices(vm);
1162
1163     // free cores
1164     for (i = 0; i < vm->num_cores; i++) {
1165         v3_scheduler_free_core(&(vm->cores[i]));
1166         v3_free_core(&(vm->cores[i]));
1167     }
1168
1169     // free vm
1170     v3_scheduler_free_vm(vm);
1171     v3_free_vm_internal(vm);
1172
1173     v3_free_config(vm);
1174
1175     V3_Free(vm);
1176
1177     return 0;
1178 }
1179
1180
1181 #ifdef __V3_32BIT__
1182
1183 v3_cpu_mode_t v3_get_host_cpu_mode() {
1184     uint32_t cr4_val;
1185     struct cr4_32 * cr4;
1186
1187     __asm__ (
1188              "movl %%cr4, %0; "
1189              : "=r"(cr4_val) 
1190              );
1191
1192     
1193     cr4 = (struct cr4_32 *)&(cr4_val);
1194
1195     if (cr4->pae == 1) {
1196         return PROTECTED_PAE;
1197     } else {
1198         return PROTECTED;
1199     }
1200 }
1201
1202 #elif __V3_64BIT__
1203
1204 v3_cpu_mode_t v3_get_host_cpu_mode() {
1205     return LONG;
1206 }
1207
1208 #endif 
1209
1210 void v3_print_cond(const char * fmt, ...) {
1211     if (v3_dbg_enable == 1) {
1212         char buf[2048];
1213         va_list ap;
1214
1215         va_start(ap, fmt);
1216         vsnprintf(buf, 2048, fmt, ap);
1217         va_end(ap);
1218
1219         V3_Print(VM_NONE, VCORE_NONE,"%s", buf);
1220     }    
1221 }
1222
1223
1224
1225 void v3_interrupt_cpu(struct v3_vm_info * vm, int logical_cpu, int vector) {
1226     extern struct v3_os_hooks * os_hooks;
1227
1228     if ((os_hooks) && (os_hooks)->interrupt_cpu) {
1229         (os_hooks)->interrupt_cpu(vm, logical_cpu, vector);
1230     }
1231 }
1232
1233
1234
1235 int v3_vm_enter(struct guest_info * info) {
1236     switch (v3_mach_type) {
1237 #ifdef V3_CONFIG_SVM
1238         case V3_SVM_CPU:
1239         case V3_SVM_REV3_CPU:
1240             return v3_svm_enter(info);
1241             break;
1242 #endif
1243 #if V3_CONFIG_VMX
1244         case V3_VMX_CPU:
1245         case V3_VMX_EPT_CPU:
1246         case V3_VMX_EPT_UG_CPU:
1247             return v3_vmx_enter(info);
1248             break;
1249 #endif
1250         default:
1251             PrintError(info->vm_info, info, "Attemping to enter a guest on an invalid CPU\n");
1252             return -1;
1253     }
1254 }
1255
1256
1257 void    *v3_get_host_vm(struct v3_vm_info *x)
1258 {
1259   if (x) { 
1260     return x->host_priv_data;
1261   } else {
1262     return 0;
1263   }
1264 }
1265
1266 int v3_get_vcore(struct guest_info *x)
1267 {
1268   if (x) {
1269     return x->vcpu_id;
1270   } else {
1271     return -1;
1272   }
1273 }