qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 00/10] target/arm: more HCR bits, improve syndrome reporting
@ 2018-10-12 14:42 Peter Maydell
  2018-10-12 14:42 ` [Qemu-devel] [PATCH 01/10] target/arm: Improve debug logging of AArch32 exception return Peter Maydell
                   ` (9 more replies)
  0 siblings, 10 replies; 21+ messages in thread
From: Peter Maydell @ 2018-10-12 14:42 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: patches

I'm currently trying to track down why my AArch32 Hyp mode
test images don't work, and thought I'd start by patching
a few of the holes we have in our implementation. (Haven't
found the problem yet, sadly.)

This patchset:
 * implements HCR.{FB,DC,VI,VF,PTW}
 * fixes ISR_EL1 in the virtual-interrupts case
 * fixes some syndrome reporting corner cases where AArch32
   or v7 differ from AArch64/v8
 * throws in a couple of minor code cleanups

The remaining unimplemented HCR trap bits (as of v8.0) are:
 * TID0 TID1 TID2 TID3 TIDCP TAC TSW TPC TPU TTLB TVM TRVM TDZ
   -- these are all "trap on various system register accesses"
 * AMO VA
   -- these require support for presenting the guest with a
      virtual asynchronous abort/SError

(We also don't yet implement HCR.TASE, which is interesting
because it requires trapping ASIMD-but-not-FP, which we don't
currently have support for in translate.c. This would also
be needed for CPACR.ASEDIS.)

thanks
-- PMM

Peter Maydell (10):
  target/arm: Improve debug logging of AArch32 exception return
  target/arm: Make switch_mode() file-local
  target/arm: Implement HCR.FB
  target/arm: Implement HCR.DC
  target/arm: ISR_EL1 bits track virtual interrupts if IMO/FMO set
  target/arm: Implement HCR.VI and VF
  target/arm: Implement HCR.PTW
  target/arm: New utility function to extract EC from syndrome
  target/arm: Get IL bit correct for v7 syndrome values
  target/arm: Report correct syndrome for FP/SIMD traps to Hyp mode

 target/arm/internals.h |  45 +++++-
 target/arm/helper.c    | 347 ++++++++++++++++++++++++++++++-----------
 target/arm/kvm64.c     |   2 +-
 target/arm/op_helper.c |   2 +-
 target/arm/translate.c |  15 +-
 5 files changed, 302 insertions(+), 109 deletions(-)

-- 
2.19.0

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

* [Qemu-devel] [PATCH 01/10] target/arm: Improve debug logging of AArch32 exception return
  2018-10-12 14:42 [Qemu-devel] [PATCH 00/10] target/arm: more HCR bits, improve syndrome reporting Peter Maydell
@ 2018-10-12 14:42 ` Peter Maydell
  2018-10-14 16:12   ` Richard Henderson
  2018-10-12 14:42 ` [Qemu-devel] [PATCH 02/10] target/arm: Make switch_mode() file-local Peter Maydell
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 21+ messages in thread
From: Peter Maydell @ 2018-10-12 14:42 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: patches

For AArch32, exception return happens through certain kinds
of CPSR write. We don't currently have any CPU_LOG_INT logging
of these events (unlike AArch64, where we log in the ERET
instruction). Add some suitable logging.

This will log exception returns like this:
Exception return from AArch32 hyp to usr PC 0x80100374

paralleling the existing logging in the exception_return
helper for AArch64 exception returns:
Exception return from AArch64 EL2 to AArch64 EL0 PC 0x8003045c
Exception return from AArch64 EL2 to AArch32 EL0 PC 0x8003045c

(Note that an AArch32 exception return can only be
AArch32->AArch32, never to AArch64.)

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/internals.h | 18 ++++++++++++++++++
 target/arm/helper.c    | 10 ++++++++++
 target/arm/translate.c |  7 +------
 3 files changed, 29 insertions(+), 6 deletions(-)

diff --git a/target/arm/internals.h b/target/arm/internals.h
index a4fc709bcc7..abe4d73b59c 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -840,4 +840,22 @@ static inline uint32_t v7m_sp_limit(CPUARMState *env)
     }
 }
 
+/**
+ * aarch32_mode_name(): Return name of the AArch32 CPU mode
+ * @psr: Program Status Register indicating CPU mode
+ *
+ * Returns, for debug logging purposes, a printable representation
+ * of the AArch32 CPU mode ("svc", "usr", etc) as indicated by
+ * the low bits of the specified PSR.
+ */
+static inline const char *aarch32_mode_name(uint32_t psr)
+{
+    static const char * const cpu_mode_names[16] = {
+        "usr", "fiq", "irq", "svc", "???", "???", "mon", "abt",
+        "???", "???", "hyp", "und", "???", "???", "???", "sys"
+    };
+
+    return cpu_mode_names[psr & 0xf];
+}
+
 #endif
diff --git a/target/arm/helper.c b/target/arm/helper.c
index e3368e7edc5..0fa5ac0450f 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -6205,7 +6205,17 @@ void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask,
                 mask |= CPSR_IL;
                 val |= CPSR_IL;
             }
+            qemu_log_mask(LOG_GUEST_ERROR,
+                          "Illegal AArch32 mode switch attempt from %s to %s\n",
+                          aarch32_mode_name(env->uncached_cpsr),
+                          aarch32_mode_name(val));
         } else {
+            qemu_log_mask(CPU_LOG_INT, "%s %s to %s PC 0x%" PRIx32 "\n",
+                          write_type == CPSRWriteExceptionReturn ?
+                          "Exception return from AArch32" :
+                          "AArch32 mode switch from",
+                          aarch32_mode_name(env->uncached_cpsr),
+                          aarch32_mode_name(val), env->regs[15]);
             switch_mode(env, val & CPSR_M);
         }
     }
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 1b4bacb522b..7c7d920e331 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -13092,11 +13092,6 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
     translator_loop(ops, &dc.base, cpu, tb);
 }
 
-static const char *cpu_mode_names[16] = {
-  "usr", "fiq", "irq", "svc", "???", "???", "mon", "abt",
-  "???", "???", "hyp", "und", "???", "???", "???", "sys"
-};
-
 void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
                         int flags)
 {
@@ -13162,7 +13157,7 @@ void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
                     psr & CPSR_V ? 'V' : '-',
                     psr & CPSR_T ? 'T' : 'A',
                     ns_status,
-                    cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
+                    aarch32_mode_name(psr), (psr & 0x10) ? 32 : 26);
     }
 
     if (flags & CPU_DUMP_FPU) {
-- 
2.19.0

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

* [Qemu-devel] [PATCH 02/10] target/arm: Make switch_mode() file-local
  2018-10-12 14:42 [Qemu-devel] [PATCH 00/10] target/arm: more HCR bits, improve syndrome reporting Peter Maydell
  2018-10-12 14:42 ` [Qemu-devel] [PATCH 01/10] target/arm: Improve debug logging of AArch32 exception return Peter Maydell
