]> git.hungrycats.org Git - linux/commitdiff
KVM: x86 emulator: fix access registers for instructions with ModR/M byte and Mod = 3
authorAurelien Jarno <aurelien@aurel32.net>
Sun, 2 Dec 2007 11:18:39 +0000 (13:18 +0200)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 14 Dec 2007 17:50:55 +0000 (09:50 -0800)
patch 4e62417bf317504c0b85e0d7abd236f334f54eaf in mainline.

The patch belows changes the access type to register from memory for
instructions that are declared as SrcMem or DstMem, but have a
ModR/M byte with Mod = 3.

It fixes (at least) the lmsw and smsw instructions on an AMD64 CPU,
which are needed for FreeBSD.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Avi Kivity <avi@qumranet.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/kvm/x86_emulate.c

index 804e86c57c6074dd4d67d5920aae900f70554365..08cd4a385c061cfa5dd3f843e1a7c64061839b17 100644 (file)
@@ -773,6 +773,14 @@ done_prefixes:
        case SrcMem:
                src.bytes = (d & ByteOp) ? 1 : op_bytes;
              srcmem_common:
+               /*
+                * For instructions with a ModR/M byte, switch to register
+                * access if Mod = 3.
+                */
+               if ((d & ModRM) && modrm_mod == 3) {
+                       src.type = OP_REG;
+                       break;
+               }
                src.type = OP_MEM;
                src.ptr = (unsigned long *)cr2;
                if ((rc = ops->read_emulated((unsigned long)src.ptr,
@@ -839,6 +847,15 @@ done_prefixes:
                dst.type = OP_MEM;
                dst.ptr = (unsigned long *)cr2;
                dst.bytes = (d & ByteOp) ? 1 : op_bytes;
+               dst.val = 0;
+               /*
+                * For instructions with a ModR/M byte, switch to register
+                * access if Mod = 3.
+                */
+               if ((d & ModRM) && modrm_mod == 3) {
+                       dst.type = OP_REG;
+                       break;
+               }
                if (d & BitOp) {
                        unsigned long mask = ~(dst.bytes * 8 - 1);