The current vmrunkernel sets up a lot of 2M pages with the
Page Size Enable bit enabled, meaning 2M pages.
It is best if we can start the kernel with the minimum amount
of page tables set up. That way, if some very bad addressing happens
in early assembly, we'll see it right away as a triple fault.

What I'm seeing with Linux is that this can be 2M -- i.e.,
we only need four page table pages even using only 4k pages.

Further, while assuming PSE is pretty reasonable, if we don't
have to make that assumption we should not. It's safer if the guest
is conservative and wants to assume 4K page table entries.
They might clear the bit that enables PSE and at that point
they will exit.  So, make the initial mapping use only 4K PTEs.

Change-Id: I1c9f458f6147e81cd7bf0c51745167a6ff17db79
Signed-off-by: Ronald G. Minnich <[email protected]>
---
 tests/vmm/vmrunkernel.c | 35 +++++++++++++++++++----------------
 1 file changed, 19 insertions(+), 16 deletions(-)

diff --git a/tests/vmm/vmrunkernel.c b/tests/vmm/vmrunkernel.c
index 6dd66a4..33a0504 100644
--- a/tests/vmm/vmrunkernel.c
+++ b/tests/vmm/vmrunkernel.c
@@ -161,7 +161,7 @@ unsigned int maxresume = (unsigned int) -1;
 #define KERNSIZE (128*MiB+GKERNBASE)
 uint8_t _kernel[KERNSIZE];
 
-unsigned long long *p512, *p1, *p2m;
+unsigned long long *p512, *p1, *p2m, *p4k;
 
 void **my_retvals;
 int nr_threads = 4;
@@ -618,32 +618,35 @@ int main(int argc, char **argv)
        assert(!ret);
 
 
-       ret = posix_memalign((void **)&p512, 4096, 3*4096);
+       /* Allocate 4 pages for page table pages. */
+       ret = posix_memalign((void **)&p512, PGSIZE, 4*PGSIZE);
        fprintf(stderr, "memalign is %p\n", p512);
        if (ret) {
                perror("ptp alloc");
                exit(1);
        }
+
+       /* Paging setup. This is really easy to mess up.
+        * So, reminder: the indexes into the tables need to be
+        * derived from a virtual address, which at this point is
+        * named 'entry'. The values stored in the tables need to
+        * be physical addresses. We get a certain benefit from the
+        * fact that we are setting up a 1:1 map; that also makes it
+        * easy to make mistakes and have it work in spite of them. */
        p1 = &p512[512];
        p2m = &p512[1024];
-       uint64_t kernbase = 0; //0xffffffff80000000;
-       uint64_t highkernbase = 0xffffffff80000000;
-       p512[PML4(kernbase)] = (unsigned long long)p1 | 7;
-       p1[PML3(kernbase)] = /*0x87; */(unsigned long long)p2m | 7;
-       p512[PML4(highkernbase)] = (unsigned long long)p1 | 7;
-       p1[PML3(highkernbase)] = /*0x87; */(unsigned long long)p2m | 7;
-#define _2MiB (0x200000)
-
-       for (i = 0; i < 512; i++) {
-               p2m[PML2(kernbase + i * _2MiB)] = 0x87 | i * _2MiB;
-       }
+       p4k = &p512[1024 + 512];
+
+       p512[PML4(entry)] = (unsigned long long)p1 | 7;
+       p1[PML3(entry)] = (unsigned long long)p2m | 7;
+       p2m[PML2(entry)] = (unsigned long long)p4k | 7;
+
+       for(i = 0; i < 512; i++)
+               p4k[i] = 7 | (entry + i * PGSIZE);
 
-       kernbase >>= (0+12);
-       kernbase <<= (0 + 12);
        uint8_t *kernel = (void *)GKERNBASE;
        //write_coreboot_table(coreboot_tables, ((void *)VIRTIOBASE) 
/*kernel*/, KERNSIZE + 1048576);
        hexdump(stdout, coreboot_tables, 512);
-       fprintf(stderr, "kernbase for pml4 is 0x%llx and entry is %llx\n", 
kernbase, entry);
        fprintf(stderr, "p512 %p p512[0] is 0x%lx p1 %p p1[0] is 0x%x\n", p512, 
p512[0], p1, p1[0]);
 
        vmm_run_task(vm, timer_thread, 0);
-- 
2.8.0.rc3.226.g39d4020

-- 
You received this message because you are subscribed to the Google Groups 
"Akaros" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to