All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] target/arm: Enforce implemented granule size limits
@ 2022-09-30 17:48 Peter Maydell
  2022-09-30 17:48 ` [PATCH 1/2] target/arm: Don't allow guest to use unimplemented granule sizes Peter Maydell
  2022-09-30 17:48 ` [PATCH 2/2] docs/system/arm/emulation.rst: Report FEAT_GTG support Peter Maydell
  0 siblings, 2 replies; 7+ messages in thread
From: Peter Maydell @ 2022-09-30 17:48 UTC (permalink / raw)
  To: qemu-arm, qemu-devel

Arm CPUs support some subset of the granule (page) sizes 4K, 16K and
64K.  The guest selects the one it wants using bits in the TCR_ELx
registers.  If it tries to program these registers with a value that
is either reserved or which requests a size that the CPU does not
implement, the architecture requires that the CPU behaves as if the
field was programmed to some size that has been implemented.
Currently we don't implement this, and instead let the guest use any
granule size, even if the CPU ID register fields say it isn't
present.

Patch 1 in this series makes us enforce this architectural
requirement (the main effect will be that we stop incorrectly
implementing 16K granules on most of the non-cpu-max CPUs).

Patch 2 adds FEAT_GTG to the list of supported features, because
all this feature really is is the definition of the separate
fields for stage1 and stage2 granule support in ID_AA64MMFR0_EL1,
and we already updated -cpu max to report its granule support
that way when we were adding the LPA2 support.

thanks
-- PMM

Peter Maydell (2):
  target/arm: Don't allow guest to use unimplemented granule sizes
  docs/system/arm/emulation.rst: Report FEAT_GTG support

 docs/system/arm/emulation.rst |   1 +
 target/arm/cpu.h              |  33 ++++++++++
 target/arm/helper.c           | 110 +++++++++++++++++++++++++++++++---
 3 files changed, 136 insertions(+), 8 deletions(-)

-- 
2.25.1



^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/2] target/arm: Don't allow guest to use unimplemented granule sizes
  2022-09-30 17:48 [PATCH 0/2] target/arm: Enforce implemented granule size limits Peter Maydell