@ 2018-10-12 14:42 ` Peter Maydell
  2018-10-14 16:13   ` Richard Henderson
  2018-10-12 14:42 ` [Qemu-devel] [PATCH 03/10] target/arm: Implement HCR.FB Peter Maydell
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 21+ messages in thread
From: Peter Maydell @ 2018-10-12 14:42 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: patches

The switch_mode() function is defined in target/arm/helper.c and used
only in that file and nowhere else, so we can make it file-local
rather than global.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/internals.h | 1 -
 target/arm/helper.c    | 6 ++++--
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/target/arm/internals.h b/target/arm/internals.h
index abe4d73b59c..d4b1973efa1 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -145,7 +145,6 @@ static inline int bank_number(int mode)
     g_assert_not_reached();
 }
 
-void switch_mode(CPUARMState *, int);
 void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu);
 void arm_translate_init(void);
 
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 0fa5ac0450f..0253a971099 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -56,6 +56,8 @@ static void v8m_security_lookup(CPUARMState *env, uint32_t address,
                                 V8M_SAttributes *sattrs);
 #endif
 
+static void switch_mode(CPUARMState *env, int mode);
+
 static int vfp_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg)
 {
     int nregs;
@@ -6313,7 +6315,7 @@ uint32_t HELPER(v7m_tt)(CPUARMState *env, uint32_t addr, uint32_t op)
     return 0;
 }
 
-void switch_mode(CPUARMState *env, int mode)
+static void switch_mode(CPUARMState *env, int mode)
 {
     ARMCPU *cpu = arm_env_get_cpu(env);
 
@@ -6335,7 +6337,7 @@ void aarch64_sync_64_to_32(CPUARMState *env)
 
 #else
 
-void switch_mode(CPUARMState *env, int mode)
+static void switch_mode(CPUARMState *env, int mode)
 {
     int old_mode;
     int i;
-- 
2.19.0

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

* [Qemu-devel] [PATCH 03/10] target/arm: Implement HCR.FB
  2018-10-12 14:42 [Qemu-devel] [PATCH 00/10] target/arm: more HCR bits, improve syndrome reporting Peter Maydell
  2018-10-12 14:42 ` [Qemu-devel] [PATCH 01/10] target/arm: Improve debug logging of AArch32 exception return Peter Maydell
  2018-10-12 14:42 ` [Qemu-devel] [PATCH 02/10] target/arm: Make switch_mode() file-local Peter Maydell
@ 2018-10-12 14:42 ` Peter Maydell
  2018-10-14 16:21   ` Richard Henderson
  2018-10-12 14:42 ` [Qemu-devel] [PATCH 04/10] target/arm: Implement HCR.DC Peter Maydell
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 21+ messages in thread
From: Peter Maydell @ 2018-10-12 14:42 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: patches

The HCR.FB virtualization configuration register bit requests that
TLB maintenance, branch predictor invalidate-all and icache
invalidate-all operations performed in NS EL1 should be upgraded
from "local CPU only to "broadcast within Inner Shareable domain".
For QEMU we NOP the branch predictor and icache operations, so
we only need to upgrade the TLB invalidates:
 AArch32 TLBIALL, TLBIMVA, TLBIASID, DTLBIALL, DTLBIMVA, DTLBIASID,
         ITLBIALL, ITLBIMVA, ITLBIASID, TLBIMVAA, TLBIMVAL, TLBIMVAAL
 AArch64 TLBI VMALLE1, TLBI VAE1, TLBI ASIDE1, TLBI VAAE1,
         TLBI VALE1, TLBI VAALE1

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/helper.c | 191 +++++++++++++++++++++++++++-----------------
 1 file changed, 116 insertions(+), 75 deletions(-)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 0253a971099..cbec6844a44 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -554,42 +554,6 @@ static void contextidr_write(CPUARMState *env, const ARMCPRegInfo *ri,
     raw_write(env, ri, value);
 }
 
-static void tlbiall_write(CPUARMState *env, const ARMCPRegInfo *ri,
-                          uint64_t value)
-{
-    /* Invalidate all (TLBIALL) */
-    ARMCPU *cpu = arm_env_get_cpu(env);
-
-    tlb_flush(CPU(cpu));
-}
-
-static void tlbimva_write(CPUARMState *env, const ARMCPRegInfo *ri,
-                          uint64_t value)
-{
-    /* Invalidate single TLB entry by MVA and ASID (TLBIMVA) */
-    ARMCPU *cpu = arm_env_get_cpu(env);
-
-    tlb_flush_page(CPU(cpu), value & TARGET_PAGE_MASK);
-}
-
-static void tlbiasid_write(CPUARMState *env, const ARMCPRegInfo *ri,
-                           uint64_t value)
-{
-    /* Invalidate by ASID (TLBIASID) */
-    ARMCPU *cpu = arm_env_get_cpu(env);
-
-    tlb_flush(CPU(cpu));
-}
-
-static void tlbimvaa_write(CPUARMState *env, const ARMCPRegInfo *ri,
-                           uint64_t value)
-{
-    /* Invalidate single entry by MVA, all ASIDs (TLBIMVAA) */
-    ARMCPU *cpu = arm_env_get_cpu(env);
-
-    tlb_flush_page(CPU(cpu), value & TARGET_PAGE_MASK);
-}
-
 /* IS variants of TLB operations must affect all cores */
 static void tlbiall_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
                              uint64_t value)
@@ -623,6 +587,73 @@ static void tlbimvaa_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
     tlb_flush_page_all_cpus_synced(cs, value & TARGET_PAGE_MASK);
 }
 
+/*
+ * Non-IS variants of TLB operations are upgraded to
+ * IS versions if we are at NS EL1 and HCR_EL2.FB is set to
+ * force broadcast of these operations.
+ */
+static bool tlb_force_broadcast(CPUARMState *env)
+{
+    return (env->cp15.hcr_el2 & HCR_FB) &&
+        arm_current_el(env) == 1 && arm_is_secure_below_el3(env);
+}
+
+static void tlbiall_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                          uint64_t value)
+{
+    /* Invalidate all (TLBIALL) */
+    ARMCPU *cpu = arm_env_get_cpu(env);
+
+    if (tlb_force_broadcast(env)) {
+        tlbiall_is_write(env, NULL, value);
+        return;
+    }
+
+    tlb_flush(CPU(cpu));
+}
+
+static void tlbimva_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                          uint64_t value)
+{
+    /* Invalidate single TLB entry by MVA and ASID (TLBIMVA) */
+    ARMCPU *cpu = arm_env_get_cpu(env);
+
+    if (tlb_force_broadcast(env)) {
+        tlbimva_is_write(env, NULL, value);
+        return;
+    }
+
+    tlb_flush_page(CPU(cpu), value & TARGET_PAGE_MASK);
+}
+
+static void tlbiasid_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                           uint64_t value)
+{
+    /* Invalidate by ASID (TLBIASID) */
+    ARMCPU *cpu = arm_env_get_cpu(env);
+
+    if (tlb_force_broadcast(env)) {
+        tlbiasid_is_write(env, NULL, value);
+        return;
+    }
+
+    tlb_flush(CPU(cpu));
+}
+
+static void tlbimvaa_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                           uint64_t value)
+{
+    /* Invalidate single entry by MVA, all ASIDs (TLBIMVAA) */
+    ARMCPU *cpu = arm_env_get_cpu(env);
+
+    if (tlb_force_broadcast(env)) {
+        tlbimvaa_is_write(env, NULL, value);
+        return;
+    }
+
+    tlb_flush_page(CPU(cpu), value & TARGET_PAGE_MASK);
+}
+
 static void tlbiall_nsnh_write(CPUARMState *env, const ARMCPRegInfo *ri,
                                uint64_t value)
 {
@@ -3082,22 +3113,6 @@ static CPAccessResult aa64_cacheop_access(CPUARMState *env,
  * Page D4-1736 (DDI0487A.b)
  */
 
-static void tlbi_aa64_vmalle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
-                                    uint64_t value)
-{
-    CPUState *cs = ENV_GET_CPU(env);
-
-    if (arm_is_secure_below_el3(env)) {
-        tlb_flush_by_mmuidx(cs,
-                            ARMMMUIdxBit_S1SE1 |
-                            ARMMMUIdxBit_S1SE0);
-    } else {
-        tlb_flush_by_mmuidx(cs,
-                            ARMMMUIdxBit_S12NSE1 |
-                            ARMMMUIdxBit_S12NSE0);
-    }
-}
-
 static void tlbi_aa64_vmalle1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
                                       uint64_t value)
 {
@@ -3115,6 +3130,27 @@ static void tlbi_aa64_vmalle1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
     }
 }
 
