}
}
+
+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<size;i++) {
+ sum+=((char*)image)[i];
+ }
+
+ HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
+
+ if (rc) {
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
int v3_hvm_ros_reset(reset_type what)
{
unsigned long long num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
int v3_hvm_ros_user_deinit();
+// Replace the existing HRT with a new one
+// - this does not boot the new HRT
+// - the intial image is the one given in the .pal config
+int v3_hvm_ros_install_hrt_image(void *image, uint64_t size);
+
typedef enum {RESET_HRT, RESET_ROS, RESET_BOTH} reset_type;
int v3_hvm_ros_reset(reset_type what);
uint8_t is_hvm;
uint32_t first_hrt_core;
uint64_t first_hrt_gpa;
- struct v3_cfg_file *hrt_file;
+ struct v3_cfg_file *hrt_file; // image provided via PAL file, if any
+ void *hrt_image; // image provided by ROS, if any
+ uint64_t hrt_image_size; // size of this image
uint64_t hrt_entry_addr;
enum { HRT_BLOB, HRT_ELF64, HRT_MBOOT2, HRT_MBOOT64 } hrt_type;
0x1 => 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
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
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;
}
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)) {
{
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) {
}
-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");
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;
}
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;
}
-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
}
-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) {
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",
} 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;
}