Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 80629
b: refs/heads/master
c: 3427318
h: refs/heads/master
i:
  80627: 5a5882b
v: v3
  • Loading branch information
Laurent Vivier authored and Avi Kivity committed Jan 30, 2008
1 parent bcbfe99 commit 63eac34
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 46 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 1be3aa47182e94944e57b176a5c4ee4e74f1ce33
refs/heads/master: 3427318fd2244737a466a06a93c5fe579852f871
8 changes: 7 additions & 1 deletion trunk/drivers/kvm/kvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,8 @@ enum {
VCPU_SREG_LDTR,
};

#include "x86_emulate.h"

struct kvm_pio_request {
unsigned long count;
int cur_count;
Expand Down Expand Up @@ -380,6 +382,10 @@ struct kvm_vcpu {

int cpuid_nent;
struct kvm_cpuid_entry cpuid_entries[KVM_MAX_CPUID_ENTRIES];

/* emulate context */

struct x86_emulate_ctxt emulate_ctxt;
};

struct kvm_mem_alias {
Expand Down Expand Up @@ -555,7 +561,7 @@ enum emulation_result {
};

int emulate_instruction(struct kvm_vcpu *vcpu, struct kvm_run *run,
unsigned long cr2, u16 error_code);
unsigned long cr2, u16 error_code, int no_decode);
void kvm_report_emulation_failure(struct kvm_vcpu *cvpu, const char *context);
void realmode_lgdt(struct kvm_vcpu *vcpu, u16 size, unsigned long address);
void realmode_lidt(struct kvm_vcpu *vcpu, u16 size, unsigned long address);
Expand Down
77 changes: 44 additions & 33 deletions trunk/drivers/kvm/kvm_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1251,45 +1251,56 @@ struct x86_emulate_ops emulate_ops = {
int emulate_instruction(struct kvm_vcpu *vcpu,
struct kvm_run *run,
unsigned long cr2,
u16 error_code)
u16 error_code,
int no_decode)
{
struct x86_emulate_ctxt emulate_ctxt;
int r;
int cs_db, cs_l;
int r = 0;

vcpu->mmio_fault_cr2 = cr2;
kvm_x86_ops->cache_regs(vcpu);

kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l);

emulate_ctxt.vcpu = vcpu;
emulate_ctxt.eflags = kvm_x86_ops->get_rflags(vcpu);
emulate_ctxt.cr2 = cr2;
emulate_ctxt.mode = (emulate_ctxt.eflags & X86_EFLAGS_VM)
? X86EMUL_MODE_REAL : cs_l
? X86EMUL_MODE_PROT64 : cs_db
? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16;

if (emulate_ctxt.mode == X86EMUL_MODE_PROT64) {
emulate_ctxt.cs_base = 0;
emulate_ctxt.ds_base = 0;
emulate_ctxt.es_base = 0;
emulate_ctxt.ss_base = 0;
} else {
emulate_ctxt.cs_base = get_segment_base(vcpu, VCPU_SREG_CS);
emulate_ctxt.ds_base = get_segment_base(vcpu, VCPU_SREG_DS);
emulate_ctxt.es_base = get_segment_base(vcpu, VCPU_SREG_ES);
emulate_ctxt.ss_base = get_segment_base(vcpu, VCPU_SREG_SS);
}

emulate_ctxt.gs_base = get_segment_base(vcpu, VCPU_SREG_GS);
emulate_ctxt.fs_base = get_segment_base(vcpu, VCPU_SREG_FS);

vcpu->mmio_is_write = 0;
vcpu->pio.string = 0;
r = x86_decode_insn(&emulate_ctxt, &emulate_ops);

if (!no_decode) {
int cs_db, cs_l;
kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l);

vcpu->emulate_ctxt.vcpu = vcpu;
vcpu->emulate_ctxt.eflags = kvm_x86_ops->get_rflags(vcpu);
vcpu->emulate_ctxt.cr2 = cr2;
vcpu->emulate_ctxt.mode =
(vcpu->emulate_ctxt.eflags & X86_EFLAGS_VM)
? X86EMUL_MODE_REAL : cs_l
? X86EMUL_MODE_PROT64 : cs_db
? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16;

if (vcpu->emulate_ctxt.mode == X86EMUL_MODE_PROT64) {
vcpu->emulate_ctxt.cs_base = 0;
vcpu->emulate_ctxt.ds_base = 0;
vcpu->emulate_ctxt.es_base = 0;
vcpu->emulate_ctxt.ss_base = 0;
} else {
vcpu->emulate_ctxt.cs_base =
get_segment_base(vcpu, VCPU_SREG_CS);
vcpu->emulate_ctxt.ds_base =
get_segment_base(vcpu, VCPU_SREG_DS);
vcpu->emulate_ctxt.es_base =
get_segment_base(vcpu, VCPU_SREG_ES);
vcpu->emulate_ctxt.ss_base =
get_segment_base(vcpu, VCPU_SREG_SS);
}

vcpu->emulate_ctxt.gs_base =
get_segment_base(vcpu, VCPU_SREG_GS);
vcpu->emulate_ctxt.fs_base =
get_segment_base(vcpu, VCPU_SREG_FS);

r = x86_decode_insn(&vcpu->emulate_ctxt, &emulate_ops);
}

