some time virtualization issues as well.
config BUILT_IN_STRDUP
bool "strdup()"
- default n
depends on BUILT_IN_STDLIB
help
This enables Palacios' internal implementation of strdup
/* the logical cpu on which this core runs */
uint32_t cpu_id;
+ /* the physical cpu on which this core runs */
+ uint32_t host_cpu_id;
+
};
// Conditionally yield the CPU if the timeslice has expired
v3_yield_cond(info);
+ // Perform any additional yielding needed for time adjustment
v3_adjust_time(info);
+ // Update timer devices prior to entering VM.
+ v3_update_timers(info);
+
// disable global interrupts for vm state transition
v3_clgi();
}
#endif
- v3_update_timers(info);
#ifdef CONFIG_TIME_HIDE_VM_COST
v3_restart_time(info);
#endif
//V3_Print("Calling v3_svm_launch\n");
- v3_svm_launch((vmcb_t *)V3_PAddr(info->vmm_data), &(info->vm_regs), (vmcb_t *)host_vmcbs[info->cpu_id]);
+ v3_svm_launch((vmcb_t *)V3_PAddr(info->vmm_data), &(info->vm_regs), (vmcb_t *)host_vmcbs[info->host_cpu_id]);
//V3_Print("SVM Returned: Exit Code: %x, guest_rip=%lx\n", (uint32_t)(guest_ctrl->exit_code), (unsigned long)guest_state->rip);
struct guest_info * core = (struct guest_info *)p;
- PrintDebug("core %u: in start_core (RIP=%p)\n",
- core->cpu_id, (void *)(addr_t)core->rip);
+ PrintDebug("virtual core %u/physical core %u: in start_core (RIP=%p)\n",
+ core->cpu_id, core->host_cpu_id, (void *)(addr_t)core->rip);
// JRL: Whoa WTF? cpu_types are tied to the vcoreID????
- switch (v3_cpu_types[core->cpu_id]) {
+ switch (v3_cpu_types[core->host_cpu_id]) {
#ifdef CONFIG_SVM
case V3_SVM_CPU:
case V3_SVM_REV3_CPU:
int v3_start_vm(struct v3_vm_info * vm, unsigned int cpu_mask) {
uint32_t i;
-#ifdef CONFIG_MULTITHREAD_OS
- int vcore_id = 0;
-#endif
uint8_t * core_mask = (uint8_t *)&cpu_mask; // This is to make future expansion easier
uint32_t avail_cores = 0;
-
-
/// CHECK IF WE ARE MULTICORE ENABLED....
V3_Print("V3 -- Starting VM (%u cores)\n", vm->num_cores);
V3_Print("CORE 0 RIP=%p\n", (void *)(addr_t)(vm->cores[0].rip));
- // Check that enough cores are present in the mask to handle vcores
- for (i = 0; i < MAX_CORES; i++) {
- int major = i / 8;
- int minor = i % 8;
-
- if (core_mask[major] & (0x1 << minor)) {
- avail_cores++;
- }
-
- }
-
- if (vm->num_cores > avail_cores) {
+ if (vm->num_cores > MAX_CORES ) {
PrintError("Attempted to start a VM with too many cores (vm->num_cores = %d, avail_cores = %d, MAX=%d)\n", vm->num_cores, avail_cores, MAX_CORES);
return -1;
}
+ if (vm->cores[0].host_cpu_id != 0) {
+ PrintError("First virtual core must run on host core 0.\n");
+ return -1;
+ }
#ifdef CONFIG_MULTITHREAD_OS
// spawn off new threads, for other cores
- for (i = 0, vcore_id = 1; (i < MAX_CORES) && (vcore_id < vm->num_cores); i++) {
- int major = i / 8;
- int minor = i % 8;
+ for (i = 1; i < vm->num_cores; i++) {
+ struct guest_info *core = &(vm->cores[i]);
+ int major = core->host_cpu_id / 8;
+ int minor = core->host_cpu_id % 8;
void * core_thread = NULL;
- struct guest_info * core = &(vm->cores[vcore_id]);
-
- /* This assumes that the core 0 thread has been mapped to physical core 0 */
- if (i == V3_Get_CPU()) {
- // We skip the local CPU, because it is reserved for vcore 0
- continue;
- }
-
if ((core_mask[major] & (0x1 << minor)) == 0) {
- // cpuid not set in cpu_mask
+ PrintError("Host CPU %d not available for virtual core %d; not started\n",
+ core->host_cpu_id, i);
continue;
}
PrintDebug("Starting virtual core %u on logical core %u\n",
- vcore_id, i);
+ i, core->host_cpu_id);
- sprintf(core->exec_name, "%s-%u", vm->name, vcore_id);
+ sprintf(core->exec_name, "%s-%u", vm->name, i);
PrintDebug("run: core=%u, func=0x%p, arg=0x%p, name=%s\n",
- i, start_core, core, core->exec_name);
+ core->host_cpu_id, start_core, core, core->exec_name);
// TODO: actually manage these threads instead of just launching them
- core_thread = V3_CREATE_THREAD_ON_CPU(i, start_core, core, core->exec_name);
+ core_thread = V3_CREATE_THREAD_ON_CPU(core->host_cpu_id, start_core,
+ core, core->exec_name);
if (core_thread == NULL) {
PrintError("Thread launch failed\n");
return -1;
}
-
- vcore_id++;
}
#endif
int v3_vm_enter(struct guest_info * info) {
- switch (v3_cpu_types[info->cpu_id]) {
+ switch (v3_cpu_types[info->host_cpu_id]) {
#ifdef CONFIG_SVM
case V3_SVM_CPU:
case V3_SVM_REV3_CPU:
vm->mem_size = (addr_t)atoi(memory_str) * 1024 * 1024;
vm->mem_align = get_alignment(align_str);
+
PrintDebug("Alignment for %lu bytes of memory computed as 0x%x\n", vm->mem_size, vm->mem_align);
if (strcasecmp(vm_class, "PC") == 0) {
if (pg_mode) {
if ((strcasecmp(pg_mode, "nested") == 0)) {
- if (v3_cpu_types[info->cpu_id] == V3_SVM_REV3_CPU) {
+ if (v3_cpu_types[info->host_cpu_id] == V3_SVM_REV3_CPU) {
info->shdw_pg_mode = NESTED_PAGING;
} else {
PrintError("Nested paging not supported on this hardware. Defaulting to shadow paging\n");
}
static int pre_config_core(struct guest_info * info, v3_cfg_tree_t * core_cfg) {
-
+ char *hcpu;
if (determine_paging_mode(info, core_cfg))
return -1;
+ hcpu = v3_cfg_val(core_cfg, "hostcpu");
+ if (hcpu) {
+ int req_id = atoi(hcpu);
+ if (req_id < 0) {
+ PrintError("Invalid host core %d requested by"
+ " virtual cpu %d - ignored.\n", req_id, info->cpu_id);
+ } else {
+ PrintDebug("Assigned host core %d to virtual core %d.\n", info->cpu_id, req_id, hcpu);
+ info->host_cpu_id = req_id;
+ }
+ }
+
v3_init_core(info);
if (info->vm_info->vm_class == V3_PC_VM) {
}
num_cores = atoi(v3_cfg_val(cores_cfg, "count"));
-
if (num_cores == 0) {
PrintError("No cores specified in configuration\n");
return NULL;
return NULL;
}
-
V3_Print("Per core configuration\n");
per_core_cfg = v3_cfg_subtree(cores_cfg, "core");
info->cpu_id = i;
info->vm_info = vm;
info->core_cfg_data = per_core_cfg;
+ info->host_cpu_id = i; // may be overriden by core config
if (pre_config_core(info, per_core_cfg) == -1) {
PrintError("Error in core %d preconfiguration\n", i);
return NULL;
}
+
per_core_cfg = v3_cfg_next_branch(per_core_cfg);
}
*eax = *(uint32_t *)"V3V";
- if ((v3_cpu_types[core->cpu_id] == V3_SVM_CPU) ||
- (v3_cpu_types[core->cpu_id] == V3_SVM_REV3_CPU)) {
+ if ((v3_cpu_types[core->host_cpu_id] == V3_SVM_CPU) ||
+ (v3_cpu_types[core->host_cpu_id] == V3_SVM_REV3_CPU)) {
*ebx = *(uint32_t *)"SVM";
- } else if ((v3_cpu_types[core->cpu_id] == V3_VMX_CPU) ||
- (v3_cpu_types[core->cpu_id] == V3_VMX_EPT_CPU)) {
+ } else if ((v3_cpu_types[core->host_cpu_id] == V3_VMX_CPU) ||
+ (v3_cpu_types[core->host_cpu_id] == V3_VMX_EPT_CPU)) {
*ebx = *(uint32_t *)"VMX";
}
struct vm_time * time_state = &(info->time_state);
if (time_state->host_cpu_freq != time_state->guest_cpu_freq) {
- uint64_t guest_time, guest_elapsed, desired_elapsed;
- uint64_t host_time, target_host_time;
+ uint64_t guest_time, host_time, target_host_time;
+ sint64_t guest_elapsed, desired_elapsed;
guest_time = v3_get_guest_time(time_state);
/* Yield until that host time is reached */
host_time = v3_get_host_time(time_state);
+ if (host_time < target_host_time) {
+ PrintDebug("Yielding until host time (%llu) greater than target (%llu).\n", host_time, target_host_time);
+ }
+
while (host_time < target_host_time) {
v3_yield(info);
host_time = v3_get_host_time(time_state);
}
- // This overrides any pause/unpause times because the difference
- // is going to be too big for any pause/unpause the notice.
- time_state->guest_host_offset = (sint64_t)guest_time - (sint64_t)host_time;
+#ifndef CONFIG_TIME_HIDE_VM_COST
+ // XXX This should turn into a target offset we want to move towards XXX
+ time_state->guest_host_offset =
+ (sint64_t)guest_time - (sint64_t)host_time;
+#endif
}
return 0;
int v3_rdtsc(struct guest_info * info) {
uint64_t tscval = v3_get_guest_tsc(&info->time_state);
- PrintDebug("Returning %llu as TSC.\n", tscval);
info->vm_regs.rdx = tscval >> 32;
info->vm_regs.rax = tscval & 0xffffffffLL;
return 0;
}
int v3_handle_rdtsc(struct guest_info * info) {
- PrintDebug("Handling virtual RDTSC call.\n");
v3_rdtsc(info);
info->vm_regs.rax &= 0x00000000ffffffffLL;
time_state->guest_cpu_freq = atoi(khz);
PrintDebug("Core %d CPU frequency requested at %d khz.\n",
info->cpu_id, time_state->guest_cpu_freq);
- }
+ }
- if ((khz == NULL) || (time_state->guest_cpu_freq > time_state->host_cpu_freq)) {
+ if ((khz == NULL) || (time_state->guest_cpu_freq <= 0)
+ || (time_state->guest_cpu_freq > time_state->host_cpu_freq)) {
time_state->guest_cpu_freq = time_state->host_cpu_freq;
}