On 26/07/2022 13:56, Jane Malalane wrote:
> Implement support for the HVMOP_set_evtchn_upcall_vector hypercall in
> order to set the per-vCPU event channel vector callback on Linux and
> use it in preference of HVM_PARAM_CALLBACK_IRQ.
> 
> If the per-VCPU vector setup is successful on BSP, use this method
> for the APs. If not, fallback to the global vector-type callback.
> 
> Also register callback_irq at per-vCPU event channel setup to trick
> toolstack to think the domain is enlightened.
> 
> Suggested-by: "Roger Pau Monné" <roger....@citrix.com>
> Signed-off-by: Jane Malalane <jane.malal...@citrix.com>
> ---
> CC: Juergen Gross <jgr...@suse.com>
> CC: Boris Ostrovsky <boris.ostrov...@oracle.com>
> CC: Thomas Gleixner <t...@linutronix.de>
> CC: Ingo Molnar <mi...@redhat.com>
> CC: Borislav Petkov <b...@alien8.de>
> CC: Dave Hansen <dave.han...@linux.intel.com>
> CC: x...@kernel.org
> CC: "H. Peter Anvin" <h...@zytor.com>
> CC: Stefano Stabellini <sstabell...@kernel.org>
> CC: Oleksandr Tyshchenko <oleksandr_tyshche...@epam.com>
> CC: Jane Malalane <jane.malal...@citrix.com>
> CC: Maximilian Heyne <mhe...@amazon.de>
> CC: Jan Beulich <jbeul...@suse.com>
> CC: Colin Ian King <colin.k...@intel.com>
> CC: xen-devel@lists.xenproject.org
> 
> v2:
>   * remove no_vector_callback
>   * make xen_have_vector_callback a bool
>   * rename xen_ack_upcall to xen_percpu_upcall
>   * fail to bring CPU up on init instead of crashing kernel
>   * add and use xen_set_upcall_vector where suitable
>   * xen_setup_upcall_vector -> xen_init_setup_upcall_vector for clarity
> ---
>   arch/x86/include/asm/xen/cpuid.h   |  2 ++
>   arch/x86/include/asm/xen/events.h  |  3 ++-
>   arch/x86/xen/enlighten.c           |  2 +-
>   arch/x86/xen/enlighten_hvm.c       | 24 ++++++++++++++-----
>   arch/x86/xen/suspend_hvm.c         | 10 +++++++-
>   drivers/xen/events/events_base.c   | 49 
> ++++++++++++++++++++++++++++++++++----
>   include/xen/hvm.h                  |  2 ++
>   include/xen/interface/hvm/hvm_op.h | 15 ++++++++++++
>   8 files changed, 93 insertions(+), 14 deletions(-)
> 
> diff --git a/arch/x86/include/asm/xen/cpuid.h 
> b/arch/x86/include/asm/xen/cpuid.h
> index 78e667a31d6c..6daa9b0c8d11 100644
> --- a/arch/x86/include/asm/xen/cpuid.h
> +++ b/arch/x86/include/asm/xen/cpuid.h
> @@ -107,6 +107,8 @@
>    * ID field from 8 to 15 bits, allowing to target APIC IDs up 32768.
>    */
>   #define XEN_HVM_CPUID_EXT_DEST_ID      (1u << 5)
> +/* Per-vCPU event channel upcalls */
> +#define XEN_HVM_CPUID_UPCALL_VECTOR    (1u << 6)
>   
>   /*
>    * Leaf 6 (0x40000x05)
> diff --git a/arch/x86/include/asm/xen/events.h 
> b/arch/x86/include/asm/xen/events.h
> index 068d9b067c83..62bdceb594f1 100644
> --- a/arch/x86/include/asm/xen/events.h
> +++ b/arch/x86/include/asm/xen/events.h
> @@ -23,7 +23,7 @@ static inline int xen_irqs_disabled(struct pt_regs *regs)
>   /* No need for a barrier -- XCHG is a barrier on x86. */
>   #define xchg_xen_ulong(ptr, val) xchg((ptr), (val))
>   
> -extern int xen_have_vector_callback;
> +extern bool xen_have_vector_callback;
>   
>   /*
>    * Events delivered via platform PCI interrupts are always
> @@ -34,4 +34,5 @@ static inline bool xen_support_evtchn_rebind(void)
>       return (!xen_hvm_domain() || xen_have_vector_callback);
>   }
>   
> +extern bool xen_percpu_upcall;
>   #endif /* _ASM_X86_XEN_EVENTS_H */
> diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
> index 30c6e986a6cd..b8db2148c07d 100644
> --- a/arch/x86/xen/enlighten.c
> +++ b/arch/x86/xen/enlighten.c
> @@ -51,7 +51,7 @@ EXPORT_SYMBOL_GPL(xen_start_info);
>   
>   struct shared_info xen_dummy_shared_info;
>   
> -__read_mostly int xen_have_vector_callback;
> +__read_mostly bool xen_have_vector_callback = true;
>   EXPORT_SYMBOL_GPL(xen_have_vector_callback);
>   
>   /*
> diff --git a/arch/x86/xen/enlighten_hvm.c b/arch/x86/xen/enlighten_hvm.c
> index 8b71b1dd7639..198d3cd3e9a5 100644
> --- a/arch/x86/xen/enlighten_hvm.c
> +++ b/arch/x86/xen/enlighten_hvm.c
> @@ -7,6 +7,8 @@
>   
>   #include <xen/features.h>
>   #include <xen/events.h>
> +#include <xen/hvm.h>
> +#include <xen/interface/hvm/hvm_op.h>
>   #include <xen/interface/memory.h>
>   
>   #include <asm/apic.h>
> @@ -30,6 +32,9 @@
>   
>   static unsigned long shared_info_pfn;
>   
> +__ro_after_init bool xen_percpu_upcall;
> +EXPORT_SYMBOL_GPL(xen_percpu_upcall);
> +
>   void xen_hvm_init_shared_info(void)
>   {
>       struct xen_add_to_physmap xatp;
> @@ -125,6 +130,9 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_xen_hvm_callback)
>   {
>       struct pt_regs *old_regs = set_irq_regs(regs);
>   
> +     if (xen_percpu_upcall)
> +             ack_APIC_irq();
> +
>       inc_irq_stat(irq_hv_callback_count);
>   
>       xen_hvm_evtchn_do_upcall();
> @@ -168,6 +176,15 @@ static int xen_cpu_up_prepare_hvm(unsigned int cpu)
>       if (!xen_have_vector_callback)
>               return 0;
>   
> +     if (xen_percpu_upcall) {
> +             rc = xen_set_upcall_vector(cpu);
> +             if (rc) {
> +                     WARN(1, "HVMOP_set_evtchn_upcall_vector"
> +                          " for CPU %d failed: %d\n", cpu, rc);
> +                     return rc;
> +             }
> +     }
> +
>       if (xen_feature(XENFEAT_hvm_safe_pvclock))
>               xen_setup_timer(cpu);
>   
> @@ -188,8 +205,6 @@ static int xen_cpu_dead_hvm(unsigned int cpu)
>       return 0;
>   }
>   
> -static bool no_vector_callback __initdata;
> -
>   static void __init xen_hvm_guest_init(void)
>   {
>       if (xen_pv_domain())
> @@ -211,9 +226,6 @@ static void __init xen_hvm_guest_init(void)
>   
>       xen_panic_handler_init();
>   
> -     if (!no_vector_callback && xen_feature(XENFEAT_hvm_callback_vector))
> -             xen_have_vector_callback = 1;
> -
>       xen_hvm_smp_init();
>       WARN_ON(xen_cpuhp_setup(xen_cpu_up_prepare_hvm, xen_cpu_dead_hvm));
>       xen_unplug_emulated_devices();
> @@ -239,7 +251,7 @@ early_param("xen_nopv", xen_parse_nopv);
>   
>   static __init int xen_parse_no_vector_callback(char *arg)
>   {
> -     no_vector_callback = true;
> +     xen_have_vector_callback = false;
>       return 0;
>   }
>   early_param("xen_no_vector_callback", xen_parse_no_vector_callback);
> diff --git a/arch/x86/xen/suspend_hvm.c b/arch/x86/xen/suspend_hvm.c
> index 9d548b0c772f..0c4f7554b7cc 100644
> --- a/arch/x86/xen/suspend_hvm.c
> +++ b/arch/x86/xen/suspend_hvm.c
> @@ -5,6 +5,7 @@
>   #include <xen/hvm.h>
>   #include <xen/features.h>
>   #include <xen/interface/features.h>
> +#include <xen/events.h>
>   
>   #include "xen-ops.h"
>   
> @@ -14,6 +15,13 @@ void xen_hvm_post_suspend(int suspend_cancelled)
>               xen_hvm_init_shared_info();
>               xen_vcpu_restore();
>       }
> -     xen_setup_callback_vector();
> +     if (xen_percpu_upcall) {
> +             unsigned int cpu;
> +
> +             for_each_online_cpu(cpu)
> +                     BUG_ON(xen_set_upcall_vector(cpu));
> +     } else {
> +             xen_setup_callback_vector();
> +     }
>       xen_unplug_emulated_devices();
>   }
> diff --git a/drivers/xen/events/events_base.c 
> b/drivers/xen/events/events_base.c
> index 46d9295d9a6e..2ad93595d03a 100644
> --- a/drivers/xen/events/events_base.c
> +++ b/drivers/xen/events/events_base.c
> @@ -48,6 +48,7 @@
>   #include <asm/xen/pci.h>
>   #endif
>   #include <asm/sync_bitops.h>
> +#include <asm/xen/cpuid.h>
>   #include <asm/xen/hypercall.h>
>   #include <asm/xen/hypervisor.h>
>   #include <xen/page.h>
> @@ -2195,11 +2196,48 @@ void xen_setup_callback_vector(void)
>               callback_via = HVM_CALLBACK_VECTOR(HYPERVISOR_CALLBACK_VECTOR);
>               if (xen_set_callback_via(callback_via)) {
>                       pr_err("Request for Xen HVM callback vector failed\n");
> -                     xen_have_vector_callback = 0;
> +                     xen_have_vector_callback = false;
>               }
>       }
>   }
>   
> +/* Setup per-vCPU vector-type callbacks and trick toolstack to think
> + * we are enlightened. If this setup is unavailable, fallback to the
> + * global vector-type callback. */
> +static __init void xen_init_setup_upcall_vector(void)
> +{
> +     unsigned int cpu = 0;
> +
> +     if (!xen_have_vector_callback)
> +             return;
> +
> +     if ((cpuid_eax(xen_cpuid_base() + 4) & XEN_HVM_CPUID_UPCALL_VECTOR) &&
> +         !xen_set_upcall_vector(cpu) && !xen_set_callback_via(1))
I should have removed xen_set_callback_via(1) here. Will send another 
version, would just like to wait for any comments before I do.

Jane.

Reply via email to