Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/torvalds/linux.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2022-06-15 18:05:06 +0300
committerPaolo Bonzini <pbonzini@redhat.com>2022-06-24 19:53:37 +0300
commit35ab3b77a0ae76246dd2666d4f8190c824392fb4 (patch)
tree6f17260e675b1f6c80ee64fa7358293c6c071e6c /arch/x86/kvm/x86.c
parent0f87ac234d98c68e4b2bfde6a8bcdeef3d3f54b7 (diff)
KVM: x86: drop PIO from unregistered devices
KVM protects the device list with SRCU, and therefore different calls to kvm_io_bus_read()/kvm_io_bus_write() can very well see different incarnations of kvm->buses. If userspace unregisters a device while vCPUs are running there is no well-defined result. This patch applies a safe fallback by returning early from emulator_pio_in_out(). This corresponds to returning zeroes from IN, and dropping the writes on the floor for OUT. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'arch/x86/kvm/x86.c')
-rw-r--r--arch/x86/kvm/x86.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 524a96d26399..5a56d39bd81f 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -7593,8 +7593,19 @@ static int emulator_pio_in_out(struct kvm_vcpu *vcpu, int size,
r = kvm_io_bus_read(vcpu, KVM_PIO_BUS, port, size, data);
else
r = kvm_io_bus_write(vcpu, KVM_PIO_BUS, port, size, data);
- if (r)
- goto userspace_io;
+
+ if (r) {
+ if (i == 0)
+ goto userspace_io;
+
+ /*
+ * Userspace must have unregistered the device while PIO
+ * was running. Drop writes / read as 0 (the buffer
+ * was zeroed in __emulator_pio_in).
+ */
+ break;
+ }
+
data += size;
}
return 1;
@@ -7606,7 +7617,6 @@ userspace_io:
vcpu->run->io.data_offset = KVM_PIO_PAGE_OFFSET * PAGE_SIZE;
vcpu->run->io.count = count;
vcpu->run->io.port = port;
-
return 0;
}