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

📄 paging-mon.c

📁 bochs : one pc simulator.
💻 C
📖 第 1 页 / 共 2 页
字号:
    /* See if present, before fetching PTE */    if (guestPDE.fields.P==0) {      *error = 0x00000000; /* RSVD=0, P=0 */      goto np_exception;      }#if 0    if (vm->guestCpuIDInfo.procSignature.fields.family < 6) {      /* Update A bit of PDE memory image if not already */      if ( guestPDE.fields.A == 0 ) {        guestPDE.fields.A = 1;        guestPDir[pdi] = guestPDE;        }      }#endif    /* Second, get the guest PDE */    ptbl_ppi = A20PageIndex(vm, guestPDE.fields.base);    if (ptbl_ppi >= vm->pages.guest_n_pages)      monpanic(vm, "mapGuestLinAddr: PG=1 guest PTE OOB\n");    guestPTbl = open_guest_phy_page(vm, ptbl_ppi,                                    vm->guest.addr.tmp_phy_page1);    guestPTE = guestPTbl[pti];    if (guestPTE.fields.P==0) {      *error = 0x00000000; /* RSVD=0, P=0 */      goto np_exception;      }#if 0/* +++ */    if (guestPDE.raw & PDEUnhandled)      monpanic(vm, "mapGuestLinAddr: guestPDE 0x%08x\n", guestPDE.raw);#endif    /* See if requested guest priv is weaker than guest PDE priv */    if (req_us > guestPDE.fields.US) {      *error = 0x00000001; /* RSVD=0, P=1 */      goto access_exception;      }    if ( (req_rw > guestPDE.fields.RW) &&         (vm->guest.addr.guest_cpu->cr0.fields.wp || req_us) ) {      *error = 0x00000001; /* RSVD=0, P=1 */      goto access_exception;      }#warning "ignoring PTEUnhandled bits"#if 0    if (guestPTE.raw & PTEUnhandled)      monpanic(vm, "mapGuestLinAddr: guestPTE 0x%08x\n", guestPTE.raw);#endif    if (req_us > guestPTE.fields.US) {      *error = 0x00000001; /* RSVD=0, P=1 */      goto access_exception;      }    if ( (req_rw > guestPTE.fields.RW) &&         (vm->guest.addr.guest_cpu->cr0.fields.wp || req_us) ) {      *error = 0x00000001; /* RSVD=0, P=1 */      goto access_exception;      }#if 0    if (vm->guestCpuIDInfo.procSignature.fields.family >= 6) {      /* Update A bit of PDE memory image if not already */      if ( guestPDE.fields.A == 0 ) {        guestPDE.fields.A = 1;        guestPDir[pdi] = guestPDE;        }      }    /* Update A bit in PTE memory image if not already */    if ( (guestPTE.fields.A == 0) ||         ((req_rw==1) && !guestPTE.fields.D) ) {      guestPTE.fields.A = 1;      if (req_rw==1)        guestPTE.fields.D = 1;      guestPTbl[pti] = guestPTE;      }#endif        *guest_ppi = A20PageIndex(vm, guestPTE.fields.base);    }  else {    /* guest paging is off, linear address is physical address */    guest_pdir_page_index = 0; /* keep compiler quiet */    *guest_ppi = A20PageIndex(vm, guest_lpage_index);    }  if (*guest_ppi >= vm->pages.guest_n_pages)    return(MapLinPPageOOB);/* +++ mapping in guest pages, check static phy_attr bits first before *//* +++ allowing non-protected. */mapIntoMonitor:  /* At this point, we know that the guest's paging system   * (if enabled) would allow for this access.  Now we have to   * see about mapping it into the monitor linear address space.   */  pusage = getPageUsage(vm, *guest_ppi);  if (wasRemap > 1)    monpanic(vm, "wasRemap>1\n");  /*   * Check monitor PDE   */  if (monPDE->fields.P == 0) {    /* OK, Lazy PT map/allocate */    if (vm->guest.addr.guest_cpu->cr0.fields.pg) {      phyPageInfo_t *pde_pusage;      pde_pusage =          getPageUsage(vm, A20PageIndex(vm, guestPDE.fields.base));      if (pde_pusage->attr.raw & PageBadUsage4PTbl) {#warning "PDE->PDir hack"/*monprint(vm, "PDE.base=0x%x CR3=0x%x\n", *  A20PageIndex(vm, guestPDE.fields.base), *  A20Addr(vm, vm->guest_cpu.cr3)); */return(MapLinEmulate);        }      if (pde_pusage->attr.raw & PageUsagePTbl) {        /* It is possible that multiple PDE entries will point to */        /* the same Page Table.  In this case, we need to search to */        /* find which one the monitor already mapped in, and get */        /* a pointer to the Page Table allocated by the monitor. */        Bit32u guest_ptbl_index;        unsigned i;        guestPDir = open_guest_phy_page(vm, guest_pdir_page_index,                                    vm->guest.addr.tmp_phy_page0);        guest_ptbl_index = A20PageIndex(vm, guestPDir[pdi].fields.base);        monPTbl = (void *) 0;        pt_index = 0; /* keep compiler quiet */        for (i=0; i<1024; i++) {          if (i==pdi) continue; /* skip current PDI */          guestPDE = guestPDir[i];          if ( guestPDE.fields.P &&               (A20PageIndex(vm, guestPDE.fields.base)==guest_ptbl_index) ) {            /* OK, guest has a PDE which matches.  If it is mapped into */            /* the monitor already, then we are done searching. */            if (vm->guest.addr.page_dir[i].fields.P) {              pt_index = getMonPTi(vm, i, 11);              vm->guest.addr.page_tbl_laddr_map[pdi] = pt_index;              monPTbl = &vm->guest.addr.page_tbl[pt_index];              break;              }            }          }        close_guest_phy_page(vm, guest_pdir_page_index);        if (i>=1024)          monpanic(vm, "mapGuestLinAddr: PDE maps to existing PTbl.\n");        }      else {        /* Allocate PT using paged scheme. */        pt_index = allocatePT(vm, pdi);        monPTbl = &vm->guest.addr.page_tbl[pt_index];        mon_memzero(monPTbl, sizeof(*monPTbl));        }      if (vm->guest.addr.guest_cpu->sreg[SRegCS].des.dpl==3) {        /* For user code, we can use the guest US & RW values as-is, */        /* since they are honored as such with either CR0.WP value. */        us = guestPDE.fields.US;        rw = guestPDE.fields.RW;        }      else { /* guest supervisor code */        /* For supervisor code, access rules are different dependent on */        /* the value of CR0.WP. */        if (vm->guest.addr.guest_cpu->cr0.fields.wp==0) {          /* If CR0.WP=0, then supervisor code can write to any page, */          /* and permissions are effectively ignored. */          us = 1;          rw = 1;          }        else { /* CR0.WP==1 */          /* If CR0.WP=0, then supervisor code can read from any page, */          /* but write permission depends on the RW bit. */          us = 1;          rw = guestPDE.fields.RW;          }        }      /* Base/Avail=0/G=0/PS=0/D=d/A=a/PCD=0/PWT=0/US=us/RW=rw/P=1 */      monPDE->raw =          (vm->pages.page_tbl[pt_index] << 12) | (guestPDE.raw & 0x60) |          (us<<2) | (rw<<1) | 1;      if ( addPageAttributes(vm, A20PageIndex(vm, guestPDE.fields.base),                             PageUsagePTbl) ) {        wasRemap++;        goto mapIntoMonitor;        }      }    else {      /* Allocate PT using non-paged scheme. */      pt_index = allocatePT(vm, pdi);      monPTbl = &vm->guest.addr.page_tbl[pt_index];      mon_memzero(monPTbl, 4096);      /* Base/Avail=0/G=0/PS=0/D=0/A=0/PCD=0/PWT=0/US=1/RW=1/P=1 */      monPDE->raw =          (vm->pages.page_tbl[pt_index] << 12) | 0x7;      }    }  else {    /* monPDE->P == 1 */    /* Make sure this laddr does not conflict with monitor space */    /* This can only happen when monPDE.P==1, since the monitor */    /* is always mapped in. */    if ( (guest_laddr & 0xffc00000) == vm->mon_pde_mask )      return(MapLinMonConflict);    pt_index = getMonPTi(vm, pdi, 12);    monPTbl = &vm->guest.addr.page_tbl[pt_index];    }  monPTE = &monPTbl->pte[pti];  /*   * Check monitor PTE   */  if (monPTE->fields.P == 0) {    if (vm->guest.addr.guest_cpu->cr0.fields.pg) {      if (vm->guest.addr.guest_cpu->sreg[SRegCS].des.dpl==3) {        /* For user code, we can use the guest US & RW values as-is, */        /* since they are honored as such with either CR0.WP value. */        us = guestPTE.fields.US;        rw = guestPTE.fields.RW;        }      else { /* guest supervisor code */        /* For supervisor code, access rules are different dependent on */        /* the value of CR0.WP. */        if (vm->guest.addr.guest_cpu->cr0.fields.wp==0) {          /* If CR0.WP=0, then supervisor code can write to any page, */          /* and permissions are effectively ignored. */          us = 1;           rw = 1;          }        else { /* CR0.WP==1 */          /* If CR0.WP=0, then supervisor code can read from any page, */          /* but write permission depends on the RW bit. */          us = 1;          rw = guestPTE.fields.RW;          }        }      if (pusage->attr.fields.access_perm==PagePermRO) {        rw = 0;        if (req_rw)          return(MapLinEmulate);        }      else if (pusage->attr.fields.access_perm==PagePermNA)        return(MapLinEmulate);      /* Base/Avail=0/G=0/PS=0/D=d/A=a/PCD=0/PWT=0/US=1/RW=rw/P=1 */      monPTE->raw =          (getHostOSPinnedPage(vm, *guest_ppi) << 12) | (guestPTE.raw & 0x60) |          0x5 | (rw<<1);      }    else { /* CR0.PG==0 */      rw = 1; /* Paging off is effectively RW */      if (pusage->attr.fields.access_perm==PagePermRO) {        rw = 0;        if (req_rw)          return(MapLinEmulate);        }      else if (pusage->attr.fields.access_perm==PagePermNA)        return(MapLinEmulate);      /* Base/Avail=0/G=0/PS=0/D=0/A=0/PCD=0/PWT=0/US=1/RW=rw/P=1 */      monPTE->raw =          (getHostOSPinnedPage(vm, *guest_ppi) << 12) | 0x5 | (rw<<1);      }    /* Mark physical page as having an unvirtualized linear address     * mapped to it.     */    if (pusage->attr.fields.lmap_count == 0) {      pusage->attr.fields.lmap_count = 1;      pusage->attr.fields.laddr_backlink = guest_lpage_index;      }    else if (pusage->attr.fields.lmap_count == 1) {      pusage->attr.fields.lmap_count = 2; /* max out count */      /* Count maxed out, we only store laddr_backlink of 1st mapping. */      }    else {      /* Count maxed out, we don't store any more info. */      }    invlpg_mon_offset( Guest2Monitor(vm, guest_laddr) );    return(MapLinOK);    }  else {    /* PTE.P == 1 */    return(MapLinAlreadyMapped);    }np_exception:access_exception:  *error |= (req_us<<2) | (req_rw<<1);  return(MapLinException);}  voidguestPageFault(vm_t *vm, guest_context_t *context, Bit32u cr2){  Bit32u   guest_ppi, error, gerror;  unsigned us, rw;  /* Make sure this laddr does not conflict with monitor space */  if ( (cr2 & 0xffc00000) == vm->mon_pde_mask )    monpanic(vm, "PageFault: guest access to monitor space\n");  error = context->error;  if (error & 0x8) /* If RSVD bits used in PDir */    monpanic(vm, "guestPageFault: RSVD\n");  us = vm->guest.addr.guest_cpu->sreg[SRegCS].des.dpl == 3;  rw = (error >> 1) & 1;/* +++ should base attr (currently 0) on whether this is *//* code or data???  only if siv==1 */  switch (mapGuestLinAddr(vm, cr2, &guest_ppi, us, rw, 0, &gerror)) {    case MapLinOK:      return;    case MapLinMonConflict:      monpanic(vm, "guestPageFault: MapLinMonConflict:\n");    case MapLinAlreadyMapped:      monpanic(vm, "guestPageFault: MapLinAlreadyMapped:\n");      /*emulate_instr(vm, context, 2);*/      return;    case MapLinPPageOOB:      monpanic(vm, "guestPageFault: MapLinPPageOOB (0x%x):\n", cr2);    case MapLinEmulate:      monpanic(vm, "guestPageFault: MapLinEmulate:\n");      /*emulate_instr(vm, context, 3);*/      return;    case MapLinException:      /*monpanic(vm, "guestPageFault: emulate_exception was here.\n");*/      /*emulate_exception(vm, ExceptionPF, gerror);*/      toHostGuestFault(vm, ExceptionPF);      return;    default:      monpanic(vm, "guestPageFault: MapLin: default case:\n");    }}#if 0  voidsanity_check_pdir(vm_t *vm, unsigned id, Bit32u guest_laddr){  pageEntry_t *monPDE;  Bit32u       pdi;  unsigned     pt_index;   for (pdi=0; pdi<1024; pdi++) {    monPDE = &vm->guest.addr.page_dir[pdi];    if ( (pdi!=vm->mon_pdi) &&        monPDE->fields.P ) {      pt_index = vm->guest.addr.page_tbl_laddr_map[pdi];      if (pt_index == -1)        monpanic(vm, "sanity_check_pdir: pt_index==-1\n");      if (pt_index >= vm->pages.guest_n_pages)        monpanic(vm, "sanity_check_pdir: pt_index OOB\n");      if ( monPDE->fields.base != vm->pages.page_tbl[pt_index] ) {        monprint(vm, "gaddr=0x%x\n", guest_laddr);        monprint(vm, "pt_index=%u\n", pt_index);        monprint(vm, "map[0x302]=%u\n",          vm->guest.addr.page_tbl_laddr_map[0x302]);        monpanic(vm, "sanity_check_pdir: id=%u "          "pdi=0x%x\n", id, pdi);        }      }    }}#endif

⌨️ 快捷键说明

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