+static void tlbi_aa64_vmalle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                                    uint64_t value)
+{
+    CPUState *cs = ENV_GET_CPU(env);
+
+    if (tlb_force_broadcast(env)) {
+        tlbi_aa64_vmalle1_write(env, NULL, value);
+        return;
+    }
+
+    if (arm_is_secure_below_el3(env)) {
+        tlb_flush_by_mmuidx(cs,
+                            ARMMMUIdxBit_S1SE1 |
+                            ARMMMUIdxBit_S1SE0);
+    } else {
+        tlb_flush_by_mmuidx(cs,
+                            ARMMMUIdxBit_S12NSE1 |
+                            ARMMMUIdxBit_S12NSE0);
+    }
+}
+
 static void tlbi_aa64_alle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
                                   uint64_t value)
 {
@@ -3204,29 +3240,6 @@ static void tlbi_aa64_alle3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
     tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_S1E3);
 }
 
-static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri,
-                                 uint64_t value)
-{
-    /* Invalidate by VA, EL1&0 (AArch64 version).
-     * Currently handles all of VAE1, VAAE1, VAALE1 and VALE1,
-     * since we don't support flush-for-specific-ASID-only or
-     * flush-last-level-only.
-     */
-    ARMCPU *cpu = arm_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
-    uint64_t pageaddr = sextract64(value << 12, 0, 56);
-
-    if (arm_is_secure_below_el3(env)) {
-        tlb_flush_page_by_mmuidx(cs, pageaddr,
-                                 ARMMMUIdxBit_S1SE1 |
-                                 ARMMMUIdxBit_S1SE0);
-    } else {
-        tlb_flush_page_by_mmuidx(cs, pageaddr,
-                                 ARMMMUIdxBit_S12NSE1 |
-                                 ARMMMUIdxBit_S12NSE0);
-    }
-}
-
 static void tlbi_aa64_vae2_write(CPUARMState *env, const ARMCPRegInfo *ri,
                                  uint64_t value)
 {
@@ -3274,6 +3287,34 @@ static void tlbi_aa64_vae1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
     }
 }
 