if (r == 0)
r = x86_emulate_insn(&emulate_ctxt, &emulate_ops);
r = x86_emulate_insn(&vcpu->emulate_ctxt, &emulate_ops);

if (vcpu->pio.string)
return EMULATE_DO_MMIO;
Expand All @@ -1313,7 +1324,7 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
}

kvm_x86_ops->decache_regs(vcpu);
kvm_x86_ops->set_rflags(vcpu, emulate_ctxt.eflags);
kvm_x86_ops->set_rflags(vcpu, vcpu->emulate_ctxt.eflags);

if (vcpu->mmio_is_write) {
vcpu->mmio_needed = 0;
Expand Down Expand Up @@ -2055,7 +2066,7 @@ static int kvm_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
vcpu->mmio_read_completed = 1;
vcpu->mmio_needed = 0;
r = emulate_instruction(vcpu, kvm_run,
vcpu->mmio_fault_cr2, 0);
vcpu->mmio_fault_cr2, 0, 1);
if (r == EMULATE_DO_MMIO) {
/*
* Read-modify-write. Back to userspace.
Expand Down
9 changes: 5 additions & 4 deletions trunk/drivers/kvm/svm.c
Original file line number Diff line number Diff line change
Expand Up @@ -960,7 +960,7 @@ static int pf_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
return 1;
}
er = emulate_instruction(&svm->vcpu, kvm_run, fault_address,
error_code);
error_code, 0);
mutex_unlock(&kvm->lock);

switch (er) {
Expand All @@ -984,7 +984,7 @@ static int ud_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
{
int er;

er = emulate_instruction(&svm->vcpu, kvm_run, 0, 0);
er = emulate_instruction(&svm->vcpu, kvm_run, 0, 0, 0);
if (er != EMULATE_DONE)
inject_ud(&svm->vcpu);

Expand Down Expand Up @@ -1027,7 +1027,8 @@ static int io_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
string = (io_info & SVM_IOIO_STR_MASK) != 0;

if (string) {
if (emulate_instruction(&svm->vcpu, kvm_run, 0, 0) == EMULATE_DO_MMIO)
if (emulate_instruction(&svm->vcpu,
kvm_run, 0, 0, 0) == EMULATE_DO_MMIO)
return 0;
return 1;
}
Expand Down Expand Up @@ -1086,7 +1087,7 @@ static int cpuid_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
static int emulate_on_interception(struct vcpu_svm *svm,
struct kvm_run *kvm_run)
{
if (emulate_instruction(&svm->vcpu, NULL, 0, 0) != EMULATE_DONE)
if (emulate_instruction(&svm->vcpu, NULL, 0, 0, 0) != EMULATE_DONE)
pr_unimpl(&svm->vcpu, "%s: failed\n", __FUNCTION__);
return 1;
}
Expand Down
9 changes: 5 additions & 4 deletions trunk/drivers/kvm/vmx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1750,7 +1750,7 @@ static int handle_rmode_exception(struct kvm_vcpu *vcpu,
* Cause the #SS fault with 0 error code in VM86 mode.
*/
if (((vec == GP_VECTOR) || (vec == SS_VECTOR)) && err_code == 0)
if (emulate_instruction(vcpu, NULL, 0, 0) == EMULATE_DONE)
if (emulate_instruction(vcpu, NULL, 0, 0, 0) == EMULATE_DONE)
return 1;
return 0;
}
Expand Down Expand Up @@ -1787,7 +1787,7 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
}

