KVM: introduce kvm_read_guest_virt, kvm_write_guest_virt
This commit change the name of emulator_read_std into kvm_read_guest_virt, and add new function name kvm_write_guest_virt that allow writing into a guest virtual address. Signed-off-by: Izik Eidus <ieidus@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com>
This commit is contained in:
parent
53f658b3c3
commit
77c2002e7c
2 changed files with 42 additions and 18 deletions
|
@ -609,10 +609,6 @@ void kvm_inject_nmi(struct kvm_vcpu *vcpu);
|
||||||
|
|
||||||
void fx_init(struct kvm_vcpu *vcpu);
|
void fx_init(struct kvm_vcpu *vcpu);
|
||||||
|
|
||||||
int emulator_read_std(unsigned long addr,
|
|
||||||
void *val,
|
|
||||||
unsigned int bytes,
|
|
||||||
struct kvm_vcpu *vcpu);
|
|
||||||
int emulator_write_emulated(unsigned long addr,
|
int emulator_write_emulated(unsigned long addr,
|
||||||
const void *val,
|
const void *val,
|
||||||
unsigned int bytes,
|
unsigned int bytes,
|
||||||
|
|
|
@ -1976,9 +1976,7 @@ static struct kvm_io_device *vcpu_find_mmio_dev(struct kvm_vcpu *vcpu,
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
int emulator_read_std(unsigned long addr,
|
int kvm_read_guest_virt(gva_t addr, void *val, unsigned int bytes,
|
||||||
void *val,
|
|
||||||
unsigned int bytes,
|
|
||||||
struct kvm_vcpu *vcpu)
|
struct kvm_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
void *data = val;
|
void *data = val;
|
||||||
|
@ -1987,27 +1985,57 @@ int emulator_read_std(unsigned long addr,
|
||||||
while (bytes) {
|
while (bytes) {
|
||||||
gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr);
|
gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr);
|
||||||
unsigned offset = addr & (PAGE_SIZE-1);
|
unsigned offset = addr & (PAGE_SIZE-1);
|
||||||
unsigned tocopy = min(bytes, (unsigned)PAGE_SIZE - offset);
|
unsigned toread = min(bytes, (unsigned)PAGE_SIZE - offset);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (gpa == UNMAPPED_GVA) {
|
if (gpa == UNMAPPED_GVA) {
|
||||||
r = X86EMUL_PROPAGATE_FAULT;
|
r = X86EMUL_PROPAGATE_FAULT;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
ret = kvm_read_guest(vcpu->kvm, gpa, data, tocopy);
|
ret = kvm_read_guest(vcpu->kvm, gpa, data, toread);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
r = X86EMUL_UNHANDLEABLE;
|
r = X86EMUL_UNHANDLEABLE;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes -= tocopy;
|
bytes -= toread;
|
||||||
data += tocopy;
|
data += toread;
|
||||||
addr += tocopy;
|
addr += toread;
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(emulator_read_std);
|
|
||||||
|
int kvm_write_guest_virt(gva_t addr, void *val, unsigned int bytes,
|
||||||
|
struct kvm_vcpu *vcpu)
|
||||||
|
{
|
||||||
|
void *data = val;
|
||||||
|
int r = X86EMUL_CONTINUE;
|
||||||
|
|
||||||
|
while (bytes) {
|
||||||
|
gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr);
|
||||||
|
unsigned offset = addr & (PAGE_SIZE-1);
|
||||||
|
unsigned towrite = min(bytes, (unsigned)PAGE_SIZE - offset);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (gpa == UNMAPPED_GVA) {
|
||||||
|
r = X86EMUL_PROPAGATE_FAULT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
ret = kvm_write_guest(vcpu->kvm, gpa, data, towrite);
|
||||||
|
if (ret < 0) {
|
||||||
|
r = X86EMUL_UNHANDLEABLE;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes -= towrite;
|
||||||
|
data += towrite;
|
||||||
|
addr += towrite;
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int emulator_read_emulated(unsigned long addr,
|
static int emulator_read_emulated(unsigned long addr,
|
||||||
void *val,
|
void *val,
|
||||||
|
@ -2029,7 +2057,7 @@ static int emulator_read_emulated(unsigned long addr,
|
||||||
if ((gpa & PAGE_MASK) == APIC_DEFAULT_PHYS_BASE)
|
if ((gpa & PAGE_MASK) == APIC_DEFAULT_PHYS_BASE)
|
||||||
goto mmio;
|
goto mmio;
|
||||||
|
|
||||||
if (emulator_read_std(addr, val, bytes, vcpu)
|
if (kvm_read_guest_virt(addr, val, bytes, vcpu)
|
||||||
== X86EMUL_CONTINUE)
|
== X86EMUL_CONTINUE)
|
||||||
return X86EMUL_CONTINUE;
|
return X86EMUL_CONTINUE;
|
||||||
if (gpa == UNMAPPED_GVA)
|
if (gpa == UNMAPPED_GVA)
|
||||||
|
@ -2233,7 +2261,7 @@ void kvm_report_emulation_failure(struct kvm_vcpu *vcpu, const char *context)
|
||||||
|
|
||||||
rip_linear = rip + get_segment_base(vcpu, VCPU_SREG_CS);
|
rip_linear = rip + get_segment_base(vcpu, VCPU_SREG_CS);
|
||||||
|
|
||||||
emulator_read_std(rip_linear, (void *)opcodes, 4, vcpu);
|
kvm_read_guest_virt(rip_linear, (void *)opcodes, 4, vcpu);
|
||||||
|
|
||||||
printk(KERN_ERR "emulation failed (%s) rip %lx %02x %02x %02x %02x\n",
|
printk(KERN_ERR "emulation failed (%s) rip %lx %02x %02x %02x %02x\n",
|
||||||
context, rip, opcodes[0], opcodes[1], opcodes[2], opcodes[3]);
|
context, rip, opcodes[0], opcodes[1], opcodes[2], opcodes[3]);
|
||||||
|
@ -2241,7 +2269,7 @@ void kvm_report_emulation_failure(struct kvm_vcpu *vcpu, const char *context)
|
||||||
EXPORT_SYMBOL_GPL(kvm_report_emulation_failure);
|
EXPORT_SYMBOL_GPL(kvm_report_emulation_failure);
|
||||||
|
|
||||||
static struct x86_emulate_ops emulate_ops = {
|
static struct x86_emulate_ops emulate_ops = {
|
||||||
.read_std = emulator_read_std,
|
.read_std = kvm_read_guest_virt,
|
||||||
.read_emulated = emulator_read_emulated,
|
.read_emulated = emulator_read_emulated,
|
||||||
.write_emulated = emulator_write_emulated,
|
.write_emulated = emulator_write_emulated,
|
||||||
.cmpxchg_emulated = emulator_cmpxchg_emulated,
|
.cmpxchg_emulated = emulator_cmpxchg_emulated,
|
||||||
|
|
Loading…
Add table
Reference in a new issue