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

Commit cef4dea0 authored by Avi Kivity's avatar Avi Kivity
Browse files

KVM: 16-byte mmio support



Since sse instructions can issue 16-byte mmios, we need to support them.  We
can't increase the kvm_run mmio buffer size to 16 bytes without breaking
compatibility, so instead we break the large mmios into two smaller 8-byte
ones.  Since the bus is 64-bit we aren't breaking any atomicity guarantees.

Signed-off-by: default avatarAvi Kivity <avi@redhat.com>
parent 5287f194
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
#define KVM_MEMORY_SLOTS 32
/* memory slots that does not exposed to userspace */
#define KVM_PRIVATE_MEM_SLOTS 4
#define KVM_MMIO_SIZE 16

#define KVM_PIO_PAGE_OFFSET 1
#define KVM_COALESCED_MMIO_PAGE_OFFSET 2
+25 −9
Original line number Diff line number Diff line
@@ -3833,8 +3833,10 @@ static int emulator_read_emulated(unsigned long addr,
	vcpu->mmio_needed = 1;
	vcpu->run->exit_reason = KVM_EXIT_MMIO;
	vcpu->run->mmio.phys_addr = vcpu->mmio_phys_addr = gpa;
	vcpu->run->mmio.len = vcpu->mmio_size = bytes;
	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;
}
@@ -3886,11 +3888,14 @@ 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->run->mmio.len = vcpu->mmio_size = bytes;
	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, val, bytes);
	memcpy(vcpu->run->mmio.data, vcpu->mmio_data, 8);
	vcpu->mmio_index = 0;

	return X86EMUL_CONTINUE;
}
@@ -4498,11 +4503,9 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu,
		if (!vcpu->arch.pio.in)
			vcpu->arch.pio.count = 0;
		r = EMULATE_DO_MMIO;
	} else if (vcpu->mmio_needed) {
		if (vcpu->mmio_is_write)
			vcpu->mmio_needed = 0;
	} else if (vcpu->mmio_needed)
		r = EMULATE_DO_MMIO;
	} else if (r == EMULATION_RESTART)
	else if (r == EMULATION_RESTART)
		goto restart;
	else
		r = EMULATE_DONE;
@@ -5450,9 +5453,22 @@ static int complete_mmio(struct kvm_vcpu *vcpu)
		return 1;

	if (vcpu->mmio_needed) {
		vcpu->mmio_needed = 0;
		if (!vcpu->mmio_is_write)
			memcpy(vcpu->mmio_data, run->mmio.data, 8);
		vcpu->mmio_index += 8;
		if (vcpu->mmio_index < vcpu->mmio_size) {
			run->exit_reason = KVM_EXIT_MMIO;
			run->mmio.phys_addr = vcpu->mmio_phys_addr + vcpu->mmio_index;
			memcpy(run->mmio.data, vcpu->mmio_data + vcpu->mmio_index, 8);
			run->mmio.len = min(vcpu->mmio_size - vcpu->mmio_index, 8);
			run->mmio.is_write = vcpu->mmio_is_write;
			vcpu->mmio_needed = 1;
			return 0;
		}
		if (vcpu->mmio_is_write)
			return 1;
		vcpu->mmio_read_completed = 1;
		vcpu->mmio_needed = 0;
	}
	vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
	r = emulate_instruction(vcpu, EMULTYPE_NO_DECODE);
+6 −1
Original line number Diff line number Diff line
@@ -27,6 +27,10 @@

#include <asm/kvm_host.h>

#ifndef KVM_MMIO_SIZE
#define KVM_MMIO_SIZE 8
#endif

/*
 * vcpu->requests bit members
 */
@@ -132,7 +136,8 @@ struct kvm_vcpu {
	int mmio_read_completed;
	int mmio_is_write;
	int mmio_size;
	unsigned char mmio_data[8];
	int mmio_index;
	unsigned char mmio_data[KVM_MMIO_SIZE];
	gpa_t mmio_phys_addr;
#endif