mirror of
https://github.com/torvalds/linux.git
synced 2024-11-16 17:12:06 +00:00
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: Avi Kivity <avi@redhat.com>
This commit is contained in:
parent
5287f194bf
commit
cef4dea07f
@ -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
|
||||
|
@ -3833,8 +3833,10 @@ mmio:
|
||||
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 @@ mmio:
|
||||
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 @@ restart:
|
||||
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) {
|
||||
memcpy(vcpu->mmio_data, run->mmio.data, 8);
|
||||
vcpu->mmio_read_completed = 1;
|
||||
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->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
|
||||
r = emulate_instruction(vcpu, EMULTYPE_NO_DECODE);
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user