+static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                                 uint64_t value)
+{
+    /* Invalidate by VA, EL1&0 (AArch64 version).
+     * Currently handles all of VAE1, VAAE1, VAALE1 and VALE1,
+     * since we don't support flush-for-specific-ASID-only or
+     * flush-last-level-only.
+     */
+    ARMCPU *cpu = arm_env_get_cpu(env);
+    CPUState *cs = CPU(cpu);
+    uint64_t pageaddr = sextract64(value << 12, 0, 56);
+
+    if (tlb_force_broadcast(env)) {
+        tlbi_aa64_vae1is_write(env, NULL, value);
+        return;
+    }
+
+    if (arm_is_secure_below_el3(env)) {
+        tlb_flush_page_by_mmuidx(cs, pageaddr,
+                                 ARMMMUIdxBit_S1SE1 |
+                                 ARMMMUIdxBit_S1SE0);
+    } else {
+        tlb_flush_page_by_mmuidx(cs, pageaddr,
+                                 ARMMMUIdxBit_S12NSE1 |
+                                 ARMMMUIdxBit_S12NSE0);
+    }
+}
+
 static void tlbi_aa64_vae2is_write(CPUARMState *env, const ARMCPRegInfo *ri,
                                    uint64_t value)
 {
-- 
2.19.0

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

* [Qemu-devel] [PATCH 04/10] target/arm: Implement HCR.DC
  2018-10-12 14:42 [Qemu-devel] [PATCH 00/10] target/arm: more HCR bits, improve syndrome reporting Peter Maydell
                   ` (2 preceding siblings ...)
  2018-10-12 14:42 ` [Qemu-devel] [PATCH 03/10] target/arm: Implement HCR.FB Peter Maydell
@ 2018-10-12 14:42 ` Peter Maydell
  2018-10-14 16:26   ` Richard Henderson
  2018-10-12 14:42 ` [Qemu-devel] [PATCH 05/10] target/arm: ISR_EL1 bits track virtual interrupts if IMO/FMO set Peter Maydell
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 21+ messages in thread
From: Peter Maydell @ 2018-10-12 14:42 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: patches

The HCR.DC virtualization configuration register bit has the
following effects:
 * SCTLR.M behaves as if it is 0 for all purposes except
   direct reads of the bit
 * HCR.VM behaves as if it is 1 for all purposes except
   direct reads of the bit
 * the memory type produced by the first stage of the EL1&EL0
   translation regime is Normal Non-Shareable,
   Inner Write-Back Read-Allocate Write-Allocate,
   Outer Write-Back Read-Allocate Write-Allocate.

Implement this behaviour.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/helper.c | 23 +++++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index cbec6844a44..84b40031b6f 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -2300,13 +2300,15 @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
          * * The Non-secure TTBCR.EAE bit is set to 1
          * * The implementation includes EL2, and the value of HCR.VM is 1
          *
+         * (Note that HCR.DC makes HCR.VM behave as if it is 1.)
+         *
          * ATS1Hx always uses the 64bit format (not supported yet).
          */
         format64 = arm_s1_regime_using_lpae_format(env, mmu_idx);
 
         if (arm_feature(env, ARM_FEATURE_EL2)) {
             if (mmu_idx == ARMMMUIdx_S12NSE0 || mmu_idx == ARMMMUIdx_S12NSE1) {
-                format64 |= env->cp15.hcr_el2 & HCR_VM;
+                format64 |= env->cp15.hcr_el2 & (HCR_VM | HCR_DC);
             } else {
                 format64 |= arm_current_el(env) == 2;
             }
@@ -8711,7 +8713,8 @@ static inline bool regime_translation_disabled(CPUARMState *env,
     }
 
     if (mmu_idx == ARMMMUIdx_S2NS) {
-        return (env->cp15.hcr_el2 & HCR_VM) == 0;
+        /* HCR.DC means HCR.VM behaves as 1 */
+        return (env->cp15.hcr_el2 & (HCR_DC | HCR_VM)) == 0;
     }
 
     if (env->cp15.hcr_el2 & HCR_TGE) {
@@ -8721,6 +8724,12 @@ static inline bool regime_translation_disabled(CPUARMState *env,
         }
     }
 
+    if ((env->cp15.hcr_el2 & HCR_DC) &&
+        (mmu_idx == ARMMMUIdx_S1NSE0 || mmu_idx == ARMMMUIdx_S1NSE1)) {
+        /* HCR.DC means SCTLR_EL1.M behaves as 0 */
+        return true;
+    }
+
     return (regime_sctlr(env, mmu_idx) & SCTLR_M) == 0;
 }
 
@@ -10701,6 +10710,16 @@ static bool get_phys_addr(CPUARMState *env, target_ulong address,
 
             /* Combine the S1 and S2 cache attributes, if needed */
             if (!ret && cacheattrs != NULL) {
+                if (env->cp15.hcr_el2 & HCR_DC) {
+                    /*
+                     * HCR.DC forces the first stage attributes to
+                     *  Normal Non-Shareable,
+                     *  Inner Write-Back Read-Allocate Write-Allocate,
+                     *  Outer Write-Back Read-Allocate Write-Allocate.
+                     */
+                    cacheattrs->attrs = 0xff;
+                    cacheattrs->shareability = 0;
+                }
                 *cacheattrs = combine_cacheattrs(*cacheattrs, cacheattrs2);
             }
 
-- 
2.19.0

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

* [Qemu-devel] [PATCH 05/10] target/arm: ISR_EL1 bits track virtual interrupts if IMO/FMO set
  2018-10-12 14:42 [Qemu-devel] [PATCH 00/10] target/arm: more HCR bits, improve syndrome reporting Peter Maydell
                   ` (3 preceding siblings ...)
  2018-10-12 14:42 ` [Qemu-devel] [PATCH 04/10] target/arm: Implement HCR.DC Peter Maydell
@ 2018-10-12 14:42 ` Peter Maydell
  2018-10-14 16:34   ` Richard Henderson
  2018-10-12 14:42 ` [Qemu-devel] [PATCH 06/10] target/arm: Implement HCR.VI and VF Peter Maydell
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 21+ messages in thread
From: Peter Maydell @ 2018-10-12 14:42 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: patches

The A/I/F bits in ISR_EL1 should track the virtual interrupt
status, not the physical interrupt status, if the associated
HCR_EL2.AMO/IMO/FMO bit is set. Implement this, rather than
always showing the physical interrupt status.

We don't currently implement anything to do with external
aborts, so this applies only to the I and F bits (though it
ought to be possible for the outer guest to present a virtual
external abort to the inner guest, even if QEMU doesn't
emulate physical external aborts, so there is missing
functionality in this area).

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/helper.c | 22 ++++++++++++++++++----
 1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 84b40031b6f..65e431e03b3 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -1328,12 +1328,26 @@ static uint64_t isr_read(CPUARMState *env, const ARMCPRegInfo *ri)
     CPUState *cs = ENV_GET_CPU(env);
     uint64_t ret = 0;
 
-    if (cs->interrupt_request & CPU_INTERRUPT_HARD) {
-        ret |= CPSR_I;
+    if (arm_hcr_el2_imo(env)) {
+        if (cs->interrupt_request & CPU_INTERRUPT_VIRQ) {
+            ret |= CPSR_I;
+        }
+    } else {
+        if (cs->interrupt_request & CPU_INTERRUPT_HARD) {
+            ret |= CPSR_I;
+        }
     }
-    if (cs->interrupt_request & CPU_INTERRUPT_FIQ) {
-        ret |= CPSR_F;
+
+    if (arm_hcr_el2_fmo(env)) {
+        if (cs->interrupt_request & CPU_INTERRUPT_VFIQ) {
+            ret |= CPSR_F;
+        }
+    } else {
+        if (cs->interrupt_request & CPU_INTERRUPT_FIQ) {
+            ret |= CPSR_F;
+        }
     }
+
     /* External aborts are not possible in QEMU so A bit is always clear */
     return ret;
 }
-- 
2.19.0

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

* [Qemu-devel] [PATCH 06/10] target/arm: Implement HCR.VI and VF
  2018-10-12 14:42 [Qemu-devel] [PATCH 00/10] target/arm: more HCR bits, improve syndrome reporting Peter Maydell
                   ` (4 preceding siblings ...)
  2018-10-12 14:42 ` [Qemu-devel] [PATCH 05/10] target/arm: ISR_EL1 bits track virtual interrupts if IMO/FMO set Peter Maydell
@ 2018-10-12 14:42 ` Peter Maydell
  2018-10-15 15:35   ` Richard Henderson
  2018-10-12 14:42 ` [Qemu-devel] [PATCH 07/10] target/arm: Implement HCR.PTW Peter Maydell
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 21+ messages in thread
From: Peter Maydell @ 2018-10-12 14:42 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: patches

The HCR_EL2 VI and VF bits are supposed to track whether there is
a pending virtual IRQ or virtual FIQ. For QEMU we store the
pending VIRQ/VFIQ status in cs->interrupt_request, so this means:
 * if the register is read we must get these bit values from
   cs->interrupt_request
 * if the register is written then we must write the bit
   values back into cs->interrupt_request

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/helper.c | 47 +++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 43 insertions(+), 4 deletions(-)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 65e431e03b3..78d05fe1e57 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -3928,6 +3928,7 @@ static const ARMCPRegInfo el3_no_el2_v8_cp_reginfo[] = {
 static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
 {
     ARMCPU *cpu = arm_env_get_cpu(env);
+    CPUState *cs = ENV_GET_CPU(env);
     uint64_t valid_mask = HCR_MASK;
 
     if (arm_feature(env, ARM_FEATURE_EL3)) {
@@ -3946,6 +3947,28 @@ static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
     /* Clear RES0 bits.  */
     value &= valid_mask;
 
+    /*
+     * VI and VF are kept in cs->interrupt_request. Modifying that
+     * requires that we have the iothread lock, which is done by
+     * marking the reginfo structs as ARM_CP_IO.
+     * Note that if a write to HCR pends a VIRQ or VFIQ it is never
+     * possible for it to be taken immediately, because VIRQ and
+     * VFIQ are masked unless running at EL0 or EL1, and HCR
+     * can only be written at EL2.
+     */
+    g_assert(qemu_mutex_iothread_locked());
+    if (value & HCR_VI) {
+        cs->interrupt_request |= CPU_INTERRUPT_VIRQ;
+    } else {
+        cs->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
+    }
+    if (value & HCR_VF) {
+        cs->interrupt_request |= CPU_INTERRUPT_VFIQ;
+    } else {
+        cs->interrupt_request &= ~CPU_INTERRUPT_VFIQ;
+    }
+    value &= ~(HCR_VI | HCR_VF);
+
     /* These bits change the MMU setup:
      * HCR_VM enables stage 2 translation
      * HCR_PTW forbids certain page-table setups
@@ -3973,16 +3996,32 @@ static void hcr_writelow(CPUARMState *env, const ARMCPRegInfo *ri,
     hcr_write(env, NULL, value);
 }
 
+static uint64_t hcr_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    /* The VI and VF bits live in cs->interrupt_request */
+    uint64_t ret = env->cp15.hcr_el2 & ~(HCR_VI | HCR_VF);
+    CPUState *cs = ENV_GET_CPU(env);
+
+    if (cs->interrupt_request & CPU_INTERRUPT_VIRQ) {
+        ret |= HCR_VI;
+    }
+    if (cs->interrupt_request & CPU_INTERRUPT_VFIQ) {
+        ret |= HCR_VF;
+    }
+    return ret;
+}
+
 static const ARMCPRegInfo el2_cp_reginfo[] = {
     { .name = "HCR_EL2", .state = ARM_CP_STATE_AA64,
+      .type = ARM_CP_IO,
       .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 0,
       .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.hcr_el2),
-      .writefn = hcr_write },
+      .writefn = hcr_write, .readfn = hcr_read },
     { .name = "HCR", .state = ARM_CP_STATE_AA32,
-      .type = ARM_CP_ALIAS,
+      .type = ARM_CP_ALIAS | ARM_CP_IO,
       .cp = 15, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 0,
       .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.hcr_el2),
-      .writefn = hcr_writelow },
+      .writefn = hcr_writelow, .readfn = hcr_read },
     { .name = "ELR_EL2", .state = ARM_CP_STATE_AA64,
       .type = ARM_CP_ALIAS,
       .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 0, .opc2 = 1,
@@ -4219,7 +4258,7 @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
 
 static const ARMCPRegInfo el2_v8_cp_reginfo[] = {
     { .name = "HCR2", .state = ARM_CP_STATE_AA32,
-      .type = ARM_CP_ALIAS,
+      .type = ARM_CP_ALIAS | ARM_CP_IO,
       .cp = 15, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 4,
       .access = PL2_RW,
       .fieldoffset = offsetofhigh32(CPUARMState, cp15.hcr_el2),
-- 
2.19.0

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

* [Qemu-devel] [PATCH 07/10] target/arm: Implement HCR.PTW
  2018-10-12 14:42 [Qemu-devel] [PATCH 00/10] target/arm: more HCR bits, improve syndrome reporting Peter Maydell
                   ` (5 preceding siblings ...)
  2018-10-12 14:42 ` [Qemu-devel] [PATCH 06/10] target/arm: Implement HCR.VI and VF Peter Maydell
@ 2018-10-12 14:42 ` Peter Maydell
  2018-10-15 15:38   ` Richard Henderson
  2018-10-12 14:42 ` [Qemu-devel] [PATCH 08/10] target/arm: New utility function to extract EC from syndrome Peter Maydell
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 21+ messages in thread
From: Peter Maydell @ 2018-10-12 14:42 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: patches

If the HCR_EL2 PTW virtualizaiton configuration register bit
is set, then this means that a stage 2 Permission fault must
be generated if a stage 1 translation table access is made
to an address that is mapped as Device memory in stage 2.
Implement this.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/helper.c | 21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 78d05fe1e57..b5752d52dd1 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -9134,9 +9134,20 @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx,
         hwaddr s2pa;
         int s2prot;
         int ret;
+        ARMCacheAttrs cacheattrs = {};
+        ARMCacheAttrs *pcacheattrs = NULL;
+
+        if (env->cp15.hcr_el2 & HCR_PTW) {
+            /*
+             * PTW means we must fault if this S1 walk touches S2 Device
+             * memory; otherwise we don't care about the attributes and can
+             * save the S2 translation the effort of computing them.
+             */
+            pcacheattrs = &cacheattrs;
+        }
 
         ret = get_phys_addr_lpae(env, addr, 0, ARMMMUIdx_S2NS, &s2pa,
-                                 &txattrs, &s2prot, &s2size, fi, NULL);
+                                 &txattrs, &s2prot, &s2size, fi, pcacheattrs);
         if (ret) {
             assert(fi->type != ARMFault_None);
             fi->s2addr = addr;
@@ -9144,6 +9155,14 @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx,
             fi->s1ptw = true;
             return ~0;
         }
+        if (pcacheattrs && (pcacheattrs->attrs & 0xf0) == 0) {
+            /* Access was to Device memory: generate Permission fault */
+            fi->type = ARMFault_Permission;
+            fi->s2addr = addr;
+            fi->stage2 = true;
+            fi->s1ptw = true;
+            return ~0;
+        }
         addr = s2pa;
     }
     return addr;
