@@ -149,6 +149,7 @@ struct KVMState
uint64_t kvm_dirty_ring_bytes; /* Size of the per-vcpu dirty ring */
uint32_t kvm_dirty_ring_size; /* Number of dirty GFNs per ring */
struct KVMDirtyRingReaper reaper;
+ int mirror_vm_fd;
};
KVMState *kvm_state;
@@ -3003,6 +3004,28 @@ int kvm_vm_ioctl(KVMState *s, int type, ...)
return ret;
}
+int kvm_mirror_vm_ioctl(KVMState *s, int type, ...)
+{
+ int ret;
+ void *arg;
+ va_list ap;
+
+ if (!s->mirror_vm_fd) {
+ return 0;
+ }
+
+ va_start(ap, type);
+ arg = va_arg(ap, void *);
+ va_end(ap);
+
+ trace_kvm_vm_ioctl(type, arg);
+ ret = ioctl(s->mirror_vm_fd, type, arg);
+ if (ret == -1) {
+ ret = -errno;
+ }
+ return ret;
+}
+
int kvm_vcpu_ioctl(CPUState *cpu, int type, ...)
{
int ret;
@@ -255,6 +255,8 @@ int kvm_ioctl(KVMState *s, int type, ...);
int kvm_vm_ioctl(KVMState *s, int type, ...);
+int kvm_mirror_vm_ioctl(KVMState *s, int type, ...);
+
int kvm_vcpu_ioctl(CPUState *cpu, int type, ...);
/**
@@ -434,6 +436,18 @@ int kvm_vm_check_extension(KVMState *s, unsigned int extension);
kvm_vm_ioctl(s, KVM_ENABLE_CAP, &cap); \
})
+#define kvm_mirror_vm_enable_cap(s, capability, cap_flags, ...) \
+ ({ \
+ struct kvm_enable_cap cap = { \
+ .cap = capability, \
+ .flags = cap_flags, \
+ }; \
+ uint64_t args_tmp[] = { __VA_ARGS__ }; \
+ size_t n = MIN(ARRAY_SIZE(args_tmp), ARRAY_SIZE(cap.args)); \
+ memcpy(cap.args, args_tmp, n * sizeof(cap.args[0])); \
+ kvm_mirror_vm_ioctl(s, KVM_ENABLE_CAP, &cap); \
+ })
+
#define kvm_vcpu_enable_cap(cpu, capability, cap_flags, ...) \
({ \
struct kvm_enable_cap cap = { \