Hello,

Le 13/08/2025 à 20:07, Dmytro Prokopchuk1 a écrit :
> Misra Rule 11.1 states: "Conversions shall not be performed between a
> pointer to a function and any other type."
>
> The violation occurs in the macro:
>      __typeof__(**(ptr)) *const o_ = (o);                                \
>      __typeof__(**(ptr)) *n_ = (n);                                      \
>      ((__typeof__(*(ptr)))__cmpxchg(ptr, (unsigned long)o_,              \
>                                     (unsigned long)n_, sizeof(*(ptr)))); \
> })
> when it is used for handling function pointers of type:
> typedef void (*)(struct vcpu *, unsigned int).
> The issue happens because the '__cmpxchg()' function returns an 'unsigned
> long', which is then converted back into a function pointer, causing a
> violation of Rule 11.1. In this particular usage, the return value of the
> macro 'cmpxchgptr()' is not required. To address the violation, the macro
> has been replaced to discard the return value of '__cmpxchg()', preventing
> the conversion.
>
> Signed-off-by: Dmytro Prokopchuk <dmytro_prokopch...@epam.com>
> ---
> Probably separate macro is too much for this single case.
>
> And the following will be enought:
> __cmpxchg(&xen_consumers[i], (unsigned long)NULL, (unsigned long)fn, 
> sizeof(*(&xen_consumers[i])));
> ---
>   xen/common/event_channel.c | 15 +++++++++++++--
>   1 file changed, 13 insertions(+), 2 deletions(-)
>
> diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c
> index 67700b050a..2094338b28 100644
> --- a/xen/common/event_channel.c
> +++ b/xen/common/event_channel.c
> @@ -93,6 +93,17 @@ static void cf_check default_xen_notification_fn(
>           vcpu_wake(v);
>   }
>
> +/*
> + * A slightly more updated variant of cmpxchgptr() where old value
> + * is not returned.
> + */
> +#define cmpxchgptr_noret(ptr, o, n) ({                  \
> +    __typeof__(**(ptr)) *const o_ = (o);                \
> +    __typeof__(**(ptr)) *n_ = (n);                      \
> +    (void)__cmpxchg(ptr, (unsigned long)o_,             \
> +                    (unsigned long)n_, sizeof(*(ptr))); \
> +})
> +
>   /*
>    * Given a notification function, return the value to stash in
>    * the evtchn->xen_consumer field.
> @@ -106,9 +117,9 @@ static uint8_t 
> get_xen_consumer(xen_event_channel_notification_t fn)
>
>       for ( i = 0; i < ARRAY_SIZE(xen_consumers); i++ )
>       {
> -        /* Use cmpxchgptr() in lieu of a global lock. */
> +        /* Use cmpxchgptr_noret() in lieu of a global lock. */
>           if ( xen_consumers[i] == NULL )
> -            cmpxchgptr(&xen_consumers[i], NULL, fn);
> +            cmpxchgptr_noret(&xen_consumers[i], NULL, fn);
>           if ( xen_consumers[i] == fn )
>               break;
>       }

AFAICS, Rule 11.1 has a deviation which allows this specific case.

In docs/misra/deviations.rst
> * - R11.1
>   - The conversion from a function pointer to unsigned long or (void \*) does
>     not lose any information, provided that the target type has enough bits
>     to store it.
>   - Tagged as `safe` for ECLAIR.

Here, we are constructing a function pointer from a unsigned long. I
assume this rule goes the other way it says, and allow converting a
unsigned long into a function pointer as long as its value is a valid
function pointer.

Teddy


Teddy Astie | Vates XCP-ng Developer

XCP-ng & Xen Orchestra - Vates solutions

web: https://vates.tech



Reply via email to