return 0;
}
-int kvm_sev_es_mmio_write(struct kvm_vcpu *vcpu, gpa_t gpa, unsigned int bytes,
- void *data)
+static int kvm_sev_es_do_mmio(struct kvm_vcpu *vcpu, gpa_t gpa,
+ unsigned int bytes, void *data,
+ const struct read_write_emulator_ops *ops)
{
- int handled;
struct kvm_mmio_fragment *frag;
+ int handled;
if (!data || WARN_ON_ONCE(object_is_on_stack(data)))
return -EINVAL;
- handled = write_emultor.read_write_mmio(vcpu, gpa, bytes, data);
+ handled = ops->read_write_mmio(vcpu, gpa, bytes, data);
if (handled == bytes)
return 1;
gpa += handled;
data += handled;
- /*TODO: Check if need to increment number of frags */
+ /*
+ * TODO: Determine whether or not userspace plays nice with MMIO
+ * requests that split a page boundary.
+ */
frag = vcpu->mmio_fragments;
vcpu->mmio_nr_fragments = 1;
frag->len = bytes;
vcpu->run->mmio.phys_addr = gpa;
vcpu->run->mmio.len = min(8u, frag->len);
- vcpu->run->mmio.is_write = 1;
- memcpy(vcpu->run->mmio.data, frag->data, min(8u, frag->len));
+ vcpu->run->mmio.is_write = ops->write;
+ if (ops->write)
+ memcpy(vcpu->run->mmio.data, frag->data, min(8u, frag->len));
vcpu->run->exit_reason = KVM_EXIT_MMIO;
vcpu->arch.complete_userspace_io = complete_sev_es_emulated_mmio;
return 0;
}
+
+int kvm_sev_es_mmio_write(struct kvm_vcpu *vcpu, gpa_t gpa, unsigned int bytes,
+ void *data)
+{
+ return kvm_sev_es_do_mmio(vcpu, gpa, bytes, data, &write_emultor);
+}
EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_sev_es_mmio_write);
int kvm_sev_es_mmio_read(struct kvm_vcpu *vcpu, gpa_t gpa, unsigned int bytes,
void *data)
{
- int handled;
- struct kvm_mmio_fragment *frag;
-
- if (!data || WARN_ON_ONCE(object_is_on_stack(data)))
- return -EINVAL;
-
- handled = read_emultor.read_write_mmio(vcpu, gpa, bytes, data);
- if (handled == bytes)
- return 1;
-
- bytes -= handled;
- gpa += handled;
- data += handled;
-
- /*TODO: Check if need to increment number of frags */
- frag = vcpu->mmio_fragments;
- vcpu->mmio_nr_fragments = 1;
- frag->len = bytes;
- frag->gpa = gpa;
- frag->data = data;
-
- vcpu->mmio_needed = 1;
- vcpu->mmio_cur_fragment = 0;
-
- vcpu->run->mmio.phys_addr = gpa;
- vcpu->run->mmio.len = min(8u, frag->len);
- vcpu->run->mmio.is_write = 0;
- vcpu->run->exit_reason = KVM_EXIT_MMIO;
-
- vcpu->arch.complete_userspace_io = complete_sev_es_emulated_mmio;
-
- return 0;
+ return kvm_sev_es_do_mmio(vcpu, gpa, bytes, data, &read_emultor);
}
EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_sev_es_mmio_read);