@ 2022-09-30 17:48 ` Peter Maydell
  2022-09-30 20:14   ` Richard Henderson
  2022-09-30 17:48 ` [PATCH 2/2] docs/system/arm/emulation.rst: Report FEAT_GTG support Peter Maydell
  1 sibling, 1 reply; 7+ messages in thread
From: Peter Maydell @ 2022-09-30 17:48 UTC (permalink / raw)
  To: qemu-arm, qemu-devel

Arm CPUs support some subset of the granule (page) sizes 4K, 16K and
64K.  The guest selects the one it wants using bits in the TCR_ELx
registers.  If it tries to program these registers with a value that
is either reserved or which requests a size that the CPU does not
implement, the architecture requires that the CPU behaves as if the
field was programmed to some size that has been implemented.
Currently we don't implement this, and instead let the guest use any
granule size, even if the CPU ID register fields say it isn't
present.

Make aa64_va_parameters() check against the supported granule size
and force use of a different one if it is not implemented.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
Unusually, the architecture would allow us to do this sanitizing
when the TCR_ELx register is written, because it permits that the
value of the register read back can be one corresponding to the
IMPDEF chosen size rather than having to be the value written.
But I opted to do the handling in aa64_va_parameters() anyway,
on the assumption that this isn't critically in the fast path.
---
 target/arm/cpu.h    |  33 +++++++++++++
 target/arm/helper.c | 110 ++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 135 insertions(+), 8 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 33cdbc0143e..6d39d27378d 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -4103,6 +4103,39 @@ static inline bool isar_feature_aa64_tgran16_2_lpa2(const ARMISARegisters *id)
     return t >= 3 || (t == 0 && isar_feature_aa64_tgran16_lpa2(id));
 }
 
+static inline bool isar_feature_aa64_tgran4(const ARMISARegisters *id)
+{
+    return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4) >= 0;
+}
+
+static inline bool isar_feature_aa64_tgran16(const ARMISARegisters *id)
+{
+    return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16) >= 1;
+}
+
+static inline bool isar_feature_aa64_tgran64(const ARMISARegisters *id)
+{
+    return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN64) >= 0;
+}
+
+static inline bool isar_feature_aa64_tgran4_2(const ARMISARegisters *id)
+{
+    unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4_2);
+    return t >= 2 || (t == 0 && isar_feature_aa64_tgran4(id));
+}
+
+static inline bool isar_feature_aa64_tgran16_2(const ARMISARegisters *id)
+{
+    unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16_2);
+    return t >= 2 || (t == 0 && isar_feature_aa64_tgran16(id));
+}
+
+static inline bool isar_feature_aa64_tgran64_2(const ARMISARegisters *id)
+{
+    unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN64_2);
+    return t >= 2 || (t == 0 && isar_feature_aa64_tgran64(id));
+}
+
 static inline bool isar_feature_aa64_ccidx(const ARMISARegisters *id)
 {
     return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, CCIDX) != 0;
diff --git a/target/arm/helper.c b/target/arm/helper.c
index b5dac651e75..7c4eea58739 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -10289,20 +10289,113 @@ static int aa64_va_parameter_tcma(uint64_t tcr, ARMMMUIdx mmu_idx)
     }
 }
 
+typedef enum GranuleSize {
+    /* Same order as TG0 encoding */
+    Gran4K,
+    Gran64K,
+    Gran16K,
+    GranInvalid,
+} GranuleSize;
+
+static GranuleSize tg0_to_gran_size(int tg)
+{
+    switch (tg) {
+    case 0:
+        return Gran4K;
+    case 1:
+        return Gran64K;
+    case 2:
+        return Gran16K;
+    default:
+        return GranInvalid;
+    }
+}
+
+static GranuleSize tg1_to_gran_size(int tg)
+{
+    switch (tg) {
+    case 1:
+        return Gran16K;
+    case 2:
+        return Gran4K;
+    case 3:
+        return Gran64K;
+    default:
+        return GranInvalid;
+    }
+}
+
+static inline bool have4k(ARMCPU *cpu, bool stage2)
+{
+    return stage2 ? cpu_isar_feature(aa64_tgran4_2, cpu)
+        : cpu_isar_feature(aa64_tgran4, cpu);
+}
+
+static inline bool have16k(ARMCPU *cpu, bool stage2)
+{
+    return stage2 ? cpu_isar_feature(aa64_tgran16_2, cpu)
+        : cpu_isar_feature(aa64_tgran16, cpu);
+}
+
+static inline bool have64k(ARMCPU *cpu, bool stage2)
+{
+    return stage2 ? cpu_isar_feature(aa64_tgran64_2, cpu)
+        : cpu_isar_feature(aa64_tgran64, cpu);
+}
+
+static GranuleSize sanitize_gran_size(ARMCPU *cpu, GranuleSize gran,
+                                      bool stage2)
+{
+    switch (gran) {
+    case Gran4K:
+        if (have4k(cpu, stage2)) {
+            return gran;
+        }
+        break;
+    case Gran16K:
+        if (have16k(cpu, stage2)) {
+            return gran;
+        }
+        break;
+    case Gran64K:
+        if (have64k(cpu, stage2)) {
+            return gran;
+        }
+        break;
+    case GranInvalid:
+        break;
+    }
+    /*
+     * If the guest selects a granule size that isn't implemented,
+     * the architecture requires that we behave as if it selected one
+     * that is (with an IMPDEF choice of which one to pick). We choose
+     * to implement the smallest supported granule size.
+     */
+    if (have4k(cpu, stage2)) {
+        return Gran4K;
+    }
+    if (have16k(cpu, stage2)) {
+        return Gran16K;
+    }
+    assert(have64k(cpu, stage2));
+    return Gran64K;
+}
+
 ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
                                    ARMMMUIdx mmu_idx, bool data)
 {
     uint64_t tcr = regime_tcr(env, mmu_idx);
     bool epd, hpd, using16k, using64k, tsz_oob, ds;
     int select, tsz, tbi, max_tsz, min_tsz, ps, sh;
+    GranuleSize gran;
     ARMCPU *cpu = env_archcpu(env);
+    bool stage2 = mmu_idx == ARMMMUIdx_Stage2 || mmu_idx == ARMMMUIdx_Stage2_S;
 
     if (!regime_has_2_ranges(mmu_idx)) {
         select = 0;
         tsz = extract32(tcr, 0, 6);
-        using64k = extract32(tcr, 14, 1);
-        using16k = extract32(tcr, 15, 1);
-        if (mmu_idx == ARMMMUIdx_Stage2 || mmu_idx == ARMMMUIdx_Stage2_S) {
+        gran = tg0_to_gran_size(extract32(tcr, 14, 2));
+        if (stage2) {
             /* VTCR_EL2 */
             hpd = false;
         } else {
@@ -10320,16 +10413,13 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
         select = extract64(va, 55, 1);
         if (!select) {
             tsz = extract32(tcr, 0, 6);
+            gran = tg0_to_gran_size(extract32(tcr, 14, 2));
             epd = extract32(tcr, 7, 1);
             sh = extract32(tcr, 12, 2);
-            using64k = extract32(tcr, 14, 1);
-            using16k = extract32(tcr, 15, 1);
             hpd = extract64(tcr, 41, 1);
         } else {
-            int tg = extract32(tcr, 30, 2);
-            using16k = tg == 1;
-            using64k = tg == 3;
             tsz = extract32(tcr, 16, 6);
+            gran = tg1_to_gran_size(extract32(tcr, 30, 2));
             epd = extract32(tcr, 23, 1);
             sh = extract32(tcr, 28, 2);
             hpd = extract64(tcr, 42, 1);
@@ -10338,6 +10428,10 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
         ds = extract64(tcr, 59, 1);
     }
 
+    gran = sanitize_gran_size(cpu, gran, stage2);
+    using64k = gran == Gran64K;
+    using16k = gran == Gran16K;
+
     if (cpu_isar_feature(aa64_st, cpu)) {
         max_tsz = 48 - using64k;
     } else {
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/2] docs/system/arm/emulation.rst: Report FEAT_GTG support
  2022-09-30 17:48 [PATCH 0/2] target/arm: Enforce implemented granule size limits Peter Maydell
  2022-09-30 17:48 ` [PATCH 1/2] target/arm: Don't allow guest to use unimplemented granule sizes Peter Maydell
