Skip to content

Commit

Permalink
x86, realmode: Replace open-coded ljmpw with a macro
Browse files Browse the repository at this point in the history
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
  • Loading branch information
H. Peter Anvin committed May 8, 2012
1 parent 968ff9e commit e5684ec
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 16 deletions.
16 changes: 16 additions & 0 deletions arch/x86/realmode/rm/realmode.h
Original file line number Diff line number Diff line change
@@ -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 */
6 changes: 2 additions & 4 deletions arch/x86/realmode/rm/reboot_32.S
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
5 changes: 2 additions & 3 deletions arch/x86/realmode/rm/trampoline_32.S
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <linux/init.h>
#include <asm/segment.h>
#include <asm/page_types.h>
#include "realmode.h"

.text
.code16
Expand All @@ -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
Expand Down
5 changes: 2 additions & 3 deletions arch/x86/realmode/rm/trampoline_64.S
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <asm/msr.h>
#include <asm/segment.h>
#include <asm/processor-flags.h>
#include "realmode.h"

.text
.balign PAGE_SIZE
Expand All @@ -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
Expand Down
9 changes: 3 additions & 6 deletions arch/x86/realmode/rm/wakeup/wakeup_asm.S
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down

0 comments on commit e5684ec

Please sign in to comment.