diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index 096edb5e19..3b57d2f976 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -90,6 +90,7 @@ struct KVMParkedVcpu { }; KVMState *kvm_state; +VmfdChangeNotifier vmfd_notifier; bool kvm_kernel_irqchip; bool kvm_split_irqchip; bool kvm_async_interrupts_allowed; @@ -123,6 +124,9 @@ static const KVMCapabilityInfo kvm_required_capabilites[] = { static NotifierList kvm_irqchip_change_notifiers = NOTIFIER_LIST_INITIALIZER(kvm_irqchip_change_notifiers); +static NotifierWithReturnList register_vmfd_changed_notifiers = + NOTIFIER_WITH_RETURN_LIST_INITIALIZER(register_vmfd_changed_notifiers); + struct KVMResampleFd { int gsi; EventNotifier *resample_event; @@ -2173,6 +2177,22 @@ void kvm_irqchip_change_notify(void) notifier_list_notify(&kvm_irqchip_change_notifiers, NULL); } +void kvm_vmfd_add_change_notifier(NotifierWithReturn *n) +{ + notifier_with_return_list_add(®ister_vmfd_changed_notifiers, n); +} + +void kvm_vmfd_remove_change_notifier(NotifierWithReturn *n) +{ + notifier_with_return_remove(n); +} + +static int kvm_vmfd_change_notify(Error **errp) +{ + return notifier_with_return_list_notify(®ister_vmfd_changed_notifiers, + &vmfd_notifier, errp); +} + int kvm_irqchip_get_virq(KVMState *s) { int next_virq; @@ -2671,6 +2691,16 @@ static int kvm_reset_vmfd(MachineState *ms) do_kvm_irqchip_create(s); } + /* + * notify everyone that vmfd has changed. + */ + vmfd_notifier.vmfd = s->vmfd; + ret = kvm_vmfd_change_notify(&err); + if (ret < 0) { + return ret; + } + assert(!err); + /* these can be only called after ram_block_rebind() */ memory_listener_register(&kml->listener, &address_space_memory); memory_listener_register(&kvm_io_listener, &address_space_io); diff --git a/accel/stubs/kvm-stub.c b/accel/stubs/kvm-stub.c index 68cd33ba97..a6e8a6e16c 100644 --- a/accel/stubs/kvm-stub.c +++ b/accel/stubs/kvm-stub.c @@ -79,6 +79,14 @@ void kvm_irqchip_change_notify(void) { } +void kvm_vmfd_add_change_notifier(NotifierWithReturn *n) +{ +} + +void kvm_vmfd_remove_change_notifier(NotifierWithReturn *n) +{ +} + int kvm_irqchip_add_irqfd_notifier_gsi(KVMState *s, EventNotifier *n, EventNotifier *rn, int virq) { diff --git a/include/system/kvm.h b/include/system/kvm.h index 5fc7251fd9..f11729f432 100644 --- a/include/system/kvm.h +++ b/include/system/kvm.h @@ -181,6 +181,7 @@ DECLARE_INSTANCE_CHECKER(KVMState, KVM_STATE, extern KVMState *kvm_state; typedef struct Notifier Notifier; +typedef struct NotifierWithReturn NotifierWithReturn; typedef struct KVMRouteChange { KVMState *s; @@ -567,4 +568,24 @@ int kvm_set_memory_attributes_shared(hwaddr start, uint64_t size); int kvm_convert_memory(hwaddr start, hwaddr size, bool to_private); +/* argument to vmfd change notifier */ +typedef struct VmfdChangeNotifier { + int vmfd; +} VmfdChangeNotifier; + +/** + * kvm_vmfd_add_change_notifier - register a notifier to get notified when + * a KVM vm file descriptor changes as a part of the confidential guest "reset" + * process. Various subsystems should use this mechanism to take actions such + * as creating new fds against this new vm file descriptor. + * @n: notifier with return value. + */ +void kvm_vmfd_add_change_notifier(NotifierWithReturn *n); +/** + * kvm_vmfd_remove_change_notifier - de-register a notifer previously + * registered with kvm_vmfd_add_change_notifier call. + * @n: notifier that was previously registered. + */ +void kvm_vmfd_remove_change_notifier(NotifierWithReturn *n); + #endif