qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PULL 00/19] target-arm queue
@ 2014-09-29 18:26 Peter Maydell
  2014-09-29 18:26 ` [Qemu-devel] [PULL 01/19] target-arm: Implement setting guest breakpoints Peter Maydell
                   ` (19 more replies)
  0 siblings, 20 replies; 21+ messages in thread
From: Peter Maydell @ 2014-09-29 18:26 UTC (permalink / raw)
  To: qemu-devel

ARM pullreq: nothing fantastically exciting, but getting the
EL2/EL3 patchset in ought to help with ongoing TZ work.

-- PMM


The following changes since commit 70556264a89a268efba1d7e8e341adcdd7881eb4:

  libqos: use microseconds instead of iterations for virtio timeout (2014-09-29 17:31:11 +0100)

are available in the git repository at:

  git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20140929

for you to fetch changes up to 136e67e9b50b61fb03fedcea5c4fbe74cf44fdcc:

  target-arm: Add support for VIRQ and VFIQ (2014-09-29 18:48:51 +0100)

----------------------------------------------------------------
target-arm:
 * more EL2/EL3 preparation work
 * don't handle c15_cpar changes via tb_flush()
 * fix some unused function warnings in ARM devices
 * build the GDB XML for 32 bit CPUs into qemu-*-aarch64
 * implement guest breakpoint support

----------------------------------------------------------------
Edgar E. Iglesias (11):
      target-arm: Add HCR_EL2
      target-arm: Add SCR_EL3
      target-arm: A64: Refactor aarch64_cpu_do_interrupt
      target-arm: Break out exception masking to a separate func
      target-arm: Don't take interrupts targeting lower ELs
      target-arm: A64: Correct updates to FAR and ESR on exceptions
      target-arm: A64: Emulate the HVC insn
      target-arm: Add a Hypervisor Trap exception type
      target-arm: A64: Emulate the SMC insn
      target-arm: Add IRQ and FIQ routing to EL2 and 3
      target-arm: Add support for VIRQ and VFIQ

Peter Maydell (8):
      target-arm: Implement setting guest breakpoints
      target-arm: Implement handling of breakpoint firing
      configure: Build GDB XML for 32 bit ARM CPUs into qemu aarch64 binaries
      hw/display/blizzard.c: Delete unused function blizzard_rgb2yuv
      hw/intc/imx_avic.c: Remove unused function imx_avic_set_prio()
      hw/display/pxa2xx_lcd.c: Remove unused function pxa2xx_dma_rdst_set
      hw/input/tsc210x.c: Delete unused array tsc2101_rates
      target-arm: Don't handle c15_cpar changes via tb_flush()

 configure                  |   2 +-
 hw/display/blizzard.c      |   8 --
 hw/display/pxa2xx_lcd.c    |   8 --
 hw/input/tsc210x.c         |  30 ------
 hw/intc/imx_avic.c         |   9 --
 target-arm/cpu.c           |  60 +++++++----
 target-arm/cpu.h           | 138 +++++++++++++++++++++++-
 target-arm/helper-a64.c    |  32 +++---
 target-arm/helper.c        | 258 +++++++++++++++++++++++++++++++++++++++++++--
 target-arm/helper.h        |   2 +
 target-arm/internals.h     |  30 ++++++
 target-arm/machine.c       |   1 +
 target-arm/op_helper.c     | 143 ++++++++++++++++++++++---
 target-arm/translate-a64.c |  44 ++++++--
 target-arm/translate.c     |  40 +++----
 target-arm/translate.h     |   2 +
 16 files changed, 662 insertions(+), 145 deletions(-)

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

* [Qemu-devel] [PULL 01/19] target-arm: Implement setting guest breakpoints
  2014-09-29 18:26 [Qemu-devel] [PULL 00/19] target-arm queue Peter Maydell
@ 2014-09-29 18:26 ` Peter Maydell
  2014-09-29 18:26 ` [Qemu-devel] [PULL 02/19] target-arm: Implement handling of breakpoint firing Peter Maydell
                   ` (18 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Peter Maydell @ 2014-09-29 18:26 UTC (permalink / raw)
  To: qemu-devel

This patch adds support for setting guest breakpoints
based on values the guest writes to the DBGBVR and DBGBCR
registers. (It doesn't include the code to handle when
these breakpoints fire, so has no guest-visible effect.)

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1410523465-13400-2-git-send-email-peter.maydell@linaro.org
---
 target-arm/cpu.c       |   1 +
 target-arm/cpu.h       |   1 +
 target-arm/helper.c    | 126 ++++++++++++++++++++++++++++++++++++++++++++++++-
 target-arm/internals.h |   9 ++++
 target-arm/machine.c   |   1 +
 5 files changed, 136 insertions(+), 2 deletions(-)

diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 407f977..6ab0e03 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -185,6 +185,7 @@ static void arm_cpu_reset(CPUState *s)
     }
 #endif
 
+    hw_breakpoint_update_all(cpu);
     hw_watchpoint_update_all(cpu);
 }
 
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index d1e1ccb..fa6ae0a 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -323,6 +323,7 @@ typedef struct CPUARMState {
     int eabi;
 #endif
 
+    struct CPUBreakpoint *cpu_breakpoint[16];
     struct CPUWatchpoint *cpu_watchpoint[16];
 
     CPU_COMMON
diff --git a/target-arm/helper.c b/target-arm/helper.c
index ece9673..d246d36 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2492,6 +2492,124 @@ static void dbgwcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
     hw_watchpoint_update(cpu, i);
 }
 
+void hw_breakpoint_update(ARMCPU *cpu, int n)
+{
+    CPUARMState *env = &cpu->env;
+    uint64_t bvr = env->cp15.dbgbvr[n];
+    uint64_t bcr = env->cp15.dbgbcr[n];
+    vaddr addr;
+    int bt;
+    int flags = BP_CPU;
+
+    if (env->cpu_breakpoint[n]) {
+        cpu_breakpoint_remove_by_ref(CPU(cpu), env->cpu_breakpoint[n]);
+        env->cpu_breakpoint[n] = NULL;
+    }
+
+    if (!extract64(bcr, 0, 1)) {
+        /* E bit clear : watchpoint disabled */
+        return;
+    }
+
+    bt = extract64(bcr, 20, 4);
+
+    switch (bt) {
+    case 4: /* unlinked address mismatch (reserved if AArch64) */
+    case 5: /* linked address mismatch (reserved if AArch64) */
+        qemu_log_mask(LOG_UNIMP,
+                      "arm: address mismatch breakpoint types not implemented");
+        return;
+    case 0: /* unlinked address match */
+    case 1: /* linked address match */
+    {
+        /* Bits [63:49] are hardwired to the value of bit [48]; that is,
+         * we behave as if the register was sign extended. Bits [1:0] are
+         * RES0. The BAS field is used to allow setting breakpoints on 16
+         * bit wide instructions; it is CONSTRAINED UNPREDICTABLE whether
+         * a bp will fire if the addresses covered by the bp and the addresses
+         * covered by the insn overlap but the insn doesn't start at the
+         * start of the bp address range. We choose to require the insn and
+         * the bp to have the same address. The constraints on writing to
+         * BAS enforced in dbgbcr_write mean we have only four cases:
+         *  0b0000  => no breakpoint
+         *  0b0011  => breakpoint on addr
+         *  0b1100  => breakpoint on addr + 2
+         *  0b1111  => breakpoint on addr
+         * See also figure D2-3 in the v8 ARM ARM (DDI0487A.c).
+         */
+        int bas = extract64(bcr, 5, 4);
+        addr = sextract64(bvr, 0, 49) & ~3ULL;
+        if (bas == 0) {
+            return;
+        }
+        if (bas == 0xc) {
+            addr += 2;
+        }
+        break;
+    }
+    case 2: /* unlinked context ID match */
+    case 8: /* unlinked VMID match (reserved if no EL2) */
+    case 10: /* unlinked context ID and VMID match (reserved if no EL2) */
+        qemu_log_mask(LOG_UNIMP,
+                      "arm: unlinked context breakpoint types not implemented");
+        return;
+    case 9: /* linked VMID match (reserved if no EL2) */
+    case 11: /* linked context ID and VMID match (reserved if no EL2) */
+    case 3: /* linked context ID match */
+    default:
+        /* We must generate no events for Linked context matches (unless
+         * they are linked to by some other bp/wp, which is handled in
+         * updates for the linking bp/wp). We choose to also generate no events
+         * for reserved values.
+         */
+        return;
+    }
+
+    cpu_breakpoint_insert(CPU(cpu), addr, flags, &env->cpu_breakpoint[n]);
+}
+
+void hw_breakpoint_update_all(ARMCPU *cpu)
+{
+    int i;
+    CPUARMState *env = &cpu->env;
+
+    /* Completely clear out existing QEMU breakpoints and our array, to
+     * avoid possible stale entries following migration load.
+     */
+    cpu_breakpoint_remove_all(CPU(cpu), BP_CPU);
+    memset(env->cpu_breakpoint, 0, sizeof(env->cpu_breakpoint));
+
+    for (i = 0; i < ARRAY_SIZE(cpu->env.cpu_breakpoint); i++) {
+        hw_breakpoint_update(cpu, i);
+    }
+}
+
+static void dbgbvr_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                         uint64_t value)
+{
+    ARMCPU *cpu = arm_env_get_cpu(env);
+    int i = ri->crm;
+
+    raw_write(env, ri, value);
+    hw_breakpoint_update(cpu, i);
+}
+
+static void dbgbcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                         uint64_t value)
+{
+    ARMCPU *cpu = arm_env_get_cpu(env);
+    int i = ri->crm;
+
+    /* BAS[3] is a read-only copy of BAS[2], and BAS[1] a read-only
+     * copy of BAS[0].
+     */
+    value = deposit64(value, 6, 1, extract64(value, 5, 1));
+    value = deposit64(value, 8, 1, extract64(value, 7, 1));
+
+    raw_write(env, ri, value);
+    hw_breakpoint_update(cpu, i);
+}
+
 static void define_debug_regs(ARMCPU *cpu)
 {
     /* Define v7 and v8 architectural debug registers.
@@ -2533,11 +2651,15 @@ static void define_debug_regs(ARMCPU *cpu)
             { .name = "DBGBVR", .state = ARM_CP_STATE_BOTH,
               .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 4,
               .access = PL1_RW,
-              .fieldoffset = offsetof(CPUARMState, cp15.dbgbvr[i]) },
+              .fieldoffset = offsetof(CPUARMState, cp15.dbgbvr[i]),
+              .writefn = dbgbvr_write, .raw_writefn = raw_write
+            },
             { .name = "DBGBCR", .state = ARM_CP_STATE_BOTH,
               .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 5,
               .access = PL1_RW,
-              .fieldoffset = offsetof(CPUARMState, cp15.dbgbcr[i]) },
+              .fieldoffset = offsetof(CPUARMState, cp15.dbgbcr[i]),
+              .writefn = dbgbcr_write, .raw_writefn = raw_write
+            },
             REGINFO_SENTINEL
         };
         define_arm_cp_regs(cpu, dbgregs);
diff --git a/target-arm/internals.h b/target-arm/internals.h
index 64751a0..b7e4822 100644
--- a/target-arm/internals.h
+++ b/target-arm/internals.h
@@ -322,6 +322,15 @@ void hw_watchpoint_update(ARMCPU *cpu, int n);
  * suitable for use after migration or on reset.
  */
 void hw_watchpoint_update_all(ARMCPU *cpu);
+/* Update a QEMU breakpoint based on the information the guest has set in the
+ * DBGBCR<n>_EL1 and DBGBVR<n>_EL1 registers.
+ */
+void hw_breakpoint_update(ARMCPU *cpu, int n);
+/* Update the QEMU breakpoints for every guest breakpoint. This does a
+ * complete delete-and-reinstate of the QEMU breakpoint list and so is
+ * suitable for use after migration or on reset.
+ */
+void hw_breakpoint_update_all(ARMCPU *cpu);
 
 /* Callback function for when a watchpoint or breakpoint triggers. */
 void arm_debug_excp_handler(CPUState *cs);
diff --git a/target-arm/machine.c b/target-arm/machine.c
index 8dfe87c..ddb7d05 100644
--- a/target-arm/machine.c
+++ b/target-arm/machine.c
@@ -214,6 +214,7 @@ static int cpu_post_load(void *opaque, int version_id)
         }
     }
 
+    hw_breakpoint_update_all(cpu);
     hw_watchpoint_update_all(cpu);
 
     return 0;
-- 
1.9.1

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

* [Qemu-devel] [PULL 02/19] target-arm: Implement handling of breakpoint firing
  2014-09-29 18:26 [Qemu-devel] [PULL 00/19] target-arm queue Peter Maydell
  2014-09-29 18:26 ` [Qemu-devel] [PULL 01/19] target-arm: Implement setting guest breakpoints Peter Maydell
