|
@@ -4136,6 +4136,78 @@ int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa,
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
+struct read_write_emulator_ops {
|
|
|
+ int (*read_write_prepare)(struct kvm_vcpu *vcpu, void *val,
|
|
|
+ int bytes);
|
|
|
+ int (*read_write_emulate)(struct kvm_vcpu *vcpu, gpa_t gpa,
|
|
|
+ void *val, int bytes);
|
|
|
+ int (*read_write_mmio)(struct kvm_vcpu *vcpu, gpa_t gpa,
|
|
|
+ int bytes, void *val);
|
|
|
+ int (*read_write_exit_mmio)(struct kvm_vcpu *vcpu, gpa_t gpa,
|
|
|
+ void *val, int bytes);
|
|
|
+ bool write;
|
|
|
+};
|
|
|
+
|
|
|
+static int read_prepare(struct kvm_vcpu *vcpu, void *val, int bytes)
|
|
|
+{
|
|
|
+ if (vcpu->mmio_read_completed) {
|
|
|
+ memcpy(val, vcpu->mmio_data, bytes);
|
|
|
+ trace_kvm_mmio(KVM_TRACE_MMIO_READ, bytes,
|
|
|
+ vcpu->mmio_phys_addr, *(u64 *)val);
|
|
|
+ vcpu->mmio_read_completed = 0;
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int read_emulate(struct kvm_vcpu *vcpu, gpa_t gpa,
|
|
|
+ void *val, int bytes)
|
|
|
+{
|
|
|
+ return !kvm_read_guest(vcpu->kvm, gpa, val, bytes);
|
|
|
+}
|
|
|
+
|
|
|
+static int write_emulate(struct kvm_vcpu *vcpu, gpa_t gpa,
|
|
|
+ void *val, int bytes)
|
|
|
+{
|
|
|
+ return emulator_write_phys(vcpu, gpa, val, bytes);
|
|
|
+}
|
|
|
+
|
|
|
+static int write_mmio(struct kvm_vcpu *vcpu, gpa_t gpa, int bytes, void *val)
|
|
|
+{
|
|
|
+ trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, bytes, gpa, *(u64 *)val);
|
|
|
+ return vcpu_mmio_write(vcpu, gpa, bytes, val);
|
|
|
+}
|
|
|
+
|
|
|
+static int read_exit_mmio(struct kvm_vcpu *vcpu, gpa_t gpa,
|
|
|
+ void *val, int bytes)
|
|
|
+{
|
|
|
+ trace_kvm_mmio(KVM_TRACE_MMIO_READ_UNSATISFIED, bytes, gpa, 0);
|
|
|
+ return X86EMUL_IO_NEEDED;
|
|
|
+}
|
|
|
+
|
|
|
+static int write_exit_mmio(struct kvm_vcpu *vcpu, gpa_t gpa,
|
|
|
+ void *val, int bytes)
|
|
|
+{
|
|
|
+ memcpy(vcpu->mmio_data, val, bytes);
|
|
|
+ memcpy(vcpu->run->mmio.data, vcpu->mmio_data, 8);
|
|
|
+ return X86EMUL_CONTINUE;
|
|
|
+}
|
|
|
+
|
|
|
+static struct read_write_emulator_ops read_emultor = {
|
|
|
+ .read_write_prepare = read_prepare,
|
|
|
+ .read_write_emulate = read_emulate,
|
|
|
+ .read_write_mmio = vcpu_mmio_read,
|
|
|
+ .read_write_exit_mmio = read_exit_mmio,
|
|
|
+};
|
|
|
+
|
|
|
+static struct read_write_emulator_ops write_emultor = {
|
|
|
+ .read_write_emulate = write_emulate,
|
|
|
+ .read_write_mmio = write_mmio,
|
|
|
+ .read_write_exit_mmio = write_exit_mmio,
|
|
|
+ .write = true,
|
|
|
+};
|
|
|
+
|
|
|
static int emulator_write_emulated_onepage(unsigned long addr,
|
|
|
const void *val,
|
|
|
unsigned int bytes,
|