diff options
author | Marcelo Tosatti <mtosatti@redhat.com> | 2011-05-30 14:23:14 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2011-06-06 03:52:09 -0400 |
commit | 221192bdff2583834984639121595fc9296120d3 (patch) | |
tree | 7e84882430b604226a822b32be6ab29107fc0c73 /arch/x86 | |
parent | 9e3bb6b6f6a0c535eb053fbf0005a8e79e053374 (diff) |
KVM: x86: use proper port value when checking io instruction permission
Commit f6511935f42 moved the permission check for io instructions
to the ->check_perm callback. It failed to copy the port value from RDX
register for string and "in,out ax,dx" instructions.
Fix it by reading RDX register at decode stage when appropriate.
Fixes FC8.32 installation.
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/kvm/emulate.c | 82 |
1 files changed, 47 insertions, 35 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index d6e2477feb18..6df88c7885c0 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c | |||
@@ -47,38 +47,40 @@ | |||
47 | #define DstDI (5<<1) /* Destination is in ES:(E)DI */ | 47 | #define DstDI (5<<1) /* Destination is in ES:(E)DI */ |
48 | #define DstMem64 (6<<1) /* 64bit memory operand */ | 48 | #define DstMem64 (6<<1) /* 64bit memory operand */ |
49 | #define DstImmUByte (7<<1) /* 8-bit unsigned immediate operand */ | 49 | #define DstImmUByte (7<<1) /* 8-bit unsigned immediate operand */ |
50 | #define DstMask (7<<1) | 50 | #define DstDX (8<<1) /* Destination is in DX register */ |
51 | #define DstMask (0xf<<1) | ||
51 | /* Source operand type. */ | 52 | /* Source operand type. */ |
52 | #define SrcNone (0<<4) /* No source operand. */ | 53 | #define SrcNone (0<<5) /* No source operand. */ |
53 | #define SrcReg (1<<4) /* Register operand. */ | 54 | #define SrcReg (1<<5) /* Register operand. */ |
54 | #define SrcMem (2<<4) /* Memory operand. */ | 55 | #define SrcMem (2<<5) /* Memory operand. */ |
55 | #define SrcMem16 (3<<4) /* Memory operand (16-bit). */ | 56 | #define SrcMem16 (3<<5) /* Memory operand (16-bit). */ |
56 | #define SrcMem32 (4<<4) /* Memory operand (32-bit). */ | 57 | #define SrcMem32 (4<<5) /* Memory operand (32-bit). */ |
57 | #define SrcImm (5<<4) /* Immediate operand. */ | 58 | #define SrcImm (5<<5) /* Immediate operand. */ |
58 | #define SrcImmByte (6<<4) /* 8-bit sign-extended immediate operand. */ | 59 | #define SrcImmByte (6<<5) /* 8-bit sign-extended immediate operand. */ |
59 | #define SrcOne (7<<4) /* Implied '1' */ | 60 | #define SrcOne (7<<5) /* Implied '1' */ |
60 | #define SrcImmUByte (8<<4) /* 8-bit unsigned immediate operand. */ | 61 | #define SrcImmUByte (8<<5) /* 8-bit unsigned immediate operand. */ |
61 | #define SrcImmU (9<<4) /* Immediate operand, unsigned */ | 62 | #define SrcImmU (9<<5) /* Immediate operand, unsigned */ |
62 | #define SrcSI (0xa<<4) /* Source is in the DS:RSI */ | 63 | #define SrcSI (0xa<<5) /* Source is in the DS:RSI */ |
63 | #define SrcImmFAddr (0xb<<4) /* Source is immediate far address */ | 64 | #define SrcImmFAddr (0xb<<5) /* Source is immediate far address */ |
64 | #define SrcMemFAddr (0xc<<4) /* Source is far address in memory */ | 65 | #define SrcMemFAddr (0xc<<5) /* Source is far address in memory */ |
65 | #define SrcAcc (0xd<<4) /* Source Accumulator */ | 66 | #define SrcAcc (0xd<<5) /* Source Accumulator */ |
66 | #define SrcImmU16 (0xe<<4) /* Immediate operand, unsigned, 16 bits */ | 67 | #define SrcImmU16 (0xe<<5) /* Immediate operand, unsigned, 16 bits */ |
67 | #define SrcMask (0xf<<4) | 68 | #define SrcDX (0xf<<5) /* Source is in DX register */ |
69 | #define SrcMask (0xf<<5) | ||
68 | /* Generic ModRM decode. */ | 70 | /* Generic ModRM decode. */ |
69 | #define ModRM (1<<8) | 71 | #define ModRM (1<<9) |
70 | /* Destination is only written; never read. */ | 72 | /* Destination is only written; never read. */ |
71 | #define Mov (1<<9) | 73 | #define Mov (1<<10) |
72 | #define BitOp (1<<10) | 74 | #define BitOp (1<<11) |
73 | #define MemAbs (1<<11) /* Memory operand is absolute displacement */ | 75 | #define MemAbs (1<<12) /* Memory operand is absolute displacement */ |
74 | #define String (1<<12) /* String instruction (rep capable) */ | 76 | #define String (1<<13) /* String instruction (rep capable) */ |
75 | #define Stack (1<<13) /* Stack instruction (push/pop) */ | 77 | #define Stack (1<<14) /* Stack instruction (push/pop) */ |
76 | #define GroupMask (7<<14) /* Opcode uses one of the group mechanisms */ | 78 | #define GroupMask (7<<15) /* Opcode uses one of the group mechanisms */ |
77 | #define Group (1<<14) /* Bits 3:5 of modrm byte extend opcode */ | 79 | #define Group (1<<15) /* Bits 3:5 of modrm byte extend opcode */ |
78 | #define GroupDual (2<<14) /* Alternate decoding of mod == 3 */ | 80 | #define GroupDual (2<<15) /* Alternate decoding of mod == 3 */ |
79 | #define Prefix (3<<14) /* Instruction varies with 66/f2/f3 prefix */ | 81 | #define Prefix (3<<15) /* Instruction varies with 66/f2/f3 prefix */ |
80 | #define RMExt (4<<14) /* Opcode extension in ModRM r/m if mod == 3 */ | 82 | #define RMExt (4<<15) /* Opcode extension in ModRM r/m if mod == 3 */ |
81 | #define Sse (1<<17) /* SSE Vector instruction */ | 83 | #define Sse (1<<18) /* SSE Vector instruction */ |
82 | /* Misc flags */ | 84 | /* Misc flags */ |
83 | #define Prot (1<<21) /* instruction generates #UD if not in prot-mode */ | 85 | #define Prot (1<<21) /* instruction generates #UD if not in prot-mode */ |
84 | #define VendorSpecific (1<<22) /* Vendor specific instruction */ | 86 | #define VendorSpecific (1<<22) /* Vendor specific instruction */ |
@@ -3154,8 +3156,8 @@ static struct opcode opcode_table[256] = { | |||
3154 | I(DstReg | SrcMem | ModRM | Src2Imm, em_imul_3op), | 3156 | I(DstReg | SrcMem | ModRM | Src2Imm, em_imul_3op), |
3155 | I(SrcImmByte | Mov | Stack, em_push), | 3157 | I(SrcImmByte | Mov | Stack, em_push), |
3156 | I(DstReg | SrcMem | ModRM | Src2ImmByte, em_imul_3op), | 3158 | I(DstReg | SrcMem | ModRM | Src2ImmByte, em_imul_3op), |
3157 | D2bvIP(DstDI | Mov | String, ins, check_perm_in), /* insb, insw/insd */ | 3159 | D2bvIP(DstDI | SrcDX | Mov | String, ins, check_perm_in), /* insb, insw/insd */ |
3158 | D2bvIP(SrcSI | ImplicitOps | String, outs, check_perm_out), /* outsb, outsw/outsd */ | 3160 | D2bvIP(SrcSI | DstDX | String, outs, check_perm_out), /* outsb, outsw/outsd */ |
3159 | /* 0x70 - 0x7F */ | 3161 | /* 0x70 - 0x7F */ |
3160 | X16(D(SrcImmByte)), | 3162 | X16(D(SrcImmByte)), |
3161 | /* 0x80 - 0x87 */ | 3163 | /* 0x80 - 0x87 */ |
@@ -3212,8 +3214,8 @@ static struct opcode opcode_table[256] = { | |||
3212 | /* 0xE8 - 0xEF */ | 3214 | /* 0xE8 - 0xEF */ |
3213 | D(SrcImm | Stack), D(SrcImm | ImplicitOps), | 3215 | D(SrcImm | Stack), D(SrcImm | ImplicitOps), |
3214 | D(SrcImmFAddr | No64), D(SrcImmByte | ImplicitOps), | 3216 | D(SrcImmFAddr | No64), D(SrcImmByte | ImplicitOps), |
3215 | D2bvIP(SrcNone | DstAcc, in, check_perm_in), | 3217 | D2bvIP(SrcDX | DstAcc, in, check_perm_in), |
3216 | D2bvIP(SrcAcc | ImplicitOps, out, check_perm_out), | 3218 | D2bvIP(SrcAcc | DstDX, out, check_perm_out), |
3217 | /* 0xF0 - 0xF7 */ | 3219 | /* 0xF0 - 0xF7 */ |
3218 | N, DI(ImplicitOps, icebp), N, N, | 3220 | N, DI(ImplicitOps, icebp), N, N, |
3219 | DI(ImplicitOps | Priv, hlt), D(ImplicitOps), | 3221 | DI(ImplicitOps | Priv, hlt), D(ImplicitOps), |
@@ -3613,6 +3615,12 @@ done_prefixes: | |||
3613 | memop.bytes = c->op_bytes + 2; | 3615 | memop.bytes = c->op_bytes + 2; |
3614 | goto srcmem_common; | 3616 | goto srcmem_common; |
3615 | break; | 3617 | break; |
3618 | case SrcDX: | ||
3619 | c->src.type = OP_REG; | ||
3620 | c->src.bytes = 2; | ||
3621 | c->src.addr.reg = &c->regs[VCPU_REGS_RDX]; | ||
3622 | fetch_register_operand(&c->src); | ||
3623 | break; | ||
3616 | } | 3624 | } |
3617 | 3625 | ||
3618 | if (rc != X86EMUL_CONTINUE) | 3626 | if (rc != X86EMUL_CONTINUE) |
@@ -3682,6 +3690,12 @@ done_prefixes: | |||
3682 | c->dst.addr.mem.seg = VCPU_SREG_ES; | 3690 | c->dst.addr.mem.seg = VCPU_SREG_ES; |
3683 | c->dst.val = 0; | 3691 | c->dst.val = 0; |
3684 | break; | 3692 | break; |
3693 | case DstDX: | ||
3694 | c->dst.type = OP_REG; | ||
3695 | c->dst.bytes = 2; | ||
3696 | c->dst.addr.reg = &c->regs[VCPU_REGS_RDX]; | ||
3697 | fetch_register_operand(&c->dst); | ||
3698 | break; | ||
3685 | case ImplicitOps: | 3699 | case ImplicitOps: |
3686 | /* Special instructions do their own operand decoding. */ | 3700 | /* Special instructions do their own operand decoding. */ |
3687 | default: | 3701 | default: |
@@ -4027,7 +4041,6 @@ special_insn: | |||
4027 | break; | 4041 | break; |
4028 | case 0xec: /* in al,dx */ | 4042 | case 0xec: /* in al,dx */ |
4029 | case 0xed: /* in (e/r)ax,dx */ | 4043 | case 0xed: /* in (e/r)ax,dx */ |
4030 | c->src.val = c->regs[VCPU_REGS_RDX]; | ||
4031 | do_io_in: | 4044 | do_io_in: |
4032 | if (!pio_in_emulated(ctxt, ops, c->dst.bytes, c->src.val, | 4045 | if (!pio_in_emulated(ctxt, ops, c->dst.bytes, c->src.val, |
4033 | &c->dst.val)) | 4046 | &c->dst.val)) |
@@ -4035,7 +4048,6 @@ special_insn: | |||
4035 | break; | 4048 | break; |
4036 | case 0xee: /* out dx,al */ | 4049 | case 0xee: /* out dx,al */ |
4037 | case 0xef: /* out dx,(e/r)ax */ | 4050 | case 0xef: /* out dx,(e/r)ax */ |
4038 | c->dst.val = c->regs[VCPU_REGS_RDX]; | ||
4039 | do_io_out: | 4051 | do_io_out: |
4040 | ops->pio_out_emulated(ctxt, c->src.bytes, c->dst.val, | 4052 | ops->pio_out_emulated(ctxt, c->src.bytes, c->dst.val, |
4041 | &c->src.val, 1); | 4053 | &c->src.val, 1); |