@ 2014-09-29 18:26 ` Peter Maydell
  2014-09-29 18:26 ` [Qemu-devel] [PULL 03/19] configure: Build GDB XML for 32 bit ARM CPUs into qemu aarch64 binaries Peter Maydell
                   ` (17 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Peter Maydell @ 2014-09-29 18:26 UTC (permalink / raw)
  To: qemu-devel

Implement handling of breakpoint event firing to correctly
inject the debug exception into the guest.

Since the breakpoint and watchpoint control register format is
very similar we adjust wp_matches() to also handle breakpoints
as well rather than using a separate function.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1410523465-13400-3-git-send-email-peter.maydell@linaro.org
---
 target-arm/internals.h |  6 ++++
 target-arm/op_helper.c | 75 ++++++++++++++++++++++++++++++++++++++++----------
 2 files changed, 66 insertions(+), 15 deletions(-)

diff --git a/target-arm/internals.h b/target-arm/internals.h
index b7e4822..986a7b1 100644
--- a/target-arm/internals.h
+++ b/target-arm/internals.h
@@ -313,6 +313,12 @@ static inline uint32_t syn_watchpoint(int same_el, int cm, int wnr)
         | (cm << 8) | (wnr << 6) | 0x22;
 }
 
+static inline uint32_t syn_breakpoint(int same_el)
+{
+    return (EC_BREAKPOINT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT)
+        | ARM_EL_IL | 0x22;
+}
+
 /* Update a QEMU watchpoint based on the information the guest has set in the
  * DBGWCR<n>_EL1 and DBGWVR<n>_EL1 registers.
  */
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index b956216..d0bcd97 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -511,32 +511,43 @@ static bool linked_bp_matches(ARMCPU *cpu, int lbn)
     return false;
 }
 
-static bool wp_matches(ARMCPU *cpu, int n)
+static bool bp_wp_matches(ARMCPU *cpu, int n, bool is_wp)
 {
     CPUARMState *env = &cpu->env;
-    uint64_t wcr = env->cp15.dbgwcr[n];
+    uint64_t cr;
     int pac, hmc, ssc, wt, lbn;
     /* TODO: check against CPU security state when we implement TrustZone */
     bool is_secure = false;
 
-    if (!env->cpu_watchpoint[n]
-        || !(env->cpu_watchpoint[n]->flags & BP_WATCHPOINT_HIT)) {
-        return false;
-    }
+    if (is_wp) {
+        if (!env->cpu_watchpoint[n]
+            || !(env->cpu_watchpoint[n]->flags & BP_WATCHPOINT_HIT)) {
+            return false;
+        }
+        cr = env->cp15.dbgwcr[n];
+    } else {
+        uint64_t pc = is_a64(env) ? env->pc : env->regs[15];
 
+        if (!env->cpu_breakpoint[n] || env->cpu_breakpoint[n]->pc != pc) {
+            return false;
+        }
+        cr = env->cp15.dbgbcr[n];
+    }
     /* The WATCHPOINT_HIT flag guarantees us that the watchpoint is
-     * enabled and that the address and access type match; check the
-     * remaining fields, including linked breakpoints.
-     * Note that some combinations of {PAC, HMC SSC} are reserved and
+     * enabled and that the address and access type match; for breakpoints
+     * we know the address matched; check the remaining fields, including
+     * linked breakpoints. We rely on WCR and BCR having the same layout
+     * for the LBN, SSC, HMC, PAC/PMC and is-linked fields.
+     * Note that some combinations of {PAC, HMC, SSC} are reserved and
      * must act either like some valid combination or as if the watchpoint
      * were disabled. We choose the former, and use this together with
      * the fact that EL3 must always be Secure and EL2 must always be
      * Non-Secure to simplify the code slightly compared to the full
      * table in the ARM ARM.
      */
-    pac = extract64(wcr, 1, 2);
-    hmc = extract64(wcr, 13, 1);
-    ssc = extract64(wcr, 14, 2);
+    pac = extract64(cr, 1, 2);
+    hmc = extract64(cr, 13, 1);
+    ssc = extract64(cr, 14, 2);
 
     switch (ssc) {
     case 0:
@@ -560,6 +571,7 @@ static bool wp_matches(ARMCPU *cpu, int n)
      * Implementing this would require reworking the core watchpoint code
      * to plumb the mmu_idx through to this point. Luckily Linux does not
      * rely on this behaviour currently.
+     * For breakpoints we do want to use the current CPU state.
      */
     switch (arm_current_pl(env)) {
     case 3:
@@ -582,8 +594,8 @@ static bool wp_matches(ARMCPU *cpu, int n)
         g_assert_not_reached();
     }
 
-    wt = extract64(wcr, 20, 1);
-    lbn = extract64(wcr, 16, 4);
+    wt = extract64(cr, 20, 1);
+    lbn = extract64(cr, 16, 4);
 
     if (wt && !linked_bp_matches(cpu, lbn)) {
         return false;
@@ -606,7 +618,28 @@ static bool check_watchpoints(ARMCPU *cpu)
     }
 
     for (n = 0; n < ARRAY_SIZE(env->cpu_watchpoint); n++) {
-        if (wp_matches(cpu, n)) {
+        if (bp_wp_matches(cpu, n, true)) {
+            return true;
+        }
+    }
+    return false;
+}
+
+static bool check_breakpoints(ARMCPU *cpu)
+{
+    CPUARMState *env = &cpu->env;
+    int n;
+
+    /* If breakpoints are disabled globally or we can't take debug
+     * exceptions here then breakpoint firings are ignored.
+     */
+    if (extract32(env->cp15.mdscr_el1, 15, 1) == 0
+        || !arm_generate_debug_exceptions(env)) {
+        return false;
+    }
+
+    for (n = 0; n < ARRAY_SIZE(env->cpu_breakpoint); n++) {
+        if (bp_wp_matches(cpu, n, false)) {
             return true;
         }
     }
@@ -641,6 +674,18 @@ void arm_debug_excp_handler(CPUState *cs)
                 cpu_resume_from_signal(cs, NULL);
             }
         }
+    } else {
+        if (check_breakpoints(cpu)) {
+            bool same_el = (arm_debug_target_el(env) == arm_current_pl(env));
+            env->exception.syndrome = syn_breakpoint(same_el);
+            if (extended_addresses_enabled(env)) {
+                env->exception.fsr = (1 << 9) | 0x22;
+            } else {
+                env->exception.fsr = 0x2;
+            }
+            /* FAR is UNKNOWN, so doesn't need setting */
+            raise_exception(env, EXCP_PREFETCH_ABORT);
+        }
     }
 }
 
-- 
1.9.1

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

* [Qemu-devel] [PULL 03/19] configure: Build GDB XML for 32 bit ARM CPUs into qemu aarch64 binaries
  2014-09-29 18:26 [Qemu-devel] [PULL 00/19] target-arm queue Peter Maydell
  2014-09-29 18:26 ` [Qemu-devel] [PULL 01/19] target-arm: Implement setting guest breakpoints Peter Maydell
  2014-09-29 18:26 ` [Qemu-devel] [PULL 02/19] target-arm: Implement handling of breakpoint firing Peter Maydell
@ 2014-09-29 18:26 ` Peter Maydell
  2014-09-29 18:26 ` [Qemu-devel] [PULL 04/19] hw/display/blizzard.c: Delete unused function blizzard_rgb2yuv Peter Maydell
                   ` (16 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Peter Maydell @ 2014-09-29 18:26 UTC (permalink / raw)
  To: qemu-devel

The qemu-aarch64 and qemu-system-aarch64 binaries include support
for all the 32 bit ARM CPUs as well as the 64 bit ones. This means
we need to build in the GDB XML files for the 32 bit CPUs too.
Otherwise gdb will complain:
 warning: while parsing target description (at line 1): Could not load XML document "arm-core.xml"
when you try to connect to our gdbserver to debug a 32 bit CPU
running in a qemu-aarch64 or qemu-system-aarch64 binary.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1410533739-13836-1-git-send-email-peter.maydell@linaro.org
---
 configure | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/configure b/configure
index 681abfc..9ac2600 100755
--- a/configure
+++ b/configure
@@ -5028,7 +5028,7 @@ case "$target_name" in
   aarch64)
     TARGET_BASE_ARCH=arm
     bflt="yes"
-    gdb_xml_files="aarch64-core.xml aarch64-fpu.xml"
+    gdb_xml_files="aarch64-core.xml aarch64-fpu.xml arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml"
   ;;
   cris)
   ;;
-- 
1.9.1

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

* [Qemu-devel] [PULL 04/19] hw/display/blizzard.c: Delete unused function blizzard_rgb2yuv
  2014-09-29 18:26 [Qemu-devel] [PULL 00/19] target-arm queue Peter Maydell
                   ` (2 preceding siblings ...)
  2014-09-29 18:26 ` [Qemu-devel] [PULL 03/19] configure: Build GDB XML for 32 bit ARM CPUs into qemu aarch64 binaries Peter Maydell
@ 2014-09-29 18:26 ` Peter Maydell
  2014-09-29 18:26 ` [Qemu-devel] [PULL 05/19] hw/intc/imx_avic.c: Remove unused function imx_avic_set_prio() Peter Maydell
                   ` (15 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Peter Maydell @ 2014-09-29 18:26 UTC (permalink / raw)
  To: qemu-devel

The function blizzard_rgb2yuv() is unused; delete it.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1410723223-17711-2-git-send-email-peter.maydell@linaro.org
---
 hw/display/blizzard.c | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/hw/display/blizzard.c b/hw/display/blizzard.c
index 55c0ddf..92b1fac 100644
--- a/hw/display/blizzard.c
+++ b/hw/display/blizzard.c
@@ -134,14 +134,6 @@ static const int blizzard_iformat_bpp[0x10] = {
     0, 0, 0, 0, 0, 0,
 };
 
-static inline void blizzard_rgb2yuv(int r, int g, int b,
-                int *y, int *u, int *v)
-{
-    *y = 0x10 + ((0x838 * r + 0x1022 * g + 0x322 * b) >> 13);
-    *u = 0x80 + ((0xe0e * b - 0x04c1 * r - 0x94e * g) >> 13);
-    *v = 0x80 + ((0xe0e * r - 0x0bc7 * g - 0x247 * b) >> 13);
-}
-
 static void blizzard_window(BlizzardState *s)
 {
     DisplaySurface *surface = qemu_console_surface(s->con);
-- 
1.9.1

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

* [Qemu-devel] [PULL 05/19] hw/intc/imx_avic.c: Remove unused function imx_avic_set_prio()
  2014-09-29 18:26 [Qemu-devel] [PULL 00/19] target-arm queue Peter Maydell
                   ` (3 preceding siblings ...)
  2014-09-29 18:26 ` [Qemu-devel] [PULL 04/19] hw/display/blizzard.c: Delete unused function blizzard_rgb2yuv Peter Maydell
@ 2014-09-29 18:26 ` Peter Maydell
  2014-09-29 18:26 ` [Qemu-devel] [PULL 06/19] hw/display/pxa2xx_lcd.c: Remove unused function pxa2xx_dma_rdst_set Peter Maydell
                   ` (14 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Peter Maydell @ 2014-09-29 18:26 UTC (permalink / raw)
  To: qemu-devel

The function imx_avic_set_prio() is unused; delete it.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1410723223-17711-3-git-send-email-peter.maydell@linaro.org
---
 hw/intc/imx_avic.c | 9 ---------
 1 file changed, 9 deletions(-)

diff --git a/hw/intc/imx_avic.c b/hw/intc/imx_avic.c
index ec5f9ad..e48f66c 100644
--- a/hw/intc/imx_avic.c
+++ b/hw/intc/imx_avic.c
@@ -97,15 +97,6 @@ static inline int imx_avic_prio(IMXAVICState *s, int irq)
     return 0xf & (s->prio[word] >> part);
 }
 
