static void init_cpu(void * arg) {
uint32_t cpu_id = (uint32_t)(addr_t)arg;
+ v3_init_fp();
+
#ifdef V3_CONFIG_SVM
if (v3_is_svm_capable()) {
PrintDebug(VM_NONE, VCORE_NONE, "Machine is SVM Capable\n");
PrintError(VM_NONE, VCORE_NONE, "CPU has no virtualization Extensions\n");
break;
}
+
+ v3_deinit_fp();
+
+}
+
+
+static int in_long_mode()
+{
+ uint32_t high, low;
+
+ v3_get_msr(0xc0000080,&high,&low); // EFER
+
+ return ((low & 0x500)== 0x500); // LMA and LME set
}
+
void Init_V3(struct v3_os_hooks * hooks, char * cpu_mask, int num_cpus, char *options) {
int i = 0;
V3_Print(VM_NONE, VCORE_NONE, "V3 Print statement to fix a Kitten page fault bug\n");
+
+#ifndef __V3_64BIT__
+#error Palacios does not support compilation for a 32 bit host OS!!!!
+#else
+ if (!in_long_mode()) {
+ PrintError(VM_NONE,VCORE_NONE,"Palacios supports execution only in long mode (64 bit).\n");
+ return;
+ }
+#endif
+
// Set global variables.
os_hooks = hooks;
int v3_start_vm(struct v3_vm_info * vm, unsigned int cpu_mask) {
- uint32_t i,j;
+ uint32_t i;
uint8_t * core_mask = (uint8_t *)&cpu_mask; // This is to make future expansion easier
uint32_t avail_cores = 0;
int vcore_id = 0;
- extern uint64_t v3_mem_block_size;
-
if (vm->run_state != VM_STOPPED) {
PrintError(vm, VCORE_NONE, "VM has already been launched (state=%d)\n", (int)vm->run_state);
return -1;
}
-
- // Do not run if any core is using shadow paging and we are out of 4 GB bounds
- for (i=0;i<vm->num_cores;i++) {
- if (vm->cores[i].shdw_pg_mode == SHADOW_PAGING) {
- for (j=0;j<vm->mem_map.num_base_regions;j++) {
- if ((vm->mem_map.base_regions[i].host_addr + v3_mem_block_size) >= 0x100000000ULL) {
- PrintError(vm, VCORE_NONE, "Base memory region %d exceeds 4 GB boundary with shadow paging enabled on core %d.\n",j, i);
- PrintError(vm, VCORE_NONE, "Any use of non-64 bit mode in the guest is likely to fail in this configuration.\n");
- PrintError(vm, VCORE_NONE, "If you would like to proceed anyway, remove this check and recompile Palacios.\n");
- PrintError(vm, VCORE_NONE, "Alternatively, change this VM to use nested paging.\n");
- return -1;
- }
- }
- }
- }
-
+
/// CHECK IF WE ARE MULTICORE ENABLED....
V3_Print(vm, VCORE_NONE, "V3 -- Starting VM (%u cores)\n", vm->num_cores);
PrintDebug(vm, VCORE_NONE, "run: core=%u, func=0x%p, arg=0x%p, name=%s\n",
core->pcpu_id, start_core, core, core->exec_name);
- core->core_run_state = CORE_STOPPED; // core zero will turn itself on
+ if (core->core_run_state==CORE_INVALID) {
+ // launch of a fresh VM
+ core->core_run_state = CORE_STOPPED;
+ // core zero will turn itself on
+ } else {
+ // this is a resume - use whatever its current run_state is
+ }
+
core->core_thread = V3_CREATE_THREAD_ON_CPU(core->pcpu_id, start_core, core, core->exec_name);
if (core->core_thread == NULL) {
// region uses exclusive addressing [guest_start,guest_end)
num_pages = (reg->guest_end-reg->guest_start)/PAGE_SIZE;
- // Now we allocate space for the new region with the same constraints as
- // it originally had
new_hpa = V3_AllocPagesExtended(num_pages,
PAGE_SIZE_4KB,
new_node,
- reg->flags.limit32 ? V3_ALLOC_PAGES_CONSTRAINT_4GB : 0);
+ 0); // no constraints given new shadow pager impl
if (!new_hpa) {
PrintError(vm, VCORE_NONE, "Cannot allocate memory for new base region...\n");
v3_invalidate_shadow_pts(&(vm->cores[i]));
} else if (vm->cores[i].shdw_pg_mode==NESTED_PAGING) {
// nested invalidator uses inclusive addressing [start,end], not [start,end)
- v3_invalidate_nested_addr_range(&(vm->cores[i]),reg->guest_start,reg->guest_end-1);
+ v3_invalidate_nested_addr_range(&(vm->cores[i]),reg->guest_start,reg->guest_end-1,NULL,NULL);
} else {
PrintError(vm,VCORE_NONE, "Cannot determine how to invalidate paging structures! Reverting to previous region.\n");
// We'll restore things...
V3_Print(core->vm_info, core, "Simulation callback activated (guest_rip=%p)\n", (void *)core->rip);
while (v3_bitmap_check(timeout_map, core->vcpu_id) == 1) {
+ // We spin here if there is noone to yield to
v3_yield(NULL,-1);
}
if (all_blocked == 1) {
break;
}
-
+
+ // Intentionally spin if there is no one to yield to
v3_yield(NULL,-1);
}