[PATCH v5 27/34] kvm/xen-emu: re-initialize capabilities during confidential guest reset

Ani Sinha posted 34 patches 1 month, 3 weeks ago
Maintainers: Paolo Bonzini <pbonzini@redhat.com>, Eduardo Habkost <eduardo@habkost.net>, Marcel Apfelbaum <marcel.apfelbaum@gmail.com>, "Philippe Mathieu-Daudé" <philmd@linaro.org>, Yanan Wang <wangyanan55@huawei.com>, Zhao Liu <zhao1.liu@intel.com>, "Maciej S. Szmigiero" <maciej.szmigiero@oracle.com>, Richard Henderson <richard.henderson@linaro.org>, "Michael S. Tsirkin" <mst@redhat.com>, Bernhard Beschow <shentey@gmail.com>, Alex Williamson <alex@shazbot.org>, "Cédric Le Goater" <clg@redhat.com>, Peter Xu <peterx@redhat.com>, Fabiano Rosas <farosas@suse.de>, Eric Blake <eblake@redhat.com>, Markus Armbruster <armbru@redhat.com>, "Daniel P. Berrangé" <berrange@redhat.com>, Ani Sinha <anisinha@redhat.com>, Marcelo Tosatti <mtosatti@redhat.com>, David Woodhouse <dwmw2@infradead.org>, Paul Durrant <paul@xen.org>
There is a newer version of this series
[PATCH v5 27/34] kvm/xen-emu: re-initialize capabilities during confidential guest reset
Posted by Ani Sinha 1 month, 3 weeks ago
On confidential guests KVM virtual machine file descriptor changes as a
part of the guest reset process. Xen capabilities needs to be re-initialized in
KVM against the new file descriptor.

Signed-off-by: Ani Sinha <anisinha@redhat.com>
---
 target/i386/kvm/xen-emu.c | 50 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 48 insertions(+), 2 deletions(-)

diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c
index 52de019834..69527145eb 100644
--- a/target/i386/kvm/xen-emu.c
+++ b/target/i386/kvm/xen-emu.c
@@ -44,9 +44,12 @@
 
 #include "xen-compat.h"
 
+NotifierWithReturn xen_vmfd_change_notifier;
+static bool hyperv_enabled;
 static void xen_vcpu_singleshot_timer_event(void *opaque);
 static void xen_vcpu_periodic_timer_event(void *opaque);
 static int vcpuop_stop_singleshot_timer(CPUState *cs);
+static int do_initialize_xen_caps(KVMState *s, uint32_t hypercall_msr);
 
 #ifdef TARGET_X86_64
 #define hypercall_compat32(longmode) (!(longmode))
@@ -54,6 +57,30 @@ static int vcpuop_stop_singleshot_timer(CPUState *cs);
 #define hypercall_compat32(longmode) (false)
 #endif
 
