Merge tag 'kvm-x86-asyncpf_abi-6.9' of https://github.com/kvm-x86/linux into HEAD
authorPaolo Bonzini <pbonzini@redhat.com>
Mon, 18 Mar 2024 23:03:42 +0000 (19:03 -0400)
committerPaolo Bonzini <pbonzini@redhat.com>
Mon, 18 Mar 2024 23:03:42 +0000 (19:03 -0400)
Guest-side KVM async #PF ABI cleanup for 6.9

Delete kvm_vcpu_pv_apf_data.enabled to fix a goof in KVM's async #PF ABI where
the enabled field pushes the size of "struct kvm_vcpu_pv_apf_data" from 64 to
68 bytes, i.e. beyond a single cache line.

The enabled field is purely a guest-side flag that Linux-as-a-guest uses to
track whether or not the guest has enabled async #PF support.  The actual flag
that is passed to the host, i.e. to KVM proper, is a single bit in a synthetic
MSR, MSR_KVM_ASYNC_PF_EN, i.e. is in a location completely unrelated to the
shared kvm_vcpu_pv_apf_data structure.

Simply drop the the field and use a dedicated guest-side per-CPU variable to
fix the ABI, as opposed to fixing the documentation to match reality.  KVM has
never consumed kvm_vcpu_pv_apf_data.enabled, so the odds of the ABI change
breaking anything are extremely low.

1  2 
arch/x86/include/uapi/asm/kvm_para.h
arch/x86/kernel/kvm.c

index 6bc3456a8ebf1d1a7c83498cbbef2b5bae106b41,605899594ebb8b68c9b67c6e6ffbab81b267bc6b..a1efa7907a0b100840f6c13c33e5abaa36ef822b
@@@ -92,7 -92,7 +92,7 @@@ struct kvm_clock_pairing 
  #define KVM_ASYNC_PF_DELIVERY_AS_INT          (1 << 3)
  
  /* MSR_KVM_ASYNC_PF_INT */
 -#define KVM_ASYNC_PF_VEC_MASK                 GENMASK(7, 0)
 +#define KVM_ASYNC_PF_VEC_MASK                 __GENMASK(7, 0)
  
  /* MSR_KVM_MIGRATION_CONTROL */
  #define KVM_MIGRATION_READY           (1 << 0)
@@@ -142,7 -142,6 +142,6 @@@ struct kvm_vcpu_pv_apf_data 
        __u32 token;
  
        __u8 pad[56];
-       __u32 enabled;
  };
  
  #define KVM_PV_EOI_BIT 0
diff --combined arch/x86/kernel/kvm.c
index 4cadfd606e8e6a9f16a10eec4fdf85ac9b67f575,e34f985c9a6fd359d24a68e8364fdea3c50d3919..7f0732bc0ccd2346d7737bb04ea796c730986143
@@@ -65,6 -65,7 +65,7 @@@ static int __init parse_no_stealacc(cha
  
  early_param("no-steal-acc", parse_no_stealacc);
  
+ static DEFINE_PER_CPU_READ_MOSTLY(bool, async_pf_enabled);
  static DEFINE_PER_CPU_DECRYPTED(struct kvm_vcpu_pv_apf_data, apf_reason) __aligned(64);
  DEFINE_PER_CPU_DECRYPTED(struct kvm_steal_time, steal_time) __aligned(64) __visible;
  static int has_steal_clock = 0;
@@@ -244,7 -245,7 +245,7 @@@ noinstr u32 kvm_read_and_reset_apf_flag
  {
        u32 flags = 0;
  
-       if (__this_cpu_read(apf_reason.enabled)) {
+       if (__this_cpu_read(async_pf_enabled)) {
                flags = __this_cpu_read(apf_reason.flags);
                __this_cpu_write(apf_reason.flags, 0);
        }
@@@ -295,7 -296,7 +296,7 @@@ DEFINE_IDTENTRY_SYSVEC(sysvec_kvm_async
  
        inc_irq_stat(irq_hv_callback_count);
  
-       if (__this_cpu_read(apf_reason.enabled)) {
+       if (__this_cpu_read(async_pf_enabled)) {
                token = __this_cpu_read(apf_reason.token);
                kvm_async_pf_task_wake(token);
                __this_cpu_write(apf_reason.token, 0);
@@@ -362,7 -363,7 +363,7 @@@ static void kvm_guest_cpu_init(void
                wrmsrl(MSR_KVM_ASYNC_PF_INT, HYPERVISOR_CALLBACK_VECTOR);
  
                wrmsrl(MSR_KVM_ASYNC_PF_EN, pa);
-               __this_cpu_write(apf_reason.enabled, 1);
+               __this_cpu_write(async_pf_enabled, true);
                pr_debug("setup async PF for cpu %d\n", smp_processor_id());
        }
  
  
  static void kvm_pv_disable_apf(void)
  {
-       if (!__this_cpu_read(apf_reason.enabled))
+       if (!__this_cpu_read(async_pf_enabled))
                return;
  
        wrmsrl(MSR_KVM_ASYNC_PF_EN, 0);
-       __this_cpu_write(apf_reason.enabled, 0);
+       __this_cpu_write(async_pf_enabled, false);
  
        pr_debug("disable async PF for cpu %d\n", smp_processor_id());
  }
@@@ -434,8 -435,7 +435,8 @@@ static void __init sev_map_percpu_data(
  {
        int cpu;
  
 -      if (!cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT))
 +      if (cc_vendor != CC_VENDOR_AMD ||
 +          !cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT))
                return;
  
        for_each_possible_cpu(cpu) {
@@@ -770,7 -770,7 +771,7 @@@ static struct notifier_block kvm_pv_reb
   * won't be valid. In cases like kexec, in which you install a new kernel, this
   * means a random memory location will be kept being written.
   */
 -#ifdef CONFIG_KEXEC_CORE
 +#ifdef CONFIG_CRASH_DUMP
  static void kvm_crash_shutdown(struct pt_regs *regs)
  {
        kvm_guest_cpu_offline(true);
@@@ -830,7 -830,7 +831,7 @@@ static void __init kvm_guest_init(void
  
        if (kvm_para_has_feature(KVM_FEATURE_ASYNC_PF_INT) && kvmapf) {
                static_branch_enable(&kvm_async_pf_enabled);
 -              alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR, asm_sysvec_kvm_asyncpf_interrupt);
 +              sysvec_install(HYPERVISOR_CALLBACK_VECTOR, sysvec_kvm_asyncpf_interrupt);
        }
  
  #ifdef CONFIG_SMP
        kvm_guest_cpu_init();
  #endif
  
 -#ifdef CONFIG_KEXEC_CORE
 +#ifdef CONFIG_CRASH_DUMP
        machine_ops.crash_shutdown = kvm_crash_shutdown;
  #endif