Commit 70252a10 authored by Avi Kivity's avatar Avi Kivity

KVM: extend in-kernel mmio to handle >8 byte transactions

Needed for coalesced mmio using sse.
Signed-off-by: default avatarAvi Kivity <avi@redhat.com>
parent 1499e54a
...@@ -3596,20 +3596,43 @@ static void kvm_init_msr_list(void) ...@@ -3596,20 +3596,43 @@ static void kvm_init_msr_list(void)
static int vcpu_mmio_write(struct kvm_vcpu *vcpu, gpa_t addr, int len, static int vcpu_mmio_write(struct kvm_vcpu *vcpu, gpa_t addr, int len,
const void *v) const void *v)
{ {
if (vcpu->arch.apic && int handled = 0;
!kvm_iodevice_write(&vcpu->arch.apic->dev, addr, len, v)) int n;
return 0;
do {
n = min(len, 8);
if (!(vcpu->arch.apic &&
!kvm_iodevice_write(&vcpu->arch.apic->dev, addr, n, v))
&& kvm_io_bus_write(vcpu->kvm, KVM_MMIO_BUS, addr, n, v))
break;
handled += n;
addr += n;
len -= n;
v += n;
} while (len);
return kvm_io_bus_write(vcpu->kvm, KVM_MMIO_BUS, addr, len, v); return handled;
} }
static int vcpu_mmio_read(struct kvm_vcpu *vcpu, gpa_t addr, int len, void *v) static int vcpu_mmio_read(struct kvm_vcpu *vcpu, gpa_t addr, int len, void *v)
{ {
if (vcpu->arch.apic && int handled = 0;
!kvm_iodevice_read(&vcpu->arch.apic->dev, addr, len, v)) int n;
return 0;
do {
n = min(len, 8);
if (!(vcpu->arch.apic &&
!kvm_iodevice_read(&vcpu->arch.apic->dev, addr, n, v))
&& kvm_io_bus_read(vcpu->kvm, KVM_MMIO_BUS, addr, n, v))
break;
trace_kvm_mmio(KVM_TRACE_MMIO_READ, n, addr, *(u64 *)v);
handled += n;
addr += n;
len -= n;
v += n;
} while (len);
return kvm_io_bus_read(vcpu->kvm, KVM_MMIO_BUS, addr, len, v); return handled;
} }
static void kvm_set_segment(struct kvm_vcpu *vcpu, static void kvm_set_segment(struct kvm_vcpu *vcpu,
...@@ -3769,6 +3792,7 @@ static int emulator_read_emulated(unsigned long addr, ...@@ -3769,6 +3792,7 @@ static int emulator_read_emulated(unsigned long addr,
struct kvm_vcpu *vcpu) struct kvm_vcpu *vcpu)
{ {
gpa_t gpa; gpa_t gpa;
int handled;
if (vcpu->mmio_read_completed) { if (vcpu->mmio_read_completed) {
memcpy(val, vcpu->mmio_data, bytes); memcpy(val, vcpu->mmio_data, bytes);
...@@ -3795,10 +3819,14 @@ static int emulator_read_emulated(unsigned long addr, ...@@ -3795,10 +3819,14 @@ static int emulator_read_emulated(unsigned long addr,
/* /*
* Is this MMIO handled locally? * Is this MMIO handled locally?
*/ */
if (!vcpu_mmio_read(vcpu, gpa, bytes, val)) { handled = vcpu_mmio_read(vcpu, gpa, bytes, val);
trace_kvm_mmio(KVM_TRACE_MMIO_READ, bytes, gpa, *(u64 *)val);
if (handled == bytes)
return X86EMUL_CONTINUE; return X86EMUL_CONTINUE;
}
gpa += handled;
bytes -= handled;
val += handled;
trace_kvm_mmio(KVM_TRACE_MMIO_READ_UNSATISFIED, bytes, gpa, 0); trace_kvm_mmio(KVM_TRACE_MMIO_READ_UNSATISFIED, bytes, gpa, 0);
...@@ -3830,6 +3858,7 @@ static int emulator_write_emulated_onepage(unsigned long addr, ...@@ -3830,6 +3858,7 @@ static int emulator_write_emulated_onepage(unsigned long addr,
struct kvm_vcpu *vcpu) struct kvm_vcpu *vcpu)
{ {
gpa_t gpa; gpa_t gpa;
int handled;
gpa = kvm_mmu_gva_to_gpa_write(vcpu, addr, exception); gpa = kvm_mmu_gva_to_gpa_write(vcpu, addr, exception);
...@@ -3848,9 +3877,14 @@ static int emulator_write_emulated_onepage(unsigned long addr, ...@@ -3848,9 +3877,14 @@ static int emulator_write_emulated_onepage(unsigned long addr,
/* /*
* Is this MMIO handled locally? * Is this MMIO handled locally?
*/ */
if (!vcpu_mmio_write(vcpu, gpa, bytes, val)) handled = vcpu_mmio_write(vcpu, gpa, bytes, val);
if (handled == bytes)
return X86EMUL_CONTINUE; return X86EMUL_CONTINUE;
gpa += handled;
bytes -= handled;
val += handled;
vcpu->mmio_needed = 1; vcpu->mmio_needed = 1;
vcpu->run->exit_reason = KVM_EXIT_MMIO; vcpu->run->exit_reason = KVM_EXIT_MMIO;
vcpu->run->mmio.phys_addr = vcpu->mmio_phys_addr = gpa; vcpu->run->mmio.phys_addr = vcpu->mmio_phys_addr = gpa;
......
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