From: Peter Dinda Date: Thu, 17 Sep 2015 20:52:54 +0000 (-0500) Subject: HRT image replacement from ROS application X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=d13fa71cb7a372c39ea92aaa69d74d63d9e0ed8e HRT image replacement from ROS application This adds the capability for a ROS application to dynamically replace the HRT image within the HVM. Combined with HRT boot and other capabilities, this allows the ROS to essentially fork and exec an HRT that operates over its address space. --- diff --git a/guest/linux/hvm-ros/v3_hvm_ros_user.c b/guest/linux/hvm-ros/v3_hvm_ros_user.c index 74e6a5a..345f8cb 100644 --- a/guest/linux/hvm-ros/v3_hvm_ros_user.c +++ b/guest/linux/hvm-ros/v3_hvm_ros_user.c @@ -239,6 +239,32 @@ static void wait_for_completion() } } + +int v3_hvm_ros_install_hrt_image(void *image, uint64_t size) +{ + unsigned long long rc, num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0; + unsigned long long i; + volatile long long sum=0; + + num = 0xf00d; + a1 = 0x8; // install image + a2 = (unsigned long long) image; + a3 = size; + + // touch the whoel image to make it has ptes + for (i=0;i Reboot ROS 0x2 => Reboot HRT 0x3 => Reboot Both + + 0x8 => Replace HRT image + pass in pointer (gva) and length of new image + 0xf => Get HRT transaction state and current ROS event first argument is pointer to the ROS event state to be filled out diff --git a/palacios/include/palacios/vmm_multiboot.h b/palacios/include/palacios/vmm_multiboot.h index 7feeb50..6803e80 100644 --- a/palacios/include/palacios/vmm_multiboot.h +++ b/palacios/include/palacios/vmm_multiboot.h @@ -295,8 +295,8 @@ int v3_setup_multiboot_core_for_boot(struct guest_info *core); int v3_handle_multiboot_reset(struct guest_info *core); // The following are utility functions that HVM builds on -int v3_parse_multiboot_header(struct v3_cfg_file *file, mb_data_t *result); -int v3_write_multiboot_kernel(struct v3_vm_info *vm, mb_data_t *mb, struct v3_cfg_file *file, +int v3_parse_multiboot_header(void *data, uint64_t len, mb_data_t *result); +int v3_write_multiboot_kernel(struct v3_vm_info *vm, mb_data_t *mb, void *data, uint64_t len, void *base, uint64_t limit); // The multiboot table is prepared from the perspective of the given // core - this allows it to be generated appropriately for ROS and HRT cores diff --git a/palacios/src/palacios/vmm_hvm.c b/palacios/src/palacios/vmm_hvm.c index ff5b34f..3818663 100644 --- a/palacios/src/palacios/vmm_hvm.c +++ b/palacios/src/palacios/vmm_hvm.c @@ -104,6 +104,7 @@ static int hvm_hcall_handler(struct guest_info * core , hcall_id_t hcall_id, voi uint64_t bitness = core->vm_regs.rbx; uint64_t a1 = core->vm_regs.rcx; uint64_t a2 = core->vm_regs.rdx; + uint64_t a3 = core->vm_regs.rsi; struct v3_vm_hvm *h = &core->vm_info->hvm_state; @@ -155,6 +156,40 @@ static int hvm_hcall_handler(struct guest_info * core , hcall_id_t hcall_id, voi } break; + case 0x8: // replace HRT image + // a2 = gva of image + // a3 = size of image + PrintDebug(core->vm_info,core,"hvm: request replacement HRT image addr=0x%llx size=0x%llx\n",a2,a3); + + if (h->hrt_image) { + // delete old + V3_VFree(h->hrt_image); + h->hrt_image = 0; + } + + h->hrt_image = V3_VMalloc(a3); + + if (!(h->hrt_image)) { + PrintError(core->vm_info,core, "hvm: failed to allocate space for replacement image\n"); + core->vm_regs.rax = -1; + } else { + if (v3_read_gva_memory(core, a2, a3, (uint8_t*) h->hrt_image)!=a3) { + PrintError(core->vm_info, core, "hvm: cannot read replacement image\n"); + core->vm_regs.rax = -1; + } else { + h->hrt_image_size = a3; + core->vm_regs.rax = 0; + } + } + + if (core->vm_regs.rax) { + PrintError(core->vm_info,core,"hvm: Failed to replace HRT image\n"); + } else { + PrintDebug(core->vm_info,core,"hvm: HRT image successfully replaced\n"); + } + + break; + case 0xf: // get HRT state core->vm_regs.rax = h->trans_state; if (v3_write_gva_memory(core, a2, sizeof(h->ros_event), (uint8_t*) &h->ros_event)!=sizeof(h->ros_event)) { @@ -520,6 +555,12 @@ int v3_deinit_hvm_vm(struct v3_vm_info *vm) { PrintDebug(vm, VCORE_NONE, "hvm: HVM VM deinit\n"); + if (vm->hvm_state.hrt_image) { + V3_VFree(vm->hvm_state.hrt_image); + vm->hvm_state.hrt_image=0; + vm->hvm_state.hrt_image_size=0; + } + v3_remove_hypercall(vm,HVM_HCALL); if (vm->hvm_state.comm_page_hpa) { @@ -1346,21 +1387,26 @@ static int configure_hrt(struct v3_vm_info *vm, mb_data_t *mb) } -static int setup_mb_kernel_hrt(struct v3_vm_info *vm) +static int setup_mb_kernel_hrt(struct v3_vm_info *vm, void *data, uint64_t size) { mb_data_t mb; - if (v3_parse_multiboot_header(vm->hvm_state.hrt_file,&mb)) { + if (v3_parse_multiboot_header(data, size, &mb)) { PrintError(vm,VCORE_NONE, "hvm: failed to parse multiboot kernel header\n"); return -1; } + if (!mb.mb64_hrt) { + PrintError(vm,VCORE_NONE,"hvm: invalid HRT - there is no MB64_HRT tag\n"); + return -1; + } + if (configure_hrt(vm,&mb)) { PrintError(vm,VCORE_NONE, "hvm: cannot configure HRT\n"); return -1; } - if (v3_write_multiboot_kernel(vm,&mb,vm->hvm_state.hrt_file, + if (v3_write_multiboot_kernel(vm,&mb,data,size, (void*)vm->hvm_state.first_hrt_gpa, vm->mem_size-vm->hvm_state.first_hrt_gpa)) { PrintError(vm,VCORE_NONE, "hvm: failed to write multiboot kernel into memory\n"); @@ -1382,11 +1428,23 @@ static int setup_mb_kernel_hrt(struct v3_vm_info *vm) static int setup_hrt(struct v3_vm_info *vm) { - if (is_elf(vm->hvm_state.hrt_file->data,vm->hvm_state.hrt_file->size) && - find_mb_header(vm->hvm_state.hrt_file->data,vm->hvm_state.hrt_file->size)) { + void *data; + uint64_t size; + + // If the ROS has installed an image, it takes priority + if (vm->hvm_state.hrt_image) { + data = vm->hvm_state.hrt_image; + size = vm->hvm_state.hrt_image_size; + } else { + data = vm->hvm_state.hrt_file->data; + size = vm->hvm_state.hrt_file->size; + } + + if (is_elf(data,size) && + find_mb_header(data,size)) { PrintDebug(vm,VCORE_NONE,"hvm: appears to be a multiboot kernel\n"); - if (setup_mb_kernel_hrt(vm)) { + if (setup_mb_kernel_hrt(vm,data,size)) { PrintError(vm,VCORE_NONE,"hvm: multiboot kernel setup failed\n"); return -1; } diff --git a/palacios/src/palacios/vmm_multiboot.c b/palacios/src/palacios/vmm_multiboot.c index 611ccaa..0959c48 100644 --- a/palacios/src/palacios/vmm_multiboot.c +++ b/palacios/src/palacios/vmm_multiboot.c @@ -181,7 +181,7 @@ static int checksum4_ok(uint32_t *data, uint64_t size) return sum==0; } -static int parse_multiboot_kernel(uint8_t *data, uint64_t size, mb_data_t *mb) +int v3_parse_multiboot_header(void *data, uint64_t size, mb_data_t *mb) { uint64_t i; @@ -327,11 +327,6 @@ static int parse_multiboot_kernel(uint8_t *data, uint64_t size, mb_data_t *mb) } -int v3_parse_multiboot_header(struct v3_cfg_file *file, mb_data_t *result) -{ - return parse_multiboot_kernel(file->data,file->size,result); -} - #define APIC_BASE 0xfee00000 #define IOAPIC_BASE 0xfec00000 @@ -541,11 +536,11 @@ uint64_t v3_build_multiboot_table(struct guest_info *core, uint8_t *dest, uint64 } -int v3_write_multiboot_kernel(struct v3_vm_info *vm, mb_data_t *mb, struct v3_cfg_file *file, +int v3_write_multiboot_kernel(struct v3_vm_info *vm, mb_data_t *mb, void *data, uint64_t len, void *base, uint64_t limit) { uint32_t offset=0; - uint32_t header_offset = (uint32_t) ((uint64_t)(mb->header) - (uint64_t)(file->data)); + uint32_t header_offset = (uint32_t) ((uint64_t)(mb->header) - (uint64_t)(data)); uint32_t size; if (!mb->addr || !mb->entry) { @@ -563,15 +558,15 @@ int v3_write_multiboot_kernel(struct v3_vm_info *vm, mb_data_t *mb, struct v3_cf offset = header_offset - (mb->addr->header_addr - mb->addr->load_addr); size = mb->addr->load_end_addr - mb->addr->load_addr; - if (size != file->size-offset) { - V3_Print(vm,VCORE_NONE,"multiboot: strange: size computed as %u, but file->size-offset = %llu\n",size,file->size-offset); + if (size != len-offset) { + V3_Print(vm,VCORE_NONE,"multiboot: strange: size computed as %u, but len-offset = %llu\n",size,len-offset); } // We are trying to do as little ELF loading here as humanly possible v3_write_gpa_memory(&vm->cores[0], (addr_t)(mb->addr->load_addr), size, - file->data+offset); + data+offset); PrintDebug(vm,VCORE_NONE, "multiboot: wrote 0x%llx bytes starting at offset 0x%llx to %p\n", @@ -615,11 +610,11 @@ static int setup_multiboot_kernel(struct v3_vm_info *vm) } else { if (find_mb_header(vm->mb_state.mb_file->data,vm->mb_state.mb_file->size)) { PrintDebug(vm,VCORE_NONE,"multiboot: appears to be a multiboot kernel\n"); - if (v3_parse_multiboot_header(vm->mb_state.mb_file,&vm->mb_state.mb_data)) { + if (v3_parse_multiboot_header(vm->mb_state.mb_file->data,vm->mb_state.mb_file->size,&vm->mb_state.mb_data)) { PrintError(vm,VCORE_NONE,"multiboot: cannot parse multiboot kernel header\n"); return -1; } - if (v3_write_multiboot_kernel(vm, &(vm->mb_state.mb_data),vm->mb_state.mb_file,base,limit)) { + if (v3_write_multiboot_kernel(vm, &(vm->mb_state.mb_data),vm->mb_state.mb_file->data,vm->mb_state.mb_file->size,base,limit)) { PrintError(vm,VCORE_NONE,"multiboot: multiboot kernel setup failed\n"); return -1; }