x86, realmode: Replace open-coded ljmpw with a macro

We cannot code an ljmpw to the real-mode segment directly, because gas
refuses to assemble an ljmp with a symbolic segment.  Instead of
open-coding it everywhere, define a macro and use it for this case.

This is specifically an ljmpw from a 16-bit segment.  This is okay, as
one should never enter real mode from a 32-bit segment: if one do, the
CPU ends up in a bizarre (and useless) mode sometimes called "unreal
mode" where segments behave like real mode but the default address and
operand sizes is 32 bits.

Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Link: http://lkml.kernel.org/r/1336501366-28617-15-git-send-email-jarkko.sakkinen@intel.com
This commit is contained in:
H. Peter Anvin 2012-05-08 21:22:37 +03:00
parent 968ff9ee56
commit e5684ec438
5 changed files with 25 additions and 16 deletions

View File

@ -0,0 +1,16 @@
#ifndef ARCH_X86_REALMODE_RM_REALMODE_H
#define ARCH_X86_REALMODE_RM_REALMODE_H
#ifdef __ASSEMBLY__
/*
* 16-bit ljmpw to the real_mode_seg
*
* This must be open-coded since gas will choke on using a
* relocatable symbol for the segment portion.
*/
#define LJMPW_RM(to) .byte 0xea ; .word (to), real_mode_seg
#endif /* __ASSEMBLY__ */
#endif /* ARCH_X86_REALMODE_RM_REALMODE_H */

View File

@ -2,6 +2,7 @@
#include <linux/init.h>
#include <asm/segment.h>
#include <asm/page_types.h>
#include "realmode.h"
/*
* The following code and data reboots the machine by switching to real
@ -82,10 +83,7 @@ machine_real_restart_asm16:
2:
andb $0x10, %dl
movl %edx, %cr0
.byte 0xea /* ljmpw */
.word 3f /* Offset */
.word real_mode_seg /* Segment */
LJMPW_RM(3f)
3:
testb $0, %al
jz bios

View File

@ -29,6 +29,7 @@
#include <linux/init.h>
#include <asm/segment.h>
#include <asm/page_types.h>
#include "realmode.h"
.text
.code16
@ -38,9 +39,7 @@
trampoline_data:
wbinvd # Needed for NUMA-Q should be harmless for others
.byte 0xea # ljmpw
.word 1f # Offset
.word real_mode_seg # Segment
LJMPW_RM(1f)
1:
mov %cs, %ax # Code and data in the same place
mov %ax, %ds

View File

@ -31,6 +31,7 @@
#include <asm/msr.h>
#include <asm/segment.h>
#include <asm/processor-flags.h>
#include "realmode.h"
.text
.balign PAGE_SIZE
@ -40,9 +41,7 @@ ENTRY(trampoline_data)
cli # We should be safe anyway
wbinvd
.byte 0xea # ljmpw
.word 1f # Offset
.word real_mode_seg # Segment
LJMPW_RM(1f)
1:
mov %cs, %ax # Code and data in the same place
mov %ax, %ds

View File

@ -6,6 +6,7 @@
#include <asm/page_types.h>
#include <asm/pgtable_types.h>
#include <asm/processor-flags.h>
#include "../realmode.h"
#include "wakeup.h"
.code16
@ -36,9 +37,7 @@ wakeup_start:
cli
cld
.byte 0xea /* ljmpw */
.word 3f
.word real_mode_seg
LJMPW_RM(3f)
3:
/* Apparently some dimwit BIOS programmers don't know how to
program a PM to RM transition, and we might end up here with
@ -59,9 +58,7 @@ wakeup_start:
andb $~X86_CR0_PE, %al
movl %eax, %cr0
.byte 0xea /* ljmpw */
.word 3f
.word real_mode_seg
LJMPW_RM(3f)
3:
/* Set up segments */
movw %cs, %ax