diff options
author | H. Peter Anvin <hpa@linux.intel.com> | 2013-01-19 13:29:37 -0500 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2013-01-19 14:01:22 -0500 |
commit | 021ef050fc092d5638e69868d126c18006ea7296 (patch) | |
tree | ea1c51b7e8da9c12ae97484214d23adb29d642ea /arch/x86/kernel/head_32.S | |
parent | 7d1f9aeff1ee4a20b1aeb377dd0f579fe9647619 (diff) |
x86-32: Start out cr0 clean, disable paging before modifying cr3/4
Patch
5a5a51db78e x86-32: Start out eflags and cr4 clean
... made x86-32 match x86-64 in that we initialize %eflags and %cr4
from scratch. This broke OLPC XO-1.5, because the XO enters the
kernel with paging enabled, which the kernel doesn't expect.
Since we no longer support 386 (the source of most of the variability
in %cr0 configuration), we can simply match further x86-64 and
initialize %cr0 to a fixed value -- the one variable part remaining in
%cr0 is for FPU control, but all that is handled later on in
initialization; in particular, configuring %cr0 as if the FPU is
present until proven otherwise is correct and necessary for the probe
to work.
To deal with the XO case sanely, explicitly disable paging in %cr0
before we muck with %cr3, %cr4 or EFER -- those operations are
inherently unsafe with paging enabled.
NOTE: There is still a lot of 386-related junk in head_32.S which we
can and should get rid of, however, this is intended as a minimal fix
whereas the cleanup can be deferred to the next merge window.
Reported-by: Andres Salomon <dilinger@queued.net>
Tested-by: Daniel Drake <dsd@laptop.org>
Link: http://lkml.kernel.org/r/50FA0661.2060400@linux.intel.com
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Diffstat (limited to 'arch/x86/kernel/head_32.S')
-rw-r--r-- | arch/x86/kernel/head_32.S | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index 8e7f6556028f..c8932c79e78b 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S | |||
@@ -300,6 +300,12 @@ ENTRY(startup_32_smp) | |||
300 | leal -__PAGE_OFFSET(%ecx),%esp | 300 | leal -__PAGE_OFFSET(%ecx),%esp |
301 | 301 | ||
302 | default_entry: | 302 | default_entry: |
303 | #define CR0_STATE (X86_CR0_PE | X86_CR0_MP | X86_CR0_ET | \ | ||
304 | X86_CR0_NE | X86_CR0_WP | X86_CR0_AM | \ | ||
305 | X86_CR0_PG) | ||
306 | movl $(CR0_STATE & ~X86_CR0_PG),%eax | ||
307 | movl %eax,%cr0 | ||
308 | |||
303 | /* | 309 | /* |
304 | * New page tables may be in 4Mbyte page mode and may | 310 | * New page tables may be in 4Mbyte page mode and may |
305 | * be using the global pages. | 311 | * be using the global pages. |
@@ -364,8 +370,7 @@ default_entry: | |||
364 | */ | 370 | */ |
365 | movl $pa(initial_page_table), %eax | 371 | movl $pa(initial_page_table), %eax |
366 | movl %eax,%cr3 /* set the page table pointer.. */ | 372 | movl %eax,%cr3 /* set the page table pointer.. */ |
367 | movl %cr0,%eax | 373 | movl $CR0_STATE,%eax |
368 | orl $X86_CR0_PG,%eax | ||
369 | movl %eax,%cr0 /* ..and set paging (PG) bit */ | 374 | movl %eax,%cr0 /* ..and set paging (PG) bit */ |
370 | ljmp $__BOOT_CS,$1f /* Clear prefetch and normalize %eip */ | 375 | ljmp $__BOOT_CS,$1f /* Clear prefetch and normalize %eip */ |
371 | 1: | 376 | 1: |