-static inline void imx_avic_set_prio(IMXAVICState *s, int irq, int prio)
-{
-    uint32_t word = irq / PRIO_PER_WORD;
-    uint32_t part = 4 * (irq % PRIO_PER_WORD);
-    uint32_t mask = ~(0xf << part);
-    s->prio[word] &= mask;
-    s->prio[word] |= prio << part;
-}
-
 /* Update interrupts.  */
 static void imx_avic_update(IMXAVICState *s)
 {
-- 
1.9.1

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

* [Qemu-devel] [PULL 06/19] hw/display/pxa2xx_lcd.c: Remove unused function pxa2xx_dma_rdst_set
  2014-09-29 18:26 [Qemu-devel] [PULL 00/19] target-arm queue Peter Maydell
                   ` (4 preceding siblings ...)
  2014-09-29 18:26 ` [Qemu-devel] [PULL 05/19] hw/intc/imx_avic.c: Remove unused function imx_avic_set_prio() Peter Maydell
@ 2014-09-29 18:26 ` Peter Maydell
  2014-09-29 18:26 ` [Qemu-devel] [PULL 07/19] hw/input/tsc210x.c: Delete unused array tsc2101_rates Peter Maydell
                   ` (13 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Peter Maydell @ 2014-09-29 18:26 UTC (permalink / raw)
  To: qemu-devel

The function pxa2xx_dma_rdst_set() is unused; delete it.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1410723223-17711-4-git-send-email-peter.maydell@linaro.org
---
 hw/display/pxa2xx_lcd.c | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/hw/display/pxa2xx_lcd.c b/hw/display/pxa2xx_lcd.c
index 611fb17..ac3c018 100644
--- a/hw/display/pxa2xx_lcd.c
+++ b/hw/display/pxa2xx_lcd.c
@@ -279,14 +279,6 @@ static inline void pxa2xx_dma_ber_set(PXA2xxLCDState *s, int ch)
         s->liidr = s->dma_ch[ch].id;
 }
 
-/* Set Read Status interrupt high and poke associated registers */
-static inline void pxa2xx_dma_rdst_set(PXA2xxLCDState *s)
-{
-    s->status[0] |= LCSR0_RDST;
-    if (s->irqlevel && !(s->control[0] & LCCR0_RDSTM))
-        s->status[0] |= LCSR0_SINT;
-}
-
 /* Load new Frame Descriptors from DMA */
 static void pxa2xx_descriptor_load(PXA2xxLCDState *s)
 {
-- 
1.9.1

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

* [Qemu-devel] [PULL 07/19] hw/input/tsc210x.c: Delete unused array tsc2101_rates
  2014-09-29 18:26 [Qemu-devel] [PULL 00/19] target-arm queue Peter Maydell
                   ` (5 preceding siblings ...)
  2014-09-29 18:26 ` [Qemu-devel] [PULL 06/19] hw/display/pxa2xx_lcd.c: Remove unused function pxa2xx_dma_rdst_set Peter Maydell
@ 2014-09-29 18:26 ` Peter Maydell
  2014-09-29 18:26 ` [Qemu-devel] [PULL 08/19] target-arm: Don't handle c15_cpar changes via tb_flush() Peter Maydell
                   ` (12 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Peter Maydell @ 2014-09-29 18:26 UTC (permalink / raw)
  To: qemu-devel

The array tsc2101_rates[] is unused (and we don't implement
the TSC2101 anyway, only the 2102); delete it.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1410723223-17711-5-git-send-email-peter.maydell@linaro.org
---
 hw/input/tsc210x.c | 30 ------------------------------
 1 file changed, 30 deletions(-)

diff --git a/hw/input/tsc210x.c b/hw/input/tsc210x.c
index aa5b688..fae3385 100644
--- a/hw/input/tsc210x.c
+++ b/hw/input/tsc210x.c
@@ -215,36 +215,6 @@ typedef struct {
     int fsref;
 } TSC210xRateInfo;
 
-/*  { rate,  dsor,  fsref } */
-static const TSC210xRateInfo tsc2101_rates[] = {
-    /* Fsref / 6.0 */
-    { 7350,	7,	1 },
-    { 8000,	7,	0 },
-    /* Fsref / 5.5 */
-    { 8018,	6,	1 },
-    { 8727,	6,	0 },
-    /* Fsref / 5.0 */
-    { 8820,	5,	1 },
-    { 9600,	5,	0 },
-    /* Fsref / 4.0 */
-    { 11025,	4,	1 },
-    { 12000,	4,	0 },
-    /* Fsref / 3.0 */
-    { 14700,	3,	1 },
-    { 16000,	3,	0 },
-    /* Fsref / 2.0 */
-    { 22050,	2,	1 },
-    { 24000,	2,	0 },
-    /* Fsref / 1.5 */
-    { 29400,	1,	1 },
-    { 32000,	1,	0 },
-    /* Fsref */
-    { 44100,	0,	1 },
-    { 48000,	0,	0 },
-
-    { 0,	0, 	0 },
-};
-
 /*  { rate,   dsor, fsref }	*/
 static const TSC210xRateInfo tsc2102_rates[] = {
     /* Fsref / 6.0 */
-- 
1.9.1

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

* [Qemu-devel] [PULL 08/19] target-arm: Don't handle c15_cpar changes via tb_flush()
  2014-09-29 18:26 [Qemu-devel] [PULL 00/19] target-arm queue Peter Maydell
                   ` (6 preceding siblings ...)
  2014-09-29 18:26 ` [Qemu-devel] [PULL 07/19] hw/input/tsc210x.c: Delete unused array tsc2101_rates Peter Maydell
@ 2014-09-29 18:26 ` Peter Maydell
  2014-09-29 18:26 ` [Qemu-devel] [PULL 09/19] target-arm: Add HCR_EL2 Peter Maydell
                   ` (11 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Peter Maydell @ 2014-09-29 18:26 UTC (permalink / raw)
  To: qemu-devel

At the moment we try to handle c15_cpar with the strategy of:
 * emit generated code which makes assumptions about its value
 * when the register value changes call tb_flush() to throw
   away the now-invalid generated code
This works because XScale CPUs are always uniprocessor, but
it's confusing because it suggests that the same approach can
be taken for other registers. It also means we do a tb_flush()
on CPU reset, which makes multithreaded linux-user binaries
even more likely to fail than would otherwise be the case.

Replace it with a combination of TB flags for the access
checks done on cp0/cp1 for the XScale and iwMMXt instructions,
plus a runtime check for cp2..cp13 coprocessor accesses.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1411056959-23070-1-git-send-email-peter.maydell@linaro.org
---
 target-arm/cpu.c       |  5 -----
 target-arm/cpu.h       |  9 +++++++++
 target-arm/helper.c    |  7 +------
 target-arm/op_helper.c | 11 +++++++++++
 target-arm/translate.c | 40 +++++++++++++++++++++-------------------
 target-arm/translate.h |  2 ++
 6 files changed, 44 insertions(+), 30 deletions(-)

diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 6ab0e03..248778d 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -173,11 +173,6 @@ static void arm_cpu_reset(CPUState *s)
     set_float_detect_tininess(float_tininess_before_rounding,
                               &env->vfp.standard_fp_status);
     tlb_flush(s, 1);
-    /* Reset is a state change for some CPUARMState fields which we
-     * bake assumptions about into translated code, so we need to
-     * tb_flush().
-     */
-    tb_flush(env);
 
 #ifndef CONFIG_USER_ONLY
     if (kvm_enabled()) {
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index fa6ae0a..7bd3af9 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1224,6 +1224,11 @@ static inline bool arm_singlestep_active(CPUARMState *env)
 #define ARM_TBFLAG_SS_ACTIVE_MASK (1 << ARM_TBFLAG_SS_ACTIVE_SHIFT)
 #define ARM_TBFLAG_PSTATE_SS_SHIFT 19
 #define ARM_TBFLAG_PSTATE_SS_MASK (1 << ARM_TBFLAG_PSTATE_SS_SHIFT)
+/* We store the bottom two bits of the CPAR as TB flags and handle
+ * checks on the other bits at runtime
+ */
+#define ARM_TBFLAG_XSCALE_CPAR_SHIFT 20
+#define ARM_TBFLAG_XSCALE_CPAR_MASK (3 << ARM_TBFLAG_XSCALE_CPAR_SHIFT)
 
 /* Bit usage when in AArch64 state */
 #define ARM_TBFLAG_AA64_EL_SHIFT    0
@@ -1258,6 +1263,8 @@ static inline bool arm_singlestep_active(CPUARMState *env)
     (((F) & ARM_TBFLAG_SS_ACTIVE_MASK) >> ARM_TBFLAG_SS_ACTIVE_SHIFT)
 #define ARM_TBFLAG_PSTATE_SS(F) \
     (((F) & ARM_TBFLAG_PSTATE_SS_MASK) >> ARM_TBFLAG_PSTATE_SS_SHIFT)
+#define ARM_TBFLAG_XSCALE_CPAR(F) \
+    (((F) & ARM_TBFLAG_XSCALE_CPAR_MASK) >> ARM_TBFLAG_XSCALE_CPAR_SHIFT)
 #define ARM_TBFLAG_AA64_EL(F) \
     (((F) & ARM_TBFLAG_AA64_EL_MASK) >> ARM_TBFLAG_AA64_EL_SHIFT)
 #define ARM_TBFLAG_AA64_FPEN(F) \
@@ -1335,6 +1342,8 @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
                 *flags |= ARM_TBFLAG_PSTATE_SS_MASK;
             }
         }
+        *flags |= (extract32(env->cp15.c15_cpar, 0, 2)
+                   << ARM_TBFLAG_XSCALE_CPAR_SHIFT);
     }
 
     *cs_base = 0;
diff --git a/target-arm/helper.c b/target-arm/helper.c
index d246d36..dd9fca5 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1714,12 +1714,7 @@ static const ARMCPRegInfo omap_cp_reginfo[] = {
 static void xscale_cpar_write(CPUARMState *env, const ARMCPRegInfo *ri,
                               uint64_t value)
 {
-    value &= 0x3fff;
-    if (env->cp15.c15_cpar != value) {
-        /* Changes cp0 to cp13 behavior, so needs a TB flush.  */
-        tb_flush(env);
-        env->cp15.c15_cpar = value;
-    }
+    env->cp15.c15_cpar = value & 0x3fff;
 }
 
 static const ARMCPRegInfo xscale_cp_reginfo[] = {
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index d0bcd97..25243bd 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -301,6 +301,17 @@ void HELPER(set_user_reg)(CPUARMState *env, uint32_t regno, uint32_t val)
 void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip, uint32_t syndrome)
 {
     const ARMCPRegInfo *ri = rip;
+
+    if (arm_feature(env, ARM_FEATURE_XSCALE) && ri->cp < 14
+        && extract32(env->cp15.c15_cpar, ri->cp, 1) == 0) {
+        env->exception.syndrome = syndrome;
+        raise_exception(env, EXCP_UDEF);
+    }
+
+    if (!ri->accessfn) {
+        return;
+    }
+
     switch (ri->accessfn(env, ri)) {
     case CP_ACCESS_OK:
         return;
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 2c0b1de..8a2994f 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -7001,22 +7001,18 @@ static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
     const ARMCPRegInfo *ri;
 
     cpnum = (insn >> 8) & 0xf;
-    if (arm_feature(env, ARM_FEATURE_XSCALE)
-	    && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
-	return 1;
-
-    /* First check for coprocessor space used for actual instructions */
-    switch (cpnum) {
-      case 0:
-      case 1:
-	if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
-	    return disas_iwmmxt_insn(env, s, insn);
-	} else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
-	    return disas_dsp_insn(env, s, insn);
-	}
-	return 1;
-    default:
-        break;
+
+    /* First check for coprocessor space used for XScale/iwMMXt insns */
+    if (arm_feature(env, ARM_FEATURE_XSCALE) && (cpnum < 2)) {
+        if (extract32(s->c15_cpar, cpnum, 1) == 0) {
+            return 1;
+        }
+        if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
+            return disas_iwmmxt_insn(env, s, insn);
+        } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
+            return disas_dsp_insn(env, s, insn);
+        }
+        return 1;
     }
 
     /* Otherwise treat as a generic register access */
@@ -7049,9 +7045,12 @@ static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
             return 1;
         }
 
-        if (ri->accessfn) {
+        if (ri->accessfn ||
+            (arm_feature(env, ARM_FEATURE_XSCALE) && cpnum < 14)) {
             /* Emit code to perform further access permissions checks at
              * runtime; this may result in an exception.
+             * Note that on XScale all cp0..c13 registers do an access check
+             * call in order to handle c15_cpar.
              */
             TCGv_ptr tmpptr;
             TCGv_i32 tcg_syn;
@@ -7675,9 +7674,11 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
         } else if ((insn & 0x0e000f00) == 0x0c000100) {
             if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
                 /* iWMMXt register transfer.  */
-                if (env->cp15.c15_cpar & (1 << 1))
-                    if (!disas_iwmmxt_insn(env, s, insn))
+                if (extract32(s->c15_cpar, 1, 1)) {
+                    if (!disas_iwmmxt_insn(env, s, insn)) {
                         return;
+                    }
+                }
             }
         } else if ((insn & 0x0fe00000) == 0x0c400000) {
             /* Coprocessor double register transfer.  */
@@ -10942,6 +10943,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
     dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
     dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags);
     dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
+    dc->c15_cpar = ARM_TBFLAG_XSCALE_CPAR(tb->flags);
     dc->cp_regs = cpu->cp_regs;
     dc->current_pl = arm_current_pl(env);
     dc->features = env->features;
diff --git a/target-arm/translate.h b/target-arm/translate.h
index b90d275..85c6f9d 100644
--- a/target-arm/translate.h
+++ b/target-arm/translate.h
@@ -52,6 +52,8 @@ typedef struct DisasContext {
     bool is_ldex;
     /* True if a single-step exception will be taken to the current EL */
     bool ss_same_el;
+    /* Bottom two bits of XScale c15_cpar coprocessor access control reg */
+    int c15_cpar;
 #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] 21+ messages in thread

* [Qemu-devel] [PULL 09/19] target-arm: Add HCR_EL2
  2014-09-29 18:26 [Qemu-devel] [PULL 00/19] target-arm queue Peter Maydell
                   ` (7 preceding siblings ...)
  2014-09-29 18:26 ` [Qemu-devel] [PULL 08/19] target-arm: Don't handle c15_cpar changes via tb_flush() Peter Maydell
@ 2014-09-29 18:26 ` Peter Maydell
  2014-09-29 18:26 ` [Qemu-devel] [PULL 10/19] target-arm: Add SCR_EL3 Peter Maydell
                   ` (10 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Peter Maydell @ 2014-09-29 18:26 UTC (permalink / raw)
  To: qemu-devel

From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>

Reviewed-by: Greg Bellows <greg.bellows@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1411718914-6608-2-git-send-email-edgar.iglesias@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/cpu.h    | 36 ++++++++++++++++++++++++++++++++++++
 target-arm/helper.c | 34 ++++++++++++++++++++++++++++++++++
 2 files changed, 70 insertions(+)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 7bd3af9..f5cbfdd 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -184,6 +184,7 @@ 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 */
+        uint64_t hcr_el2; /* Hypervisor configuration register */
         uint32_t ifsr_el2; /* Fault status registers.  */
         uint64_t esr_el[4];
         uint32_t c6_region[8]; /* MPU base/size registers.  */
@@ -566,6 +567,41 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
     }
 }
 
+#define HCR_VM        (1ULL << 0)
+#define HCR_SWIO      (1ULL << 1)
+#define HCR_PTW       (1ULL << 2)
+#define HCR_FMO       (1ULL << 3)
+#define HCR_IMO       (1ULL << 4)
+#define HCR_AMO       (1ULL << 5)
+#define HCR_VF        (1ULL << 6)
+#define HCR_VI        (1ULL << 7)
+#define HCR_VSE       (1ULL << 8)
+#define HCR_FB        (1ULL << 9)
+#define HCR_BSU_MASK  (3ULL << 10)
+#define HCR_DC        (1ULL << 12)
+#define HCR_TWI       (1ULL << 13)
+#define HCR_TWE       (1ULL << 14)
+#define HCR_TID0      (1ULL << 15)
+#define HCR_TID1      (1ULL << 16)
+#define HCR_TID2      (1ULL << 17)
+#define HCR_TID3      (1ULL << 18)
+#define HCR_TSC       (1ULL << 19)
+#define HCR_TIDCP     (1ULL << 20)
+#define HCR_TACR      (1ULL << 21)
+#define HCR_TSW       (1ULL << 22)
+#define HCR_TPC       (1ULL << 23)
+#define HCR_TPU       (1ULL << 24)
+#define HCR_TTLB      (1ULL << 25)
+#define HCR_TVM       (1ULL << 26)
+#define HCR_TGE       (1ULL << 27)
+#define HCR_TDZ       (1ULL << 28)
+#define HCR_HCD       (1ULL << 29)
+#define HCR_TRVM      (1ULL << 30)
+#define HCR_RW        (1ULL << 31)
+#define HCR_CD        (1ULL << 32)
+#define HCR_ID        (1ULL << 33)
+#define HCR_MASK      ((1ULL << 34) - 1)
+
 /* Return the current FPSCR value.  */
 uint32_t vfp_get_fpscr(CPUARMState *env);
 void vfp_set_fpscr(CPUARMState *env, uint32_t val);
diff --git a/target-arm/helper.c b/target-arm/helper.c
index dd9fca5..d117e83 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2225,10 +2225,44 @@ static const ARMCPRegInfo v8_el3_no_el2_cp_reginfo[] = {
       .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 0, .opc2 = 0,
       .access = PL2_RW,
       .readfn = arm_cp_read_zero, .writefn = arm_cp_write_ignore },
+    { .name = "HCR_EL2", .state = ARM_CP_STATE_AA64,
+      .type = ARM_CP_NO_MIGRATE,
+      .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 0,
+      .access = PL2_RW,
+      .readfn = arm_cp_read_zero, .writefn = arm_cp_write_ignore },
     REGINFO_SENTINEL
 };
 
+static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
+{
+    ARMCPU *cpu = arm_env_get_cpu(env);
+    uint64_t valid_mask = HCR_MASK;
+
+    if (arm_feature(env, ARM_FEATURE_EL3)) {
+        valid_mask &= ~HCR_HCD;
+    } else {
+        valid_mask &= ~HCR_TSC;
+    }
+
+    /* Clear RES0 bits.  */
+    value &= valid_mask;
+
+    /* These bits change the MMU setup:
+     * HCR_VM enables stage 2 translation
+     * HCR_PTW forbids certain page-table setups
+     * HCR_DC Disables stage1 and enables stage2 translation
+     */
+    if ((raw_read(env, ri) ^ value) & (HCR_VM | HCR_PTW | HCR_DC)) {
+        tlb_flush(CPU(cpu), 1);
+    }
+    raw_write(env, ri, value);
+}
+
 static const ARMCPRegInfo v8_el2_cp_reginfo[] = {
+    { .name = "HCR_EL2", .state = ARM_CP_STATE_AA64,
+      .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 0,
+      .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.hcr_el2),
+      .writefn = hcr_write },
     { .name = "ELR_EL2", .state = ARM_CP_STATE_AA64,
       .type = ARM_CP_NO_MIGRATE,
       .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 0, .opc2 = 1,
-- 
1.9.1

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

* [Qemu-devel] [PULL 10/19] target-arm: Add SCR_EL3
  2014-09-29 18:26 [Qemu-devel] [PULL 00/19] target-arm queue Peter Maydell
                   ` (8 preceding siblings ...)
  2014-09-29 18:26 ` [Qemu-devel] [PULL 09/19] target-arm: Add HCR_EL2 Peter Maydell
@ 2014-09-29 18:26 ` Peter Maydell
  2014-09-29 18:26 ` [Qemu-devel] [PULL 11/19] target-arm: A64: Refactor aarch64_cpu_do_interrupt Peter Maydell
                   ` (9 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Peter Maydell @ 2014-09-29 18:26 UTC (permalink / raw)
  To: qemu-devel

From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1411718914-6608-3-git-send-email-edgar.iglesias@gmail.com
[PMM: apply offsetoflow32() to correct regdef]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/cpu.h    | 19 ++++++++++++++++++-
 target-arm/helper.c | 35 +++++++++++++++++++++++++++++++++--
 2 files changed, 51 insertions(+), 3 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index f5cbfdd..8878d06 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -172,7 +172,6 @@ typedef struct CPUARMState {
         uint64_t c1_sys; /* System control register.  */
         uint64_t c1_coproc; /* Coprocessor access register.  */
         uint32_t c1_xscaleauxcr; /* XScale auxiliary control register.  */
-        uint32_t c1_scr; /* secure config register.  */
         uint64_t ttbr0_el1; /* MMU translation table base 0. */
         uint64_t ttbr1_el1; /* MMU translation table base 1. */
         uint64_t c2_control; /* MMU translation table base control.  */
@@ -185,6 +184,7 @@ typedef struct CPUARMState {
         uint32_t pmsav5_data_ap; /* PMSAv5 MPU data access permissions */
         uint32_t pmsav5_insn_ap; /* PMSAv5 MPU insn access permissions */
         uint64_t hcr_el2; /* Hypervisor configuration register */
+        uint64_t scr_el3; /* Secure configuration register.  */
         uint32_t ifsr_el2; /* Fault status registers.  */
         uint64_t esr_el[4];
         uint32_t c6_region[8]; /* MPU base/size registers.  */
@@ -602,6 +602,23 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
 #define HCR_ID        (1ULL << 33)
 #define HCR_MASK      ((1ULL << 34) - 1)
 
+#define SCR_NS                (1U << 0)
+#define SCR_IRQ               (1U << 1)
+#define SCR_FIQ               (1U << 2)
+#define SCR_EA                (1U << 3)
+#define SCR_FW                (1U << 4)
+#define SCR_AW                (1U << 5)
+#define SCR_NET               (1U << 6)
+#define SCR_SMD               (1U << 7)
+#define SCR_HCE               (1U << 8)
+#define SCR_SIF               (1U << 9)
+#define SCR_RW                (1U << 10)
+#define SCR_ST                (1U << 11)
+#define SCR_TWI               (1U << 12)
+#define SCR_TWE               (1U << 13)
+#define SCR_AARCH32_MASK      (0x3fff & ~(SCR_RW | SCR_ST))
+#define SCR_AARCH64_MASK      (0x3fff & ~SCR_NET)
+
 /* Return the current FPSCR value.  */
 uint32_t vfp_get_fpscr(CPUARMState *env);
 void vfp_set_fpscr(CPUARMState *env, uint32_t val);
diff --git a/target-arm/helper.c b/target-arm/helper.c
index d117e83..e47e7b4 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -747,6 +747,32 @@ static void vbar_write(CPUARMState *env, const ARMCPRegInfo *ri,
     raw_write(env, ri, value & ~0x1FULL);
 }
 
+static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
+{
+    /* We only mask off bits that are RES0 both for AArch64 and AArch32.
+     * For bits that vary between AArch32/64, code needs to check the
+     * current execution mode before directly using the feature bit.
+     */
+    uint32_t valid_mask = SCR_AARCH64_MASK | SCR_AARCH32_MASK;
+
+    if (!arm_feature(env, ARM_FEATURE_EL2)) {
+        valid_mask &= ~SCR_HCE;
+
+        /* On ARMv7, SMD (or SCD as it is called in v7) is only
+         * supported if EL2 exists. The bit is UNK/SBZP when
+         * EL2 is unavailable. In QEMU ARMv7, we force it to always zero
+         * when EL2 is unavailable.
+         */
+        if (arm_feature(env, ARM_FEATURE_V7)) {
+            valid_mask &= ~SCR_SMD;
+        }
+    }
+
+    /* Clear all-context RES0 bits.  */
+    value &= valid_mask;
+    raw_write(env, ri, value);
+}
+
 static uint64_t ccsidr_read(CPUARMState *env, const ARMCPRegInfo *ri)
 {
     ARMCPU *cpu = arm_env_get_cpu(env);
@@ -873,8 +899,8 @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
       .fieldoffset = offsetof(CPUARMState, cp15.vbar_el[1]),
       .resetvalue = 0 },
     { .name = "SCR", .cp = 15, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 0,
-      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c1_scr),
-      .resetvalue = 0, },
+      .access = PL1_RW, .fieldoffset = offsetoflow32(CPUARMState, cp15.scr_el3),
+      .resetvalue = 0, .writefn = scr_write },
     { .name = "CCSIDR", .state = ARM_CP_STATE_BOTH,
       .opc0 = 3, .crn = 0, .crm = 0, .opc1 = 1, .opc2 = 0,
       .access = PL1_R, .readfn = ccsidr_read, .type = ARM_CP_NO_MIGRATE },
@@ -2309,6 +2335,11 @@ static const ARMCPRegInfo v8_el3_cp_reginfo[] = {
       .access = PL3_RW, .writefn = vbar_write,
       .fieldoffset = offsetof(CPUARMState, cp15.vbar_el[3]),
       .resetvalue = 0 },
+    { .name = "SCR_EL3", .state = ARM_CP_STATE_AA64,
+      .type = ARM_CP_NO_MIGRATE,
+      .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 1, .opc2 = 0,
+      .access = PL3_RW, .fieldoffset = offsetof(CPUARMState, cp15.scr_el3),
+      .writefn = scr_write },
     REGINFO_SENTINEL
 };
 
-- 
1.9.1

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

* [Qemu-devel] [PULL 11/19] target-arm: A64: Refactor aarch64_cpu_do_interrupt
  2014-09-29 18:26 [Qemu-devel] [PULL 00/19] target-arm queue Peter Maydell
                   ` (9 preceding siblings ...)
  2014-09-29 18:26 ` [Qemu-devel] [PULL 10/19] target-arm: Add SCR_EL3 Peter Maydell
@ 2014-09-29 18:26 ` Peter Maydell
  2014-09-29 18:26 ` [Qemu-devel] [PULL 12/19] target-arm: Break out exception masking to a separate func Peter Maydell
                   ` (8 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Peter Maydell @ 2014-09-29 18:26 UTC (permalink / raw)
  To: qemu-devel

From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>

Introduce new_el and new_mode in preparation for future patches
that add support for taking exceptions to and from EL2 and 3.
No functional change.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1411718914-6608-4-git-send-email-edgar.iglesias@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/cpu.h        |  7 +++++++
 target-arm/helper-a64.c | 24 +++++++++++++-----------
 target-arm/helper.c     | 13 +++++++++++++
 3 files changed, 33 insertions(+), 11 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 8878d06..a3ba624 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -500,6 +500,12 @@ void pmccntr_sync(CPUARMState *env);
 #define PSTATE_MODE_EL1t 4
 #define PSTATE_MODE_EL0t 0
 
+/* Map EL and handler into a PSTATE_MODE.  */
+static inline unsigned int aarch64_pstate_mode(unsigned int el, bool handler)
+{
+    return (el << 2) | handler;
+}
+
 /* Return the current PSTATE value. For the moment we don't support 32<->64 bit
  * interprocessing, so we don't attempt to sync with the cpsr state used by
  * the 32 bit decoder.
@@ -755,6 +761,7 @@ static inline bool arm_el_is_aa64(CPUARMState *env, int el)
 }
 
 void arm_cpu_list(FILE *f, fprintf_function cpu_fprintf);
+unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx);
 
 /* Interface between CPU and Interrupt controller.  */
 void armv7m_nvic_set_pending(void *opaque, int irq);
diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c
index 2e9ef64..4be0784 100644
--- a/target-arm/helper-a64.c
+++ b/target-arm/helper-a64.c
@@ -443,10 +443,12 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
 {
     ARMCPU *cpu = ARM_CPU(cs);
     CPUARMState *env = &cpu->env;
-    target_ulong addr = env->cp15.vbar_el[1];
+    unsigned int new_el = arm_excp_target_el(cs, cs->exception_index);
+    target_ulong addr = env->cp15.vbar_el[new_el];
+    unsigned int new_mode = aarch64_pstate_mode(new_el, true);
     int i;
 
-    if (arm_current_pl(env) == 0) {
+    if (arm_current_pl(env) < new_el) {
         if (env->aarch64) {
             addr += 0x400;
         } else {
@@ -464,14 +466,14 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
                       env->exception.syndrome);
     }
 
-    env->cp15.esr_el[1] = env->exception.syndrome;
-    env->cp15.far_el[1] = env->exception.vaddress;
+    env->cp15.esr_el[new_el] = env->exception.syndrome;
+    env->cp15.far_el[new_el] = 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_el[1]);
+                      env->cp15.far_el[new_el]);
         break;
     case EXCP_BKPT:
     case EXCP_UDEF:
@@ -488,15 +490,15 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
     }
 
     if (is_a64(env)) {
-        env->banked_spsr[aarch64_banked_spsr_index(1)] = pstate_read(env);
+        env->banked_spsr[aarch64_banked_spsr_index(new_el)] = pstate_read(env);
         aarch64_save_sp(env, arm_current_pl(env));
-        env->elr_el[1] = env->pc;
+        env->elr_el[new_el] = env->pc;
     } else {
         env->banked_spsr[0] = cpsr_read(env);
         if (!env->thumb) {
-            env->cp15.esr_el[1] |= 1 << 25;
+            env->cp15.esr_el[new_el] |= 1 << 25;
         }
-        env->elr_el[1] = env->regs[15];
+        env->elr_el[new_el] = env->regs[15];
 
         for (i = 0; i < 15; i++) {
             env->xregs[i] = env->regs[i];
@@ -505,9 +507,9 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
         env->condexec_bits = 0;
     }
 
-    pstate_write(env, PSTATE_DAIF | PSTATE_MODE_EL1h);
+    pstate_write(env, PSTATE_DAIF | new_mode);
     env->aarch64 = 1;
-    aarch64_restore_sp(env, 1);
+    aarch64_restore_sp(env, new_el);
 
     env->pc = addr;
     cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
diff --git a/target-arm/helper.c b/target-arm/helper.c
index e47e7b4..25477bd 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3704,6 +3704,11 @@ uint32_t HELPER(get_r13_banked)(CPUARMState *env, uint32_t mode)
     return 0;
 }
 
+unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx)
+{
+    return 1;
+}
+
 #else
 
 /* Map CPU modes onto saved register banks.  */
@@ -3759,6 +3764,14 @@ void switch_mode(CPUARMState *env, int mode)
     env->spsr = env->banked_spsr[i];
 }
 
