]> err.no Git - linux-2.6/commitdiff
KVM: x86 emulator: fix access registers for instructions with ModR/M byte and Mod = 3
authorAurelien Jarno <aurelien@aurel32.net>
Wed, 17 Oct 2007 17:30:41 +0000 (19:30 +0200)
committerAvi Kivity <avi@qumranet.com>
Mon, 22 Oct 2007 10:03:29 +0000 (12:03 +0200)
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>
drivers/kvm/x86_emulate.c

index 0a8696d9b82c5618d09b6e1ccccb11c3d13bbc5c..a6ace302e0cd454f1f413306013b0920305e4a67 100644 (file)
@@ -825,6 +825,14 @@ done_prefixes:
                if (twobyte && b == 0x01 && modrm_reg == 7)
                        break;
              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;
                src.val = 0;
@@ -893,6 +901,14 @@ done_prefixes:
                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);