+static int xen_handle_vmfd_change(NotifierWithReturn *n,
+                                  void *data, Error** errp)
+{
+    int ret;
+
+    /* we are not interested in pre vmfd change notification */
+    if (((VmfdChangeNotifier *)data)->pre) {
+        return 0;
+    }
+
+    ret = do_initialize_xen_caps(kvm_state, XEN_HYPERCALL_MSR);
+    if (ret < 0) {
+        return ret;
+    }
+
+    if (hyperv_enabled) {
+        ret = do_initialize_xen_caps(kvm_state, XEN_HYPERCALL_MSR_HYPERV);
+        if (ret < 0) {
+            return ret;
+        }
+    }
+    return 0;
+}
+
 static bool kvm_gva_to_gpa(CPUState *cs, uint64_t gva, uint64_t *gpa,
                            size_t *len, bool is_write)
 {
@@ -111,15 +138,16 @@ static inline int kvm_copy_to_gva(CPUState *cs, uint64_t gva, void *buf,
     return kvm_gva_rw(cs, gva, buf, sz, true);
 }
 
-int kvm_xen_init(KVMState *s, uint32_t hypercall_msr)
+static int do_initialize_xen_caps(KVMState *s, uint32_t hypercall_msr)
 {
+    int xen_caps, ret;
     const int required_caps = KVM_XEN_HVM_CONFIG_HYPERCALL_MSR |
         KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL | KVM_XEN_HVM_CONFIG_SHARED_INFO;
+
     struct kvm_xen_hvm_config cfg = {
         .msr = hypercall_msr,
         .flags = KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL,
     };
-    int xen_caps, ret;
 
     xen_caps = kvm_check_extension(s, KVM_CAP_XEN_HVM);
     if (required_caps & ~xen_caps) {
@@ -143,6 +171,21 @@ int kvm_xen_init(KVMState *s, uint32_t hypercall_msr)
                      strerror(-ret));
         return ret;
     }
+    return xen_caps;
+}
+
+int kvm_xen_init(KVMState *s, uint32_t hypercall_msr)
+{
+    int xen_caps;
+
+    xen_caps = do_initialize_xen_caps(s, hypercall_msr);
+    if (xen_caps < 0) {
+        return xen_caps;
+    }
+
+    if (!hyperv_enabled && (hypercall_msr == XEN_HYPERCALL_MSR_HYPERV)) {
+        hyperv_enabled = true;
+    }
 
     /* If called a second time, don't repeat the rest of the setup. */
     if (s->xen_caps) {
@@ -185,6 +228,9 @@ int kvm_xen_init(KVMState *s, uint32_t hypercall_msr)
     xen_primary_console_reset();
     xen_xenstore_reset();
 
+    xen_vmfd_change_notifier.notify = xen_handle_vmfd_change;
+    kvm_vmfd_add_change_notifier(&xen_vmfd_change_notifier);
+
     return 0;
 }
 
-- 
2.42.0
Re: [PATCH v5 27/34] kvm/xen-emu: re-initialize capabilities during confidential guest reset
Posted by Paul Durrant 1 month, 3 weeks ago
On 18/02/2026 11:42, Ani Sinha wrote:
> On confidential guests KVM virtual machine file descriptor changes as a
> part of the guest reset process. Xen capabilities needs to be re-initialized in
> KVM against the new file descriptor.
> 
> Signed-off-by: Ani Sinha <anisinha@redhat.com>
> ---
>   target/i386/kvm/xen-emu.c | 50 +++++++++++++++++++++++++++++++++++++--
>   1 file changed, 48 insertions(+), 2 deletions(-)
> 
> diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c
> index 52de019834..69527145eb 100644
> --- a/target/i386/kvm/xen-emu.c
> +++ b/target/i386/kvm/xen-emu.c
> @@ -44,9 +44,12 @@
>   
>   #include "xen-compat.h"
>   
> +NotifierWithReturn xen_vmfd_change_notifier;
> +static bool hyperv_enabled;
>   static void xen_vcpu_singleshot_timer_event(void *opaque);
>   static void xen_vcpu_periodic_timer_event(void *opaque);
>   static int vcpuop_stop_singleshot_timer(CPUState *cs);
> +static int do_initialize_xen_caps(KVMState *s, uint32_t hypercall_msr);
>   
>   #ifdef TARGET_X86_64
>   #define hypercall_compat32(longmode) (!(longmode))
> @@ -54,6 +57,30 @@ static int vcpuop_stop_singleshot_timer(CPUState *cs);
>   #define hypercall_compat32(longmode) (false)
>   #endif
>   
> +static int xen_handle_vmfd_change(NotifierWithReturn *n,
> +                                  void *data, Error** errp)
> +{
> +    int ret;
> +
> +    /* we are not interested in pre vmfd change notification */
> +    if (((VmfdChangeNotifier *)data)->pre) {
> +        return 0;
> +    }
> +
> +    ret = do_initialize_xen_caps(kvm_state, XEN_HYPERCALL_MSR);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +
> +    if (hyperv_enabled) {
> +        ret = do_initialize_xen_caps(kvm_state, XEN_HYPERCALL_MSR_HYPERV);
> +        if (ret < 0) {
> +            return ret;
> +        }
> +    }
> +    return 0;

This seems odd. Why use the hyperv_enabled boolean, rather than simply 
the msr value, since when hyperv_enabled is set you will be calling 
do_initialize_xen_caps() twice.

> +}
> +
>   static bool kvm_gva_to_gpa(CPUState *cs, uint64_t gva, uint64_t *gpa,
>                              size_t *len, bool is_write)
>   {
> @@ -111,15 +138,16 @@ static inline int kvm_copy_to_gva(CPUState *cs, uint64_t gva, void *buf,
>       return kvm_gva_rw(cs, gva, buf, sz, true);
>   }
>   
> -int kvm_xen_init(KVMState *s, uint32_t hypercall_msr)
> +static int do_initialize_xen_caps(KVMState *s, uint32_t hypercall_msr)
>   {
> +    int xen_caps, ret;
>       const int required_caps = KVM_XEN_HVM_CONFIG_HYPERCALL_MSR |
>           KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL | KVM_XEN_HVM_CONFIG_SHARED_INFO;
> +

Gratuitous whitespace change.

>       struct kvm_xen_hvm_config cfg = {
>           .msr = hypercall_msr,
>           .flags = KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL,
>       };
> -    int xen_caps, ret;
>   
>       xen_caps = kvm_check_extension(s, KVM_CAP_XEN_HVM);
>       if (required_caps & ~xen_caps) {
> @@ -143,6 +171,21 @@ int kvm_xen_init(KVMState *s, uint32_t hypercall_msr)
>                        strerror(-ret));
>           return ret;
>       }
> +    return xen_caps;
> +}
> +
> +int kvm_xen_init(KVMState *s, uint32_t hypercall_msr)
> +{
> +    int xen_caps;
> +
> +    xen_caps = do_initialize_xen_caps(s, hypercall_msr);
> +    if (xen_caps < 0) {
> +        return xen_caps;
> +    }
> +

Clearly here the code would be simpler here if you just saved the value 
of hypercall_msr which you have used in the call above.

> +    if (!hyperv_enabled && (hypercall_msr == XEN_HYPERCALL_MSR_HYPERV)) {
> +        hyperv_enabled = true;
> +    }
>   
>       /* If called a second time, don't repeat the rest of the setup. */
>       if (s->xen_caps) {
> @@ -185,6 +228,9 @@ int kvm_xen_init(KVMState *s, uint32_t hypercall_msr)
>       xen_primary_console_reset();
>       xen_xenstore_reset();
>   
> +    xen_vmfd_change_notifier.notify = xen_handle_vmfd_change;
> +    kvm_vmfd_add_change_notifier(&xen_vmfd_change_notifier);
> +
>       return 0;
>   }
>
Re: [PATCH v5 27/34] kvm/xen-emu: re-initialize capabilities during confidential guest reset
Posted by Ani Sinha 1 month, 3 weeks ago

> On 19 Feb 2026, at 3:09 PM, Paul Durrant <xadimgnik@gmail.com> wrote:
> 
> On 18/02/2026 11:42, Ani Sinha wrote:
>> On confidential guests KVM virtual machine file descriptor changes as a
>> part of the guest reset process. Xen capabilities needs to be re-initialized in
>> KVM against the new file descriptor.
>> Signed-off-by: Ani Sinha <anisinha@redhat.com>
>> ---
>>  target/i386/kvm/xen-emu.c | 50 +++++++++++++++++++++++++++++++++++++--
>>  1 file changed, 48 insertions(+), 2 deletions(-)
>> diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c
>> index 52de019834..69527145eb 100644
>> --- a/target/i386/kvm/xen-emu.c
>> +++ b/target/i386/kvm/xen-emu.c
>> @@ -44,9 +44,12 @@
>>    #include "xen-compat.h"
>>  +NotifierWithReturn xen_vmfd_change_notifier;
>> +static bool hyperv_enabled;
>>  static void xen_vcpu_singleshot_timer_event(void *opaque);
>>  static void xen_vcpu_periodic_timer_event(void *opaque);
>>  static int vcpuop_stop_singleshot_timer(CPUState *cs);
>> +static int do_initialize_xen_caps(KVMState *s, uint32_t hypercall_msr);
>>    #ifdef TARGET_X86_64
>>  #define hypercall_compat32(longmode) (!(longmode))
>> @@ -54,6 +57,30 @@ static int vcpuop_stop_singleshot_timer(CPUState *cs);
>>  #define hypercall_compat32(longmode) (false)
>>  #endif
>>  +static int xen_handle_vmfd_change(NotifierWithReturn *n,
>> +                                  void *data, Error** errp)
>> +{
>> +    int ret;
>> +
>> +    /* we are not interested in pre vmfd change notification */
>> +    if (((VmfdChangeNotifier *)data)->pre) {
>> +        return 0;
>> +    }
>> +
>> +    ret = do_initialize_xen_caps(kvm_state, XEN_HYPERCALL_MSR);
>> +    if (ret < 0) {
>> +        return ret;
>> +    }
>> +
>> +    if (hyperv_enabled) {
>> +        ret = do_initialize_xen_caps(kvm_state, XEN_HYPERCALL_MSR_HYPERV);
>> +        if (ret < 0) {
>> +            return ret;
>> +        }
>> +    }
>> +    return 0;
> 
> This seems odd. Why use the hyperv_enabled boolean, rather than simply the msr value, since when hyperv_enabled is set you will be calling do_initialize_xen_caps() twice.

I am not sure of enabling capabilities for Xen. I assumed we need to call kvm_xen_init() twice, once normally with XEN_HYPERCALL_MSR and if hyper is enabled, again with XEN_HYPERCALL_MSR_HYPERV. Is that not the case? Is it one or the other but not both? It seems kvm_arch_init() calls kvm_xen_init() once with XEN_HYPERCALL_MSR and another time vcpu_arch_init() calls it again if hyperv is enabled with XEN_HYPERCALL_MSR_HYPERV .

> 
>> +}
>> +
>>  static bool kvm_gva_to_gpa(CPUState *cs, uint64_t gva, uint64_t *gpa,
>>                             size_t *len, bool is_write)
>>  {
>> @@ -111,15 +138,16 @@ static inline int kvm_copy_to_gva(CPUState *cs, uint64_t gva, void *buf,
>>      return kvm_gva_rw(cs, gva, buf, sz, true);
>>  }
>>  -int kvm_xen_init(KVMState *s, uint32_t hypercall_msr)
>> +static int do_initialize_xen_caps(KVMState *s, uint32_t hypercall_msr)
>>  {
>> +    int xen_caps, ret;
>>      const int required_caps = KVM_XEN_HVM_CONFIG_HYPERCALL_MSR |
>>          KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL | KVM_XEN_HVM_CONFIG_SHARED_INFO;
>> +
> 
> Gratuitous whitespace change.
> 
>>      struct kvm_xen_hvm_config cfg = {
>>          .msr = hypercall_msr,
>>          .flags = KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL,
>>      };
>> -    int xen_caps, ret;
>>        xen_caps = kvm_check_extension(s, KVM_CAP_XEN_HVM);
>>      if (required_caps & ~xen_caps) {
>> @@ -143,6 +171,21 @@ int kvm_xen_init(KVMState *s, uint32_t hypercall_msr)
>>                       strerror(-ret));
>>          return ret;
>>      }
>> +    return xen_caps;
>> +}
>> +
>> +int kvm_xen_init(KVMState *s, uint32_t hypercall_msr)
>> +{
>> +    int xen_caps;
>> +
>> +    xen_caps = do_initialize_xen_caps(s, hypercall_msr);
>> +    if (xen_caps < 0) {
>> +        return xen_caps;
>> +    }
>> +
> 
> Clearly here the code would be simpler here if you just saved the value of hypercall_msr which you have used in the call above.
> 
>> +    if (!hyperv_enabled && (hypercall_msr == XEN_HYPERCALL_MSR_HYPERV)) {
>> +        hyperv_enabled = true;
>> +    }
>>        /* If called a second time, don't repeat the rest of the setup. */
>>      if (s->xen_caps) {
>> @@ -185,6 +228,9 @@ int kvm_xen_init(KVMState *s, uint32_t hypercall_msr)
>>      xen_primary_console_reset();
>>      xen_xenstore_reset();
>>  +    xen_vmfd_change_notifier.notify = xen_handle_vmfd_change;
>> +    kvm_vmfd_add_change_notifier(&xen_vmfd_change_notifier);
>> +
>>      return 0;
>>  }
Re: [PATCH v5 27/34] kvm/xen-emu: re-initialize capabilities during confidential guest reset
Posted by Paul Durrant 1 month, 3 weeks ago
On 19/02/2026 10:31, Ani Sinha wrote:
> 
> 
>> On 19 Feb 2026, at 3:09 PM, Paul Durrant <xadimgnik@gmail.com> wrote:
>>
>> On 18/02/2026 11:42, Ani Sinha wrote:
>>> On confidential guests KVM virtual machine file descriptor changes as a
>>> part of the guest reset process. Xen capabilities needs to be re-initialized in
>>> KVM against the new file descriptor.
>>> Signed-off-by: Ani Sinha <anisinha@redhat.com>
>>> ---
>>>   target/i386/kvm/xen-emu.c | 50 +++++++++++++++++++++++++++++++++++++--
>>>   1 file changed, 48 insertions(+), 2 deletions(-)
>>> diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c
>>> index 52de019834..69527145eb 100644
>>> --- a/target/i386/kvm/xen-emu.c
>>> +++ b/target/i386/kvm/xen-emu.c
>>> @@ -44,9 +44,12 @@
>>>     #include "xen-compat.h"
>>>   +NotifierWithReturn xen_vmfd_change_notifier;
>>> +static bool hyperv_enabled;
>>>   static void xen_vcpu_singleshot_timer_event(void *opaque);
>>>   static void xen_vcpu_periodic_timer_event(void *opaque);
>>>   static int vcpuop_stop_singleshot_timer(CPUState *cs);
>>> +static int do_initialize_xen_caps(KVMState *s, uint32_t hypercall_msr);
>>>     #ifdef TARGET_X86_64
>>>   #define hypercall_compat32(longmode) (!(longmode))
>>> @@ -54,6 +57,30 @@ static int vcpuop_stop_singleshot_timer(CPUState *cs);
>>>   #define hypercall_compat32(longmode) (false)
>>>   #endif
>>>   +static int xen_handle_vmfd_change(NotifierWithReturn *n,
>>> +                                  void *data, Error** errp)
>>> +{
>>> +    int ret;
>>> +
>>> +    /* we are not interested in pre vmfd change notification */
>>> +    if (((VmfdChangeNotifier *)data)->pre) {
>>> +        return 0;
>>> +    }
>>> +
>>> +    ret = do_initialize_xen_caps(kvm_state, XEN_HYPERCALL_MSR);
>>> +    if (ret < 0) {
>>> +        return ret;
>>> +    }
>>> +
>>> +    if (hyperv_enabled) {
>>> +        ret = do_initialize_xen_caps(kvm_state, XEN_HYPERCALL_MSR_HYPERV);
>>> +        if (ret < 0) {
>>> +            return ret;
>>> +        }
>>> +    }
>>> +    return 0;
>>
>> This seems odd. Why use the hyperv_enabled boolean, rather than simply the msr value, since when hyperv_enabled is set you will be calling do_initialize_xen_caps() twice.
> 
> I am not sure of enabling capabilities for Xen. I assumed we need to call kvm_xen_init() twice, once normally with XEN_HYPERCALL_MSR and if hyper is enabled, again with XEN_HYPERCALL_MSR_HYPERV. Is that not the case? Is it one or the other but not both? It seems kvm_arch_init() calls kvm_xen_init() once with XEN_HYPERCALL_MSR and another time vcpu_arch_init() calls it again if hyperv is enabled with XEN_HYPERCALL_MSR_HYPERV .

Yes, it has to be assumed that XEN_HYPERCALL_MSR is correct until 
Hyper-V supported is enabled, which comes later, at which point the MSR 
is changed. So you only need save the latest MSR value and use that in 
xen_handle_vmfd_change().

> 
>>
>>> +}
>>> +
>>>   static bool kvm_gva_to_gpa(CPUState *cs, uint64_t gva, uint64_t *gpa,
>>>                              size_t *len, bool is_write)
>>>   {
>>> @@ -111,15 +138,16 @@ static inline int kvm_copy_to_gva(CPUState *cs, uint64_t gva, void *buf,
>>>       return kvm_gva_rw(cs, gva, buf, sz, true);
>>>   }
>>>   -int kvm_xen_init(KVMState *s, uint32_t hypercall_msr)
>>> +static int do_initialize_xen_caps(KVMState *s, uint32_t hypercall_msr)
>>>   {
>>> +    int xen_caps, ret;
>>>       const int required_caps = KVM_XEN_HVM_CONFIG_HYPERCALL_MSR |
>>>           KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL | KVM_XEN_HVM_CONFIG_SHARED_INFO;
>>> +
>>
>> Gratuitous whitespace change.
>>
>>>       struct kvm_xen_hvm_config cfg = {
>>>           .msr = hypercall_msr,
>>>           .flags = KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL,
>>>       };
>>> -    int xen_caps, ret;
>>>         xen_caps = kvm_check_extension(s, KVM_CAP_XEN_HVM);
>>>       if (required_caps & ~xen_caps) {
>>> @@ -143,6 +171,21 @@ int kvm_xen_init(KVMState *s, uint32_t hypercall_msr)
>>>                        strerror(-ret));
>>>           return ret;
>>>       }
>>> +    return xen_caps;
>>> +}
>>> +
>>> +int kvm_xen_init(KVMState *s, uint32_t hypercall_msr)
>>> +{
>>> +    int xen_caps;
>>> +
>>> +    xen_caps = do_initialize_xen_caps(s, hypercall_msr);
>>> +    if (xen_caps < 0) {
>>> +        return xen_caps;
>>> +    }
>>> +
>>
>> Clearly here the code would be simpler here if you just saved the value of hypercall_msr which you have used in the call above.
>>
>>> +    if (!hyperv_enabled && (hypercall_msr == XEN_HYPERCALL_MSR_HYPERV)) {
>>> +        hyperv_enabled = true;
>>> +    }
>>>         /* If called a second time, don't repeat the rest of the setup. */
>>>       if (s->xen_caps) {
>>> @@ -185,6 +228,9 @@ int kvm_xen_init(KVMState *s, uint32_t hypercall_msr)
>>>       xen_primary_console_reset();
>>>       xen_xenstore_reset();
>>>   +    xen_vmfd_change_notifier.notify = xen_handle_vmfd_change;
>>> +    kvm_vmfd_add_change_notifier(&xen_vmfd_change_notifier);
>>> +
>>>       return 0;
>>>   }
> 
> 


Re: [PATCH v5 27/34] kvm/xen-emu: re-initialize capabilities during confidential guest reset
Posted by Ani Sinha 1 month, 3 weeks ago
On Thu, Feb 19, 2026 at 4:15 PM Paul Durrant <xadimgnik@gmail.com> wrote:
>
> On 19/02/2026 10:31, Ani Sinha wrote:
> >
> >
> >> On 19 Feb 2026, at 3:09 PM, Paul Durrant <xadimgnik@gmail.com> wrote:
> >>
> >> On 18/02/2026 11:42, Ani Sinha wrote:
> >>> On confidential guests KVM virtual machine file descriptor changes as a
> >>> part of the guest reset process. Xen capabilities needs to be re-initialized in
> >>> KVM against the new file descriptor.
> >>> Signed-off-by: Ani Sinha <anisinha@redhat.com>
> >>> ---
> >>>   target/i386/kvm/xen-emu.c | 50 +++++++++++++++++++++++++++++++++++++--
> >>>   1 file changed, 48 insertions(+), 2 deletions(-)
> >>> diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c
> >>> index 52de019834..69527145eb 100644
> >>> --- a/target/i386/kvm/xen-emu.c
> >>> +++ b/target/i386/kvm/xen-emu.c
> >>> @@ -44,9 +44,12 @@
> >>>     #include "xen-compat.h"
> >>>   +NotifierWithReturn xen_vmfd_change_notifier;
> >>> +static bool hyperv_enabled;
> >>>   static void xen_vcpu_singleshot_timer_event(void *opaque);
> >>>   static void xen_vcpu_periodic_timer_event(void *opaque);
> >>>   static int vcpuop_stop_singleshot_timer(CPUState *cs);
> >>> +static int do_initialize_xen_caps(KVMState *s, uint32_t hypercall_msr);
> >>>     #ifdef TARGET_X86_64
> >>>   #define hypercall_compat32(longmode) (!(longmode))
> >>> @@ -54,6 +57,30 @@ static int vcpuop_stop_singleshot_timer(CPUState *cs);
> >>>   #define hypercall_compat32(longmode) (false)
> >>>   #endif
> >>>   +static int xen_handle_vmfd_change(NotifierWithReturn *n,
> >>> +                                  void *data, Error** errp)
> >>> +{
> >>> +    int ret;
> >>> +
> >>> +    /* we are not interested in pre vmfd change notification */
> >>> +    if (((VmfdChangeNotifier *)data)->pre) {
> >>> +        return 0;
> >>> +    }
> >>> +
> >>> +    ret = do_initialize_xen_caps(kvm_state, XEN_HYPERCALL_MSR);
> >>> +    if (ret < 0) {
> >>> +        return ret;
> >>> +    }
> >>> +
> >>> +    if (hyperv_enabled) {
> >>> +        ret = do_initialize_xen_caps(kvm_state, XEN_HYPERCALL_MSR_HYPERV);
> >>> +        if (ret < 0) {
> >>> +            return ret;
> >>> +        }
> >>> +    }
> >>> +    return 0;
> >>
> >> This seems odd. Why use the hyperv_enabled boolean, rather than simply the msr value, since when hyperv_enabled is set you will be calling do_initialize_xen_caps() twice.
> >
> > I am not sure of enabling capabilities for Xen. I assumed we need to call kvm_xen_init() twice, once normally with XEN_HYPERCALL_MSR and if hyper is enabled, again with XEN_HYPERCALL_MSR_HYPERV. Is that not the case? Is it one or the other but not both? It seems kvm_arch_init() calls kvm_xen_init() once with XEN_HYPERCALL_MSR and another time vcpu_arch_init() calls it again if hyperv is enabled with XEN_HYPERCALL_MSR_HYPERV .
>
> Yes, it has to be assumed that XEN_HYPERCALL_MSR is correct until
> Hyper-V supported is enabled, which comes later, at which point the MSR
> is changed. So you only need save the latest MSR value and use that in
> xen_handle_vmfd_change().

ok hopefully this looks good
https://gitlab.com/anisinha/qemu/-/commit/7f7ba25151b6a658c54f95a370f1970c01a6269a

sending this out to minimize churn and to make v6 as close to the
merge worthy as possible.
Re: [PATCH v5 27/34] kvm/xen-emu: re-initialize capabilities during confidential guest reset
Posted by Paul Durrant 1 month, 3 weeks ago
On 19/02/2026 11:19, Ani Sinha wrote:
> On Thu, Feb 19, 2026 at 4:15 PM Paul Durrant <xadimgnik@gmail.com> wrote:
>>
>> On 19/02/2026 10:31, Ani Sinha wrote:
>>>
>>>
>>>> On 19 Feb 2026, at 3:09 PM, Paul Durrant <xadimgnik@gmail.com> wrote:
>>>>
>>>> On 18/02/2026 11:42, Ani Sinha wrote:
>>>>> On confidential guests KVM virtual machine file descriptor changes as a
>>>>> part of the guest reset process. Xen capabilities needs to be re-initialized in
>>>>> KVM against the new file descriptor.
>>>>> Signed-off-by: Ani Sinha <anisinha@redhat.com>
>>>>> ---
>>>>>    target/i386/kvm/xen-emu.c | 50 +++++++++++++++++++++++++++++++++++++--
>>>>>    1 file changed, 48 insertions(+), 2 deletions(-)
>>>>> diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c
>>>>> index 52de019834..69527145eb 100644
>>>>> --- a/target/i386/kvm/xen-emu.c
>>>>> +++ b/target/i386/kvm/xen-emu.c
>>>>> @@ -44,9 +44,12 @@
>>>>>      #include "xen-compat.h"
>>>>>    +NotifierWithReturn xen_vmfd_change_notifier;
>>>>> +static bool hyperv_enabled;
>>>>>    static void xen_vcpu_singleshot_timer_event(void *opaque);
>>>>>    static void xen_vcpu_periodic_timer_event(void *opaque);
>>>>>    static int vcpuop_stop_singleshot_timer(CPUState *cs);
>>>>> +static int do_initialize_xen_caps(KVMState *s, uint32_t hypercall_msr);
>>>>>      #ifdef TARGET_X86_64
>>>>>    #define hypercall_compat32(longmode) (!(longmode))
>>>>> @@ -54,6 +57,30 @@ static int vcpuop_stop_singleshot_timer(CPUState *cs);
>>>>>    #define hypercall_compat32(longmode) (false)
>>>>>    #endif
>>>>>    +static int xen_handle_vmfd_change(NotifierWithReturn *n,
>>>>> +                                  void *data, Error** errp)
>>>>> +{
>>>>> +    int ret;
>>>>> +
>>>>> +    /* we are not interested in pre vmfd change notification */
>>>>> +    if (((VmfdChangeNotifier *)data)->pre) {
>>>>> +        return 0;
>>>>> +    }
>>>>> +
>>>>> +    ret = do_initialize_xen_caps(kvm_state, XEN_HYPERCALL_MSR);
>>>>> +    if (ret < 0) {
>>>>> +        return ret;
>>>>> +    }
>>>>> +
>>>>> +    if (hyperv_enabled) {
>>>>> +        ret = do_initialize_xen_caps(kvm_state, XEN_HYPERCALL_MSR_HYPERV);
>>>>> +        if (ret < 0) {
>>>>> +            return ret;
>>>>> +        }
>>>>> +    }
>>>>> +    return 0;
>>>>
>>>> This seems odd. Why use the hyperv_enabled boolean, rather than simply the msr value, since when hyperv_enabled is set you will be calling do_initialize_xen_caps() twice.
>>>
>>> I am not sure of enabling capabilities for Xen. I assumed we need to call kvm_xen_init() twice, once normally with XEN_HYPERCALL_MSR and if hyper is enabled, again with XEN_HYPERCALL_MSR_HYPERV. Is that not the case? Is it one or the other but not both? It seems kvm_arch_init() calls kvm_xen_init() once with XEN_HYPERCALL_MSR and another time vcpu_arch_init() calls it again if hyperv is enabled with XEN_HYPERCALL_MSR_HYPERV .
>>
>> Yes, it has to be assumed that XEN_HYPERCALL_MSR is correct until
>> Hyper-V supported is enabled, which comes later, at which point the MSR
>> is changed. So you only need save the latest MSR value and use that in
>> xen_handle_vmfd_change().
> 
> ok hopefully this looks good
> https://gitlab.com/anisinha/qemu/-/commit/7f7ba25151b6a658c54f95a370f1970c01a6269a
> 
> sending this out to minimize churn and to make v6 as close to the
> merge worthy as possible.
> 

Yeah, that looks better. I don't think you need to move the `int 
xen_caps, ret;` line though so your patch can be even smaller AFAICS.