+/*
+ * Determine the target EL for a given exception type.
+ */
+unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx)
+{
+    return 1;
+}
+
 static void v7m_push(CPUARMState *env, uint32_t val)
 {
     CPUState *cs = CPU(arm_env_get_cpu(env));
-- 
1.9.1

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

* [Qemu-devel] [PULL 12/19] target-arm: Break out exception masking to a separate func
  2014-09-29 18:26 [Qemu-devel] [PULL 00/19] target-arm queue Peter Maydell
                   ` (10 preceding siblings ...)
  2014-09-29 18:26 ` [Qemu-devel] [PULL 11/19] target-arm: A64: Refactor aarch64_cpu_do_interrupt Peter Maydell
@ 2014-09-29 18:26 ` Peter Maydell
  2014-09-29 18:26 ` [Qemu-devel] [PULL 13/19] target-arm: Don't take interrupts targeting lower ELs Peter Maydell
                   ` (7 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Peter Maydell @ 2014-09-29 18:26 UTC (permalink / raw)
  To: qemu-devel

From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>

Reviewed-by: Greg Bellows <greg.bellows@linaro.org>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1411718914-6608-5-git-send-email-edgar.iglesias@gmail.com
[PMM: updated to account for recent cpu-exec refactoring]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/cpu.c |  7 ++-----
 target-arm/cpu.h | 15 +++++++++++++++
 2 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 248778d..b7cdcd7 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -187,12 +187,10 @@ static void arm_cpu_reset(CPUState *s)
 bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
 {
     CPUClass *cc = CPU_GET_CLASS(cs);
-    ARMCPU *cpu = ARM_CPU(cs);
-    CPUARMState *env = &cpu->env;
     bool ret = false;
 
     if (interrupt_request & CPU_INTERRUPT_FIQ
-        && !(env->daif & PSTATE_F)) {
+        && arm_excp_unmasked(cs, EXCP_FIQ)) {
         cs->exception_index = EXCP_FIQ;
         cc->do_interrupt(cs);
         ret = true;
@@ -207,8 +205,7 @@ bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
        We avoid this by disabling interrupts when
        pc contains a magic address.  */
     if (interrupt_request & CPU_INTERRUPT_HARD
-        && !(env->daif & PSTATE_I)
-        && (!IS_M(env) || env->regs[15] < 0xfffffff0)) {
+        && arm_excp_unmasked(cs, EXCP_IRQ)) {
         cs->exception_index = EXCP_IRQ;
         cc->do_interrupt(cs);
         ret = true;
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index a3ba624..cc2c210 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1172,6 +1172,21 @@ bool write_cpustate_to_list(ARMCPU *cpu);
 #  define TARGET_VIRT_ADDR_SPACE_BITS 32
 #endif
 
+static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx)
+{
+    CPUARMState *env = cs->env_ptr;
+
+    switch (excp_idx) {
+    case EXCP_FIQ:
+        return !(env->daif & PSTATE_F);
+    case EXCP_IRQ:
+        return !(env->daif & PSTATE_I)
+               && (!IS_M(env) || env->regs[15] < 0xfffffff0);
+    default:
+        g_assert_not_reached();
+    }
+}
+
 static inline CPUARMState *cpu_init(const char *cpu_model)
 {
     ARMCPU *cpu = cpu_arm_init(cpu_model);
-- 
1.9.1

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

* [Qemu-devel] [PULL 13/19] target-arm: Don't take interrupts targeting lower ELs
  2014-09-29 18:26 [Qemu-devel] [PULL 00/19] target-arm queue Peter Maydell
                   ` (11 preceding siblings ...)
  2014-09-29 18:26 ` [Qemu-devel] [PULL 12/19] target-arm: Break out exception masking to a separate func Peter Maydell
@ 2014-09-29 18:26 ` Peter Maydell
  2014-09-29 18:26 ` [Qemu-devel] [PULL 14/19] target-arm: A64: Correct updates to FAR and ESR on exceptions Peter Maydell
                   ` (6 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Peter Maydell @ 2014-09-29 18:26 UTC (permalink / raw)
  To: qemu-devel

From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Greg Bellows <greg.bellows@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1411718914-6608-6-git-send-email-edgar.iglesias@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/cpu.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index cc2c210..81e7e81 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1175,6 +1175,13 @@ bool write_cpustate_to_list(ARMCPU *cpu);
 static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx)
 {
     CPUARMState *env = cs->env_ptr;
+    unsigned int cur_el = arm_current_pl(env);
+    unsigned int target_el = arm_excp_target_el(cs, excp_idx);
+
+    /* Don't take exceptions if they target a lower EL.  */
+    if (cur_el > target_el) {
+        return false;
+    }
 
     switch (excp_idx) {
     case EXCP_FIQ:
-- 
1.9.1

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

* [Qemu-devel] [PULL 14/19] target-arm: A64: Correct updates to FAR and ESR on exceptions
  2014-09-29 18:26 [Qemu-devel] [PULL 00/19] target-arm queue Peter Maydell
                   ` (12 preceding siblings ...)
  2014-09-29 18:26 ` [Qemu-devel] [PULL 13/19] target-arm: Don't take interrupts targeting lower ELs Peter Maydell
@ 2014-09-29 18:26 ` Peter Maydell
  2014-09-29 18:26 ` [Qemu-devel] [PULL 15/19] target-arm: A64: Emulate the HVC insn Peter Maydell
                   ` (5 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Peter Maydell @ 2014-09-29 18:26 UTC (permalink / raw)
  To: qemu-devel

From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>

Not all exception types update both FAR and ESR.

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Greg Bellows <greg.bellows@linaro.org>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1411718914-6608-7-git-send-email-edgar.iglesias@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/helper-a64.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c
index 4be0784..c6ef8e9 100644
--- a/target-arm/helper-a64.c
+++ b/target-arm/helper-a64.c
@@ -466,18 +466,17 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
                       env->exception.syndrome);
     }
 
-    env->cp15.esr_el[new_el] = env->exception.syndrome;
-    env->cp15.far_el[new_el] = env->exception.vaddress;
-
     switch (cs->exception_index) {
     case EXCP_PREFETCH_ABORT:
     case EXCP_DATA_ABORT:
+        env->cp15.far_el[new_el] = env->exception.vaddress;
         qemu_log_mask(CPU_LOG_INT, "...with FAR 0x%" PRIx64 "\n",
                       env->cp15.far_el[new_el]);
-        break;
+        /* fall through */
     case EXCP_BKPT:
     case EXCP_UDEF:
     case EXCP_SWI:
+        env->cp15.esr_el[new_el] = env->exception.syndrome;
         break;
     case EXCP_IRQ:
         addr += 0x80;
-- 
1.9.1

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

* [Qemu-devel] [PULL 15/19] target-arm: A64: Emulate the HVC insn
  2014-09-29 18:26 [Qemu-devel] [PULL 00/19] target-arm queue Peter Maydell
                   ` (13 preceding siblings ...)
  2014-09-29 18:26 ` [Qemu-devel] [PULL 14/19] target-arm: A64: Correct updates to FAR and ESR on exceptions Peter Maydell
@ 2014-09-29 18:26 ` Peter Maydell
  2014-09-29 18:26 ` [Qemu-devel] [PULL 16/19] target-arm: Add a Hypervisor Trap exception type Peter Maydell
                   ` (4 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Peter Maydell @ 2014-09-29 18:26 UTC (permalink / raw)
  To: qemu-devel

From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1411718914-6608-8-git-send-email-edgar.iglesias@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/cpu.h           |  1 +
 target-arm/helper-a64.c    |  1 +
 target-arm/helper.c        | 20 +++++++++++++++++++-
 target-arm/helper.h        |  1 +
 target-arm/internals.h     |  6 ++++++
 target-arm/op_helper.c     | 31 +++++++++++++++++++++++++++++++
 target-arm/translate-a64.c | 31 ++++++++++++++++++++++---------
 7 files changed, 81 insertions(+), 10 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 81e7e81..e13b6d4 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -51,6 +51,7 @@
 #define EXCP_EXCEPTION_EXIT  8   /* Return from v7M exception.  */
 #define EXCP_KERNEL_TRAP     9   /* Jumped to kernel code page.  */
 #define EXCP_STREX          10
+#define EXCP_HVC            11   /* HyperVisor Call */
 
 #define ARMV7M_EXCP_RESET   1
 #define ARMV7M_EXCP_NMI     2
diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c
index c6ef8e9..4e6ca26 100644
--- a/target-arm/helper-a64.c
+++ b/target-arm/helper-a64.c
@@ -476,6 +476,7 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
     case EXCP_BKPT:
     case EXCP_UDEF:
     case EXCP_SWI:
+    case EXCP_HVC:
         env->cp15.esr_el[new_el] = env->exception.syndrome;
         break;
     case EXCP_IRQ:
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 25477bd..4d5a653 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3769,7 +3769,25 @@ void switch_mode(CPUARMState *env, int mode)
  */
 unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx)
 {
-    return 1;
+    ARMCPU *cpu = ARM_CPU(cs);
+    CPUARMState *env = &cpu->env;
+    unsigned int cur_el = arm_current_pl(env);
+    unsigned int target_el;
+
+    if (!env->aarch64) {
+        /* TODO: Add EL2 and 3 exception handling for AArch32.  */
+        return 1;
+    }
+
+    switch (excp_idx) {
+    case EXCP_HVC:
+        target_el = 2;
+        break;
+    default:
+        target_el = MAX(cur_el, 1);
+        break;
+    }
+    return target_el;
 }
 
 static void v7m_push(CPUARMState *env, uint32_t val)
diff --git a/target-arm/helper.h b/target-arm/helper.h
index 1d7003b..75fc1b3 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -50,6 +50,7 @@ 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)
+DEF_HELPER_1(pre_hvc, void, env)
 
 DEF_HELPER_3(cpsr_write, void, env, i32, i32)
 DEF_HELPER_1(cpsr_read, i32, env)
diff --git a/target-arm/internals.h b/target-arm/internals.h
index 986a7b1..25c5ec3 100644
--- a/target-arm/internals.h
+++ b/target-arm/internals.h
@@ -53,6 +53,7 @@ static const char * const excnames[] = {
     [EXCP_EXCEPTION_EXIT] = "QEMU v7M exception exit",
     [EXCP_KERNEL_TRAP] = "QEMU intercept of kernel commpage",
     [EXCP_STREX] = "QEMU intercept of STREX",
+    [EXCP_HVC] = "Hypervisor Call",
 };
 
 static inline void arm_log_exception(int idx)
@@ -215,6 +216,11 @@ 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_aa64_hvc(uint32_t imm16)
+{
+    return (EC_AA64_HVC << 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)
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 25243bd..e5cb690 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -385,6 +385,37 @@ void HELPER(clear_pstate_ss)(CPUARMState *env)
     env->pstate &= ~PSTATE_SS;
 }
 
+void HELPER(pre_hvc)(CPUARMState *env)
+{
+    int cur_el = arm_current_pl(env);
+    /* FIXME: Use actual secure state.  */
+    bool secure = false;
+    bool undef;
+
+    /* We've already checked that EL2 exists at translation time.
+     * EL3.HCE has priority over EL2.HCD.
+     */
+    if (arm_feature(env, ARM_FEATURE_EL3)) {
+        undef = !(env->cp15.scr_el3 & SCR_HCE);
+    } else {
+        undef = env->cp15.hcr_el2 & HCR_HCD;
+    }
+
+    /* In ARMv7 and ARMv8/AArch32, HVC is undef in secure state.
+     * For ARMv8/AArch64, HVC is allowed in EL3.
+     * Note that we've already trapped HVC from EL0 at translation
+     * time.
+     */
+    if (secure && (!is_a64(env) || cur_el == 1)) {
+        undef = true;
+    }
+
+    if (undef) {
+        env->exception.syndrome = syn_uncategorized();
+        raise_exception(env, EXCP_UDEF);
+    }
+}
+
 void HELPER(exception_return)(CPUARMState *env)
 {
     int cur_el = arm_current_pl(env);
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 8e66b6c..f4cb56e 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -1473,20 +1473,33 @@ static void disas_exc(DisasContext *s, uint32_t insn)
 
     switch (opc) {
     case 0:
-        /* SVC, HVC, SMC; since we don't support the Virtualization
-         * or TrustZone extensions these all UNDEF except SVC.
-         */
-        if (op2_ll != 1) {
-            unallocated_encoding(s);
-            break;
-        }
         /* For SVC, HVC and SMC we advance the single-step state
          * machine before taking the exception. This is architecturally
          * mandated, to ensure that single-stepping a system call
          * instruction works properly.
          */
-        gen_ss_advance(s);
-        gen_exception_insn(s, 0, EXCP_SWI, syn_aa64_svc(imm16));
+        switch (op2_ll) {
+        case 1:
+            gen_ss_advance(s);
+            gen_exception_insn(s, 0, EXCP_SWI, syn_aa64_svc(imm16));
+            break;
+        case 2:
+            if (!arm_dc_feature(s, ARM_FEATURE_EL2) || s->current_pl == 0) {
+                unallocated_encoding(s);
+                break;
+            }
+            /* The pre HVC helper handles cases when HVC gets trapped
+             * as an undefined insn by runtime configuration.
+             */
+            gen_a64_set_pc_im(s->pc - 4);
+            gen_helper_pre_hvc(cpu_env);
+            gen_ss_advance(s);
+            gen_exception_insn(s, 0, EXCP_HVC, syn_aa64_hvc(imm16));
+            break;
+        default:
+            unallocated_encoding(s);
+            break;
+        }
         break;
     case 1:
         if (op2_ll != 0) {
-- 
1.9.1

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

* [Qemu-devel] [PULL 16/19] target-arm: Add a Hypervisor Trap exception type
  2014-09-29 18:26 [Qemu-devel] [PULL 00/19] target-arm queue Peter Maydell
                   ` (14 preceding siblings ...)
  2014-09-29 18:26 ` [Qemu-devel] [PULL 15/19] target-arm: A64: Emulate the HVC insn Peter Maydell
@ 2014-09-29 18:26 ` Peter Maydell
  2014-09-29 18:26 ` [Qemu-devel] [PULL 17/19] target-arm: A64: Emulate the SMC insn Peter Maydell
                   ` (3 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Peter Maydell @ 2014-09-29 18:26 UTC (permalink / raw)
  To: qemu-devel

From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1411718914-6608-9-git-send-email-edgar.iglesias@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/cpu.h        | 1 +
 target-arm/helper-a64.c | 1 +
 target-arm/helper.c     | 1 +
 target-arm/internals.h  | 1 +
 4 files changed, 4 insertions(+)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index e13b6d4..98610f0 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -52,6 +52,7 @@
 #define EXCP_KERNEL_TRAP     9   /* Jumped to kernel code page.  */
 #define EXCP_STREX          10
 #define EXCP_HVC            11   /* HyperVisor Call */
+#define EXCP_HYP_TRAP       12
 
 #define ARMV7M_EXCP_RESET   1
 #define ARMV7M_EXCP_NMI     2
diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c
index 4e6ca26..0a7c155 100644
--- a/target-arm/helper-a64.c
+++ b/target-arm/helper-a64.c
@@ -477,6 +477,7 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
     case EXCP_UDEF:
     case EXCP_SWI:
     case EXCP_HVC:
+    case EXCP_HYP_TRAP:
         env->cp15.esr_el[new_el] = env->exception.syndrome;
         break;
     case EXCP_IRQ:
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 4d5a653..48f549a 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3781,6 +3781,7 @@ unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx)
 
     switch (excp_idx) {
     case EXCP_HVC:
+    case EXCP_HYP_TRAP:
         target_el = 2;
         break;
     default:
diff --git a/target-arm/internals.h b/target-arm/internals.h
index 25c5ec3..203c423 100644
--- a/target-arm/internals.h
+++ b/target-arm/internals.h
@@ -54,6 +54,7 @@ static const char * const excnames[] = {
     [EXCP_KERNEL_TRAP] = "QEMU intercept of kernel commpage",
     [EXCP_STREX] = "QEMU intercept of STREX",
     [EXCP_HVC] = "Hypervisor Call",
+    [EXCP_HYP_TRAP] = "Hypervisor Trap",
 };
 
 static inline void arm_log_exception(int idx)
-- 
1.9.1

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

* [Qemu-devel] [PULL 17/19] target-arm: A64: Emulate the SMC insn
  2014-09-29 18:26 [Qemu-devel] [PULL 00/19] target-arm queue Peter Maydell
                   ` (15 preceding siblings ...)
  2014-09-29 18:26 ` [Qemu-devel] [PULL 16/19] target-arm: Add a Hypervisor Trap exception type Peter Maydell
@ 2014-09-29 18:26 ` Peter Maydell
  2014-09-29 18:26 ` [Qemu-devel] [PULL 18/19] target-arm: Add IRQ and FIQ routing to EL2 and 3 Peter Maydell
                   ` (2 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Peter Maydell @ 2014-09-29 18:26 UTC (permalink / raw)
  To: qemu-devel

From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1411718914-6608-10-git-send-email-edgar.iglesias@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/cpu.h           |  1 +
 target-arm/helper-a64.c    |  1 +
 target-arm/helper.c        |  3 +++
 target-arm/helper.h        |  1 +
 target-arm/internals.h     |  6 ++++++
 target-arm/op_helper.c     | 26 ++++++++++++++++++++++++++
 target-arm/translate-a64.c | 13 +++++++++++++
 7 files changed, 51 insertions(+)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 98610f0..d104a7d 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -53,6 +53,7 @@
 #define EXCP_STREX          10
 #define EXCP_HVC            11   /* HyperVisor Call */
 #define EXCP_HYP_TRAP       12
+#define EXCP_SMC            13   /* Secure Monitor Call */
 
 #define ARMV7M_EXCP_RESET   1
 #define ARMV7M_EXCP_NMI     2
diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c
index 0a7c155..0011488 100644
--- a/target-arm/helper-a64.c
+++ b/target-arm/helper-a64.c
@@ -478,6 +478,7 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
     case EXCP_SWI:
     case EXCP_HVC:
     case EXCP_HYP_TRAP:
+    case EXCP_SMC:
         env->cp15.esr_el[new_el] = env->exception.syndrome;
         break;
     case EXCP_IRQ:
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 48f549a..af2d2e6 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3784,6 +3784,9 @@ unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx)
     case EXCP_HYP_TRAP:
         target_el = 2;
         break;
+    case EXCP_SMC:
+        target_el = 3;
+        break;
     default:
         target_el = MAX(cur_el, 1);
         break;
diff --git a/target-arm/helper.h b/target-arm/helper.h
index 75fc1b3..dec3728 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -51,6 +51,7 @@ DEF_HELPER_3(exception_with_syndrome, void, env, i32, i32)
 DEF_HELPER_1(wfi, void, env)
 DEF_HELPER_1(wfe, void, env)
 DEF_HELPER_1(pre_hvc, void, env)
+DEF_HELPER_2(pre_smc, void, env, i32)
 
 DEF_HELPER_3(cpsr_write, void, env, i32, i32)
 DEF_HELPER_1(cpsr_read, i32, env)
diff --git a/target-arm/internals.h b/target-arm/internals.h
index 203c423..1486595 100644
--- a/target-arm/internals.h
+++ b/target-arm/internals.h
@@ -55,6 +55,7 @@ static const char * const excnames[] = {
     [EXCP_STREX] = "QEMU intercept of STREX",
     [EXCP_HVC] = "Hypervisor Call",
     [EXCP_HYP_TRAP] = "Hypervisor Trap",
+    [EXCP_SMC] = "Secure Monitor Call",
 };
 
 static inline void arm_log_exception(int idx)
@@ -222,6 +223,11 @@ static inline uint32_t syn_aa64_hvc(uint32_t imm16)
     return (EC_AA64_HVC << ARM_EL_EC_SHIFT) | ARM_EL_IL | (imm16 & 0xffff);
 }
 
+static inline uint32_t syn_aa64_smc(uint32_t imm16)
+{
+    return (EC_AA64_SMC << 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)
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index e5cb690..03ac92a 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -416,6 +416,32 @@ void HELPER(pre_hvc)(CPUARMState *env)
     }
 }
 
+void HELPER(pre_smc)(CPUARMState *env, uint32_t syndrome)
+{
+    int cur_el = arm_current_pl(env);
+    /* FIXME: Use real secure state.  */
+    bool secure = false;
+    bool smd = env->cp15.scr_el3 & SCR_SMD;
+    /* On ARMv8 AArch32, SMD only applies to NS state.
+     * On ARMv7 SMD only applies to NS state and only if EL2 is available.
+     * For ARMv7 non EL2, we force SMD to zero so we don't need to re-check
+     * the EL2 condition here.
+     */
+    bool undef = is_a64(env) ? smd : (!secure && smd);
+
+    /* In NS EL1, HCR controlled routing to EL2 has priority over SMD.  */
+    if (!secure && cur_el == 1 && (env->cp15.hcr_el2 & HCR_TSC)) {
+        env->exception.syndrome = syndrome;
+        raise_exception(env, EXCP_HYP_TRAP);
+    }
+
+    /* We've already checked that EL3 exists at translation time.  */
+    if (undef) {
+        env->exception.syndrome = syn_uncategorized();
+        raise_exception(env, EXCP_UDEF);
+    }
+}
+
 void HELPER(exception_return)(CPUARMState *env)
 {
     int cur_el = arm_current_pl(env);
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index f4cb56e..35ae3ea 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -1470,6 +1470,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);
+    TCGv_i32 tmp;
 
     switch (opc) {
     case 0:
@@ -1496,6 +1497,18 @@ static void disas_exc(DisasContext *s, uint32_t insn)
             gen_ss_advance(s);
             gen_exception_insn(s, 0, EXCP_HVC, syn_aa64_hvc(imm16));
             break;
+        case 3:
+            if (!arm_dc_feature(s, ARM_FEATURE_EL3) || s->current_pl == 0) {
+                unallocated_encoding(s);
+                break;
+            }
+            gen_a64_set_pc_im(s->pc - 4);
+            tmp = tcg_const_i32(syn_aa64_smc(imm16));
+            gen_helper_pre_smc(cpu_env, tmp);
+            tcg_temp_free_i32(tmp);
+            gen_ss_advance(s);
+            gen_exception_insn(s, 0, EXCP_SMC, syn_aa64_smc(imm16));
+            break;
         default:
             unallocated_encoding(s);
             break;
-- 
1.9.1

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

* [Qemu-devel] [PULL 18/19] target-arm: Add IRQ and FIQ routing to EL2 and 3
  2014-09-29 18:26 [Qemu-devel] [PULL 00/19] target-arm queue Peter Maydell
                   ` (16 preceding siblings ...)
  2014-09-29 18:26 ` [Qemu-devel] [PULL 17/19] target-arm: A64: Emulate the SMC insn Peter Maydell
@ 2014-09-29 18:26 ` Peter Maydell
  2014-09-29 18:26 ` [Qemu-devel] [PULL 19/19] target-arm: Add support for VIRQ and VFIQ Peter Maydell
  2014-09-30 10:52 ` [Qemu-devel] [PULL 00/19] target-arm queue Peter Maydell
  19 siblings, 0 replies; 21+ messages in thread
From: Peter Maydell @ 2014-09-29 18:26 UTC (permalink / raw)
  To: qemu-devel

From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>

Reviewed-by: Greg Bellows <greg.bellows@linaro.org>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1411718914-6608-11-git-send-email-edgar.iglesias@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/cpu.h    | 10 ++++++++++
 target-arm/helper.c | 17 +++++++++++++++++
 2 files changed, 27 insertions(+)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index d104a7d..11ba9d6 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1180,6 +1180,10 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx)
     CPUARMState *env = cs->env_ptr;
     unsigned int cur_el = arm_current_pl(env);
     unsigned int target_el = arm_excp_target_el(cs, excp_idx);
+    /* FIXME: Use actual secure state.  */
+    bool secure = false;
+    /* If in EL1/0, Physical IRQ routing to EL2 only happens from NS state.  */
+    bool irq_can_hyp = !secure && cur_el < 2 && target_el == 2;
 
     /* Don't take exceptions if they target a lower EL.  */
     if (cur_el > target_el) {
@@ -1188,8 +1192,14 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx)
 
     switch (excp_idx) {
     case EXCP_FIQ:
+        if (irq_can_hyp && (env->cp15.hcr_el2 & HCR_FMO)) {
+            return true;
+        }
         return !(env->daif & PSTATE_F);
     case EXCP_IRQ:
+        if (irq_can_hyp && (env->cp15.hcr_el2 & HCR_IMO)) {
+            return true;
+        }
         return !(env->daif & PSTATE_I)
                && (!IS_M(env) || env->regs[15] < 0xfffffff0);
     default:
diff --git a/target-arm/helper.c b/target-arm/helper.c
index af2d2e6..6135594 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3773,6 +3773,8 @@ unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx)
     CPUARMState *env = &cpu->env;
     unsigned int cur_el = arm_current_pl(env);
     unsigned int target_el;
+    /* FIXME: Use actual secure state.  */
+    bool secure = false;
 
     if (!env->aarch64) {
         /* TODO: Add EL2 and 3 exception handling for AArch32.  */
@@ -3787,6 +3789,21 @@ unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx)
     case EXCP_SMC:
         target_el = 3;
         break;
+    case EXCP_FIQ:
+    case EXCP_IRQ:
+    {
+        const uint64_t hcr_mask = excp_idx == EXCP_FIQ ? HCR_FMO : HCR_IMO;
+        const uint32_t scr_mask = excp_idx == EXCP_FIQ ? SCR_FIQ : SCR_IRQ;
+
+        target_el = 1;
+        if (!secure && (env->cp15.hcr_el2 & hcr_mask)) {
+            target_el = 2;
+        }
+        if (env->cp15.scr_el3 & scr_mask) {
+            target_el = 3;
+        }
+        break;
+    }
     default:
         target_el = MAX(cur_el, 1);
         break;
-- 
1.9.1

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

* [Qemu-devel] [PULL 19/19] target-arm: Add support for VIRQ and VFIQ
  2014-09-29 18:26 [Qemu-devel] [PULL 00/19] target-arm queue Peter Maydell
                   ` (17 preceding siblings ...)
  2014-09-29 18:26 ` [Qemu-devel] [PULL 18/19] target-arm: Add IRQ and FIQ routing to EL2 and 3 Peter Maydell
@ 2014-09-29 18:26 ` Peter Maydell
  2014-09-30 10:52 ` [Qemu-devel] [PULL 00/19] target-arm queue Peter Maydell
  19 siblings, 0 replies; 21+ messages in thread
From: Peter Maydell @ 2014-09-29 18:26 UTC (permalink / raw)
  To: qemu-devel

From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>

This only implements the external delivery method via the GIC.

Acked-by: Greg Bellows <greg.bellows@linaro.org>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1411718914-6608-12-git-send-email-edgar.iglesias@gmail.com
[PMM: adjusted following cpu-exec refactoring]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/cpu.c        | 47 ++++++++++++++++++++++++++++++++++++-----------
 target-arm/cpu.h        | 35 ++++++++++++++++++++++++++++++++---
 target-arm/helper-a64.c |  2 ++
 target-arm/helper.c     |  4 ++++
 target-arm/internals.h  |  2 ++
 5 files changed, 76 insertions(+), 14 deletions(-)

diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index b7cdcd7..8ab6d95 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -41,7 +41,9 @@ static void arm_cpu_set_pc(CPUState *cs, vaddr value)
 static bool arm_cpu_has_work(CPUState *cs)
 {
     return cs->interrupt_request &
-        (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB);
+        (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD
+         | CPU_INTERRUPT_VFIQ | CPU_INTERRUPT_VIRQ
+         | CPU_INTERRUPT_EXITTB);
 }
 
 static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
@@ -210,6 +212,18 @@ bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
         cc->do_interrupt(cs);
         ret = true;
     }
+    if (interrupt_request & CPU_INTERRUPT_VIRQ
+        && arm_excp_unmasked(cs, EXCP_VIRQ)) {
+        cs->exception_index = EXCP_VIRQ;
+        cc->do_interrupt(cs);
+        ret = true;
+    }
+    if (interrupt_request & CPU_INTERRUPT_VFIQ
+        && arm_excp_unmasked(cs, EXCP_VFIQ)) {
+        cs->exception_index = EXCP_VFIQ;
+        cc->do_interrupt(cs);
+        ret = true;
+    }
 
     return ret;
 }
@@ -218,21 +232,29 @@ bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
 static void arm_cpu_set_irq(void *opaque, int irq, int level)
 {
     ARMCPU *cpu = opaque;
+    CPUARMState *env = &cpu->env;
     CPUState *cs = CPU(cpu);
+    static const int mask[] = {
+        [ARM_CPU_IRQ] = CPU_INTERRUPT_HARD,
+        [ARM_CPU_FIQ] = CPU_INTERRUPT_FIQ,
+        [ARM_CPU_VIRQ] = CPU_INTERRUPT_VIRQ,
+        [ARM_CPU_VFIQ] = CPU_INTERRUPT_VFIQ
+    };
 
     switch (irq) {
-    case ARM_CPU_IRQ:
-        if (level) {
-            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
-        } else {
-            cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+    case ARM_CPU_VIRQ:
+    case ARM_CPU_VFIQ:
+        if (!arm_feature(env, ARM_FEATURE_EL2)) {
+            hw_error("%s: Virtual interrupt line %d with no EL2 support\n",
+                     __func__, irq);
         }
-        break;
+        /* fall through */
+    case ARM_CPU_IRQ:
     case ARM_CPU_FIQ:
         if (level) {
-            cpu_interrupt(cs, CPU_INTERRUPT_FIQ);
+            cpu_interrupt(cs, mask[irq]);
         } else {
-            cpu_reset_interrupt(cs, CPU_INTERRUPT_FIQ);
+            cpu_reset_interrupt(cs, mask[irq]);
         }
         break;
     default:
@@ -282,9 +304,12 @@ static void arm_cpu_initfn(Object *obj)
 #ifndef CONFIG_USER_ONLY
     /* Our inbound IRQ and FIQ lines */
     if (kvm_enabled()) {
-        qdev_init_gpio_in(DEVICE(cpu), arm_cpu_kvm_set_irq, 2);
+        /* VIRQ and VFIQ are unused with KVM but we add them to maintain
+         * the same interface as non-KVM CPUs.
+         */
+        qdev_init_gpio_in(DEVICE(cpu), arm_cpu_kvm_set_irq, 4);
     } else {
-        qdev_init_gpio_in(DEVICE(cpu), arm_cpu_set_irq, 2);
+        qdev_init_gpio_in(DEVICE(cpu), arm_cpu_set_irq, 4);
     }
 
     cpu->gt_timer[GTIMER_PHYS] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 11ba9d6..65a3417 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -54,6 +54,8 @@
 #define EXCP_HVC            11   /* HyperVisor Call */
 #define EXCP_HYP_TRAP       12
 #define EXCP_SMC            13   /* Secure Monitor Call */
+#define EXCP_VIRQ           14
+#define EXCP_VFIQ           15
 
 #define ARMV7M_EXCP_RESET   1
 #define ARMV7M_EXCP_NMI     2
@@ -68,6 +70,8 @@
 
 /* ARM-specific interrupt pending bits.  */
 #define CPU_INTERRUPT_FIQ   CPU_INTERRUPT_TGT_EXT_1
+#define CPU_INTERRUPT_VIRQ  CPU_INTERRUPT_TGT_EXT_2
+#define CPU_INTERRUPT_VFIQ  CPU_INTERRUPT_TGT_EXT_3
 
 /* The usual mapping for an AArch64 system register to its AArch32
  * counterpart is for the 32 bit world to have access to the lower
@@ -83,9 +87,11 @@
 #define offsetofhigh32(S, M) (offsetof(S, M) + sizeof(uint32_t))
 #endif
 
-/* Meanings of the ARMCPU object's two inbound GPIO lines */
+/* Meanings of the ARMCPU object's four inbound GPIO lines */
 #define ARM_CPU_IRQ 0
 #define ARM_CPU_FIQ 1
+#define ARM_CPU_VIRQ 2
+#define ARM_CPU_VFIQ 3
 
 typedef void ARMWriteCPFunc(void *opaque, int cp_info,
                             int srcreg, int operand, uint32_t value);
@@ -1184,6 +1190,18 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx)
     bool secure = false;
     /* If in EL1/0, Physical IRQ routing to EL2 only happens from NS state.  */
     bool irq_can_hyp = !secure && cur_el < 2 && target_el == 2;
+    /* ARMv7-M interrupt return works by loading a magic value
+     * into the PC.  On real hardware the load causes the
+     * return to occur.  The qemu implementation performs the
+     * jump normally, then does the exception return when the
+     * CPU tries to execute code at the magic address.
+     * This will cause the magic PC value to be pushed to
+     * the stack if an interrupt occurred at the wrong time.
+     * We avoid this by disabling interrupts when
+     * pc contains a magic address.
+     */
+    bool irq_unmasked = !(env->daif & PSTATE_I)
+                        && (!IS_M(env) || env->regs[15] < 0xfffffff0);
 
     /* Don't take exceptions if they target a lower EL.  */
     if (cur_el > target_el) {
@@ -1200,8 +1218,19 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx)
         if (irq_can_hyp && (env->cp15.hcr_el2 & HCR_IMO)) {
             return true;
         }
-        return !(env->daif & PSTATE_I)
-               && (!IS_M(env) || env->regs[15] < 0xfffffff0);
+        return irq_unmasked;
+    case EXCP_VFIQ:
+        if (!secure && !(env->cp15.hcr_el2 & HCR_FMO)) {
+            /* VFIQs are only taken when hypervized and non-secure.  */
+            return false;
+        }
+        return !(env->daif & PSTATE_F);
+    case EXCP_VIRQ:
+        if (!secure && !(env->cp15.hcr_el2 & HCR_IMO)) {
+            /* VIRQs are only taken when hypervized and non-secure.  */
+            return false;
+        }
+        return irq_unmasked;
     default:
         g_assert_not_reached();
     }
diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c
index 0011488..8228e29 100644
--- a/target-arm/helper-a64.c
+++ b/target-arm/helper-a64.c
@@ -482,9 +482,11 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
         env->cp15.esr_el[new_el] = env->exception.syndrome;
         break;
     case EXCP_IRQ:
+    case EXCP_VIRQ:
         addr += 0x80;
         break;
     case EXCP_FIQ:
+    case EXCP_VFIQ:
         addr += 0x100;
         break;
     default:
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 6135594..2669e15 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3804,6 +3804,10 @@ unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx)
         }
         break;
     }
+    case EXCP_VIRQ:
+    case EXCP_VFIQ:
+        target_el = 1;
+        break;
     default:
         target_el = MAX(cur_el, 1);
         break;
diff --git a/target-arm/internals.h b/target-arm/internals.h
index 1486595..b7547bb 100644
--- a/target-arm/internals.h
+++ b/target-arm/internals.h
@@ -56,6 +56,8 @@ static const char * const excnames[] = {
     [EXCP_HVC] = "Hypervisor Call",
     [EXCP_HYP_TRAP] = "Hypervisor Trap",
     [EXCP_SMC] = "Secure Monitor Call",
+    [EXCP_VIRQ] = "Virtual IRQ",
+    [EXCP_VFIQ] = "Virtual FIQ",
 };
 
 static inline void arm_log_exception(int idx)
-- 
1.9.1

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

* Re: [Qemu-devel] [PULL 00/19] target-arm queue
  2014-09-29 18:26 [Qemu-devel] [PULL 00/19] target-arm queue Peter Maydell
                   ` (18 preceding siblings ...)
  2014-09-29 18:26 ` [Qemu-devel] [PULL 19/19] target-arm: Add support for VIRQ and VFIQ Peter Maydell
@ 2014-09-30 10:52 ` Peter Maydell
  19 siblings, 0 replies; 21+ messages in thread
From: Peter Maydell @ 2014-09-30 10:52 UTC (permalink / raw)
  To: QEMU Developers

On 29 September 2014 19:26, Peter Maydell <peter.maydell@linaro.org> wrote:
> ARM pullreq: nothing fantastically exciting, but getting the
> EL2/EL3 patchset in ought to help with ongoing TZ work.
>
> -- PMM
>
>
> The following changes since commit 70556264a89a268efba1d7e8e341adcdd7881eb4:
>
>   libqos: use microseconds instead of iterations for virtio timeout (2014-09-29 17:31:11 +0100)
>
> are available in the git repository at:
>
>   git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20140929
>
> for you to fetch changes up to 136e67e9b50b61fb03fedcea5c4fbe74cf44fdcc:
>
>   target-arm: Add support for VIRQ and VFIQ (2014-09-29 18:48:51 +0100)
>
> ----------------------------------------------------------------
> target-arm:
>  * more EL2/EL3 preparation work
>  * don't handle c15_cpar changes via tb_flush()
>  * fix some unused function warnings in ARM devices
>  * build the GDB XML for 32 bit CPUs into qemu-*-aarch64
>  * implement guest breakpoint support
>
> ----------------------------------------------------------------

Applied, thanks.

-- PMM

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

end of thread, other threads:[~2014-09-30 10:52 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-09-29 18:26 [Qemu-devel] [PULL 00/19] target-arm queue Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 01/19] target-arm: Implement setting guest breakpoints Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 02/19] target-arm: Implement handling of breakpoint firing Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 03/19] configure: Build GDB XML for 32 bit ARM CPUs into qemu aarch64 binaries Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 04/19] hw/display/blizzard.c: Delete unused function blizzard_rgb2yuv Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 05/19] hw/intc/imx_avic.c: Remove unused function imx_avic_set_prio() Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 06/19] hw/display/pxa2xx_lcd.c: Remove unused function pxa2xx_dma_rdst_set Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 07/19] hw/input/tsc210x.c: Delete unused array tsc2101_rates Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 08/19] target-arm: Don't handle c15_cpar changes via tb_flush() Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 09/19] target-arm: Add HCR_EL2 Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 10/19] target-arm: Add SCR_EL3 Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 11/19] target-arm: A64: Refactor aarch64_cpu_do_interrupt Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 12/19] target-arm: Break out exception masking to a separate func Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 13/19] target-arm: Don't take interrupts targeting lower ELs Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 14/19] target-arm: A64: Correct updates to FAR and ESR on exceptions Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 15/19] target-arm: A64: Emulate the HVC insn Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 16/19] target-arm: Add a Hypervisor Trap exception type Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 17/19] target-arm: A64: Emulate the SMC insn Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 18/19] target-arm: Add IRQ and FIQ routing to EL2 and 3 Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 19/19] target-arm: Add support for VIRQ and VFIQ Peter Maydell
2014-09-30 10:52 ` [Qemu-devel] [PULL 00/19] target-arm queue Peter Maydell

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