# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Node ID 84c0f49de1b1e241a4b409a48192c110b01788a0
# Parent b0a86eda868a047e444da80291ab8755f2d62238
[PATCH] svm: fix RIP-relative addressing in invlpg emulation
RIP-relative addressing as relative to the beginning of the next (or,
in other word, the end of the current) instruction.
Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>
---
xen/arch/x86/hvm/svm/emulate.c | 26 +++++++++-----------------
xen/arch/x86/hvm/svm/svm.c | 4 ++--
xen/include/asm-x86/hvm/svm/emulate.h | 4 ++--
3 files changed, 13 insertions(+), 21 deletions(-)
diff -r b0a86eda868a -r 84c0f49de1b1 xen/arch/x86/hvm/svm/emulate.c
--- a/xen/arch/x86/hvm/svm/emulate.c Mon Nov 27 10:05:23 2006 +0000
+++ b/xen/arch/x86/hvm/svm/emulate.c Mon Nov 27 10:06:41 2006 +0000
@@ -145,8 +145,8 @@ static inline u64 hv_is_canonical(u64 ad
unsigned long get_effective_addr_modrm64(struct vmcb_struct *vmcb,
- struct cpu_user_regs *regs, const u8 prefix, const u8 *operand,
- u8 *size)
+ struct cpu_user_regs *regs, const u8 prefix, int inst_len,
+ const u8 *operand, u8 *size)
{
unsigned long effective_addr = (unsigned long) -1;
u8 length, modrm_mod, modrm_rm;
@@ -191,17 +191,8 @@ unsigned long get_effective_addr_modrm64
*size = 1;
break;
}
-
- CHECK_LENGTH64(*size + (u8)sizeof(u32));
-
- memcpy (&disp, operand + 1, sizeof (u32));
- *size += sizeof (u32);
- if (vmcb->cs.attributes.fields.l) // 64-bit mode
- return vmcb->rip + disp;
- else
- return disp;
-
#if __x86_64__
+ /* FALLTHRU */
case 0xD:
if (0 < modrm_mod)
{
@@ -209,19 +200,20 @@ unsigned long get_effective_addr_modrm64
effective_addr = regs->r13;
break;
}
+#endif
CHECK_LENGTH64(*size + (u8)sizeof(u32));
memcpy (&disp, operand + 1, sizeof (u32));
*size += sizeof (u32);
+#if __x86_64__
/* 64-bit mode */
- if (vmcb->cs.attributes.fields.l)
- return vmcb->rip + disp;
- else
- return disp;
-
+ if (vmcb->cs.attributes.fields.l && (vmcb->efer & EFER_LMA))
+ return vmcb->rip + inst_len + *size + disp;
#endif
+ return disp;
+
default:
effective_addr = DECODE_GPR_VALUE(vmcb, regs, modrm_rm);
diff -r b0a86eda868a -r 84c0f49de1b1 xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c Mon Nov 27 10:05:23 2006 +0000
+++ b/xen/arch/x86/hvm/svm/svm.c Mon Nov 27 10:06:41 2006 +0000
@@ -2053,10 +2053,10 @@ void svm_handle_invlpg(const short invlp
/*
* Decode memory operand of the instruction including ModRM, SIB, and
- * displacement to get effecticve address and length in bytes. Assume
+ * displacement to get effective address and length in bytes. Assume
* the system in either 32- or 64-bit mode.
*/
- g_vaddr = get_effective_addr_modrm64(vmcb, regs, prefix,
+ g_vaddr = get_effective_addr_modrm64(vmcb, regs, prefix, inst_len,
&opcode[inst_len], &length);
inst_len += length;
diff -r b0a86eda868a -r 84c0f49de1b1 xen/include/asm-x86/hvm/svm/emulate.h
--- a/xen/include/asm-x86/hvm/svm/emulate.h Mon Nov 27 10:05:23 2006 +0000
+++ b/xen/include/asm-x86/hvm/svm/emulate.h Mon Nov 27 10:06:41 2006 +0000
@@ -77,8 +77,8 @@ enum instruction_index {
extern unsigned long get_effective_addr_modrm64(struct vmcb_struct *vmcb,
- struct cpu_user_regs *regs, const u8 prefix, const u8 *operand,
- u8 *size);
+ struct cpu_user_regs *regs, const u8 prefix, int inst_len,
+ const u8 *operand, u8 *size);
extern unsigned long get_effective_addr_sib(struct vmcb_struct *vmcb,
struct cpu_user_regs *regs, const u8 prefix, const u8 *operand,
u8 *size);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|