summaryrefslogtreecommitdiffstats
path: root/lib/libkvm
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2007-05-19 13:11:27 +0000
committermarcel <marcel@FreeBSD.org>2007-05-19 13:11:27 +0000
commit797bdcc549d01b2416969e9d1df898f99bde3929 (patch)
tree218bb359e1871db89deebbfb8bd87054852acd37 /lib/libkvm
parent20660c08c200573ac97f77ad95ba440270a3829e (diff)
downloadFreeBSD-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.c24
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))
OpenPOWER on IntegriCloud