Loading drivers/kvm/x86_emulate.c +177 −160 Original line number Diff line number Diff line Loading @@ -548,122 +548,20 @@ static void decode_register_operand(struct operand *op, op->orig_val = op->val; } int x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) static int decode_modrm(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) { struct decode_cache *c = &ctxt->decode; u8 sib; int rc = 0; int mode = ctxt->mode; int index_reg = 0, base_reg = 0, scale, rip_relative = 0; int rc = 0; /* Shadow copy of register state. Committed on successful emulation. */ memset(c, 0, sizeof(struct decode_cache)); c->eip = ctxt->vcpu->rip; memcpy(c->regs, ctxt->vcpu->regs, sizeof c->regs); switch (mode) { case X86EMUL_MODE_REAL: case X86EMUL_MODE_PROT16: c->op_bytes = c->ad_bytes = 2; break; case X86EMUL_MODE_PROT32: c->op_bytes = c->ad_bytes = 4; break; #ifdef CONFIG_X86_64 case X86EMUL_MODE_PROT64: c->op_bytes = 4; c->ad_bytes = 8; break; #endif default: return -1; } /* Legacy prefixes. */ for (;;) { switch (c->b = insn_fetch(u8, 1, c->eip)) { case 0x66: /* operand-size override */ c->op_bytes ^= 6; /* switch between 2/4 bytes */ break; case 0x67: /* address-size override */ if (mode == X86EMUL_MODE_PROT64) /* switch between 4/8 bytes */ c->ad_bytes ^= 12; else /* switch between 2/4 bytes */ c->ad_bytes ^= 6; break; case 0x2e: /* CS override */ c->override_base = &ctxt->cs_base; break; case 0x3e: /* DS override */ c->override_base = &ctxt->ds_base; break; case 0x26: /* ES override */ c->override_base = &ctxt->es_base; break; case 0x64: /* FS override */ c->override_base = &ctxt->fs_base; break; case 0x65: /* GS override */ c->override_base = &ctxt->gs_base; break; case 0x36: /* SS override */ c->override_base = &ctxt->ss_base; break; case 0x40 ... 0x4f: /* REX */ if (mode != X86EMUL_MODE_PROT64) goto done_prefixes; c->rex_prefix = c->b; continue; case 0xf0: /* LOCK */ c->lock_prefix = 1; break; case 0xf2: /* REPNE/REPNZ */ case 0xf3: /* REP/REPE/REPZ */ c->rep_prefix = 1; break; default: goto done_prefixes; } /* Any legacy prefix after a REX prefix nullifies its effect. */ c->rex_prefix = 0; } done_prefixes: /* REX prefix. */ if (c->rex_prefix) { if (c->rex_prefix & 8) c->op_bytes = 8; /* REX.W */ c->modrm_reg = (c->rex_prefix & 4) << 1; /* REX.R */ index_reg = (c->rex_prefix & 2) << 2; /* REX.X */ c->modrm_rm = base_reg = (c->rex_prefix & 1) << 3; /* REG.B */ } /* Opcode byte(s). */ c->d = opcode_table[c->b]; if (c->d == 0) { /* Two-byte opcode? */ if (c->b == 0x0f) { c->twobyte = 1; c->b = insn_fetch(u8, 1, c->eip); c->d = twobyte_table[c->b]; } /* Unrecognised? */ if (c->d == 0) { DPRINTF("Cannot emulate %02x\n", c->b); return -1; } } /* ModRM and SIB bytes. */ if (c->d & ModRM) { c->modrm = insn_fetch(u8, 1, c->eip); c->modrm_mod |= (c->modrm & 0xc0) >> 6; c->modrm_reg |= (c->modrm & 0x38) >> 3; Loading @@ -674,7 +572,7 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) if (c->modrm_mod == 3) { c->modrm_val = *(unsigned long *) decode_register(c->modrm_rm, c->regs, c->d & ByteOp); goto modrm_done; return rc; } if (c->ad_bytes == 2) { Loading @@ -687,8 +585,7 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) switch (c->modrm_mod) { case 0: if (c->modrm_rm == 6) c->modrm_ea += insn_fetch(u16, 2, c->eip); c->modrm_ea += insn_fetch(u16, 2, c->eip); break; case 1: c->modrm_ea += insn_fetch(s8, 1, c->eip); Loading Loading @@ -742,8 +639,7 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) switch (base_reg) { case 5: if (c->modrm_mod != 0) c->modrm_ea += c->regs[base_reg]; c->modrm_ea += c->regs[base_reg]; else c->modrm_ea += insn_fetch(s32, 4, c->eip); Loading @@ -755,15 +651,13 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) case 4: break; default: c->modrm_ea += c->regs[index_reg] << scale; c->modrm_ea += c->regs[index_reg] << scale; } break; case 5: if (c->modrm_mod != 0) c->modrm_ea += c->regs[c->modrm_rm]; else if (mode == X86EMUL_MODE_PROT64) else if (ctxt->mode == X86EMUL_MODE_PROT64) rip_relative = 1; break; default: Loading @@ -773,8 +667,7 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) switch (c->modrm_mod) { case 0: if (c->modrm_rm == 5) c->modrm_ea += insn_fetch(s32, 4, c->eip); c->modrm_ea += insn_fetch(s32, 4, c->eip); break; case 1: c->modrm_ea += insn_fetch(s8, 1, c->eip); Loading @@ -800,9 +693,16 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) c->modrm_ea += c->op_bytes; } } modrm_done: ; } else if (c->d & MemAbs) { done: return rc; } static int decode_abs(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) { struct decode_cache *c = &ctxt->decode; int rc = 0; switch (c->ad_bytes) { case 2: c->modrm_ea = insn_fetch(u16, 2, c->eip); Loading @@ -814,9 +714,126 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) c->modrm_ea = insn_fetch(u64, 8, c->eip); break; } done: return rc; } int x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) { struct decode_cache *c = &ctxt->decode; int rc = 0; int mode = ctxt->mode; /* Shadow copy of register state. Committed on successful emulation. */ memset(c, 0, sizeof(struct decode_cache)); c->eip = ctxt->vcpu->rip; memcpy(c->regs, ctxt->vcpu->regs, sizeof c->regs); switch (mode) { case X86EMUL_MODE_REAL: case X86EMUL_MODE_PROT16: c->op_bytes = c->ad_bytes = 2; break; case X86EMUL_MODE_PROT32: c->op_bytes = c->ad_bytes = 4; break; #ifdef CONFIG_X86_64 case X86EMUL_MODE_PROT64: c->op_bytes = 4; c->ad_bytes = 8; break; #endif default: return -1; } /* Legacy prefixes. */ for (;;) { switch (c->b = insn_fetch(u8, 1, c->eip)) { case 0x66: /* operand-size override */ c->op_bytes ^= 6; /* switch between 2/4 bytes */ break; case 0x67: /* address-size override */ if (mode == X86EMUL_MODE_PROT64) /* switch between 4/8 bytes */ c->ad_bytes ^= 12; else /* switch between 2/4 bytes */ c->ad_bytes ^= 6; break; case 0x2e: /* CS override */ c->override_base = &ctxt->cs_base; break; case 0x3e: /* DS override */ c->override_base = &ctxt->ds_base; break; case 0x26: /* ES override */ c->override_base = &ctxt->es_base; break; case 0x64: /* FS override */ c->override_base = &ctxt->fs_base; break; case 0x65: /* GS override */ c->override_base = &ctxt->gs_base; break; case 0x36: /* SS override */ c->override_base = &ctxt->ss_base; break; case 0x40 ... 0x4f: /* REX */ if (mode != X86EMUL_MODE_PROT64) goto done_prefixes; c->rex_prefix = c->b; continue; case 0xf0: /* LOCK */ c->lock_prefix = 1; break; case 0xf2: /* REPNE/REPNZ */ case 0xf3: /* REP/REPE/REPZ */ c->rep_prefix = 1; break; default: goto done_prefixes; } /* Any legacy prefix after a REX prefix nullifies its effect. */ c->rex_prefix = 0; } done_prefixes: /* REX prefix. */ if (c->rex_prefix) if (c->rex_prefix & 8) c->op_bytes = 8; /* REX.W */ /* Opcode byte(s). */ c->d = opcode_table[c->b]; if (c->d == 0) { /* Two-byte opcode? */ if (c->b == 0x0f) { c->twobyte = 1; c->b = insn_fetch(u8, 1, c->eip); c->d = twobyte_table[c->b]; } /* Unrecognised? */ if (c->d == 0) { DPRINTF("Cannot emulate %02x\n", c->b); return -1; } } /* ModRM and SIB bytes. */ if (c->d & ModRM) rc = decode_modrm(ctxt, ops); else if (c->d & MemAbs) rc = decode_abs(ctxt, ops); if (rc) goto done; if (!c->override_base) c->override_base = &ctxt->ds_base; if (mode == X86EMUL_MODE_PROT64 && Loading Loading
drivers/kvm/x86_emulate.c +177 −160 Original line number Diff line number Diff line Loading @@ -548,122 +548,20 @@ static void decode_register_operand(struct operand *op, op->orig_val = op->val; } int x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) static int decode_modrm(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) { struct decode_cache *c = &ctxt->decode; u8 sib; int rc = 0; int mode = ctxt->mode; int index_reg = 0, base_reg = 0, scale, rip_relative = 0; int rc = 0; /* Shadow copy of register state. Committed on successful emulation. */ memset(c, 0, sizeof(struct decode_cache)); c->eip = ctxt->vcpu->rip; memcpy(c->regs, ctxt->vcpu->regs, sizeof c->regs); switch (mode) { case X86EMUL_MODE_REAL: case X86EMUL_MODE_PROT16: c->op_bytes = c->ad_bytes = 2; break; case X86EMUL_MODE_PROT32: c->op_bytes = c->ad_bytes = 4; break; #ifdef CONFIG_X86_64 case X86EMUL_MODE_PROT64: c->op_bytes = 4; c->ad_bytes = 8; break; #endif default: return -1; } /* Legacy prefixes. */ for (;;) { switch (c->b = insn_fetch(u8, 1, c->eip)) { case 0x66: /* operand-size override */ c->op_bytes ^= 6; /* switch between 2/4 bytes */ break; case 0x67: /* address-size override */ if (mode == X86EMUL_MODE_PROT64) /* switch between 4/8 bytes */ c->ad_bytes ^= 12; else /* switch between 2/4 bytes */ c->ad_bytes ^= 6; break; case 0x2e: /* CS override */ c->override_base = &ctxt->cs_base; break; case 0x3e: /* DS override */ c->override_base = &ctxt->ds_base; break; case 0x26: /* ES override */ c->override_base = &ctxt->es_base; break; case 0x64: /* FS override */ c->override_base = &ctxt->fs_base; break; case 0x65: /* GS override */ c->override_base = &ctxt->gs_base; break; case 0x36: /* SS override */ c->override_base = &ctxt->ss_base; break; case 0x40 ... 0x4f: /* REX */ if (mode != X86EMUL_MODE_PROT64) goto done_prefixes; c->rex_prefix = c->b; continue; case 0xf0: /* LOCK */ c->lock_prefix = 1; break; case 0xf2: /* REPNE/REPNZ */ case 0xf3: /* REP/REPE/REPZ */ c->rep_prefix = 1; break; default: goto done_prefixes; } /* Any legacy prefix after a REX prefix nullifies its effect. */ c->rex_prefix = 0; } done_prefixes: /* REX prefix. */ if (c->rex_prefix) { if (c->rex_prefix & 8) c->op_bytes = 8; /* REX.W */ c->modrm_reg = (c->rex_prefix & 4) << 1; /* REX.R */ index_reg = (c->rex_prefix & 2) << 2; /* REX.X */ c->modrm_rm = base_reg = (c->rex_prefix & 1) << 3; /* REG.B */ } /* Opcode byte(s). */ c->d = opcode_table[c->b]; if (c->d == 0) { /* Two-byte opcode? */ if (c->b == 0x0f) { c->twobyte = 1; c->b = insn_fetch(u8, 1, c->eip); c->d = twobyte_table[c->b]; } /* Unrecognised? */ if (c->d == 0) { DPRINTF("Cannot emulate %02x\n", c->b); return -1; } } /* ModRM and SIB bytes. */ if (c->d & ModRM) { c->modrm = insn_fetch(u8, 1, c->eip); c->modrm_mod |= (c->modrm & 0xc0) >> 6; c->modrm_reg |= (c->modrm & 0x38) >> 3; Loading @@ -674,7 +572,7 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) if (c->modrm_mod == 3) { c->modrm_val = *(unsigned long *) decode_register(c->modrm_rm, c->regs, c->d & ByteOp); goto modrm_done; return rc; } if (c->ad_bytes == 2) { Loading @@ -687,8 +585,7 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) switch (c->modrm_mod) { case 0: if (c->modrm_rm == 6) c->modrm_ea += insn_fetch(u16, 2, c->eip); c->modrm_ea += insn_fetch(u16, 2, c->eip); break; case 1: c->modrm_ea += insn_fetch(s8, 1, c->eip); Loading Loading @@ -742,8 +639,7 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) switch (base_reg) { case 5: if (c->modrm_mod != 0) c->modrm_ea += c->regs[base_reg]; c->modrm_ea += c->regs[base_reg]; else c->modrm_ea += insn_fetch(s32, 4, c->eip); Loading @@ -755,15 +651,13 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) case 4: break; default: c->modrm_ea += c->regs[index_reg] << scale; c->modrm_ea += c->regs[index_reg] << scale; } break; case 5: if (c->modrm_mod != 0) c->modrm_ea += c->regs[c->modrm_rm]; else if (mode == X86EMUL_MODE_PROT64) else if (ctxt->mode == X86EMUL_MODE_PROT64) rip_relative = 1; break; default: Loading @@ -773,8 +667,7 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) switch (c->modrm_mod) { case 0: if (c->modrm_rm == 5) c->modrm_ea += insn_fetch(s32, 4, c->eip); c->modrm_ea += insn_fetch(s32, 4, c->eip); break; case 1: c->modrm_ea += insn_fetch(s8, 1, c->eip); Loading @@ -800,9 +693,16 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) c->modrm_ea += c->op_bytes; } } modrm_done: ; } else if (c->d & MemAbs) { done: return rc; } static int decode_abs(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) { struct decode_cache *c = &ctxt->decode; int rc = 0; switch (c->ad_bytes) { case 2: c->modrm_ea = insn_fetch(u16, 2, c->eip); Loading @@ -814,9 +714,126 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) c->modrm_ea = insn_fetch(u64, 8, c->eip); break; } done: return rc; } int x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) { struct decode_cache *c = &ctxt->decode; int rc = 0; int mode = ctxt->mode; /* Shadow copy of register state. Committed on successful emulation. */ memset(c, 0, sizeof(struct decode_cache)); c->eip = ctxt->vcpu->rip; memcpy(c->regs, ctxt->vcpu->regs, sizeof c->regs); switch (mode) { case X86EMUL_MODE_REAL: case X86EMUL_MODE_PROT16: c->op_bytes = c->ad_bytes = 2; break; case X86EMUL_MODE_PROT32: c->op_bytes = c->ad_bytes = 4; break; #ifdef CONFIG_X86_64 case X86EMUL_MODE_PROT64: c->op_bytes = 4; c->ad_bytes = 8; break; #endif default: return -1; } /* Legacy prefixes. */ for (;;) { switch (c->b = insn_fetch(u8, 1, c->eip)) { case 0x66: /* operand-size override */ c->op_bytes ^= 6; /* switch between 2/4 bytes */ break; case 0x67: /* address-size override */ if (mode == X86EMUL_MODE_PROT64) /* switch between 4/8 bytes */ c->ad_bytes ^= 12; else /* switch between 2/4 bytes */ c->ad_bytes ^= 6; break; case 0x2e: /* CS override */ c->override_base = &ctxt->cs_base; break; case 0x3e: /* DS override */ c->override_base = &ctxt->ds_base; break; case 0x26: /* ES override */ c->override_base = &ctxt->es_base; break; case 0x64: /* FS override */ c->override_base = &ctxt->fs_base; break; case 0x65: /* GS override */ c->override_base = &ctxt->gs_base; break; case 0x36: /* SS override */ c->override_base = &ctxt->ss_base; break; case 0x40 ... 0x4f: /* REX */ if (mode != X86EMUL_MODE_PROT64) goto done_prefixes; c->rex_prefix = c->b; continue; case 0xf0: /* LOCK */ c->lock_prefix = 1; break; case 0xf2: /* REPNE/REPNZ */ case 0xf3: /* REP/REPE/REPZ */ c->rep_prefix = 1; break; default: goto done_prefixes; } /* Any legacy prefix after a REX prefix nullifies its effect. */ c->rex_prefix = 0; } done_prefixes: /* REX prefix. */ if (c->rex_prefix) if (c->rex_prefix & 8) c->op_bytes = 8; /* REX.W */ /* Opcode byte(s). */ c->d = opcode_table[c->b]; if (c->d == 0) { /* Two-byte opcode? */ if (c->b == 0x0f) { c->twobyte = 1; c->b = insn_fetch(u8, 1, c->eip); c->d = twobyte_table[c->b]; } /* Unrecognised? */ if (c->d == 0) { DPRINTF("Cannot emulate %02x\n", c->b); return -1; } } /* ModRM and SIB bytes. */ if (c->d & ModRM) rc = decode_modrm(ctxt, ops); else if (c->d & MemAbs) rc = decode_abs(ctxt, ops); if (rc) goto done; if (!c->override_base) c->override_base = &ctxt->ds_base; if (mode == X86EMUL_MODE_PROT64 && Loading