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

📄 monitor-host.c

📁 bochs : one pc simulator.
💻 C
📖 第 1 页 / 共 4 页
字号:
  r |= hostInitIDTSlot(vm,  0, IDT_EXCEPTION_NOERROR); /* Divide error        */  r |= hostInitIDTSlot(vm,  1, IDT_EXCEPTION_NOERROR); /* Debug exceptions    */  r |= hostInitIDTSlot(vm,  2, IDT_INTERRUPT);         /* NMI                 */  r |= hostInitIDTSlot(vm,  3, IDT_EXCEPTION_NOERROR); /* Breakpoint          */  r |= hostInitIDTSlot(vm,  4, IDT_EXCEPTION_NOERROR); /* Overflow            */  r |= hostInitIDTSlot(vm,  5, IDT_EXCEPTION_NOERROR); /* Bounds check        */  r |= hostInitIDTSlot(vm,  6, IDT_EXCEPTION_NOERROR); /* Invalid opcode      */  r |= hostInitIDTSlot(vm,  7, IDT_EXCEPTION_NOERROR); /* FPU not available   */  r |= hostInitIDTSlot(vm,  8, IDT_EXCEPTION_ERROR);   /* Double fault        */  r |= hostInitIDTSlot(vm,  9, IDT_EXCEPTION_NOERROR); /* FPU segment overrun */  r |= hostInitIDTSlot(vm, 10, IDT_EXCEPTION_ERROR);   /* Invalid TSS         */  r |= hostInitIDTSlot(vm, 11, IDT_EXCEPTION_ERROR);   /* Segment not present */  r |= hostInitIDTSlot(vm, 12, IDT_EXCEPTION_ERROR);   /* Stack exception     */  r |= hostInitIDTSlot(vm, 13, IDT_EXCEPTION_ERROR);   /* GP fault            */  r |= hostInitIDTSlot(vm, 14, IDT_EXCEPTION_ERROR);   /* Page fault          */  r |= hostInitIDTSlot(vm, 15, IDT_EXCEPTION_NOERROR); /* reserved            */  r |= hostInitIDTSlot(vm, 16, IDT_EXCEPTION_NOERROR); /* Coprocessor error   */  r |= hostInitIDTSlot(vm, 17, IDT_EXCEPTION_ERROR);   /* Alignment check     */  r |= hostInitIDTSlot(vm, 18, IDT_EXCEPTION_NOERROR); /* Machine check       */  /* Reserved exceptions */  for (i = 19; i < 32; i++)      r |= hostInitIDTSlot(vm, i, IDT_EXCEPTION_NOERROR);  /* Hardware interrupts */  for (i = 32; i < 256; i++)      r |= hostInitIDTSlot(vm, i, IDT_INTERRUPT);  if (r!=0)       goto error;  /*   *  Setup the initial guest context   */  mon_memzero(vm->host.addr.guest_context, sizeof(guest_context_t));  /* Wind up the monitor stack for the initial transition via   * __host2mon.  At the tail end, monitor state is popped from the   * stack and a RET is executed.   */  {  Bit32u *ptr;  ptr = (Bit32u *) (((unsigned char *) vm->host.addr.guest_context) - 4);  *ptr-- = (Bit32u) &__ret_to_guest;  *ptr-- = 0x02; /* eflags: only reserved bit on */  *ptr-- = 0; /* eax */  *ptr-- = 0; /* ecx */  *ptr-- = 0; /* edx */  *ptr-- = 0; /* ebx */  *ptr-- = 0; /* esp dummy */  *ptr-- = 0; /* ebp */  *ptr-- = 0; /* esi */  *ptr-- = 0; /* edi */  *ptr-- = 0; /* FS; start with null value. */  *ptr-- = 0; /* GS; start with null value. */  }  vm->vmState |= VMStateInitMonitor;  vm->mon_request = MonReqNone;  return(1); /* all OK */error:  return(0); /* error */}  unsignedhostInitGuestPhyMem(vm_t *vm){  unsigned i;  mon_memzero(vm->pageInfo, sizeof(vm->pageInfo));  for (i=0; i<vm->pages.guest_n_pages; i++) {    /* For now, we start out by preallocating physical pages */    /* for the guest, though not necessarily mapped into linear */    /* space. */    vm->pageInfo[i].attr.raw = 0;    vm->pageInfo[i].tsc = 0;    vm->pageInfo[i].attr.fields.allocated = 1;    }   {  Bit32u rom_page;  unsigned npages;   /* Mark BIOS ROM area as ReadOnly */  rom_page = 0xf0000 >> 12;  npages = (1 + 0xfffff - 0xf0000) / 4096;  for (i=0; i<npages; i++)    vm->pageInfo[rom_page + i].attr.fields.RO = 1;  /* Mark VGA BIOS ROM area as ReadOnly */  rom_page = 0xc0000 >> 12;  npages = (1 + 0xc7fff - 0xc0000) / 4096;  for (i=0; i<npages; i++)    vm->pageInfo[rom_page + i].attr.fields.RO = 1;  } #if 1  /* Mark VGA framebuffer area as Memory Mapped IO */  {  Bit32u vga_page;  unsigned npages;   vga_page = 0xa0000 >> 12;  npages = (1 + 0xbffff - 0xa0000) / 4096;  for (i=0; i<npages; i++)    vm->pageInfo[vga_page + i].attr.fields.memMapIO = 1;  }#endif  return(0);}  inthostInitIDTSlot(vm_t *vm, unsigned vec, int type)/* *  initIDTSlot():  Initialize a monitor IDT slot. */{  /* IDT slot stubs */  idt_stub_t *stub = &vm->host.addr.idt_stubs[vec];  Bit32u stub_mon = ((Bit32u) vm->guest.addr.idt_stubs) +                    vec*sizeof(idt_stub_t);  if (sizeof(idt_stub_t) != IDT_STUB_SIZE)    return( -1 );  switch (type) {    case IDT_INTERRUPT:      stub->m2.pushla = 0x68;      stub->m2.dummy  = 0;      stub->m2.pushlb = 0x68;      stub->m2.vector = vec;      stub->m2.jmp    = 0xe9;      stub->m2.reloc  = ((Bit32u) &__handle_int) -        (stub_mon + sizeof(idt_method2_t));      break;    case IDT_EXCEPTION_ERROR:      stub->m1.pushl  = 0x68;      stub->m1.vector = vec;      stub->m1.jmp    = 0xe9;      stub->m1.reloc  = ((Bit32u) &__handle_fault) -        (stub_mon + sizeof(idt_method1_t));      break;    case IDT_EXCEPTION_NOERROR:      stub->m2.pushla = 0x68;      stub->m2.dummy  = 0;      stub->m2.pushlb = 0x68;      stub->m2.vector = vec;      stub->m2.jmp    = 0xe9;      stub->m2.reloc  = ((Bit32u) &__handle_fault) -        (stub_mon + sizeof(idt_method2_t));      break;    default:      return -1;    }  /* Set the interrupt gate */  SET_INT_GATE(vm->host.addr.idt[vec],               nullSelector, stub_mon, D_PRESENT, D_DPL0, D_D32);  return 0;}/* *  Map pages allocated by host, into the linear address space of *  the monitor/guest, given the Page Table supplied. */  voidhostMapMonPages(vm_t *vm, Bit32u *pages, unsigned n, Bit32u *laddr_p,                page_t *pageTable, unsigned user, unsigned writable, char *name){  unsigned i, pti;#if 0hostOSPrint("hostMapMonPages: '%s' mapped at 0x%x .. 0x%x.\n",            name,            (*laddr_p) - MON_BASE_FROM_LADDR(0),            ((*laddr_p) + (n*4096)) - MON_BASE_FROM_LADDR(0) );#endif  pti = (*laddr_p >> 12) & 0x3ff;  for (i = 0; i < n; i++, pti++) {    if (pti > 1024)        break;  /* This should not happen! */    /* Fill in the PTE flags */    pageTable->pte[pti].fields.base = pages[i];    pageTable->pte[pti].fields.avail = 0;    pageTable->pte[pti].fields.G = 0;         /* not global */    pageTable->pte[pti].fields.PS = 0;        /* (unused in pte) */    pageTable->pte[pti].fields.D = 0;         /* clean */    pageTable->pte[pti].fields.A = 0;         /* not accessed */    pageTable->pte[pti].fields.PCD = 0;       /* normal caching */    pageTable->pte[pti].fields.PWT = 0;       /* normal write-back */    pageTable->pte[pti].fields.US = user;     /* 0=system, 1=user */    pageTable->pte[pti].fields.RW = writable; /* 0=RO, 1=RW */    pageTable->pte[pti].fields.P = 1;         /* present in memory */    }  /*   *  Advance linear address pointer, for the next set of pages   *  to be mapped.   */  *laddr_p += 4096 * n;}#if ANAL_CHECKS  voidhostMapBlankPage(vm_t *vm, Bit32u *laddr_p, page_t *pageTable){  unsigned pti;   pti = (*laddr_p >> 12) & 0x3ff;  if (pti > 1024)    return;  /* This should not happen! */   /* Fill in the PTE flags */  pageTable->pte[pti].fields.base = 0;  pageTable->pte[pti].fields.avail = 0;  pageTable->pte[pti].fields.G = 0;      /* not global */  pageTable->pte[pti].fields.PS = 0;     /* (unused in pte) */  pageTable->pte[pti].fields.D = 0;      /* clean */  pageTable->pte[pti].fields.A = 0;      /* not accessed */  pageTable->pte[pti].fields.PCD = 0;    /* normal caching */  pageTable->pte[pti].fields.PWT = 0;    /* normal write-back */  pageTable->pte[pti].fields.US = 0;  pageTable->pte[pti].fields.RW = 0;  pageTable->pte[pti].fields.P = 0;   /*   *  Advance linear address pointer, for the next set of pages   *  to be mapped.   */  *laddr_p += 4096;}#endif  inthostIoctlGeneric(vm_t *vm, void *inode, void *filp,                 unsigned int cmd, unsigned long arg){  switch (cmd) {    /*     * Set the guest CPUID info.     */    case PLEX86_CPUID:      {      if ( vm->vmState & VMStateGuestCPUID ) {        /* Can't change guest CPUID. */        return -Plex86ErrnoEINVAL;        }      if ( hostOSCopyFromUser(&vm->guestCPUIDInfo, (void *)arg,                              sizeof(vm->guestCPUIDInfo)) )        return -Plex86ErrnoEFAULT;/* xxx Value checks here. */      vm->vmState |= VMStateGuestCPUID;      return 0;      }    case PLEX86_REGISTER_MEMORY:      {      plex86IoctlRegisterMem_t registerMemMsg;      if ( hostOSCopyFromUser(&registerMemMsg, (void *)arg,                              sizeof(registerMemMsg)) )        return -Plex86ErrnoEFAULT;      return( hostIoctlRegisterMem(vm, &registerMemMsg) );      }    /*     * Tear down the VM environment.     */    case PLEX86_TEARDOWN:      if ( vm->vmState & VMStateRegisteredAll ) {        hostOSPrint("plex86: guest memory is still registered!\n");        /* Could effect the unpinning here and then do:         *   vm->vmState &= ~VMStateRegisteredAll;         */        return -Plex86ErrnoEBUSY;        }      hostUnallocVmPages(vm);      /* Fixme: deal with state better here. */      /* Reset state to only FD opened. */      vm->vmState = VMStateFDOpened;      return 0;    /*     * Execute the guest in the VM for a while.  The guest CPU state     * is specified in a memory window mmap()'d to user space.     */    case PLEX86_EXECUTE:      {      plex86IoctlExecute_t executeMsg;      int ret;      if ( hostOSCopyFromUser(&executeMsg, (void *)arg, sizeof(executeMsg)) )        return -Plex86ErrnoEFAULT;      ret = hostIoctlExecute(vm, &executeMsg);      if ( hostOSCopyToUser((void *)arg, &executeMsg, sizeof(executeMsg)) )        return -Plex86ErrnoEFAULT;      return ret;      }#warning "PLEX86_RESET should only conditionally compiled for debugging."    /*     * For debugging, when the module gets hosed, this is a way     * to reset the in-use count, so we can rmmod it.     */    case PLEX86_RESET:      hostOSModuleCountReset(vm, inode, filp);      return 0;    default:      hostOSPrint("plex86: unknown ioctl(%d) called\n", cmd);      return -Plex86ErrnoEINVAL;    }}  inthostIoctlExecute(vm_t *vm, plex86IoctlExecute_t *executeMsg){  guest_cpu_t     *guest_cpu;  guest_context_t *guest_stack_context;  nexus_t *nexus;  unsigned s;  int retval;  if ( (vm->vmState != VMStateReady) ||       (vm->mon_request != MonReqNone) ) {    retval = Plex86NoExecute_VMState; /* Fail. */    goto handlePanic;    }  /* Only (virtualized) native execution is supported currently.   * Later, it will be interesting to breakpoint one instruction   * at-a-time using Plex86ExecuteMethodBreakpoint, for   * cosimulation.   */  if (executeMsg->executeMethod != Plex86ExecuteMethodNative) {    retval = Plex86NoExecute_Method; /* Fail. */    goto handleFail;    }  /* 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;  /* =================================================================   * Before executing the guest in the VM, we must check that   * the guest conditions meet the requirements of the user-level-only   * VM.   * =================================================================   */  /* CR0:   *   PG(31)==1   *   CD(30)==? (look into this later)   *   NW(29)==? (look into this later)   *   AM(18)==pass-thru from guest   *   WP(16)==Don't care.  Monitor always sets this to 1.   *   NE( 5)==? (look into this later)   *   ET( 4)==? (look into this later)   *   TS( 3)==? (look into this later)   *   EM( 2)==? (look into this later)   *   MP( 1)==? (look into this later)   *   PE( 0)==1   */  /* 0x8005003b */  if ( (guest_cpu->cr0.raw & 0xe0000037) != 0x80000033 ) {    hostOSPrint("plex86: guest CR0=0x%x\n", guest_cpu->cr0.raw);    retval = Plex86NoExecute_CR0; /* Fail. */    goto handleFail;    }  /* CR4:   *   OSXMMEXCPT(10)==? (look into this later)   *   OSFXSR(9)==? (look into this later)   *   PCE(8)==? (look into this later)   *   PGE(7)==? (look into this later)   *   MCE(6)==? (look into this later)   *   PAE(5)==? (look into this later)   *   PSE(4)==? (look into this later)   *   DE(3)==? (look into this later)   *   TSD(2)==? (look into this later)   *   PVI(1)==? (look into this later)   *   VME(0)==? (look into this later)   */  if ( (guest_cpu->cr4.raw & 0x000007ff) != 0x00000000 ) {    hostOSPrint("plex86: guest CR4=0x%x\n", guest_cpu->cr4.raw);    retval = Plex86NoExecute_CR4; /* Fail. */    goto handleFail;    }  /* Guest CPL must be 3 (user-level).   * CS selector must not be NULL.   */  if ( (guest_cpu->sreg[SRegCS].sel.fields.rpl != 3) ||       (guest_cpu->sreg[SRegCS].sel.fields.index == 0) ||       (guest_cpu->sreg[SRegCS].des.dpl != 3) ) {    retval = Plex86NoExecute_CS; /* Fail. */    goto handleFail;    }  /* A20 line must be enabled. */  if ( guest_cpu->a20Enable != 1 ) {    retval = Plex86NoExecute_A20; /* Fail. */    goto handleFail;    }  /* Some code not really used now, since we only support A20 being enabled. */  {  unsigned newA20Enable;  newA20Enable = guest_cpu->a20Enable > 0; /* Make 0 or 1. */  if ( newA20Enable != vm->system.a20Enable ) {    if ( (!newA20Enable) && guest_cpu->cr0.fields.pg ) {      /* A20 disabled, paging on not supported.  Well, really I have to       * see if it matters.  This check was in old plex86 code.       */      retval = Plex86NoExecute_A20; /* Fail. */      goto handleFail;      }    vm->system.a20Enable = newA20Enable;    vm->system.a20AddrMask  = 0xffefffff | (newA20Enable << 20);    vm->system.a20IndexMask = 0x000ffeff | (newA20Enable << 8);    }  }  /* LDT not supported.   * Monitor uses GDT slots 1,2,3, so guest segments can not.   * Segment descriptor cache DPL should equal 3.   */  for (s=0; s<6; s++) {    unsigned selector = guest_cpu->sreg[s].sel.raw;    unsigned index;    /* Only care if selector is not NULL. */    if ( selector & 0xfffc ) {      if ( (selector & 0x0007) != 3 ) {        /* Either TI=1 (LDT usage) or RPL!=3. */        retval = Plex86NoExecute_Selector; /* Fail. */        goto handleFail;        }      index = selector >> 3;      if ( index <= 3 ) {        /* Selector index field uses one of the monitor GDT slots. */        retval = Plex86NoExecute_Selector; /* Fail. */        goto handleFail;        }      if ( index >= (MON_GDT_SIZE/8) ) {        /* Selector index field uses a slot beyond the monitor GDT size. */        retval = Plex86NoExecute_Selector; /* Fail. */        goto handleFail;        }

⌨️ 快捷键说明

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