Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


fix potential overflow condition in VMX assist
[palacios.git] / palacios / src / palacios / vmm_hvm.c
index 3e506d7..ff5b34f 100644 (file)
@@ -157,9 +157,34 @@ static int hvm_hcall_handler(struct guest_info * core , hcall_id_t hcall_id, voi
            
        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)) { 
+               PrintError(core->vm_info, core, "hvm: cannot write back ROS event state to %p - continuing\n",(void*)a2);
+           }
            //PrintDebug(core->vm_info,core,"hvm: get HRT transaction state 0x%llx\n",core->vm_regs.rax);
            break;
 
+       case 0x10:
+           PrintDebug(core->vm_info, core, "hvm: ROS event request\n");
+           if (h->ros_event.event_type!=ROS_NONE) { 
+               PrintError(core->vm_info, core, "hvm: ROS event is already in progress\n");
+               core->vm_regs.rax = -1;
+           } else {
+               if (v3_read_gva_memory(core, a2, sizeof(h->ros_event), (uint8_t*)&h->ros_event)!=sizeof(h->ros_event)) { 
+                   PrintError(core->vm_info, core, "hvm: cannot read ROS event from %p\n",(void*)a2);
+                   core->vm_regs.rax = -1;
+               } else {
+                   core->vm_regs.rax = 0;
+               }
+           }
+
+           break;
+
+       case 0x1f:
+           PrintDebug(core->vm_info, core, "hvm: completion of ROS event (rc=0x%llx)\n",a2);
+           h->ros_event.event_type=ROS_NONE;
+           h->ros_event.last_ros_event_result = a2;
+           break;
+
        case 0x20: // invoke function (ROS->HRT)
        case 0x21: // invoke parallel function (ROS->HRT)
            if (v3_is_hvm_hrt_core(core)) { 
@@ -228,21 +253,92 @@ static int hvm_hcall_handler(struct guest_info * core , hcall_id_t hcall_id, voi
            break;
 
 
-       case 0x2f: // function exec done
+       case 0x28: // setup for synchronous operation (ROS->HRT)
+       case 0x29: // teardown for synchronous operation (ROS->HRT)
+           if (v3_is_hvm_hrt_core(core)) { 
+               PrintError(core->vm_info,core,"hvm: %ssynchronization invocation not supported from HRT core\n",a1==0x29 ? "de" : "");
+               core->vm_regs.rax = -1;
+           } else {
+               if (ENFORCE_STATE_MACHINE && 
+                   ((a1==0x28 && h->trans_state!=HRT_IDLE) || (a1==0x29 && h->trans_state!=HRT_SYNC))) { 
+                   PrintError(core->vm_info,core, "hvm: cannot invoke %ssynchronization in state %d\n",a1==0x29 ? "de" : "", h->trans_state);
+                   core->vm_regs.rax = -1;
+               } else {
+                   uint64_t *page = (uint64_t *) h->comm_page_hva;
+                   uint64_t first, last, cur;
+
+                   PrintDebug(core->vm_info,core, "hvm: invoke %ssynchronization on address %p\n",a1==0x29 ? "de" : "",(void*)a2);
+                   page[0] = a1;
+                   page[1] = a2;
+
+                   first=last=h->first_hrt_core;  // initially we will sync only with BSP
+
+                   core->vm_regs.rax = 0;
+
+                   h->trans_count = last-first+1;
+
+                   for (cur=first;cur<=last;cur++) { 
+
+#if USE_UPCALL_MAGIC_PF
+                       PrintDebug(core->vm_info,core,"hvm: injecting magic #PF into core %llu\n",cur);
+                       core->vm_info->cores[cur].ctrl_regs.cr2 = UPCALL_MAGIC_ADDRESS;
+                       if (v3_raise_exception_with_error(&core->vm_info->cores[cur],
+                                                         PF_EXCEPTION, 
+                                                         UPCALL_MAGIC_ERROR)) { 
+                           PrintError(core->vm_info,core, "hvm: cannot inject HRT #PF to core %llu\n",cur);
+                           core->vm_regs.rax = -1;
+                           break;
+                       }
+#else
+                       PrintDebug(core->vm_info,core,"hvm: injecting SW intr 0x%u into core %llu\n",h->hrt_int_vector,cur);
+                       if (v3_raise_swintr(&core->vm_info->cores[cur],h->hrt_int_vector)) { 
+                           PrintError(core->vm_info,core, "hvm: cannot inject HRT interrupt to core %llu\n",cur);
+                           core->vm_regs.rax = -1;
+                           break;
+                       }
+#endif
+                       // Force core to exit now
+                       v3_interrupt_cpu(core->vm_info,core->vm_info->cores[cur].pcpu_id,0);
+                         
+                   }
+                   if (core->vm_regs.rax==0) { 
+                       if (a1==0x28) { 
+                           h->trans_state = HRT_SYNCSETUP;
+                       } else {
+                           h->trans_state = HRT_SYNCTEARDOWN;                      
+                       }
+                   }  else {
+                       PrintError(core->vm_info,core,"hvm: in inconsistent state due to HRT call failure\n");
+                       h->trans_state = HRT_IDLE;
+                       h->trans_count = 0;
+                   }
+               }
+           }
+           break;
+
+       case 0x2f: // function exec or sync done
            if (v3_is_hvm_ros_core(core)) { 
-               PrintError(core->vm_info,core, "hvm: request for exec done from ROS core\n");
+               PrintError(core->vm_info,core, "hvm: request for exec or sync done from ROS core\n");
                core->vm_regs.rax=-1;
            } else {
-               if (ENFORCE_STATE_MACHINE && h->trans_state!=HRT_CALL && h->trans_state!=HRT_PARCALL) {
-                   PrintError(core->vm_info,core,"hvm: function completion when not in HRT_CALL or HRT_PARCALL state\n");
+               if (ENFORCE_STATE_MACHINE && 
+                   h->trans_state!=HRT_CALL && 
+                   h->trans_state!=HRT_PARCALL && 
+                   h->trans_state!=HRT_SYNCSETUP &&
+                   h->trans_state!=HRT_SYNCTEARDOWN) {
+                   PrintError(core->vm_info,core,"hvm: function or sync completion when not in HRT_CALL, HRT_PARCALL, HRT_SYNCSETUP, or HRT_SYNCTEARDOWN state\n");
                    core->vm_regs.rax=-1;
                } else {
                    uint64_t one=1;
-                   PrintDebug(core->vm_info,core, "hvm: function complete\n");
+                   PrintDebug(core->vm_info,core, "hvm: function or sync complete\n");
                    if (__sync_fetch_and_sub(&h->trans_count,one)==1) {
                        // last one, switch state
-                       h->trans_state=HRT_IDLE;
-                       PrintDebug(core->vm_info,core, "hvm: function complete - back to idle\n");
+                       if (h->trans_state==HRT_SYNCSETUP) { 
+                           h->trans_state=HRT_SYNC;
+                           PrintDebug(core->vm_info,core, "hvm: function complete - now synchronous\n");
+                       } else {
+                           h->trans_state=HRT_IDLE;
+                       }
                    }
                    core->vm_regs.rax=0;
                }
@@ -492,7 +588,7 @@ uint32_t v3_get_hvm_hrt_cores(struct v3_vm_info *vm)
 int v3_is_hvm_ros_mem_gpa(struct v3_vm_info *vm, addr_t gpa)
 {
     if (vm->hvm_state.is_hvm) { 
-       return gpa>=0 && gpa<vm->hvm_state.first_hrt_gpa;
+       return gpa<vm->hvm_state.first_hrt_gpa;
     } else {
        return 1;
     }