diff options
author | H. Peter Anvin <hpa@linux.intel.com> | 2012-05-08 14:22:37 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2012-05-08 14:48:03 -0400 |
commit | e5684ec438a094bec0f7d5c52652c0901b48b613 (patch) | |
tree | 8cc3cf787a582977ff08ed578907d6df7dbc7e6e | |
parent | 968ff9ee56f1e3ed4ff4a6d10185865dc77d8f7e (diff) |
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
-rw-r--r-- | arch/x86/realmode/rm/realmode.h | 16 | ||||
-rw-r--r-- | arch/x86/realmode/rm/reboot_32.S | 6 | ||||
-rw-r--r-- | arch/x86/realmode/rm/trampoline_32.S | 5 | ||||
-rw-r--r-- | arch/x86/realmode/rm/trampoline_64.S | 5 | ||||
-rw-r--r-- | arch/x86/realmode/rm/wakeup/wakeup_asm.S | 9 |
5 files changed, 25 insertions, 16 deletions
diff --git a/arch/x86/realmode/rm/realmode.h b/arch/x86/realmode/rm/realmode.h new file mode 100644 index 00000000000..15ab6335f84 --- /dev/null +++ b/arch/x86/realmode/rm/realmode.h | |||
@@ -0,0 +1,16 @@ | |||
1 | #ifndef ARCH_X86_REALMODE_RM_REALMODE_H | ||
2 | #define ARCH_X86_REALMODE_RM_REALMODE_H | ||
3 | |||
4 | #ifdef __ASSEMBLY__ | ||
5 | |||
6 | /* | ||
7 | * 16-bit ljmpw to the real_mode_seg | ||
8 | * | ||
9 | * This must be open-coded since gas will choke on using a | ||
10 | * relocatable symbol for the segment portion. | ||
11 | */ | ||
12 | #define LJMPW_RM(to) .byte 0xea ; .word (to), real_mode_seg | ||
13 | |||
14 | #endif /* __ASSEMBLY__ */ | ||
15 | |||
16 | #endif /* ARCH_X86_REALMODE_RM_REALMODE_H */ | ||
diff --git a/arch/x86/realmode/rm/reboot_32.S b/arch/x86/realmode/rm/reboot_32.S index 83803c222b4..e90f8c4bbae 100644 --- a/arch/x86/realmode/rm/reboot_32.S +++ b/arch/x86/realmode/rm/reboot_32.S | |||
@@ -2,6 +2,7 @@ | |||
2 | #include <linux/init.h> | 2 | #include <linux/init.h> |
3 | #include <asm/segment.h> | 3 | #include <asm/segment.h> |
4 | #include <asm/page_types.h> | 4 | #include <asm/page_types.h> |
5 | #include "realmode.h" | ||
5 | 6 | ||
6 | /* | 7 | /* |
7 | * The following code and data reboots the machine by switching to real | 8 | * The following code and data reboots the machine by switching to real |
@@ -82,10 +83,7 @@ machine_real_restart_asm16: | |||
82 | 2: | 83 | 2: |
83 | andb $0x10, %dl | 84 | andb $0x10, %dl |
84 | movl %edx, %cr0 | 85 | movl %edx, %cr0 |
85 | .byte 0xea /* ljmpw */ | 86 | LJMPW_RM(3f) |
86 | .word 3f /* Offset */ | ||
87 | .word real_mode_seg /* Segment */ | ||
88 | |||
89 | 3: | 87 | 3: |
90 | testb $0, %al | 88 | testb $0, %al |
91 | jz bios | 89 | jz bios |
diff --git a/arch/x86/realmode/rm/trampoline_32.S b/arch/x86/realmode/rm/trampoline_32.S index 1315ef48dbf..279f82ef7a9 100644 --- a/arch/x86/realmode/rm/trampoline_32.S +++ b/arch/x86/realmode/rm/trampoline_32.S | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/init.h> | 29 | #include <linux/init.h> |
30 | #include <asm/segment.h> | 30 | #include <asm/segment.h> |
31 | #include <asm/page_types.h> | 31 | #include <asm/page_types.h> |
32 | #include "realmode.h" | ||
32 | 33 | ||
33 | .text | 34 | .text |
34 | .code16 | 35 | .code16 |
@@ -38,9 +39,7 @@ | |||
38 | trampoline_data: | 39 | trampoline_data: |
39 | wbinvd # Needed for NUMA-Q should be harmless for others | 40 | wbinvd # Needed for NUMA-Q should be harmless for others |
40 | 41 | ||
41 | .byte 0xea # ljmpw | 42 | LJMPW_RM(1f) |
42 | .word 1f # Offset | ||
43 | .word real_mode_seg # Segment | ||
44 | 1: | 43 | 1: |
45 | mov %cs, %ax # Code and data in the same place | 44 | mov %cs, %ax # Code and data in the same place |
46 | mov %ax, %ds | 45 | mov %ax, %ds |
diff --git a/arch/x86/realmode/rm/trampoline_64.S b/arch/x86/realmode/rm/trampoline_64.S index 77b72b45d70..7459c52f0c2 100644 --- a/arch/x86/realmode/rm/trampoline_64.S +++ b/arch/x86/realmode/rm/trampoline_64.S | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <asm/msr.h> | 31 | #include <asm/msr.h> |
32 | #include <asm/segment.h> | 32 | #include <asm/segment.h> |
33 | #include <asm/processor-flags.h> | 33 | #include <asm/processor-flags.h> |
34 | #include "realmode.h" | ||
34 | 35 | ||
35 | .text | 36 | .text |
36 | .balign PAGE_SIZE | 37 | .balign PAGE_SIZE |
@@ -40,9 +41,7 @@ ENTRY(trampoline_data) | |||
40 | cli # We should be safe anyway | 41 | cli # We should be safe anyway |
41 | wbinvd | 42 | wbinvd |
42 | 43 | ||
43 | .byte 0xea # ljmpw | 44 | LJMPW_RM(1f) |
44 | .word 1f # Offset | ||
45 | .word real_mode_seg # Segment | ||
46 | 1: | 45 | 1: |
47 | mov %cs, %ax # Code and data in the same place | 46 | mov %cs, %ax # Code and data in the same place |
48 | mov %ax, %ds | 47 | mov %ax, %ds |
diff --git a/arch/x86/realmode/rm/wakeup/wakeup_asm.S b/arch/x86/realmode/rm/wakeup/wakeup_asm.S index 4c5c5f2bfbe..8064e1c3591 100644 --- a/arch/x86/realmode/rm/wakeup/wakeup_asm.S +++ b/arch/x86/realmode/rm/wakeup/wakeup_asm.S | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <asm/page_types.h> | 6 | #include <asm/page_types.h> |
7 | #include <asm/pgtable_types.h> | 7 | #include <asm/pgtable_types.h> |
8 | #include <asm/processor-flags.h> | 8 | #include <asm/processor-flags.h> |
9 | #include "../realmode.h" | ||
9 | #include "wakeup.h" | 10 | #include "wakeup.h" |
10 | 11 | ||
11 | .code16 | 12 | .code16 |
@@ -36,9 +37,7 @@ wakeup_start: | |||
36 | cli | 37 | cli |
37 | cld | 38 | cld |
38 | 39 | ||
39 | .byte 0xea /* ljmpw */ | 40 | LJMPW_RM(3f) |
40 | .word 3f | ||
41 | .word real_mode_seg | ||
42 | 3: | 41 | 3: |
43 | /* Apparently some dimwit BIOS programmers don't know how to | 42 | /* Apparently some dimwit BIOS programmers don't know how to |
44 | program a PM to RM transition, and we might end up here with | 43 | program a PM to RM transition, and we might end up here with |
@@ -59,9 +58,7 @@ wakeup_start: | |||
59 | 58 | ||
60 | andb $~X86_CR0_PE, %al | 59 | andb $~X86_CR0_PE, %al |
61 | movl %eax, %cr0 | 60 | movl %eax, %cr0 |
62 | .byte 0xea /* ljmpw */ | 61 | LJMPW_RM(3f) |
63 | .word 3f | ||
64 | .word real_mode_seg | ||
65 | 3: | 62 | 3: |
66 | /* Set up segments */ | 63 | /* Set up segments */ |
67 | movw %cs, %ax | 64 | movw %cs, %ax |