@ 2022-09-30 17:48 ` Peter Maydell
  2022-09-30 20:15   ` Richard Henderson
  1 sibling, 1 reply; 7+ messages in thread
From: Peter Maydell @ 2022-09-30 17:48 UTC (permalink / raw)
  To: qemu-arm, qemu-devel

FEAT_GTG is a change tho the ID register ID_AA64MMFR0_EL1 so that it
can report a different set of supported granule (page) sizes for
stage 1 and stage 2 translation tables.  As of commit c20281b2a5048
we already report the granule sizes that way for '-cpu max', and now
we also correctly make attempts to use unimplemented granule sizes
fail, so we can report the support of the feature in the
documentation.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 docs/system/arm/emulation.rst | 1 +
 1 file changed, 1 insertion(+)

diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
index be7bbffe595..cfb4b0768b0 100644
--- a/docs/system/arm/emulation.rst
+++ b/docs/system/arm/emulation.rst
@@ -31,6 +31,7 @@ the following architecture extensions:
 - FEAT_FRINTTS (Floating-point to integer instructions)
 - FEAT_FlagM (Flag manipulation instructions v2)
 - FEAT_FlagM2 (Enhancements to flag manipulation instructions)
+- FEAT_GTG (Guest translation granule size)
 - FEAT_HCX (Support for the HCRX_EL2 register)
 - FEAT_HPDS (Hierarchical permission disables)
 - FEAT_I8MM (AArch64 Int8 matrix multiplication instructions)
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/2] target/arm: Don't allow guest to use unimplemented granule sizes
  2022-09-30 17:48 ` [PATCH 1/2] target/arm: Don't allow guest to use unimplemented granule sizes Peter Maydell
@ 2022-09-30 20:14   ` Richard Henderson
  2022-10-03 10:28     ` Peter Maydell
  0 siblings, 1 reply; 7+ messages in thread
From: Richard Henderson @ 2022-09-30 20:14 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel

On 9/30/22 10:48, Peter Maydell wrote:
> @@ -10289,20 +10289,113 @@ static int aa64_va_parameter_tcma(uint64_t tcr, ARMMMUIdx mmu_idx)
>       }
>   }
>   
> +typedef enum GranuleSize {
> +    /* Same order as TG0 encoding */
> +    Gran4K,
> +    Gran64K,
> +    Gran16K,
> +    GranInvalid,
> +} GranuleSize;

It might be worth using this in ARMVAParameters. Even if you don't do that now, it would 
be worth putting this typedef in internals.h.

Otherwise,
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>


r~


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/2] docs/system/arm/emulation.rst: Report FEAT_GTG support
  2022-09-30 17:48 ` [PATCH 2/2] docs/system/arm/emulation.rst: Report FEAT_GTG support Peter Maydell
