Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+46 −12
Original line number Diff line number Diff line
@@ -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,
			   const void *v)
{
	if (vcpu->arch.apic &&
	    !kvm_iodevice_write(&vcpu->arch.apic->dev, addr, len, v))
		return 0;
	int handled = 0;
	int n;

	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)
{
	if (vcpu->arch.apic &&
	    !kvm_iodevice_read(&vcpu->arch.apic->dev, addr, len, v))
		return 0;
	int handled = 0;
	int n;

	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,
@@ -3769,6 +3792,7 @@ static int emulator_read_emulated(unsigned long addr,
				  struct kvm_vcpu *vcpu)
{
	gpa_t                 gpa;
	int handled;

	if (vcpu->mmio_read_completed) {
		memcpy(val, vcpu->mmio_data, bytes);
@@ -3795,10 +3819,14 @@ static int emulator_read_emulated(unsigned long addr,
	/*
	 * Is this MMIO handled locally?
	 */
	if (!vcpu_mmio_read(vcpu, gpa, bytes, val)) {
		trace_kvm_mmio(KVM_TRACE_MMIO_READ, bytes, gpa, *(u64 *)val);
	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);

@@ -3830,6 +3858,7 @@ static int emulator_write_emulated_onepage(unsigned long addr,
					   struct kvm_vcpu *vcpu)
{
	gpa_t                 gpa;
	int handled;

	gpa = kvm_mmu_gva_to_gpa_write(vcpu, addr, exception);

@@ -3848,9 +3877,14 @@ static int emulator_write_emulated_onepage(unsigned long addr,
	/*
	 * 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;

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

	vcpu->mmio_needed = 1;
	vcpu->run->exit_reason = KVM_EXIT_MMIO;
	vcpu->run->mmio.phys_addr = vcpu->mmio_phys_addr = gpa;