-- 
2.19.0

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

* [Qemu-devel] [PATCH 08/10] target/arm: New utility function to extract EC from syndrome
  2018-10-12 14:42 [Qemu-devel] [PATCH 00/10] target/arm: more HCR bits, improve syndrome reporting Peter Maydell
                   ` (6 preceding siblings ...)
  2018-10-12 14:42 ` [Qemu-devel] [PATCH 07/10] target/arm: Implement HCR.PTW Peter Maydell
@ 2018-10-12 14:42 ` Peter Maydell
  2018-10-15 15:38   ` Richard Henderson
  2018-10-12 14:42 ` [Qemu-devel] [PATCH 09/10] target/arm: Get IL bit correct for v7 syndrome values Peter Maydell
  2018-10-12 14:42 ` [Qemu-devel] [PATCH 10/10] target/arm: Report correct syndrome for FP/SIMD traps to Hyp mode Peter Maydell
  9 siblings, 1 reply; 21+ messages in thread
From: Peter Maydell @ 2018-10-12 14:42 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: patches

Create and use a utility function to extract the EC field
from a syndrome, rather than open-coding the shift.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/internals.h | 5 +++++
 target/arm/helper.c    | 4 ++--
 target/arm/kvm64.c     | 2 +-
 target/arm/op_helper.c | 2 +-
 4 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/target/arm/internals.h b/target/arm/internals.h
