All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation
@ 2014-04-10 16:14 Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 01/37] target-arm: Split out private-to-target functions into internals.h Peter Maydell
                   ` (37 more replies)
  0 siblings, 38 replies; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:14 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

Here's v5 of the AArch64 system emulation patchset.
Still missing/TODO:
 * SMP support (needs PSCI emulation in QEMU; being prototyped)
 * save/restore (I have a patch which adds this but I think it will
   look better if we consolidate AArch32 cpsr and AArch64 pstate
   handling)
but both of these I think are best done once this main series
is committed to master.

The changes v5->v6 are pretty minor, and these patches have
been kicking around onlist for a long time, so I plan to
put these in a pull request pretty much as soon as we reopen
trunk after 2.0 releases. Last chance for review!


Changes v5->v6:
 * add extract64() when putting together 32-bit CBAR value
 * be consistent about int vs bool for 1 bit fields in the
   syn_insn_abort/syn_data_abort functions
 * added some FIXMEs about inaccurate syndrome info for A32/T32
   Neon unallocated insns when FP is disabled
 * decided that using a15mpcore_priv in the virt machine is actually
   the best approach, and added a suitable comment
Changes v4->v5:
 * new patches:
   + MVFR registers
   + various extra system registers
   + don't expose wildcards for ARMv8
   + make A15's CBAR R/O
   + support interprocessing in set_pc
 * minor tweaks per review (I haven't always taken the review
   suggestion; see mail threads on the previous version of the
   patch series)
 * DC ZVA: use helper_ret_stb_mmu
           make tlb_vaddr_to_host take param for access type
 * NB: I didn't make gen_exception and gen_exception_internal shared
   in patch 5: I think keeping the A64 and A32 decoders independent
   is preferable
 * have syn_insn_abort and syn_data_abort set the syndrome bit
   for 'exception to same level' rather than making caller do it
Changes v3->v4:
 * reviewed patches from bottom of stack got committed to master
 * new patches at top of stack
 * addressed review issues on v8 mmu translation patch and DAIF patch

thanks
-- PMM


Peter Maydell (33):
  target-arm: Split out private-to-target functions into internals.h
  target-arm: Implement AArch64 DAIF system register
  target-arm: Define exception record for AArch64 exceptions
  target-arm: Provide correct syndrome information for cpreg access
    traps
  target-arm: Add support for generating exceptions with syndrome
    information
  target-arm: A64: Correctly fault FP/Neon if CPACR.FPEN set
  target-arm: A64: Add assertion that FP access was checked
  target-arm: Fix VFP enables for AArch32 EL0 under AArch64 EL1
  target-arm: Don't mention PMU in debug feature register
  target-arm: A64: Implement DC ZVA
  target-arm: Use dedicated CPU state fields for ARM946 access bit
    registers
  target-arm: Add AArch64 ELR_EL1 register.
  target-arm: Implement SP_EL0, SP_EL1
  target-arm: Implement AArch64 SPSR_EL1
  target-arm: Move arm_log_exception() into internals.h
  target-arm: Implement ARMv8 MVFR registers
  target-arm: Add Cortex-A57 processor
  hw/arm/virt: Add support for Cortex-A57
  target-arm: Implement AArch64 views of AArch32 ID registers
  target-arm: Implement AArch64 view of CONTEXTIDR
  target-arm: Implement AArch64 view of ACTLR
  target-arm: Implement ISR_EL1 register
  target-arm: Remove THUMB2EE feature from AArch64 'any' CPU
  target-arm: Don't expose wildcard ID register definitions for ARMv8
  target-arm: Replace wildcarded cpreg definitions with precise ones for
    ARMv8
  target-arm: Implement auxiliary fault status registers
  target-arm: Implement AArch64 address translation operations
  target-arm: Implement RVBAR register
  target-arm: Implement Cortex-A57 implementation-defined system
    registers
  target-arm: Implement CBAR for Cortex-A57
  target-arm: Make Cortex-A15 CBAR read-only
  target-arm: Handle the CPU being in AArch32 mode in the AArch64 set_pc
  target-arm: Dump 32-bit CPU state if 64 bit CPU is in AArch32

Rob Herring (4):
  target-arm: Provide syndrome information for MMU faults
  target-arm: Add v8 mmu translation support
  target-arm: Implement AArch64 views of fault status and data registers
  target-arm: Implement AArch64 EL1 exception handling

 hw/arm/virt.c               |   8 +
 include/exec/softmmu_exec.h |  52 +++
 linux-user/main.c           |  56 ++-
 target-arm/cpu-qom.h        |  10 +-
 target-arm/cpu.c            |  30 +-
 target-arm/cpu.h            |  81 +++--
 target-arm/cpu64.c          | 115 ++++++-
 target-arm/helper-a64.c     |  75 ++++
 target-arm/helper.c         | 809 +++++++++++++++++++++++++++++++++-----------
 target-arm/helper.h         |   7 +-
 target-arm/internals.h      | 267 +++++++++++++++
 target-arm/kvm32.c          |  19 +-
 target-arm/kvm64.c          |  71 +++-
 target-arm/machine.c        |  13 +-
 target-arm/op_helper.c      |  92 ++++-
 target-arm/translate-a64.c  | 441 +++++++++++++++++++++---
 target-arm/translate.c      | 195 ++++++++---
 target-arm/translate.h      |  23 +-
 18 files changed, 1987 insertions(+), 377 deletions(-)
 create mode 100644 target-arm/internals.h

-- 
1.9.1

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

* [Qemu-devel] [PATCH v6 01/37] target-arm: Split out private-to-target functions into internals.h
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
@ 2014-04-10 16:15 ` Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 02/37] target-arm: Implement AArch64 DAIF system register Peter Maydell
                   ` (36 subsequent siblings)
  37 siblings, 0 replies; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

Currently cpu.h defines a mixture of functions and types needed by
the rest of QEMU and those needed only by files within target-arm/.
Split the latter out into a new header so they aren't needlessly
exposed further than required.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
 target-arm/cpu.c           |  1 +
 target-arm/cpu.h           | 20 -------------------
 target-arm/helper.c        |  1 +
 target-arm/internals.h     | 49 ++++++++++++++++++++++++++++++++++++++++++++++
 target-arm/kvm32.c         |  1 +
 target-arm/op_helper.c     |  1 +
 target-arm/translate-a64.c |  1 +
 target-arm/translate.c     |  1 +
 8 files changed, 55 insertions(+), 20 deletions(-)
 create mode 100644 target-arm/internals.h

diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index c32d8c4..0b1ad10 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -19,6 +19,7 @@
  */
 
 #include "cpu.h"
+#include "internals.h"
 #include "qemu-common.h"
 #include "hw/qdev-properties.h"
 #include "qapi/qmp/qerror.h"
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index bf37cd6..78d4fc5 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -111,11 +111,6 @@ typedef struct ARMGenericTimer {
 #define GTIMER_VIRT 1
 #define NUM_GTIMERS 2
 
-/* Scale factor for generic timers, ie number of ns per tick.
- * This gives a 62.5MHz timer.
- */
-#define GTIMER_SCALE 16
-
 typedef struct CPUARMState {
     /* Regs for current mode.  */
     uint32_t regs[16];
@@ -322,11 +317,7 @@ typedef struct CPUARMState {
 #include "cpu-qom.h"
 
 ARMCPU *cpu_arm_init(const char *cpu_model);
-void arm_translate_init(void);
-void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu);
 int cpu_arm_exec(CPUARMState *s);
-int bank_number(int mode);
-void switch_mode(CPUARMState *, int);
 uint32_t do_arm_semihosting(CPUARMState *env);
 
 static inline bool is_a64(CPUARMState *env)
@@ -548,17 +539,6 @@ static inline void vfp_set_fpcr(CPUARMState *env, uint32_t val)
     vfp_set_fpscr(env, new_fpscr);
 }
 
-enum arm_fprounding {
-    FPROUNDING_TIEEVEN,
-    FPROUNDING_POSINF,
-    FPROUNDING_NEGINF,
-    FPROUNDING_ZERO,
-    FPROUNDING_TIEAWAY,
-    FPROUNDING_ODD
-};
-
-int arm_rmode_to_sf(int rmode);
-
 enum arm_cpu_mode {
   ARM_CPU_MODE_USR = 0x10,
   ARM_CPU_MODE_FIQ = 0x11,
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 55077ed..e642b30 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1,4 +1,5 @@
 #include "cpu.h"
+#include "internals.h"
 #include "exec/gdbstub.h"
 #include "helper.h"
 #include "qemu/host-utils.h"
diff --git a/target-arm/internals.h b/target-arm/internals.h
new file mode 100644
index 0000000..a38a57f
--- /dev/null
+++ b/target-arm/internals.h
@@ -0,0 +1,49 @@
+/*
+ * QEMU ARM CPU -- internal functions and types
+ *
+ * Copyright (c) 2014 Linaro Ltd
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see
+ * <http://www.gnu.org/licenses/gpl-2.0.html>
+ *
+ * This header defines functions, types, etc which need to be shared
+ * between different source files within target-arm/ but which are
+ * private to it and not required by the rest of QEMU.
+ */
+
+#ifndef TARGET_ARM_INTERNALS_H
+#define TARGET_ARM_INTERNALS_H
+
+/* Scale factor for generic timers, ie number of ns per tick.
+ * This gives a 62.5MHz timer.
+ */
+#define GTIMER_SCALE 16
+
+int bank_number(int mode);
+void switch_mode(CPUARMState *, int);
+void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu);
+void arm_translate_init(void);
+
+enum arm_fprounding {
+    FPROUNDING_TIEEVEN,
+    FPROUNDING_POSINF,
+    FPROUNDING_NEGINF,
+    FPROUNDING_ZERO,
+    FPROUNDING_TIEAWAY,
+    FPROUNDING_ODD
+};
+
+int arm_rmode_to_sf(int rmode);
+
+#endif
diff --git a/target-arm/kvm32.c b/target-arm/kvm32.c
index a4fde07..b21f844 100644
--- a/target-arm/kvm32.c
+++ b/target-arm/kvm32.c
@@ -21,6 +21,7 @@
 #include "sysemu/kvm.h"
 #include "kvm_arm.h"
 #include "cpu.h"
+#include "internals.h"
 #include "hw/arm/arm.h"
 
 static inline void set_feature(uint64_t *features, int feature)
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 21ff58e..4193eca 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -18,6 +18,7 @@
  */
 #include "cpu.h"
 #include "helper.h"
+#include "internals.h"
 
 #define SIGNBIT (uint32_t)0x80000000
 #define SIGNBIT64 ((uint64_t)1 << 63)
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 9175e48..6689165 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -26,6 +26,7 @@
 #include "tcg-op.h"
 #include "qemu/log.h"
 #include "translate.h"
+#include "internals.h"
 #include "qemu/host-utils.h"
 
 #include "exec/gen-icount.h"
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 56e3b4b..f869bc6 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -25,6 +25,7 @@
 #include <inttypes.h>
 
 #include "cpu.h"
+#include "internals.h"
 #include "disas/disas.h"
 #include "tcg-op.h"
 #include "qemu/log.h"
-- 
1.9.1

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

* [Qemu-devel] [PATCH v6 02/37] target-arm: Implement AArch64 DAIF system register
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 01/37] target-arm: Split out private-to-target functions into internals.h Peter Maydell
@ 2014-04-10 16:15 ` Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 03/37] target-arm: Define exception record for AArch64 exceptions Peter Maydell
                   ` (35 subsequent siblings)
  37 siblings, 0 replies; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

Implement the DAIF system register which is a view of the
DAIF bits in PSTATE. To avoid needing a readfn, we widen
the daif field in CPUARMState to uint64_t.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
 target-arm/cpu.h    |  2 +-
 target-arm/helper.c | 20 ++++++++++++++++++++
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 78d4fc5..695a1e2 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -160,7 +160,7 @@ typedef struct CPUARMState {
     uint32_t GE; /* cpsr[19:16] */
     uint32_t thumb; /* cpsr[5]. 0 = arm mode, 1 = thumb mode. */
     uint32_t condexec_bits; /* IT bits.  cpsr[15:10,26:25].  */
-    uint32_t daif; /* exception masks, in the bits they are in in PSTATE */
+    uint64_t daif; /* exception masks, in the bits they are in in PSTATE */
 
     /* System control coprocessor (cp15) */
     struct {
diff --git a/target-arm/helper.c b/target-arm/helper.c
index e642b30..c8348da 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1691,6 +1691,20 @@ static void aa64_fpsr_write(CPUARMState *env, const ARMCPRegInfo *ri,
     vfp_set_fpsr(env, value);
 }
 
+static CPAccessResult aa64_daif_access(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    if (arm_current_pl(env) == 0 && !(env->cp15.c1_sys & SCTLR_UMA)) {
+        return CP_ACCESS_TRAP;
+    }
+    return CP_ACCESS_OK;
+}
+
+static void aa64_daif_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                            uint64_t value)
+{
+    env->daif = value & PSTATE_DAIF;
+}
+
 static CPAccessResult aa64_cacheop_access(CPUARMState *env,
                                           const ARMCPRegInfo *ri)
 {
@@ -1737,6 +1751,12 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
     { .name = "NZCV", .state = ARM_CP_STATE_AA64,
       .opc0 = 3, .opc1 = 3, .opc2 = 0, .crn = 4, .crm = 2,
       .access = PL0_RW, .type = ARM_CP_NZCV },
+    { .name = "DAIF", .state = ARM_CP_STATE_AA64,
+      .opc0 = 3, .opc1 = 3, .opc2 = 1, .crn = 4, .crm = 2,
+      .type = ARM_CP_NO_MIGRATE,
+      .access = PL0_RW, .accessfn = aa64_daif_access,
+      .fieldoffset = offsetof(CPUARMState, daif),
+      .writefn = aa64_daif_write, .resetfn = arm_cp_reset_ignore },
     { .name = "FPCR", .state = ARM_CP_STATE_AA64,
       .opc0 = 3, .opc1 = 3, .opc2 = 0, .crn = 4, .crm = 4,
       .access = PL0_RW, .readfn = aa64_fpcr_read, .writefn = aa64_fpcr_write },
-- 
1.9.1

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

* [Qemu-devel] [PATCH v6 03/37] target-arm: Define exception record for AArch64 exceptions
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 01/37] target-arm: Split out private-to-target functions into internals.h Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 02/37] target-arm: Implement AArch64 DAIF system register Peter Maydell
@ 2014-04-10 16:15 ` Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 04/37] target-arm: Provide correct syndrome information for cpreg access traps Peter Maydell
                   ` (34 subsequent siblings)
  37 siblings, 0 replies; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

For AArch32 exceptions, the only information provided about
the cause of an exception is the individual exception type (data
abort, undef, etc), which we store in cs->exception_index. For
AArch64, the CPU provides much more detail about the cause of
the exception, which can be found in the syndrome register.
Create a set of fields in CPUARMState which must be filled in
whenever an exception is raised, so that exception entry can
correctly fill in the syndrome register for the guest.
This includes the information which in AArch32 appears in
the DFAR and IFAR (fault address registers) and the DFSR
and IFSR (fault status registers) for data aborts and
prefetch aborts, since if we end up taking the MMU fault
to AArch64 rather than AArch32 this will need to end up
in different system registers.

This patch does a refactoring which moves the setting of the
AArch32 DFAR/DFSR/IFAR/IFSR from the point where the exception
is raised to the point where it is taken. (This is no change
for cores with an MMU, retains the existing clearly incorrect
behaviour for ARM946 of trashing the MP access permissions
registers which share the c5_data and c5_insn state fields,
and has no effect for v7M because we don't implement its
MPU fault status or address registers.)

As a side effect of the cleanup we fix a bug in the AArch64
linux-user mode code where we were passing a 64 bit fault
address through the 32 bit c6_data/c6_insn fields: it now
goes via the always-64-bit exception.vaddress.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
 linux-user/main.c    | 56 ++++++++++++++++++++++------------------------------
 target-arm/cpu.h     | 15 ++++++++++++++
 target-arm/helper.c  | 23 ++++++++++++---------
 target-arm/machine.c |  3 +++
 4 files changed, 56 insertions(+), 41 deletions(-)

diff --git a/linux-user/main.c b/linux-user/main.c
index af924dc..947358a 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -483,17 +483,17 @@ static void arm_kernel_cmpxchg64_helper(CPUARMState *env)
     addr = env->regs[2];
 
     if (get_user_u64(oldval, env->regs[0])) {
-        env->cp15.c6_data = env->regs[0];
+        env->exception.vaddress = env->regs[0];
         goto segv;
     };
 
     if (get_user_u64(newval, env->regs[1])) {
-        env->cp15.c6_data = env->regs[1];
+        env->exception.vaddress = env->regs[1];
         goto segv;
     };
 
     if (get_user_u64(val, addr)) {
-        env->cp15.c6_data = addr;
+        env->exception.vaddress = addr;
         goto segv;
     }
 
@@ -501,7 +501,7 @@ static void arm_kernel_cmpxchg64_helper(CPUARMState *env)
         val = newval;
 
         if (put_user_u64(val, addr)) {
-            env->cp15.c6_data = addr;
+            env->exception.vaddress = addr;
             goto segv;
         };
 
@@ -523,7 +523,7 @@ segv:
     info.si_errno = 0;
     /* XXX: check env->error_code */
     info.si_code = TARGET_SEGV_MAPERR;
-    info._sifields._sigfault._addr = env->cp15.c6_data;
+    info._sifields._sigfault._addr = env->exception.vaddress;
     queue_signal(env, info.si_signo, &info);
 
     end_exclusive();
@@ -620,14 +620,14 @@ static int do_strex(CPUARMState *env)
         abort();
     }
     if (segv) {
-        env->cp15.c6_data = addr;
+        env->exception.vaddress = addr;
         goto done;
     }
     if (size == 3) {
         uint32_t valhi;
         segv = get_user_u32(valhi, addr + 4);
         if (segv) {
-            env->cp15.c6_data = addr + 4;
+            env->exception.vaddress = addr + 4;
             goto done;
         }
         val = deposit64(val, 32, 32, valhi);
@@ -650,14 +650,14 @@ static int do_strex(CPUARMState *env)
         break;
     }
     if (segv) {
-        env->cp15.c6_data = addr;
+        env->exception.vaddress = addr;
         goto done;
     }
     if (size == 3) {
         val = env->regs[(env->exclusive_info >> 12) & 0xf];
         segv = put_user_u32(val, addr + 4);
         if (segv) {
-            env->cp15.c6_data = addr + 4;
+            env->exception.vaddress = addr + 4;
             goto done;
         }
     }
@@ -832,12 +832,14 @@ void cpu_loop(CPUARMState *env)
         case EXCP_INTERRUPT:
             /* just indicate that signals should be handled asap */
             break;
+        case EXCP_STREX:
+            if (!do_strex(env)) {
+                break;
+            }
+            /* fall through for segv */
         case EXCP_PREFETCH_ABORT:
-            addr = env->cp15.c6_insn;
-            goto do_segv;
         case EXCP_DATA_ABORT:
-            addr = env->cp15.c6_data;
-        do_segv:
+            addr = env->exception.vaddress;
             {
                 info.si_signo = SIGSEGV;
                 info.si_errno = 0;
@@ -865,12 +867,6 @@ void cpu_loop(CPUARMState *env)
             if (do_kernel_trap(env))
               goto error;
             break;
-        case EXCP_STREX:
-            if (do_strex(env)) {
-                addr = env->cp15.c6_data;
-                goto do_segv;
-            }
-            break;
         default:
         error:
             fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
@@ -933,7 +929,7 @@ static int do_strex_a64(CPUARMState *env)
         abort();
     }
     if (segv) {
-        env->cp15.c6_data = addr;
+        env->exception.vaddress = addr;
         goto error;
     }
     if (val != env->exclusive_val) {
@@ -946,7 +942,7 @@ static int do_strex_a64(CPUARMState *env)
             segv = get_user_u64(val, addr + 8);
         }
         if (segv) {
-            env->cp15.c6_data = addr + (size == 2 ? 4 : 8);
+            env->exception.vaddress = addr + (size == 2 ? 4 : 8);
             goto error;
         }
         if (val != env->exclusive_high) {
@@ -981,7 +977,7 @@ static int do_strex_a64(CPUARMState *env)
             segv = put_user_u64(val, addr + 8);
         }
         if (segv) {
-            env->cp15.c6_data = addr + (size == 2 ? 4 : 8);
+            env->exception.vaddress = addr + (size == 2 ? 4 : 8);
             goto error;
         }
     }
@@ -1037,12 +1033,14 @@ void cpu_loop(CPUARMState *env)
             info._sifields._sigfault._addr = env->pc;
             queue_signal(env, info.si_signo, &info);
             break;
+        case EXCP_STREX:
+            if (!do_strex_a64(env)) {
+                break;
+            }
+            /* fall through for segv */
         case EXCP_PREFETCH_ABORT:
-            addr = env->cp15.c6_insn;
-            goto do_segv;
         case EXCP_DATA_ABORT:
-            addr = env->cp15.c6_data;
-        do_segv:
+            addr = env->exception.vaddress;
             info.si_signo = SIGSEGV;
             info.si_errno = 0;
             /* XXX: check env->error_code */
@@ -1060,12 +1058,6 @@ void cpu_loop(CPUARMState *env)
                 queue_signal(env, info.si_signo, &info);
             }
             break;
-        case EXCP_STREX:
-            if (do_strex_a64(env)) {
-                addr = env->cp15.c6_data;
-                goto do_segv;
-            }
-            break;
         default:
             fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
                     trapnr);
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 695a1e2..7a48241 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -233,6 +233,21 @@ typedef struct CPUARMState {
         int pending_exception;
     } v7m;
 
+    /* Information associated with an exception about to be taken:
+     * code which raises an exception must set cs->exception_index and
+     * the relevant parts of this structure; the cpu_do_interrupt function
+     * will then set the guest-visible registers as part of the exception
+     * entry process.
+     */
+    struct {
+        uint32_t syndrome; /* AArch64 format syndrome register */
+        uint32_t fsr; /* AArch32 format fault status register info */
+        uint64_t vaddress; /* virtual addr associated with exception, if any */
+        /* If we implement EL2 we will also need to store information
+         * about the intermediate physical address for stage 2 faults.
+         */
+    } exception;
+
     /* Thumb-2 EE state.  */
     uint32_t teecr;
     uint32_t teehbr;
diff --git a/target-arm/helper.c b/target-arm/helper.c
index c8348da..fe642df 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2705,12 +2705,11 @@ int arm_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
     ARMCPU *cpu = ARM_CPU(cs);
     CPUARMState *env = &cpu->env;
 
+    env->exception.vaddress = address;
     if (rw == 2) {
         cs->exception_index = EXCP_PREFETCH_ABORT;
-        env->cp15.c6_insn = address;
     } else {
         cs->exception_index = EXCP_DATA_ABORT;
-        env->cp15.c6_data = address;
     }
     return 1;
 }
@@ -2928,6 +2927,9 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
         return;
     case EXCP_PREFETCH_ABORT:
     case EXCP_DATA_ABORT:
+        /* TODO: if we implemented the MPU registers, this is where we
+         * should set the MMFAR, etc from exception.fsr and exception.vaddress.
+         */
         armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_MEM);
         return;
     case EXCP_BKPT:
@@ -3042,9 +3044,11 @@ void arm_cpu_do_interrupt(CPUState *cs)
                 return;
             }
         }
-        env->cp15.c5_insn = 2;
+        env->exception.fsr = 2;
         /* Fall through to prefetch abort.  */
     case EXCP_PREFETCH_ABORT:
+        env->cp15.c5_insn = env->exception.fsr;
+        env->cp15.c6_insn = env->exception.vaddress;
         qemu_log_mask(CPU_LOG_INT, "...with IFSR 0x%x IFAR 0x%x\n",
                       env->cp15.c5_insn, env->cp15.c6_insn);
         new_mode = ARM_CPU_MODE_ABT;
@@ -3053,6 +3057,8 @@ void arm_cpu_do_interrupt(CPUState *cs)
         offset = 4;
         break;
     case EXCP_DATA_ABORT:
+        env->cp15.c5_data = env->exception.fsr;
+        env->cp15.c6_data = env->exception.vaddress;
         qemu_log_mask(CPU_LOG_INT, "...with DFSR 0x%x DFAR 0x%x\n",
                       env->cp15.c5_data, env->cp15.c6_data);
         new_mode = ARM_CPU_MODE_ABT;
@@ -3703,16 +3709,15 @@ int arm_cpu_handle_mmu_fault(CPUState *cs, vaddr address,
     }
 
     if (access_type == 2) {
-        env->cp15.c5_insn = ret;
-        env->cp15.c6_insn = address;
         cs->exception_index = EXCP_PREFETCH_ABORT;
     } else {
-        env->cp15.c5_data = ret;
-        if (access_type == 1 && arm_feature(env, ARM_FEATURE_V6))
-            env->cp15.c5_data |= (1 << 11);
-        env->cp15.c6_data = address;
+        if (access_type == 1 && arm_feature(env, ARM_FEATURE_V6)) {
+            ret |= (1 << 11);
+        }
         cs->exception_index = EXCP_DATA_ABORT;
     }
+    env->exception.vaddress = address;
+    env->exception.fsr = ret;
     return 1;
 }
 
diff --git a/target-arm/machine.c b/target-arm/machine.c
index 7ced87a..b9d9c0f 100644
--- a/target-arm/machine.c
+++ b/target-arm/machine.c
@@ -257,6 +257,9 @@ const VMStateDescription vmstate_arm_cpu = {
         VMSTATE_UINT64(env.exclusive_val, ARMCPU),
         VMSTATE_UINT64(env.exclusive_high, ARMCPU),
         VMSTATE_UINT64(env.features, ARMCPU),
+        VMSTATE_UINT32(env.exception.syndrome, ARMCPU),
+        VMSTATE_UINT32(env.exception.fsr, ARMCPU),
+        VMSTATE_UINT64(env.exception.vaddress, ARMCPU),
         VMSTATE_TIMER(gt_timer[GTIMER_PHYS], ARMCPU),
         VMSTATE_TIMER(gt_timer[GTIMER_VIRT], ARMCPU),
         VMSTATE_END_OF_LIST()
-- 
1.9.1

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

* [Qemu-devel] [PATCH v6 04/37] target-arm: Provide correct syndrome information for cpreg access traps
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
                   ` (2 preceding siblings ...)
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 03/37] target-arm: Define exception record for AArch64 exceptions Peter Maydell
@ 2014-04-10 16:15 ` Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 05/37] target-arm: Add support for generating exceptions with syndrome information Peter Maydell
                   ` (33 subsequent siblings)
  37 siblings, 0 replies; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

For exceptions taken to AArch64, if a coprocessor/system register
access fails due to a trap or enable bit then the syndrome information
must include details of the failing instruction (crn/crm/opc1/opc2
fields, etc). Make the decoder construct the syndrome information
at translate time so it can be passed at runtime to the access-check
helper function and used as required.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/helper.h        |   2 +-
 target-arm/internals.h     | 128 +++++++++++++++++++++++++++++++++++++++++++++
 target-arm/op_helper.c     |   8 +--
 target-arm/translate-a64.c |   8 ++-
 target-arm/translate.c     |  45 +++++++++++++++-
 5 files changed, 184 insertions(+), 7 deletions(-)

diff --git a/target-arm/helper.h b/target-arm/helper.h
index 366c1b3..2cdeadd 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -58,7 +58,7 @@ DEF_HELPER_1(cpsr_read, i32, env)
 DEF_HELPER_3(v7m_msr, void, env, i32, i32)
 DEF_HELPER_2(v7m_mrs, i32, env, i32)
 
-DEF_HELPER_2(access_check_cp_reg, void, env, ptr)
+DEF_HELPER_3(access_check_cp_reg, void, env, ptr, i32)
 DEF_HELPER_3(set_cp_reg, void, env, ptr, i32)
 DEF_HELPER_2(get_cp_reg, i32, env, ptr)
 DEF_HELPER_3(set_cp_reg64, void, env, ptr, i64)
diff --git a/target-arm/internals.h b/target-arm/internals.h
index a38a57f..cc3fbf9 100644
--- a/target-arm/internals.h
+++ b/target-arm/internals.h
@@ -46,4 +46,132 @@ enum arm_fprounding {
 
 int arm_rmode_to_sf(int rmode);
 
+/* Valid Syndrome Register EC field values */
+enum arm_exception_class {
+    EC_UNCATEGORIZED          = 0x00,
+    EC_WFX_TRAP               = 0x01,
+    EC_CP15RTTRAP             = 0x03,
+    EC_CP15RRTTRAP            = 0x04,
+    EC_CP14RTTRAP             = 0x05,
+    EC_CP14DTTRAP             = 0x06,
+    EC_ADVSIMDFPACCESSTRAP    = 0x07,
+    EC_FPIDTRAP               = 0x08,
+    EC_CP14RRTTRAP            = 0x0c,
+    EC_ILLEGALSTATE           = 0x0e,
+    EC_AA32_SVC               = 0x11,
+    EC_AA32_HVC               = 0x12,
+    EC_AA32_SMC               = 0x13,
+    EC_AA64_SVC               = 0x15,
+    EC_AA64_HVC               = 0x16,
+    EC_AA64_SMC               = 0x17,
+    EC_SYSTEMREGISTERTRAP     = 0x18,
+    EC_INSNABORT              = 0x20,
+    EC_INSNABORT_SAME_EL      = 0x21,
+    EC_PCALIGNMENT            = 0x22,
+    EC_DATAABORT              = 0x24,
+    EC_DATAABORT_SAME_EL      = 0x25,
+    EC_SPALIGNMENT            = 0x26,
+    EC_AA32_FPTRAP            = 0x28,
+    EC_AA64_FPTRAP            = 0x2c,
+    EC_SERROR                 = 0x2f,
+    EC_BREAKPOINT             = 0x30,
+    EC_BREAKPOINT_SAME_EL     = 0x31,
+    EC_SOFTWARESTEP           = 0x32,
+    EC_SOFTWARESTEP_SAME_EL   = 0x33,
+    EC_WATCHPOINT             = 0x34,
+    EC_WATCHPOINT_SAME_EL     = 0x35,
+    EC_AA32_BKPT              = 0x38,
+    EC_VECTORCATCH            = 0x3a,
+    EC_AA64_BKPT              = 0x3c,
+};
+
+#define ARM_EL_EC_SHIFT 26
+#define ARM_EL_IL_SHIFT 25
+#define ARM_EL_IL (1 << ARM_EL_IL_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
+ * 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.)
+ */
+static inline uint32_t syn_uncategorized(void)
+{
+    return (EC_UNCATEGORIZED << ARM_EL_EC_SHIFT) | ARM_EL_IL;
+}
+
+static inline uint32_t syn_aa64_svc(uint32_t imm16)
+{
+    return (EC_AA64_SVC << ARM_EL_EC_SHIFT) | ARM_EL_IL | (imm16 & 0xffff);
+}
+
+static inline uint32_t syn_aa32_svc(uint32_t imm16, bool is_thumb)
+{
+    return (EC_AA32_SVC << ARM_EL_EC_SHIFT) | (imm16 & 0xffff)
+        | (is_thumb ? 0 : ARM_EL_IL);
+}
+
+static inline uint32_t syn_aa64_bkpt(uint32_t imm16)
+{
+    return (EC_AA64_BKPT << ARM_EL_EC_SHIFT) | ARM_EL_IL | (imm16 & 0xffff);
+}
+
+static inline uint32_t syn_aa32_bkpt(uint32_t imm16, bool is_thumb)
+{
+    return (EC_AA32_BKPT << ARM_EL_EC_SHIFT) | (imm16 & 0xffff)
+        | (is_thumb ? 0 : ARM_EL_IL);
+}
+
+static inline uint32_t syn_aa64_sysregtrap(int op0, int op1, int op2,
+                                           int crn, int crm, int rt,
+                                           int isread)
+{
+    return (EC_SYSTEMREGISTERTRAP << ARM_EL_EC_SHIFT) | ARM_EL_IL
+        | (op0 << 20) | (op2 << 17) | (op1 << 14) | (crn << 10) | (rt << 5)
+        | (crm << 1) | isread;
+}
+
+static inline uint32_t syn_cp14_rt_trap(int cv, int cond, int opc1, int opc2,
+                                        int crn, int crm, int rt, int isread,
+                                        bool is_thumb)
+{
+    return (EC_CP14RTTRAP << ARM_EL_EC_SHIFT)
+        | (is_thumb ? 0 : ARM_EL_IL)
+        | (cv << 24) | (cond << 20) | (opc2 << 17) | (opc1 << 14)
+        | (crn << 10) | (rt << 5) | (crm << 1) | isread;
+}
+
+static inline uint32_t syn_cp15_rt_trap(int cv, int cond, int opc1, int opc2,
+                                        int crn, int crm, int rt, int isread,
+                                        bool is_thumb)
+{
+    return (EC_CP15RTTRAP << ARM_EL_EC_SHIFT)
+        | (is_thumb ? 0 : ARM_EL_IL)
+        | (cv << 24) | (cond << 20) | (opc2 << 17) | (opc1 << 14)
+        | (crn << 10) | (rt << 5) | (crm << 1) | isread;
+}
+
+static inline uint32_t syn_cp14_rrt_trap(int cv, int cond, int opc1, int crm,
+                                         int rt, int rt2, int isread,
+                                         bool is_thumb)
+{
+    return (EC_CP14RRTTRAP << ARM_EL_EC_SHIFT)
+        | (is_thumb ? 0 : ARM_EL_IL)
+        | (cv << 24) | (cond << 20) | (opc1 << 16)
+        | (rt2 << 10) | (rt << 5) | (crm << 1) | isread;
+}
+
+static inline uint32_t syn_cp15_rrt_trap(int cv, int cond, int opc1, int crm,
+                                         int rt, int rt2, int isread,
+                                         bool is_thumb)
+{
+    return (EC_CP15RRTTRAP << ARM_EL_EC_SHIFT)
+        | (is_thumb ? 0 : ARM_EL_IL)
+        | (cv << 24) | (cond << 20) | (opc1 << 16)
+        | (rt2 << 10) | (rt << 5) | (crm << 1) | isread;
+}
+
 #endif
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 4193eca..bacfbc0 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -294,17 +294,17 @@ void HELPER(set_user_reg)(CPUARMState *env, uint32_t regno, uint32_t val)
     }
 }
 
