[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [XEN][PATCH] xen/x86: guest_access: optimize raw_x_guest() for PV and HVM combinations



Le 31/10/2025 à 22:25, Grygorii Strashko a écrit :
> From: Grygorii Strashko <grygorii_strashko@xxxxxxxx>
>
> Xen uses below pattern for raw_x_guest() functions:
>
> define raw_copy_to_guest(dst, src, len)        \
>      (is_hvm_vcpu(current) ?                     \
>       copy_to_user_hvm((dst), (src), (len)) :    \
>       copy_to_guest_pv(dst, src, len))
>
> How this pattern is working depends on CONFIG_PV/CONFIG_HVM as:
> - PV=y and HVM=y
>    Proper guest access function is selected depending on domain type.
> - PV=y and HVM=n
>    Only PV domains are possible. is_hvm_domain/vcpu() will constify to "false"
>    and compiler will optimize code and skip HVM specific part.
> - PV=n and HVM=y
>    Only HVM domains are possible. is_hvm_domain/vcpu() will not be constified.
>    No PV specific code will be optimized by compiler.
> - PV=n and HVM=n
>    No guests should possible. The code will still follow PV path.
>
> Rework raw_x_guest() code to use required functions explicitly for each
> combination of CONFIG_PV/CONFIG_HVM with main intention to optimize code for
> (PV=n and HVM=y) case.
>
> For the case (PV=n and HVM=n) empty stubs are created which return (1)
> indicating failure. Hence, no guests should possible in this case -
> which means no access to guest memory  should ever happen.
> The two calls of __raw_copy_to_guest() in 
> common/domain.c->update_runstate_area()
> are fixed for this case by explicitly cast the return value to void
> (MISRA C Rule 17.7).
>
> Finally build arch/x86/usercopy.c only for PV=y.
>
> The measured (bloat-o-meter) improvement for (PV=n and HVM=y) case is:
>    add/remove: 0/10 grow/shrink: 2/90 up/down: 163/-30932 (-30769)
>    Total: Before=1937113, After=1906344, chg -1.59%
>
> Signed-off-by: Grygorii Strashko <grygorii_strashko@xxxxxxxx>
> ---
>   xen/arch/x86/Makefile                   |  2 +-
>   xen/arch/x86/include/asm/guest_access.h | 38 +++++++++++++++++++++++++
>   xen/common/domain.c                     | 10 ++++---
>   3 files changed, 45 insertions(+), 5 deletions(-)
>
> diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile
> index 407571c510e1..27f131ffeb61 100644
> --- a/xen/arch/x86/Makefile
> +++ b/xen/arch/x86/Makefile
> @@ -71,7 +71,7 @@ obj-y += time.o
>   obj-y += traps-setup.o
>   obj-y += traps.o
>   obj-$(CONFIG_INTEL) += tsx.o
> -obj-y += usercopy.o
> +obj-$(CONFIG_PV) += usercopy.o
>   obj-y += x86_emulate.o
>   obj-$(CONFIG_TBOOT) += tboot.o
>   obj-y += hpet.o
> diff --git a/xen/arch/x86/include/asm/guest_access.h 
> b/xen/arch/x86/include/asm/guest_access.h
> index 69716c8b41bb..36aeb89524ab 100644
> --- a/xen/arch/x86/include/asm/guest_access.h
> +++ b/xen/arch/x86/include/asm/guest_access.h
> @@ -13,6 +13,7 @@
>   #include <asm/hvm/guest_access.h>
>
>   /* Raw access functions: no type checking. */
> +#if defined(CONFIG_PV) && defined(CONFIG_HVM)
>   #define raw_copy_to_guest(dst, src, len)        \
>       (is_hvm_vcpu(current) ?                     \
>        copy_to_user_hvm((dst), (src), (len)) :    \
> @@ -34,6 +35,43 @@
>        copy_from_user_hvm((dst), (src), (len)) :  \
>        __copy_from_guest_pv(dst, src, len))
>
> +#elif defined(CONFIG_HVM)
> +#define raw_copy_to_guest(dst, src, len)        \
> +     copy_to_user_hvm((dst), (src), (len))
> +#define raw_copy_from_guest(dst, src, len)      \
> +     copy_from_user_hvm((dst), (src), (len))
> +#define raw_clear_guest(dst,  len)              \
> +     clear_user_hvm((dst), (len))
> +#define __raw_copy_to_guest(dst, src, len)      \
> +     copy_to_user_hvm((dst), (src), (len))
> +#define __raw_copy_from_guest(dst, src, len)    \
> +     copy_from_user_hvm((dst), (src), (len))
> +
> +#elif defined(CONFIG_PV)
> +#define raw_copy_to_guest(dst, src, len)        \
> +     copy_to_guest_pv(dst, src, len)
> +#define raw_copy_from_guest(dst, src, len)      \
> +     copy_from_guest_pv(dst, src, len)
> +#define raw_clear_guest(dst,  len)              \
> +     clear_guest_pv(dst, len)
> +#define __raw_copy_to_guest(dst, src, len)      \
> +     __copy_to_guest_pv(dst, src, len)
> +#define __raw_copy_from_guest(dst, src, len)    \
> +     __copy_from_guest_pv(dst, src, len)
> +
> +#else
> +#define raw_copy_to_guest(dst, src, len)        \
> +        ((void)(dst), (void)(src), (void)(len), 1)
> +#define raw_copy_from_guest(dst, src, len)      \
> +        ((void)(dst), (void)(src), (void)(len), 1)
> +#define raw_clear_guest(dst, len)               \
> +        ((void)(dst), (void)(len), 1)
> +#define __raw_copy_to_guest(dst, src, len)      \
> +        ((void)(dst), (void)(src), (void)(len), 1)
> +#define __raw_copy_from_guest(dst, src, len)    \
> +        ((void)(dst), (void)(src), (void)(len), 1)
> +#endif
> +
>   /*
>    * Pre-validate a guest handle.
>    * Allows use of faster __copy_* functions.
> diff --git a/xen/common/domain.c b/xen/common/domain.c
> index 4f91316ad93e..c603edcc7d46 100644
> --- a/xen/common/domain.c
> +++ b/xen/common/domain.c
> @@ -1985,8 +1985,9 @@ bool update_runstate_area(struct vcpu *v)
>   #endif
>           guest_handle--;
>           runstate.state_entry_time |= XEN_RUNSTATE_UPDATE;
> -        __raw_copy_to_guest(guest_handle,
> -                            (void *)(&runstate.state_entry_time + 1) - 1, 1);
> +        (void)__raw_copy_to_guest(guest_handle,
> +                                  (void *)(&runstate.state_entry_time + 1) - 
> 1,
> +                                  1);
>           smp_wmb();
>       }
>
> @@ -2008,8 +2009,9 @@ bool update_runstate_area(struct vcpu *v)
>       {
>           runstate.state_entry_time &= ~XEN_RUNSTATE_UPDATE;
>           smp_wmb();
> -        __raw_copy_to_guest(guest_handle,
> -                            (void *)(&runstate.state_entry_time + 1) - 1, 1);
> +        (void)__raw_copy_to_guest(guest_handle,
> +                                  (void *)(&runstate.state_entry_time + 1) - 
> 1,
> +                                  1);
>       }
>
>       update_guest_memory_policy(v, &policy);

Alternatively, we can make all the raw_* functions `static inline` and
have something like this which should have the same effect with much
less redundancy.

static inline
unsigned int raw_copy_to_user_hvm(void *to, const void *from,
                                   unsigned int len)
{
     if ( IS_ENABLED(CONFIG_HVM) &&
          (!IS_ENABLED(CONFIG_PV) || is_hvm_vcpu(current) )
        copy_to_user_hvm(to, from, len);
     else if ( IS_ENABLED(CONFIG_PV) )
        copy_to_guest_pv(to, from, len);
}

Teddy


--
Teddy Astie | Vates XCP-ng Developer

XCP-ng & Xen Orchestra - Vates solutions

web: https://vates.tech





 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.