From 797bdcc549d01b2416969e9d1df898f99bde3929 Mon Sep 17 00:00:00 2001 From: marcel Date: Sat, 19 May 2007 13:11:27 +0000 Subject: 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. --- lib/libkvm/kvm_ia64.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'lib/libkvm') 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)) -- cgit v1.1