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.


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