Wednesday, March 23, 2011

kvm: x86 instruction decoder/emulator

In case you've been wondered about kvm emulation, devs did
steb-by-step decoding/emulation. Really outstanding and impressive:

arch/x86/kvm/emulate.c
x86_emulate_insn
[..]
3036     switch (c->b) {
[..]
3078     case 0x28 ... 0x2d:
3079           sub:      /* sub */
3080         emulate_2op_SrcV("sub", c->src, c->dst, ctxt->eflags);
3081         break;
3082     case 0x30 ... 0x35:
3083           xor:      /* xor */
3084         emulate_2op_SrcV("xor", c->src, c->dst, ctxt->eflags);
3085         break;
3086     case 0x38 ... 0x3d:
3087           cmp:      /* cmp */
3088         emulate_2op_SrcV("cmp", c->src, c->dst, ctxt->eflags);
3089         break;
3090     case 0x40 ... 0x47: /* inc r16/r32 */
3091         emulate_1op("inc", c->dst, ctxt->eflags);
3092         break;
3093     case 0x48 ... 0x4f: /* dec r16/r32 */
3094         emulate_1op("dec", c->dst, ctxt->eflags);
3095         break;
3096     case 0x58 ... 0x5f: /* pop reg */
3097     pop_instruction:
3098         rc = emulate_pop(ctxt, ops, &c->dst.val, c->op_bytes);
3099         break;
3100     case 0x60/* pusha */
3101         rc = emulate_pusha(ctxt, ops);
3102         break;
3103     case 0x61/* popa */
3104         rc = emulate_popa(ctxt, ops);
3105         break;
3106     case 0x63:      /* movsxd */
3107         if (ctxt->mode != X86EMUL_MODE_PROT64)
3108             goto cannot_emulate;
3109         c->dst.val = (s32) c->src.val;
3110         break;
3111     case 0x6c:      /* insb */
3112     case 0x6d:      /* insw/insd */
3113         c->src.val = c->regs[VCPU_REGS_RDX];
3114         goto do_io_in;
3115     case 0x6e:      /* outsb */
3116     case 0x6f:      /* outsw/outsd */
3117         c->dst.val = c->regs[VCPU_REGS_RDX];
3118         goto do_io_out;
3119         break;
3120     case 0x70 ... 0x7f: /* jcc (short) */
3121         if (test_cc(c->b, ctxt->eflags))
3122             jmp_rel(c, c->src.val);
3123         break;
3124     case 0x80 ... 0x83: /* Grp1 */
3125         switch (c->modrm_reg) {
3126         case 0:
3127             goto add;
3128         case 1:
3129             goto or;
3130         case 2:
3131             goto adc;
3132         case 3:
3133             goto sbb;
3134         case 4:
3135             goto and;
3136         case 5:
3137             goto sub;
3138         case 6:
3139             goto xor;
3140         case 7:
3141             goto cmp;
3142         }
3143         break;
3144     case 0x84 ... 0x85:
[..]



the whole platform... with sysenter/sysexit/syscal/etc.

emulate_sysenter
[..]
1650     /* inject #GP if in real mode */
1651     if (ctxt->mode == X86EMUL_MODE_REAL)
1652         return emulate_gp(ctxt, 0);
1653
1654     /* XXX sysenter/sysexit have not been tested in 64bit mode.
1655     * Therefore, we inject an #UD.
1656     */
1657     if (ctxt->mode == X86EMUL_MODE_PROT64)
1658         return emulate_ud(ctxt);
1659
1660     setup_syscalls_segments(ctxt, ops, &cs, &ss);
1661
1662     ops->get_msr(ctxt->vcpu, MSR_IA32_SYSENTER_CS, &msr_data);
1663     switch (ctxt->mode) {                                                      
1664     case X86EMUL_MODE_PROT32:
1665         if ((msr_data & 0xfffc) == 0x0)
1666             return emulate_gp(ctxt, 0);
1667         break;
1668     case X86EMUL_MODE_PROT64:
1669         if (msr_data == 0x0)
1670             return emulate_gp(ctxt, 0);
1671         break;
1672     }
[..]

No comments:

Post a Comment