#include "vmm_config_class.h"
+
+/* The Palacios cookie encodes "v3vee" followed by a
+ 3 byte version code. There are currently two versions:
+
+ \0\0\0 => original (no checksum)
+ \0\0\1 => checksum
+*/
+#define COOKIE_LEN 8
+#define COOKIE_V0 "v3vee\0\0\0"
+#define COOKIE_V1 "v3vee\0\0\1"
+
+
+
+
// This is used to access the configuration file index table
-struct file_hdr {
+struct file_hdr_v0 {
uint32_t index;
uint32_t size;
uint64_t offset;
};
-struct file_idx_table {
+struct file_hdr_v1 {
+ uint32_t index;
+ uint32_t size;
+ uint64_t offset;
+ ulong_t hash;
+};
+
+
+struct file_idx_table_v0 {
+ uint64_t num_files;
+ struct file_hdr_v0 hdrs[0];
+};
+
+struct file_idx_table_v1 {
uint64_t num_files;
- struct file_hdr hdrs[0];
+ struct file_hdr_v1 hdrs[0];
};
struct v3_config * cfg = NULL;
int offset = 0;
uint_t xml_len = 0;
- struct file_idx_table * files = NULL;
+ struct file_idx_table_v0 * files_v0 = NULL;
+ struct file_idx_table_v1 * files_v1 = NULL;
v3_cfg_tree_t * file_tree = NULL;
+ int version=-1;
V3_Print("cfg data at %p\n", cfg_blob);
- if (memcmp(cfg_blob, "v3vee\0\0\0", 8) != 0) {
- PrintError("Invalid Configuration Header\n");
+ if (memcmp(cfg_blob, COOKIE_V0, COOKIE_LEN) == 0) {
+ version = 0;
+ } else if (memcmp(cfg_blob, COOKIE_V1, COOKIE_LEN) == 0) {
+ version = 1;
+ } else {
+ PrintError("Invalid Configuration Header Or Unknown Version\n");
return NULL;
- }
+ }
- offset += 8;
+ V3_Print("Handling Palacios Image Format, Version 0x%x\n",version);
+
+ offset += COOKIE_LEN;
cfg = (struct v3_config *)V3_Malloc(sizeof(struct v3_config));
+
+ if (!cfg) {
+ PrintError("Unable to allocate while parsing\n");
+ return NULL;
+ }
+
memset(cfg, 0, sizeof(struct v3_config));
cfg->blob = cfg_blob;
INIT_LIST_HEAD(&(cfg->file_list));
cfg->file_table = v3_create_htable(0, file_hash_fn, file_eq_fn);
+
+ if (!(cfg->file_table)) {
+ PrintError("Unable to allocate hash table while parsing\n");
+ V3_Free(cfg);
+ return NULL;
+ }
xml_len = *(uint32_t *)(cfg_blob + offset);
offset += 4;
offset += 8;
- files = (struct file_idx_table *)(cfg_blob + offset);
+ // This is hideous, but the file formats are still very close
+ if (version==0) {
+ files_v0 = (struct file_idx_table_v0 *)(cfg_blob + offset);
+ V3_Print("Number of files in cfg: %d\n", (uint32_t)(files_v0->num_files));
+ } else {
+ files_v1 = (struct file_idx_table_v1 *)(cfg_blob + offset);
+ V3_Print("Number of files in cfg: %d\n", (uint32_t)(files_v1->num_files));
+ }
- V3_Print("Number of files in cfg: %d\n", (uint32_t)(files->num_files));
file_tree = v3_cfg_subtree(v3_cfg_subtree(cfg->cfg, "files"), "file");
char * id = v3_cfg_val(file_tree, "id");
char * index = v3_cfg_val(file_tree, "index");
int idx = atoi(index);
- struct file_hdr * hdr = &(files->hdrs[idx]);
struct v3_cfg_file * file = NULL;
file = (struct v3_cfg_file *)V3_Malloc(sizeof(struct v3_cfg_file));
if (!file) {
PrintError("Could not allocate file structure\n");
+ v3_free_htable(cfg->file_table,0,0);
+ V3_Free(cfg);
return NULL;
}
V3_Print("File index=%d id=%s\n", idx, id);
- strncpy(file->tag, id, 256);
- file->size = hdr->size;
- file->data = cfg_blob + hdr->offset;
-
- V3_Print("Storing file data offset = %d, size=%d\n", (uint32_t)hdr->offset, hdr->size);
- V3_Print("file data at %p\n", file->data);
+ strncpy(file->tag, id, V3_MAX_TAG_LEN);
+
+ if (version==0) {
+ struct file_hdr_v0 * hdr = &(files_v0->hdrs[idx]);
+
+ file->size = hdr->size;
+ file->data = cfg_blob + hdr->offset;
+ file->hash = 0;
+
+ V3_Print("Storing file data offset = %d, size=%d\n", (uint32_t)hdr->offset, hdr->size);
+ V3_Print("file data at %p\n", file->data);
+
+ } else if (version==1) {
+ struct file_hdr_v1 * hdr = &(files_v1->hdrs[idx]);
+ unsigned long hash;
+
+ file->size = hdr->size;
+ file->data = cfg_blob + hdr->offset;
+ file->hash = hdr->hash;
+
+ V3_Print("Storing file data offset = %d, size=%d\n", (uint32_t)hdr->offset, hdr->size);
+ V3_Print("file data at %p\n", file->data);
+ V3_Print("Checking file data integrity...\n");
+ if ((hash = v3_hash_buffer(file->data, file->size)) != file->hash) {
+ PrintError("File data corrupted! (orig hash=0x%lx, new=0x%lx\n",
+ file->hash, hash);
+ return NULL;
+ }
+ V3_Print("File data OK\n");
+
+ }
+
+
list_add( &(file->file_node), &(cfg->file_list));
V3_Print("Keying file to name\n");
static int determine_paging_mode(struct guest_info * info, v3_cfg_tree_t * core_cfg) {
- extern v3_cpu_arch_t v3_cpu_types[];
+ extern v3_cpu_arch_t v3_mach_type;
v3_cfg_tree_t * vm_tree = info->vm_info->cfg_data->cfg;
v3_cfg_tree_t * pg_tree = v3_cfg_subtree(vm_tree, "paging");
if (pg_mode) {
if ((strcasecmp(pg_mode, "nested") == 0)) {
// we assume symmetric cores, so if core 0 has nested paging they all do
- if ((v3_cpu_types[0] == V3_SVM_REV3_CPU) ||
- (v3_cpu_types[0] == V3_VMX_EPT_CPU) ||
- (v3_cpu_types[0] == V3_VMX_EPT_UG_CPU)) {
+ if ((v3_mach_type == V3_SVM_REV3_CPU) ||
+ (v3_mach_type == V3_VMX_EPT_CPU) ||
+ (v3_mach_type == V3_VMX_EPT_UG_CPU)) {
+
+ V3_Print("Setting paging mode to NESTED\n");
info->shdw_pg_mode = NESTED_PAGING;
} else {
PrintError("Nested paging not supported on this hardware. Defaulting to shadow paging\n");
info->shdw_pg_mode = SHADOW_PAGING;
}
} else if ((strcasecmp(pg_mode, "shadow") == 0)) {
+ V3_Print("Setting paging mode to SHADOW\n");
info->shdw_pg_mode = SHADOW_PAGING;
} else {
PrintError("Invalid paging mode (%s) specified in configuration. Defaulting to shadow paging\n", pg_mode);
info->shdw_pg_mode = SHADOW_PAGING;
}
} else {
- PrintDebug("No paging type specified in configuration. Defaulting to shadow paging\n");
+ V3_Print("No paging type specified in configuration. Defaulting to shadow paging\n");
info->shdw_pg_mode = SHADOW_PAGING;
}
return -1;
}
- v3_init_core(info);
+ if (v3_init_core(info) == -1) {
+ PrintError("Error Initializing Core\n");
+ return -1;
+ }
if (info->vm_info->vm_class == V3_PC_VM) {
if (pre_config_pc_core(info, core_cfg) == -1) {
static int post_config_vm(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
- vm->run_state = VM_STOPPED;
+
// Configure the memory map for the guest
if (setup_memory_map(vm, cfg) == -1) {
}
+ if (vm->vm_class == V3_PC_VM) {
+ if (post_config_pc(vm, cfg) == -1) {
+ PrintError("PC Post configuration failure\n");
+ return -1;
+ }
+ } else {
+ PrintError("Invalid VM Class\n");
+ return -1;
+ }
+
+
/*
* Initialize configured devices
*/
v3_print_msr_map(vm);
- if (vm->vm_class == V3_PC_VM) {
- if (post_config_pc(vm, cfg) == -1) {
- PrintError("PC Post configuration failure\n");
- return -1;
- }
- } else {
- PrintError("Invalid VM Class\n");
- return -1;
- }
+
/*
* Initialize configured extensions
}
+ vm->run_state = VM_STOPPED;
+
return 0;
}
static int post_config_core(struct guest_info * info, v3_cfg_tree_t * cfg) {
- info->core_run_state = CORE_STOPPED;
if (v3_init_core_extensions(info) == -1) {
PrintError("Error intializing extension core states\n");
int guest_state_size = sizeof(struct v3_vm_info) + (sizeof(struct guest_info) * num_cores);
struct v3_vm_info * vm = V3_Malloc(guest_state_size);
+ if (!vm) {
+ PrintError("Unable to allocate space for guest data structures\n");
+ return NULL;
+ }
+
+ int i = 0;
+
memset(vm, 0, guest_state_size);
vm->num_cores = num_cores;
+ for (i = 0; i < num_cores; i++) {
+ vm->cores[i].core_run_state = CORE_INVALID;
+ }
+
+ vm->run_state = VM_INVALID;
+
return vm;
}
struct v3_vm_info * v3_config_guest(void * cfg_blob, void * priv_data) {
- v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
+ extern v3_cpu_arch_t v3_mach_type;
struct v3_config * cfg_data = NULL;
struct v3_vm_info * vm = NULL;
int num_cores = 0;
v3_cfg_tree_t * cores_cfg = NULL;
v3_cfg_tree_t * per_core_cfg = NULL;
- if (cpu_type == V3_INVALID_CPU) {
+ if (v3_mach_type == V3_INVALID_CPU) {
PrintError("Configuring guest on invalid CPU\n");
return NULL;
}
for (i = 0; i < vm->num_cores; i++) {
struct guest_info * info = &(vm->cores[i]);
- info->cpu_id = i;
+ info->vcpu_id = i;
info->vm_info = vm;
info->core_cfg_data = per_core_cfg;
while (extension) {
char * ext_name = v3_cfg_val(extension, "name");
+ if (!ext_name) {
+ PrintError("Extension has no name\n");
+ return -1;
+ }
+
V3_Print("Configuring extension %s\n", ext_name);
if (v3_add_extension(vm, ext_name, extension) == -1) {