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