-void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip)
+void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip, uint32_t syndrome)
 {
     const ARMCPRegInfo *ri = rip;
     switch (ri->accessfn(env, ri)) {
     case CP_ACCESS_OK:
         return;
     case CP_ACCESS_TRAP:
+        env->exception.syndrome = syndrome;
+        break;
     case CP_ACCESS_TRAP_UNCATEGORIZED:
-        /* These cases will eventually need to generate different
-         * syndrome information.
-         */
+        env->exception.syndrome = syn_uncategorized();
         break;
     default:
         g_assert_not_reached();
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 6689165..37399df 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -1242,10 +1242,16 @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
          * runtime; this may result in an exception.
          */
         TCGv_ptr tmpptr;
+        TCGv_i32 tcg_syn;
+        uint32_t syndrome;
+
         gen_a64_set_pc_im(s->pc - 4);
         tmpptr = tcg_const_ptr(ri);
-        gen_helper_access_check_cp_reg(cpu_env, tmpptr);
+        syndrome = syn_aa64_sysregtrap(op0, op1, op2, crn, crm, rt, isread);
+        tcg_syn = tcg_const_i32(syndrome);
+        gen_helper_access_check_cp_reg(cpu_env, tmpptr, tcg_syn);
         tcg_temp_free_ptr(tmpptr);
+        tcg_temp_free_i32(tcg_syn);
     }
 
     /* Handle special cases first */
diff --git a/target-arm/translate.c b/target-arm/translate.c
index f869bc6..d31f5c1 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -6862,10 +6862,53 @@ static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
              * runtime; this may result in an exception.
              */
             TCGv_ptr tmpptr;
+            TCGv_i32 tcg_syn;
+            uint32_t syndrome;
+
+            /* Note that since we are an implementation which takes an
+             * exception on a trapped conditional instruction only if the
+             * instruction passes its condition code check, we can take
+             * advantage of the clause in the ARM ARM that allows us to set
+             * the COND field in the instruction to 0xE in all cases.
+             * We could fish the actual condition out of the insn (ARM)
+             * or the condexec bits (Thumb) but it isn't necessary.
+             */
+            switch (cpnum) {
+            case 14:
+                if (is64) {
+                    syndrome = syn_cp14_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
+                                                 isread, s->thumb);
+                } else {
+                    syndrome = syn_cp14_rt_trap(1, 0xe, opc1, opc2, crn, crm,
+                                                rt, isread, s->thumb);
+                }
+                break;
+            case 15:
+                if (is64) {
+                    syndrome = syn_cp15_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
+                                                 isread, s->thumb);
+                } else {
+                    syndrome = syn_cp15_rt_trap(1, 0xe, opc1, opc2, crn, crm,
+                                                rt, isread, s->thumb);
+                }
+                break;
+            default:
+                /* ARMv8 defines that only coprocessors 14 and 15 exist,
+                 * so this can only happen if this is an ARMv7 or earlier CPU,
+                 * in which case the syndrome information won't actually be
+                 * guest visible.
+                 */
+                assert(!arm_feature(env, ARM_FEATURE_V8));
+                syndrome = syn_uncategorized();
+                break;
+            }
+
             gen_set_pc_im(s, s->pc);
             tmpptr = tcg_const_ptr(ri);
-            gen_helper_access_check_cp_reg(cpu_env, tmpptr);
+            tcg_syn = tcg_const_i32(syndrome);
+            gen_helper_access_check_cp_reg(cpu_env, tmpptr, tcg_syn);
             tcg_temp_free_ptr(tmpptr);
+            tcg_temp_free_i32(tcg_syn);
         }
 
         /* Handle special cases first */
-- 
1.9.1

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

* [Qemu-devel] [PATCH v6 05/37] target-arm: Add support for generating exceptions with syndrome information
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
                   ` (3 preceding siblings ...)
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 04/37] target-arm: Provide correct syndrome information for cpreg access traps Peter Maydell
@ 2014-04-10 16:15 ` Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 06/37] target-arm: Provide syndrome information for MMU faults Peter Maydell
                   ` (32 subsequent siblings)
  37 siblings, 0 replies; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

Add new helpers exception_with_syndrome (for generating an exception
with syndrome information) and exception_uncategorized (for generating
an exception with "Unknown or Uncategorized Reason", which have a syndrome
register value of zero), and use them to generate the correct syndrome
information for exceptions which are raised directly from generated code.

This patch includes moving the A32/T32 gen_exception_insn functions
further up in the source file; they will be needed for "VFP/Neon disabled"
exception generation later.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
 target-arm/helper.h        |   3 +-
 target-arm/internals.h     |  14 ++++++
 target-arm/op_helper.c     |  21 ++++++++-
 target-arm/translate-a64.c |  49 +++++++++++++++------
 target-arm/translate.c     | 103 ++++++++++++++++++++++++++++-----------------
 target-arm/translate.h     |   4 ++
 6 files changed, 140 insertions(+), 54 deletions(-)

diff --git a/target-arm/helper.h b/target-arm/helper.h
index 2cdeadd..0abdb0c 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -48,7 +48,8 @@ DEF_HELPER_FLAGS_2(usad8, TCG_CALL_NO_RWG_SE, i32, i32, i32)
 
 DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE,
                    i32, i32, i32, i32)
-DEF_HELPER_2(exception, void, env, i32)
+DEF_HELPER_2(exception_internal, void, env, i32)
+DEF_HELPER_3(exception_with_syndrome, void, env, i32, i32)
 DEF_HELPER_1(wfi, void, env)
 DEF_HELPER_1(wfe, void, env)
 
diff --git a/target-arm/internals.h b/target-arm/internals.h
index cc3fbf9..0300ba3 100644
--- a/target-arm/internals.h
+++ b/target-arm/internals.h
@@ -25,6 +25,20 @@
 #ifndef TARGET_ARM_INTERNALS_H
 #define TARGET_ARM_INTERNALS_H
 
+static inline bool excp_is_internal(int excp)
+{
+    /* Return true if this exception number represents a QEMU-internal
+     * exception that will not be passed to the guest.
+     */
+    return excp == EXCP_INTERRUPT
+        || excp == EXCP_HLT
+        || excp == EXCP_DEBUG
+        || excp == EXCP_HALTED
+        || excp == EXCP_EXCEPTION_EXIT
+        || excp == EXCP_KERNEL_TRAP
+        || excp == EXCP_STREX;
+}
+
 /* Scale factor for generic timers, ie number of ns per tick.
  * This gives a 62.5MHz timer.
  */
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index bacfbc0..51edd90 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -244,11 +244,30 @@ void HELPER(wfe)(CPUARMState *env)
     cpu_loop_exit(cs);
 }
 
-void HELPER(exception)(CPUARMState *env, uint32_t excp)
+/* Raise an internal-to-QEMU exception. This is limited to only
+ * those EXCP values which are special cases for QEMU to interrupt
+ * execution and not to be used for exceptions which are passed to
+ * the guest (those must all have syndrome information and thus should
+ * use exception_with_syndrome).
+ */
+void HELPER(exception_internal)(CPUARMState *env, uint32_t excp)
+{
+    CPUState *cs = CPU(arm_env_get_cpu(env));
+
+    assert(excp_is_internal(excp));
+    cs->exception_index = excp;
+    cpu_loop_exit(cs);
+}
+
+/* Raise an exception with the specified syndrome register value */
+void HELPER(exception_with_syndrome)(CPUARMState *env, uint32_t excp,
+                                     uint32_t syndrome)
 {
     CPUState *cs = CPU(arm_env_get_cpu(env));
 
+    assert(!excp_is_internal(excp));
     cs->exception_index = excp;
+    env->exception.syndrome = syndrome;
     cpu_loop_exit(cs);
 }
 
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 37399df..210df2d 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -176,18 +176,37 @@ void gen_a64_set_pc_im(uint64_t val)
     tcg_gen_movi_i64(cpu_pc, val);
 }
 
-static void gen_exception(int excp)
+static void gen_exception_internal(int excp)
 {
-    TCGv_i32 tmp = tcg_temp_new_i32();
-    tcg_gen_movi_i32(tmp, excp);
-    gen_helper_exception(cpu_env, tmp);
-    tcg_temp_free_i32(tmp);
+    TCGv_i32 tcg_excp = tcg_const_i32(excp);
+
+    assert(excp_is_internal(excp));
+    gen_helper_exception_internal(cpu_env, tcg_excp);
+    tcg_temp_free_i32(tcg_excp);
+}
+
+static void gen_exception(int excp, uint32_t syndrome)
+{
+    TCGv_i32 tcg_excp = tcg_const_i32(excp);
+    TCGv_i32 tcg_syn = tcg_const_i32(syndrome);
+
+    gen_helper_exception_with_syndrome(cpu_env, tcg_excp, tcg_syn);
+    tcg_temp_free_i32(tcg_syn);
+    tcg_temp_free_i32(tcg_excp);
+}
+
+static void gen_exception_internal_insn(DisasContext *s, int offset, int excp)
+{
+    gen_a64_set_pc_im(s->pc - offset);
+    gen_exception_internal(excp);
+    s->is_jmp = DISAS_EXC;
 }
 
-static void gen_exception_insn(DisasContext *s, int offset, int excp)
+static void gen_exception_insn(DisasContext *s, int offset, int excp,
+                               uint32_t syndrome)
 {
     gen_a64_set_pc_im(s->pc - offset);
-    gen_exception(excp);
+    gen_exception(excp, syndrome);
     s->is_jmp = DISAS_EXC;
 }
 
@@ -219,7 +238,7 @@ static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest)
     } else {
         gen_a64_set_pc_im(dest);
         if (s->singlestep_enabled) {
-            gen_exception(EXCP_DEBUG);
+            gen_exception_internal(EXCP_DEBUG);
         }
         tcg_gen_exit_tb(0);
         s->is_jmp = DISAS_JUMP;
@@ -228,7 +247,8 @@ static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest)
 
 static void unallocated_encoding(DisasContext *s)
 {
-    gen_exception_insn(s, 4, EXCP_UDEF);
+    /* Unallocated and reserved encodings are uncategorized */
+    gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized());
 }
 
 #define unsupported_encoding(s, insn)                                    \
@@ -1373,6 +1393,7 @@ static void disas_exc(DisasContext *s, uint32_t insn)
 {
     int opc = extract32(insn, 21, 3);
     int op2_ll = extract32(insn, 0, 5);
+    int imm16 = extract32(insn, 5, 16);
 
     switch (opc) {
     case 0:
@@ -1383,7 +1404,7 @@ static void disas_exc(DisasContext *s, uint32_t insn)
             unallocated_encoding(s);
             break;
         }
-        gen_exception_insn(s, 0, EXCP_SWI);
+        gen_exception_insn(s, 0, EXCP_SWI, syn_aa64_svc(imm16));
         break;
     case 1:
         if (op2_ll != 0) {
@@ -1391,7 +1412,7 @@ static void disas_exc(DisasContext *s, uint32_t insn)
             break;
         }
         /* BRK */
-        gen_exception_insn(s, 0, EXCP_BKPT);
+        gen_exception_insn(s, 0, EXCP_BKPT, syn_aa64_bkpt(imm16));
         break;
     case 2:
         if (op2_ll != 0) {
@@ -1540,7 +1561,7 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
     tcg_gen_mov_i64(cpu_exclusive_test, addr);
     tcg_gen_movi_i32(cpu_exclusive_info,
                      size | is_pair << 2 | (rd << 4) | (rt << 9) | (rt2 << 14));
-    gen_exception_insn(s, 4, EXCP_STREX);
+    gen_exception_internal_insn(s, 4, EXCP_STREX);
 }
 #else
 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
@@ -10338,7 +10359,7 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
         if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
             QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
                 if (bp->pc == dc->pc) {
-                    gen_exception_insn(dc, 0, EXCP_DEBUG);
+                    gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
                     /* Advance PC so that clearing the breakpoint will
                        invalidate this TB.  */
                     dc->pc += 2;
@@ -10401,7 +10422,7 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
         if (dc->is_jmp != DISAS_JUMP) {
             gen_a64_set_pc_im(dc->pc);
         }
-        gen_exception(EXCP_DEBUG);
+        gen_exception_internal(EXCP_DEBUG);
     } else {
         switch (dc->is_jmp) {
         case DISAS_NEXT:
diff --git a/target-arm/translate.c b/target-arm/translate.c
index d31f5c1..84700ca 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -183,12 +183,23 @@ static inline void gen_set_cpsr(TCGv_i32 var, uint32_t mask)
 /* Set NZCV flags from the high 4 bits of var.  */
 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
 
-static void gen_exception(int excp)
+static void gen_exception_internal(int excp)
 {
-    TCGv_i32 tmp = tcg_temp_new_i32();
-    tcg_gen_movi_i32(tmp, excp);
-    gen_helper_exception(cpu_env, tmp);
-    tcg_temp_free_i32(tmp);
+    TCGv_i32 tcg_excp = tcg_const_i32(excp);
+
+    assert(excp_is_internal(excp));
+    gen_helper_exception_internal(cpu_env, tcg_excp);
+    tcg_temp_free_i32(tcg_excp);
+}
+
+static void gen_exception(int excp, uint32_t syndrome)
+{
+    TCGv_i32 tcg_excp = tcg_const_i32(excp);
+    TCGv_i32 tcg_syn = tcg_const_i32(syndrome);
+
+    gen_helper_exception_with_syndrome(cpu_env, tcg_excp, tcg_syn);
+    tcg_temp_free_i32(tcg_syn);
+    tcg_temp_free_i32(tcg_excp);
 }
 
 static void gen_smul_dual(TCGv_i32 a, TCGv_i32 b)
@@ -900,6 +911,33 @@ static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
     tcg_gen_movi_i32(cpu_R[15], val);
 }
 
+static inline void
+gen_set_condexec (DisasContext *s)
+{
+    if (s->condexec_mask) {
+        uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
+        TCGv_i32 tmp = tcg_temp_new_i32();
+        tcg_gen_movi_i32(tmp, val);
+        store_cpu_field(tmp, condexec_bits);
+    }
+}
+
+static void gen_exception_internal_insn(DisasContext *s, int offset, int excp)
+{
+    gen_set_condexec(s);
+    gen_set_pc_im(s, s->pc - offset);
+    gen_exception_internal(excp);
+    s->is_jmp = DISAS_JUMP;
+}
+
+static void gen_exception_insn(DisasContext *s, int offset, int excp, int syn)
+{
+    gen_set_condexec(s);
+    gen_set_pc_im(s, s->pc - offset);
+    gen_exception(excp, syn);
+    s->is_jmp = DISAS_JUMP;
+}
+
 /* Force a TB lookup after an instruction that changes the CPU state.  */
 static inline void gen_lookup_tb(DisasContext *s)
 {
@@ -3913,25 +3951,6 @@ static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
     s->is_jmp = DISAS_UPDATE;
 }
 
-static inline void
-gen_set_condexec (DisasContext *s)
-{
-    if (s->condexec_mask) {
-        uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
-        TCGv_i32 tmp = tcg_temp_new_i32();
-        tcg_gen_movi_i32(tmp, val);
-        store_cpu_field(tmp, condexec_bits);
-    }
-}
-
-static void gen_exception_insn(DisasContext *s, int offset, int excp)
-{
-    gen_set_condexec(s);
-    gen_set_pc_im(s, s->pc - offset);
-    gen_exception(excp);
-    s->is_jmp = DISAS_JUMP;
-}
-
 static void gen_nop_hint(DisasContext *s, int val)
 {
     switch (val) {
@@ -7160,7 +7179,7 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
     tcg_gen_extu_i32_i64(cpu_exclusive_test, addr);
     tcg_gen_movi_i32(cpu_exclusive_info,
                      size | (rd << 4) | (rt << 8) | (rt2 << 12));
-    gen_exception_insn(s, 4, EXCP_STREX);
+    gen_exception_internal_insn(s, 4, EXCP_STREX);
 }
 #else
 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
@@ -7670,6 +7689,8 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
             store_reg(s, rd, tmp);
             break;
         case 7:
+        {
+            int imm16 = extract32(insn, 0, 4) | (extract32(insn, 8, 12) << 4);
             /* SMC instruction (op1 == 3)
                and undefined instructions (op1 == 0 || op1 == 2)
                will trap */
@@ -7678,8 +7699,9 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
             }
             /* bkpt */
             ARCH(5);
-            gen_exception_insn(s, 4, EXCP_BKPT);
+            gen_exception_insn(s, 4, EXCP_BKPT, syn_aa32_bkpt(imm16, false));
             break;
+        }
         case 0x8: /* signed multiply */
         case 0xa:
         case 0xc:
@@ -8686,11 +8708,12 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
         case 0xf:
             /* swi */
             gen_set_pc_im(s, s->pc);
+            s->svc_imm = extract32(insn, 0, 24);
             s->is_jmp = DISAS_SWI;
             break;
         default:
         illegal_op:
-            gen_exception_insn(s, 4, EXCP_UDEF);
+            gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized());
             break;
         }
     }
@@ -10501,9 +10524,12 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
             break;
 
         case 0xe: /* bkpt */
+        {
+            int imm8 = extract32(insn, 0, 8);
             ARCH(5);
-            gen_exception_insn(s, 2, EXCP_BKPT);
+            gen_exception_insn(s, 2, EXCP_BKPT, syn_aa32_bkpt(imm8, true));
             break;
+        }
 
         case 0xa: /* rev */
             ARCH(6);
@@ -10620,6 +10646,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
         if (cond == 0xf) {
             /* swi */
             gen_set_pc_im(s, s->pc);
+            s->svc_imm = extract32(insn, 0, 8);
             s->is_jmp = DISAS_SWI;
             break;
         }
@@ -10655,11 +10682,11 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
     }
     return;
 undef32:
-    gen_exception_insn(s, 4, EXCP_UDEF);
+    gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized());
     return;
 illegal_op:
 undef:
-    gen_exception_insn(s, 2, EXCP_UDEF);
+    gen_exception_insn(s, 2, EXCP_UDEF, syn_uncategorized());
 }
 
 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
@@ -10780,7 +10807,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
         if (dc->pc >= 0xffff0000) {
             /* We always get here via a jump, so know we are not in a
                conditional execution block.  */
-            gen_exception(EXCP_KERNEL_TRAP);
+            gen_exception_internal(EXCP_KERNEL_TRAP);
             dc->is_jmp = DISAS_UPDATE;
             break;
         }
@@ -10788,7 +10815,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
         if (dc->pc >= 0xfffffff0 && IS_M(env)) {
             /* We always get here via a jump, so know we are not in a
                conditional execution block.  */
-            gen_exception(EXCP_EXCEPTION_EXIT);
+            gen_exception_internal(EXCP_EXCEPTION_EXIT);
             dc->is_jmp = DISAS_UPDATE;
             break;
         }
@@ -10797,7 +10824,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
         if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
             QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
                 if (bp->pc == dc->pc) {
-                    gen_exception_insn(dc, 0, EXCP_DEBUG);
+                    gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
                     /* Advance PC so that clearing the breakpoint will
                        invalidate this TB.  */
                     dc->pc += 2;
@@ -10877,9 +10904,9 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
         if (dc->condjmp) {
             gen_set_condexec(dc);
             if (dc->is_jmp == DISAS_SWI) {
-                gen_exception(EXCP_SWI);
+                gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
             } else {
-                gen_exception(EXCP_DEBUG);
+                gen_exception_internal(EXCP_DEBUG);
             }
             gen_set_label(dc->condlabel);
         }
@@ -10889,11 +10916,11 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
         }
         gen_set_condexec(dc);
         if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
-            gen_exception(EXCP_SWI);
+            gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
         } else {
             /* FIXME: Single stepping a WFI insn will not halt
                the CPU.  */
-            gen_exception(EXCP_DEBUG);
+            gen_exception_internal(EXCP_DEBUG);
         }
     } else {
         /* While branches must always occur at the end of an IT block,
@@ -10925,7 +10952,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
             gen_helper_wfe(cpu_env);
             break;
         case DISAS_SWI:
-            gen_exception(EXCP_SWI);
+            gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
             break;
         }
         if (dc->condjmp) {
diff --git a/target-arm/translate.h b/target-arm/translate.h
index 3525ffc..5c18dc9 100644
--- a/target-arm/translate.h
+++ b/target-arm/translate.h
@@ -23,6 +23,10 @@ typedef struct DisasContext {
     int vfp_enabled;
     int vec_len;
     int vec_stride;
+    /* Immediate value in AArch32 SVC insn; must be set if is_jmp == DISAS_SWI
+     * so that top level loop can generate correct syndrome information.
+     */
+    uint32_t svc_imm;
     int aarch64;
     int current_pl;
     GHashTable *cp_regs;
-- 
1.9.1

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

* [Qemu-devel] [PATCH v6 06/37] target-arm: Provide syndrome information for MMU faults
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
                   ` (4 preceding siblings ...)
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 05/37] target-arm: Add support for generating exceptions with syndrome information Peter Maydell
@ 2014-04-10 16:15 ` Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 07/37] target-arm: A64: Correctly fault FP/Neon if CPACR.FPEN set Peter Maydell
                   ` (31 subsequent siblings)
  37 siblings, 0 replies; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

From: Rob Herring <rob.herring@linaro.org>

Set up the required syndrome information when we detect an MMU fault.

Signed-off-by: Rob Herring <rob.herring@linaro.org>
[PMM: split out from exception handling patch, tweaked to bring
 in line with how we create other kinds of syndrome information]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/helper.c    | 12 ++++++++++++
 target-arm/internals.h | 13 +++++++++++++
 2 files changed, 25 insertions(+)

diff --git a/target-arm/helper.c b/target-arm/helper.c
index fe642df..9866e50 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3696,6 +3696,8 @@ int arm_cpu_handle_mmu_fault(CPUState *cs, vaddr address,
     target_ulong page_size;
     int prot;
     int ret, is_user;
+    uint32_t syn;
+    bool same_el = (arm_current_pl(env) != 0);
 
     is_user = mmu_idx == MMU_USER_IDX;
     ret = get_phys_addr(env, address, access_type, is_user, &phys_addr, &prot,
@@ -3708,14 +3710,24 @@ int arm_cpu_handle_mmu_fault(CPUState *cs, vaddr address,
         return 0;
     }
 
+    /* AArch64 syndrome does not have an LPAE bit */
+    syn = ret & ~(1 << 9);
+
+    /* For insn and data aborts we assume there is no instruction syndrome
+     * information; this is always true for exceptions reported to EL1.
+     */
     if (access_type == 2) {
+        syn = syn_insn_abort(same_el, 0, 0, syn);
         cs->exception_index = EXCP_PREFETCH_ABORT;
     } else {
+        syn = syn_data_abort(same_el, 0, 0, 0, access_type == 1, syn);
         if (access_type == 1 && arm_feature(env, ARM_FEATURE_V6)) {
             ret |= (1 << 11);
         }
         cs->exception_index = EXCP_DATA_ABORT;
     }
+
+    env->exception.syndrome = syn;
     env->exception.vaddress = address;
     env->exception.fsr = ret;
     return 1;
diff --git a/target-arm/internals.h b/target-arm/internals.h
index 0300ba3..fad203b 100644
--- a/target-arm/internals.h
+++ b/target-arm/internals.h
@@ -188,4 +188,17 @@ static inline uint32_t syn_cp15_rrt_trap(int cv, int cond, int opc1, int crm,
         | (rt2 << 10) | (rt << 5) | (crm << 1) | isread;
 }
 
+static inline uint32_t syn_insn_abort(int same_el, int ea, int s1ptw, int fsc)
+{
+    return (EC_INSNABORT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT)
+        | (ea << 9) | (s1ptw << 7) | fsc;
+}
+
+static inline uint32_t syn_data_abort(int same_el, int ea, int cm, int s1ptw,
+                                      int wnr, int fsc)
+{
+    return (EC_DATAABORT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT)
+        | (ea << 9) | (cm << 8) | (s1ptw << 7) | (wnr << 6) | fsc;
+}
+
 #endif
-- 
1.9.1

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

* [Qemu-devel] [PATCH v6 07/37] target-arm: A64: Correctly fault FP/Neon if CPACR.FPEN set
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
                   ` (5 preceding siblings ...)
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 06/37] target-arm: Provide syndrome information for MMU faults Peter Maydell
@ 2014-04-10 16:15 ` Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 08/37] target-arm: A64: Add assertion that FP access was checked Peter Maydell
                   ` (30 subsequent siblings)
  37 siblings, 0 replies; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

For the A64 instruction set, the only FP/Neon disable trap
is the CPACR FPEN bits, which may indicate "enabled", "disabled"
or "disabled for EL0". Add a bit to the AArch64 tb flags indicating
whether FP/Neon access is currently enabled and make the decoder
emit code to raise exceptions on use of FP/Neon insns if it is not.

We use a new flag in DisasContext rather than borrowing the
existing vfp_enabled flag because the A32/T32 decoder is going
to need both.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
I'm aware this is a rather hard to review patch; sorry.
I have done an exhaustive check that we have fp access checks
in all code paths with the aid of the assertions added in the
next patch plus the code-coverage hack patch I posted to the
list earlier.

This patch is correct as of
09e037354 target-arm: A64: Add saturating accumulate ops (USQADD/SUQADD)
which was the last of the Neon insns to be added, so assuming
no refactoring of the code it should be fine.
---
 target-arm/cpu.c           |   7 ++
 target-arm/cpu.h           |   9 ++
 target-arm/internals.h     |   7 ++
 target-arm/translate-a64.c | 300 ++++++++++++++++++++++++++++++++++++++++++++-
 target-arm/translate.h     |   3 +-
 5 files changed, 320 insertions(+), 6 deletions(-)

diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 0b1ad10..d62b792 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -100,9 +100,16 @@ static void arm_cpu_reset(CPUState *s)
         env->pstate = PSTATE_MODE_EL0t;
         /* Userspace expects access to CTL_EL0 and the cache ops */
         env->cp15.c1_sys |= SCTLR_UCT | SCTLR_UCI;
+        /* and to the FP/Neon instructions */
+        env->cp15.c1_coproc = deposit64(env->cp15.c1_coproc, 20, 2, 3);
 #else
         env->pstate = PSTATE_MODE_EL1h;
 #endif
+    } else {
+#if defined(CONFIG_USER_ONLY)
+        /* Userspace expects access to cp10 and cp11 for FP/Neon */
+        env->cp15.c1_coproc = deposit64(env->cp15.c1_coproc, 20, 4, 0xf);
+#endif
     }
 
 #if defined(CONFIG_USER_ONLY)
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 7a48241..72c4c7a 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1108,6 +1108,8 @@ static inline int cpu_mmu_index (CPUARMState *env)
 /* Bit usage when in AArch64 state */
 #define ARM_TBFLAG_AA64_EL_SHIFT    0
 #define ARM_TBFLAG_AA64_EL_MASK     (0x3 << ARM_TBFLAG_AA64_EL_SHIFT)
+#define ARM_TBFLAG_AA64_FPEN_SHIFT  2
+#define ARM_TBFLAG_AA64_FPEN_MASK   (1 << ARM_TBFLAG_AA64_FPEN_SHIFT)
 
 /* some convenience accessor macros */
 #define ARM_TBFLAG_AARCH64_STATE(F) \
@@ -1128,14 +1130,21 @@ static inline int cpu_mmu_index (CPUARMState *env)
     (((F) & ARM_TBFLAG_BSWAP_CODE_MASK) >> ARM_TBFLAG_BSWAP_CODE_SHIFT)
 #define ARM_TBFLAG_AA64_EL(F) \
     (((F) & ARM_TBFLAG_AA64_EL_MASK) >> ARM_TBFLAG_AA64_EL_SHIFT)
+#define ARM_TBFLAG_AA64_FPEN(F) \
+    (((F) & ARM_TBFLAG_AA64_FPEN_MASK) >> ARM_TBFLAG_AA64_FPEN_SHIFT)
 
 static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
                                         target_ulong *cs_base, int *flags)
 {
+    int fpen = extract32(env->cp15.c1_coproc, 20, 2);
+
     if (is_a64(env)) {
         *pc = env->pc;
         *flags = ARM_TBFLAG_AARCH64_STATE_MASK
             | (arm_current_pl(env) << ARM_TBFLAG_AA64_EL_SHIFT);
+        if (fpen == 3 || (fpen == 1 && arm_current_pl(env) != 0)) {
+            *flags |= ARM_TBFLAG_AA64_FPEN_MASK;
+        }
     } else {
         int privmode;
         *pc = env->regs[15];
diff --git a/target-arm/internals.h b/target-arm/internals.h
index fad203b..a527f02 100644
--- a/target-arm/internals.h
+++ b/target-arm/internals.h
@@ -188,6 +188,13 @@ static inline uint32_t syn_cp15_rrt_trap(int cv, int cond, int opc1, int crm,
         | (rt2 << 10) | (rt << 5) | (crm << 1) | isread;
 }
 
+static inline uint32_t syn_fp_access_trap(int cv, int cond, bool is_thumb)
+{
+    return (EC_ADVSIMDFPACCESSTRAP << ARM_EL_EC_SHIFT)
+        | (is_thumb ? 0 : ARM_EL_IL)
+        | (cv << 24) | (cond << 20);
+}
+
 static inline uint32_t syn_insn_abort(int same_el, int ea, int s1ptw, int fsc)
 {
     return (EC_INSNABORT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT)
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 210df2d..2f67af3 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -890,6 +890,23 @@ static void do_vec_ld(DisasContext *s, int destidx, int element,
     tcg_temp_free_i64(tcg_tmp);
 }
 
+/* Check that FP/Neon access is enabled. If it is, return
+ * true. If not, emit code to generate an appropriate exception,
+ * and return false; the caller should not emit any code for
+ * the instruction. Note that this check must happen after all
+ * unallocated-encoding checks (otherwise the syndrome information
+ * for the resulting exception will be incorrect).
+ */
+static inline bool fp_access_check(DisasContext *s)
+{
+    if (s->cpacr_fpen) {
+        return true;
+    }
+
+    gen_exception_insn(s, 4, EXCP_UDEF, syn_fp_access_trap(1, 0xe, false));
+    return false;
+}
+
 /*
  * This utility function is for doing register extension with an
  * optional shift. You will likely want to pass a temporary for the
@@ -1728,6 +1745,9 @@ static void disas_ld_lit(DisasContext *s, uint32_t insn)
             return;
         }
         size = 2 + opc;
+        if (!fp_access_check(s)) {
+            return;
+        }
     } else {
         if (opc == 3) {
             /* PRFM (literal) : prefetch */
@@ -1837,6 +1857,10 @@ static void disas_ldst_pair(DisasContext *s, uint32_t insn)
         break;
     }
 
+    if (is_vector && !fp_access_check(s)) {
+        return;
+    }
+
     offset <<= size;
 
     if (rn == 31) {
@@ -1930,6 +1954,9 @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn)
             return;
         }
         is_store = ((opc & 1) == 0);
+        if (!fp_access_check(s)) {
+            return;
+        }
     } else {
         if (size == 3 && opc == 2) {
             /* PRFM - prefetch */
@@ -2050,6 +2077,9 @@ static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn)
             return;
         }
         is_store = !extract32(opc, 0, 1);
+        if (!fp_access_check(s)) {
+            return;
+        }
     } else {
         if (size == 3 && opc == 2) {
             /* PRFM - prefetch */
@@ -2130,6 +2160,9 @@ static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn)
             return;
         }
         is_store = !extract32(opc, 0, 1);
+        if (!fp_access_check(s)) {
+            return;
+        }
     } else {
         if (size == 3 && opc == 2) {
             /* PRFM - prefetch */
@@ -2272,6 +2305,10 @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
         return;
     }
 
+    if (!fp_access_check(s)) {
+        return;
+    }
+
     if (rn == 31) {
         gen_check_sp_alignment(s);
     }
@@ -2398,6 +2435,10 @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
         g_assert_not_reached();
     }
 
+    if (!fp_access_check(s)) {
+        return;
+    }
+
     ebytes = 1 << scale;
 
     if (rn == 31) {
@@ -3874,6 +3915,10 @@ static void disas_fp_compare(DisasContext *s, uint32_t insn)
         return;
     }
 
+    if (!fp_access_check(s)) {
+        return;
+    }
+
     handle_fp_compare(s, type, rn, rm, opc & 1, opc & 2);
 }
 
@@ -3902,6 +3947,10 @@ static void disas_fp_ccomp(DisasContext *s, uint32_t insn)
         return;
     }
 
+    if (!fp_access_check(s)) {
+        return;
+    }
+
     if (cond < 0x0e) { /* not always */
         int label_match = gen_new_label();
         label_continue = gen_new_label();
@@ -3958,6 +4007,10 @@ static void disas_fp_csel(DisasContext *s, uint32_t insn)
         return;
     }
 
+    if (!fp_access_check(s)) {
+        return;
+    }
+
     if (cond < 0x0e) { /* not always */
         int label_match = gen_new_label();
         label_continue = gen_new_label();
@@ -4175,6 +4228,10 @@ static void disas_fp_1src(DisasContext *s, uint32_t insn)
             unallocated_encoding(s);
             return;
         }
+        if (!fp_access_check(s)) {
+            return;
+        }
+
         handle_fp_fcvt(s, opcode, rd, rn, dtype, type);
         break;
     }
@@ -4184,9 +4241,17 @@ static void disas_fp_1src(DisasContext *s, uint32_t insn)
         /* 32-to-32 and 64-to-64 ops */
         switch (type) {
         case 0:
+            if (!fp_access_check(s)) {
+                return;
+            }
+
             handle_fp_1src_single(s, opcode, rd, rn);
             break;
         case 1:
+            if (!fp_access_check(s)) {
+                return;
+            }
+
             handle_fp_1src_double(s, opcode, rd, rn);
             break;
         default:
@@ -4326,9 +4391,15 @@ static void disas_fp_2src(DisasContext *s, uint32_t insn)
 
     switch (type) {
     case 0:
+        if (!fp_access_check(s)) {
+            return;
+        }
         handle_fp_2src_single(s, opcode, rd, rn, rm);
         break;
     case 1:
+        if (!fp_access_check(s)) {
+            return;
+        }
         handle_fp_2src_double(s, opcode, rd, rn, rm);
         break;
     default:
@@ -4430,9 +4501,15 @@ static void disas_fp_3src(DisasContext *s, uint32_t insn)
 
     switch (type) {
     case 0:
+        if (!fp_access_check(s)) {
+            return;
+        }
         handle_fp_3src_single(s, o0, o1, rd, rn, rm, ra);
         break;
     case 1:
+        if (!fp_access_check(s)) {
+            return;
+        }
         handle_fp_3src_double(s, o0, o1, rd, rn, rm, ra);
         break;
     default:
@@ -4459,6 +4536,10 @@ static void disas_fp_imm(DisasContext *s, uint32_t insn)
         return;
     }
 
+    if (!fp_access_check(s)) {
+        return;
+    }
+
     /* The imm8 encodes the sign bit, enough bits to represent
      * an exponent in the range 01....1xx to 10....0xx,
      * and the most significant 4 bits of the mantissa; see
@@ -4645,6 +4726,10 @@ static void disas_fp_fixed_conv(DisasContext *s, uint32_t insn)
         return;
     }
 
+    if (!fp_access_check(s)) {
+        return;
+    }
+
     handle_fpfpcvt(s, rd, rn, opcode, itof, FPROUNDING_ZERO, scale, sf, type);
 }
 
@@ -4744,6 +4829,9 @@ static void disas_fp_int_conv(DisasContext *s, uint32_t insn)
             break;
         }
 
+        if (!fp_access_check(s)) {
+            return;
+        }
         handle_fmov(s, rd, rn, type, itof);
     } else {
         /* actual FP conversions */
@@ -4754,6 +4842,9 @@ static void disas_fp_int_conv(DisasContext *s, uint32_t insn)
             return;
         }
 
+        if (!fp_access_check(s)) {
+            return;
+        }
         handle_fpfpcvt(s, rd, rn, opcode, itof, rmode, 64, sf, type);
     }
 }
@@ -4854,6 +4945,10 @@ static void disas_simd_ext(DisasContext *s, uint32_t insn)
         return;
     }
 
+    if (!fp_access_check(s)) {
+        return;
+    }
+
     tcg_resh = tcg_temp_new_i64();
     tcg_resl = tcg_temp_new_i64();
 
@@ -4924,6 +5019,10 @@ static void disas_simd_tb(DisasContext *s, uint32_t insn)
         return;
     }
 
+    if (!fp_access_check(s)) {
+        return;
+    }
+
     /* This does a table lookup: for every byte element in the input
      * we index into a table formed from up to four vector registers,
      * and then the output is the result of the lookups. Our helper
@@ -4994,6 +5093,10 @@ static void disas_simd_zip_trn(DisasContext *s, uint32_t insn)
         return;
     }
 
+    if (!fp_access_check(s)) {
+        return;
+    }
+
     tcg_resl = tcg_const_i64(0);
     tcg_resh = tcg_const_i64(0);
     tcg_res = tcg_temp_new_i64();
@@ -5127,6 +5230,10 @@ static void disas_simd_across_lanes(DisasContext *s, uint32_t insn)
         return;
     }
 
+    if (!fp_access_check(s)) {
+        return;
+    }
+
     esize = 8 << size;
     elements = (is_q ? 128 : 64) / esize;
 
@@ -5259,6 +5366,10 @@ static void handle_simd_dupe(DisasContext *s, int is_q, int rd, int rn,
         return;
     }
 
+    if (!fp_access_check(s)) {
+        return;
+    }
+
     index = imm5 >> (size + 1);
 
     tmp = tcg_temp_new_i64();
@@ -5293,6 +5404,10 @@ static void handle_simd_dupes(DisasContext *s, int rd, int rn,
         return;
     }
 
+    if (!fp_access_check(s)) {
+        return;
+    }
+
     index = imm5 >> (size + 1);
 
     /* This instruction just extracts the specified element and
@@ -5325,6 +5440,11 @@ static void handle_simd_dupg(DisasContext *s, int is_q, int rd, int rn,
         unallocated_encoding(s);
         return;
     }
+
+    if (!fp_access_check(s)) {
+        return;
+    }
+
     for (i = 0; i < elements; i++) {
         write_vec_element(s, cpu_reg(s, rn), rd, i, size);
     }
@@ -5354,6 +5474,11 @@ static void handle_simd_inse(DisasContext *s, int rd, int rn,
         unallocated_encoding(s);
         return;
     }
+
+    if (!fp_access_check(s)) {
+        return;
+    }
+
     dst_index = extract32(imm5, 1+size, 5);
     src_index = extract32(imm4, size, 4);
 
@@ -5386,6 +5511,10 @@ static void handle_simd_insg(DisasContext *s, int rd, int rn, int imm5)
         return;
     }
 
+    if (!fp_access_check(s)) {
+        return;
+    }
+
     idx = extract32(imm5, 1 + size, 4 - size);
     write_vec_element(s, cpu_reg(s, rn), rd, idx, size);
 }
@@ -5423,6 +5552,11 @@ static void handle_simd_umov_smov(DisasContext *s, int is_q, int is_signed,
             return;
         }
     }
+
+    if (!fp_access_check(s)) {
+        return;
+    }
+
     element = extract32(imm5, 1+size, 4);
 
     tcg_rd = cpu_reg(s, rd);
@@ -5515,6 +5649,10 @@ static void disas_simd_mod_imm(DisasContext *s, uint32_t insn)
         return;
     }
 
+    if (!fp_access_check(s)) {
+        return;
+    }
+
     /* See AdvSIMDExpandImm() in ARM ARM */
     switch (cmode_3_1) {
     case 0: /* Replicate(Zeros(24):imm8, 2) */
@@ -5663,6 +5801,10 @@ static void disas_simd_scalar_pairwise(DisasContext *s, uint32_t insn)
             unallocated_encoding(s);
             return;
         }
+        if (!fp_access_check(s)) {
+            return;
+        }
+
         TCGV_UNUSED_PTR(fpst);
         break;
     case 0xc: /* FMAXNMP */
@@ -5675,6 +5817,10 @@ static void disas_simd_scalar_pairwise(DisasContext *s, uint32_t insn)
             unallocated_encoding(s);
             return;
         }
+        if (!fp_access_check(s)) {
+            return;
+        }
+
         size = extract32(size, 0, 1) ? 3 : 2;
         fpst = get_fpstatus_ptr();
         break;
@@ -5893,6 +6039,10 @@ static void handle_scalar_simd_shri(DisasContext *s,
         return;
     }
 
+    if (!fp_access_check(s)) {
+        return;
+    }
+
     switch (opcode) {
     case 0x02: /* SSRA / USRA (accumulate) */
         accumulate = true;
@@ -5950,6 +6100,10 @@ static void handle_scalar_simd_shli(DisasContext *s, bool insert,
         return;
     }
 
+    if (!fp_access_check(s)) {
+        return;
+    }
+
     tcg_rn = read_fp_dreg(s, rn);
     tcg_rd = insert ? read_fp_dreg(s, rd) : tcg_temp_new_i64();
 
@@ -6005,6 +6159,10 @@ static void handle_vec_simd_sqshrn(DisasContext *s, bool is_scalar, bool is_q,
         return;
     }
 
+    if (!fp_access_check(s)) {
+        return;
+    }
+
     if (is_u_shift) {
         narrowfn = unsigned_narrow_fns[size];
     } else {
@@ -6087,6 +6245,10 @@ static void handle_simd_qshl(DisasContext *s, bool scalar, bool is_q,
         }
     }
 
+    if (!fp_access_check(s)) {
+        return;
+    }
+
     if (size == 3) {
         TCGv_i64 tcg_shift = tcg_const_i64(shift);
         static NeonGenTwo64OpEnvFn * const fns[2][2] = {
@@ -6247,6 +6409,11 @@ static void handle_simd_shift_intfp_conv(DisasContext *s, bool is_scalar,
             return;
         }
     }
+
+    if (!fp_access_check(s)) {
+        return;
+    }
+
     /* immh == 0 would be a failure of the decode logic */
     g_assert(immh);
 
@@ -6275,6 +6442,10 @@ static void handle_simd_shift_fpint_conv(DisasContext *s, bool is_scalar,
         return;
     }
 
+    if (!fp_access_check(s)) {
+        return;
+    }
+
     assert(!(is_scalar && is_q));
 
     tcg_rmode = tcg_const_i32(arm_rmode_to_sf(FPROUNDING_ZERO));
@@ -6438,6 +6609,10 @@ static void disas_simd_scalar_three_reg_diff(DisasContext *s, uint32_t insn)
         return;
     }
 
+    if (!fp_access_check(s)) {
+        return;
+    }
+
     if (size == 2) {
         TCGv_i64 tcg_op1 = tcg_temp_new_i64();
         TCGv_i64 tcg_op2 = tcg_temp_new_i64();
@@ -6822,6 +6997,10 @@ static void disas_simd_scalar_three_reg_same(DisasContext *s, uint32_t insn)
             return;
         }
 
+        if (!fp_access_check(s)) {
+            return;
+        }
+
         handle_3same_float(s, extract32(size, 0, 1), 1, fpopcode, rd, rn, rm);
         return;
     }
@@ -6854,6 +7033,10 @@ static void disas_simd_scalar_three_reg_same(DisasContext *s, uint32_t insn)
         return;
     }
 
+    if (!fp_access_check(s)) {
+        return;
+    }
+
     tcg_rd = tcg_temp_new_i64();
 
     if (size == 3) {
@@ -7057,7 +7240,13 @@ static void handle_2misc_fcmp_zero(DisasContext *s, int opcode,
                                    int size, int rn, int rd)
 {
     bool is_double = (size == 3);
-    TCGv_ptr fpst = get_fpstatus_ptr();
+    TCGv_ptr fpst;
+
+    if (!fp_access_check(s)) {
+        return;
+    }
+
+    fpst = get_fpstatus_ptr();
 
     if (is_double) {
         TCGv_i64 tcg_op = tcg_temp_new_i64();
@@ -7464,6 +7653,9 @@ static void disas_simd_scalar_two_reg_misc(DisasContext *s, uint32_t insn)
 
     switch (opcode) {
     case 0x3: /* USQADD / SUQADD*/
+        if (!fp_access_check(s)) {
+            return;
+        }
         handle_2misc_satacc(s, true, u, false, size, rn, rd);
         return;
     case 0x7: /* SQABS / SQNEG */
@@ -7493,6 +7685,9 @@ static void disas_simd_scalar_two_reg_misc(DisasContext *s, uint32_t insn)
             unallocated_encoding(s);
             return;
         }
+        if (!fp_access_check(s)) {
+            return;
+        }
         handle_2misc_narrow(s, true, opcode, u, false, size, rn, rd);
         return;
     case 0xc ... 0xf:
@@ -7515,12 +7710,18 @@ static void disas_simd_scalar_two_reg_misc(DisasContext *s, uint32_t insn)
         case 0x5d: /* UCVTF */
         {
             bool is_signed = (opcode == 0x1d);
+            if (!fp_access_check(s)) {
+                return;
+            }
             handle_simd_intfp_conv(s, rd, rn, 1, is_signed, 0, size);
             return;
         }
         case 0x3d: /* FRECPE */
         case 0x3f: /* FRECPX */
         case 0x7d: /* FRSQRTE */
+            if (!fp_access_check(s)) {
+                return;
+            }
             handle_2misc_reciprocal(s, opcode, true, u, true, size, rn, rd);
             return;
         case 0x1a: /* FCVTNS */
@@ -7545,6 +7746,9 @@ static void disas_simd_scalar_two_reg_misc(DisasContext *s, uint32_t insn)
                 unallocated_encoding(s);
                 return;
             }
+            if (!fp_access_check(s)) {
+                return;
+            }
             handle_2misc_narrow(s, true, opcode, u, false, size - 1, rn, rd);
             return;
         default:
@@ -7557,6 +7761,10 @@ static void disas_simd_scalar_two_reg_misc(DisasContext *s, uint32_t insn)
         return;
     }
 
+    if (!fp_access_check(s)) {
+        return;
+    }
+
     if (is_fcvt) {
         tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
         gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
@@ -7660,6 +7868,10 @@ static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u,
         return;
     }
 
+    if (!fp_access_check(s)) {
+        return;
+    }
+
     switch (opcode) {
     case 0x02: /* SSRA / USRA (accumulate) */
         accumulate = true;
@@ -7731,6 +7943,10 @@ static void handle_vec_simd_shli(DisasContext *s, bool is_q, bool insert,
         return;
     }
 
+    if (!fp_access_check(s)) {
+        return;
+    }
+
     for (i = 0; i < elements; i++) {
         read_vec_element(s, tcg_rn, rn, i, size);
         if (insert) {
@@ -7766,6 +7982,10 @@ static void handle_vec_simd_wshli(DisasContext *s, bool is_q, bool is_u,
         return;
     }
 
+    if (!fp_access_check(s)) {
+        return;
+    }
+
     /* For the LL variants the store is larger than the load,
      * so if rd == rn we would overwrite parts of our input.
      * So load everything right now and use shifts in the main loop.
@@ -7800,6 +8020,10 @@ static void handle_vec_simd_shrn(DisasContext *s, bool is_q,
         return;
     }
 
+    if (!fp_access_check(s)) {
+        return;
+    }
+
     tcg_rn = tcg_temp_new_i64();
     tcg_rd = tcg_temp_new_i64();
     tcg_final = tcg_temp_new_i64();
@@ -8296,6 +8520,9 @@ static void disas_simd_three_reg_diff(DisasContext *s, uint32_t insn)
             unallocated_encoding(s);
             return;
         }
+        if (!fp_access_check(s)) {
+            return;
+        }
         handle_3rd_wide(s, is_q, is_u, size, opcode, rd, rn, rm);
         break;
     case 4: /* ADDHN, ADDHN2, RADDHN, RADDHN2 */
@@ -8305,6 +8532,9 @@ static void disas_simd_three_reg_diff(DisasContext *s, uint32_t insn)
             unallocated_encoding(s);
             return;
         }
+        if (!fp_access_check(s)) {
+            return;
+        }
         handle_3rd_narrowing(s, is_q, is_u, size, opcode, rd, rn, rm);
         break;
     case 14: /* PMULL, PMULL2 */
@@ -8317,6 +8547,9 @@ static void disas_simd_three_reg_diff(DisasContext *s, uint32_t insn)
                 unallocated_encoding(s);
                 return;
             }
+            if (!fp_access_check(s)) {
+                return;
+            }
             handle_pmull_64(s, is_q, rd, rn, rm);
             return;
         }
@@ -8342,6 +8575,10 @@ static void disas_simd_three_reg_diff(DisasContext *s, uint32_t insn)
             return;
         }
     is_widening:
+        if (!fp_access_check(s)) {
+            return;
+        }
+
         handle_3rd_widening(s, is_q, is_u, size, opcode, rd, rn, rm);
         break;
     default:
@@ -8360,11 +8597,15 @@ static void disas_simd_3same_logic(DisasContext *s, uint32_t insn)
     int size = extract32(insn, 22, 2);
     bool is_u = extract32(insn, 29, 1);
     bool is_q = extract32(insn, 30, 1);
-    TCGv_i64 tcg_op1 = tcg_temp_new_i64();
-    TCGv_i64 tcg_op2 = tcg_temp_new_i64();
-    TCGv_i64 tcg_res[2];
+    TCGv_i64 tcg_op1, tcg_op2, tcg_res[2];
     int pass;
 
+    if (!fp_access_check(s)) {
+        return;
+    }
+
+    tcg_op1 = tcg_temp_new_i64();
+    tcg_op2 = tcg_temp_new_i64();
     tcg_res[0] = tcg_temp_new_i64();
     tcg_res[1] = tcg_temp_new_i64();
 
@@ -8467,6 +8708,10 @@ static void handle_simd_3same_pair(DisasContext *s, int is_q, int u, int opcode,
         TCGV_UNUSED_PTR(fpst);
     }
 
+    if (!fp_access_check(s)) {
+        return;
+    }
+
     /* These operations work on the concatenated rm:rn, with each pair of
      * adjacent elements being operated on to produce an element in the result.
      */
@@ -8659,6 +8904,10 @@ static void disas_simd_3same_float(DisasContext *s, uint32_t insn)
     case 0x5f: /* FDIV */
     case 0x7a: /* FABD */
     case 0x7c: /* FCMGT */
+        if (!fp_access_check(s)) {
+            return;
+        }
+
         handle_3same_float(s, size, elements, fpopcode, rd, rn, rm);
         return;
     default:
@@ -8713,6 +8962,10 @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
         break;
     }
 
+    if (!fp_access_check(s)) {
+        return;
+    }
+
     if (size == 3) {
         for (pass = 0; pass < (is_q ? 2 : 1); pass++) {
             TCGv_i64 tcg_op1 = tcg_temp_new_i64();
@@ -9077,6 +9330,10 @@ static void handle_rev(DisasContext *s, int opcode, bool u,
         return;
     }
 
+    if (!fp_access_check(s)) {
+        return;
+    }
+
     if (size == 0) {
         /* Special case bytes, use bswap op on each group of elements */
         int groups = dsize / (8 << grp_size);
@@ -9279,6 +9536,10 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
             unallocated_encoding(s);
             return;
         }
+        if (!fp_access_check(s)) {
+            return;
+        }
+
         handle_2misc_narrow(s, false, opcode, u, is_q, size, rn, rd);
         return;
     case 0x4: /* CLS, CLZ */
@@ -9293,6 +9554,9 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
             unallocated_encoding(s);
             return;
         }
+        if (!fp_access_check(s)) {
+            return;
+        }
         handle_2misc_pairwise(s, opcode, u, is_q, size, rn, rd);
         return;
     case 0x13: /* SHLL, SHLL2 */
@@ -9300,6 +9564,9 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
             unallocated_encoding(s);
             return;
         }
+        if (!fp_access_check(s)) {
+            return;
+        }
         handle_shll(s, is_q, size, rn, rd);
         return;
     case 0xa: /* CMLT */
@@ -9321,6 +9588,9 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
             unallocated_encoding(s);
             return;
         }
+        if (!fp_access_check(s)) {
+            return;
+        }
         handle_2misc_satacc(s, false, u, is_q, size, rn, rd);
         return;
     case 0x7: /* SQABS, SQNEG */
@@ -9356,6 +9626,9 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
                 unallocated_encoding(s);
                 return;
             }
+            if (!fp_access_check(s)) {
+                return;
+            }
             handle_simd_intfp_conv(s, rd, rn, elements, is_signed, 0, size);
             return;
         }
@@ -9414,6 +9687,9 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
                 unallocated_encoding(s);
                 return;
             }
+            if (!fp_access_check(s)) {
+                return;
+            }
             handle_2misc_reciprocal(s, opcode, false, u, is_q, size, rn, rd);
             return;
         case 0x56: /* FCVTXN, FCVTXN2 */
@@ -9426,9 +9702,15 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
             /* handle_2misc_narrow does a 2*size -> size operation, but these
              * instructions encode the source size rather than dest size.
              */
+            if (!fp_access_check(s)) {
+                return;
+            }
             handle_2misc_narrow(s, false, opcode, 0, is_q, size - 1, rn, rd);
             return;
         case 0x17: /* FCVTL, FCVTL2 */
+            if (!fp_access_check(s)) {
+                return;
+            }
             handle_2misc_widening(s, opcode, is_q, size, rn, rd);
             return;
         case 0x18: /* FRINTN */
@@ -9473,6 +9755,10 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
         return;
     }
 
+    if (!fp_access_check(s)) {
+        return;
+    }
+
     if (need_fpstatus) {
         tcg_fpstatus = get_fpstatus_ptr();
     } else {
@@ -9836,6 +10122,10 @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
         }
     }
 
+    if (!fp_access_check(s)) {
+        return;
+    }
+
     if (is_fp) {
         fpst = get_fpstatus_ptr();
     } else {
@@ -10334,7 +10624,7 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
 #if !defined(CONFIG_USER_ONLY)
     dc->user = (ARM_TBFLAG_AA64_EL(tb->flags) == 0);
 #endif
-    dc->vfp_enabled = 0;
+    dc->cpacr_fpen = ARM_TBFLAG_AA64_FPEN(tb->flags);
     dc->vec_len = 0;
     dc->vec_stride = 0;
     dc->cp_regs = cpu->cp_regs;
diff --git a/target-arm/translate.h b/target-arm/translate.h
index 5c18dc9..4536f82 100644
--- a/target-arm/translate.h
+++ b/target-arm/translate.h
@@ -20,7 +20,8 @@ typedef struct DisasContext {
 #if !defined(CONFIG_USER_ONLY)
     int user;
 #endif
-    int vfp_enabled;
+    bool cpacr_fpen; /* FP enabled via CPACR.FPEN */
+    bool vfp_enabled; /* FP enabled via FPSCR.EN */
     int vec_len;
     int vec_stride;
     /* Immediate value in AArch32 SVC insn; must be set if is_jmp == DISAS_SWI
-- 
1.9.1

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

* [Qemu-devel] [PATCH v6 08/37] target-arm: A64: Add assertion that FP access was checked
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
                   ` (6 preceding siblings ...)
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 07/37] target-arm: A64: Correctly fault FP/Neon if CPACR.FPEN set Peter Maydell
@ 2014-04-10 16:15 ` Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 09/37] target-arm: Fix VFP enables for AArch32 EL0 under AArch64 EL1 Peter Maydell
                   ` (29 subsequent siblings)
  37 siblings, 0 replies; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

Because unallocated encodings generate different exception syndrome
information from traps due to FP being disabled, we can't do a single
"is fp access disabled" check at a high level in the decode tree.
To help in catching bugs where the access check was forgotten in some
code path, we set this flag when the access check is done, and assert
that it is set at the point where we actually touch the FP regs.

This requires us to pass the DisasContext to the vec_reg_offset
and fp_reg_offset functions.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
 target-arm/translate-a64.c | 75 +++++++++++++++++++++++++++++++---------------
 target-arm/translate.h     |  8 +++++
 2 files changed, 59 insertions(+), 24 deletions(-)

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 2f67af3..0ec2f65 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -353,11 +353,30 @@ static TCGv_i64 read_cpu_reg_sp(DisasContext *s, int reg, int sf)
     return v;
 }
 
+/* We should have at some point before trying to access an FP register
+ * done the necessary access check, so assert that
+ * (a) we did the check and
+ * (b) we didn't then just plough ahead anyway if it failed.
+ * Print the instruction pattern in the abort message so we can figure
+ * out what we need to fix if a user encounters this problem in the wild.
+ */
+static inline void assert_fp_access_checked(DisasContext *s)
+{
+#ifdef CONFIG_DEBUG_TCG
+    if (unlikely(!s->fp_access_checked || !s->cpacr_fpen)) {
+        fprintf(stderr, "target-arm: FP access check missing for "
+                "instruction 0x%08x\n", s->insn);
+        abort();
+    }
+#endif
+}
+
 /* Return the offset into CPUARMState of an element of specified
  * size, 'element' places in from the least significant end of
  * the FP/vector register Qn.
  */
-static inline int vec_reg_offset(int regno, int element, TCGMemOp size)
+static inline int vec_reg_offset(DisasContext *s, int regno,
+                                 int element, TCGMemOp size)
 {
     int offs = offsetof(CPUARMState, vfp.regs[regno * 2]);
 #ifdef HOST_WORDS_BIGENDIAN
@@ -372,6 +391,7 @@ static inline int vec_reg_offset(int regno, int element, TCGMemOp size)
 #else
     offs += element * (1 << size);
 #endif
+    assert_fp_access_checked(s);
     return offs;
 }
 
@@ -380,18 +400,20 @@ static inline int vec_reg_offset(int regno, int element, TCGMemOp size)
  * Dn, Sn, Hn or Bn).
  * (Note that this is not the same mapping as for A32; see cpu.h)
  */
-static inline int fp_reg_offset(int regno, TCGMemOp size)
+static inline int fp_reg_offset(DisasContext *s, int regno, TCGMemOp size)
 {
     int offs = offsetof(CPUARMState, vfp.regs[regno * 2]);
 #ifdef HOST_WORDS_BIGENDIAN
     offs += (8 - (1 << size));
 #endif
+    assert_fp_access_checked(s);
     return offs;
 }
 
 /* Offset of the high half of the 128 bit vector Qn */
-static inline int fp_reg_hi_offset(int regno)
+static inline int fp_reg_hi_offset(DisasContext *s, int regno)
 {
+    assert_fp_access_checked(s);
     return offsetof(CPUARMState, vfp.regs[regno * 2 + 1]);
 }
 
@@ -405,7 +427,7 @@ static TCGv_i64 read_fp_dreg(DisasContext *s, int reg)
 {
     TCGv_i64 v = tcg_temp_new_i64();
 
-    tcg_gen_ld_i64(v, cpu_env, fp_reg_offset(reg, MO_64));
+    tcg_gen_ld_i64(v, cpu_env, fp_reg_offset(s, reg, MO_64));
     return v;
 }
 
@@ -413,7 +435,7 @@ static TCGv_i32 read_fp_sreg(DisasContext *s, int reg)
 {
     TCGv_i32 v = tcg_temp_new_i32();
 
-    tcg_gen_ld_i32(v, cpu_env, fp_reg_offset(reg, MO_32));
+    tcg_gen_ld_i32(v, cpu_env, fp_reg_offset(s, reg, MO_32));
     return v;
 }
 
@@ -421,8 +443,8 @@ static void write_fp_dreg(DisasContext *s, int reg, TCGv_i64 v)
 {
     TCGv_i64 tcg_zero = tcg_const_i64(0);
 
-    tcg_gen_st_i64(v, cpu_env, fp_reg_offset(reg, MO_64));
-    tcg_gen_st_i64(tcg_zero, cpu_env, fp_reg_hi_offset(reg));
+    tcg_gen_st_i64(v, cpu_env, fp_reg_offset(s, reg, MO_64));
+    tcg_gen_st_i64(tcg_zero, cpu_env, fp_reg_hi_offset(s, reg));
     tcg_temp_free_i64(tcg_zero);
 }
 
@@ -693,14 +715,14 @@ static void do_fp_st(DisasContext *s, int srcidx, TCGv_i64 tcg_addr, int size)
 {
     /* This writes the bottom N bits of a 128 bit wide vector to memory */
     TCGv_i64 tmp = tcg_temp_new_i64();
-    tcg_gen_ld_i64(tmp, cpu_env, fp_reg_offset(srcidx, MO_64));
+    tcg_gen_ld_i64(tmp, cpu_env, fp_reg_offset(s, srcidx, MO_64));
     if (size < 4) {
         tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s), MO_TE + size);
     } else {
         TCGv_i64 tcg_hiaddr = tcg_temp_new_i64();
         tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s), MO_TEQ);
         tcg_gen_qemu_st64(tmp, tcg_addr, get_mem_index(s));
-        tcg_gen_ld_i64(tmp, cpu_env, fp_reg_hi_offset(srcidx));
+        tcg_gen_ld_i64(tmp, cpu_env, fp_reg_hi_offset(s, srcidx));
         tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
         tcg_gen_qemu_st_i64(tmp, tcg_hiaddr, get_mem_index(s), MO_TEQ);
         tcg_temp_free_i64(tcg_hiaddr);
@@ -733,8 +755,8 @@ static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, int size)
         tcg_temp_free_i64(tcg_hiaddr);
     }
 
-    tcg_gen_st_i64(tmplo, cpu_env, fp_reg_offset(destidx, MO_64));
-    tcg_gen_st_i64(tmphi, cpu_env, fp_reg_hi_offset(destidx));
+    tcg_gen_st_i64(tmplo, cpu_env, fp_reg_offset(s, destidx, MO_64));
+    tcg_gen_st_i64(tmphi, cpu_env, fp_reg_hi_offset(s, destidx));
 
     tcg_temp_free_i64(tmplo);
     tcg_temp_free_i64(tmphi);