if (is_invalid_opcode(intr_info)) {
er = emulate_instruction(vcpu, kvm_run, 0, 0);
er = emulate_instruction(vcpu, kvm_run, 0, 0, 0);
if (er != EMULATE_DONE)
vmx_inject_ud(vcpu);

Expand All @@ -1812,7 +1812,7 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
return 1;
}

er = emulate_instruction(vcpu, kvm_run, cr2, error_code);
er = emulate_instruction(vcpu, kvm_run, cr2, error_code, 0);
mutex_unlock(&vcpu->kvm->lock);

switch (er) {
Expand Down Expand Up @@ -1873,7 +1873,8 @@ static int handle_io(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
string = (exit_qualification & 16) != 0;

if (string) {
if (emulate_instruction(vcpu, kvm_run, 0, 0) == EMULATE_DO_MMIO)
if (emulate_instruction(vcpu,
kvm_run, 0, 0, 0) == EMULATE_DO_MMIO)
return 0;
return 1;
}
Expand Down
24 changes: 21 additions & 3 deletions trunk/drivers/kvm/x86_emulate.c
Original file line number Diff line number Diff line change
Expand Up @@ -913,10 +913,19 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
unsigned long cr2 = ctxt->cr2;
int no_wb = 0;
u64 msr_data;
unsigned long saved_eip = 0;
unsigned long _eflags = ctxt->eflags;
struct decode_cache *c = &ctxt->decode;
int rc = 0;

/* Shadow copy of register state. Committed on successful emulation.
* NOTE: we can copy them from vcpu as x86_decode_insn() doesn't
* modify them.
*/

memcpy(c->regs, ctxt->vcpu->regs, sizeof c->regs);
saved_eip = c->eip;

if ((c->d & ModRM) && (c->modrm_mod != 3))
cr2 = c->modrm_ea;

Expand Down Expand Up @@ -1250,7 +1259,11 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
ctxt->vcpu->rip = c->eip;

done:
return (rc == X86EMUL_UNHANDLEABLE) ? -1 : 0;
if (rc == X86EMUL_UNHANDLEABLE) {
c->eip = saved_eip;
return -1;
}
return 0;

special_insn:
if (c->twobyte)
Expand Down Expand Up @@ -1305,8 +1318,10 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
register_address(ctxt->es_base,
c->regs[VCPU_REGS_RDI]),
c->rep_prefix,
c->regs[VCPU_REGS_RDX]) == 0)
c->regs[VCPU_REGS_RDX]) == 0) {
c->eip = saved_eip;
return -1;
}
return 0;
case 0x6e: /* outsb */
case 0x6f: /* outsw/outsd */
Expand All @@ -1321,8 +1336,10 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
ctxt->ds_base,
c->regs[VCPU_REGS_RSI]),
c->rep_prefix,
c->regs[VCPU_REGS_RDX]) == 0)
c->regs[VCPU_REGS_RDX]) == 0) {
c->eip = saved_eip;
return -1;
}
return 0;
case 0x70 ... 0x7f: /* jcc (short) */ {
int rel = insn_fetch(s8, 1, c->eip);
Expand Down Expand Up @@ -1711,5 +1728,6 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)

cannot_emulate:
DPRINTF("Cannot emulate %02x\n", c->b);
c->eip = saved_eip;
return -1;
}

0 comments on commit 63eac34

Please sign in to comment.