index d4b1973efa1..516f9454e9b 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -278,6 +278,11 @@ enum arm_exception_class {
 #define ARM_EL_IL (1 << ARM_EL_IL_SHIFT)
 #define ARM_EL_ISV (1 << ARM_EL_ISV_SHIFT)
 
+static inline uint32_t syn_get_ec(uint32_t syn)
+{
+    return syn >> ARM_EL_EC_SHIFT;
+}
+
 /* Utility functions for constructing various kinds of syndrome value.
  * Note that in general we follow the AArch64 syndrome values; in a
  * few cases the value in HSR for exceptions taken to AArch32 Hyp
diff --git a/target/arm/helper.c b/target/arm/helper.c
index b5752d52dd1..0b89804961b 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -8333,7 +8333,7 @@ static void arm_cpu_do_interrupt_aarch32(CPUState *cs)
     uint32_t moe;
 
     /* If this is a debug exception we must update the DBGDSCR.MOE bits */
-    switch (env->exception.syndrome >> ARM_EL_EC_SHIFT) {
+    switch (syn_get_ec(env->exception.syndrome)) {
     case EC_BREAKPOINT:
     case EC_BREAKPOINT_SAME_EL:
         moe = 1;
@@ -8669,7 +8669,7 @@ void arm_cpu_do_interrupt(CPUState *cs)
     if (qemu_loglevel_mask(CPU_LOG_INT)
         && !excp_is_internal(cs->exception_index)) {
         qemu_log_mask(CPU_LOG_INT, "...with ESR 0x%x/0x%" PRIx32 "\n",
-                      env->exception.syndrome >> ARM_EL_EC_SHIFT,
+                      syn_get_ec(env->exception.syndrome),
                       env->exception.syndrome);
     }
 
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
index e0b82462838..ce33cbc65a6 100644
--- a/target/arm/kvm64.c
+++ b/target/arm/kvm64.c
@@ -920,7 +920,7 @@ int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
 
 bool kvm_arm_handle_debug(CPUState *cs, struct kvm_debug_exit_arch *debug_exit)
 {
-    int hsr_ec = debug_exit->hsr >> ARM_EL_EC_SHIFT;
+    int hsr_ec = syn_get_ec(debug_exit->hsr);
     ARMCPU *cpu = ARM_CPU(cs);
     CPUClass *cc = CPU_GET_CLASS(cs);
     CPUARMState *env = &cpu->env;
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
index fb15a13e6c9..b1e65f43d38 100644
--- a/target/arm/op_helper.c
+++ b/target/arm/op_helper.c
@@ -42,7 +42,7 @@ void raise_exception(CPUARMState *env, uint32_t excp,
          * (see DDI0478C.a D1.10.4)
          */
         target_el = 2;
-        if (syndrome >> ARM_EL_EC_SHIFT == EC_ADVSIMDFPACCESSTRAP) {
+        if (syn_get_ec(syndrome) == EC_ADVSIMDFPACCESSTRAP) {
             syndrome = syn_uncategorized();
         }
     }
-- 
2.19.0

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

* [Qemu-devel] [PATCH 09/10] target/arm: Get IL bit correct for v7 syndrome values
  2018-10-12 14:42 [Qemu-devel] [PATCH 00/10] target/arm: more HCR bits, improve syndrome reporting Peter Maydell
                   ` (7 preceding siblings ...)
  2018-10-12 14:42 ` [Qemu-devel] [PATCH 08/10] target/arm: New utility function to extract EC from syndrome Peter Maydell
@ 2018-10-12 14:42 ` Peter Maydell
  2018-10-15 15:41   ` Richard Henderson
  2018-10-12 14:42 ` [Qemu-devel] [PATCH 10/10] target/arm: Report correct syndrome for FP/SIMD traps to Hyp mode Peter Maydell
  9 siblings, 1 reply; 21+ messages in thread
From: Peter Maydell @ 2018-10-12 14:42 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: patches

For the v7 version of the Arm architecture, the IL bit in
syndrome register values where the field is not valid was
defined to be UNK/SBZP. In v8 this is RES1, which is what
QEMU currently implements. Handle the desired v7 behaviour
by squashing the IL bit for the affected cases:
 * EC == EC_UNCATEGORIZED
 * prefetch aborts
 * data aborts where ISV is 0

(The fourth case listed in the v8 Arm ARM DDI 0487C.a in
section G7.2.70, "illegal state exception", can't happen
on a v7 CPU.)

This deals with a corner case noted in a comment.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/internals.h |  7 ++-----
 target/arm/helper.c    | 14 ++++++++++++++
 2 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/target/arm/internals.h b/target/arm/internals.h
index 516f9454e9b..cd8bc1ec3d4 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -286,11 +286,8 @@ static inline uint32_t syn_get_ec(uint32_t syn)
 /* Utility functions for constructing various kinds of syndrome value.
  * Note that in general we follow the AArch64 syndrome values; in a
  * few cases the value in HSR for exceptions taken to AArch32 Hyp
- * mode differs slightly, so if we ever implemented Hyp mode then the
- * syndrome value would need some massaging on exception entry.
- * (One example of this is that AArch64 defaults to IL bit set for
- * exceptions which don't specifically indicate information about the
- * trapping instruction, whereas AArch32 defaults to IL bit clear.)
+ * mode differs slightly, and we fix this up when populating HSR in
+ * arm_cpu_do_interrupt_aarch32_hyp().
  */
 static inline uint32_t syn_uncategorized(void)
 {
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 0b89804961b..0b659171b07 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -8299,6 +8299,20 @@ static void arm_cpu_do_interrupt_aarch32_hyp(CPUState *cs)
     }
 
     if (cs->exception_index != EXCP_IRQ && cs->exception_index != EXCP_FIQ) {
+
+        if (!arm_feature(env, ARM_FEATURE_V8)) {
+            /*
+             * QEMU syndrome values are v8-style. v7 has the IL bit
+             * UNK/SBZP for "field not valid" cases, where v8 uses RES1.
+             * If this is a v7 CPU, squash the IL bit in those cases.
+             */
+            if (cs->exception_index == EXCP_PREFETCH_ABORT ||
+                (cs->exception_index == EXCP_DATA_ABORT &&
+                 !(env->exception.syndrome & ARM_EL_ISV)) ||
+                syn_get_ec(env->exception.syndrome) == EC_UNCATEGORIZED) {
+                env->exception.syndrome &= ~ARM_EL_IL;
+            }
+        }
         env->cp15.esr_el[2] = env->exception.syndrome;
     }
 
-- 
2.19.0

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

* [Qemu-devel] [PATCH 10/10] target/arm: Report correct syndrome for FP/SIMD traps to Hyp mode
  2018-10-12 14:42 [Qemu-devel] [PATCH 00/10] target/arm: more HCR bits, improve syndrome reporting Peter Maydell
                   ` (8 preceding siblings ...)
  2018-10-12 14:42 ` [Qemu-devel] [PATCH 09/10] target/arm: Get IL bit correct for v7 syndrome values Peter Maydell
@ 2018-10-12 14:42 ` Peter Maydell
  2018-10-15 16:00   ` Richard Henderson
  9 siblings, 1 reply; 21+ messages in thread
From: Peter Maydell @ 2018-10-12 14:42 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: patches

For traps of FP/SIMD instructions to AArch32 Hyp mode, the syndrome
provided in HSR has more information than is reported to AArch64.
Specifically, there are extra fields TA and coproc which indicate
whether the trapped instruction was FP or SIMD. Add this extra
information to the syndromes we construct, and mask it out when
taking the exception to AArch64.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/internals.h | 14 +++++++++++++-
 target/arm/helper.c    |  9 +++++++++
 target/arm/translate.c |  8 ++++----
 3 files changed, 26 insertions(+), 5 deletions(-)

diff --git a/target/arm/internals.h b/target/arm/internals.h
index cd8bc1ec3d4..960dfb3c06a 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -288,6 +288,9 @@ static inline uint32_t syn_get_ec(uint32_t syn)
  * few cases the value in HSR for exceptions taken to AArch32 Hyp
  * mode differs slightly, and we fix this up when populating HSR in
  * arm_cpu_do_interrupt_aarch32_hyp().
+ * The exception is FP/SIMD access traps -- these report extra information
+ * when taking an exception to AArch32. For those we include the extra coproc
+ * and TA fields, and mask them out when taking the exception to AArch64.
  */
 static inline uint32_t syn_uncategorized(void)
 {
@@ -387,9 +390,18 @@ static inline uint32_t syn_cp15_rrt_trap(int cv, int cond, int opc1, int crm,
 
 static inline uint32_t syn_fp_access_trap(int cv, int cond, bool is_16bit)
 {
+    /* AArch32 FP trap or any AArch64 FP/SIMD trap: TA == 0 coproc == 0xa */
     return (EC_ADVSIMDFPACCESSTRAP << ARM_EL_EC_SHIFT)
         | (is_16bit ? 0 : ARM_EL_IL)
-        | (cv << 24) | (cond << 20);
+        | (cv << 24) | (cond << 20) | 0xa;
+}
+
+static inline uint32_t syn_simd_access_trap(int cv, int cond, bool is_16bit)
+{
+    /* AArch32 SIMD trap: TA == 1 coproc == 0 */
+    return (EC_ADVSIMDFPACCESSTRAP << ARM_EL_EC_SHIFT)
+        | (is_16bit ? 0 : ARM_EL_IL)
+        | (cv << 24) | (cond << 20) | (1 << 5);
 }
 
 static inline uint32_t syn_sve_access_trap(void)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 0b659171b07..43afdd082e1 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -8540,6 +8540,15 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
     case EXCP_HVC:
     case EXCP_HYP_TRAP:
     case EXCP_SMC:
+        if (syn_get_ec(env->exception.syndrome) == EC_ADVSIMDFPACCESSTRAP) {
+            /*
+             * QEMU internal FP/SIMD syndromes from AArch32 include the
+             * TA and coproc fields which are only exposed if the exception
+             * is taken to AArch32 Hyp mode. Mask them out to get a valid
+             * AArch64 format syndrome.
+             */
+            env->exception.syndrome &= ~MAKE_64BIT_MASK(0, 20);
+        }
         env->cp15.esr_el[new_el] = env->exception.syndrome;
         break;
     case EXCP_IRQ:
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 7c7d920e331..d71597796f5 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -4948,7 +4948,7 @@ static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
      */
     if (s->fp_excp_el) {
         gen_exception_insn(s, 4, EXCP_UDEF,
-                           syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
+                           syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
         return 0;
     }
 
@@ -5727,7 +5727,7 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
      */
     if (s->fp_excp_el) {
         gen_exception_insn(s, 4, EXCP_UDEF,
-                           syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
+                           syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
         return 0;
     }
 
@@ -7840,7 +7840,7 @@ static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
 
     if (s->fp_excp_el) {
         gen_exception_insn(s, 4, EXCP_UDEF,
-                           syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
+                           syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
         return 0;
     }
     if (!s->vfp_enabled) {
@@ -7926,7 +7926,7 @@ static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn)
 
     if (s->fp_excp_el) {
         gen_exception_insn(s, 4, EXCP_UDEF,
-                           syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
+                           syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
         return 0;
     }
     if (!s->vfp_enabled) {
-- 
2.19.0

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

* Re: [Qemu-devel] [PATCH 01/10] target/arm: Improve debug logging of AArch32 exception return
  2018-10-12 14:42 ` [Qemu-devel] [PATCH 01/10] target/arm: Improve debug logging of AArch32 exception return Peter Maydell
@ 2018-10-14 16:12   ` Richard Henderson
  0 siblings, 0 replies; 21+ messages in thread
From: Richard Henderson @ 2018-10-14 16:12 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: patches

On 10/12/18 7:42 AM, Peter Maydell wrote:
> For AArch32, exception return happens through certain kinds
> of CPSR write. We don't currently have any CPU_LOG_INT logging
> of these events (unlike AArch64, where we log in the ERET
> instruction). Add some suitable logging.
> 
> This will log exception returns like this:
> Exception return from AArch32 hyp to usr PC 0x80100374
> 
> paralleling the existing logging in the exception_return
> helper for AArch64 exception returns:
> Exception return from AArch64 EL2 to AArch64 EL0 PC 0x8003045c
> Exception return from AArch64 EL2 to AArch32 EL0 PC 0x8003045c
> 
> (Note that an AArch32 exception return can only be
> AArch32->AArch32, never to AArch64.)
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---

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

> +    static const char * const cpu_mode_names[16] = {
> +        "usr", "fiq", "irq", "svc", "???", "???", "mon", "abt",
> +        "???", "???", "hyp", "und", "???", "???", "???", "sys"
> +    };

Nit: Better as static const char cpu_mode_names[16][4].

For tiny strings like this, the pointer to a separate string is larger than the
string itself.


r~

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

* Re: [Qemu-devel] [PATCH 02/10] target/arm: Make switch_mode() file-local
  2018-10-12 14:42 ` [Qemu-devel] [PATCH 02/10] target/arm: Make switch_mode() file-local Peter Maydell
@ 2018-10-14 16:13   ` Richard Henderson
  0 siblings, 0 replies; 21+ messages in thread
From: Richard Henderson @ 2018-10-14 16:13 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: patches

On 10/12/18 7:42 AM, Peter Maydell wrote:
> The switch_mode() function is defined in target/arm/helper.c and used
> only in that file and nowhere else, so we can make it file-local
> rather than global.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  target/arm/internals.h | 1 -
>  target/arm/helper.c    | 6 ++++--
>  2 files changed, 4 insertions(+), 3 deletions(-)

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

r~

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

* Re: [Qemu-devel] [PATCH 03/10] target/arm: Implement HCR.FB
  2018-10-12 14:42 ` [Qemu-devel] [PATCH 03/10] target/arm: Implement HCR.FB Peter Maydell
@ 2018-10-14 16:21   ` Richard Henderson
  0 siblings, 0 replies; 21+ messages in thread
From: Richard Henderson @ 2018-10-14 16:21 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: patches

On 10/12/18 7:42 AM, Peter Maydell wrote:
> The HCR.FB virtualization configuration register bit requests that
> TLB maintenance, branch predictor invalidate-all and icache
> invalidate-all operations performed in NS EL1 should be upgraded
> from "local CPU only to "broadcast within Inner Shareable domain".
> For QEMU we NOP the branch predictor and icache operations, so
> we only need to upgrade the TLB invalidates:
>  AArch32 TLBIALL, TLBIMVA, TLBIASID, DTLBIALL, DTLBIMVA, DTLBIASID,
>          ITLBIALL, ITLBIMVA, ITLBIASID, TLBIMVAA, TLBIMVAL, TLBIMVAAL
>  AArch64 TLBI VMALLE1, TLBI VAE1, TLBI ASIDE1, TLBI VAAE1,
>          TLBI VALE1, TLBI VAALE1
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  target/arm/helper.c | 191 +++++++++++++++++++++++++++-----------------
>  1 file changed, 116 insertions(+), 75 deletions(-)

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

r~

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

* Re: [Qemu-devel] [PATCH 04/10] target/arm: Implement HCR.DC
  2018-10-12 14:42 ` [Qemu-devel] [PATCH 04/10] target/arm: Implement HCR.DC Peter Maydell
@ 2018-10-14 16:26   ` Richard Henderson
  0 siblings, 0 replies; 21+ messages in thread
From: Richard Henderson @ 2018-10-14 16:26 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: patches

On 10/12/18 7:42 AM, Peter Maydell wrote:
> The HCR.DC virtualization configuration register bit has the
> following effects:
>  * SCTLR.M behaves as if it is 0 for all purposes except
>    direct reads of the bit
>  * HCR.VM behaves as if it is 1 for all purposes except
>    direct reads of the bit
>  * the memory type produced by the first stage of the EL1&EL0
>    translation regime is Normal Non-Shareable,
>    Inner Write-Back Read-Allocate Write-Allocate,
>    Outer Write-Back Read-Allocate Write-Allocate.
> 
> Implement this behaviour.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---

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

r~

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

* Re: [Qemu-devel] [PATCH 05/10] target/arm: ISR_EL1 bits track virtual interrupts if IMO/FMO set
  2018-10-12 14:42 ` [Qemu-devel] [PATCH 05/10] target/arm: ISR_EL1 bits track virtual interrupts if IMO/FMO set Peter Maydell
@ 2018-10-14 16:34   ` Richard Henderson
  0 siblings, 0 replies; 21+ messages in thread
From: Richard Henderson @ 2018-10-14 16:34 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: patches

On 10/12/18 7:42 AM, Peter Maydell wrote:
> The A/I/F bits in ISR_EL1 should track the virtual interrupt
> status, not the physical interrupt status, if the associated
> HCR_EL2.AMO/IMO/FMO bit is set. Implement this, rather than
> always showing the physical interrupt status.
> 
> We don't currently implement anything to do with external
> aborts, so this applies only to the I and F bits (though it
> ought to be possible for the outer guest to present a virtual
> external abort to the inner guest, even if QEMU doesn't
> emulate physical external aborts, so there is missing
> functionality in this area).
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  target/arm/helper.c | 22 ++++++++++++++++++----
>  1 file changed, 18 insertions(+), 4 deletions(-)

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

r~

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

* Re: [Qemu-devel] [PATCH 06/10] target/arm: Implement HCR.VI and VF
  2018-10-12 14:42 ` [Qemu-devel] [PATCH 06/10] target/arm: Implement HCR.VI and VF Peter Maydell
@ 2018-10-15 15:35   ` Richard Henderson
  0 siblings, 0 replies; 21+ messages in thread
From: Richard Henderson @ 2018-10-15 15:35 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: patches

On 10/12/18 7:42 AM, Peter Maydell wrote:
> The HCR_EL2 VI and VF bits are supposed to track whether there is
> a pending virtual IRQ or virtual FIQ. For QEMU we store the
> pending VIRQ/VFIQ status in cs->interrupt_request, so this means:
>  * if the register is read we must get these bit values from
>    cs->interrupt_request
>  * if the register is written then we must write the bit
>    values back into cs->interrupt_request
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  target/arm/helper.c | 47 +++++++++++++++++++++++++++++++++++++++++----
>  1 file changed, 43 insertions(+), 4 deletions(-)

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

r~

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

* Re: [Qemu-devel] [PATCH 07/10] target/arm: Implement HCR.PTW
  2018-10-12 14:42 ` [Qemu-devel] [PATCH 07/10] target/arm: Implement HCR.PTW Peter Maydell
@ 2018-10-15 15:38   ` Richard Henderson
  0 siblings, 0 replies; 21+ messages in thread
From: Richard Henderson @ 2018-10-15 15:38 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: patches

On 10/12/18 7:42 AM, Peter Maydell wrote:
> If the HCR_EL2 PTW virtualizaiton configuration register bit
> is set, then this means that a stage 2 Permission fault must
> be generated if a stage 1 translation table access is made
> to an address that is mapped as Device memory in stage 2.
> Implement this.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  target/arm/helper.c | 21 ++++++++++++++++++++-
>  1 file changed, 20 insertions(+), 1 deletion(-)

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

r~

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

* Re: [Qemu-devel] [PATCH 08/10] target/arm: New utility function to extract EC from syndrome
  2018-10-12 14:42 ` [Qemu-devel] [PATCH 08/10] target/arm: New utility function to extract EC from syndrome Peter Maydell
@ 2018-10-15 15:38   ` Richard Henderson
  0 siblings, 0 replies; 21+ messages in thread
From: Richard Henderson @ 2018-10-15 15:38 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: patches

On 10/12/18 7:42 AM, Peter Maydell wrote:
> Create and use a utility function to extract the EC field
> from a syndrome, rather than open-coding the shift.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  target/arm/internals.h | 5 +++++
>  target/arm/helper.c    | 4 ++--
>  target/arm/kvm64.c     | 2 +-
>  target/arm/op_helper.c | 2 +-
>  4 files changed, 9 insertions(+), 4 deletions(-)

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

r~

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

* Re: [Qemu-devel] [PATCH 09/10] target/arm: Get IL bit correct for v7 syndrome values
  2018-10-12 14:42 ` [Qemu-devel] [PATCH 09/10] target/arm: Get IL bit correct for v7 syndrome values Peter Maydell
@ 2018-10-15 15:41   ` Richard Henderson
  0 siblings, 0 replies; 21+ messages in thread
From: Richard Henderson @ 2018-10-15 15:41 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: patches

On 10/12/18 7:42 AM, Peter Maydell wrote:
> For the v7 version of the Arm architecture, the IL bit in
> syndrome register values where the field is not valid was
> defined to be UNK/SBZP. In v8 this is RES1, which is what
> QEMU currently implements. Handle the desired v7 behaviour
> by squashing the IL bit for the affected cases:
>  * EC == EC_UNCATEGORIZED
>  * prefetch aborts
>  * data aborts where ISV is 0
> 
> (The fourth case listed in the v8 Arm ARM DDI 0487C.a in
> section G7.2.70, "illegal state exception", can't happen
> on a v7 CPU.)
> 
> This deals with a corner case noted in a comment.

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

>      if (cs->exception_index != EXCP_IRQ && cs->exception_index != EXCP_FIQ) {
> +
> +        if (!arm_feature(env, ARM_FEATURE_V8)) {

Extra line.


r~

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

* Re: [Qemu-devel] [PATCH 10/10] target/arm: Report correct syndrome for FP/SIMD traps to Hyp mode
  2018-10-12 14:42 ` [Qemu-devel] [PATCH 10/10] target/arm: Report correct syndrome for FP/SIMD traps to Hyp mode Peter Maydell
@ 2018-10-15 16:00   ` Richard Henderson
  0 siblings, 0 replies; 21+ messages in thread
From: Richard Henderson @ 2018-10-15 16:00 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: patches

On 10/12/18 7:42 AM, Peter Maydell wrote:
> For traps of FP/SIMD instructions to AArch32 Hyp mode, the syndrome
> provided in HSR has more information than is reported to AArch64.
> Specifically, there are extra fields TA and coproc which indicate
> whether the trapped instruction was FP or SIMD. Add this extra
> information to the syndromes we construct, and mask it out when
> taking the exception to AArch64.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  target/arm/internals.h | 14 +++++++++++++-
>  target/arm/helper.c    |  9 +++++++++
>  target/arm/translate.c |  8 ++++----
>  3 files changed, 26 insertions(+), 5 deletions(-)

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

r~

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

end of thread, other threads:[~2018-10-15 16:01 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-10-12 14:42 [Qemu-devel] [PATCH 00/10] target/arm: more HCR bits, improve syndrome reporting Peter Maydell
2018-10-12 14:42 ` [Qemu-devel] [PATCH 01/10] target/arm: Improve debug logging of AArch32 exception return Peter Maydell
2018-10-14 16:12   ` Richard Henderson
2018-10-12 14:42 ` [Qemu-devel] [PATCH 02/10] target/arm: Make switch_mode() file-local Peter Maydell
2018-10-14 16:13   ` Richard Henderson
2018-10-12 14:42 ` [Qemu-devel] [PATCH 03/10] target/arm: Implement HCR.FB Peter Maydell
2018-10-14 16:21   ` Richard Henderson
2018-10-12 14:42 ` [Qemu-devel] [PATCH 04/10] target/arm: Implement HCR.DC Peter Maydell
2018-10-14 16:26   ` Richard Henderson
2018-10-12 14:42 ` [Qemu-devel] [PATCH 05/10] target/arm: ISR_EL1 bits track virtual interrupts if IMO/FMO set Peter Maydell
2018-10-14 16:34   ` Richard Henderson
2018-10-12 14:42 ` [Qemu-devel] [PATCH 06/10] target/arm: Implement HCR.VI and VF Peter Maydell
2018-10-15 15:35   ` Richard Henderson
2018-10-12 14:42 ` [Qemu-devel] [PATCH 07/10] target/arm: Implement HCR.PTW Peter Maydell
2018-10-15 15:38   ` Richard Henderson
2018-10-12 14:42 ` [Qemu-devel] [PATCH 08/10] target/arm: New utility function to extract EC from syndrome Peter Maydell
2018-10-15 15:38   ` Richard Henderson
2018-10-12 14:42 ` [Qemu-devel] [PATCH 09/10] target/arm: Get IL bit correct for v7 syndrome values Peter Maydell
2018-10-15 15:41   ` Richard Henderson
2018-10-12 14:42 ` [Qemu-devel] [PATCH 10/10] target/arm: Report correct syndrome for FP/SIMD traps to Hyp mode Peter Maydell
2018-10-15 16:00   ` Richard Henderson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).