Commit 26d05cc7 authored by Avi Kivity's avatar Avi Kivity

KVM: x86 emulator: move 0F 01 sub-opcodes into their own functions

Signed-off-by: default avatarAvi Kivity <avi@redhat.com>
parent d4224449
...@@ -2589,6 +2589,95 @@ static int em_clts(struct x86_emulate_ctxt *ctxt) ...@@ -2589,6 +2589,95 @@ static int em_clts(struct x86_emulate_ctxt *ctxt)
return X86EMUL_CONTINUE; return X86EMUL_CONTINUE;
} }
static int em_vmcall(struct x86_emulate_ctxt *ctxt)
{
struct decode_cache *c = &ctxt->decode;
int rc;
if (c->modrm_mod != 3 || c->modrm_rm != 1)
return X86EMUL_UNHANDLEABLE;
rc = ctxt->ops->fix_hypercall(ctxt);
if (rc != X86EMUL_CONTINUE)
return rc;
/* Let the processor re-execute the fixed hypercall */
c->eip = ctxt->eip;
/* Disable writeback. */
c->dst.type = OP_NONE;
return X86EMUL_CONTINUE;
}
static int em_lgdt(struct x86_emulate_ctxt *ctxt)
{
struct decode_cache *c = &ctxt->decode;
struct desc_ptr desc_ptr;
int rc;
rc = read_descriptor(ctxt, ctxt->ops, c->src.addr.mem,
&desc_ptr.size, &desc_ptr.address,
c->op_bytes);
if (rc != X86EMUL_CONTINUE)
return rc;
ctxt->ops->set_gdt(ctxt, &desc_ptr);
/* Disable writeback. */
c->dst.type = OP_NONE;
return X86EMUL_CONTINUE;
}
static int em_svm(struct x86_emulate_ctxt *ctxt)
{
struct decode_cache *c = &ctxt->decode;
int rc;
switch (c->modrm_rm) {
case 1:
rc = ctxt->ops->fix_hypercall(ctxt);
break;
default:
return X86EMUL_UNHANDLEABLE;
}
/* Disable writeback. */
c->dst.type = OP_NONE;
return rc;
}
static int em_lidt(struct x86_emulate_ctxt *ctxt)
{
struct decode_cache *c = &ctxt->decode;
struct desc_ptr desc_ptr;
int rc;
rc = read_descriptor(ctxt, ctxt->ops, c->src.addr.mem,
&desc_ptr.size,
&desc_ptr.address,
c->op_bytes);
if (rc != X86EMUL_CONTINUE)
return rc;
ctxt->ops->set_idt(ctxt, &desc_ptr);
/* Disable writeback. */
c->dst.type = OP_NONE;
return X86EMUL_CONTINUE;
}
static int em_smsw(struct x86_emulate_ctxt *ctxt)
{
struct decode_cache *c = &ctxt->decode;
c->dst.bytes = 2;
c->dst.val = ctxt->ops->get_cr(ctxt, 0);
return X86EMUL_CONTINUE;
}
static int em_lmsw(struct x86_emulate_ctxt *ctxt)
{
struct decode_cache *c = &ctxt->decode;
ctxt->ops->set_cr(ctxt, 0, (ctxt->ops->get_cr(ctxt, 0) & ~0x0eul)
| (c->src.val & 0x0f));
c->dst.type = OP_NONE;
return X86EMUL_CONTINUE;
}
static bool valid_cr(int nr) static bool valid_cr(int nr)
{ {
switch (nr) { switch (nr) {
...@@ -3509,7 +3598,6 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt) ...@@ -3509,7 +3598,6 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
int rc = X86EMUL_CONTINUE; int rc = X86EMUL_CONTINUE;
int saved_dst_type = c->dst.type; int saved_dst_type = c->dst.type;
int irq; /* Used for int 3, int, and into */ int irq; /* Used for int 3, int, and into */
struct desc_ptr desc_ptr;
ctxt->decode.mem_read.pos = 0; ctxt->decode.mem_read.pos = 0;
...@@ -4022,62 +4110,26 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt) ...@@ -4022,62 +4110,26 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
case 0x01: /* lgdt, lidt, lmsw */ case 0x01: /* lgdt, lidt, lmsw */
switch (c->modrm_reg) { switch (c->modrm_reg) {
case 0: /* vmcall */ case 0: /* vmcall */
if (c->modrm_mod != 3 || c->modrm_rm != 1) rc = em_vmcall(ctxt);
goto cannot_emulate;
rc = ctxt->ops->fix_hypercall(ctxt);
if (rc != X86EMUL_CONTINUE)
goto done;
/* Let the processor re-execute the fixed hypercall */
c->eip = ctxt->eip;
/* Disable writeback. */
c->dst.type = OP_NONE;
break; break;
case 2: /* lgdt */ case 2: /* lgdt */
rc = read_descriptor(ctxt, ops, c->src.addr.mem, rc = em_lgdt(ctxt);
&desc_ptr.size, &desc_ptr.address,
c->op_bytes);
if (rc != X86EMUL_CONTINUE)
goto done;
ctxt->ops->set_gdt(ctxt, &desc_ptr);
/* Disable writeback. */
c->dst.type = OP_NONE;
break; break;
case 3: /* lidt/vmmcall */ case 3: /* lidt/vmmcall */
if (c->modrm_mod == 3) { if (c->modrm_mod == 3)
switch (c->modrm_rm) { return em_svm(ctxt);
case 1: else
rc = ctxt->ops->fix_hypercall(ctxt); return em_lidt(ctxt);
break;
default:
goto cannot_emulate;
}
} else {
rc = read_descriptor(ctxt, ops, c->src.addr.mem,
&desc_ptr.size,
&desc_ptr.address,
c->op_bytes);
if (rc != X86EMUL_CONTINUE)
goto done;
ctxt->ops->set_idt(ctxt, &desc_ptr);
}
/* Disable writeback. */
c->dst.type = OP_NONE;
break; break;
case 4: /* smsw */ case 4: /* smsw */
c->dst.bytes = 2; rc = em_smsw(ctxt);
c->dst.val = ops->get_cr(ctxt, 0);
break; break;
case 6: /* lmsw */ case 6: /* lmsw */
ops->set_cr(ctxt, 0, (ops->get_cr(ctxt, 0) & ~0x0eul) | rc = em_lmsw(ctxt);
(c->src.val & 0x0f));
c->dst.type = OP_NONE;
break; break;
case 5: /* not defined */ case 5: /* not defined */
emulate_ud(ctxt); rc = emulate_ud(ctxt);
rc = X86EMUL_PROPAGATE_FAULT; break;
goto done;
case 7: /* invlpg*/ case 7: /* invlpg*/
rc = em_invlpg(ctxt); rc = em_invlpg(ctxt);
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment