diff options
author | Wei Yongjun <yjwei@cn.fujitsu.com> | 2010-08-23 02:56:54 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2010-10-24 04:51:20 -0400 |
commit | 09b5f4d3c4aa2d4928c0a3723a8de26a76b6339e (patch) | |
tree | 8d937d45806faf3af18073099eb3e3b017d339f0 | |
parent | 45221ab6684a82a5b60208b76d6f8bfb1bbcb969 (diff) |
KVM: x86 emulator: add LDS/LES/LFS/LGS/LSS instruction emulation
Add LDS/LES/LFS/LGS/LSS instruction emulation.
(opcode 0xc4, 0xc5, 0x0f 0xb2, 0x0f 0xb4~0xb5)
Signed-off-by: Wei Yongjun <yjwei@cn.fujitsu.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
-rw-r--r-- | arch/x86/kvm/emulate.c | 50 |
1 files changed, 46 insertions, 4 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index e257f2286866..aece501edce4 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c | |||
@@ -1514,6 +1514,23 @@ static int emulate_ret_far(struct x86_emulate_ctxt *ctxt, | |||
1514 | return rc; | 1514 | return rc; |
1515 | } | 1515 | } |
1516 | 1516 | ||
1517 | static int emulate_load_segment(struct x86_emulate_ctxt *ctxt, | ||
1518 | struct x86_emulate_ops *ops, int seg) | ||
1519 | { | ||
1520 | struct decode_cache *c = &ctxt->decode; | ||
1521 | unsigned short sel; | ||
1522 | int rc; | ||
1523 | |||
1524 | memcpy(&sel, c->src.valptr + c->op_bytes, 2); | ||
1525 | |||
1526 | rc = load_segment_descriptor(ctxt, ops, sel, seg); | ||
1527 | if (rc != X86EMUL_CONTINUE) | ||
1528 | return rc; | ||
1529 | |||
1530 | c->dst.val = c->src.val; | ||
1531 | return rc; | ||
1532 | } | ||
1533 | |||
1517 | static inline void | 1534 | static inline void |
1518 | setup_syscalls_segments(struct x86_emulate_ctxt *ctxt, | 1535 | setup_syscalls_segments(struct x86_emulate_ctxt *ctxt, |
1519 | struct x86_emulate_ops *ops, struct desc_struct *cs, | 1536 | struct x86_emulate_ops *ops, struct desc_struct *cs, |
@@ -2458,7 +2475,7 @@ static struct opcode opcode_table[256] = { | |||
2458 | D(ByteOp | DstMem | SrcImm | ModRM), D(DstMem | SrcImmByte | ModRM), | 2475 | D(ByteOp | DstMem | SrcImm | ModRM), D(DstMem | SrcImmByte | ModRM), |
2459 | I(ImplicitOps | Stack | SrcImmU16, em_ret_near_imm), | 2476 | I(ImplicitOps | Stack | SrcImmU16, em_ret_near_imm), |
2460 | D(ImplicitOps | Stack), | 2477 | D(ImplicitOps | Stack), |
2461 | N, N, | 2478 | D(DstReg | SrcMemFAddr | ModRM | No64), D(DstReg | SrcMemFAddr | ModRM | No64), |
2462 | D(ByteOp | DstMem | SrcImm | ModRM | Mov), D(DstMem | SrcImm | ModRM | Mov), | 2479 | D(ByteOp | DstMem | SrcImm | ModRM | Mov), D(DstMem | SrcImm | ModRM | Mov), |
2463 | /* 0xC8 - 0xCF */ | 2480 | /* 0xC8 - 0xCF */ |
2464 | N, N, N, D(ImplicitOps | Stack), | 2481 | N, N, N, D(ImplicitOps | Stack), |
@@ -2529,9 +2546,9 @@ static struct opcode twobyte_table[256] = { | |||
2529 | D(ModRM), I(DstReg | SrcMem | ModRM, em_imul), | 2546 | D(ModRM), I(DstReg | SrcMem | ModRM, em_imul), |
2530 | /* 0xB0 - 0xB7 */ | 2547 | /* 0xB0 - 0xB7 */ |
2531 | D(ByteOp | DstMem | SrcReg | ModRM | Lock), D(DstMem | SrcReg | ModRM | Lock), | 2548 | D(ByteOp | DstMem | SrcReg | ModRM | Lock), D(DstMem | SrcReg | ModRM | Lock), |
2532 | N, D(DstMem | SrcReg | ModRM | BitOp | Lock), | 2549 | D(DstReg | SrcMemFAddr | ModRM), D(DstMem | SrcReg | ModRM | BitOp | Lock), |
2533 | N, N, D(ByteOp | DstReg | SrcMem | ModRM | Mov), | 2550 | D(DstReg | SrcMemFAddr | ModRM), D(DstReg | SrcMemFAddr | ModRM), |
2534 | D(DstReg | SrcMem16 | ModRM | Mov), | 2551 | D(ByteOp | DstReg | SrcMem | ModRM | Mov), D(DstReg | SrcMem16 | ModRM | Mov), |
2535 | /* 0xB8 - 0xBF */ | 2552 | /* 0xB8 - 0xBF */ |
2536 | N, N, | 2553 | N, N, |
2537 | G(BitOp, group8), D(DstMem | SrcReg | ModRM | BitOp | Lock), | 2554 | G(BitOp, group8), D(DstMem | SrcReg | ModRM | BitOp | Lock), |
@@ -3214,6 +3231,16 @@ special_insn: | |||
3214 | c->dst.addr.reg = &c->eip; | 3231 | c->dst.addr.reg = &c->eip; |
3215 | c->dst.bytes = c->op_bytes; | 3232 | c->dst.bytes = c->op_bytes; |
3216 | goto pop_instruction; | 3233 | goto pop_instruction; |
3234 | case 0xc4: /* les */ | ||
3235 | rc = emulate_load_segment(ctxt, ops, VCPU_SREG_ES); | ||
3236 | if (rc != X86EMUL_CONTINUE) | ||
3237 | goto done; | ||
3238 | break; | ||
3239 | case 0xc5: /* lds */ | ||
3240 | rc = emulate_load_segment(ctxt, ops, VCPU_SREG_DS); | ||
3241 | if (rc != X86EMUL_CONTINUE) | ||
3242 | goto done; | ||
3243 | break; | ||
3217 | case 0xc6 ... 0xc7: /* mov (sole member of Grp11) */ | 3244 | case 0xc6 ... 0xc7: /* mov (sole member of Grp11) */ |
3218 | mov: | 3245 | mov: |
3219 | c->dst.val = c->src.val; | 3246 | c->dst.val = c->src.val; |
@@ -3659,10 +3686,25 @@ twobyte_insn: | |||
3659 | c->dst.addr.reg = (unsigned long *)&c->regs[VCPU_REGS_RAX]; | 3686 | c->dst.addr.reg = (unsigned long *)&c->regs[VCPU_REGS_RAX]; |
3660 | } | 3687 | } |
3661 | break; | 3688 | break; |
3689 | case 0xb2: /* lss */ | ||
3690 | rc = emulate_load_segment(ctxt, ops, VCPU_SREG_SS); | ||
3691 | if (rc != X86EMUL_CONTINUE) | ||
3692 | goto done; | ||
3693 | break; | ||
3662 | case 0xb3: | 3694 | case 0xb3: |
3663 | btr: /* btr */ | 3695 | btr: /* btr */ |
3664 | emulate_2op_SrcV_nobyte("btr", c->src, c->dst, ctxt->eflags); | 3696 | emulate_2op_SrcV_nobyte("btr", c->src, c->dst, ctxt->eflags); |
3665 | break; | 3697 | break; |
3698 | case 0xb4: /* lfs */ | ||
3699 | rc = emulate_load_segment(ctxt, ops, VCPU_SREG_FS); | ||
3700 | if (rc != X86EMUL_CONTINUE) | ||
3701 | goto done; | ||
3702 | break; | ||
3703 | case 0xb5: /* lgs */ | ||
3704 | rc = emulate_load_segment(ctxt, ops, VCPU_SREG_GS); | ||
3705 | if (rc != X86EMUL_CONTINUE) | ||
3706 | goto done; | ||
3707 | break; | ||
3666 | case 0xb6 ... 0xb7: /* movzx */ | 3708 | case 0xb6 ... 0xb7: /* movzx */ |
3667 | c->dst.bytes = c->op_bytes; | 3709 | c->dst.bytes = c->op_bytes; |
3668 | c->dst.val = (c->d & ByteOp) ? (u8) c->src.val | 3710 | c->dst.val = (c->d & ByteOp) ? (u8) c->src.val |