Signed-off-by: Asias He <asias.hejun@xxxxxxxxx> --- kvm/test/x86/vm.c | 46 +++++++++++++++++++++++++++++++++++----------- 1 files changed, 35 insertions(+), 11 deletions(-) diff --git a/kvm/test/x86/vm.c b/kvm/test/x86/vm.c index ec9c145..c9876e5 100644 --- a/kvm/test/x86/vm.c +++ b/kvm/test/x86/vm.c @@ -1,11 +1,16 @@ - #include "vm.h" - -void print(const char *s); +#include "libcflat.h" #define PAGE_SIZE 4096ul +#ifdef __x86_64__ #define LARGE_PAGE_SIZE (512 * PAGE_SIZE) +#else +#define LARGE_PAGE_SIZE (1024 * PAGE_SIZE) +#endif +#define X86_CR0_PE 0x00000001 +#define X86_CR0_PG 0x80000000 +#define X86_CR4_PSE 0x00000010 static void *free = 0; static void *vfree_top = 0; @@ -66,6 +71,16 @@ static unsigned long end_of_memory; #define PTE_WRITE (1ull << 1) #define PTE_ADDR (0xffffffffff000ull) +#ifdef __x86_64__ +#define PAGE_LEVEL 4 +#define PGDIR_WIDTH 9 +#define PGDIR_MASK 511 +#else +#define PAGE_LEVEL 2 +#define PGDIR_WIDTH 10 +#define PGDIR_MASK 1023 +#endif + static void install_pte(unsigned long *cr3, int pte_level, void *virt, @@ -75,8 +90,8 @@ static void install_pte(unsigned long *cr3, unsigned long *pt = cr3; unsigned offset; - for (level = 4; level > pte_level; --level) { - offset = ((unsigned long)virt >> ((level-1) * 9 + 12)) & 511; + for (level = PAGE_LEVEL; level > pte_level; --level) { + offset = ((unsigned long)virt >> ((level-1) * PGDIR_WIDTH + 12)) & PGDIR_MASK; if (!(pt[offset] & PTE_PRESENT)) { unsigned long *new_pt = alloc_page(); memset(new_pt, 0, PAGE_SIZE); @@ -84,7 +99,7 @@ static void install_pte(unsigned long *cr3, } pt = phys_to_virt(pt[offset] & 0xffffffffff000ull); } - offset = ((unsigned long)virt >> (((level-1) * 9) + 12)) & 511; + offset = ((unsigned long)virt >> ((level-1) * PGDIR_WIDTH + 12)) & PGDIR_MASK; pt[offset] = pte; } @@ -94,8 +109,8 @@ static unsigned long get_pte(unsigned long *cr3, void *virt) unsigned long *pt = cr3, pte; unsigned offset; - for (level = 4; level > 1; --level) { - offset = ((unsigned long)virt >> (((level-1) * 9) + 12)) & 511; + for (level = PAGE_LEVEL; level > 1; --level) { + offset = ((unsigned long)virt >> (((level-1) * PGDIR_WIDTH) + 12)) & PGDIR_MASK; pte = pt[offset]; if (!(pte & PTE_PRESENT)) return 0; @@ -103,7 +118,7 @@ static unsigned long get_pte(unsigned long *cr3, void *virt) return pte; pt = phys_to_virt(pte & 0xffffffffff000ull); } - offset = ((unsigned long)virt >> (((level-1) * 9) + 12)) & 511; + offset = ((unsigned long)virt >> (((level-1) * PGDIR_WIDTH) + 12)) & PGDIR_MASK; pte = pt[offset]; return pte; } @@ -189,8 +204,10 @@ static void setup_mmu(unsigned long len) unsigned long *cr3 = alloc_page(); unsigned long phys = 0; +#if 0 if (len < (1ul << 32)) len = 1ul << 32; /* map mmio 1:1 */ +#endif memset(cr3, 0, PAGE_SIZE); while (phys + LARGE_PAGE_SIZE <= len) { @@ -201,9 +218,16 @@ static void setup_mmu(unsigned long len) install_page(cr3, phys, (void *)phys); phys += PAGE_SIZE; } - load_cr3(virt_to_phys(cr3)); - print("paging enabled\n"); +#ifndef __x86_64__ + load_cr4(X86_CR4_PSE); +#endif + load_cr0(X86_CR0_PG |X86_CR0_PE); + + printf("paging enabled\n"); + printf("cr0 = %x\n", read_cr0()); + printf("cr3 = %x\n", read_cr3()); + printf("cr4 = %x\n", read_cr4()); } static unsigned int inl(unsigned short port) -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html