aboutsummaryrefslogtreecommitdiff
path: root/lib/libkvm
diff options
context:
space:
mode:
authorMarcel Moolenaar <marcel@FreeBSD.org>2007-05-19 13:11:27 +0000
committerMarcel Moolenaar <marcel@FreeBSD.org>2007-05-19 13:11:27 +0000
commitaea0bb5c9b9774341d7f6f79fb6ceedeeed22474 (patch)
tree218bb359e1871db89deebbfb8bd87054852acd37 /lib/libkvm
parent345407a9a11167c820e09afb91a7a5c905984740 (diff)
downloadsrc-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.c24
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))