⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 monitor-host.c

📁 bochs : one pc simulator.
💻 C
📖 第 1 页 / 共 4 页
字号:
      if ( guest_cpu->sreg[s].des.dpl != 3 ) {        retval = Plex86NoExecute_DPL; /* Fail. */        goto handleFail;        }      }    }  /* EFlags constraints:   *   VIP/VIF==0   *   VM==0   *   RF==0   *   NT==0   *   IOPL==0 (We may be able to allow this to be 0..2)   *   IF==1   *   TF==0   *   bit1==1   */  if ( (guest_cpu->eflags & (0x001b7302)) !=       (0x00000202) ) {    retval = Plex86NoExecute_EFlags; /* Fail. */    goto handleFail;    }  /* Notes on other stuff:   *  - CPUID emulation vs virtualization match.   */  /* NOTE: We should commit to executing the guest at this point.   *   We must not leave stray entries in the GDT.   *//* Install virtualized guest descriptors in GDT. * Either use descriptor caches from guest space, or we have * to chase down the GDT entries using the guest's paging * system.  Might be a cheaper/safe bet to just use the * descriptor caches.  If the guest reloads a descriptor, * just let the user space deal with it. */  for (s=0; s<6; s++) {    if ( (guest_cpu->sreg[s].sel.raw & 0xfffc) != 0) {      vm->host.addr.gdt[ guest_cpu->sreg[s].sel.fields.index ] =          guest_cpu->sreg[s].des;      }    }#warning "Have to clear out GDT"  guest_stack_context->gs = guest_cpu->sreg[SRegGS].sel.raw;  guest_stack_context->fs = guest_cpu->sreg[SRegFS].sel.raw;  guest_stack_context->ds = guest_cpu->sreg[SRegDS].sel.raw;  guest_stack_context->es = guest_cpu->sreg[SRegES].sel.raw;  /* Could use memcpy(); both are in order.  Pack both structs. */  guest_stack_context->edi = guest_cpu->edi;  guest_stack_context->esi = guest_cpu->esi;  guest_stack_context->ebp = guest_cpu->ebp;  guest_stack_context->dummy_esp = 0; /* Not needed. */  guest_stack_context->ebx = guest_cpu->ebx;  guest_stack_context->edx = guest_cpu->edx;  guest_stack_context->ecx = guest_cpu->ecx;  guest_stack_context->eax = guest_cpu->eax;  /* Fields vector/error are ignored for return to guest. */  /* CS:EIP */  guest_stack_context->eip = guest_cpu->eip;  guest_stack_context->cs  = guest_cpu->sreg[SRegCS].sel.raw;  guest_stack_context->eflags.raw = guest_cpu->eflags;  vm->veflags.raw = 0; /* Virtualized EFLAGS - implement later. */  guest_stack_context->esp = guest_cpu->esp;  guest_stack_context->ss  = guest_cpu->sreg[SRegSS].sel.raw;  /* Pointer to the fields in the nexus.S assembly code. */  nexus = vm->host.addr.nexus;#warning "Monitor CRx hacks"  nexus->mon_cr0 = 0x8001003b | /* PG/WP/NE/ET/TS/MP/PE */    (guest_cpu->cr0.raw & 0x00040000); /* Pass-thru AM from guest. */  /* Could move mon_cr3 load to mapMonitor. */  nexus->mon_cr3 = vm->pages.page_dir << 12;  nexus->mon_cr4 = 0x00000004; /* TSD=1 *//* vm->guest_cpu.cr0.raw = guest_cpu->cr0 | 0x32; */ /* +++ hack for now */// Notes://   - Implement some of monPagingRemap from old code, since that//   was intended to be run/triggered by an initial mode change.//   - After execution of 1st timeslice, need to copy dynamic state//   from VM to guest_cpu area.//   - Deal with cycle counts etc.  hostInitShadowPaging(vm);  for (;;) {    unsigned long eflags;#if 0    /* If print buffer has contents, return to user space to print. */    if (vm->log_buffer_info.offset) {      vm->mon_msgs.header.msg_type = VMMessagePrintBuf;      vm->mon_msgs.header.msg_len  = 0;      vm->mon_request = MonReqNone; /* Request satisfied */      resetPrintBuf(vm); /* xxx Fix print mess */      retval = 100;      goto handleFail;      }#endif    vm_save_flags(eflags);    vm_restore_flags(eflags & ~0x00004300); /* clear NT/IF/TF */#if ANAL_CHECKS    if (!(eflags & 0x200)) {      vm_restore_flags(eflags);      hostOSPrint("ioctlExecute: EFLAGS.IF==0\n");      retval = 101; /* Fail. */      goto handlePanic;      }#endif    /* Call assembly routine to effect transition. */    vm->host.__host2mon();    /* First check for an asynchronous event (interrupt redirection) */    if ( vm->mon_request == MonReqRedirect ) {      vm_restore_flags(eflags & ~0x00000200); /* restore all but IF */      soft_int(vm->redirect_vector); /* sets IF to 1 */      hostOSInstrumentIntRedirCount(vm->redirect_vector);      vm->mon_request = MonReqNone; /* Request satisfied */      }    /* Event was synchronous; monitor requested a switch back to host. */    else {      vm_restore_flags(eflags);      /* Perform action requested by monitor. */      switch ( vm->mon_request ) {        case MonReqRemapMonitor:#if 0          if ( mapMonitor(vm) ) {            vm->mon_request = MonReqNone; /* Request satisfied */            break;            }          else {            hostOSPrint("mapMonitor failed.\n");            hostOSPrint("Panic w/ abort_code=%u\n", vm->abort_code);            retval = 102;            goto handlePanic;            }#endif          hostOSPrint("ioctlExecute: case MonReqRemapMonitor.\n");          retval = 103;          goto handlePanic;        case MonReqFlushPrintBuf:          hostOSPrint("ioctlExecute: case MonReqFlushPrintBuf.\n");          retval = 104;          goto handlePanic;        case MonReqGuestFault:          /* Encountered a guest fault. */          hostCopyGuestStateToUserSpace(vm);          executeMsg->cyclesExecuted       = 0; /* Handle later. */          executeMsg->instructionsExecuted = 0; /* Handle later. */          executeMsg->monitorState.state   = vm->vmState;          executeMsg->monitorState.request = vm->mon_request;          executeMsg->monitorState.guestFaultNo = vm->guestFaultNo;          vm->mon_request = MonReqNone;          return 0;        case MonReqPanic:          if (vm->abort_code)            hostOSPrint("Panic w/ abort_code=%u\n", vm->abort_code);          hostOSPrint("ioctlExecute: case MonReqPanic.\n");          retval = 106;          goto handlePanic;        case MonReqPinUserPage:          if ( !hostHandlePagePinRequest(vm, vm->pinReqPPI) ) {            retval = 108;            goto handlePanic;            }          continue; /* Back to VM monitor. */        default:          hostOSPrint("ioctlExecute: default case (%u).\n", vm->mon_request);          retval = 107;          goto handlePanic;        }      }    /* Let host decide whether we are allowed another timeslice */    if ( !hostOSIdle() ) {      /* We are returning only because the host wants to       * schedule other work.       */      executeMsg->monitorState.state   = vm->vmState;      executeMsg->monitorState.request = MonReqNone;      return 0;      }    }  /* Should not get here. */  retval = 109;  goto handlePanic;handleFail:  /* Handle inabilitiy to execute the guest due to certain state. */  executeMsg->monitorState.state   = vm->vmState;  executeMsg->monitorState.request = vm->mon_request;  return(retval);handlePanic:  vm->vmState  |= VMStatePanic;  vm->mon_request = MonReqPanic;  executeMsg->monitorState.state   = vm->vmState;  executeMsg->monitorState.request = vm->mon_request;  return(retval);}  voidhostCopyGuestStateToUserSpace(vm_t *vm){  guest_cpu_t     *guest_cpu;  guest_context_t *guest_stack_context;  /* A pointer to the guest CPU state as passed from host-user space.   * This structure is memory mapped between user and kernel/monitor space.   */  guest_cpu = vm->host.addr.guest_cpu;  /* A pointer to the guest CPU state saved on the monitor stack. */  guest_stack_context =  vm->host.addr.guest_context;  guest_cpu->sreg[SRegES].sel.raw = guest_stack_context->es;  if ( (guest_stack_context->es & 0xfffc) == 0 ) {    guest_cpu->sreg[SRegES].des = nullDescriptor;    guest_cpu->sreg[SRegES].valid = 0;    }  else {    guest_cpu->sreg[SRegES].des =      vm->host.addr.gdt[ guest_cpu->sreg[SRegES].sel.fields.index ];    guest_cpu->sreg[SRegES].valid = 1;    }  guest_cpu->sreg[SRegCS].sel.raw = guest_stack_context->cs;  if ( (guest_stack_context->cs & 0xfffc) == 0 ) {    guest_cpu->sreg[SRegCS].des = nullDescriptor;    guest_cpu->sreg[SRegCS].valid = 0;    }  else {    guest_cpu->sreg[SRegCS].des =      vm->host.addr.gdt[ guest_cpu->sreg[SRegCS].sel.fields.index ];    guest_cpu->sreg[SRegCS].valid = 1;    }  guest_cpu->sreg[SRegSS].sel.raw = guest_stack_context->ss;  if ( (guest_stack_context->ss & 0xfffc) == 0 ) {    guest_cpu->sreg[SRegSS].des = nullDescriptor;    guest_cpu->sreg[SRegSS].valid = 0;    }  else {    guest_cpu->sreg[SRegSS].des =      vm->host.addr.gdt[ guest_cpu->sreg[SRegSS].sel.fields.index ];    guest_cpu->sreg[SRegSS].valid = 1;    }  guest_cpu->sreg[SRegDS].sel.raw = guest_stack_context->ds;  if ( (guest_stack_context->ds & 0xfffc) == 0 ) {    guest_cpu->sreg[SRegDS].des = nullDescriptor;    guest_cpu->sreg[SRegDS].valid = 0;    }  else {    guest_cpu->sreg[SRegDS].des =      vm->host.addr.gdt[ guest_cpu->sreg[SRegDS].sel.fields.index ];    guest_cpu->sreg[SRegDS].valid = 1;    }  guest_cpu->sreg[SRegFS].sel.raw = guest_stack_context->fs;  if ( (guest_stack_context->fs & 0xfffc) == 0 ) {    guest_cpu->sreg[SRegFS].des = nullDescriptor;    guest_cpu->sreg[SRegFS].valid = 0;    }  else {    guest_cpu->sreg[SRegFS].des =      vm->host.addr.gdt[ guest_cpu->sreg[SRegFS].sel.fields.index ];    guest_cpu->sreg[SRegFS].valid = 1;    }  guest_cpu->sreg[SRegGS].sel.raw = guest_stack_context->gs;  if ( (guest_stack_context->gs & 0xfffc) == 0 ) {    guest_cpu->sreg[SRegGS].des = nullDescriptor;    guest_cpu->sreg[SRegGS].valid = 0;    }  else {    guest_cpu->sreg[SRegGS].des =      vm->host.addr.gdt[ guest_cpu->sreg[SRegGS].sel.fields.index ];    guest_cpu->sreg[SRegGS].valid = 1;    }  /* Could use memcpy(); both are in order.  Pack both structs. */  guest_cpu->edi = guest_stack_context->edi;  guest_cpu->esi = guest_stack_context->esi;  guest_cpu->ebp = guest_stack_context->ebp;  guest_cpu->esp = guest_stack_context->esp;  guest_cpu->ebx = guest_stack_context->ebx;  guest_cpu->edx = guest_stack_context->edx;  guest_cpu->ecx = guest_stack_context->ecx;  guest_cpu->eax = guest_stack_context->eax;  /* CS:EIP */  guest_cpu->eip = guest_stack_context->eip;  guest_cpu->eflags = guest_stack_context->eflags.raw;  /* vm->veflags.raw = 0; */ /* Virtualized EFLAGS - implement later. */}  inthostIoctlRegisterMem(vm_t *vm, plex86IoctlRegisterMem_t *registerMemMsg){  unsigned error;  /* Do not allow duplicate allocation.  The file descriptor must be   * opened.  The guest CPUID info can be filled in later.   */  if ( (vm->vmState & ~VMStateGuestCPUID) != VMStateFDOpened )    return -Plex86ErrnoEBUSY;  if (vm->pages.guest_n_megs != 0)    return -Plex86ErrnoEBUSY;  /* Check that the amount of memory is reasonable. */  if ( (registerMemMsg->nMegs > PLEX86_MAX_PHY_MEGS)  ||       (registerMemMsg->nMegs < 4) ||       (registerMemMsg->nMegs & 0x3) )    return -Plex86ErrnoEINVAL;  /* Check that the guest memory vector is page aligned. */  if ( registerMemMsg->guestPhyMemVector & 0xfff )    return -Plex86ErrnoEINVAL;  /* Check that the log buffer area is page aligned. */  if ( registerMemMsg->logBufferWindow & 0xfff )    return -Plex86ErrnoEINVAL;  /* Check that the guest CPU area is page aligned. */  if ( registerMemMsg->guestCPUWindow & 0xfff )    return -Plex86ErrnoEINVAL;  /* Check that none of the user areas overlap.  In case we have a   * number of regions, use some generic code to handle N regions.   */  {#define NumUserRegions 3  struct {    Bit32u min, max;    } userRegion[NumUserRegions];  unsigned i,j;  userRegion[0].min = registerMemMsg->guestPhyMemVector;  userRegion[0].max = userRegion[0].min + (registerMemMsg->nMegs<<20) - 1;  userRegion[1].min = registerMemMsg->logBufferWindow;  userRegion[1].max = userRegion[1].min + LOG_BUFF_SIZE - 1;  userRegion[2].min = registerMemMsg->guestCPUWindow;  userRegion[2].max = userRegion[2].min + (4096) - 1;  for (i=1; i<NumUserRegions; i++) {    for (j=1; j<NumUserRegions; j++) {      if (j == i)        continue; /* Don't compare at the same region. */      /* Check for min(j) contained in region(i). */      if ( (userRegion[j].min >= userRegion[i].min) &&           (userRegion[j].min <= userRegion[i].max) )        return -Plex86ErrnoEINVAL;      /* Check for max(j) contained in region(i). */      if ( (userRegion[j].max >= userRegion[i].min) &&           (userRegion[j].max <= userRegion[i].max) )        return -Plex86ErrnoEINVAL;      }    }  }  /* Allocate memory */  if ( (error = hostAllocVmPages(vm, registerMemMsg)) != 0 ) {    hostOSPrint("plex86: allocVmPages failed at %u\n",                error);    return -Plex86ErrnoENOMEM;    }  /* Initialize the guests physical memory. */  if ( hostInitGuestPhyMem(vm) ) {    hostUnallocVmPages(vm);    return -Plex86ErrnoEFAULT;    }  /* Initialize the monitor. */  if ( !hostInitMonitor(vm) ||       !hostMapMonitor(vm) ) {    hostUnallocVmPages(vm);    return -Plex86ErrnoEFAULT;    }  return 0;}/* * Allocate various pages/memory needed by monitor. */  inthostAllocVmPages(vm_t *vm, plex86IoctlRegisterMem_t *registerMemMsg){  vm_pages_t *pg = &vm->pages;  vm_addr_t  *ad = &vm->host.addr;#warning "Fix these shortcuts"  unsigned where = 1;  /* clear out allocated pages lists */  mon_memzero(pg, sizeof(*pg));  mon_memzero(ad, sizeof(*ad));  /* Guest physical memory pages */  pg->guest_n_megs  = registerMemMsg->nMegs;  pg->guest_n_pages = registerMemMsg->nMegs * 256;  pg->guest_n_bytes = registerMemMsg->nMegs * 1024 * 1024;  if ( pg->guest_n_pages > MAX_MON_GUEST_PAGES) {    /* The size of the user-space allocated guest physical memory must     * fit within the maximum number of guest pages that the VM monitor     * supports.     */    goto error;    }  where++;  vm->guestPhyMemAddr = registerMemMsg->guestPhyMemVector;  vm->vmState |= VMStateRegisteredPhyMem; /* Bogus for now. */  where++;  {  Bit32u hostPPI, kernelAddr;  /* Guest CPU state (malloc()'d in user space). */  if ( !hostOSGetAndPinUserPage(vm, registerMemMsg->guestCPUWindow,            &pg->guest_cpu_hostOSPtr, &hostPPI, &kernelAddr) ) {    goto error;    }  ad->guest_cpu = (guest_cpu_t *) kernelAddr;  pg->guest_cpu = hostPPI;vm->vmState |= VMStateRegisteredGuestCPU; /* For now. */  where++;  /* Log buffer area (malloc()'d in user space). */  /* LOG_BUFF_PAGES */  if ( !hostOSGetAndPinUserPage(vm, registerMemMsg->logBufferWindow,            &pg->log_buffer_hostOSPtr[0], &hostPPI, &kernelAddr) ) {    goto error;    }  ad->log_buffer = (Bit8u *) kernelAddr;  pg->log_buffer[0] = hostPPI;  where++;vm->vmState |= VMStateRegisteredPrintBuffer; /* For now. */  }  /* Monitor page directory */  if ( !(ad->page_dir = (pageEntry_t *) hostOSAllocZeroedPage()) ) {    goto error;    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -