diff options
author | Marcel Moolenaar <marcel@FreeBSD.org> | 2007-05-19 13:11:27 +0000 |
---|---|---|
committer | Marcel Moolenaar <marcel@FreeBSD.org> | 2007-05-19 13:11:27 +0000 |
commit | aea0bb5c9b9774341d7f6f79fb6ceedeeed22474 (patch) | |
tree | 218bb359e1871db89deebbfb8bd87054852acd37 /lib/libkvm | |
parent | 345407a9a11167c820e09afb91a7a5c905984740 (diff) | |
download | src-aea0bb5c9b9774341d7f6f79fb6ceedeeed22474.tar.gz src-aea0bb5c9b9774341d7f6f79fb6ceedeeed22474.zip |
Add a level of indirection to the kernel PTE table. The old
scheme allowed for 1024 PTE pages, each containing 256 PTEs.
This yielded 2GB of KVA. This is not enough to boot a kernel
on a 16GB box and in general too low for a 64-bit machine.
By adding a level of indirection we now have 1024 2nd-level
directory pages, each capable of supporting 2GB of KVA. This
brings the grand total to 2TB of KVA.
Notes
Notes:
svn path=/head/; revision=169760
Diffstat (limited to 'lib/libkvm')
-rw-r--r-- | lib/libkvm/kvm_ia64.c | 24 |
1 files changed, 16 insertions, 8 deletions
diff --git a/lib/libkvm/kvm_ia64.c b/lib/libkvm/kvm_ia64.c index fbee55180d3d..eac58335ff45 100644 --- a/lib/libkvm/kvm_ia64.c +++ b/lib/libkvm/kvm_ia64.c @@ -45,8 +45,10 @@ #define REGION_ADDR(x) ((x) & ((1LL<<61)-1LL)) #define NKPTEPG(ps) ((ps) / sizeof(struct ia64_lpte)) +#define NKPTEDIR(ps) ((ps) >> 3) #define KPTE_PTE_INDEX(va,ps) (((va)/(ps)) % NKPTEPG(ps)) -#define KPTE_DIR_INDEX(va,ps) (((va)/(ps)) / NKPTEPG(ps)) +#define KPTE_DIR0_INDEX(va,ps) ((((va)/(ps)) / NKPTEPG(ps)) / NKPTEDIR(ps)) +#define KPTE_DIR1_INDEX(va,ps) ((((va)/(ps)) / NKPTEPG(ps)) % NKPTEDIR(ps)) struct vmstate { void *mmapbase; @@ -174,8 +176,8 @@ int _kvm_kvatop(kvm_t *kd, u_long va, off_t *pa) { struct ia64_lpte pte; - uint64_t pgaddr, ptaddr; - size_t pgno, pgsz, ptno; + uint64_t pgaddr, pt0addr, pt1addr; + size_t pgno, pgsz, pt0no, pt1no; if (va >= REGION_BASE(6)) { /* Regions 6 and 7: direct mapped. */ @@ -184,16 +186,22 @@ _kvm_kvatop(kvm_t *kd, u_long va, off_t *pa) /* Region 5: virtual. */ va = REGION_ADDR(va); pgsz = kd->vmst->pagesize; - ptno = KPTE_DIR_INDEX(va, pgsz); + pt0no = KPTE_DIR0_INDEX(va, pgsz); + pt1no = KPTE_DIR1_INDEX(va, pgsz); pgno = KPTE_PTE_INDEX(va, pgsz); - if (ptno >= (pgsz >> 3)) + if (pt0no >= NKPTEDIR(pgsz)) goto fail; - ptaddr = kd->vmst->kptdir + (ptno << 3); - if (kvm_read(kd, ptaddr, &pgaddr, 8) != 8) + pt0addr = kd->vmst->kptdir + (pt0no << 3); + if (kvm_read(kd, pt0addr, &pt1addr, 8) != 8) + goto fail; + if (pt1addr == 0) + goto fail; + pt1addr += pt1no << 3; + if (kvm_read(kd, pt1addr, &pgaddr, 8) != 8) goto fail; if (pgaddr == 0) goto fail; - pgaddr += (pgno * sizeof(pte)); + pgaddr += pgno * sizeof(pte); if (kvm_read(kd, pgaddr, &pte, sizeof(pte)) != sizeof(pte)) goto fail; if (!(pte.pte & PTE_PRESENT)) |