Skip to content

Commit

Permalink
KVM: x86: cleanup the code of read/write emulation
Browse files Browse the repository at this point in the history
Using the read/write operation to remove the same code

Signed-off-by: Xiao Guangrong <[email protected]>
Signed-off-by: Avi Kivity <[email protected]>
  • Loading branch information
Xiao Guangrong authored and avikivity committed Sep 25, 2011
1 parent 77d197b commit 22388a3
Showing 1 changed file with 45 additions and 101 deletions.
146 changes: 45 additions & 101 deletions arch/x86/kvm/x86.c
Original file line number Diff line number Diff line change
Expand Up @@ -4045,85 +4045,6 @@ static int vcpu_mmio_gva_to_gpa(struct kvm_vcpu *vcpu, unsigned long gva,
return 0;
}

static int emulator_read_emulated_onepage(unsigned long addr,
void *val,
unsigned int bytes,
struct x86_exception *exception,
struct kvm_vcpu *vcpu)
{
gpa_t gpa;
int handled, ret;

if (vcpu->mmio_read_completed) {
memcpy(val, vcpu->mmio_data, bytes);
trace_kvm_mmio(KVM_TRACE_MMIO_READ, bytes,
vcpu->mmio_phys_addr, *(u64 *)val);
vcpu->mmio_read_completed = 0;
return X86EMUL_CONTINUE;
}

ret = vcpu_mmio_gva_to_gpa(vcpu, addr, &gpa, exception, false);

if (ret < 0)
return X86EMUL_PROPAGATE_FAULT;

if (ret)
goto mmio;

if (!kvm_read_guest(vcpu->kvm, gpa, val, bytes))
return X86EMUL_CONTINUE;

mmio:
/*
* Is this MMIO handled locally?
*/
handled = vcpu_mmio_read(vcpu, gpa, bytes, val);

if (handled == bytes)
return X86EMUL_CONTINUE;

gpa += handled;
bytes -= handled;
val += handled;

trace_kvm_mmio(KVM_TRACE_MMIO_READ_UNSATISFIED, bytes, gpa, 0);

vcpu->mmio_needed = 1;
vcpu->run->exit_reason = KVM_EXIT_MMIO;
vcpu->run->mmio.phys_addr = vcpu->mmio_phys_addr = gpa;
vcpu->mmio_size = bytes;
vcpu->run->mmio.len = min(vcpu->mmio_size, 8);
vcpu->run->mmio.is_write = vcpu->mmio_is_write = 0;
vcpu->mmio_index = 0;

return X86EMUL_IO_NEEDED;
}

static int emulator_read_emulated(struct x86_emulate_ctxt *ctxt,
unsigned long addr,
void *val,
unsigned int bytes,
struct x86_exception *exception)
{
struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);

/* Crossing a page boundary? */
if (((addr + bytes - 1) ^ addr) & PAGE_MASK) {
int rc, now;

now = -addr & ~PAGE_MASK;
rc = emulator_read_emulated_onepage(addr, val, now, exception,
vcpu);
if (rc != X86EMUL_CONTINUE)
return rc;
addr += now;
val += now;
bytes -= now;
}
return emulator_read_emulated_onepage(addr, val, bytes, exception,
vcpu);
}

int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa,
const void *val, int bytes)
{
Expand Down Expand Up @@ -4208,16 +4129,21 @@ static struct read_write_emulator_ops write_emultor = {
.write = true,
};

static int emulator_write_emulated_onepage(unsigned long addr,
const void *val,
unsigned int bytes,
struct x86_exception *exception,
struct kvm_vcpu *vcpu)
static int emulator_read_write_onepage(unsigned long addr, void *val,
unsigned int bytes,
struct x86_exception *exception,
struct kvm_vcpu *vcpu,
struct read_write_emulator_ops *ops)
{
gpa_t gpa;
int handled, ret;
bool write = ops->write;

if (ops->read_write_prepare &&
ops->read_write_prepare(vcpu, val, bytes))
return X86EMUL_CONTINUE;

ret = vcpu_mmio_gva_to_gpa(vcpu, addr, &gpa, exception, true);
ret = vcpu_mmio_gva_to_gpa(vcpu, addr, &gpa, exception, write);

if (ret < 0)
return X86EMUL_PROPAGATE_FAULT;
Expand All @@ -4226,15 +4152,14 @@ static int emulator_write_emulated_onepage(unsigned long addr,
if (ret)
goto mmio;

if (emulator_write_phys(vcpu, gpa, val, bytes))
if (ops->read_write_emulate(vcpu, gpa, val, bytes))
return X86EMUL_CONTINUE;

mmio:
trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, bytes, gpa, *(u64 *)val);
/*
* Is this MMIO handled locally?
*/
handled = vcpu_mmio_write(vcpu, gpa, bytes, val);
handled = ops->read_write_mmio(vcpu, gpa, bytes, val);
if (handled == bytes)
return X86EMUL_CONTINUE;

Expand All @@ -4243,23 +4168,20 @@ static int emulator_write_emulated_onepage(unsigned long addr,
val += handled;

vcpu->mmio_needed = 1;
memcpy(vcpu->mmio_data, val, bytes);
vcpu->run->exit_reason = KVM_EXIT_MMIO;
vcpu->run->mmio.phys_addr = vcpu->mmio_phys_addr = gpa;
vcpu->mmio_size = bytes;
vcpu->run->mmio.len = min(vcpu->mmio_size, 8);
vcpu->run->mmio.is_write = vcpu->mmio_is_write = 1;
memcpy(vcpu->run->mmio.data, vcpu->mmio_data, 8);
vcpu->run->mmio.is_write = vcpu->mmio_is_write = write;
vcpu->mmio_index = 0;

return X86EMUL_CONTINUE;
return ops->read_write_exit_mmio(vcpu, gpa, val, bytes);
}

int emulator_write_emulated(struct x86_emulate_ctxt *ctxt,
unsigned long addr,
const void *val,
unsigned int bytes,
struct x86_exception *exception)
int emulator_read_write(struct x86_emulate_ctxt *ctxt, unsigned long addr,
void *val, unsigned int bytes,
struct x86_exception *exception,
struct read_write_emulator_ops *ops)
{
struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);

Expand All @@ -4268,16 +4190,38 @@ int emulator_write_emulated(struct x86_emulate_ctxt *ctxt,
int rc, now;

now = -addr & ~PAGE_MASK;
rc = emulator_write_emulated_onepage(addr, val, now, exception,
vcpu);
rc = emulator_read_write_onepage(addr, val, now, exception,
vcpu, ops);

if (rc != X86EMUL_CONTINUE)
return rc;
addr += now;
val += now;
bytes -= now;
}
return emulator_write_emulated_onepage(addr, val, bytes, exception,
vcpu);

return emulator_read_write_onepage(addr, val, bytes, exception,
vcpu, ops);
}

static int emulator_read_emulated(struct x86_emulate_ctxt *ctxt,
unsigned long addr,
void *val,
unsigned int bytes,
struct x86_exception *exception)
{
return emulator_read_write(ctxt, addr, val, bytes,
exception, &read_emultor);
}

int emulator_write_emulated(struct x86_emulate_ctxt *ctxt,
unsigned long addr,
const void *val,
unsigned int bytes,
struct x86_exception *exception)
{
return emulator_read_write(ctxt, addr, (void *)val, bytes,
exception, &write_emultor);
}

#define CMPXCHG_TYPE(t, ptr, old, new) \
Expand Down

0 comments on commit 22388a3

Please sign in to comment.