mirror of https://gitee.com/openkylin/linux.git
x86, mm: Initialize initial_page_table before paravirt jumps
v2.6.36-rc8-54-gb40827f (x86-32, mm: Add an initial page table
for core bootstrapping) made x86 boot using initial_page_table
and broke lguest.
For 2.6.37 we simply cut & paste the initialization code into
lguest (da32dac101
"lguest: populate initial_page_table"), now
we fix it properly by doing that initialization before the
paravirt jump.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Acked-by: Jeremy Fitzhardinge <jeremy@goop.org>
Cc: lguest <lguest@ozlabs.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
LKML-Reference: <201101041720.54535.rusty@rustcorp.com.au>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
parent
387c31c7e5
commit
d50d8fe192
|
@ -139,39 +139,6 @@ ENTRY(startup_32)
|
||||||
movl %eax, pa(olpc_ofw_pgd)
|
movl %eax, pa(olpc_ofw_pgd)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_PARAVIRT
|
|
||||||
/* This is can only trip for a broken bootloader... */
|
|
||||||
cmpw $0x207, pa(boot_params + BP_version)
|
|
||||||
jb default_entry
|
|
||||||
|
|
||||||
/* Paravirt-compatible boot parameters. Look to see what architecture
|
|
||||||
we're booting under. */
|
|
||||||
movl pa(boot_params + BP_hardware_subarch), %eax
|
|
||||||
cmpl $num_subarch_entries, %eax
|
|
||||||
jae bad_subarch
|
|
||||||
|
|
||||||
movl pa(subarch_entries)(,%eax,4), %eax
|
|
||||||
subl $__PAGE_OFFSET, %eax
|
|
||||||
jmp *%eax
|
|
||||||
|
|
||||||
bad_subarch:
|
|
||||||
WEAK(lguest_entry)
|
|
||||||
WEAK(xen_entry)
|
|
||||||
/* Unknown implementation; there's really
|
|
||||||
nothing we can do at this point. */
|
|
||||||
ud2a
|
|
||||||
|
|
||||||
__INITDATA
|
|
||||||
|
|
||||||
subarch_entries:
|
|
||||||
.long default_entry /* normal x86/PC */
|
|
||||||
.long lguest_entry /* lguest hypervisor */
|
|
||||||
.long xen_entry /* Xen hypervisor */
|
|
||||||
.long default_entry /* Moorestown MID */
|
|
||||||
num_subarch_entries = (. - subarch_entries) / 4
|
|
||||||
.previous
|
|
||||||
#endif /* CONFIG_PARAVIRT */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize page tables. This creates a PDE and a set of page
|
* Initialize page tables. This creates a PDE and a set of page
|
||||||
* tables, which are located immediately beyond __brk_base. The variable
|
* tables, which are located immediately beyond __brk_base. The variable
|
||||||
|
@ -181,7 +148,6 @@ num_subarch_entries = (. - subarch_entries) / 4
|
||||||
*
|
*
|
||||||
* Note that the stack is not yet set up!
|
* Note that the stack is not yet set up!
|
||||||
*/
|
*/
|
||||||
default_entry:
|
|
||||||
#ifdef CONFIG_X86_PAE
|
#ifdef CONFIG_X86_PAE
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -261,7 +227,42 @@ page_pde_offset = (__PAGE_OFFSET >> 20);
|
||||||
movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax
|
movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax
|
||||||
movl %eax,pa(initial_page_table+0xffc)
|
movl %eax,pa(initial_page_table+0xffc)
|
||||||
#endif
|
#endif
|
||||||
jmp 3f
|
|
||||||
|
#ifdef CONFIG_PARAVIRT
|
||||||
|
/* This is can only trip for a broken bootloader... */
|
||||||
|
cmpw $0x207, pa(boot_params + BP_version)
|
||||||
|
jb default_entry
|
||||||
|
|
||||||
|
/* Paravirt-compatible boot parameters. Look to see what architecture
|
||||||
|
we're booting under. */
|
||||||
|
movl pa(boot_params + BP_hardware_subarch), %eax
|
||||||
|
cmpl $num_subarch_entries, %eax
|
||||||
|
jae bad_subarch
|
||||||
|
|
||||||
|
movl pa(subarch_entries)(,%eax,4), %eax
|
||||||
|
subl $__PAGE_OFFSET, %eax
|
||||||
|
jmp *%eax
|
||||||
|
|
||||||
|
bad_subarch:
|
||||||
|
WEAK(lguest_entry)
|
||||||
|
WEAK(xen_entry)
|
||||||
|
/* Unknown implementation; there's really
|
||||||
|
nothing we can do at this point. */
|
||||||
|
ud2a
|
||||||
|
|
||||||
|
__INITDATA
|
||||||
|
|
||||||
|
subarch_entries:
|
||||||
|
.long default_entry /* normal x86/PC */
|
||||||
|
.long lguest_entry /* lguest hypervisor */
|
||||||
|
.long xen_entry /* Xen hypervisor */
|
||||||
|
.long default_entry /* Moorestown MID */
|
||||||
|
num_subarch_entries = (. - subarch_entries) / 4
|
||||||
|
.previous
|
||||||
|
#else
|
||||||
|
jmp default_entry
|
||||||
|
#endif /* CONFIG_PARAVIRT */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Non-boot CPU entry point; entered from trampoline.S
|
* Non-boot CPU entry point; entered from trampoline.S
|
||||||
* We can't lgdt here, because lgdt itself uses a data segment, but
|
* We can't lgdt here, because lgdt itself uses a data segment, but
|
||||||
|
@ -282,7 +283,7 @@ ENTRY(startup_32_smp)
|
||||||
movl %eax,%fs
|
movl %eax,%fs
|
||||||
movl %eax,%gs
|
movl %eax,%gs
|
||||||
#endif /* CONFIG_SMP */
|
#endif /* CONFIG_SMP */
|
||||||
3:
|
default_entry:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* New page tables may be in 4Mbyte page mode and may
|
* New page tables may be in 4Mbyte page mode and may
|
||||||
|
@ -622,13 +623,13 @@ ENTRY(initial_code)
|
||||||
__PAGE_ALIGNED_BSS
|
__PAGE_ALIGNED_BSS
|
||||||
.align PAGE_SIZE_asm
|
.align PAGE_SIZE_asm
|
||||||
#ifdef CONFIG_X86_PAE
|
#ifdef CONFIG_X86_PAE
|
||||||
ENTRY(initial_pg_pmd)
|
initial_pg_pmd:
|
||||||
.fill 1024*KPMDS,4,0
|
.fill 1024*KPMDS,4,0
|
||||||
#else
|
#else
|
||||||
ENTRY(initial_page_table)
|
ENTRY(initial_page_table)
|
||||||
.fill 1024,4,0
|
.fill 1024,4,0
|
||||||
#endif
|
#endif
|
||||||
ENTRY(initial_pg_fixmap)
|
initial_pg_fixmap:
|
||||||
.fill 1024,4,0
|
.fill 1024,4,0
|
||||||
ENTRY(empty_zero_page)
|
ENTRY(empty_zero_page)
|
||||||
.fill 4096,1,0
|
.fill 4096,1,0
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
#include <asm/asm-offsets.h>
|
#include <asm/asm-offsets.h>
|
||||||
#include <asm/thread_info.h>
|
#include <asm/thread_info.h>
|
||||||
#include <asm/processor-flags.h>
|
#include <asm/processor-flags.h>
|
||||||
#include <asm/pgtable.h>
|
|
||||||
|
|
||||||
/*G:020
|
/*G:020
|
||||||
* Our story starts with the kernel booting into startup_32 in
|
* Our story starts with the kernel booting into startup_32 in
|
||||||
|
@ -38,113 +37,9 @@ ENTRY(lguest_entry)
|
||||||
/* Set up the initial stack so we can run C code. */
|
/* Set up the initial stack so we can run C code. */
|
||||||
movl $(init_thread_union+THREAD_SIZE),%esp
|
movl $(init_thread_union+THREAD_SIZE),%esp
|
||||||
|
|
||||||
call init_pagetables
|
|
||||||
|
|
||||||
/* Jumps are relative: we're running __PAGE_OFFSET too low. */
|
/* Jumps are relative: we're running __PAGE_OFFSET too low. */
|
||||||
jmp lguest_init+__PAGE_OFFSET
|
jmp lguest_init+__PAGE_OFFSET
|
||||||
|
|
||||||
/*
|
|
||||||
* Initialize page tables. This creates a PDE and a set of page
|
|
||||||
* tables, which are located immediately beyond __brk_base. The variable
|
|
||||||
* _brk_end is set up to point to the first "safe" location.
|
|
||||||
* Mappings are created both at virtual address 0 (identity mapping)
|
|
||||||
* and PAGE_OFFSET for up to _end.
|
|
||||||
*
|
|
||||||
* FIXME: This code is taken verbatim from arch/x86/kernel/head_32.S: they
|
|
||||||
* don't have a stack at this point, so we can't just use call and ret.
|
|
||||||
*/
|
|
||||||
init_pagetables:
|
|
||||||
#if PTRS_PER_PMD > 1
|
|
||||||
#define PAGE_TABLE_SIZE(pages) (((pages) / PTRS_PER_PMD) + PTRS_PER_PGD)
|
|
||||||
#else
|
|
||||||
#define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PGD)
|
|
||||||
#endif
|
|
||||||
#define pa(X) ((X) - __PAGE_OFFSET)
|
|
||||||
|
|
||||||
/* Enough space to fit pagetables for the low memory linear map */
|
|
||||||
MAPPING_BEYOND_END = \
|
|
||||||
PAGE_TABLE_SIZE(((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT) << PAGE_SHIFT
|
|
||||||
#ifdef CONFIG_X86_PAE
|
|
||||||
|
|
||||||
/*
|
|
||||||
* In PAE mode initial_page_table is statically defined to contain
|
|
||||||
* enough entries to cover the VMSPLIT option (that is the top 1, 2 or 3
|
|
||||||
* entries). The identity mapping is handled by pointing two PGD entries
|
|
||||||
* to the first kernel PMD.
|
|
||||||
*
|
|
||||||
* Note the upper half of each PMD or PTE are always zero at this stage.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define KPMDS (((-__PAGE_OFFSET) >> 30) & 3) /* Number of kernel PMDs */
|
|
||||||
|
|
||||||
xorl %ebx,%ebx /* %ebx is kept at zero */
|
|
||||||
|
|
||||||
movl $pa(__brk_base), %edi
|
|
||||||
movl $pa(initial_pg_pmd), %edx
|
|
||||||
movl $PTE_IDENT_ATTR, %eax
|
|
||||||
10:
|
|
||||||
leal PDE_IDENT_ATTR(%edi),%ecx /* Create PMD entry */
|
|
||||||
movl %ecx,(%edx) /* Store PMD entry */
|
|
||||||
/* Upper half already zero */
|
|
||||||
addl $8,%edx
|
|
||||||
movl $512,%ecx
|
|
||||||
11:
|
|
||||||
stosl
|
|
||||||
xchgl %eax,%ebx
|
|
||||||
stosl
|
|
||||||
xchgl %eax,%ebx
|
|
||||||
addl $0x1000,%eax
|
|
||||||
loop 11b
|
|
||||||
|
|
||||||
/*
|
|
||||||
* End condition: we must map up to the end + MAPPING_BEYOND_END.
|
|
||||||
*/
|
|
||||||
movl $pa(_end) + MAPPING_BEYOND_END + PTE_IDENT_ATTR, %ebp
|
|
||||||
cmpl %ebp,%eax
|
|
||||||
jb 10b
|
|
||||||
1:
|
|
||||||
addl $__PAGE_OFFSET, %edi
|
|
||||||
movl %edi, pa(_brk_end)
|
|
||||||
shrl $12, %eax
|
|
||||||
movl %eax, pa(max_pfn_mapped)
|
|
||||||
|
|
||||||
/* Do early initialization of the fixmap area */
|
|
||||||
movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax
|
|
||||||
movl %eax,pa(initial_pg_pmd+0x1000*KPMDS-8)
|
|
||||||
#else /* Not PAE */
|
|
||||||
|
|
||||||
page_pde_offset = (__PAGE_OFFSET >> 20);
|
|
||||||
|
|
||||||
movl $pa(__brk_base), %edi
|
|
||||||
movl $pa(initial_page_table), %edx
|
|
||||||
movl $PTE_IDENT_ATTR, %eax
|
|
||||||
10:
|
|
||||||
leal PDE_IDENT_ATTR(%edi),%ecx /* Create PDE entry */
|
|
||||||
movl %ecx,(%edx) /* Store identity PDE entry */
|
|
||||||
movl %ecx,page_pde_offset(%edx) /* Store kernel PDE entry */
|
|
||||||
addl $4,%edx
|
|
||||||
movl $1024, %ecx
|
|
||||||
11:
|
|
||||||
stosl
|
|
||||||
addl $0x1000,%eax
|
|
||||||
loop 11b
|
|
||||||
/*
|
|
||||||
* End condition: we must map up to the end + MAPPING_BEYOND_END.
|
|
||||||
*/
|
|
||||||
movl $pa(_end) + MAPPING_BEYOND_END + PTE_IDENT_ATTR, %ebp
|
|
||||||
cmpl %ebp,%eax
|
|
||||||
jb 10b
|
|
||||||
addl $__PAGE_OFFSET, %edi
|
|
||||||
movl %edi, pa(_brk_end)
|
|
||||||
shrl $12, %eax
|
|
||||||
movl %eax, pa(max_pfn_mapped)
|
|
||||||
|
|
||||||
/* Do early initialization of the fixmap area */
|
|
||||||
movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax
|
|
||||||
movl %eax,pa(initial_page_table+0xffc)
|
|
||||||
#endif
|
|
||||||
ret
|
|
||||||
|
|
||||||
/*G:055
|
/*G:055
|
||||||
* We create a macro which puts the assembler code between lgstart_ and lgend_
|
* We create a macro which puts the assembler code between lgstart_ and lgend_
|
||||||
* markers. These templates are put in the .text section: they can't be
|
* markers. These templates are put in the .text section: they can't be
|
||||||
|
|
Loading…
Reference in New Issue