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

Re: [Xen-devel] [PATCH 4/4] xen/public: arm: rework the macro set_xen_guest_handle_raw



On Fri, 30 Oct 2015, Julien Grall wrote:
> The current implementation of set_xen_guest_handle_raw is using the
> keyword "typeof" which is not part of C spec.
> 
> Furthermore, when the guest handle is defined in ARM32 guest, the
> pointer will always be smaller than the handle. Based on the C99 spec
> [1] 6.2.6.1#7, the bits that do not correspond to the member written
> will take unspecified value.
> 
> Finally, based on the defect report #283 [2], the behavior of writing
> from one member and reading from another is not clear.
> 
> We don't hit the problems for Xen and the toolstack because they are
> both built with strict aliasing disabled. However, this may not be true
> for any software using those headers.
> 
> We want to rewrite the macro set_xen_guest_handle_raw based on the
> following constraint:
>     1) typeof should not be used
>     2) the parameters of the macros should only be interpreted one time
>     3) the bits unused by the pointer should be zeroed
> 
> So we to have to zeroed the top 32-bit (for ARM32) and set the pointer
> in a single expression. This means that we have to use a 64-bit access
> via the field '.q' represent an uint64_t. Because of that we loose the
> type safety provided by the field '.p' storing the pointer. Two compile
> time checks have been added to ensure the validity of the handle and the
> data stored.
> 
> While we don't provide a generic macro to get the guest pointer from the
> handle, Xen obviously uses the guest pointer. As Xen is build with strict
> aliasing disabled, we don't have to worry to set and get the value in the
> union using different field. To avoid future issue, comments has been
> added in the public header and Xen guest access to explain the problem
> and why it works.
> 
> Note that set_xen_guest_handle_raw won't work with guest handle param.
> But this is fine as this kind of handle is only used within the
> hypervisor and updating the guest pointer for ARM guest will require
> more care. FWIW, the caller of set_xen_guest_handle_raw in the
> hypervisor are in compat code and kexec. None of them of build for ARM
> today.
> 
> Finally while we modify asm-arm/guest_access.h, fix a typo.
> 
> [1] http://cs.nyu.edu/courses/spring13/CSCI-GA.2110-001/downloads/C99.pdf
> [2] http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_283.htm
> 
> Signed-off-by: Julien Grall <julien.grall@xxxxxxxxxx>
> 
> ---
> 
> Cc: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
> Cc: Jan Beulich <jbeulich@xxxxxxxx>
> Cc: Keir Fraser <keir@xxxxxxx>
> Cc: Tim Deegan <tim@xxxxxxx>
> ---
>  xen/include/asm-arm/guest_access.h | 10 ++++++++++
>  xen/include/public/arch-arm.h      | 19 ++++++++++++++-----
>  2 files changed, 24 insertions(+), 5 deletions(-)
> 
> diff --git a/xen/include/asm-arm/guest_access.h 
> b/xen/include/asm-arm/guest_access.h
> index 5876988..fd2a849 100644
> --- a/xen/include/asm-arm/guest_access.h
> +++ b/xen/include/asm-arm/guest_access.h
> @@ -4,6 +4,16 @@
>  #include <xen/guest_access.h>
>  #include <xen/errno.h>
>  
> +/*
> + * Some of the macros within this file are using the field ".p" of the
> + * guest handle.
> + *
> + * While set_xen_guest_handle is always setting the handle using 64-bit
> + * access, the value is retrieved using the field ".p" which is 32-bit
> + * on ARM32 and 64-bit on ARM64. However, it's safe to use as Xen is built
> + * with strict aliasing disabled.
> + */
> +
>  /* Guests have their own comlete address space */
>  #define access_ok(addr,size) (1)
>  
> diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h
> index b278bc0..390f6f3 100644
> --- a/xen/include/public/arch-arm.h
> +++ b/xen/include/public/arch-arm.h
> @@ -193,11 +193,20 @@
>  #define XEN_GUEST_HANDLE_PARAM(name)    __guest_handle_param_ ## name
>  #endif
>  
> -#define set_xen_guest_handle_raw(hnd, val)                  \
> -    do {                                                    \
> -        typeof(&(hnd)) _sxghr_tmp = &(hnd);                 \
> -        _sxghr_tmp->q = 0;                                  \
> -        _sxghr_tmp->p = val;                                \
> +/*
> + * Macro to set a guest pointer in the handle.
> + *
> + * Note that it's not possible to implement safely a macro to retrieve the
> + * handle unless the guest is built with strict aliasing disabling.
> + * Hence, we don't provide a such macro in the public headers.
> + */
> +#define set_xen_guest_handle_raw(hnd, val)                              \
> +    do {                                                                \
> +        /* Check if the handle is 64-bit (i.e 8-byte) */                \
> +        (void) sizeof(struct { int : -!!(sizeof (hnd) != 8); });        \
> +        /* Check if the type of val is compatible with the handle */    \
> +        (void) sizeof((val) != (hnd).p);                                \
> +        (hnd).q = (uint64_t)(uintptr_t)(val);                           \
>      } while ( 0 )

Honestly I would be OK with having a typeof in the public headers to
avoid this code, which is much harder to follow. Why don't we do
something like the following:


diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h
index 9a96401..e676ffb 100644
--- a/xen/include/public/arch-arm.h
+++ b/xen/include/public/arch-arm.h
@@ -189,11 +189,12 @@
 #define __XEN_GUEST_HANDLE(name)        __guest_handle_64_ ## name
 #define XEN_GUEST_HANDLE(name)          __XEN_GUEST_HANDLE(name)
 #define XEN_GUEST_HANDLE_PARAM(name)    __guest_handle_ ## name
+#define barrier()     __asm__ __volatile__("": : :"memory")
 #define set_xen_guest_handle_raw(hnd, val)                  \
     do {                                                    \
-        typeof(&(hnd)) _sxghr_tmp = &(hnd);                 \
-        _sxghr_tmp->q = 0;                                  \
-        _sxghr_tmp->p = val;                                \
+        *((uint64_aligned_t *)&(hnd)) = 0;                  \
+        barrier();                                          \
+        (hnd).p = val;                                      \
     } while ( 0 )
 #ifdef __XEN_TOOLS__
 #define get_xen_guest_handle(val, hnd)  do { val = (hnd).p; } while (0)

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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