@ 2022-09-30 20:15   ` Richard Henderson
  0 siblings, 0 replies; 7+ messages in thread
From: Richard Henderson @ 2022-09-30 20:15 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel

On 9/30/22 10:48, Peter Maydell wrote:
> FEAT_GTG is a change tho the ID register ID_AA64MMFR0_EL1 so that it
> can report a different set of supported granule (page) sizes for
> stage 1 and stage 2 translation tables.  As of commit c20281b2a5048
> we already report the granule sizes that way for '-cpu max', and now
> we also correctly make attempts to use unimplemented granule sizes
> fail, so we can report the support of the feature in the
> documentation.
> 
> Signed-off-by: Peter Maydell<peter.maydell@linaro.org>
> ---
>   docs/system/arm/emulation.rst | 1 +
>   1 file changed, 1 insertion(+)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/2] target/arm: Don't allow guest to use unimplemented granule sizes
  2022-09-30 20:14   ` Richard Henderson
@ 2022-10-03 10:28     ` Peter Maydell
  2022-10-03 13:46       ` Richard Henderson
  0 siblings, 1 reply; 7+ messages in thread
From: Peter Maydell @ 2022-10-03 10:28 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-arm, qemu-devel

On Fri, 30 Sept 2022 at 22:05, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> On 9/30/22 10:48, Peter Maydell wrote:
> > @@ -10289,20 +10289,113 @@ static int aa64_va_parameter_tcma(uint64_t tcr, ARMMMUIdx mmu_idx)
> >       }
> >   }
> >
> > +typedef enum GranuleSize {
> > +    /* Same order as TG0 encoding */
> > +    Gran4K,
> > +    Gran64K,
> > +    Gran16K,
> > +    GranInvalid,
> > +} GranuleSize;
>
> It might be worth using this in ARMVAParameters. Even if you don't do that now, it would
> be worth putting this typedef in internals.h.

I'd assumed you had a reason for using two bools rather than
an enum in ARMVAParameters, so I left that alone :-) But it would
make more sense to consistently use GranuleSize. (I guess for
putting it in internals.h it ought to be named ARMGranSize.)

Putting GranuleSize into ARMVAParameters brings us into the
area of enums in bitfields, where I'm not sure exactly what
the standard says or our supported compilers allow as an
impdef extension.
 GranuleSize gsize : 2;
seems to work, but is it portable? Or should I just put
 GranuleSize gsize;
and accept that that means the ARMVAParameters goes from
4 bytes to 8 bytes in size?

thanks
-- PMM


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/2] target/arm: Don't allow guest to use unimplemented granule sizes
  2022-10-03 10:28     ` Peter Maydell
@ 2022-10-03 13:46       ` Richard Henderson
  0 siblings, 0 replies; 7+ messages in thread
From: Richard Henderson @ 2022-10-03 13:46 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-arm, qemu-devel

On 10/3/22 03:28, Peter Maydell wrote:
> I'd assumed you had a reason for using two bools rather than
> an enum in ARMVAParameters, so I left that alone :-)

I think it was because the existing code had variables of those names, so the patch 
changed "foo" to "param.foo".  :-)

> Putting GranuleSize into ARMVAParameters brings us into the
> area of enums in bitfields, where I'm not sure exactly what
> the standard says or our supported compilers allow as an
> impdef extension.
>   GranuleSize gsize : 2;
> seems to work, but is it portable?

I think so.  Leastwise, we use those elsewhere.  I would certainly expect a warning from 
any of our supported compilers if we were to use too few bits for the enum type.


r~


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2022-10-03 13:51 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-30 17:48 [PATCH 0/2] target/arm: Enforce implemented granule size limits Peter Maydell
2022-09-30 17:48 ` [PATCH 1/2] target/arm: Don't allow guest to use unimplemented granule sizes Peter Maydell
2022-09-30 20:14   ` Richard Henderson
2022-10-03 10:28     ` Peter Maydell
2022-10-03 13:46       ` Richard Henderson
2022-09-30 17:48 ` [PATCH 2/2] docs/system/arm/emulation.rst: Report FEAT_GTG support Peter Maydell
2022-09-30 20:15   ` Richard Henderson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.