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;
>>> }
>
>