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>
This commit is contained in:
parent
f3834b9ef6
commit
ae24ffe5ec
3 changed files with 8 additions and 35 deletions
|
@ -570,7 +570,6 @@ extern struct movsl_mask {
|
|||
#ifdef CONFIG_X86_32
|
||||
# include "uaccess_32.h"
|
||||
#else
|
||||
# define ARCH_HAS_SEARCH_EXTABLE
|
||||
# include "uaccess_64.h"
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1491,12 +1491,17 @@ error_kernelspace:
|
|||
leaq irq_return(%rip),%rcx
|
||||
cmpq %rcx,RIP+8(%rsp)
|
||||
je error_swapgs
|
||||
movl %ecx,%ecx /* zero extend */
|
||||
cmpq %rcx,RIP+8(%rsp)
|
||||
je error_swapgs
|
||||
movl %ecx,%eax /* zero extend */
|
||||
cmpq %rax,RIP+8(%rsp)
|
||||
je bstep_iret
|
||||
cmpq $gs_change,RIP+8(%rsp)
|
||||
je error_swapgs
|
||||
jmp error_sti
|
||||
|
||||
bstep_iret:
|
||||
/* Fix truncated RIP */
|
||||
movq %rcx,RIP+8(%rsp)
|
||||
je error_swapgs
|
||||
END(error_entry)
|
||||
|
||||
|
||||
|
|
|
@ -35,34 +35,3 @@ int fixup_exception(struct pt_regs *regs)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
/*
|
||||
* Need to defined our own search_extable on X86_64 to work around
|
||||
* a B stepping K8 bug.
|
||||
*/
|
||||
const struct exception_table_entry *
|
||||
search_extable(const struct exception_table_entry *first,
|
||||
const struct exception_table_entry *last,
|
||||
unsigned long value)
|
||||
{
|
||||
/* B stepping K8 bug */
|
||||
if ((value >> 32) == 0)
|
||||
value |= 0xffffffffUL << 32;
|
||||
|
||||
while (first <= last) {
|
||||
const struct exception_table_entry *mid;
|
||||
long diff;
|
||||
|
||||
mid = (last - first) / 2 + first;
|
||||
diff = mid->insn - value;
|
||||
if (diff == 0)
|
||||
return mid;
|
||||
else if (diff < 0)
|
||||
first = mid+1;
|
||||
else
|
||||
last = mid-1;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue