diff options
author | marcel <marcel@FreeBSD.org> | 2007-05-19 13:11:27 +0000 |
---|---|---|
committer | marcel <marcel@FreeBSD.org> | 2007-05-19 13:11:27 +0000 |
commit | 797bdcc549d01b2416969e9d1df898f99bde3929 (patch) | |
tree | 218bb359e1871db89deebbfb8bd87054852acd37 /lib/libkvm | |
parent | 20660c08c200573ac97f77ad95ba440270a3829e (diff) | |
download | FreeBSD-src-797bdcc549d01b2416969e9d1df898f99bde3929.zip FreeBSD-src-797bdcc549d01b2416969e9d1df898f99bde3929.tar.gz |
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.
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 fbee551..eac5833 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)) |