@@ -756,7 +778,7 @@ static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, int size)
 static void read_vec_element(DisasContext *s, TCGv_i64 tcg_dest, int srcidx,
                              int element, TCGMemOp memop)
 {
-    int vect_off = vec_reg_offset(srcidx, element, memop & MO_SIZE);
+    int vect_off = vec_reg_offset(s, srcidx, element, memop & MO_SIZE);
     switch (memop) {
     case MO_8:
         tcg_gen_ld8u_i64(tcg_dest, cpu_env, vect_off);
@@ -788,7 +810,7 @@ static void read_vec_element(DisasContext *s, TCGv_i64 tcg_dest, int srcidx,
 static void read_vec_element_i32(DisasContext *s, TCGv_i32 tcg_dest, int srcidx,
                                  int element, TCGMemOp memop)
 {
-    int vect_off = vec_reg_offset(srcidx, element, memop & MO_SIZE);
+    int vect_off = vec_reg_offset(s, srcidx, element, memop & MO_SIZE);
     switch (memop) {
     case MO_8:
         tcg_gen_ld8u_i32(tcg_dest, cpu_env, vect_off);
@@ -815,7 +837,7 @@ static void read_vec_element_i32(DisasContext *s, TCGv_i32 tcg_dest, int srcidx,
 static void write_vec_element(DisasContext *s, TCGv_i64 tcg_src, int destidx,
                               int element, TCGMemOp memop)
 {
-    int vect_off = vec_reg_offset(destidx, element, memop & MO_SIZE);
+    int vect_off = vec_reg_offset(s, destidx, element, memop & MO_SIZE);
     switch (memop) {
     case MO_8:
         tcg_gen_st8_i64(tcg_src, cpu_env, vect_off);
@@ -837,7 +859,7 @@ static void write_vec_element(DisasContext *s, TCGv_i64 tcg_src, int destidx,
 static void write_vec_element_i32(DisasContext *s, TCGv_i32 tcg_src,
                                   int destidx, int element, TCGMemOp memop)
 {
-    int vect_off = vec_reg_offset(destidx, element, memop & MO_SIZE);
+    int vect_off = vec_reg_offset(s, destidx, element, memop & MO_SIZE);
     switch (memop) {
     case MO_8:
         tcg_gen_st8_i32(tcg_src, cpu_env, vect_off);
@@ -899,6 +921,9 @@ static void do_vec_ld(DisasContext *s, int destidx, int element,
  */
 static inline bool fp_access_check(DisasContext *s)
 {
+    assert(!s->fp_access_checked);
+    s->fp_access_checked = true;
+
     if (s->cpacr_fpen) {
         return true;
     }
@@ -4748,9 +4773,9 @@ static void handle_fmov(DisasContext *s, int rd, int rn, int type, bool itof)
             /* 32 bit */
             TCGv_i64 tmp = tcg_temp_new_i64();
             tcg_gen_ext32u_i64(tmp, tcg_rn);
-            tcg_gen_st_i64(tmp, cpu_env, fp_reg_offset(rd, MO_64));
+            tcg_gen_st_i64(tmp, cpu_env, fp_reg_offset(s, rd, MO_64));
             tcg_gen_movi_i64(tmp, 0);
-            tcg_gen_st_i64(tmp, cpu_env, fp_reg_hi_offset(rd));
+            tcg_gen_st_i64(tmp, cpu_env, fp_reg_hi_offset(s, rd));
             tcg_temp_free_i64(tmp);
             break;
         }
@@ -4758,14 +4783,14 @@ static void handle_fmov(DisasContext *s, int rd, int rn, int type, bool itof)
         {
             /* 64 bit */
             TCGv_i64 tmp = tcg_const_i64(0);
-            tcg_gen_st_i64(tcg_rn, cpu_env, fp_reg_offset(rd, MO_64));
-            tcg_gen_st_i64(tmp, cpu_env, fp_reg_hi_offset(rd));
+            tcg_gen_st_i64(tcg_rn, cpu_env, fp_reg_offset(s, rd, MO_64));
+            tcg_gen_st_i64(tmp, cpu_env, fp_reg_hi_offset(s, rd));
             tcg_temp_free_i64(tmp);
             break;
         }
         case 2:
             /* 64 bit to top half. */
-            tcg_gen_st_i64(tcg_rn, cpu_env, fp_reg_hi_offset(rd));
+            tcg_gen_st_i64(tcg_rn, cpu_env, fp_reg_hi_offset(s, rd));
             break;
         }
     } else {
@@ -4774,15 +4799,15 @@ static void handle_fmov(DisasContext *s, int rd, int rn, int type, bool itof)
         switch (type) {
         case 0:
             /* 32 bit */
-            tcg_gen_ld32u_i64(tcg_rd, cpu_env, fp_reg_offset(rn, MO_32));
+            tcg_gen_ld32u_i64(tcg_rd, cpu_env, fp_reg_offset(s, rn, MO_32));
             break;
         case 1:
             /* 64 bit */
-            tcg_gen_ld_i64(tcg_rd, cpu_env, fp_reg_offset(rn, MO_64));
+            tcg_gen_ld_i64(tcg_rd, cpu_env, fp_reg_offset(s, rn, MO_64));
             break;
         case 2:
             /* 64 bits from top half */
-            tcg_gen_ld_i64(tcg_rd, cpu_env, fp_reg_hi_offset(rn));
+            tcg_gen_ld_i64(tcg_rd, cpu_env, fp_reg_hi_offset(s, rn));
             break;
         }
     }
@@ -5727,7 +5752,7 @@ static void disas_simd_mod_imm(DisasContext *s, uint32_t insn)
     tcg_rd = new_tmp_a64(s);
 
     for (i = 0; i < 2; i++) {
-        int foffs = i ? fp_reg_hi_offset(rd) : fp_reg_offset(rd, MO_64);
+        int foffs = i ? fp_reg_hi_offset(s, rd) : fp_reg_offset(s, rd, MO_64);
 
         if (i == 1 && !is_q) {
             /* non-quad ops clear high half of vector */
@@ -10557,6 +10582,8 @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s)
     s->insn = insn;
     s->pc += 4;
 
+    s->fp_access_checked = false;
+
     switch (extract32(insn, 25, 4)) {
     case 0x0: case 0x1: case 0x2: case 0x3: /* UNALLOCATED */
         unallocated_encoding(s);
diff --git a/target-arm/translate.h b/target-arm/translate.h
index 4536f82..3f7d5ca 100644
--- a/target-arm/translate.h
+++ b/target-arm/translate.h
@@ -32,6 +32,14 @@ typedef struct DisasContext {
     int current_pl;
     GHashTable *cp_regs;
     uint64_t features; /* CPU features bits */
+    /* Because unallocated encodings generate different exception syndrome
+     * information from traps due to FP being disabled, we can't do a single
+     * "is fp access disabled" check at a high level in the decode tree.
+     * To help in catching bugs where the access check was forgotten in some
+     * code path, we set this flag when the access check is done, and assert
+     * that it is set at the point where we actually touch the FP regs.
+     */
+    bool fp_access_checked;
 #define TMP_A64_MAX 16
     int tmp_a64_count;
     TCGv_i64 tmp_a64[TMP_A64_MAX];
-- 
1.9.1

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

* [Qemu-devel] [PATCH v6 09/37] target-arm: Fix VFP enables for AArch32 EL0 under AArch64 EL1
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
                   ` (7 preceding siblings ...)
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 08/37] target-arm: A64: Add assertion that FP access was checked Peter Maydell
@ 2014-04-10 16:15 ` Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 10/37] target-arm: Add v8 mmu translation support Peter Maydell
                   ` (28 subsequent siblings)
  37 siblings, 0 replies; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

The current A32/T32 decoder bases its "is VFP/Neon enabled?" check
on the FPSCR.EN bit. This is correct if EL1 is AArch32, but for
an AArch64 EL1 the logic is different: it must act as if FPSCR.EN
is always set. Instead, trapping must happen according to CPACR
bits for cp10/cp11; these cover all of FP/Neon, including the
FPSCR/FPSID/MVFR register accesses which FPSCR.EN does not affect.
Add support for CPACR checks (which are also required for ARMv7,
but were unimplemented because Linux happens not to use them)
and make sure they generate exceptions with the correct syndrome.

We actually return incorrect syndrome information for cases
where FP is disabled but the specific instruction bit pattern
is unallocated: strictly these should be the Uncategorized
exception, not a "SIMD disabled" exception. This should be
mostly harmless, and the structure of the A32/T32 VFP/Neon
decoder makes it painful to put the 'FP disabled?' checks in
the right places.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
 target-arm/cpu.h       | 10 +++++++++-
 target-arm/translate.c | 31 +++++++++++++++++++++++++++++++
 2 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 72c4c7a..ff56519 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1104,6 +1104,8 @@ static inline int cpu_mmu_index (CPUARMState *env)
 #define ARM_TBFLAG_CONDEXEC_MASK    (0xff << ARM_TBFLAG_CONDEXEC_SHIFT)
 #define ARM_TBFLAG_BSWAP_CODE_SHIFT 16
 #define ARM_TBFLAG_BSWAP_CODE_MASK  (1 << ARM_TBFLAG_BSWAP_CODE_SHIFT)
+#define ARM_TBFLAG_CPACR_FPEN_SHIFT 17
+#define ARM_TBFLAG_CPACR_FPEN_MASK  (1 << ARM_TBFLAG_CPACR_FPEN_SHIFT)
 
 /* Bit usage when in AArch64 state */
 #define ARM_TBFLAG_AA64_EL_SHIFT    0
@@ -1128,6 +1130,8 @@ static inline int cpu_mmu_index (CPUARMState *env)
     (((F) & ARM_TBFLAG_CONDEXEC_MASK) >> ARM_TBFLAG_CONDEXEC_SHIFT)
 #define ARM_TBFLAG_BSWAP_CODE(F) \
     (((F) & ARM_TBFLAG_BSWAP_CODE_MASK) >> ARM_TBFLAG_BSWAP_CODE_SHIFT)
+#define ARM_TBFLAG_CPACR_FPEN(F) \
+    (((F) & ARM_TBFLAG_CPACR_FPEN_MASK) >> ARM_TBFLAG_CPACR_FPEN_SHIFT)
 #define ARM_TBFLAG_AA64_EL(F) \
     (((F) & ARM_TBFLAG_AA64_EL_MASK) >> ARM_TBFLAG_AA64_EL_SHIFT)
 #define ARM_TBFLAG_AA64_FPEN(F) \
@@ -1161,9 +1165,13 @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
         if (privmode) {
             *flags |= ARM_TBFLAG_PRIV_MASK;
         }
-        if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) {
+        if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)
+            || arm_el_is_aa64(env, 1)) {
             *flags |= ARM_TBFLAG_VFPEN_MASK;
         }
+        if (fpen == 3 || (fpen == 1 && arm_current_pl(env) != 0)) {
+            *flags |= ARM_TBFLAG_CPACR_FPEN_MASK;
+        }
     }
 
     *cs_base = 0;
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 84700ca..03e2c00 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -2952,6 +2952,16 @@ static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
     if (!arm_feature(env, ARM_FEATURE_VFP))
         return 1;
 
+    /* FIXME: this access check should not take precedence over UNDEF
+     * for invalid encodings; we will generate incorrect syndrome information
+     * for attempts to execute invalid vfp/neon encodings with FP disabled.
+     */
+    if (!s->cpacr_fpen) {
+        gen_exception_insn(s, 4, EXCP_UDEF,
+                           syn_fp_access_trap(1, 0xe, s->thumb));
+        return 0;
+    }
+
     if (!s->vfp_enabled) {
         /* VFP disabled.  Only allow fmxr/fmrx to/from some control regs.  */
         if ((insn & 0x0fe00fff) != 0x0ee00a10)
@@ -4232,6 +4242,16 @@ static int disas_neon_ls_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
     TCGv_i32 tmp2;
     TCGv_i64 tmp64;
 
+    /* FIXME: this access check should not take precedence over UNDEF
+     * for invalid encodings; we will generate incorrect syndrome information
+     * for attempts to execute invalid vfp/neon encodings with FP disabled.
+     */
+    if (!s->cpacr_fpen) {
+        gen_exception_insn(s, 4, EXCP_UDEF,
+                           syn_fp_access_trap(1, 0xe, s->thumb));
+        return 0;
+    }
+
     if (!s->vfp_enabled)
       return 1;
     VFP_DREG_D(rd, insn);
@@ -4954,6 +4974,16 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins
     TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5;
     TCGv_i64 tmp64;
 
+    /* FIXME: this access check should not take precedence over UNDEF
+     * for invalid encodings; we will generate incorrect syndrome information
+     * for attempts to execute invalid vfp/neon encodings with FP disabled.
+     */
+    if (!s->cpacr_fpen) {
+        gen_exception_insn(s, 4, EXCP_UDEF,
+                           syn_fp_access_trap(1, 0xe, s->thumb));
+        return 0;
+    }
+
     if (!s->vfp_enabled)
       return 1;
     q = (insn & (1 << 6)) != 0;
@@ -10736,6 +10766,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
 #if !defined(CONFIG_USER_ONLY)
     dc->user = (ARM_TBFLAG_PRIV(tb->flags) == 0);
 #endif
+    dc->cpacr_fpen = ARM_TBFLAG_CPACR_FPEN(tb->flags);
     dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
     dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags);
     dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
-- 
1.9.1

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

* [Qemu-devel] [PATCH v6 10/37] target-arm: Add v8 mmu translation support
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
                   ` (8 preceding siblings ...)
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 09/37] target-arm: Fix VFP enables for AArch32 EL0 under AArch64 EL1 Peter Maydell
@ 2014-04-10 16:15 ` Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 11/37] target-arm: Don't mention PMU in debug feature register Peter Maydell
                   ` (27 subsequent siblings)
  37 siblings, 0 replies; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

From: Rob Herring <rob.herring@linaro.org>

Add support for v8 page table walks. This supports stage 1 translations
for 4KB, 16KB and 64KB page sizes starting with 0 or 1 level.

Signed-off-by: Rob Herring <rob.herring@linaro.org>
[PMM: fix style nits, fold in 16/64K page support patch, use
 arm_el_is_aa64() to decide whether to do 64 bit page table walk]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/helper.c | 109 +++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 77 insertions(+), 32 deletions(-)

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 9866e50..4b6c1b6 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -10,7 +10,7 @@
 #include <zlib.h> /* For crc32 */
 
 #ifndef CONFIG_USER_ONLY
-static inline int get_phys_addr(CPUARMState *env, uint32_t address,
+static inline int get_phys_addr(CPUARMState *env, target_ulong address,
                                 int access_type, int is_user,
                                 hwaddr *phys_ptr, int *prot,
                                 target_ulong *page_size);
@@ -1151,14 +1151,15 @@ static void par_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
 #ifndef CONFIG_USER_ONLY
 /* get_phys_addr() isn't present for user-mode-only targets */
 
-/* Return true if extended addresses are enabled, ie this is an
- * LPAE implementation and we are using the long-descriptor translation
- * table format because the TTBCR EAE bit is set.
+/* Return true if extended addresses are enabled.
+ * This is always the case if our translation regime is 64 bit,
+ * but depends on TTBCR.EAE for 32 bit.
  */
 static inline bool extended_addresses_enabled(CPUARMState *env)
 {
-    return arm_feature(env, ARM_FEATURE_LPAE)
-        && (env->cp15.c2_control & (1U << 31));
+    return arm_el_is_aa64(env, 1)
+        || ((arm_feature(env, ARM_FEATURE_LPAE)
+             && (env->cp15.c2_control & (1U << 31))));
 }
 
 static CPAccessResult ats_access(CPUARMState *env, const ARMCPRegInfo *ri)
@@ -3402,7 +3403,7 @@ typedef enum {
     permission_fault = 3,
 } MMUFaultType;
 
-static int get_phys_addr_lpae(CPUARMState *env, uint32_t address,
+static int get_phys_addr_lpae(CPUARMState *env, target_ulong address,
                               int access_type, int is_user,
                               hwaddr *phys_ptr, int *prot,
                               target_ulong *page_size_ptr)
@@ -3412,26 +3413,46 @@ static int get_phys_addr_lpae(CPUARMState *env, uint32_t address,
     MMUFaultType fault_type = translation_fault;
     uint32_t level = 1;
     uint32_t epd;
-    uint32_t tsz;
+    int32_t tsz;
+    uint32_t tg;
     uint64_t ttbr;
     int ttbr_select;
-    int n;
-    hwaddr descaddr;
+    hwaddr descaddr, descmask;
     uint32_t tableattrs;
     target_ulong page_size;
     uint32_t attrs;
+    int32_t granule_sz = 9;
+    int32_t va_size = 32;
+    int32_t tbi = 0;
+
+    if (arm_el_is_aa64(env, 1)) {
+        va_size = 64;
+        if (extract64(address, 55, 1))
+            tbi = extract64(env->cp15.c2_control, 38, 1);
+        else
+            tbi = extract64(env->cp15.c2_control, 37, 1);
+        tbi *= 8;
+    }
 
     /* Determine whether this address is in the region controlled by
      * TTBR0 or TTBR1 (or if it is in neither region and should fault).
      * This is a Non-secure PL0/1 stage 1 translation, so controlled by
      * TTBCR/TTBR0/TTBR1 in accordance with ARM ARM DDI0406C table B-32:
      */
-    uint32_t t0sz = extract32(env->cp15.c2_control, 0, 3);
-    uint32_t t1sz = extract32(env->cp15.c2_control, 16, 3);
-    if (t0sz && !extract32(address, 32 - t0sz, t0sz)) {
+    uint32_t t0sz = extract32(env->cp15.c2_control, 0, 6);
+    if (arm_el_is_aa64(env, 1)) {
+        t0sz = MIN(t0sz, 39);
+        t0sz = MAX(t0sz, 16);
+    }
+    uint32_t t1sz = extract32(env->cp15.c2_control, 16, 6);
+    if (arm_el_is_aa64(env, 1)) {
+        t1sz = MIN(t1sz, 39);
+        t1sz = MAX(t1sz, 16);
+    }
+    if (t0sz && !extract64(address, va_size - t0sz, t0sz - tbi)) {
         /* there is a ttbr0 region and we are in it (high bits all zero) */
         ttbr_select = 0;
-    } else if (t1sz && !extract32(~address, 32 - t1sz, t1sz)) {
+    } else if (t1sz && !extract64(~address, va_size - t1sz, t1sz - tbi)) {
         /* there is a ttbr1 region and we are in it (high bits all one) */
         ttbr_select = 1;
     } else if (!t0sz) {
@@ -3457,10 +3478,26 @@ static int get_phys_addr_lpae(CPUARMState *env, uint32_t address,
         ttbr = env->cp15.ttbr0_el1;
         epd = extract32(env->cp15.c2_control, 7, 1);
         tsz = t0sz;
+
+        tg = extract32(env->cp15.c2_control, 14, 2);
+        if (tg == 1) { /* 64KB pages */
+            granule_sz = 13;
+        }
+        if (tg == 2) { /* 16KB pages */
+            granule_sz = 11;
+        }
     } else {
         ttbr = env->cp15.ttbr1_el1;
         epd = extract32(env->cp15.c2_control, 23, 1);
         tsz = t1sz;
+
+        tg = extract32(env->cp15.c2_control, 30, 2);
+        if (tg == 3)  { /* 64KB pages */
+            granule_sz = 13;
+        }
+        if (tg == 1) { /* 16KB pages */
+            granule_sz = 11;
+        }
     }
 
     if (epd) {
@@ -3468,34 +3505,37 @@ static int get_phys_addr_lpae(CPUARMState *env, uint32_t address,
         goto do_fault;
     }
 
-    /* If the region is small enough we will skip straight to a 2nd level
-     * lookup. This affects the number of bits of the address used in
-     * combination with the TTBR to find the first descriptor. ('n' here
-     * matches the usage in the ARM ARM sB3.6.6, where bits [39..n] are
-     * from the TTBR, [n-1..3] from the vaddr, and [2..0] always zero).
+    /* The starting level depends on the virtual address size which can be
+     * up to 48-bits and the translation granule size.
      */
-    if (tsz > 1) {
-        level = 2;
-        n = 14 - tsz;
+    if ((va_size - tsz) > (granule_sz * 4 + 3)) {
+        level = 0;
+    } else if ((va_size - tsz) > (granule_sz * 3 + 3)) {
+        level = 1;
     } else {
-        n = 5 - tsz;
+        level = 2;
     }
 
     /* Clear the vaddr bits which aren't part of the within-region address,
      * so that we don't have to special case things when calculating the
      * first descriptor address.
      */
-    address &= (0xffffffffU >> tsz);
+    if (tsz) {
+        address &= (1ULL << (va_size - tsz)) - 1;
+    }
+
+    descmask = (1ULL << (granule_sz + 3)) - 1;
 
     /* Now we can extract the actual base address from the TTBR */
-    descaddr = extract64(ttbr, 0, 40);
-    descaddr &= ~((1ULL << n) - 1);
+    descaddr = extract64(ttbr, 0, 48);
+    descaddr &= ~((1ULL << (va_size - tsz - (granule_sz * (4 - level)))) - 1);
 
     tableattrs = 0;
     for (;;) {
         uint64_t descriptor;
 
-        descaddr |= ((address >> (9 * (4 - level))) & 0xff8);
+        descaddr |= (address >> (granule_sz * (4 - level))) & descmask;
+        descaddr &= ~7ULL;
         descriptor = ldq_phys(cs->as, descaddr);
         if (!(descriptor & 1) ||
             (!(descriptor & 2) && (level == 3))) {
@@ -3518,11 +3558,16 @@ static int get_phys_addr_lpae(CPUARMState *env, uint32_t address,
          * These are basically the same thing, although the number
          * of bits we pull in from the vaddr varies.
          */
-        page_size = (1 << (39 - (9 * level)));
+        page_size = (1 << ((granule_sz * (4 - level)) + 3));
         descaddr |= (address & (page_size - 1));
         /* Extract attributes from the descriptor and merge with table attrs */
-        attrs = extract64(descriptor, 2, 10)
-            | (extract64(descriptor, 52, 12) << 10);
+        if (arm_feature(env, ARM_FEATURE_V8)) {
+            attrs = extract64(descriptor, 2, 10)
+                | (extract64(descriptor, 53, 11) << 10);
+        } else {
+            attrs = extract64(descriptor, 2, 10)
+                | (extract64(descriptor, 52, 12) << 10);
+        }
         attrs |= extract32(tableattrs, 0, 2) << 11; /* XN, PXN */
         attrs |= extract32(tableattrs, 3, 1) << 5; /* APTable[1] => AP[2] */
         /* The sense of AP[1] vs APTable[0] is reversed, as APTable[0] == 1
@@ -3656,7 +3701,7 @@ static int get_phys_addr_mpu(CPUARMState *env, uint32_t address,
  * @prot: set to the permissions for the page containing phys_ptr
  * @page_size: set to the size of the page containing phys_ptr
  */
-static inline int get_phys_addr(CPUARMState *env, uint32_t address,
+static inline int get_phys_addr(CPUARMState *env, target_ulong address,
                                 int access_type, int is_user,
                                 hwaddr *phys_ptr, int *prot,
                                 target_ulong *page_size)
@@ -3705,7 +3750,7 @@ int arm_cpu_handle_mmu_fault(CPUState *cs, vaddr address,
     if (ret == 0) {
         /* Map a single [sub]page.  */
         phys_addr &= ~(hwaddr)0x3ff;
-        address &= ~(uint32_t)0x3ff;
+        address &= ~(target_ulong)0x3ff;
         tlb_set_page(cs, address, phys_addr, prot, mmu_idx, page_size);
         return 0;
     }
-- 
1.9.1

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

* [Qemu-devel] [PATCH v6 11/37] target-arm: Don't mention PMU in debug feature register
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
                   ` (9 preceding siblings ...)
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 10/37] target-arm: Add v8 mmu translation support Peter Maydell
@ 2014-04-10 16:15 ` Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 12/37] target-arm: A64: Implement DC ZVA Peter Maydell
                   ` (26 subsequent siblings)
  37 siblings, 0 replies; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

Suppress the ID_AA64DFR0_EL1 PMUVer field, even if the CPU specific
value claims that it exists. QEMU doesn't currently implement it,
and not advertising it prevents the guest from trying to use it
and getting UNDEFs on unimplemented registers.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
This is arguably a hack, but otherwise Linux tries to prod
half a dozen PMU sysregs.
---
 target-arm/helper.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 4b6c1b6..62f7fd3 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2036,7 +2036,12 @@ void register_cp_regs_for_features(ARMCPU *cpu)
             { .name = "ID_AA64DFR0_EL1", .state = ARM_CP_STATE_AA64,
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 0,
               .access = PL1_R, .type = ARM_CP_CONST,
-              .resetvalue = cpu->id_aa64dfr0 },
+              /* We mask out the PMUVer field, beacuse we don't currently
+               * implement the PMU. Not advertising it prevents the guest
+               * from trying to use it and getting UNDEFs on registers we
+               * don't implement.
+               */
+              .resetvalue = cpu->id_aa64dfr0 & ~0xf00 },
             { .name = "ID_AA64DFR1_EL1", .state = ARM_CP_STATE_AA64,
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 1,
               .access = PL1_R, .type = ARM_CP_CONST,
-- 
1.9.1

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

* [Qemu-devel] [PATCH v6 12/37] target-arm: A64: Implement DC ZVA
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
                   ` (10 preceding siblings ...)
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 11/37] target-arm: Don't mention PMU in debug feature register Peter Maydell
@ 2014-04-10 16:15 ` Peter Maydell
  2014-04-10 17:22   ` Richard Henderson
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 13/37] target-arm: Use dedicated CPU state fields for ARM946 access bit registers Peter Maydell
                   ` (25 subsequent siblings)
  37 siblings, 1 reply; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

Implement the DC ZVA instruction, which clears a block of memory.
The fast path obtains a pointer to the underlying RAM via the TCG TLB
data structure so we can do a direct memset(), with fallback to a
simple byte-store loop in the slow path.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 include/exec/softmmu_exec.h |  52 +++++++++++++++++++
 target-arm/cpu-qom.h        |   2 +
 target-arm/cpu.h            |   3 +-
 target-arm/cpu64.c          |   1 +
 target-arm/helper.c         | 122 ++++++++++++++++++++++++++++++++++++++++++--
 target-arm/helper.h         |   1 +
 target-arm/translate-a64.c  |   5 ++
 7 files changed, 180 insertions(+), 6 deletions(-)

diff --git a/include/exec/softmmu_exec.h b/include/exec/softmmu_exec.h
index 6fde154..470db20 100644
--- a/include/exec/softmmu_exec.h
+++ b/include/exec/softmmu_exec.h
@@ -162,3 +162,55 @@
 #define stw(p, v) stw_data(p, v)
 #define stl(p, v) stl_data(p, v)
 #define stq(p, v) stq_data(p, v)
+
+/**
+ * tlb_vaddr_to_host:
+ * @env: CPUArchState
+ * @addr: guest virtual address to look up
+ * @access_type: 0 for read, 1 for write, 2 for execute
+ * @mmu_idx: MMU index to use for lookup
+ *
+ * Look up the specified guest virtual index in the TCG softmmu TLB.
+ * If the TLB contains a host virtual address suitable for direct RAM
+ * access, then return it. Otherwise (TLB miss, TLB entry is for an
+ * I/O access, etc) return NULL.
+ *
+ * This is the equivalent of the initial fast-path code used by
+ * TCG backends for guest load and store accesses.
+ */
+static inline void *tlb_vaddr_to_host(CPUArchState *env, target_ulong addr,
+                                      int access_type, int mmu_idx)
+{
+    int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
+    CPUTLBEntry *tlbentry = &env->tlb_table[mmu_idx][index];
+    target_ulong tlb_addr;
+    uintptr_t haddr;
+
+    switch (access_type) {
+    case 0:
+        tlb_addr = tlbentry->addr_read;
+        break;
+    case 1:
+        tlb_addr = tlbentry->addr_write;
+        break;
+    case 2:
+        tlb_addr = tlbentry->addr_code;
+        break;
+    default:
+        g_assert_not_reached();
+    }
+
+    if ((addr & TARGET_PAGE_MASK)
+        != (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
+        /* TLB entry is for a different page */
+        return NULL;
+    }
+
+    if (tlb_addr & ~TARGET_PAGE_MASK) {
+        /* IO access */
+        return NULL;
+    }
+
+    haddr = addr + env->tlb_table[mmu_idx][index].addend;
+    return (void *)haddr;
+}
diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
index 00234e1..41caa6c 100644
--- a/target-arm/cpu-qom.h
+++ b/target-arm/cpu-qom.h
@@ -150,6 +150,8 @@ typedef struct ARMCPU {
     uint32_t reset_cbar;
     uint32_t reset_auxcr;
     bool reset_hivecs;
+    /* DCZ blocksize, in log_2(words), ie low 4 bits of DCZID_EL0 */
+    uint32_t dcz_blocksize;
 } ARMCPU;
 
 #define TYPE_AARCH64_CPU "aarch64-cpu"
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index ff56519..a00ff73 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -758,7 +758,8 @@ static inline uint64_t cpreg_to_kvm_id(uint32_t cpregid)
 #define ARM_CP_WFI (ARM_CP_SPECIAL | (2 << 8))
 #define ARM_CP_NZCV (ARM_CP_SPECIAL | (3 << 8))
 #define ARM_CP_CURRENTEL (ARM_CP_SPECIAL | (4 << 8))
-#define ARM_LAST_SPECIAL ARM_CP_CURRENTEL
+#define ARM_CP_DC_ZVA (ARM_CP_SPECIAL | (5 << 8))
+#define ARM_LAST_SPECIAL ARM_CP_DC_ZVA
 /* Used only as a terminator for ARMCPRegInfo lists */
 #define ARM_CP_SENTINEL 0xffff
 /* Mask of only the flag bits in a type field */
diff --git a/target-arm/cpu64.c b/target-arm/cpu64.c
index 8426bf1..fccecc2 100644
--- a/target-arm/cpu64.c
+++ b/target-arm/cpu64.c
@@ -46,6 +46,7 @@ static void aarch64_any_initfn(Object *obj)
     set_feature(&cpu->env, ARM_FEATURE_V7MP);
     set_feature(&cpu->env, ARM_FEATURE_AARCH64);
     cpu->ctr = 0x80030003; /* 32 byte I and D cacheline size, VIPT icache */
+    cpu->dcz_blocksize = 7; /*  512 bytes */
 }
 #endif
 
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 62f7fd3..2ffc588 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -10,6 +10,8 @@
 #include <zlib.h> /* For crc32 */
 
 #ifndef CONFIG_USER_ONLY
+#include "exec/softmmu_exec.h"
+
 static inline int get_phys_addr(CPUARMState *env, target_ulong address,
                                 int access_type, int is_user,
                                 hwaddr *phys_ptr, int *prot,
@@ -1745,6 +1747,29 @@ static void tlbi_aa64_asid_write(CPUARMState *env, const ARMCPRegInfo *ri,
     tlb_flush(CPU(cpu), asid == 0);
 }
 
+static CPAccessResult aa64_zva_access(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    /* We don't implement EL2, so the only control on DC ZVA is the
+     * bit in the SCTLR which can prohibit access for EL0.
+     */
+    if (arm_current_pl(env) == 0 && !(env->cp15.c1_sys & SCTLR_DZE)) {
+        return CP_ACCESS_TRAP;
+    }
+    return CP_ACCESS_OK;
+}
+
+static uint64_t aa64_dczid_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    ARMCPU *cpu = arm_env_get_cpu(env);
+    int dzp_bit = 1 << 4;
+
+    /* DZP indicates whether DC ZVA access is allowed */
+    if (aa64_zva_access(env, NULL) != CP_ACCESS_OK) {
+        dzp_bit = 0;
+    }
+    return cpu->dcz_blocksize | dzp_bit;
+}
+
 static const ARMCPRegInfo v8_cp_reginfo[] = {
     /* Minimal set of EL0-visible registers. This will need to be expanded
      * significantly for system emulation of AArch64 CPUs.
@@ -1764,13 +1789,18 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
     { .name = "FPSR", .state = ARM_CP_STATE_AA64,
       .opc0 = 3, .opc1 = 3, .opc2 = 1, .crn = 4, .crm = 4,
       .access = PL0_RW, .readfn = aa64_fpsr_read, .writefn = aa64_fpsr_write },
-    /* Prohibit use of DC ZVA. OPTME: implement DC ZVA and allow its use.
-     * For system mode the DZP bit here will need to be computed, not constant.
-     */
     { .name = "DCZID_EL0", .state = ARM_CP_STATE_AA64,
       .opc0 = 3, .opc1 = 3, .opc2 = 7, .crn = 0, .crm = 0,
-      .access = PL0_R, .type = ARM_CP_CONST,
-      .resetvalue = 0x10 },
+      .access = PL0_R, .type = ARM_CP_NO_MIGRATE,
+      .readfn = aa64_dczid_read },
+    { .name = "DC_ZVA", .state = ARM_CP_STATE_AA64,
+      .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 4, .opc2 = 1,
+      .access = PL0_W, .type = ARM_CP_DC_ZVA,
+#ifndef CONFIG_USER_ONLY
+      /* Avoid overhead of an access check that always passes in user-mode */
+      .accessfn = aa64_zva_access,
+#endif
+    },
     { .name = "CURRENTEL", .state = ARM_CP_STATE_AA64,
       .opc0 = 3, .opc1 = 0, .opc2 = 2, .crn = 4, .crm = 2,
       .access = PL1_R, .type = ARM_CP_CURRENTEL },
@@ -3930,6 +3960,88 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t reg, uint32_t val)
 
 #endif
 
+void HELPER(dc_zva)(CPUARMState *env, uint64_t vaddr_in)
+{
+    /* Implement DC ZVA, which zeroes a fixed-length block of memory.
+     * Note that we do not implement the (architecturally mandated)
+     * alignment fault for attempts to use this on Device memory
+     * (which matches the usual QEMU behaviour of not implementing either
+     * alignment faults or any memory attribute handling).
+     */
+
+    ARMCPU *cpu = arm_env_get_cpu(env);
+    uint64_t blocklen = 4 << cpu->dcz_blocksize;
+    uint64_t vaddr = vaddr_in & ~(blocklen - 1);
+
+#ifndef CONFIG_USER_ONLY
+    {
+        /* Slightly awkwardly, QEMU's TARGET_PAGE_SIZE may be less than
+         * the block size so we might have to do more than one TLB lookup.
+         * We know that in fact for any v8 CPU the page size is at least 4K
+         * and the block size must be 2K or less, but TARGET_PAGE_SIZE is only
+         * 1K as an artefact of legacy v5 subpage support being present in the
+         * same QEMU executable.
+         */
+        int maxidx = DIV_ROUND_UP(blocklen, TARGET_PAGE_SIZE);
+        void *hostaddr[maxidx];
+        int try, i;
+
+        for (try = 0; try < 2; try++) {
+
+            for (i = 0; i < maxidx; i++) {
+                hostaddr[i] = tlb_vaddr_to_host(env,
+                                                vaddr + TARGET_PAGE_SIZE * i,
+                                                1, cpu_mmu_index(env));
+                if (!hostaddr[i]) {
+                    break;
+                }
+            }
+            if (i == maxidx) {
+                /* If it's all in the TLB it's fair game for just writing to;
+                 * we know we don't need to update dirty status, etc.
+                 */
+                for (i = 0; i < maxidx - 1; i++) {
+                    memset(hostaddr[i], 0, TARGET_PAGE_SIZE);
+                }
+                memset(hostaddr[i], 0, blocklen - (i * TARGET_PAGE_SIZE));
+                return;
+            }
+            /* OK, try a store and see if we can populate the tlb. This
+             * might cause an exception if the memory isn't writable,
+             * in which case we will longjmp out of here. We must for
+             * this purpose use the actual register value passed to us
+             * so that we get the fault address right.
+             */
+            helper_ret_stb_mmu(env, vaddr_in, 0, cpu_mmu_index(env), GETRA());
+            /* Now we can populate the other TLB entries, if any */
+            for (i = 0; i < maxidx; i++) {
+                uint64_t va = vaddr + TARGET_PAGE_SIZE * i;
+                if (va != (vaddr_in & TARGET_PAGE_MASK)) {
+                    helper_ret_stb_mmu(env, va, 0, cpu_mmu_index(env), GETRA());
+                }
+            }
+        }
+
+        /* Slow path (probably attempt to do this to an I/O device or
+         * similar, or clearing of a block of code we have translations
+         * cached for). Just do a series of byte writes as the architecture
+         * demands. It's not worth trying to use a cpu_physical_memory_map(),
+         * memset(), unmap() sequence here because:
+         *  + we'd need to account for the blocksize being larger than a page
+         *  + the direct-RAM access case is almost always going to be dealt
+         *    with in the fastpath code above, so there's no speed benefit
+         *  + we would have to deal with the map returning NULL because the
+         *    bounce buffer was in use
+         */
+        for (i = 0; i < blocklen; i++) {
+            helper_ret_stb_mmu(env, vaddr + i, 0, cpu_mmu_index(env), GETRA());
+        }
+    }
+#else
+    memset(g2h(vaddr), 0, blocklen);
+#endif
+}
+
 /* Note that signed overflow is undefined in C.  The following routines are
    careful to use unsigned types where modulo arithmetic is required.
    Failure to do so _will_ break on newer gcc.  */
diff --git a/target-arm/helper.h b/target-arm/helper.h
index 0abdb0c..5977169 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -515,6 +515,7 @@ DEF_HELPER_4(crypto_aesmc, void, env, i32, i32, i32)
 
 DEF_HELPER_FLAGS_3(crc32, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
 DEF_HELPER_FLAGS_3(crc32c, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
+DEF_HELPER_2(dc_zva, void, env, i64)
 
 #ifdef TARGET_AARCH64
 #include "helper-a64.h"
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 0ec2f65..4c5402a 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -1335,6 +1335,11 @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
         tcg_rt = cpu_reg(s, rt);
         tcg_gen_movi_i64(tcg_rt, s->current_pl << 2);
         return;
+    case ARM_CP_DC_ZVA:
+        /* Writes clear the aligned block of memory which rt points into. */
+        tcg_rt = cpu_reg(s, rt);
+        gen_helper_dc_zva(cpu_env, tcg_rt);
+        return;
     default:
         break;
     }
-- 
1.9.1

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

* [Qemu-devel] [PATCH v6 13/37] target-arm: Use dedicated CPU state fields for ARM946 access bit registers
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
                   ` (11 preceding siblings ...)
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 12/37] target-arm: A64: Implement DC ZVA Peter Maydell
@ 2014-04-10 16:15 ` Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 14/37] target-arm: Implement AArch64 views of fault status and data registers Peter Maydell
                   ` (24 subsequent siblings)
  37 siblings, 0 replies; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

The ARM946 model currently uses the c5_data and c5_insn fields in the CPU
state struct to store the contents of its access permission registers.
This is confusing and a good source of bugs because for all the MMU-based
CPUs those fields are fault status and fault address registers, which
behave completely differently; they just happen to use the same cpreg
encoding. Split them out to use their own fields instead.

These registers are only present in PMSAv5 MPU systems (of which the
ARM946 is our only current example); PMSAv6 and PMSAv7 (which we have
no implementations of) handle access permissions differently. We name
the new state fields accordingly.

Note that this change fixes a bug where a data abort or prefetch abort
on the ARM946 would accidentally corrupt the access permission registers
because the interrupt handling code assumed the c5_data and c5_insn
fields were always fault status registers.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
 target-arm/cpu.h    |  2 ++
 target-arm/helper.c | 24 ++++++++++++++----------
 2 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index a00ff73..42fa7db 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -179,6 +179,8 @@ typedef struct CPUARMState {
         uint32_t c2_insn; /* MPU instruction cachable bits.  */
         uint32_t c3; /* MMU domain access control register
                         MPU write buffer control.  */
+        uint32_t pmsav5_data_ap; /* PMSAv5 MPU data access permissions */
+        uint32_t pmsav5_insn_ap; /* PMSAv5 MPU insn access permissions */
         uint32_t c5_insn; /* Fault status registers.  */
         uint32_t c5_data;
         uint32_t c6_region[8]; /* MPU base/size registers.  */
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 2ffc588..289a5c0 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1275,40 +1275,44 @@ static uint32_t extended_mpu_ap_bits(uint32_t val)
 static void pmsav5_data_ap_write(CPUARMState *env, const ARMCPRegInfo *ri,
                                  uint64_t value)
 {
-    env->cp15.c5_data = extended_mpu_ap_bits(value);
+    env->cp15.pmsav5_data_ap = extended_mpu_ap_bits(value);
 }
 
 static uint64_t pmsav5_data_ap_read(CPUARMState *env, const ARMCPRegInfo *ri)
 {
-    return simple_mpu_ap_bits(env->cp15.c5_data);
+    return simple_mpu_ap_bits(env->cp15.pmsav5_data_ap);
 }
 
 static void pmsav5_insn_ap_write(CPUARMState *env, const ARMCPRegInfo *ri,
                                  uint64_t value)
 {
-    env->cp15.c5_insn = extended_mpu_ap_bits(value);
+    env->cp15.pmsav5_insn_ap = extended_mpu_ap_bits(value);
 }
 
 static uint64_t pmsav5_insn_ap_read(CPUARMState *env, const ARMCPRegInfo *ri)
 {
-    return simple_mpu_ap_bits(env->cp15.c5_insn);
+    return simple_mpu_ap_bits(env->cp15.pmsav5_insn_ap);
 }
 
 static const ARMCPRegInfo pmsav5_cp_reginfo[] = {
     { .name = "DATA_AP", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 0,
       .access = PL1_RW, .type = ARM_CP_NO_MIGRATE,
-      .fieldoffset = offsetof(CPUARMState, cp15.c5_data), .resetvalue = 0,
+      .fieldoffset = offsetof(CPUARMState, cp15.pmsav5_data_ap),
+      .resetvalue = 0,
       .readfn = pmsav5_data_ap_read, .writefn = pmsav5_data_ap_write, },
     { .name = "INSN_AP", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 1,
       .access = PL1_RW, .type = ARM_CP_NO_MIGRATE,
-      .fieldoffset = offsetof(CPUARMState, cp15.c5_insn), .resetvalue = 0,
+      .fieldoffset = offsetof(CPUARMState, cp15.pmsav5_insn_ap),
+      .resetvalue = 0,
       .readfn = pmsav5_insn_ap_read, .writefn = pmsav5_insn_ap_write, },
     { .name = "DATA_EXT_AP", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 2,
       .access = PL1_RW,
-      .fieldoffset = offsetof(CPUARMState, cp15.c5_data), .resetvalue = 0, },
+      .fieldoffset = offsetof(CPUARMState, cp15.pmsav5_data_ap),
+      .resetvalue = 0, },
     { .name = "INSN_EXT_AP", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 3,
       .access = PL1_RW,
-      .fieldoffset = offsetof(CPUARMState, cp15.c5_insn), .resetvalue = 0, },
+      .fieldoffset = offsetof(CPUARMState, cp15.pmsav5_insn_ap),
+      .resetvalue = 0, },
     { .name = "DCACHE_CFG", .cp = 15, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 0,
       .access = PL1_RW,
       .fieldoffset = offsetof(CPUARMState, cp15.c2_data), .resetvalue = 0, },
@@ -3676,9 +3680,9 @@ static int get_phys_addr_mpu(CPUARMState *env, uint32_t address,
 	return 2;
 
     if (access_type == 2) {
-	mask = env->cp15.c5_insn;
+        mask = env->cp15.pmsav5_insn_ap;
     } else {
-	mask = env->cp15.c5_data;
+        mask = env->cp15.pmsav5_data_ap;
     }
     mask = (mask >> (n * 4)) & 0xf;
     switch (mask) {
-- 
1.9.1

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

* [Qemu-devel] [PATCH v6 14/37] target-arm: Implement AArch64 views of fault status and data registers
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
                   ` (12 preceding siblings ...)
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 13/37] target-arm: Use dedicated CPU state fields for ARM946 access bit registers Peter Maydell
@ 2014-04-10 16:15 ` Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 15/37] target-arm: Add AArch64 ELR_EL1 register Peter Maydell
                   ` (23 subsequent siblings)
  37 siblings, 0 replies; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

From: Rob Herring <rob.herring@linaro.org>

Implement AArch64 views of ESR_EL1 and FAR_EL1, and make the 32 bit
DFSR, DFAR, IFAR share state with them as architecturally specified.
The IFSR doesn't share state with any AArch64 register visible at EL1,
so just rename the state field without widening it to 64 bits.

Signed-off-by: Rob Herring <rob.herring@linaro.org>
[PMM: Minor tweaks; fix some bugs involving inconsistencies between
 use of offsetof() or offsetoflow32() and struct field width]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/cpu.c    |  2 +-
 target-arm/cpu.h    |  7 +++----
 target-arm/helper.c | 38 +++++++++++++++++++++++++-------------
 3 files changed, 29 insertions(+), 18 deletions(-)

diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index d62b792..a3c7492 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -425,7 +425,7 @@ static void arm1026_initfn(Object *obj)
         ARMCPRegInfo ifar = {
             .name = "IFAR", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 1,
             .access = PL1_RW,
-            .fieldoffset = offsetof(CPUARMState, cp15.c6_insn),
+            .fieldoffset = offsetofhigh32(CPUARMState, cp15.far_el1),
             .resetvalue = 0
         };
         define_one_arm_cp_reg(cpu, &ifar);
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 42fa7db..4ca75cd 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -181,11 +181,10 @@ typedef struct CPUARMState {
                         MPU write buffer control.  */
         uint32_t pmsav5_data_ap; /* PMSAv5 MPU data access permissions */
         uint32_t pmsav5_insn_ap; /* PMSAv5 MPU insn access permissions */
-        uint32_t c5_insn; /* Fault status registers.  */
-        uint32_t c5_data;
+        uint32_t ifsr_el2; /* Fault status registers.  */
+        uint64_t esr_el1;
         uint32_t c6_region[8]; /* MPU base/size registers.  */
-        uint32_t c6_insn; /* Fault address registers.  */
-        uint32_t c6_data;
+        uint64_t far_el1; /* Fault address registers.  */
         uint32_t c7_par;  /* Translation result. */
         uint32_t c7_par_hi;  /* Translation result, high 32 bits */
         uint32_t c9_insn; /* Cache lockdown registers.  */
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 289a5c0..5f6233b 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -475,7 +475,8 @@ static const ARMCPRegInfo v6_cp_reginfo[] = {
     { .name = "DMB", .cp = 15, .crn = 7, .crm = 10, .opc1 = 0, .opc2 = 5,
       .access = PL0_W, .type = ARM_CP_NOP },
     { .name = "IFAR", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 2,
-      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c6_insn),
+      .access = PL1_RW,
+      .fieldoffset = offsetofhigh32(CPUARMState, cp15.far_el1),
       .resetvalue = 0, },
     /* Watchpoint Fault Address Register : should actually only be present
      * for 1136, 1176, 11MPCore.
@@ -1414,11 +1415,16 @@ static void vmsa_ttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
 
 static const ARMCPRegInfo vmsa_cp_reginfo[] = {
     { .name = "DFSR", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 0,
-      .access = PL1_RW,
-      .fieldoffset = offsetof(CPUARMState, cp15.c5_data), .resetvalue = 0, },
+      .access = PL1_RW, .type = ARM_CP_NO_MIGRATE,
+      .fieldoffset = offsetoflow32(CPUARMState, cp15.esr_el1),
+      .resetfn = arm_cp_reset_ignore, },
     { .name = "IFSR", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 1,
       .access = PL1_RW,
-      .fieldoffset = offsetof(CPUARMState, cp15.c5_insn), .resetvalue = 0, },
+      .fieldoffset = offsetof(CPUARMState, cp15.ifsr_el2), .resetvalue = 0, },
+    { .name = "ESR_EL1", .state = ARM_CP_STATE_AA64,
+      .opc0 = 3, .crn = 5, .crm = 2, .opc1 = 0, .opc2 = 0,
+      .access = PL1_RW,
+      .fieldoffset = offsetof(CPUARMState, cp15.esr_el1), .resetvalue = 0, },
     { .name = "TTBR0_EL1", .state = ARM_CP_STATE_BOTH,
       .opc0 = 3, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 0,
       .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.ttbr0_el1),
@@ -1436,8 +1442,10 @@ static const ARMCPRegInfo vmsa_cp_reginfo[] = {
       .access = PL1_RW, .type = ARM_CP_NO_MIGRATE, .writefn = vmsa_ttbcr_write,
       .resetfn = arm_cp_reset_ignore, .raw_writefn = vmsa_ttbcr_raw_write,
       .fieldoffset = offsetoflow32(CPUARMState, cp15.c2_control) },
-    { .name = "DFAR", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 0,
-      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c6_data),
+    /* 64-bit FAR; this entry also gives us the AArch32 DFAR */
+    { .name = "FAR_EL1", .state = ARM_CP_STATE_BOTH,
+      .opc0 = 3, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 0,
+      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.far_el1),
       .resetvalue = 0, },
     REGINFO_SENTINEL
 };
@@ -1477,7 +1485,8 @@ static void omap_cachemaint_write(CPUARMState *env, const ARMCPRegInfo *ri,
 static const ARMCPRegInfo omap_cp_reginfo[] = {
     { .name = "DFSR", .cp = 15, .crn = 5, .crm = CP_ANY,
       .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_RW, .type = ARM_CP_OVERRIDE,
-      .fieldoffset = offsetof(CPUARMState, cp15.c5_data), .resetvalue = 0, },
+      .fieldoffset = offsetoflow32(CPUARMState, cp15.esr_el1),
+      .resetvalue = 0, },
     { .name = "", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 0,
       .access = PL1_RW, .type = ARM_CP_NOP },
     { .name = "TICONFIG", .cp = 15, .crn = 15, .crm = 1, .opc1 = 0, .opc2 = 0,
@@ -3087,20 +3096,23 @@ void arm_cpu_do_interrupt(CPUState *cs)
         env->exception.fsr = 2;
         /* Fall through to prefetch abort.  */
     case EXCP_PREFETCH_ABORT:
-        env->cp15.c5_insn = env->exception.fsr;
-        env->cp15.c6_insn = env->exception.vaddress;
+        env->cp15.ifsr_el2 = env->exception.fsr;
+        env->cp15.far_el1 = deposit64(env->cp15.far_el1, 32, 32,
+                                      env->exception.vaddress);
         qemu_log_mask(CPU_LOG_INT, "...with IFSR 0x%x IFAR 0x%x\n",
-                      env->cp15.c5_insn, env->cp15.c6_insn);
+                      env->cp15.ifsr_el2, (uint32_t)env->exception.vaddress);
         new_mode = ARM_CPU_MODE_ABT;
         addr = 0x0c;
         mask = CPSR_A | CPSR_I;
         offset = 4;
         break;
     case EXCP_DATA_ABORT:
-        env->cp15.c5_data = env->exception.fsr;
-        env->cp15.c6_data = env->exception.vaddress;
+        env->cp15.esr_el1 = env->exception.fsr;
+        env->cp15.far_el1 = deposit64(env->cp15.far_el1, 0, 32,
+                                      env->exception.vaddress);
         qemu_log_mask(CPU_LOG_INT, "...with DFSR 0x%x DFAR 0x%x\n",
-                      env->cp15.c5_data, env->cp15.c6_data);
+                      (uint32_t)env->cp15.esr_el1,
+                      (uint32_t)env->exception.vaddress);
         new_mode = ARM_CPU_MODE_ABT;
         addr = 0x10;
         mask = CPSR_A | CPSR_I;
-- 
1.9.1

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

* [Qemu-devel] [PATCH v6 15/37] target-arm: Add AArch64 ELR_EL1 register.
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
                   ` (13 preceding siblings ...)
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 14/37] target-arm: Implement AArch64 views of fault status and data registers Peter Maydell
@ 2014-04-10 16:15 ` Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 16/37] target-arm: Implement SP_EL0, SP_EL1 Peter Maydell
                   ` (22 subsequent siblings)
  37 siblings, 0 replies; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

Add the AArch64 ELR_EL1 register.

Note that this does not live in env->cp15: for KVM migration
compatibility we need to migrate it separately rather than
as part of the system registers, because the KVM-to-userspace
interface puts it in the struct kvm_regs rather than making
them visible via the ONE_REG ioctls.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
 target-arm/cpu.h     |  2 ++
 target-arm/helper.c  |  4 ++++
 target-arm/kvm64.c   | 15 ++++++++++++++-
 target-arm/machine.c |  7 ++++---
 4 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 4ca75cd..ecdd7a7 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -162,6 +162,8 @@ typedef struct CPUARMState {
     uint32_t condexec_bits; /* IT bits.  cpsr[15:10,26:25].  */
     uint64_t daif; /* exception masks, in the bits they are in in PSTATE */
 
+    uint64_t elr_el1; /* AArch64 ELR_EL1 */
+
     /* System control coprocessor (cp15) */
     struct {
         uint32_t c0_cpuid;
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 5f6233b..276ecf2 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1911,6 +1911,10 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
     { .name = "OSLAR_EL1", .state = ARM_CP_STATE_AA64,
       .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 4,
       .access = PL1_W, .type = ARM_CP_NOP },
+    { .name = "ELR_EL1", .state = ARM_CP_STATE_AA64,
+      .type = ARM_CP_NO_MIGRATE,
+      .opc0 = 3, .opc1 = 0, .crn = 4, .crm = 0, .opc2 = 1,
+      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, elr_el1) },
     REGINFO_SENTINEL
 };
 
diff --git a/target-arm/kvm64.c b/target-arm/kvm64.c
index 1b7ca90..ee72748 100644
--- a/target-arm/kvm64.c
+++ b/target-arm/kvm64.c
@@ -144,9 +144,15 @@ int kvm_arch_put_registers(CPUState *cs, int level)
         return ret;
     }
 
+    reg.id = AARCH64_CORE_REG(elr_el1);
+    reg.addr = (uintptr_t) &env->elr_el1;
+    ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
+    if (ret) {
+        return ret;
+    }
+
     /* TODO:
      * SP_EL1
-     * ELR_EL1
      * SPSR[]
      * FP state
      * system registers
@@ -195,6 +201,13 @@ int kvm_arch_get_registers(CPUState *cs)
         return ret;
     }
 
+    reg.id = AARCH64_CORE_REG(elr_el1);
+    reg.addr = (uintptr_t) &env->elr_el1;
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
+    if (ret) {
+        return ret;
+    }
+
     /* TODO: other registers */
     return ret;
 }
diff --git a/target-arm/machine.c b/target-arm/machine.c
index b9d9c0f..42b1c90 100644
--- a/target-arm/machine.c
+++ b/target-arm/machine.c
@@ -222,9 +222,9 @@ static int cpu_post_load(void *opaque, int version_id)
 
 const VMStateDescription vmstate_arm_cpu = {
     .name = "cpu",
-    .version_id = 14,
-    .minimum_version_id = 14,
-    .minimum_version_id_old = 14,
+    .version_id = 15,
+    .minimum_version_id = 15,
+    .minimum_version_id_old = 15,
     .pre_save = cpu_pre_save,
     .post_load = cpu_post_load,
     .fields = (VMStateField[]) {
@@ -243,6 +243,7 @@ const VMStateDescription vmstate_arm_cpu = {
         VMSTATE_UINT32_ARRAY(env.banked_r14, ARMCPU, 6),
         VMSTATE_UINT32_ARRAY(env.usr_regs, ARMCPU, 5),
         VMSTATE_UINT32_ARRAY(env.fiq_regs, ARMCPU, 5),
+        VMSTATE_UINT64(env.elr_el1, ARMCPU),
         /* The length-check must come before the arrays to avoid
          * incoming data possibly overflowing the array.
          */
-- 
1.9.1

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

* [Qemu-devel] [PATCH v6 16/37] target-arm: Implement SP_EL0, SP_EL1
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
                   ` (14 preceding siblings ...)
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 15/37] target-arm: Add AArch64 ELR_EL1 register Peter Maydell
@ 2014-04-10 16:15 ` Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 17/37] target-arm: Implement AArch64 SPSR_EL1 Peter Maydell
                   ` (21 subsequent siblings)
  37 siblings, 0 replies; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

Implement handling for the AArch64 SP_EL0 system register.
This holds the EL0 stack pointer, and is only accessible when
it's not being used as the stack pointer, ie when we're in EL1
and EL1 is using its own stack pointer. We also provide a
definition of the SP_EL1 register; this isn't guest visible
as a system register for an implementation like QEMU which
doesn't provide EL2 or EL3; however it is useful for ensuring
the underlying state is migrated.

We need to update the state fields in the CPU state whenever
we switch stack pointers; this happens when we take an exception
and also when SPSEL is used to change the bit in PSTATE which
indicates which stack pointer EL1 should use.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/cpu.h       |  2 ++
 target-arm/helper.c    | 34 ++++++++++++++++++++++++++++++++++
 target-arm/internals.h | 25 +++++++++++++++++++++++++
 target-arm/kvm64.c     | 37 ++++++++++++++++++++++++++++++++++---
 target-arm/machine.c   |  7 ++++---
 target-arm/op_helper.c |  2 +-
 6 files changed, 100 insertions(+), 7 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index ecdd7a7..28b9bda 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -163,6 +163,7 @@ typedef struct CPUARMState {
     uint64_t daif; /* exception masks, in the bits they are in in PSTATE */
 
     uint64_t elr_el1; /* AArch64 ELR_EL1 */
+    uint64_t sp_el[2]; /* AArch64 banked stack pointers */
 
     /* System control coprocessor (cp15) */
     struct {
@@ -434,6 +435,7 @@ int arm_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
  * Only these are valid when in AArch64 mode; in
  * AArch32 mode SPSRs are basically CPSR-format.
  */
+#define PSTATE_SP (1U)
 #define PSTATE_M (0xFU)
 #define PSTATE_nRW (1U << 4)
 #define PSTATE_F (1U << 6)
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 276ecf2..27a3dc2 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1783,6 +1783,27 @@ static uint64_t aa64_dczid_read(CPUARMState *env, const ARMCPRegInfo *ri)
     return cpu->dcz_blocksize | dzp_bit;
 }
 
+static CPAccessResult sp_el0_access(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    if (!env->pstate & PSTATE_SP) {
+        /* Access to SP_EL0 is undefined if it's being used as
+         * the stack pointer.
+         */
+        return CP_ACCESS_TRAP_UNCATEGORIZED;
+    }
+    return CP_ACCESS_OK;
+}
+
+static uint64_t spsel_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    return env->pstate & PSTATE_SP;
+}
+
+static void spsel_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t val)
+{
+    update_spsel(env, val);
+}
+
 static const ARMCPRegInfo v8_cp_reginfo[] = {
     /* Minimal set of EL0-visible registers. This will need to be expanded
      * significantly for system emulation of AArch64 CPUs.
@@ -1915,6 +1936,19 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
       .type = ARM_CP_NO_MIGRATE,
       .opc0 = 3, .opc1 = 0, .crn = 4, .crm = 0, .opc2 = 1,
       .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, elr_el1) },
+    /* We rely on the access checks not allowing the guest to write to the
+     * state field when SPSel indicates that it's being used as the stack
+     * pointer.
+     */
+    { .name = "SP_EL0", .state = ARM_CP_STATE_AA64,
+      .opc0 = 3, .opc1 = 0, .crn = 4, .crm = 1, .opc2 = 0,
+      .access = PL1_RW, .accessfn = sp_el0_access,
+      .type = ARM_CP_NO_MIGRATE,
+      .fieldoffset = offsetof(CPUARMState, sp_el[0]) },
+    { .name = "SPSel", .state = ARM_CP_STATE_AA64,
+      .opc0 = 3, .opc1 = 0, .crn = 4, .crm = 2, .opc2 = 0,
+      .type = ARM_CP_NO_MIGRATE,
+      .access = PL1_RW, .readfn = spsel_read, .writefn = spsel_write },
     REGINFO_SENTINEL
 };
 
diff --git a/target-arm/internals.h b/target-arm/internals.h
index a527f02..de79dfc 100644
--- a/target-arm/internals.h
+++ b/target-arm/internals.h
@@ -60,6 +60,31 @@ enum arm_fprounding {
 
 int arm_rmode_to_sf(int rmode);
 
+static inline void update_spsel(CPUARMState *env, uint32_t imm)
+{
+    /* Update PSTATE SPSel bit; this requires us to update the
+     * working stack pointer in xregs[31].
+     */
+    if (!((imm ^ env->pstate) & PSTATE_SP)) {
+        return;
+    }
+    env->pstate = deposit32(env->pstate, 0, 1, imm);
+
+    /* EL0 has no access rights to update SPSel, and this code
+     * assumes we are updating SP for EL1 while running as EL1.
+     */
+    assert(arm_current_pl(env) == 1);
+    if (env->pstate & PSTATE_SP) {
+        /* Switch from using SP_EL0 to using SP_ELx */
+        env->sp_el[0] = env->xregs[31];
+        env->xregs[31] = env->sp_el[1];
+    } else {
+        /* Switch from SP_EL0 to SP_ELx */
+        env->sp_el[1] = env->xregs[31];
+        env->xregs[31] = env->sp_el[0];
+    }
+}
+
 /* Valid Syndrome Register EC field values */
 enum arm_exception_class {
     EC_UNCATEGORIZED          = 0x00,
diff --git a/target-arm/kvm64.c b/target-arm/kvm64.c
index ee72748..39c4364 100644
--- a/target-arm/kvm64.c
+++ b/target-arm/kvm64.c
@@ -121,8 +121,24 @@ int kvm_arch_put_registers(CPUState *cs, int level)
         }
     }
 
+    /* KVM puts SP_EL0 in regs.sp and SP_EL1 in regs.sp_el1. On the
+     * QEMU side we keep the current SP in xregs[31] as well.
+     */
+    if (env->pstate & PSTATE_SP) {
+        env->sp_el[1] = env->xregs[31];
+    } else {
+        env->sp_el[0] = env->xregs[31];
+    }
+
     reg.id = AARCH64_CORE_REG(regs.sp);
-    reg.addr = (uintptr_t) &env->xregs[31];
+    reg.addr = (uintptr_t) &env->sp_el[0];
+    ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
+    if (ret) {
+        return ret;
+    }
+
+    reg.id = AARCH64_CORE_REG(sp_el1);
+    reg.addr = (uintptr_t) &env->sp_el[1];
     ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
     if (ret) {
         return ret;
@@ -152,7 +168,6 @@ int kvm_arch_put_registers(CPUState *cs, int level)
     }
 
     /* TODO:
-     * SP_EL1
      * SPSR[]
      * FP state
      * system registers
@@ -180,7 +195,14 @@ int kvm_arch_get_registers(CPUState *cs)
     }
 
     reg.id = AARCH64_CORE_REG(regs.sp);
-    reg.addr = (uintptr_t) &env->xregs[31];
+    reg.addr = (uintptr_t) &env->sp_el[0];
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
+    if (ret) {
+        return ret;
+    }
+
+    reg.id = AARCH64_CORE_REG(sp_el1);
+    reg.addr = (uintptr_t) &env->sp_el[1];
     ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
     if (ret) {
         return ret;
@@ -194,6 +216,15 @@ int kvm_arch_get_registers(CPUState *cs)
     }
     pstate_write(env, val);
 
+    /* KVM puts SP_EL0 in regs.sp and SP_EL1 in regs.sp_el1. On the
+     * QEMU side we keep the current SP in xregs[31] as well.
+     */
+    if (env->pstate & PSTATE_SP) {
+        env->xregs[31] = env->sp_el[1];
+    } else {
+        env->xregs[31] = env->sp_el[0];
+    }
+
     reg.id = AARCH64_CORE_REG(regs.pc);
     reg.addr = (uintptr_t) &env->pc;
     ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
diff --git a/target-arm/machine.c b/target-arm/machine.c
index 42b1c90..c2c0780 100644
--- a/target-arm/machine.c
+++ b/target-arm/machine.c
@@ -222,9 +222,9 @@ static int cpu_post_load(void *opaque, int version_id)
 
 const VMStateDescription vmstate_arm_cpu = {
     .name = "cpu",
-    .version_id = 15,
-    .minimum_version_id = 15,
-    .minimum_version_id_old = 15,
+    .version_id = 16,
+    .minimum_version_id = 16,
+    .minimum_version_id_old = 16,
     .pre_save = cpu_pre_save,
     .post_load = cpu_post_load,
     .fields = (VMStateField[]) {
@@ -244,6 +244,7 @@ const VMStateDescription vmstate_arm_cpu = {
         VMSTATE_UINT32_ARRAY(env.usr_regs, ARMCPU, 5),
         VMSTATE_UINT32_ARRAY(env.fiq_regs, ARMCPU, 5),
         VMSTATE_UINT64(env.elr_el1, ARMCPU),
+        VMSTATE_UINT64_ARRAY(env.sp_el, ARMCPU, 2),
         /* The length-check must come before the arrays to avoid
          * incoming data possibly overflowing the array.
          */
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 51edd90..64a33dd 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -371,7 +371,7 @@ void HELPER(msr_i_pstate)(CPUARMState *env, uint32_t op, uint32_t imm)
 
     switch (op) {
     case 0x05: /* SPSel */
-        env->pstate = deposit32(env->pstate, 0, 1, imm);
+        update_spsel(env, imm);
         break;
     case 0x1e: /* DAIFSet */
         env->daif |= (imm << 6) & PSTATE_DAIF;
-- 
1.9.1

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

* [Qemu-devel] [PATCH v6 17/37] target-arm: Implement AArch64 SPSR_EL1
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
                   ` (15 preceding siblings ...)
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 16/37] target-arm: Implement SP_EL0, SP_EL1 Peter Maydell
@ 2014-04-10 16:15 ` Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 18/37] target-arm: Move arm_log_exception() into internals.h Peter Maydell
                   ` (20 subsequent siblings)
  37 siblings, 0 replies; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

Implement the AArch64 SPSR_EL1. For compatibility with how KVM
handles SPSRs and with the architectural mapping between AArch32
and AArch64, we put this in the banked_spsr[] array in the slot
that is used for SVC in AArch32. This means we need to extend the
array from uint32_t to uint64_t, which requires some reworking
of the 32 bit KVM save/restore code.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/cpu.h     |  2 +-
 target-arm/helper.c  |  4 ++++
 target-arm/kvm32.c   | 18 +++++++++++++-----
 target-arm/kvm64.c   | 19 ++++++++++++++++++-
 target-arm/machine.c |  8 ++++----
 5 files changed, 40 insertions(+), 11 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 28b9bda..0ce4c26 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -143,7 +143,7 @@ typedef struct CPUARMState {
     uint32_t spsr;
 
     /* Banked registers.  */
-    uint32_t banked_spsr[6];
+    uint64_t banked_spsr[6];
     uint32_t banked_r13[6];
     uint32_t banked_r14[6];
 
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 27a3dc2..68f8c6a 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1936,6 +1936,10 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
       .type = ARM_CP_NO_MIGRATE,
       .opc0 = 3, .opc1 = 0, .crn = 4, .crm = 0, .opc2 = 1,
       .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, elr_el1) },
+    { .name = "SPSR_EL1", .state = ARM_CP_STATE_AA64,
+      .type = ARM_CP_NO_MIGRATE,
+      .opc0 = 3, .opc1 = 0, .crn = 4, .crm = 0, .opc2 = 0,
+      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, banked_spsr[0]) },
     /* We rely on the access checks not allowing the guest to write to the
      * state field when SPSel indicates that it's being used as the stack
      * pointer.
diff --git a/target-arm/kvm32.c b/target-arm/kvm32.c
index b21f844..a690d99 100644
--- a/target-arm/kvm32.c
+++ b/target-arm/kvm32.c
@@ -295,6 +295,14 @@ typedef struct Reg {
         offsetof(CPUARMState, vfp.xregs[ARM_VFP_##R])      \
     }
 
+/* Like COREREG, but handle fields which are in a uint64_t in CPUARMState. */
+#define COREREG64(KERNELNAME, QEMUFIELD)                     \
+    {                                                        \
+        KVM_REG_ARM | KVM_REG_SIZE_U32 |                     \
+        KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(KERNELNAME), \
+        offsetoflow32(CPUARMState, QEMUFIELD)                \
+    }
+
 static const Reg regs[] = {
     /* R0_usr .. R14_usr */
     COREREG(usr_regs.uregs[0], regs[0]),
@@ -315,16 +323,16 @@ static const Reg regs[] = {
     /* R13, R14, SPSR for SVC, ABT, UND, IRQ banks */
     COREREG(svc_regs[0], banked_r13[1]),
     COREREG(svc_regs[1], banked_r14[1]),
-    COREREG(svc_regs[2], banked_spsr[1]),
+    COREREG64(svc_regs[2], banked_spsr[1]),
     COREREG(abt_regs[0], banked_r13[2]),
     COREREG(abt_regs[1], banked_r14[2]),
-    COREREG(abt_regs[2], banked_spsr[2]),
+    COREREG64(abt_regs[2], banked_spsr[2]),
     COREREG(und_regs[0], banked_r13[3]),
     COREREG(und_regs[1], banked_r14[3]),
-    COREREG(und_regs[2], banked_spsr[3]),
+    COREREG64(und_regs[2], banked_spsr[3]),
     COREREG(irq_regs[0], banked_r13[4]),
     COREREG(irq_regs[1], banked_r14[4]),
-    COREREG(irq_regs[2], banked_spsr[4]),
+    COREREG64(irq_regs[2], banked_spsr[4]),
     /* R8_fiq .. R14_fiq and SPSR_fiq */
     COREREG(fiq_regs[0], fiq_regs[0]),
     COREREG(fiq_regs[1], fiq_regs[1]),
@@ -333,7 +341,7 @@ static const Reg regs[] = {
     COREREG(fiq_regs[4], fiq_regs[4]),
     COREREG(fiq_regs[5], banked_r13[5]),
     COREREG(fiq_regs[6], banked_r14[5]),
-    COREREG(fiq_regs[7], banked_spsr[5]),
+    COREREG64(fiq_regs[7], banked_spsr[5]),
     /* R15 */
     COREREG(usr_regs.uregs[15], regs[15]),
     /* VFP system registers */
diff --git a/target-arm/kvm64.c b/target-arm/kvm64.c
index 39c4364..e115879 100644
--- a/target-arm/kvm64.c
+++ b/target-arm/kvm64.c
@@ -167,8 +167,16 @@ int kvm_arch_put_registers(CPUState *cs, int level)
         return ret;
     }
 
+    for (i = 0; i < KVM_NR_SPSR; i++) {
+        reg.id = AARCH64_CORE_REG(spsr[i]);
+        reg.addr = (uintptr_t) &env->banked_spsr[i - 1];
+        ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
+        if (ret) {
+            return ret;
+        }
+    }
+
     /* TODO:
-     * SPSR[]
      * FP state
      * system registers
      */
@@ -239,6 +247,15 @@ int kvm_arch_get_registers(CPUState *cs)
         return ret;
     }
 
+    for (i = 0; i < KVM_NR_SPSR; i++) {
+        reg.id = AARCH64_CORE_REG(spsr[i]);
+        reg.addr = (uintptr_t) &env->banked_spsr[i - 1];
+        ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
+        if (ret) {
+            return ret;
+        }
+    }
+
     /* TODO: other registers */
     return ret;
 }
diff --git a/target-arm/machine.c b/target-arm/machine.c
index c2c0780..b967223 100644
--- a/target-arm/machine.c
+++ b/target-arm/machine.c
@@ -222,9 +222,9 @@ static int cpu_post_load(void *opaque, int version_id)
 
 const VMStateDescription vmstate_arm_cpu = {
     .name = "cpu",
-    .version_id = 16,
-    .minimum_version_id = 16,
-    .minimum_version_id_old = 16,
+    .version_id = 17,
+    .minimum_version_id = 17,
+    .minimum_version_id_old = 17,
     .pre_save = cpu_pre_save,
     .post_load = cpu_post_load,
     .fields = (VMStateField[]) {
@@ -238,7 +238,7 @@ const VMStateDescription vmstate_arm_cpu = {
             .offset = 0,
         },
         VMSTATE_UINT32(env.spsr, ARMCPU),
-        VMSTATE_UINT32_ARRAY(env.banked_spsr, ARMCPU, 6),
+        VMSTATE_UINT64_ARRAY(env.banked_spsr, ARMCPU, 6),
         VMSTATE_UINT32_ARRAY(env.banked_r13, ARMCPU, 6),
         VMSTATE_UINT32_ARRAY(env.banked_r14, ARMCPU, 6),
         VMSTATE_UINT32_ARRAY(env.usr_regs, ARMCPU, 5),
-- 
1.9.1

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

* [Qemu-devel] [PATCH v6 18/37] target-arm: Move arm_log_exception() into internals.h
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
                   ` (16 preceding siblings ...)
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 17/37] target-arm: Implement AArch64 SPSR_EL1 Peter Maydell
@ 2014-04-10 16:15 ` Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 19/37] target-arm: Implement AArch64 EL1 exception handling Peter Maydell
                   ` (19 subsequent siblings)
  37 siblings, 0 replies; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

Move arm_log_exception() into internals.h so we can use it from
helper-a64.c for the AArch64 exception entry code.

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

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 68f8c6a..e9b64f3 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2957,37 +2957,6 @@ static void do_v7m_exception_exit(CPUARMState *env)
        pointer.  */
 }
 
-/* Exception names for debug logging; note that not all of these
- * precisely correspond to architectural exceptions.
- */
-static const char * const excnames[] = {
-    [EXCP_UDEF] = "Undefined Instruction",
-    [EXCP_SWI] = "SVC",
-    [EXCP_PREFETCH_ABORT] = "Prefetch Abort",
-    [EXCP_DATA_ABORT] = "Data Abort",
-    [EXCP_IRQ] = "IRQ",
-    [EXCP_FIQ] = "FIQ",
-    [EXCP_BKPT] = "Breakpoint",
-    [EXCP_EXCEPTION_EXIT] = "QEMU v7M exception exit",
-    [EXCP_KERNEL_TRAP] = "QEMU intercept of kernel commpage",
-    [EXCP_STREX] = "QEMU intercept of STREX",
-};
-
-static inline void arm_log_exception(int idx)
-{
-    if (qemu_loglevel_mask(CPU_LOG_INT)) {
-        const char *exc = NULL;
-
-        if (idx >= 0 && idx < ARRAY_SIZE(excnames)) {
-            exc = excnames[idx];
-        }
-        if (!exc) {
-            exc = "unknown";
-        }
-        qemu_log_mask(CPU_LOG_INT, "Taking exception %d [%s]\n", idx, exc);
-    }
-}
-
 void arm_v7m_cpu_do_interrupt(CPUState *cs)
 {
     ARMCPU *cpu = ARM_CPU(cs);
diff --git a/target-arm/internals.h b/target-arm/internals.h
index de79dfc..d63a975 100644
--- a/target-arm/internals.h
+++ b/target-arm/internals.h
@@ -39,6 +39,37 @@ static inline bool excp_is_internal(int excp)
         || excp == EXCP_STREX;
 }
 
+/* Exception names for debug logging; note that not all of these
+ * precisely correspond to architectural exceptions.
+ */
+static const char * const excnames[] = {
+    [EXCP_UDEF] = "Undefined Instruction",
+    [EXCP_SWI] = "SVC",
+    [EXCP_PREFETCH_ABORT] = "Prefetch Abort",
+    [EXCP_DATA_ABORT] = "Data Abort",
+    [EXCP_IRQ] = "IRQ",
+    [EXCP_FIQ] = "FIQ",
+    [EXCP_BKPT] = "Breakpoint",
+    [EXCP_EXCEPTION_EXIT] = "QEMU v7M exception exit",
+    [EXCP_KERNEL_TRAP] = "QEMU intercept of kernel commpage",
+    [EXCP_STREX] = "QEMU intercept of STREX",
+};
+
+static inline void arm_log_exception(int idx)
+{
+    if (qemu_loglevel_mask(CPU_LOG_INT)) {
+        const char *exc = NULL;
+
+        if (idx >= 0 && idx < ARRAY_SIZE(excnames)) {
+            exc = excnames[idx];
+        }
+        if (!exc) {
+            exc = "unknown";
+        }
+        qemu_log_mask(CPU_LOG_INT, "Taking exception %d [%s]\n", idx, exc);
+    }
+}
+
 /* Scale factor for generic timers, ie number of ns per tick.
  * This gives a 62.5MHz timer.
  */
-- 
1.9.1

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

* [Qemu-devel] [PATCH v6 19/37] target-arm: Implement AArch64 EL1 exception handling
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
                   ` (17 preceding siblings ...)
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 18/37] target-arm: Move arm_log_exception() into internals.h Peter Maydell
@ 2014-04-10 16:15 ` Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 20/37] target-arm: Implement ARMv8 MVFR registers Peter Maydell
                   ` (18 subsequent siblings)
  37 siblings, 0 replies; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

From: Rob Herring <rob.herring@linaro.org>

Implement exception handling for AArch64 EL1. Exceptions from AArch64 or
AArch32 EL0 are supported.

Signed-off-by: Rob Herring <rob.herring@linaro.org>
[PMM: fixed minor style nits; updated to match changes in
 previous patches; added some of the simpler cases of
 illegal-exception-return support]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/cpu-qom.h       |  2 ++
 target-arm/cpu64.c         |  1 +
 target-arm/helper-a64.c    | 75 ++++++++++++++++++++++++++++++++++++++++++++++
 target-arm/helper.h        |  1 +
 target-arm/op_helper.c     | 60 +++++++++++++++++++++++++++++++++++++
 target-arm/translate-a64.c |  3 ++
 6 files changed, 142 insertions(+)

diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
index 41caa6c..afdee9d 100644
--- a/target-arm/cpu-qom.h
+++ b/target-arm/cpu-qom.h
@@ -202,6 +202,8 @@ void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
                             fprintf_function cpu_fprintf, int flags);
 int aarch64_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
 int aarch64_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+
+void aarch64_cpu_do_interrupt(CPUState *cs);
 #endif
 
 #endif
diff --git a/target-arm/cpu64.c b/target-arm/cpu64.c
index fccecc2..d4fb1de 100644
--- a/target-arm/cpu64.c
+++ b/target-arm/cpu64.c
@@ -85,6 +85,7 @@ static void aarch64_cpu_class_init(ObjectClass *oc, void *data)
 {
     CPUClass *cc = CPU_CLASS(oc);
 
+    cc->do_interrupt = aarch64_cpu_do_interrupt;
     cc->dump_state = aarch64_cpu_dump_state;
     cc->set_pc = aarch64_cpu_set_pc;
     cc->gdb_read_register = aarch64_cpu_gdb_read_register;
diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c
index ec02582..1a82056 100644
--- a/target-arm/helper-a64.c
+++ b/target-arm/helper-a64.c
@@ -23,6 +23,7 @@
 #include "qemu/host-utils.h"
 #include "sysemu/sysemu.h"
 #include "qemu/bitops.h"
+#include "internals.h"
 
 /* C2.4.7 Multiply and divide */
 /* special cases for 0 and LLONG_MIN are mandated by the standard */
@@ -436,3 +437,77 @@ float32 HELPER(fcvtx_f64_to_f32)(float64 a, CPUARMState *env)
     set_float_exception_flags(exflags, fpst);
     return r;
 }
+
+/* Handle a CPU exception.  */
+void aarch64_cpu_do_interrupt(CPUState *cs)
+{
+    ARMCPU *cpu = ARM_CPU(cs);
+    CPUARMState *env = &cpu->env;
+    target_ulong addr = env->cp15.c12_vbar;
+    int i;
+
+    if (arm_current_pl(env) == 0) {
+        if (env->aarch64) {
+            addr += 0x400;
+        } else {
+            addr += 0x600;
+        }
+    } else if (pstate_read(env) & PSTATE_SP) {
+        addr += 0x200;
+    }
+
+    arm_log_exception(cs->exception_index);
+    qemu_log_mask(CPU_LOG_INT, "...from EL%d\n", arm_current_pl(env));
+    if (qemu_loglevel_mask(CPU_LOG_INT)
+        && !excp_is_internal(cs->exception_index)) {
+        qemu_log_mask(CPU_LOG_INT, "...with ESR 0x%" PRIx32 "\n",
+                      env->exception.syndrome);
+    }
+
+    env->cp15.esr_el1 = env->exception.syndrome;
+    env->cp15.far_el1 = env->exception.vaddress;
+
+    switch (cs->exception_index) {
+    case EXCP_PREFETCH_ABORT:
+    case EXCP_DATA_ABORT:
+        qemu_log_mask(CPU_LOG_INT, "...with FAR 0x%" PRIx64 "\n",
+                      env->cp15.far_el1);
+    case EXCP_BKPT:
+    case EXCP_UDEF:
+    case EXCP_SWI:
+        break;
+    case EXCP_IRQ:
+        addr += 0x80;
+        break;
+    case EXCP_FIQ:
+        addr += 0x100;
+        break;
+    default:
+        cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
+    }
+
+    if (is_a64(env)) {
+        env->banked_spsr[0] = pstate_read(env);
+        env->sp_el[arm_current_pl(env)] = env->xregs[31];
+        env->xregs[31] = env->sp_el[1];
+        env->elr_el1 = env->pc;
+    } else {
+        env->banked_spsr[0] = cpsr_read(env);
+        if (!env->thumb) {
+            env->cp15.esr_el1 |= 1 << 25;
+        }
+        env->elr_el1 = env->regs[15];
+
+        for (i = 0; i < 15; i++) {
+            env->xregs[i] = env->regs[i];
+        }
+
+        env->condexec_bits = 0;
+    }
+
+    pstate_write(env, PSTATE_DAIF | PSTATE_MODE_EL1h);
+    env->aarch64 = 1;
+
+    env->pc = addr;
+    cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
+}
diff --git a/target-arm/helper.h b/target-arm/helper.h
index 5977169..a5449e7 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -66,6 +66,7 @@ DEF_HELPER_3(set_cp_reg64, void, env, ptr, i64)
 DEF_HELPER_2(get_cp_reg64, i64, env, ptr)
 
 DEF_HELPER_3(msr_i_pstate, void, env, i32, i32)
+DEF_HELPER_1(exception_return, void, env)
 
 DEF_HELPER_2(get_r13_banked, i32, env, i32)
 DEF_HELPER_3(set_r13_banked, void, env, i32, i32)
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 64a33dd..57e7d9c 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -384,6 +384,66 @@ void HELPER(msr_i_pstate)(CPUARMState *env, uint32_t op, uint32_t imm)
     }
 }
 
+void HELPER(exception_return)(CPUARMState *env)
+{
+    uint32_t spsr = env->banked_spsr[0];
+    int new_el, i;
+
+    if (env->pstate & PSTATE_SP) {
+        env->sp_el[1] = env->xregs[31];
+    } else {
+        env->sp_el[0] = env->xregs[31];
+    }
+
+    env->exclusive_addr = -1;
+
+    if (spsr & PSTATE_nRW) {
+        env->aarch64 = 0;
+        new_el = 0;
+        env->uncached_cpsr = 0x10;
+        cpsr_write(env, spsr, ~0);
+        for (i = 0; i < 15; i++) {
+            env->regs[i] = env->xregs[i];
+        }
+
+        env->regs[15] = env->elr_el1 & ~0x1;
+    } else {
+        new_el = extract32(spsr, 2, 2);
+        if (new_el > 1) {
+            /* Return to unimplemented EL */
+            goto illegal_return;
+        }
+        if (extract32(spsr, 1, 1)) {
+            /* Return with reserved M[1] bit set */
+            goto illegal_return;
+        }
+        if (new_el == 0 && (spsr & PSTATE_SP)) {
+            /* Return to EL1 with M[0] bit set */
+            goto illegal_return;
+        }
+        env->aarch64 = 1;
+        pstate_write(env, spsr);
+        env->xregs[31] = env->sp_el[new_el];
+        env->pc = env->elr_el1;
+    }
+
+    return;
+
+illegal_return:
+    /* Illegal return events of various kinds have architecturally
+     * mandated behaviour:
+     * restore NZCV and DAIF from SPSR_ELx
+     * set PSTATE.IL
+     * restore PC from ELR_ELx
+     * no change to exception level, execution state or stack pointer
+     */
+    env->pstate |= PSTATE_IL;
+    env->pc = env->elr_el1;
+    spsr &= PSTATE_NZCV | PSTATE_DAIF;
+    spsr |= pstate_read(env) & ~(PSTATE_NZCV | PSTATE_DAIF);
+    pstate_write(env, spsr);
+}
+
 /* ??? Flag setting arithmetic is awkward because we need to do comparisons.
    The only way to do that in TCG is a conditional branch, which clobbers
    all our temporaries.  For now implement these as helper functions.  */
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 4c5402a..188287d 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -1512,6 +1512,9 @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
         tcg_gen_movi_i64(cpu_reg(s, 30), s->pc);
         break;
     case 4: /* ERET */
+        gen_helper_exception_return(cpu_env);
+        s->is_jmp = DISAS_JUMP;
+        return;
     case 5: /* DRPS */
         if (rn != 0x1f) {
             unallocated_encoding(s);
-- 
1.9.1

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

* [Qemu-devel] [PATCH v6 20/37] target-arm: Implement ARMv8 MVFR registers
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
                   ` (18 preceding siblings ...)
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 19/37] target-arm: Implement AArch64 EL1 exception handling Peter Maydell
@ 2014-04-10 16:15 ` Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 21/37] target-arm: Add Cortex-A57 processor Peter Maydell
                   ` (17 subsequent siblings)
  37 siblings, 0 replies; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

For ARMv8 there are two changes to the MVFR media feature registers:
 * there is a new MVFR2 which is accessible from 32 bit code
 * 64 bit code accesses these via the usual sysreg instructions
   rather than with a floating-point specific instruction

Implement this.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/cpu-qom.h   |  1 +
 target-arm/cpu.c       |  1 +
 target-arm/cpu.h       |  1 +
 target-arm/helper.c    | 12 ++++++++++++
 target-arm/translate.c | 10 ++++++++--
 5 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
index afdee9d..2b6b370 100644
--- a/target-arm/cpu-qom.h
+++ b/target-arm/cpu-qom.h
@@ -116,6 +116,7 @@ typedef struct ARMCPU {
     uint32_t reset_fpsid;
     uint32_t mvfr0;
     uint32_t mvfr1;
+    uint32_t mvfr2;
     uint32_t ctr;
     uint32_t reset_sctlr;
     uint32_t id_pfr0;
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index a3c7492..a78a36b 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -88,6 +88,7 @@ static void arm_cpu_reset(CPUState *s)
     env->vfp.xregs[ARM_VFP_FPSID] = cpu->reset_fpsid;
     env->vfp.xregs[ARM_VFP_MVFR0] = cpu->mvfr0;
     env->vfp.xregs[ARM_VFP_MVFR1] = cpu->mvfr1;
+    env->vfp.xregs[ARM_VFP_MVFR2] = cpu->mvfr2;
 
     if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
         env->iwmmxt.cregs[ARM_IWMMXT_wCID] = 0x69051000 | 'Q';
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 0ce4c26..ec0306b 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -572,6 +572,7 @@ enum arm_cpu_mode {
 /* VFP system registers.  */
 #define ARM_VFP_FPSID   0
 #define ARM_VFP_FPSCR   1
+#define ARM_VFP_MVFR2   5
 #define ARM_VFP_MVFR1   6
 #define ARM_VFP_MVFR0   7
 #define ARM_VFP_FPEXC   8
diff --git a/target-arm/helper.c b/target-arm/helper.c
index e9b64f3..cf5fab8 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2155,6 +2155,18 @@ void register_cp_regs_for_features(ARMCPU *cpu)
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 1,
               .access = PL1_R, .type = ARM_CP_CONST,
               .resetvalue = cpu->id_aa64mmfr1 },
+            { .name = "MVFR0_EL1", .state = ARM_CP_STATE_AA64,
+              .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 0,
+              .access = PL1_R, .type = ARM_CP_CONST,
+              .resetvalue = cpu->mvfr0 },
+            { .name = "MVFR1_EL1", .state = ARM_CP_STATE_AA64,
+              .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 1,
+              .access = PL1_R, .type = ARM_CP_CONST,
+              .resetvalue = cpu->mvfr1 },
+            { .name = "MVFR2_EL1", .state = ARM_CP_STATE_AA64,
+              .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 2,
+              .access = PL1_R, .type = ARM_CP_CONST,
+              .resetvalue = cpu->mvfr2 },
             REGINFO_SENTINEL
         };
         define_arm_cp_regs(cpu, v8_idregs);
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 03e2c00..f7b5daf 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -2967,9 +2967,10 @@ static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
         if ((insn & 0x0fe00fff) != 0x0ee00a10)
             return 1;
         rn = (insn >> 16) & 0xf;
-        if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
-            && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
+        if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC && rn != ARM_VFP_MVFR2
+            && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0) {
             return 1;
+        }
     }
 
     if (extract32(insn, 28, 4) == 0xf) {
@@ -3115,6 +3116,11 @@ static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
                                 gen_helper_vfp_get_fpscr(tmp, cpu_env);
                             }
                             break;
+                        case ARM_VFP_MVFR2:
+                            if (!arm_feature(env, ARM_FEATURE_V8)) {
+                                return 1;
+                            }
+                            /* fall through */
                         case ARM_VFP_MVFR0:
                         case ARM_VFP_MVFR1:
                             if (IS_USER(s)
-- 
1.9.1

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

* [Qemu-devel] [PATCH v6 21/37] target-arm: Add Cortex-A57 processor
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
                   ` (19 preceding siblings ...)
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 20/37] target-arm: Implement ARMv8 MVFR registers Peter Maydell
@ 2014-04-10 16:15 ` Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 22/37] hw/arm/virt: Add support for Cortex-A57 Peter Maydell
                   ` (16 subsequent siblings)
  37 siblings, 0 replies; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

Add Cortex-A57 processor.

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

diff --git a/target-arm/cpu64.c b/target-arm/cpu64.c
index d4fb1de..5be7d72 100644
--- a/target-arm/cpu64.c
+++ b/target-arm/cpu64.c
@@ -32,6 +32,48 @@ static inline void set_feature(CPUARMState *env, int feature)
     env->features |= 1ULL << feature;
 }
 
+static void aarch64_a57_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+
+    set_feature(&cpu->env, ARM_FEATURE_V8);
+    set_feature(&cpu->env, ARM_FEATURE_VFP4);
+    set_feature(&cpu->env, ARM_FEATURE_VFP_FP16);
+    set_feature(&cpu->env, ARM_FEATURE_NEON);
+    set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
+    set_feature(&cpu->env, ARM_FEATURE_AARCH64);
+    cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A57;
+    cpu->midr = 0x411fd070;
+    cpu->reset_fpsid = 0x41034070;
+    cpu->mvfr0 = 0x10110222;
+    cpu->mvfr1 = 0x12111111;
+    cpu->mvfr2 = 0x00000043;
+    cpu->ctr = 0x8444c004;
+    cpu->reset_sctlr = 0x00c50838;
+    cpu->id_pfr0 = 0x00000131;
+    cpu->id_pfr1 = 0x00011011;
+    cpu->id_dfr0 = 0x03010066;
+    cpu->id_afr0 = 0x00000000;
+    cpu->id_mmfr0 = 0x10101105;
+    cpu->id_mmfr1 = 0x40000000;
+    cpu->id_mmfr2 = 0x01260000;
+    cpu->id_mmfr3 = 0x02102211;
+    cpu->id_isar0 = 0x02101110;
+    cpu->id_isar1 = 0x13112111;
+    cpu->id_isar2 = 0x21232042;
+    cpu->id_isar3 = 0x01112131;
+    cpu->id_isar4 = 0x00011142;
+    cpu->id_aa64pfr0 = 0x00002222;
+    cpu->id_aa64dfr0 = 0x10305106;
+    cpu->id_aa64isar0 = 0x00010000;
+    cpu->id_aa64mmfr0 = 0x00001124;
+    cpu->clidr = 0x0a200023;
+    cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */
+    cpu->ccsidr[1] = 0x201fe012; /* 48KB L1 icache */
+    cpu->ccsidr[2] = 0x70ffe07a; /* 2048KB L2 cache */
+    cpu->dcz_blocksize = 4; /* 64 bytes */
+}
+
 #ifdef CONFIG_USER_ONLY
 static void aarch64_any_initfn(Object *obj)
 {
@@ -57,6 +99,7 @@ typedef struct ARMCPUInfo {
 } ARMCPUInfo;
 
 static const ARMCPUInfo aarch64_cpus[] = {
+    { .name = "cortex-a57",         .initfn = aarch64_a57_initfn },
 #ifdef CONFIG_USER_ONLY
     { .name = "any",         .initfn = aarch64_any_initfn },
 #endif
-- 
1.9.1

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

* [Qemu-devel] [PATCH v6 22/37] hw/arm/virt: Add support for Cortex-A57
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
                   ` (20 preceding siblings ...)
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 21/37] target-arm: Add Cortex-A57 processor Peter Maydell
@ 2014-04-10 16:15 ` Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 23/37] target-arm: Implement AArch64 views of AArch32 ID registers Peter Maydell
                   ` (15 subsequent siblings)
  37 siblings, 0 replies; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

Support the Cortex-A57 in the virt machine model.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
This should perhaps not be just stealing the a15mpcore_priv
on the basis that it's a GICv2...
---
 hw/arm/virt.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 2bbc931..e23868a 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -123,6 +123,14 @@ static VirtBoardInfo machines[] = {
         .irqmap = a15irqmap,
     },
     {
+        .cpu_model = "cortex-a57",
+        /* Our A57 has an A15-style GICv2, so we can use a15mpcore_priv */
+        .qdevname = "a15mpcore_priv",
+        .gic_compatible = "arm,cortex-a15-gic",
+        .memmap = a15memmap,
+        .irqmap = a15irqmap,
+    },
+    {
         .cpu_model = "host",
         /* We use the A15 private peripheral model to get a V2 GIC */
         .qdevname = "a15mpcore_priv",
-- 
1.9.1

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

* [Qemu-devel] [PATCH v6 23/37] target-arm: Implement AArch64 views of AArch32 ID registers
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
                   ` (21 preceding siblings ...)
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 22/37] hw/arm/virt: Add support for Cortex-A57 Peter Maydell
@ 2014-04-10 16:15 ` Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 24/37] target-arm: Implement AArch64 view of CONTEXTIDR Peter Maydell
                   ` (14 subsequent siblings)
  37 siblings, 0 replies; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

All the AArch32 ID registers are visible from AArch64
(in addition to the AArch64-specific ID_AA64* registers).

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

diff --git a/target-arm/helper.c b/target-arm/helper.c
index cf5fab8..655c5ab 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -745,7 +745,8 @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
     /* Auxiliary ID register: this actually has an IMPDEF value but for now
      * just RAZ for all cores:
      */
-    { .name = "AIDR", .cp = 15, .crn = 0, .crm = 0, .opc1 = 1, .opc2 = 7,
+    { .name = "AIDR", .state = ARM_CP_STATE_BOTH,
+      .opc0 = 3, .opc1 = 1, .crn = 0, .crm = 0, .opc2 = 7,
       .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
     /* MAIR can just read-as-written because we don't implement caches
      * and so don't need to care about memory attributes.
@@ -2022,47 +2023,61 @@ void register_cp_regs_for_features(ARMCPU *cpu)
     if (arm_feature(env, ARM_FEATURE_V6)) {
         /* The ID registers all have impdef reset values */
         ARMCPRegInfo v6_idregs[] = {
-            { .name = "ID_PFR0", .cp = 15, .crn = 0, .crm = 1,
-              .opc1 = 0, .opc2 = 0, .access = PL1_R, .type = ARM_CP_CONST,
+            { .name = "ID_PFR0", .state = ARM_CP_STATE_BOTH,
+              .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 0,
+              .access = PL1_R, .type = ARM_CP_CONST,
               .resetvalue = cpu->id_pfr0 },
-            { .name = "ID_PFR1", .cp = 15, .crn = 0, .crm = 1,
-              .opc1 = 0, .opc2 = 1, .access = PL1_R, .type = ARM_CP_CONST,
+            { .name = "ID_PFR1", .state = ARM_CP_STATE_BOTH,
+              .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 1,
+              .access = PL1_R, .type = ARM_CP_CONST,
               .resetvalue = cpu->id_pfr1 },
-            { .name = "ID_DFR0", .cp = 15, .crn = 0, .crm = 1,
-              .opc1 = 0, .opc2 = 2, .access = PL1_R, .type = ARM_CP_CONST,
+            { .name = "ID_DFR0", .state = ARM_CP_STATE_BOTH,
+              .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 2,
+              .access = PL1_R, .type = ARM_CP_CONST,
               .resetvalue = cpu->id_dfr0 },
-            { .name = "ID_AFR0", .cp = 15, .crn = 0, .crm = 1,
-              .opc1 = 0, .opc2 = 3, .access = PL1_R, .type = ARM_CP_CONST,
+            { .name = "ID_AFR0", .state = ARM_CP_STATE_BOTH,
+              .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 3,
+              .access = PL1_R, .type = ARM_CP_CONST,
               .resetvalue = cpu->id_afr0 },
-            { .name = "ID_MMFR0", .cp = 15, .crn = 0, .crm = 1,
-              .opc1 = 0, .opc2 = 4, .access = PL1_R, .type = ARM_CP_CONST,
+            { .name = "ID_MMFR0", .state = ARM_CP_STATE_BOTH,
+              .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 4,
+              .access = PL1_R, .type = ARM_CP_CONST,
               .resetvalue = cpu->id_mmfr0 },
-            { .name = "ID_MMFR1", .cp = 15, .crn = 0, .crm = 1,
-              .opc1 = 0, .opc2 = 5, .access = PL1_R, .type = ARM_CP_CONST,
+            { .name = "ID_MMFR1", .state = ARM_CP_STATE_BOTH,
+              .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 5,
+              .access = PL1_R, .type = ARM_CP_CONST,
               .resetvalue = cpu->id_mmfr1 },
-            { .name = "ID_MMFR2", .cp = 15, .crn = 0, .crm = 1,
-              .opc1 = 0, .opc2 = 6, .access = PL1_R, .type = ARM_CP_CONST,
+            { .name = "ID_MMFR2", .state = ARM_CP_STATE_BOTH,
+              .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 6,
+              .access = PL1_R, .type = ARM_CP_CONST,
               .resetvalue = cpu->id_mmfr2 },
-            { .name = "ID_MMFR3", .cp = 15, .crn = 0, .crm = 1,
-              .opc1 = 0, .opc2 = 7, .access = PL1_R, .type = ARM_CP_CONST,
+            { .name = "ID_MMFR3", .state = ARM_CP_STATE_BOTH,
+              .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 7,
+              .access = PL1_R, .type = ARM_CP_CONST,
               .resetvalue = cpu->id_mmfr3 },
-            { .name = "ID_ISAR0", .cp = 15, .crn = 0, .crm = 2,
-              .opc1 = 0, .opc2 = 0, .access = PL1_R, .type = ARM_CP_CONST,
+            { .name = "ID_ISAR0", .state = ARM_CP_STATE_BOTH,
+              .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 0,
+              .access = PL1_R, .type = ARM_CP_CONST,
               .resetvalue = cpu->id_isar0 },
-            { .name = "ID_ISAR1", .cp = 15, .crn = 0, .crm = 2,
-              .opc1 = 0, .opc2 = 1, .access = PL1_R, .type = ARM_CP_CONST,
+            { .name = "ID_ISAR1", .state = ARM_CP_STATE_BOTH,
+              .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 1,
+              .access = PL1_R, .type = ARM_CP_CONST,
               .resetvalue = cpu->id_isar1 },
-            { .name = "ID_ISAR2", .cp = 15, .crn = 0, .crm = 2,
-              .opc1 = 0, .opc2 = 2, .access = PL1_R, .type = ARM_CP_CONST,
+            { .name = "ID_ISAR2", .state = ARM_CP_STATE_BOTH,
+              .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 2,
+              .access = PL1_R, .type = ARM_CP_CONST,
               .resetvalue = cpu->id_isar2 },
-            { .name = "ID_ISAR3", .cp = 15, .crn = 0, .crm = 2,
-              .opc1 = 0, .opc2 = 3, .access = PL1_R, .type = ARM_CP_CONST,
+            { .name = "ID_ISAR3", .state = ARM_CP_STATE_BOTH,
+              .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 3,
+              .access = PL1_R, .type = ARM_CP_CONST,
               .resetvalue = cpu->id_isar3 },
-            { .name = "ID_ISAR4", .cp = 15, .crn = 0, .crm = 2,
-              .opc1 = 0, .opc2 = 4, .access = PL1_R, .type = ARM_CP_CONST,
+            { .name = "ID_ISAR4", .state = ARM_CP_STATE_BOTH,
+              .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 4,
+              .access = PL1_R, .type = ARM_CP_CONST,
               .resetvalue = cpu->id_isar4 },
-            { .name = "ID_ISAR5", .cp = 15, .crn = 0, .crm = 2,
-              .opc1 = 0, .opc2 = 5, .access = PL1_R, .type = ARM_CP_CONST,
+            { .name = "ID_ISAR5", .state = ARM_CP_STATE_BOTH,
+              .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 5,
+              .access = PL1_R, .type = ARM_CP_CONST,
               .resetvalue = cpu->id_isar5 },
             /* 6..7 are as yet unallocated and must RAZ */
             { .name = "ID_ISAR6", .cp = 15, .crn = 0, .crm = 2,
-- 
1.9.1

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

* [Qemu-devel] [PATCH v6 24/37] target-arm: Implement AArch64 view of CONTEXTIDR
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
                   ` (22 preceding siblings ...)
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 23/37] target-arm: Implement AArch64 views of AArch32 ID registers Peter Maydell
@ 2014-04-10 16:15 ` Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 25/37] target-arm: Implement AArch64 view of ACTLR Peter Maydell
                   ` (13 subsequent siblings)
  37 siblings, 0 replies; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

Implement AArch64 view of the CONTEXTIDR register.
We tighten up the condition when we flush the TLB on a CONTEXTIDR
write to avoid needlessly flushing the TLB every time on a 64
bit system (and also on a 32 bit system using LPAE, as a bonus).

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

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index ec0306b..d0f42fd 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -201,7 +201,7 @@ typedef struct CPUARMState {
         uint64_t mair_el1;
         uint64_t c12_vbar; /* vector base address register */
         uint32_t c13_fcse; /* FCSE PID.  */
-        uint32_t c13_context; /* Context ID.  */
+        uint64_t contextidr_el1; /* Context ID.  */
         uint64_t tpidr_el0; /* User RW Thread register.  */
         uint64_t tpidrro_el0; /* User RO Thread register.  */
         uint64_t tpidr_el1; /* Privileged Thread register.  */
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 655c5ab..10300aa 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -304,6 +304,17 @@ void init_cpreg_list(ARMCPU *cpu)
     g_list_free(keys);
 }
 
+/* Return true if extended addresses are enabled.
+ * This is always the case if our translation regime is 64 bit,
+ * but depends on TTBCR.EAE for 32 bit.
+ */
+static inline bool extended_addresses_enabled(CPUARMState *env)
+{
+    return arm_el_is_aa64(env, 1)
+        || ((arm_feature(env, ARM_FEATURE_LPAE)
+             && (env->cp15.c2_control & (1U << 31))));
+}
+
 static void dacr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
 {
     ARMCPU *cpu = arm_env_get_cpu(env);
@@ -330,14 +341,15 @@ static void contextidr_write(CPUARMState *env, const ARMCPRegInfo *ri,
 {
     ARMCPU *cpu = arm_env_get_cpu(env);
 
-    if (env->cp15.c13_context != value && !arm_feature(env, ARM_FEATURE_MPU)) {
+    if (env->cp15.contextidr_el1 != value && !arm_feature(env, ARM_FEATURE_MPU)
+        && !extended_addresses_enabled(env)) {
         /* For VMSA (when not using the LPAE long descriptor page table
          * format) this register includes the ASID, so do a TLB flush.
          * For PMSA it is purely a process ID and no action is needed.
          */
         tlb_flush(CPU(cpu), 1);
     }
-    env->cp15.c13_context = value;
+    env->cp15.contextidr_el1 = value;
 }
 
 static void tlbiall_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -391,8 +403,10 @@ static const ARMCPRegInfo cp_reginfo[] = {
     { .name = "FCSEIDR", .cp = 15, .crn = 13, .crm = 0, .opc1 = 0, .opc2 = 0,
       .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c13_fcse),
       .resetvalue = 0, .writefn = fcse_write, .raw_writefn = raw_write, },
-    { .name = "CONTEXTIDR", .cp = 15, .crn = 13, .crm = 0, .opc1 = 0, .opc2 = 1,
-      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c13_context),
+    { .name = "CONTEXTIDR", .state = ARM_CP_STATE_BOTH,
+      .opc0 = 3, .opc1 = 0, .crn = 13, .crm = 0, .opc2 = 1,
+      .access = PL1_RW,
+      .fieldoffset = offsetof(CPUARMState, cp15.contextidr_el1),
       .resetvalue = 0, .writefn = contextidr_write, .raw_writefn = raw_write, },
     /* ??? This covers not just the impdef TLB lockdown registers but also
      * some v7VMSA registers relating to TEX remap, so it is overly broad.
@@ -1155,17 +1169,6 @@ static void par_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
 #ifndef CONFIG_USER_ONLY
 /* get_phys_addr() isn't present for user-mode-only targets */
 
-/* Return true if extended addresses are enabled.
- * This is always the case if our translation regime is 64 bit,
- * but depends on TTBCR.EAE for 32 bit.
- */
-static inline bool extended_addresses_enabled(CPUARMState *env)
-{
-    return arm_el_is_aa64(env, 1)
-        || ((arm_feature(env, ARM_FEATURE_LPAE)
-             && (env->cp15.c2_control & (1U << 31))));
-}
-
 static CPAccessResult ats_access(CPUARMState *env, const ARMCPRegInfo *ri)
 {
     if (ri->opc2 & 4) {
-- 
1.9.1

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

* [Qemu-devel] [PATCH v6 25/37] target-arm: Implement AArch64 view of ACTLR
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
                   ` (23 preceding siblings ...)
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 24/37] target-arm: Implement AArch64 view of CONTEXTIDR Peter Maydell
@ 2014-04-10 16:15 ` Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 26/37] target-arm: Implement ISR_EL1 register Peter Maydell
                   ` (12 subsequent siblings)
  37 siblings, 0 replies; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

Implement the AArch64 view of the ACTLR (auxiliary control
register). Note that QEMU internally tends to call this
AUXCR for historical reasons.

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

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 10300aa..f2e6f17 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2316,7 +2316,8 @@ void register_cp_regs_for_features(ARMCPU *cpu)
 
     if (arm_feature(env, ARM_FEATURE_AUXCR)) {
         ARMCPRegInfo auxcr = {
-            .name = "AUXCR", .cp = 15, .crn = 1, .crm = 0, .opc1 = 0, .opc2 = 1,
+            .name = "AUXCR", .state = ARM_CP_STATE_BOTH,
+            .opc0 = 3, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 1,
             .access = PL1_RW, .type = ARM_CP_CONST,
             .resetvalue = cpu->reset_auxcr
         };
-- 
1.9.1

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

* [Qemu-devel] [PATCH v6 26/37] target-arm: Implement ISR_EL1 register
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
                   ` (24 preceding siblings ...)
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 25/37] target-arm: Implement AArch64 view of ACTLR Peter Maydell
@ 2014-04-10 16:15 ` Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 27/37] target-arm: Remove THUMB2EE feature from AArch64 'any' CPU Peter Maydell
                   ` (11 subsequent siblings)
  37 siblings, 0 replies; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

Implement the ISR_EL1 register. This is actually present in
ARMv7 as well but was previously unimplemented. It is a
read-only register that indicates whether interrupts are
currently pending.

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

diff --git a/target-arm/helper.c b/target-arm/helper.c
index f2e6f17..398c8f5 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -665,6 +665,21 @@ static void csselr_write(CPUARMState *env, const ARMCPRegInfo *ri,
     env->cp15.c0_cssel = value & 0xf;
 }
 
+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 (cs->interrupt_request & CPU_INTERRUPT_FIQ) {
+        ret |= CPSR_F;
+    }
+    /* External aborts are not possible in QEMU so A bit is always clear */
+    return ret;
+}
+
 static const ARMCPRegInfo v7_cp_reginfo[] = {
     /* DBGDRAR, DBGDSAR: always RAZ since we don't implement memory mapped
      * debug components
@@ -782,6 +797,9 @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
       .cp = 15, .opc1 = 0, .crn = 10, .crm = 2, .opc2 = 1, .access = PL1_RW,
       .fieldoffset = offsetofhigh32(CPUARMState, cp15.mair_el1),
       .resetfn = arm_cp_reset_ignore },
+    { .name = "ISR_EL1", .state = ARM_CP_STATE_BOTH,
+      .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 1, .opc2 = 0,
+      .type = ARM_CP_NO_MIGRATE, .access = PL1_R, .readfn = isr_read },
     REGINFO_SENTINEL
 };
 
-- 
1.9.1

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

* [Qemu-devel] [PATCH v6 27/37] target-arm: Remove THUMB2EE feature from AArch64 'any' CPU
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
                   ` (25 preceding siblings ...)
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 26/37] target-arm: Implement ISR_EL1 register Peter Maydell
@ 2014-04-10 16:15 ` Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 28/37] target-arm: Don't expose wildcard ID register definitions for ARMv8 Peter Maydell
                   ` (10 subsequent siblings)
  37 siblings, 0 replies; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

The AArch64 usermode 'any' CPU type was accidentally specified
with the ARM_FEATURE_THUMB2EE bit set. This is incorrect since
ARMv8 removes Thumb2EE completely. Since we never implemented
Thumb2EE anyway having the feature bit set was fairly harmless
for user-mode, but the correct thing is to not set it at all.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
 target-arm/cpu64.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/target-arm/cpu64.c b/target-arm/cpu64.c
index 5be7d72..b8b4fa6 100644
--- a/target-arm/cpu64.c
+++ b/target-arm/cpu64.c
@@ -83,7 +83,6 @@ static void aarch64_any_initfn(Object *obj)
     set_feature(&cpu->env, ARM_FEATURE_VFP4);
     set_feature(&cpu->env, ARM_FEATURE_VFP_FP16);
     set_feature(&cpu->env, ARM_FEATURE_NEON);
-    set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
     set_feature(&cpu->env, ARM_FEATURE_ARM_DIV);
     set_feature(&cpu->env, ARM_FEATURE_V7MP);
     set_feature(&cpu->env, ARM_FEATURE_AARCH64);
-- 
1.9.1

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

* [Qemu-devel] [PATCH v6 28/37] target-arm: Don't expose wildcard ID register definitions for ARMv8
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
                   ` (26 preceding siblings ...)
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 27/37] target-arm: Remove THUMB2EE feature from AArch64 'any' CPU Peter Maydell
@ 2014-04-10 16:15 ` Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 29/37] target-arm: Replace wildcarded cpreg definitions with precise ones " Peter Maydell
                   ` (9 subsequent siblings)
  37 siblings, 0 replies; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

In ARMv8 the 32 bit coprocessor ID register space is tidied up to
remove the wildcarded aliases of the MIDR and the RAZ behaviour
for the unassigned space where crm = 3..7. Make sure we don't
expose thes wildcards for v8 cores. This means we need to have
a specific implementation for REVIDR, an IMPDEF register which
may be the same as the MIDR (and which we always implement as such).

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

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 398c8f5..20952c3 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2258,8 +2258,9 @@ void register_cp_regs_for_features(ARMCPU *cpu)
      * be read-only (ie write causes UNDEF exception).
      */
     {
-        ARMCPRegInfo id_cp_reginfo[] = {
-            /* Note that the MIDR isn't a simple constant register because
+        ARMCPRegInfo id_old_midr_cp_reginfo[] = {
+            /* Pre-v8 MIDR space.
+             * Note that the MIDR isn't a simple constant register because
              * of the TI925 behaviour where writes to another register can
              * cause the MIDR value to change.
              *
@@ -2273,22 +2274,6 @@ void register_cp_regs_for_features(ARMCPU *cpu)
               .writefn = arm_cp_write_ignore, .raw_writefn = raw_write,
               .fieldoffset = offsetof(CPUARMState, cp15.c0_cpuid),
               .type = ARM_CP_OVERRIDE },
-            { .name = "MIDR_EL1", .state = ARM_CP_STATE_AA64,
-              .opc0 = 3, .opc1 = 0, .opc2 = 0, .crn = 0, .crm = 0,
-              .access = PL1_R, .resetvalue = cpu->midr, .type = ARM_CP_CONST },
-            { .name = "CTR",
-              .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 1,
-              .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = cpu->ctr },
-            { .name = "CTR_EL0", .state = ARM_CP_STATE_AA64,
-              .opc0 = 3, .opc1 = 3, .opc2 = 1, .crn = 0, .crm = 0,
-              .access = PL0_R, .accessfn = ctr_el0_access,
-              .type = ARM_CP_CONST, .resetvalue = cpu->ctr },
-            { .name = "TCMTR",
-              .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 2,
-              .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
-            { .name = "TLBTR",
-              .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 3,
-              .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
             /* crn = 0 op1 = 0 crm = 3..7 : currently unassigned; we RAZ. */
             { .name = "DUMMY",
               .cp = 15, .crn = 0, .crm = 3, .opc1 = 0, .opc2 = CP_ANY,
@@ -2307,6 +2292,37 @@ void register_cp_regs_for_features(ARMCPU *cpu)
               .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
             REGINFO_SENTINEL
         };
+        ARMCPRegInfo id_v8_midr_cp_reginfo[] = {
+            /* v8 MIDR -- the wildcard isn't necessary, and nor is the
+             * variable-MIDR TI925 behaviour. Instead we have a single
+             * (strictly speaking IMPDEF) alias of the MIDR, REVIDR.
+             */
+            { .name = "MIDR_EL1", .state = ARM_CP_STATE_BOTH,
+              .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 0, .opc2 = 0,
+              .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = cpu->midr },
+            { .name = "REVIDR_EL1", .state = ARM_CP_STATE_BOTH,
+              .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 0, .opc2 = 6,
+              .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = cpu->midr },
+            REGINFO_SENTINEL
+        };
+        ARMCPRegInfo id_cp_reginfo[] = {
+            /* These are common to v8 and pre-v8 */
+            { .name = "CTR",
+              .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 1,
+              .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = cpu->ctr },
+            { .name = "CTR_EL0", .state = ARM_CP_STATE_AA64,
+              .opc0 = 3, .opc1 = 3, .opc2 = 1, .crn = 0, .crm = 0,
+              .access = PL0_R, .accessfn = ctr_el0_access,
+              .type = ARM_CP_CONST, .resetvalue = cpu->ctr },
+            /* TCMTR and TLBTR exist in v8 but have no 64-bit versions */
+            { .name = "TCMTR",
+              .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 2,
+              .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
+            { .name = "TLBTR",
+              .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 3,
+              .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
+            REGINFO_SENTINEL
+        };
         ARMCPRegInfo crn0_wi_reginfo = {
             .name = "CRN0_WI", .cp = 15, .crn = 0, .crm = CP_ANY,
             .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_W,
@@ -2321,10 +2337,18 @@ void register_cp_regs_for_features(ARMCPU *cpu)
              * UNDEF.
              */
             define_one_arm_cp_reg(cpu, &crn0_wi_reginfo);
+            for (r = id_old_midr_cp_reginfo; r->type != ARM_CP_SENTINEL; r++) {
+                r->access = PL1_RW;
+            }
             for (r = id_cp_reginfo; r->type != ARM_CP_SENTINEL; r++) {
                 r->access = PL1_RW;
             }
         }
+        if (arm_feature(env, ARM_FEATURE_V8)) {
+            define_arm_cp_regs(cpu, id_v8_midr_cp_reginfo);
+        } else {
+            define_arm_cp_regs(cpu, id_old_midr_cp_reginfo);
+        }
         define_arm_cp_regs(cpu, id_cp_reginfo);
     }
 
-- 
1.9.1

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

* [Qemu-devel] [PATCH v6 29/37] target-arm: Replace wildcarded cpreg definitions with precise ones for ARMv8
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
                   ` (27 preceding siblings ...)
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 28/37] target-arm: Don't expose wildcard ID register definitions for ARMv8 Peter Maydell
@ 2014-04-10 16:15 ` Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 30/37] target-arm: Implement auxiliary fault status registers Peter Maydell
                   ` (8 subsequent siblings)
  37 siblings, 0 replies; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

Many of the reginfo definitions in cp_reginfo[] use CP_ANY wildcards.
This is for a combination of reasons:
 * early ARM implementations really did underdecode
 * earlier versions of QEMU underdecoded and we can't tighten
   this up because we don't know if guests really require this or not
 * implementation convenience

For ARMv8 the architecture has tightened things up and system and
coprocessor registers are always specifically decoded. We take
advantage of this opportunity for a clean break by restricting
our CP_ANY wildcarded reginfo to pre-v8 CPUs, and providing
specifically decoded versions where necessary for v8 CPUs.

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

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 20952c3..1d1e7b4 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -395,11 +395,6 @@ static const ARMCPRegInfo cp_reginfo[] = {
      */
     { .name = "DBGDIDR", .cp = 14, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 0,
       .access = PL0_R, .type = ARM_CP_CONST, .resetvalue = 0 },
-    /* MMU Domain access control / MPU write buffer control */
-    { .name = "DACR", .cp = 15,
-      .crn = 3, .crm = CP_ANY, .opc1 = CP_ANY, .opc2 = CP_ANY,
-      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c3),
-      .resetvalue = 0, .writefn = dacr_write, .raw_writefn = raw_write, },
     { .name = "FCSEIDR", .cp = 15, .crn = 13, .crm = 0, .opc1 = 0, .opc2 = 0,
       .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c13_fcse),
       .resetvalue = 0, .writefn = fcse_write, .raw_writefn = raw_write, },
@@ -408,6 +403,18 @@ static const ARMCPRegInfo cp_reginfo[] = {
       .access = PL1_RW,
       .fieldoffset = offsetof(CPUARMState, cp15.contextidr_el1),
       .resetvalue = 0, .writefn = contextidr_write, .raw_writefn = raw_write, },
+    REGINFO_SENTINEL
+};
+
+static const ARMCPRegInfo not_v8_cp_reginfo[] = {
+    /* NB: Some of these registers exist in v8 but with more precise
+     * definitions that don't use CP_ANY wildcards (mostly in v8_cp_reginfo[]).
+     */
+    /* MMU Domain access control / MPU write buffer control */
+    { .name = "DACR", .cp = 15,
+      .crn = 3, .crm = CP_ANY, .opc1 = CP_ANY, .opc2 = CP_ANY,
+      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c3),
+      .resetvalue = 0, .writefn = dacr_write, .raw_writefn = raw_write, },
     /* ??? This covers not just the impdef TLB lockdown registers but also
      * some v7VMSA registers relating to TEX remap, so it is overly broad.
      */
@@ -1944,6 +1951,78 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
       .opc0 = 1, .opc2 = 0, .crn = 8, .crm = 7, .opc2 = 7,
       .access = PL1_W, .type = ARM_CP_NO_MIGRATE,
       .writefn = tlbi_aa64_vaa_write },
+    /* 32 bit TLB invalidates, Inner Shareable */
+    { .name = "TLBIALLIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 0,
+      .type = ARM_CP_NO_MIGRATE, .access = PL1_W, .writefn = tlbiall_write },
+    { .name = "TLBIMVAIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 1,
+      .type = ARM_CP_NO_MIGRATE, .access = PL1_W, .writefn = tlbimva_write },
+    { .name = "TLBIASIDIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 2,
+      .type = ARM_CP_NO_MIGRATE, .access = PL1_W, .writefn = tlbiasid_write },
+    { .name = "TLBIMVAAIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 3,
+      .type = ARM_CP_NO_MIGRATE, .access = PL1_W, .writefn = tlbimvaa_write },
+    { .name = "TLBIMVALIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 5,
+      .type = ARM_CP_NO_MIGRATE, .access = PL1_W, .writefn = tlbimva_write },
+    { .name = "TLBIMVAALIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 7,
+      .type = ARM_CP_NO_MIGRATE, .access = PL1_W, .writefn = tlbimvaa_write },
+    /* 32 bit ITLB invalidates */
+    { .name = "ITLBIALL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 0,
+      .type = ARM_CP_NO_MIGRATE, .access = PL1_W, .writefn = tlbiall_write },
+    { .name = "ITLBIMVA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 1,
+      .type = ARM_CP_NO_MIGRATE, .access = PL1_W, .writefn = tlbimva_write },
+    { .name = "ITLBIASID", .cp = 15, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 2,
+      .type = ARM_CP_NO_MIGRATE, .access = PL1_W, .writefn = tlbiasid_write },
+    /* 32 bit DTLB invalidates */
+    { .name = "DTLBIALL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 0,
+      .type = ARM_CP_NO_MIGRATE, .access = PL1_W, .writefn = tlbiall_write },
+    { .name = "DTLBIMVA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 1,
+      .type = ARM_CP_NO_MIGRATE, .access = PL1_W, .writefn = tlbimva_write },
+    { .name = "DTLBIASID", .cp = 15, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 2,
+      .type = ARM_CP_NO_MIGRATE, .access = PL1_W, .writefn = tlbiasid_write },
+    /* 32 bit TLB invalidates */
+    { .name = "TLBIALL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 0,
+      .type = ARM_CP_NO_MIGRATE, .access = PL1_W, .writefn = tlbiall_write },
+    { .name = "TLBIMVA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 1,
+      .type = ARM_CP_NO_MIGRATE, .access = PL1_W, .writefn = tlbimva_write },
+    { .name = "TLBIASID", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 2,
+      .type = ARM_CP_NO_MIGRATE, .access = PL1_W, .writefn = tlbiasid_write },
+    { .name = "TLBIMVAA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 3,
+      .type = ARM_CP_NO_MIGRATE, .access = PL1_W, .writefn = tlbimvaa_write },
+    { .name = "TLBIMVAL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 5,
+      .type = ARM_CP_NO_MIGRATE, .access = PL1_W, .writefn = tlbimva_write },
+    { .name = "TLBIMVAAL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 7,
+      .type = ARM_CP_NO_MIGRATE, .access = PL1_W, .writefn = tlbimvaa_write },
+    /* 32 bit cache operations */
+    { .name = "ICIALLUIS", .cp = 15, .opc1 = 0, .crn = 7, .crm = 1, .opc2 = 0,
+      .type = ARM_CP_NOP, .access = PL1_W },
+    { .name = "BPIALLUIS", .cp = 15, .opc1 = 0, .crn = 7, .crm = 1, .opc2 = 6,
+      .type = ARM_CP_NOP, .access = PL1_W },
+    { .name = "ICIALLU", .cp = 15, .opc1 = 0, .crn = 7, .crm = 5, .opc2 = 0,
+      .type = ARM_CP_NOP, .access = PL1_W },
+    { .name = "ICIMVAU", .cp = 15, .opc1 = 0, .crn = 7, .crm = 5, .opc2 = 1,
+      .type = ARM_CP_NOP, .access = PL1_W },
+    { .name = "BPIALL", .cp = 15, .opc1 = 0, .crn = 7, .crm = 5, .opc2 = 6,
+      .type = ARM_CP_NOP, .access = PL1_W },
+    { .name = "BPIMVA", .cp = 15, .opc1 = 0, .crn = 7, .crm = 5, .opc2 = 7,
+      .type = ARM_CP_NOP, .access = PL1_W },
+    { .name = "DCIMVAC", .cp = 15, .opc1 = 0, .crn = 7, .crm = 6, .opc2 = 1,
+      .type = ARM_CP_NOP, .access = PL1_W },
+    { .name = "DCISW", .cp = 15, .opc1 = 0, .crn = 7, .crm = 6, .opc2 = 2,
+      .type = ARM_CP_NOP, .access = PL1_W },
+    { .name = "DCCMVAC", .cp = 15, .opc1 = 0, .crn = 7, .crm = 10, .opc2 = 1,
+      .type = ARM_CP_NOP, .access = PL1_W },
+    { .name = "DCCSW", .cp = 15, .opc1 = 0, .crn = 7, .crm = 10, .opc2 = 2,
+      .type = ARM_CP_NOP, .access = PL1_W },
+    { .name = "DCCMVAU", .cp = 15, .opc1 = 0, .crn = 7, .crm = 11, .opc2 = 1,
+      .type = ARM_CP_NOP, .access = PL1_W },
+    { .name = "DCCIMVAC", .cp = 15, .opc1 = 0, .crn = 7, .crm = 14, .opc2 = 1,
+      .type = ARM_CP_NOP, .access = PL1_W },
+    { .name = "DCCISW", .cp = 15, .opc1 = 0, .crn = 7, .crm = 14, .opc2 = 2,
+      .type = ARM_CP_NOP, .access = PL1_W },
+    /* MMU Domain access control / MPU write buffer control */
+    { .name = "DACR", .cp = 15,
+      .opc1 = 0, .crn = 3, .crm = 0, .opc2 = 0,
+      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c3),
+      .resetvalue = 0, .writefn = dacr_write, .raw_writefn = raw_write, },
     /* Dummy implementation of monitor debug system control register:
      * we don't support debug.
      */
@@ -2041,6 +2120,13 @@ void register_cp_regs_for_features(ARMCPU *cpu)
     }
 
     define_arm_cp_regs(cpu, cp_reginfo);
+    if (!arm_feature(env, ARM_FEATURE_V8)) {
+        /* Must go early as it is full of wildcards that may be
+         * overridden by later definitions.
+         */
+        define_arm_cp_regs(cpu, not_v8_cp_reginfo);
+    }
+
     if (arm_feature(env, ARM_FEATURE_V6)) {
         /* The ID registers all have impdef reset values */
         ARMCPRegInfo v6_idregs[] = {
-- 
1.9.1

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

* [Qemu-devel] [PATCH v6 30/37] target-arm: Implement auxiliary fault status registers
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
                   ` (28 preceding siblings ...)
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 29/37] target-arm: Replace wildcarded cpreg definitions with precise ones " Peter Maydell
@ 2014-04-10 16:15 ` Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 31/37] target-arm: Implement AArch64 address translation operations Peter Maydell
                   ` (7 subsequent siblings)
  37 siblings, 0 replies; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

Implement the auxiliary fault status registers AFSR0_EL1 and
AFSR1_EL1. These are present on v7 and later, and have IMPDEF
behaviour; we choose to RAZ/WI for all cores.

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

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 1d1e7b4..988a8e9 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -784,6 +784,15 @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
     { .name = "AIDR", .state = ARM_CP_STATE_BOTH,
       .opc0 = 3, .opc1 = 1, .crn = 0, .crm = 0, .opc2 = 7,
       .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
+    /* Auxiliary fault status registers: these also are IMPDEF, and we
+     * choose to RAZ/WI for all cores.
+     */
+    { .name = "AFSR0_EL1", .state = ARM_CP_STATE_BOTH,
+      .opc0 = 3, .opc1 = 0, .crn = 5, .crm = 1, .opc2 = 0,
+      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+    { .name = "AFSR1_EL1", .state = ARM_CP_STATE_BOTH,
+      .opc0 = 3, .opc1 = 0, .crn = 5, .crm = 1, .opc2 = 1,
+      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
     /* MAIR can just read-as-written because we don't implement caches
      * and so don't need to care about memory attributes.
      */
-- 
1.9.1

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

* [Qemu-devel] [PATCH v6 31/37] target-arm: Implement AArch64 address translation operations
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
                   ` (29 preceding siblings ...)
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 30/37] target-arm: Implement auxiliary fault status registers Peter Maydell
@ 2014-04-10 16:15 ` Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 32/37] target-arm: Implement RVBAR register Peter Maydell
                   ` (6 subsequent siblings)
  37 siblings, 0 replies; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

Implement the AArch64 address translation operations.

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

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index d0f42fd..bebb333 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -188,8 +188,7 @@ typedef struct CPUARMState {
         uint64_t esr_el1;
         uint32_t c6_region[8]; /* MPU base/size registers.  */
         uint64_t far_el1; /* Fault address registers.  */
-        uint32_t c7_par;  /* Translation result. */
-        uint32_t c7_par_hi;  /* Translation result, high 32 bits */
+        uint64_t par_el1;  /* Translation result. */
         uint32_t c9_insn; /* Cache lockdown registers.  */
         uint32_t c9_data;
         uint32_t c9_pmcr; /* performance monitor control register */
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 988a8e9..34b0277 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1192,11 +1192,11 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
 static void par_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
 {
     if (arm_feature(env, ARM_FEATURE_LPAE)) {
-        env->cp15.c7_par = value;
+        env->cp15.par_el1 = value;
     } else if (arm_feature(env, ARM_FEATURE_V7)) {
-        env->cp15.c7_par = value & 0xfffff6ff;
+        env->cp15.par_el1 = value & 0xfffff6ff;
     } else {
-        env->cp15.c7_par = value & 0xfffff1ff;
+        env->cp15.par_el1 = value & 0xfffff1ff;
     }
 }
 
@@ -1243,8 +1243,7 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
              * fault.
              */
         }
-        env->cp15.c7_par = par64;
-        env->cp15.c7_par_hi = par64 >> 32;
+        env->cp15.par_el1 = par64;
     } else {
         /* ret is a DFSR/IFSR value for the short descriptor
          * translation table format (with WnR always clear).
@@ -1254,16 +1253,15 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
             /* We do not set any attribute bits in the PAR */
             if (page_size == (1 << 24)
                 && arm_feature(env, ARM_FEATURE_V7)) {
-                env->cp15.c7_par = (phys_addr & 0xff000000) | 1 << 1;
+                env->cp15.par_el1 = (phys_addr & 0xff000000) | 1 << 1;
             } else {
-                env->cp15.c7_par = phys_addr & 0xfffff000;
+                env->cp15.par_el1 = phys_addr & 0xfffff000;
             }
         } else {
-            env->cp15.c7_par = ((ret & (1 << 10)) >> 5) |
+            env->cp15.par_el1 = ((ret & (1 << 10)) >> 5) |
                 ((ret & (1 << 12)) >> 6) |
                 ((ret & 0xf) << 1) | 1;
         }
-        env->cp15.c7_par_hi = 0;
     }
 }
 #endif
@@ -1271,7 +1269,7 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
 static const ARMCPRegInfo vapa_cp_reginfo[] = {
     { .name = "PAR", .cp = 15, .crn = 7, .crm = 4, .opc1 = 0, .opc2 = 0,
       .access = PL1_RW, .resetvalue = 0,
-      .fieldoffset = offsetof(CPUARMState, cp15.c7_par),
+      .fieldoffset = offsetoflow32(CPUARMState, cp15.par_el1),
       .writefn = par_write },
 #ifndef CONFIG_USER_ONLY
     { .name = "ATS", .cp = 15, .crn = 7, .crm = 8, .opc1 = 0, .opc2 = CP_ANY,
@@ -1674,24 +1672,6 @@ static const ARMCPRegInfo mpidr_cp_reginfo[] = {
     REGINFO_SENTINEL
 };
 
-static uint64_t par64_read(CPUARMState *env, const ARMCPRegInfo *ri)
-{
-    return ((uint64_t)env->cp15.c7_par_hi << 32) | env->cp15.c7_par;
-}
-
-static void par64_write(CPUARMState *env, const ARMCPRegInfo *ri,
-                        uint64_t value)
-{
-    env->cp15.c7_par_hi = value >> 32;
-    env->cp15.c7_par = value;
-}
-
-static void par64_reset(CPUARMState *env, const ARMCPRegInfo *ri)
-{
-    env->cp15.c7_par_hi = 0;
-    env->cp15.c7_par = 0;
-}
-
 static const ARMCPRegInfo lpae_cp_reginfo[] = {
     /* NOP AMAIR0/1: the override is because these clash with the rather
      * broadly specified TLB_LOCKDOWN entry in the generic cp_reginfo.
@@ -1711,7 +1691,7 @@ static const ARMCPRegInfo lpae_cp_reginfo[] = {
       .access = PL0_R, .type = ARM_CP_CONST|ARM_CP_64BIT, .resetvalue = 0 },
     { .name = "PAR", .cp = 15, .crm = 7, .opc1 = 0,
       .access = PL1_RW, .type = ARM_CP_64BIT,
-      .readfn = par64_read, .writefn = par64_write, .resetfn = par64_reset },
+      .fieldoffset = offsetof(CPUARMState, cp15.par_el1), .resetvalue = 0 },
     { .name = "TTBR0", .cp = 15, .crm = 2, .opc1 = 0,
       .access = PL1_RW, .type = ARM_CP_64BIT | ARM_CP_NO_MIGRATE,
       .fieldoffset = offsetof(CPUARMState, cp15.ttbr0_el1),
@@ -1960,6 +1940,21 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
       .opc0 = 1, .opc2 = 0, .crn = 8, .crm = 7, .opc2 = 7,
       .access = PL1_W, .type = ARM_CP_NO_MIGRATE,
       .writefn = tlbi_aa64_vaa_write },
+#ifndef CONFIG_USER_ONLY
+    /* 64 bit address translation operations */
+    { .name = "AT_S1E1R", .state = ARM_CP_STATE_AA64,
+      .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 8, .opc2 = 0,
+      .access = PL1_W, .type = ARM_CP_NO_MIGRATE, .writefn = ats_write },
+    { .name = "AT_S1E1W", .state = ARM_CP_STATE_AA64,
+      .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 8, .opc2 = 1,
+      .access = PL1_W, .type = ARM_CP_NO_MIGRATE, .writefn = ats_write },
+    { .name = "AT_S1E0R", .state = ARM_CP_STATE_AA64,
+      .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 8, .opc2 = 2,
+      .access = PL1_W, .type = ARM_CP_NO_MIGRATE, .writefn = ats_write },
+    { .name = "AT_S1E0W", .state = ARM_CP_STATE_AA64,
+      .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 8, .opc2 = 3,
+      .access = PL1_W, .type = ARM_CP_NO_MIGRATE, .writefn = ats_write },
+#endif
     /* 32 bit TLB invalidates, Inner Shareable */
     { .name = "TLBIALLIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 0,
       .type = ARM_CP_NO_MIGRATE, .access = PL1_W, .writefn = tlbiall_write },
-- 
1.9.1

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

* [Qemu-devel] [PATCH v6 32/37] target-arm: Implement RVBAR register
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
                   ` (30 preceding siblings ...)
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 31/37] target-arm: Implement AArch64 address translation operations Peter Maydell
@ 2014-04-10 16:15 ` Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 33/37] target-arm: Implement Cortex-A57 implementation-defined system registers Peter Maydell
                   ` (5 subsequent siblings)
  37 siblings, 0 replies; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

Implement the AArch64 RVBAR register, which indicates the reset
address. Since the reset address is implementation defined and
usually configurable by setting config signals in hardware, we
also provide a QOM property so it can be set at board level if
necessary.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
 target-arm/cpu-qom.h | 1 +
 target-arm/cpu.c     | 9 +++++++++
 target-arm/helper.c  | 6 ++++++
 3 files changed, 16 insertions(+)

diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
index 2b6b370..743985e 100644
--- a/target-arm/cpu-qom.h
+++ b/target-arm/cpu-qom.h
@@ -153,6 +153,7 @@ typedef struct ARMCPU {
     bool reset_hivecs;
     /* DCZ blocksize, in log_2(words), ie low 4 bits of DCZID_EL0 */
     uint32_t dcz_blocksize;
+    uint64_t rvbar;
 } ARMCPU;
 
 #define TYPE_AARCH64_CPU "aarch64-cpu"
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index a78a36b..783fc73 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -105,6 +105,7 @@ static void arm_cpu_reset(CPUState *s)
         env->cp15.c1_coproc = deposit64(env->cp15.c1_coproc, 20, 2, 3);
 #else
         env->pstate = PSTATE_MODE_EL1h;
+        env->pc = cpu->rvbar;
 #endif
     } else {
 #if defined(CONFIG_USER_ONLY)
@@ -266,6 +267,9 @@ static Property arm_cpu_reset_cbar_property =
 static Property arm_cpu_reset_hivecs_property =
             DEFINE_PROP_BOOL("reset-hivecs", ARMCPU, reset_hivecs, false);
 
+static Property arm_cpu_rvbar_property =
+            DEFINE_PROP_UINT64("rvbar", ARMCPU, rvbar, 0);
+
 static void arm_cpu_post_init(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
@@ -279,6 +283,11 @@ static void arm_cpu_post_init(Object *obj)
         qdev_property_add_static(DEVICE(obj), &arm_cpu_reset_hivecs_property,
                                  &error_abort);
     }
+
+    if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
+        qdev_property_add_static(DEVICE(obj), &arm_cpu_rvbar_property,
+                                 &error_abort);
+    }
 }
 
 static void arm_cpu_finalizefn(Object *obj)
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 34b0277..4a74249 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2295,6 +2295,12 @@ void register_cp_regs_for_features(ARMCPU *cpu)
               .resetvalue = cpu->mvfr2 },
             REGINFO_SENTINEL
         };
+        ARMCPRegInfo rvbar = {
+            .name = "RVBAR_EL1", .state = ARM_CP_STATE_AA64,
+            .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 0, .opc2 = 2,
+            .type = ARM_CP_CONST, .access = PL1_R, .resetvalue = cpu->rvbar
+        };
+        define_one_arm_cp_reg(cpu, &rvbar);
         define_arm_cp_regs(cpu, v8_idregs);
         define_arm_cp_regs(cpu, v8_cp_reginfo);
         define_aarch64_debug_regs(cpu);
-- 
1.9.1

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

* [Qemu-devel] [PATCH v6 33/37] target-arm: Implement Cortex-A57 implementation-defined system registers
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
                   ` (31 preceding siblings ...)
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 32/37] target-arm: Implement RVBAR register Peter Maydell
@ 2014-04-10 16:15 ` Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 34/37] target-arm: Implement CBAR for Cortex-A57 Peter Maydell
                   ` (4 subsequent siblings)
  37 siblings, 0 replies; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

Implement a subset of the Cortex-A57's implementation defined system
registers. We provide RAZ/WI or reads-as-constant/writes-ignored
implementations of the various control and syndrome reigsters.
We do not implement registers which provide direct access to and
manipulation of the L1 cache, since QEMU doesn't implement caches.

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

diff --git a/target-arm/cpu64.c b/target-arm/cpu64.c
index b8b4fa6..70a83fc 100644
--- a/target-arm/cpu64.c
+++ b/target-arm/cpu64.c
@@ -32,6 +32,61 @@ static inline void set_feature(CPUARMState *env, int feature)
     env->features |= 1ULL << feature;
 }
 
+#ifndef CONFIG_USER_ONLY
+static uint64_t a57_l2ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    /* Number of processors is in [25:24]; otherwise we RAZ */
+    return (smp_cpus - 1) << 24;
+}
+#endif
+
+static const ARMCPRegInfo cortexa57_cp_reginfo[] = {
+#ifndef CONFIG_USER_ONLY
+    { .name = "L2CTLR_EL1", .state = ARM_CP_STATE_AA64,
+      .opc0 = 3, .opc1 = 1, .crn = 11, .crm = 0, .opc2 = 2,
+      .access = PL1_RW, .readfn = a57_l2ctlr_read,
+      .writefn = arm_cp_write_ignore },
+    { .name = "L2CTLR",
+      .cp = 15, .opc1 = 1, .crn = 9, .crm = 0, .opc2 = 2,
+      .access = PL1_RW, .readfn = a57_l2ctlr_read,
+      .writefn = arm_cp_write_ignore },
+#endif
+    { .name = "L2ECTLR_EL1", .state = ARM_CP_STATE_AA64,
+      .opc0 = 3, .opc1 = 1, .crn = 11, .crm = 0, .opc2 = 3,
+      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+    { .name = "L2ECTLR",
+      .cp = 15, .opc1 = 1, .crn = 9, .crm = 0, .opc2 = 3,
+      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+    { .name = "L2ACTLR", .state = ARM_CP_STATE_BOTH,
+      .opc0 = 3, .opc1 = 1, .crn = 15, .crm = 0, .opc2 = 0,
+      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+    { .name = "CPUACTLR_EL1", .state = ARM_CP_STATE_AA64,
+      .opc0 = 3, .opc1 = 1, .crn = 15, .crm = 2, .opc2 = 0,
+      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+    { .name = "CPUACTLR",
+      .cp = 15, .opc1 = 0, .crm = 15,
+      .access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 },
+    { .name = "CPUECTLR_EL1", .state = ARM_CP_STATE_AA64,
+      .opc0 = 3, .opc1 = 1, .crn = 15, .crm = 2, .opc2 = 1,
+      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+    { .name = "CPUECTLR",
+      .cp = 15, .opc1 = 1, .crm = 15,
+      .access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 },
+    { .name = "CPUMERRSR_EL1", .state = ARM_CP_STATE_AA64,
+      .opc0 = 3, .opc1 = 1, .crn = 15, .crm = 2, .opc2 = 2,
+      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+    { .name = "CPUMERRSR",
+      .cp = 15, .opc1 = 2, .crm = 15,
+      .access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 },
+    { .name = "L2MERRSR_EL1", .state = ARM_CP_STATE_AA64,
+      .opc0 = 3, .opc1 = 1, .crn = 15, .crm = 2, .opc2 = 3,
+      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+    { .name = "L2MERRSR",
+      .cp = 15, .opc1 = 3, .crm = 15,
+      .access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 },
+    REGINFO_SENTINEL
+};
+
 static void aarch64_a57_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
-- 
1.9.1

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

* [Qemu-devel] [PATCH v6 34/37] target-arm: Implement CBAR for Cortex-A57
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
                   ` (32 preceding siblings ...)
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 33/37] target-arm: Implement Cortex-A57 implementation-defined system registers Peter Maydell
@ 2014-04-10 16:15 ` Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 35/37] target-arm: Make Cortex-A15 CBAR read-only Peter Maydell
                   ` (3 subsequent siblings)
  37 siblings, 0 replies; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

The Cortex-A57, like most of the other ARM cores, has a CBAR
register which defines the base address of the per-CPU
peripherals. However it has a 64-bit view as well as a
32-bit view; expand the QOM reset-cbar property from UINT32
to UINT64 so this can be specified, and implement the
32-bit and 64-bit views of a 64-bit CBAR.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
 target-arm/cpu-qom.h |  2 +-
 target-arm/cpu.c     |  8 ++++++--
 target-arm/cpu.h     |  1 +
 target-arm/cpu64.c   |  1 +
 target-arm/helper.c  | 39 +++++++++++++++++++++++++++++++++------
 5 files changed, 42 insertions(+), 9 deletions(-)

diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
index 743985e..82f1bc7 100644
--- a/target-arm/cpu-qom.h
+++ b/target-arm/cpu-qom.h
@@ -148,7 +148,7 @@ typedef struct ARMCPU {
      * in the order L1DCache, L1ICache, L2DCache, L2ICache, etc.
      */
     uint32_t ccsidr[16];
-    uint32_t reset_cbar;
+    uint64_t reset_cbar;
     uint32_t reset_auxcr;
     bool reset_hivecs;
     /* DCZ blocksize, in log_2(words), ie low 4 bits of DCZID_EL0 */
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 783fc73..f9f6187 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -262,7 +262,7 @@ static void arm_cpu_initfn(Object *obj)
 }
 
 static Property arm_cpu_reset_cbar_property =
-            DEFINE_PROP_UINT32("reset-cbar", ARMCPU, reset_cbar, 0);
+            DEFINE_PROP_UINT64("reset-cbar", ARMCPU, reset_cbar, 0);
 
 static Property arm_cpu_reset_hivecs_property =
             DEFINE_PROP_BOOL("reset-hivecs", ARMCPU, reset_hivecs, false);
@@ -274,7 +274,8 @@ static void arm_cpu_post_init(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
 
-    if (arm_feature(&cpu->env, ARM_FEATURE_CBAR)) {
+    if (arm_feature(&cpu->env, ARM_FEATURE_CBAR) ||
+        arm_feature(&cpu->env, ARM_FEATURE_CBAR_RO)) {
         qdev_property_add_static(DEVICE(obj), &arm_cpu_reset_cbar_property,
                                  &error_abort);
     }
@@ -349,6 +350,9 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
         set_feature(env, ARM_FEATURE_V7MP);
         set_feature(env, ARM_FEATURE_PXN);
     }
+    if (arm_feature(env, ARM_FEATURE_CBAR_RO)) {
+        set_feature(env, ARM_FEATURE_CBAR);
+    }
 
     if (cpu->reset_hivecs) {
             cpu->reset_sctlr |= (1 << 13);
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index bebb333..c83f249 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -630,6 +630,7 @@ enum arm_features {
     ARM_FEATURE_V8_AES, /* implements AES part of v8 Crypto Extensions */
     ARM_FEATURE_CBAR, /* has cp15 CBAR */
     ARM_FEATURE_CRC, /* ARMv8 CRC instructions */
+    ARM_FEATURE_CBAR_RO, /* has cp15 CBAR and it is read-only */
 };
 
 static inline int arm_feature(CPUARMState *env, int feature)
diff --git a/target-arm/cpu64.c b/target-arm/cpu64.c
index 70a83fc..9a0c431 100644
--- a/target-arm/cpu64.c
+++ b/target-arm/cpu64.c
@@ -97,6 +97,7 @@ static void aarch64_a57_initfn(Object *obj)
     set_feature(&cpu->env, ARM_FEATURE_NEON);
     set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
     set_feature(&cpu->env, ARM_FEATURE_AARCH64);
+    set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
     cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A57;
     cpu->midr = 0x411fd070;
     cpu->reset_fpsid = 0x41034070;
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 4a74249..3dc20c4 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2463,12 +2463,39 @@ void register_cp_regs_for_features(ARMCPU *cpu)
     }
 
     if (arm_feature(env, ARM_FEATURE_CBAR)) {
-        ARMCPRegInfo cbar = {
-            .name = "CBAR", .cp = 15, .crn = 15, .crm = 0, .opc1 = 4, .opc2 = 0,
-            .access = PL1_R|PL3_W, .resetvalue = cpu->reset_cbar,
-            .fieldoffset = offsetof(CPUARMState, cp15.c15_config_base_address)
-        };
-        define_one_arm_cp_reg(cpu, &cbar);
+        if (arm_feature(env, ARM_FEATURE_AARCH64)) {
+            /* 32 bit view is [31:18] 0...0 [43:32]. */
+            uint32_t cbar32 = (extract64(cpu->reset_cbar, 18, 14) << 18)
+                | extract64(cpu->reset_cbar, 32, 12);
+            ARMCPRegInfo cbar_reginfo[] = {
+                { .name = "CBAR",
+                  .type = ARM_CP_CONST,
+                  .cp = 15, .crn = 15, .crm = 0, .opc1 = 4, .opc2 = 0,
+                  .access = PL1_R, .resetvalue = cpu->reset_cbar },
+                { .name = "CBAR_EL1", .state = ARM_CP_STATE_AA64,
+                  .type = ARM_CP_CONST,
+                  .opc0 = 3, .opc1 = 1, .crn = 15, .crm = 3, .opc2 = 0,
+                  .access = PL1_R, .resetvalue = cbar32 },
+                REGINFO_SENTINEL
+            };
+            /* We don't implement a r/w 64 bit CBAR currently */
+            assert(arm_feature(env, ARM_FEATURE_CBAR_RO));
+            define_arm_cp_regs(cpu, cbar_reginfo);
+        } else {
+            ARMCPRegInfo cbar = {
+                .name = "CBAR",
+                .cp = 15, .crn = 15, .crm = 0, .opc1 = 4, .opc2 = 0,
+                .access = PL1_R|PL3_W, .resetvalue = cpu->reset_cbar,
+                .fieldoffset = offsetof(CPUARMState,
+                                        cp15.c15_config_base_address)
+            };
+            if (arm_feature(env, ARM_FEATURE_CBAR_RO)) {
+                cbar.access = PL1_R;
+                cbar.fieldoffset = 0;
+                cbar.type = ARM_CP_CONST;
+            }
+            define_one_arm_cp_reg(cpu, &cbar);
+        }
     }
 
     /* Generic registers whose values depend on the implementation */
-- 
1.9.1

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

* [Qemu-devel] [PATCH v6 35/37] target-arm: Make Cortex-A15 CBAR read-only
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
                   ` (33 preceding siblings ...)
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 34/37] target-arm: Implement CBAR for Cortex-A57 Peter Maydell
@ 2014-04-10 16:15 ` Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 36/37] target-arm: Handle the CPU being in AArch32 mode in the AArch64 set_pc Peter Maydell
                   ` (2 subsequent siblings)
  37 siblings, 0 replies; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

The Cortex-A15's CBAR register is actually read-only (unlike that
of the Cortex-A9). Correct our model to match the hardware.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
 target-arm/cpu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index f9f6187..c0ddc3e 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -744,7 +744,7 @@ static void cortex_a15_initfn(Object *obj)
     set_feature(&cpu->env, ARM_FEATURE_ARM_DIV);
     set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
     set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
-    set_feature(&cpu->env, ARM_FEATURE_CBAR);
+    set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
     set_feature(&cpu->env, ARM_FEATURE_LPAE);
     cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A15;
     cpu->midr = 0x412fc0f1;
-- 
1.9.1

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

* [Qemu-devel] [PATCH v6 36/37] target-arm: Handle the CPU being in AArch32 mode in the AArch64 set_pc
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
                   ` (34 preceding siblings ...)
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 35/37] target-arm: Make Cortex-A15 CBAR read-only Peter Maydell
@ 2014-04-10 16:15 ` Peter Maydell
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 37/37] target-arm: Dump 32-bit CPU state if 64 bit CPU is in AArch32 Peter Maydell
  2014-04-10 22:43 ` [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Crosthwaite
  37 siblings, 0 replies; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

The AArch64 implementation of the set_pc method needs to be updated to
handle the possibility that the CPU is in AArch32 mode; otherwise there
are weird crashes when doing interprocessing in system emulation mode
when an interrupt occurs and we fail to resynchronize the 32-bit PC
with the TB we need to execute next.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
---
 target-arm/cpu64.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/target-arm/cpu64.c b/target-arm/cpu64.c
index 9a0c431..c673ac2 100644
--- a/target-arm/cpu64.c
+++ b/target-arm/cpu64.c
@@ -172,11 +172,15 @@ static void aarch64_cpu_finalizefn(Object *obj)
 static void aarch64_cpu_set_pc(CPUState *cs, vaddr value)
 {
     ARMCPU *cpu = ARM_CPU(cs);
-    /*
-     * TODO: this will need updating for system emulation,
-     * when the core may be in AArch32 mode.
+    /* It's OK to look at env for the current mode here, because it's
+     * never possible for an AArch64 TB to chain to an AArch32 TB.
+     * (Otherwise we would need to use synchronize_from_tb instead.)
      */
-    cpu->env.pc = value;
+    if (is_a64(&cpu->env)) {
+        cpu->env.pc = value;
+    } else {
+        cpu->env.regs[15] = value;
+    }
 }
 
 static void aarch64_cpu_class_init(ObjectClass *oc, void *data)
-- 
1.9.1

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

* [Qemu-devel] [PATCH v6 37/37] target-arm: Dump 32-bit CPU state if 64 bit CPU is in AArch32
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
                   ` (35 preceding siblings ...)
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 36/37] target-arm: Handle the CPU being in AArch32 mode in the AArch64 set_pc Peter Maydell
@ 2014-04-10 16:15 ` Peter Maydell
  2014-04-10 22:43 ` [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Crosthwaite
  37 siblings, 0 replies; 40+ messages in thread
From: Peter Maydell @ 2014-04-10 16:15 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
	Richard Henderson

For system mode, we may have a 64 bit CPU which is currently executing
in AArch32 state; if we're dumping CPU state to the logs we should
therefore show the correct state for the current execution state,
rather than hardwiring it based on the type of the CPU. For consistency
with how we handle translation, we leave the 32 bit dump function
as the default, and have it hand off control to the 64 bit dump code
if we're in AArch64 mode.

Reported-by: Rob Herring <rob.herring@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/cpu-qom.h   | 2 --
 target-arm/cpu64.c     | 1 -
 target-arm/translate.c | 5 +++++
 target-arm/translate.h | 8 ++++++++
 4 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
index 82f1bc7..edc7f26 100644
--- a/target-arm/cpu-qom.h
+++ b/target-arm/cpu-qom.h
@@ -200,8 +200,6 @@ void arm_gt_ptimer_cb(void *opaque);
 void arm_gt_vtimer_cb(void *opaque);
 
 #ifdef TARGET_AARCH64
-void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
-                            fprintf_function cpu_fprintf, int flags);
 int aarch64_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
 int aarch64_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
 
diff --git a/target-arm/cpu64.c b/target-arm/cpu64.c
index c673ac2..8daa622 100644
--- a/target-arm/cpu64.c
+++ b/target-arm/cpu64.c
@@ -188,7 +188,6 @@ static void aarch64_cpu_class_init(ObjectClass *oc, void *data)
     CPUClass *cc = CPU_CLASS(oc);
 
     cc->do_interrupt = aarch64_cpu_do_interrupt;
-    cc->dump_state = aarch64_cpu_dump_state;
     cc->set_pc = aarch64_cpu_set_pc;
     cc->gdb_read_register = aarch64_cpu_gdb_read_register;
     cc->gdb_write_register = aarch64_cpu_gdb_write_register;
diff --git a/target-arm/translate.c b/target-arm/translate.c
index f7b5daf..0c08cc1 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -11047,6 +11047,11 @@ void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
     int i;
     uint32_t psr;
 
+    if (is_a64(env)) {
+        aarch64_cpu_dump_state(cs, f, cpu_fprintf, flags);
+        return;
+    }
+
     for(i=0;i<16;i++) {
         cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
         if ((i % 4) == 3)
diff --git a/target-arm/translate.h b/target-arm/translate.h
index 3f7d5ca..34328f4 100644
--- a/target-arm/translate.h
+++ b/target-arm/translate.h
@@ -72,6 +72,8 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
                                         TranslationBlock *tb,
                                         bool search_pc);
 void gen_a64_set_pc_im(uint64_t val);
+void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
+                            fprintf_function cpu_fprintf, int flags);
 #else
 static inline void a64_translate_init(void)
 {
@@ -86,6 +88,12 @@ static inline void gen_intermediate_code_internal_a64(ARMCPU *cpu,
 static inline void gen_a64_set_pc_im(uint64_t val)
 {
 }
+
+static inline void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
+                                          fprintf_function cpu_fprintf,
+                                          int flags)
+{
+}
 #endif
 
 void arm_gen_test_cc(int cc, int label);
-- 
1.9.1

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

* Re: [Qemu-devel] [PATCH v6 12/37] target-arm: A64: Implement DC ZVA
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 12/37] target-arm: A64: Implement DC ZVA Peter Maydell
@ 2014-04-10 17:22   ` Richard Henderson
  0 siblings, 0 replies; 40+ messages in thread
From: Richard Henderson @ 2014-04-10 17:22 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel
  Cc: Peter Crosthwaite, patches, Alexander Graf, Greg Bellows,
	Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall

On 04/10/2014 09:15 AM, Peter Maydell wrote:
> Implement the DC ZVA instruction, which clears a block of memory.
> The fast path obtains a pointer to the underlying RAM via the TCG TLB
> data structure so we can do a direct memset(), with fallback to a
> simple byte-store loop in the slow path.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

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

* Re: [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation
  2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
                   ` (36 preceding siblings ...)
  2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 37/37] target-arm: Dump 32-bit CPU state if 64 bit CPU is in AArch32 Peter Maydell
@ 2014-04-10 22:43 ` Peter Crosthwaite
  37 siblings, 0 replies; 40+ messages in thread
From: Peter Crosthwaite @ 2014-04-10 22:43 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Patch Tracking, Alexander Graf, qemu-devel@nongnu.org Developers,
	Greg Bellows, Laurent Desnogues, Alex Bennée, kvmarm,
	Christoffer Dall, Richard Henderson

On Fri, Apr 11, 2014 at 2:14 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
> Here's v5 of the AArch64 system emulation patchset.
> Still missing/TODO:
>  * SMP support (needs PSCI emulation in QEMU; being prototyped)
>  * save/restore (I have a patch which adds this but I think it will
>    look better if we consolidate AArch32 cpsr and AArch64 pstate
>    handling)
> but both of these I think are best done once this main series
> is committed to master.
>
> The changes v5->v6 are pretty minor, and these patches have
> been kicking around onlist for a long time, so I plan to
> put these in a pull request pretty much as soon as we reopen
> trunk after 2.0 releases. Last chance for review!
>

Ill do another sweep before the end of the week and review those Ive
skipped over so far for completeness.

Regards,
Peter

>
> Changes v5->v6:
>  * add extract64() when putting together 32-bit CBAR value
>  * be consistent about int vs bool for 1 bit fields in the
>    syn_insn_abort/syn_data_abort functions
>  * added some FIXMEs about inaccurate syndrome info for A32/T32
>    Neon unallocated insns when FP is disabled
>  * decided that using a15mpcore_priv in the virt machine is actually
>    the best approach, and added a suitable comment
> Changes v4->v5:
>  * new patches:
>    + MVFR registers
>    + various extra system registers
>    + don't expose wildcards for ARMv8
>    + make A15's CBAR R/O
>    + support interprocessing in set_pc
>  * minor tweaks per review (I haven't always taken the review
>    suggestion; see mail threads on the previous version of the
>    patch series)
>  * DC ZVA: use helper_ret_stb_mmu
>            make tlb_vaddr_to_host take param for access type
>  * NB: I didn't make gen_exception and gen_exception_internal shared
>    in patch 5: I think keeping the A64 and A32 decoders independent
>    is preferable
>  * have syn_insn_abort and syn_data_abort set the syndrome bit
>    for 'exception to same level' rather than making caller do it
> Changes v3->v4:
>  * reviewed patches from bottom of stack got committed to master
>  * new patches at top of stack
>  * addressed review issues on v8 mmu translation patch and DAIF patch
>
> thanks
> -- PMM
>
>
> Peter Maydell (33):
>   target-arm: Split out private-to-target functions into internals.h
>   target-arm: Implement AArch64 DAIF system register
>   target-arm: Define exception record for AArch64 exceptions
>   target-arm: Provide correct syndrome information for cpreg access
>     traps
>   target-arm: Add support for generating exceptions with syndrome
>     information
>   target-arm: A64: Correctly fault FP/Neon if CPACR.FPEN set
>   target-arm: A64: Add assertion that FP access was checked
>   target-arm: Fix VFP enables for AArch32 EL0 under AArch64 EL1
>   target-arm: Don't mention PMU in debug feature register
>   target-arm: A64: Implement DC ZVA
>   target-arm: Use dedicated CPU state fields for ARM946 access bit
>     registers
>   target-arm: Add AArch64 ELR_EL1 register.
>   target-arm: Implement SP_EL0, SP_EL1
>   target-arm: Implement AArch64 SPSR_EL1
>   target-arm: Move arm_log_exception() into internals.h
>   target-arm: Implement ARMv8 MVFR registers
>   target-arm: Add Cortex-A57 processor
>   hw/arm/virt: Add support for Cortex-A57
>   target-arm: Implement AArch64 views of AArch32 ID registers
>   target-arm: Implement AArch64 view of CONTEXTIDR
>   target-arm: Implement AArch64 view of ACTLR
>   target-arm: Implement ISR_EL1 register
>   target-arm: Remove THUMB2EE feature from AArch64 'any' CPU
>   target-arm: Don't expose wildcard ID register definitions for ARMv8
>   target-arm: Replace wildcarded cpreg definitions with precise ones for
>     ARMv8
>   target-arm: Implement auxiliary fault status registers
>   target-arm: Implement AArch64 address translation operations
>   target-arm: Implement RVBAR register
>   target-arm: Implement Cortex-A57 implementation-defined system
>     registers
>   target-arm: Implement CBAR for Cortex-A57
>   target-arm: Make Cortex-A15 CBAR read-only
>   target-arm: Handle the CPU being in AArch32 mode in the AArch64 set_pc
>   target-arm: Dump 32-bit CPU state if 64 bit CPU is in AArch32
>
> Rob Herring (4):
>   target-arm: Provide syndrome information for MMU faults
>   target-arm: Add v8 mmu translation support
>   target-arm: Implement AArch64 views of fault status and data registers
>   target-arm: Implement AArch64 EL1 exception handling
>
>  hw/arm/virt.c               |   8 +
>  include/exec/softmmu_exec.h |  52 +++
>  linux-user/main.c           |  56 ++-
>  target-arm/cpu-qom.h        |  10 +-
>  target-arm/cpu.c            |  30 +-
>  target-arm/cpu.h            |  81 +++--
>  target-arm/cpu64.c          | 115 ++++++-
>  target-arm/helper-a64.c     |  75 ++++
>  target-arm/helper.c         | 809 +++++++++++++++++++++++++++++++++-----------
>  target-arm/helper.h         |   7 +-
>  target-arm/internals.h      | 267 +++++++++++++++
>  target-arm/kvm32.c          |  19 +-
>  target-arm/kvm64.c          |  71 +++-
>  target-arm/machine.c        |  13 +-
>  target-arm/op_helper.c      |  92 ++++-
>  target-arm/translate-a64.c  | 441 +++++++++++++++++++++---
>  target-arm/translate.c      | 195 ++++++++---
>  target-arm/translate.h      |  23 +-
>  18 files changed, 1987 insertions(+), 377 deletions(-)
>  create mode 100644 target-arm/internals.h
>
> --
> 1.9.1
>
>

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

end of thread, other threads:[~2014-04-10 22:43 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-04-10 16:14 [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Maydell
2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 01/37] target-arm: Split out private-to-target functions into internals.h Peter Maydell
2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 02/37] target-arm: Implement AArch64 DAIF system register Peter Maydell
2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 03/37] target-arm: Define exception record for AArch64 exceptions Peter Maydell
2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 04/37] target-arm: Provide correct syndrome information for cpreg access traps Peter Maydell
2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 05/37] target-arm: Add support for generating exceptions with syndrome information Peter Maydell
2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 06/37] target-arm: Provide syndrome information for MMU faults Peter Maydell
2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 07/37] target-arm: A64: Correctly fault FP/Neon if CPACR.FPEN set Peter Maydell
2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 08/37] target-arm: A64: Add assertion that FP access was checked Peter Maydell
2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 09/37] target-arm: Fix VFP enables for AArch32 EL0 under AArch64 EL1 Peter Maydell
2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 10/37] target-arm: Add v8 mmu translation support Peter Maydell
2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 11/37] target-arm: Don't mention PMU in debug feature register Peter Maydell
2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 12/37] target-arm: A64: Implement DC ZVA Peter Maydell
2014-04-10 17:22   ` Richard Henderson
2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 13/37] target-arm: Use dedicated CPU state fields for ARM946 access bit registers Peter Maydell
2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 14/37] target-arm: Implement AArch64 views of fault status and data registers Peter Maydell
2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 15/37] target-arm: Add AArch64 ELR_EL1 register Peter Maydell
2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 16/37] target-arm: Implement SP_EL0, SP_EL1 Peter Maydell
2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 17/37] target-arm: Implement AArch64 SPSR_EL1 Peter Maydell
2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 18/37] target-arm: Move arm_log_exception() into internals.h Peter Maydell
2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 19/37] target-arm: Implement AArch64 EL1 exception handling Peter Maydell
2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 20/37] target-arm: Implement ARMv8 MVFR registers Peter Maydell
2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 21/37] target-arm: Add Cortex-A57 processor Peter Maydell
2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 22/37] hw/arm/virt: Add support for Cortex-A57 Peter Maydell
2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 23/37] target-arm: Implement AArch64 views of AArch32 ID registers Peter Maydell
2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 24/37] target-arm: Implement AArch64 view of CONTEXTIDR Peter Maydell
2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 25/37] target-arm: Implement AArch64 view of ACTLR Peter Maydell
2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 26/37] target-arm: Implement ISR_EL1 register Peter Maydell
2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 27/37] target-arm: Remove THUMB2EE feature from AArch64 'any' CPU Peter Maydell
2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 28/37] target-arm: Don't expose wildcard ID register definitions for ARMv8 Peter Maydell
2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 29/37] target-arm: Replace wildcarded cpreg definitions with precise ones " Peter Maydell
2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 30/37] target-arm: Implement auxiliary fault status registers Peter Maydell
2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 31/37] target-arm: Implement AArch64 address translation operations Peter Maydell
2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 32/37] target-arm: Implement RVBAR register Peter Maydell
2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 33/37] target-arm: Implement Cortex-A57 implementation-defined system registers Peter Maydell
2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 34/37] target-arm: Implement CBAR for Cortex-A57 Peter Maydell
2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 35/37] target-arm: Make Cortex-A15 CBAR read-only Peter Maydell
2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 36/37] target-arm: Handle the CPU being in AArch32 mode in the AArch64 set_pc Peter Maydell
2014-04-10 16:15 ` [Qemu-devel] [PATCH v6 37/37] target-arm: Dump 32-bit CPU state if 64 bit CPU is in AArch32 Peter Maydell
2014-04-10 22:43 ` [Qemu-devel] [PATCH v6 00/37] AArch64 system emulation Peter Crosthwaite

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.