KVM: Fix page-crossing MMIO
MMIO that are split across a page boundary are currently broken - the code does not expect to be aborted by the exit to userspace for the first MMIO fragment. This patch fixes the problem by generalizing the current code for handling 16-byte MMIOs to handle a number of "fragments", and changes the MMIO code to create those fragments. Signed-off-by: Avi Kivity <avi@redhat.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
This commit is contained in:

zatwierdzone przez
Marcelo Tosatti

rodzic
eac0556750
commit
f78146b0f9
@@ -449,6 +449,8 @@ struct kvm_vcpu_arch {
|
||||
char log_buf[VMM_LOG_LEN];
|
||||
union context host;
|
||||
union context guest;
|
||||
|
||||
char mmio_data[8];
|
||||
};
|
||||
|
||||
struct kvm_vm_stat {
|
||||
|
@@ -232,12 +232,12 @@ static int handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
|
||||
if ((p->addr & PAGE_MASK) == IOAPIC_DEFAULT_BASE_ADDRESS)
|
||||
goto mmio;
|
||||
vcpu->mmio_needed = 1;
|
||||
vcpu->mmio_phys_addr = kvm_run->mmio.phys_addr = p->addr;
|
||||
vcpu->mmio_size = kvm_run->mmio.len = p->size;
|
||||
vcpu->mmio_fragments[0].gpa = kvm_run->mmio.phys_addr = p->addr;
|
||||
vcpu->mmio_fragments[0].len = kvm_run->mmio.len = p->size;
|
||||
vcpu->mmio_is_write = kvm_run->mmio.is_write = !p->dir;
|
||||
|
||||
if (vcpu->mmio_is_write)
|
||||
memcpy(vcpu->mmio_data, &p->data, p->size);
|
||||
memcpy(vcpu->arch.mmio_data, &p->data, p->size);
|
||||
memcpy(kvm_run->mmio.data, &p->data, p->size);
|
||||
kvm_run->exit_reason = KVM_EXIT_MMIO;
|
||||
return 0;
|
||||
@@ -719,7 +719,7 @@ static void kvm_set_mmio_data(struct kvm_vcpu *vcpu)
|
||||
struct kvm_mmio_req *p = kvm_get_vcpu_ioreq(vcpu);
|
||||
|
||||
if (!vcpu->mmio_is_write)
|
||||
memcpy(&p->data, vcpu->mmio_data, 8);
|
||||
memcpy(&p->data, vcpu->arch.mmio_data, 8);
|
||||
p->state = STATE_IORESP_READY;
|
||||
}
|
||||
|
||||
@@ -739,7 +739,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
|
||||
}
|
||||
|
||||
if (vcpu->mmio_needed) {
|
||||
memcpy(vcpu->mmio_data, kvm_run->mmio.data, 8);
|
||||
memcpy(vcpu->arch.mmio_data, kvm_run->mmio.data, 8);
|
||||
kvm_set_mmio_data(vcpu);
|
||||
vcpu->mmio_read_completed = 1;
|
||||
vcpu->mmio_needed = 0;
|
||||
|
Reference in New Issue
Block a user