lguest: populate initial_page_table

Two x86 patches broke lguest:
1) v2.6.35-492-g72d7c3b, which changed x86 to use the memblock allocator.

In lguest, the host places linear page tables at the top of mem, which
used to be enough to get us up to the swapper_pg_dir page tables. With
the first patch, the direct mapping tables used that memory:

Before: kernel direct mapping tables up to 4000000 @ 7000-1a000
After: kernel direct mapping tables up to 4000000 @ 3fed000-4000000

I initially fixed this by lying about the amount of memory we had, so
the kernel wouldn't blatt the lguest boot pagetables (yuk!), but then...

2) v2.6.36-rc8-54-gb40827f, which made x86 boot use initial_page_table.

This was initialized in a part of head_32.S which isn't executed by
lguest; it is then copied into swapper_pg_dir. So we have to initialize
it; and anyway we switch to it before we blatt the old tables, so that
fixes the previous damage as well.

For the moment, I cut & pasted the code into lguest's boot code, but
next merge window I will merge them.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Cc: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
To: x86@kernel.org

+107 -5
+2 -2
arch/x86/kernel/head_32.S
··· 620 620 __PAGE_ALIGNED_BSS 621 621 .align PAGE_SIZE_asm 622 622 #ifdef CONFIG_X86_PAE 623 - initial_pg_pmd: 623 + ENTRY(initial_pg_pmd) 624 624 .fill 1024*KPMDS,4,0 625 625 #else 626 626 ENTRY(initial_page_table) 627 627 .fill 1024,4,0 628 628 #endif 629 - initial_pg_fixmap: 629 + ENTRY(initial_pg_fixmap) 630 630 .fill 1024,4,0 631 631 ENTRY(empty_zero_page) 632 632 .fill 4096,1,0
-3
arch/x86/lguest/boot.c
··· 1352 1352 */ 1353 1353 switch_to_new_gdt(0); 1354 1354 1355 - /* We actually boot with all memory mapped, but let's say 128MB. */ 1356 - max_pfn_mapped = (128*1024*1024) >> PAGE_SHIFT; 1357 - 1358 1355 /* 1359 1356 * The Host<->Guest Switcher lives at the top of our address space, and 1360 1357 * the Host told us how big it is when we made LGUEST_INIT hypercall:
+105
arch/x86/lguest/i386_head.S
··· 4 4 #include <asm/asm-offsets.h> 5 5 #include <asm/thread_info.h> 6 6 #include <asm/processor-flags.h> 7 + #include <asm/pgtable.h> 7 8 8 9 /*G:020 9 10 * Our story starts with the kernel booting into startup_32 in ··· 38 37 /* Set up the initial stack so we can run C code. */ 39 38 movl $(init_thread_union+THREAD_SIZE),%esp 40 39 40 + call init_pagetables 41 + 41 42 /* Jumps are relative: we're running __PAGE_OFFSET too low. */ 42 43 jmp lguest_init+__PAGE_OFFSET 44 + 45 + /* 46 + * Initialize page tables. This creates a PDE and a set of page 47 + * tables, which are located immediately beyond __brk_base. The variable 48 + * _brk_end is set up to point to the first "safe" location. 49 + * Mappings are created both at virtual address 0 (identity mapping) 50 + * and PAGE_OFFSET for up to _end. 51 + * 52 + * FIXME: This code is taken verbatim from arch/x86/kernel/head_32.S: they 53 + * don't have a stack at this point, so we can't just use call and ret. 54 + */ 55 + init_pagetables: 56 + #if PTRS_PER_PMD > 1 57 + #define PAGE_TABLE_SIZE(pages) (((pages) / PTRS_PER_PMD) + PTRS_PER_PGD) 58 + #else 59 + #define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PGD) 60 + #endif 61 + #define pa(X) ((X) - __PAGE_OFFSET) 62 + 63 + /* Enough space to fit pagetables for the low memory linear map */ 64 + MAPPING_BEYOND_END = \ 65 + PAGE_TABLE_SIZE(((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT) << PAGE_SHIFT 66 + #ifdef CONFIG_X86_PAE 67 + 68 + /* 69 + * In PAE mode initial_page_table is statically defined to contain 70 + * enough entries to cover the VMSPLIT option (that is the top 1, 2 or 3 71 + * entries). The identity mapping is handled by pointing two PGD entries 72 + * to the first kernel PMD. 73 + * 74 + * Note the upper half of each PMD or PTE are always zero at this stage. 75 + */ 76 + 77 + #define KPMDS (((-__PAGE_OFFSET) >> 30) & 3) /* Number of kernel PMDs */ 78 + 79 + xorl %ebx,%ebx /* %ebx is kept at zero */ 80 + 81 + movl $pa(__brk_base), %edi 82 + movl $pa(initial_pg_pmd), %edx 83 + movl $PTE_IDENT_ATTR, %eax 84 + 10: 85 + leal PDE_IDENT_ATTR(%edi),%ecx /* Create PMD entry */ 86 + movl %ecx,(%edx) /* Store PMD entry */ 87 + /* Upper half already zero */ 88 + addl $8,%edx 89 + movl $512,%ecx 90 + 11: 91 + stosl 92 + xchgl %eax,%ebx 93 + stosl 94 + xchgl %eax,%ebx 95 + addl $0x1000,%eax 96 + loop 11b 97 + 98 + /* 99 + * End condition: we must map up to the end + MAPPING_BEYOND_END. 100 + */ 101 + movl $pa(_end) + MAPPING_BEYOND_END + PTE_IDENT_ATTR, %ebp 102 + cmpl %ebp,%eax 103 + jb 10b 104 + 1: 105 + addl $__PAGE_OFFSET, %edi 106 + movl %edi, pa(_brk_end) 107 + shrl $12, %eax 108 + movl %eax, pa(max_pfn_mapped) 109 + 110 + /* Do early initialization of the fixmap area */ 111 + movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax 112 + movl %eax,pa(initial_pg_pmd+0x1000*KPMDS-8) 113 + #else /* Not PAE */ 114 + 115 + page_pde_offset = (__PAGE_OFFSET >> 20); 116 + 117 + movl $pa(__brk_base), %edi 118 + movl $pa(initial_page_table), %edx 119 + movl $PTE_IDENT_ATTR, %eax 120 + 10: 121 + leal PDE_IDENT_ATTR(%edi),%ecx /* Create PDE entry */ 122 + movl %ecx,(%edx) /* Store identity PDE entry */ 123 + movl %ecx,page_pde_offset(%edx) /* Store kernel PDE entry */ 124 + addl $4,%edx 125 + movl $1024, %ecx 126 + 11: 127 + stosl 128 + addl $0x1000,%eax 129 + loop 11b 130 + /* 131 + * End condition: we must map up to the end + MAPPING_BEYOND_END. 132 + */ 133 + movl $pa(_end) + MAPPING_BEYOND_END + PTE_IDENT_ATTR, %ebp 134 + cmpl %ebp,%eax 135 + jb 10b 136 + addl $__PAGE_OFFSET, %edi 137 + movl %edi, pa(_brk_end) 138 + shrl $12, %eax 139 + movl %eax, pa(max_pfn_mapped) 140 + 141 + /* Do early initialization of the fixmap area */ 142 + movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax 143 + movl %eax,pa(initial_page_table+0xffc) 144 + #endif 145 + ret 43 146 44 147 /*G:055 45 148 * We create a macro which puts the assembler code between lgstart_ and lgend_