[PATCH 02/10] target/arm: Correct value returned by pmu_counter_mask()

Peter Maydell posted 10 patches 3 years, 6 months ago
Maintainers: Peter Maydell <peter.maydell@linaro.org>
There is a newer version of this series
[PATCH 02/10] target/arm: Correct value returned by pmu_counter_mask()
Posted by Peter Maydell 3 years, 6 months ago
pmu_counter_mask() accidentally returns a value with bits [63:32]
set, because the expression it returns is evaluated as a signed value
that gets sign-extended to 64 bits.  Force the whole expression to be
evaluated with 64-bit arithmetic with ULL suffixes.

The main effect of this bug was that a guest could write to the bits
in the high half of registers like PMCNTENSET_EL0 that are supposed
to be RES0.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/internals.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/arm/internals.h b/target/arm/internals.h
index b8fefdff675..83526166de0 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1296,7 +1296,7 @@ static inline uint32_t pmu_num_counters(CPUARMState *env)
 /* Bits allowed to be set/cleared for PMCNTEN* and PMINTEN* */
 static inline uint64_t pmu_counter_mask(CPUARMState *env)
 {
-  return (1 << 31) | ((1 << pmu_num_counters(env)) - 1);
+  return (1ULL << 31) | ((1ULL << pmu_num_counters(env)) - 1);
 }
 
 #ifdef TARGET_AARCH64
-- 
2.25.1
Re: [PATCH 02/10] target/arm: Correct value returned by pmu_counter_mask()
Posted by Richard Henderson 3 years, 6 months ago
On 8/11/22 10:16, Peter Maydell wrote:
> pmu_counter_mask() accidentally returns a value with bits [63:32]
> set, because the expression it returns is evaluated as a signed value
> that gets sign-extended to 64 bits.  Force the whole expression to be
> evaluated with 64-bit arithmetic with ULL suffixes.
> 
> The main effect of this bug was that a guest could write to the bits
> in the high half of registers like PMCNTENSET_EL0 that are supposed
> to be RES0.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>   target/arm/internals.h | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/target/arm/internals.h b/target/arm/internals.h
> index b8fefdff675..83526166de0 100644
> --- a/target/arm/internals.h
> +++ b/target/arm/internals.h
> @@ -1296,7 +1296,7 @@ static inline uint32_t pmu_num_counters(CPUARMState *env)
>   /* Bits allowed to be set/cleared for PMCNTEN* and PMINTEN* */
>   static inline uint64_t pmu_counter_mask(CPUARMState *env)
>   {
> -  return (1 << 31) | ((1 << pmu_num_counters(env)) - 1);
> +  return (1ULL << 31) | ((1ULL << pmu_num_counters(env)) - 1);
>   }
>   
>   #ifdef TARGET_AARCH64
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~