diff options
author | Brian Gerst <brgerst@gmail.com> | 2009-10-12 10:18:23 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-10-12 12:29:46 -0400 |
commit | ae24ffe5ecec17c956ac25371d7c2e12b4b36e53 (patch) | |
tree | dac0241dcc85e8ec6e8fe25705fce8bf7f4ea57e | |
parent | f3834b9ef68067199486740b31f691afb14dbdf5 (diff) |
x86, 64-bit: Move K8 B step iret fixup to fault entry asm
Move the handling of truncated %rip from an iret fault to the fault
entry path.
This allows x86-64 to use the standard search_extable() function.
Signed-off-by: Brian Gerst <brgerst@gmail.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Jan Beulich <jbeulich@novell.com>
LKML-Reference: <1255357103-5418-1-git-send-email-brgerst@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | arch/x86/include/asm/uaccess.h | 1 | ||||
-rw-r--r-- | arch/x86/kernel/entry_64.S | 11 | ||||
-rw-r--r-- | arch/x86/mm/extable.c | 31 |
3 files changed, 8 insertions, 35 deletions
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h index d2c6c930b491..abd3e0ea762a 100644 --- a/arch/x86/include/asm/uaccess.h +++ b/arch/x86/include/asm/uaccess.h | |||
@@ -570,7 +570,6 @@ extern struct movsl_mask { | |||
570 | #ifdef CONFIG_X86_32 | 570 | #ifdef CONFIG_X86_32 |
571 | # include "uaccess_32.h" | 571 | # include "uaccess_32.h" |
572 | #else | 572 | #else |
573 | # define ARCH_HAS_SEARCH_EXTABLE | ||
574 | # include "uaccess_64.h" | 573 | # include "uaccess_64.h" |
575 | #endif | 574 | #endif |
576 | 575 | ||
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index b5c061f8f358..af0f4b226dbe 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S | |||
@@ -1491,12 +1491,17 @@ error_kernelspace: | |||
1491 | leaq irq_return(%rip),%rcx | 1491 | leaq irq_return(%rip),%rcx |
1492 | cmpq %rcx,RIP+8(%rsp) | 1492 | cmpq %rcx,RIP+8(%rsp) |
1493 | je error_swapgs | 1493 | je error_swapgs |
1494 | movl %ecx,%ecx /* zero extend */ | 1494 | movl %ecx,%eax /* zero extend */ |
1495 | cmpq %rcx,RIP+8(%rsp) | 1495 | cmpq %rax,RIP+8(%rsp) |
1496 | je error_swapgs | 1496 | je bstep_iret |
1497 | cmpq $gs_change,RIP+8(%rsp) | 1497 | cmpq $gs_change,RIP+8(%rsp) |
1498 | je error_swapgs | 1498 | je error_swapgs |
1499 | jmp error_sti | 1499 | jmp error_sti |
1500 | |||
1501 | bstep_iret: | ||
1502 | /* Fix truncated RIP */ | ||
1503 | movq %rcx,RIP+8(%rsp) | ||
1504 | je error_swapgs | ||
1500 | END(error_entry) | 1505 | END(error_entry) |
1501 | 1506 | ||
1502 | 1507 | ||
diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c index 61b41ca3b5a2..d0474ad2a6e5 100644 --- a/arch/x86/mm/extable.c +++ b/arch/x86/mm/extable.c | |||
@@ -35,34 +35,3 @@ int fixup_exception(struct pt_regs *regs) | |||
35 | 35 | ||
36 | return 0; | 36 | return 0; |
37 | } | 37 | } |
38 | |||
39 | #ifdef CONFIG_X86_64 | ||
40 | /* | ||
41 | * Need to defined our own search_extable on X86_64 to work around | ||
42 | * a B stepping K8 bug. | ||
43 | */ | ||
44 | const struct exception_table_entry * | ||
45 | search_extable(const struct exception_table_entry *first, | ||
46 | const struct exception_table_entry *last, | ||
47 | unsigned long value) | ||
48 | { | ||
49 | /* B stepping K8 bug */ | ||
50 | if ((value >> 32) == 0) | ||
51 | value |= 0xffffffffUL << 32; | ||
52 | |||
53 | while (first <= last) { | ||
54 | const struct exception_table_entry *mid; | ||
55 | long diff; | ||
56 | |||
57 | mid = (last - first) / 2 + first; | ||
58 | diff = mid->insn - value; | ||
59 | if (diff == 0) | ||
60 | return mid; | ||
61 | else if (diff < 0) | ||
62 | first = mid+1; | ||
63 | else | ||
64 | last = mid-1; | ||
65 | } | ||
66 | return NULL; | ||
67 | } | ||
68 | #endif | ||