Date: Wed, 19 May 2004 11:12:39 -0700 (PDT) From: Peter Wemm <peter@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 53065 for review Message-ID: <200405191812.i4JICdiv026430@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=53065 Change 53065 by peter@peter_hammer on 2004/05/19 11:12:00 checkpoint Affected files ... .. //depot/projects/hammer/lib/libkvm/kvm_amd64.c#4 edit Differences ... ==== //depot/projects/hammer/lib/libkvm/kvm_amd64.c#4 (text+ko) ==== @@ -71,15 +71,15 @@ #endif struct vmstate { - pd_entry_t *PTD; + pml4_entry_t *PML4; }; void _kvm_freevtop(kvm_t *kd) { if (kd->vmst != 0) { - if (kd->vmst->PTD) { - free(kd->vmst->PTD); + if (kd->vmst->PML4) { + free(kd->vmst->PML4); } free(kd->vmst); } @@ -92,7 +92,7 @@ struct nlist nlist[2]; u_long pa; u_long kernbase; - pd_entry_t *PTD; + pml4_entry_t *PML4; vm = (struct vmstate *)_kvm_malloc(kd, sizeof(*vm)); if (vm == 0) { @@ -100,34 +100,35 @@ return (-1); } kd->vmst = vm; - vm->PTD = 0; + vm->PML4 = 0; nlist[0].n_name = "kernbase"; nlist[1].n_name = 0; - if (kvm_nlist(kd, nlist) != 0) - kernbase = KERNBASE; /* for old kernels */ - else - kernbase = nlist[0].n_value; + if (kvm_nlist(kd, nlist) != 0) { + _kvm_err(kd, kd->program, "bad namelist - no kernbase"); + return (-1); + } + kernbase = nlist[0].n_value; - nlist[0].n_name = "IdlePTD"; + nlist[0].n_name = "KPML4phys"; nlist[1].n_name = 0; if (kvm_nlist(kd, nlist) != 0) { - _kvm_err(kd, kd->program, "bad namelist"); + _kvm_err(kd, kd->program, "bad namelist - no KPML4phys"); return (-1); } if (kvm_read(kd, (nlist[0].n_value - kernbase), &pa, sizeof(pa)) != sizeof(pa)) { - _kvm_err(kd, kd->program, "cannot read IdlePTD"); + _kvm_err(kd, kd->program, "cannot read KPML4phys"); return (-1); } - PTD = _kvm_malloc(kd, PAGE_SIZE); - if (kvm_read(kd, pa, PTD, PAGE_SIZE) != PAGE_SIZE) { - _kvm_err(kd, kd->program, "cannot read PTD"); + PML4 = _kvm_malloc(kd, PAGE_SIZE); + if (kvm_read(kd, pa, PML4, PAGE_SIZE) != PAGE_SIZE) { + _kvm_err(kd, kd->program, "cannot read KPML4phys"); return (-1); } - vm->PTD = PTD; + vm->PML4 = PML4; return (0); } @@ -136,15 +137,21 @@ { struct vmstate *vm; u_long offset; + u_long pdpe_pa; + u_long pde_pa; u_long pte_pa; + pml4_entry_t pml4e; + pdp_entry_t pdpe; pd_entry_t pde; pt_entry_t pte; + u_long pml4eindex; + u_long pdpeindex; u_long pdeindex; u_long pteindex; int i; if (ISALIVE(kd)) { - _kvm_err(kd, 0, "vatop called in live kernel!"); + _kvm_err(kd, 0, "kvm_vatop called in live kernel!"); return((off_t)0); } @@ -155,27 +162,55 @@ * If we are initializing (kernel page table descriptor pointer * not yet set) then return pa == va to avoid infinite recursion. */ - if (vm->PTD == 0) { + if (vm->PML4 == 0) { *pa = va; return (PAGE_SIZE - offset); } - pdeindex = va >> PDRSHIFT; - pde = vm->PTD[pdeindex]; + pml4eindex = va >> PML4SHIFT; + pml4e = vm->PML4[pml4eindex]; + if (((u_long)pml4e & PG_V) == 0) + goto invalid; + + pdpeindex = (va >> PDPSHIFT) & (NPDPEPG-1); + pdpe_pa = ((u_long)pml4e & PG_FRAME) + (pdpeindex * sizeof(pdp_entry_t)); + + /* XXX This has to be a physical address read, kvm_read is virtual */ + if (lseek(kd->pmfd, pdpe_pa, 0) == -1) { + _kvm_syserr(kd, kd->program, "_kvm_vatop: lseek pdpe_pa"); + goto invalid; + } + if (read(kd->pmfd, &pdpe, sizeof pdpe) != sizeof pdpe) { + _kvm_syserr(kd, kd->program, "_kvm_vatop: read pdpe"); + goto invalid; + } + if (((u_long)pdpe & PG_V) == 0) + goto invalid; + + + pdeindex = (va >> PDRSHIFT) & (NPDEPG-1); + pde_pa = ((u_long)pdpe & PG_FRAME) + (pdeindex * sizeof(pd_entry_t)); + + /* XXX This has to be a physical address read, kvm_read is virtual */ + if (lseek(kd->pmfd, pde_pa, 0) == -1) { + _kvm_syserr(kd, kd->program, "_kvm_vatop: lseek pde_pa"); + goto invalid; + } + if (read(kd->pmfd, &pde, sizeof pde) != sizeof pde) { + _kvm_syserr(kd, kd->program, "_kvm_vatop: read pde"); + goto invalid; + } if (((u_long)pde & PG_V) == 0) goto invalid; if ((u_long)pde & PG_PS) { /* - * No second-level page table; ptd describes one 4MB page. - * (We assume that the kernel wouldn't set PG_PS without enabling - * it cr0, and that the kernel doesn't support 36-bit physical - * addresses). + * No final-level page table; ptd describes one 2MB page. */ -#define PAGE4M_MASK (NBPDR - 1) -#define PG_FRAME4M (~PAGE4M_MASK) - *pa = ((u_long)pde & PG_FRAME4M) + (va & PAGE4M_MASK); - return (NBPDR - (va & PAGE4M_MASK)); +#define PAGE2M_MASK (NBPDR - 1) +#define PG_FRAME2M (~PAGE2M_MASK) + *pa = ((u_long)pde & PG_FRAME2M) + (va & PAGE2M_MASK); + return (NBPDR - (va & PAGE2M_MASK)); } pteindex = (va >> PAGE_SHIFT) & (NPTEPG-1);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200405191812.i4JICdiv026430>