|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [XEN v2 03/12] xen/Arm: vreg: Support vreg_reg64_* helpers on Aarch32
Hi Ayan,
On 31/10/2022 16:13, Ayan Kumar Halder wrote:
>
>
> In some situations (eg GICR_TYPER), the hypervior may need to emulate
> 64bit registers in aarch32 mode. In such situations, the hypervisor may
> need to read/modify the lower or upper 32 bits of the 64 bit register.
>
> In aarch32, 'unsigned long' is 32 bits. Thus, we cannot use it for 64 bit
> registers.
>
> The correct approach is to typecast 'mask' based on the size of register
> access
> (ie uint32_t or uint64_t) instead of using 'unsigned long' as it will not
> generate the correct mask for the upper 32 bits of a 64 bit register.
> Also, 'val' needs to be typecasted so that it can correctly update the upper/
> lower 32 bits of a 64 bit register.
>
> Signed-off-by: Ayan Kumar Halder <ayankuma@xxxxxxx>
> ---
>
> Changes from :-
> v1 - 1. Remove vreg_reg_extract(), vreg_reg_update(), vreg_reg_setbits() and
> vreg_reg_clearbits(). Moved the implementation to vreg_reg##sz##_*.
> 'mask' and 'val' is now using uint##sz##_t.
>
> xen/arch/arm/include/asm/vreg.h | 88 ++++++++-------------------------
> 1 file changed, 20 insertions(+), 68 deletions(-)
>
> diff --git a/xen/arch/arm/include/asm/vreg.h b/xen/arch/arm/include/asm/vreg.h
> index f26a70d024..122ea79b65 100644
> --- a/xen/arch/arm/include/asm/vreg.h
> +++ b/xen/arch/arm/include/asm/vreg.h
> @@ -89,107 +89,59 @@ static inline bool vreg_emulate_sysreg(struct
> cpu_user_regs *regs, union hsr hsr
> * The check on the size supported by the register has to be done by
> * the caller of vreg_regN_*.
> *
> - * vreg_reg_* should never be called directly. Instead use the vreg_regN_*
> - * according to size of the emulated register
> - *
> * Note that the alignment fault will always be taken in the guest
> * (see B3.12.7 DDI0406.b).
> */
> -static inline register_t vreg_reg_extract(unsigned long reg,
> - unsigned int offset,
> - enum dabt_size size)
> -{
> - reg >>= 8 * offset;
> - reg &= VREG_REG_MASK(size);
> -
> - return reg;
> -}
> -
> -static inline void vreg_reg_update(unsigned long *reg, register_t val,
> - unsigned int offset,
> - enum dabt_size size)
> -{
> - unsigned long mask = VREG_REG_MASK(size);
> - int shift = offset * 8;
> -
> - *reg &= ~(mask << shift);
> - *reg |= ((unsigned long)val & mask) << shift;
> -}
> -
> -static inline void vreg_reg_setbits(unsigned long *reg, register_t bits,
> - unsigned int offset,
> - enum dabt_size size)
> -{
> - unsigned long mask = VREG_REG_MASK(size);
> - int shift = offset * 8;
> -
> - *reg |= ((unsigned long)bits & mask) << shift;
> -}
> -
> -static inline void vreg_reg_clearbits(unsigned long *reg, register_t bits,
> - unsigned int offset,
> - enum dabt_size size)
> -{
> - unsigned long mask = VREG_REG_MASK(size);
> - int shift = offset * 8;
> -
> - *reg &= ~(((unsigned long)bits & mask) << shift);
> -}
>
> /* N-bit register helpers */
> #define VREG_REG_HELPERS(sz, offmask) \
> static inline register_t vreg_reg##sz##_extract(uint##sz##_t reg, \
> const mmio_info_t *info)\
> { \
> - return vreg_reg_extract(reg, info->gpa & (offmask), \
> - info->dabt.size); \
> + unsigned int offset = info->gpa & (offmask); \
In all the other helpers you are also defining the variables to store shift and
mask,
no matter the number of uses. I know that this is a left over from the removed
helpers,
but since you are modifying the file you could improve consistency and define
them
here as well.
> + \
> + reg >>= 8 * offset; \
> + reg &= VREG_REG_MASK(info->dabt.size); \
> + \
> + return reg; \
> } \
> \
> static inline void vreg_reg##sz##_update(uint##sz##_t *reg, \
> register_t val, \
> const mmio_info_t *info) \
> { \
> - unsigned long tmp = *reg; \
> - \
> - vreg_reg_update(&tmp, val, info->gpa & (offmask), \
> - info->dabt.size); \
> + unsigned int offset = info->gpa & (offmask); \
> + uint##sz##_t mask = VREG_REG_MASK(info->dabt.size); \
> + int shift = offset * 8; \
> \
> - *reg = tmp; \
> + *reg &= ~(mask << shift); \
> + *reg |= ((uint##sz##_t)val & mask) << shift; \
> } \
> \
> static inline void vreg_reg##sz##_setbits(uint##sz##_t *reg, \
> register_t bits, \
> const mmio_info_t *info) \
> { \
> - unsigned long tmp = *reg; \
> - \
> - vreg_reg_setbits(&tmp, bits, info->gpa & (offmask), \
> - info->dabt.size); \
> + unsigned int offset = info->gpa & (offmask); \
> + uint##sz##_t mask = VREG_REG_MASK(info->dabt.size); \
> + int shift = offset * 8; \
> \
> - *reg = tmp; \
> + *reg |= ((uint##sz##_t)bits & mask) << shift; \
> } \
> \
> static inline void vreg_reg##sz##_clearbits(uint##sz##_t *reg, \
> register_t bits, \
> const mmio_info_t *info) \
> { \
> - unsigned long tmp = *reg; \
> + unsigned int offset = info->gpa & (offmask); \
> + uint##sz##_t mask = VREG_REG_MASK(info->dabt.size); \
> + int shift = offset * 8; \
> \
> - vreg_reg_clearbits(&tmp, bits, info->gpa & (offmask), \
> - info->dabt.size); \
> - \
> - *reg = tmp; \
> + *reg &= ~(((uint##sz##_t)bits & mask) << shift); \
> }
>
> -/*
> - * 64 bits registers are only supported on platform with 64-bit long.
> - * This is also allow us to optimize the 32 bit case by using
> - * unsigned long rather than uint64_t
> - */
> -#if BITS_PER_LONG == 64
> -VREG_REG_HELPERS(64, 0x7);
> -#endif
> VREG_REG_HELPERS(32, 0x3);
> +VREG_REG_HELPERS(64, 0x7);
No need for the movement. 64 should stay as it was before 32 and you should only
remove the guards.
>
> #undef VREG_REG_HELPERS
>
> --
> 2.17.1
>
>
Apart from that, the change looks good.
~Michal
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |