qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v4] target-sparc: Add and use CPU_FEATURE_CASA


From: Mark Cave-Ayland
Subject: Re: [Qemu-devel] [PATCH v4] target-sparc: Add and use CPU_FEATURE_CASA
Date: Sat, 08 Mar 2014 20:16:26 +0000
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:10.0.12) Gecko/20130116 Icedove/10.0.12

On 14/02/14 16:06, Sebastian Huber wrote:

The LEON3 processor has support for the CASA instruction which is
normally only available for SPARC V9 processors.  Binutils 2.24
and GCC 4.9 will support this instruction for LEON3.  GCC uses it to
generate C11 atomic operations.

The CAS synthetic instruction uses an ASI of 0x80.  If TARGET_SPARC64 is
not defined use a supervisor data load/store for an ASI of 0x80 in
helper_ld_asi()/helper_st_asi().  The supervisor data load/store was
choosen according to the LEON3 documentation.

The ASI 0x80 is defined in the SPARC V9 manual, Table 12—Address Space
Identifiers (ASIs).  Here we have: 0x80, ASI_PRIMARY, Unrestricted
access, Primary address space.

Tested with the following program:

   #include<assert.h>
   #include<stdatomic.h>

   void test(void)
   {
     atomic_int a;
     int e;
     _Bool b;

     atomic_store(&a, 1);
     e = 1;
     b = atomic_compare_exchange_strong(&a,&e, 2);
     assert(b);
     assert(atomic_load(&a) == 2);

     atomic_store(&a, 3);
     e = 4;
     b = atomic_compare_exchange_strong(&a,&e, 5);
     assert(!b);
     assert(atomic_load(&a) == 3);
   }

Tested also on a NGMP board with a LEON4 processor.

v4: Fix coding style.

Signed-off-by: Sebastian Huber<address@hidden>
Reviewed-by: Fabien Chouteau<address@hidden>
---
  target-sparc/cpu.c         |    3 +-
  target-sparc/cpu.h         |    4 ++-
  target-sparc/helper.h      |    4 ++-
  target-sparc/ldst_helper.c |   28 ++++++++++++++----------
  target-sparc/translate.c   |   49 ++++++++++++++++++++++++++++---------------
  5 files changed, 56 insertions(+), 32 deletions(-)

diff --git a/target-sparc/cpu.c b/target-sparc/cpu.c
index e7f878e..5806e59 100644
--- a/target-sparc/cpu.c
+++ b/target-sparc/cpu.c
@@ -458,7 +458,8 @@ static const sparc_def_t sparc_defs[] = {
          .mmu_trcr_mask = 0xffffffff,
          .nwindows = 8,
          .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
-        CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL | CPU_FEATURE_POWERDOWN,
+        CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL | CPU_FEATURE_POWERDOWN |
+        CPU_FEATURE_CASA,
      },
  #endif
  };
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index c519063..2531cf9 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -271,12 +271,14 @@ typedef struct sparc_def_t {
  #define CPU_FEATURE_ASR17        (1<<  15)
  #define CPU_FEATURE_CACHE_CTRL   (1<<  16)
  #define CPU_FEATURE_POWERDOWN    (1<<  17)
+#define CPU_FEATURE_CASA         (1<<  18)

  #ifndef TARGET_SPARC64
  #define CPU_DEFAULT_FEATURES (CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP |  \
                                CPU_FEATURE_MUL | CPU_FEATURE_DIV |     \
                                CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT | \
-                              CPU_FEATURE_FMUL | CPU_FEATURE_FSMULD)
+                              CPU_FEATURE_FMUL | CPU_FEATURE_FSMULD | \
+                              CPU_FEATURE_CASA)
  #else
  #define CPU_DEFAULT_FEATURES (CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP |  \
                                CPU_FEATURE_MUL | CPU_FEATURE_DIV |     \
diff --git a/target-sparc/helper.h b/target-sparc/helper.h
index 2a771b2..cd8d3fa 100644
--- a/target-sparc/helper.h
+++ b/target-sparc/helper.h
@@ -22,7 +22,6 @@ DEF_HELPER_1(popc, tl, tl)
  DEF_HELPER_4(ldda_asi, void, env, tl, int, int)
  DEF_HELPER_5(ldf_asi, void, env, tl, int, int, int)
  DEF_HELPER_5(stf_asi, void, env, tl, int, int, int)
-DEF_HELPER_5(cas_asi, tl, env, tl, tl, tl, i32)
  DEF_HELPER_5(casx_asi, tl, env, tl, tl, tl, i32)
  DEF_HELPER_2(set_softint, void, env, i64)
  DEF_HELPER_2(clear_softint, void, env, i64)
@@ -31,6 +30,9 @@ DEF_HELPER_2(tick_set_count, void, ptr, i64)
  DEF_HELPER_1(tick_get_count, i64, ptr)
  DEF_HELPER_2(tick_set_limit, void, ptr, i64)
  #endif
+#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
+DEF_HELPER_5(cas_asi, tl, env, tl, tl, tl, i32)
+#endif
  DEF_HELPER_3(check_align, void, env, tl, i32)
  DEF_HELPER_1(debug, void, env)
  DEF_HELPER_1(save, void, env)
diff --git a/target-sparc/ldst_helper.c b/target-sparc/ldst_helper.c
index 92761ad..32491b4 100644
--- a/target-sparc/ldst_helper.c
+++ b/target-sparc/ldst_helper.c
@@ -584,6 +584,7 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong 
addr, int asi, int size,
          }
          break;
      case 0xb: /* Supervisor data access */
+    case 0x80:
          switch (size) {
          case 1:
              ret = cpu_ldub_kernel(env, addr);
@@ -955,6 +956,7 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, 
uint64_t val, int asi,
          }
          break;
      case 0xb: /* Supervisor data access */
+    case 0x80:
          switch (size) {
          case 1:
              cpu_stb_kernel(env, addr, val);
@@ -2232,33 +2234,35 @@ void helper_stf_asi(CPUSPARCState *env, target_ulong 
addr, int asi, int size,
      }
  }

-target_ulong helper_cas_asi(CPUSPARCState *env, target_ulong addr,
-                            target_ulong val1, target_ulong val2, uint32_t asi)
+target_ulong helper_casx_asi(CPUSPARCState *env, target_ulong addr,
+                             target_ulong val1, target_ulong val2,
+                             uint32_t asi)
  {
      target_ulong ret;

-    val2&= 0xffffffffUL;
-    ret = helper_ld_asi(env, addr, asi, 4, 0);
-    ret&= 0xffffffffUL;
+    ret = helper_ld_asi(env, addr, asi, 8, 0);
      if (val2 == ret) {
-        helper_st_asi(env, addr, val1&  0xffffffffUL, asi, 4);
+        helper_st_asi(env, addr, val1, asi, 8);
      }
      return ret;
  }
+#endif /* TARGET_SPARC64 */

-target_ulong helper_casx_asi(CPUSPARCState *env, target_ulong addr,
-                             target_ulong val1, target_ulong val2,
-                             uint32_t asi)
+#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
+target_ulong helper_cas_asi(CPUSPARCState *env, target_ulong addr,
+                            target_ulong val1, target_ulong val2, uint32_t asi)
  {
      target_ulong ret;

-    ret = helper_ld_asi(env, addr, asi, 8, 0);
+    val2&= 0xffffffffUL;
+    ret = helper_ld_asi(env, addr, asi, 4, 0);
+    ret&= 0xffffffffUL;
      if (val2 == ret) {
-        helper_st_asi(env, addr, val1, asi, 8);
+        helper_st_asi(env, addr, val1&  0xffffffffUL, asi, 4);
      }
      return ret;
  }
-#endif /* TARGET_SPARC64 */
+#endif /* !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) */

  void helper_ldqf(CPUSPARCState *env, target_ulong addr, int mem_idx)
  {
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 6150b22..58f6da2 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -2107,18 +2107,6 @@ static inline void gen_stda_asi(DisasContext *dc, TCGv 
hi, TCGv addr,
      tcg_temp_free_i64(t64);
  }

-static inline void gen_cas_asi(DisasContext *dc, TCGv addr,
-                               TCGv val2, int insn, int rd)
-{
-    TCGv val1 = gen_load_gpr(dc, rd);
-    TCGv dst = gen_dest_gpr(dc, rd);
-    TCGv_i32 r_asi = gen_get_asi(insn, addr);
-
-    gen_helper_cas_asi(dst, cpu_env, addr, val1, val2, r_asi);
-    tcg_temp_free_i32(r_asi);
-    gen_store_gpr(dc, rd, dst);
-}
-
  static inline void gen_casx_asi(DisasContext *dc, TCGv addr,
                                  TCGv val2, int insn, int rd)
  {
@@ -2229,6 +2217,22 @@ static inline void gen_stda_asi(DisasContext *dc, TCGv 
hi, TCGv addr,
  #endif

  #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
+static inline void gen_cas_asi(DisasContext *dc, TCGv addr,
+                               TCGv val2, int insn, int rd)
+{
+    TCGv val1 = gen_load_gpr(dc, rd);
+    TCGv dst = gen_dest_gpr(dc, rd);
+#ifdef TARGET_SPARC64
+    TCGv_i32 r_asi = gen_get_asi(insn, addr);
+#else
+    TCGv_i32 r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
+#endif
+
+    gen_helper_cas_asi(dst, cpu_env, addr, val1, val2, r_asi);
+    tcg_temp_free_i32(r_asi);
+    gen_store_gpr(dc, rd, dst);
+}
+
  static inline void gen_ldstub_asi(TCGv dst, TCGv addr, int insn)
  {
      TCGv_i64 r_val;
@@ -5103,11 +5107,6 @@ static void disas_sparc_insn(DisasContext * dc, unsigned 
int insn)
                      }
                      gen_stf_asi(cpu_addr, insn, 8, DFPREG(rd));
                      break;
-                case 0x3c: /* V9 casa */
-                    rs2 = GET_FIELD(insn, 27, 31);
-                    cpu_src2 = gen_load_gpr(dc, rs2);
-                    gen_cas_asi(dc, cpu_addr, cpu_src2, insn, rd);
-                    break;
                  case 0x3e: /* V9 casxa */
                      rs2 = GET_FIELD(insn, 27, 31);
                      cpu_src2 = gen_load_gpr(dc, rs2);
@@ -5120,6 +5119,22 @@ static void disas_sparc_insn(DisasContext * dc, unsigned 
int insn)
                  case 0x37: /* stdc */
                      goto ncp_insn;
  #endif
+#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
+                case 0x3c: /* V9 or LEON3 casa */
+                    CHECK_FPU_FEATURE(dc, CASA);
+#ifndef TARGET_SPARC64
+                    if (IS_IMM) {
+                        goto illegal_insn;
+                    }
+                    if (!supervisor(dc)) {
+                        goto priv_insn;
+                    }
+#endif
+                    rs2 = GET_FIELD(insn, 27, 31);
+                    cpu_src2 = gen_load_gpr(dc, rs2);
+                    gen_cas_asi(dc, cpu_addr, cpu_src2, insn, rd);
+                    break;
+#endif
                  default:
                      goto illegal_insn;
                  }

Hi all,

Apologies for the delay in testing this patch - it's been a busy few weeks with work, along with a QEMU freeze deadline. Unfortunately this patch causes regressions when booting my Debian lenny/squeeze ISO test images on qemu-system-sparc64 (see below for the output from current git master with the v4 patch applied):


address@hidden:~/rel-qemu-git/bin$ ./qemu-system-sparc64 -cdrom /home/build/src/qemu/image/sparc64/debian-504-sparc-netinst.iso -boot d -nographic
OpenBIOS for Sparc64
Configuration device id QEMU version 1 machine id 0
kernel cmdline
CPUs: 1 x SUNW,UltraSPARC-IIi
UUID: 00000000-0000-0000-0000-000000000000
Welcome to OpenBIOS v1.1 built on Mar 8 2014 12:54
  Type 'help' for detailed information
Trying cdrom:f...
Not a bootable ELF image
Loading a.out image...
Loaded 7680 bytes
entry point is 0x4000

Jumping to entry point 0000000000004000 for type 0000000000000005...
switching to new context: entry point 0x4000 stack 0x00000000ffe86a01
SILO Version 1.4.13
\


                  Welcome to Debian GNU/Linux lenny!

This is a Debian installation CDROM, built on 20100201-16:54.
Keep it once you have installed your system, as you can boot from it
to repair the system on your hard disk if that ever becomes necessary.

WARNING: You should completely back up all of your hard disks before
  proceeding. The installation procedure can completely and irreversibly
  erase them! If you haven't made backups yet, remove the rescue CD from
  the drive and press L1-A to get back to the OpenBoot prompt.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted
by applicable law.

[ ENTER - Boot install ]   [ Type "expert" - Boot into expert mode ]
                           [ Type "rescue" - Boot into rescue mode ]
boot:
Allocated 8 Megs of memory at 0x40000000 for kernel
Loaded kernel version 2.6.26
Loading initial ramdisk (4312781 bytes at 0xC00000 phys, 0x40C00000 virt)...
|
Unhandled Exception 0x0000000000000021
PC = 0x0000000000551b88 NPC = 0x0000000000551b8c
Stopping execution
QEMU 1.7.50 monitor - type 'help' for more information
(qemu) quit



address@hidden:~/rel-qemu-git/bin$ ./qemu-system-sparc64 -cdrom /home/build/src/qemu/image/sparc64/debian-6.0.4-sparc-netinst.iso -boot d -nographic
OpenBIOS for Sparc64
Configuration device id QEMU version 1 machine id 0
kernel cmdline
CPUs: 1 x SUNW,UltraSPARC-IIi
UUID: 00000000-0000-0000-0000-000000000000
Welcome to OpenBIOS v1.1 built on Mar 8 2014 12:54
  Type 'help' for detailed information
Trying cdrom:f...
Not a bootable ELF image
Loading a.out image...
Loaded 7680 bytes
entry point is 0x4000

Jumping to entry point 0000000000004000 for type 0000000000000005...
switching to new context: entry point 0x4000 stack 0x00000000ffe86a01
SILO Version 1.4.14
\


                  Welcome to Debian GNU/Linux squeeze!

This is a Debian installation CDROM, built on 20120129-00:49.
Keep it once you have installed your system, as you can boot from it
to repair the system on your hard disk if that ever becomes necessary.

WARNING: You should completely back up all of your hard disks before
  proceeding. The installation procedure can completely and irreversibly
  erase them! If you haven't made backups yet, remove the rescue CD from
  the drive and press L1-A to get back to the OpenBoot prompt.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted
by applicable law.

[ ENTER - Boot install ]   [ Type "expert" - Boot into expert mode ]
                           [ Type "rescue" - Boot into rescue mode ]
boot:
Allocated 64 Megs of memory at 0x40000000 for kernel
Loaded kernel version 2.6.32
Loading initial ramdisk (4465945 bytes at 0x4400000 phys, 0x40C00000 virt)...
/
[    0.000000] PROMLIB: Sun IEEE Boot Prom 'OBP 3.10.24 1999/01/01 01:01'
[    0.000000] PROMLIB: Root node compatible: sun4u
[    0.000000] Initializing cgroup subsys cpuset
[    0.000000] Initializing cgroup subsys cpu
[ 0.000000] Linux version 2.6.32-5-sparc64 (Debian 2.6.32-41) (address@hidden) (gcc version 4.3.5 (Debian 4.3.5-4) ) #1 Mon Jan 16 16:15:31 UTC 2012
[    0.000000] bootconsole [earlyprom0] enabled
[    0.000000] ARCH: SUN4U
[    0.000000] Ethernet address: 52:54:00:12:34:56
[    0.000000] Kernel: Using 2 locked TLB entries for main kernel image.
[    0.000000] Remapping the kernel... done.
[    0.000000] TRAPLOG: Error at trap level 0x2, dumping track stack.
[ 0.000000] TRAPLOG: Trap level 1 TSTATE[0000004480001605] TPC[00000000005ae3ac] TNPC[00000000005ae3c0] TT[68]
[    0.000000] TRAPLOG: TPC<__bzero+0x20/0xc0>
[ 0.000000] TRAPLOG: Trap level 2 TSTATE[0000004480041405] TPC[00000000004074d4] TNPC[00000000004074d8] TT[21]
[    0.000000] TRAPLOG: TPC<kvmap_dtlb_tsb4m_load+0x14/0x3c>
[ 0.000000] TRAPLOG: Trap level 3 TSTATE[0000000000000000] TPC[0000000000000000] TNPC[0000000000000000] TT[0]
[    0.000000] TRAPLOG: TPC<(null)>
[ 0.000000] TRAPLOG: Trap level 4 TSTATE[0000000000000000] TPC[0000000000000000] TNPC[0000000000000000] TT[0]
[    0.000000] TRAPLOG: TPC<(null)>
[    0.000000]               \|/ ____ \|/
[    0.000000]               "@'/ .. \`@"
[    0.000000]               /_| \__/ |_\
[    0.000000]                  \__U_/
[    0.000000] swapper(0): TL1: FPU IEEE Exception [#1]
[ 0.000000] TSTATE: 0000004480001605 TPC: 00000000005ae3ac TNPC: 00000000005ae3c0 Y: 00000000 Not tainted
[    0.000000] TPC: <__bzero+0x20/0xc0>
[ 0.000000] g0: 000000000007cd2a g1: 0000000000000003 g2: 0000000000961710 g3: 0000000000000001 [ 0.000000] g4: 0000000000848378 g5: 0000000000000000 g6: 000000000083c000 g7: 0000000004400000 [ 0.000000] o0: fffff80007e7ff40 o1: 0000000000000090 o2: 0000000000000000 o3: fffff80007e7ff40 [ 0.000000] o4: 0000000000000000 o5: 00000000ffea7400 sp: 000000000083f261 ret_pc: 00000000008a7888
[    0.000000] RPC: <prom_early_alloc+0x3c/0x5c>
[ 0.000000] l0: 0000000000000090 l1: 000000000084e518 l2: 000000000000000e l3: fffffffffffffd74 [ 0.000000] l4: 000000000084e4ec l5: 000000000084e4f0 l6: 00000000008f7564 l7: ffffffffffffffff [ 0.000000] i0: fffff80007e7ff40 i1: 00000000ffd0cad8 i2: 0012910005070000 i3: 0000000000000017 [ 0.000000] i4: 00000000008f7560 i5: 000000000084e4b8 i6: 000000000083f321 i7: 00000000008a7558
[    0.000000] I7: <prom_create_node+0x10/0xe8>
[    0.000000] OOPS: Bogus kernel PC [0000000000000004] in fault handler
[    0.000000] OOPS: RPC [0000000000734e70]
[    0.000000] OOPS: RPC <printk+0x24/0x3c>
[    0.000000] OOPS: Fault was to vaddr[fffff80007e7e000]
[    0.000000] Call Trace:
[    0.000000]  [0000000000407900] sparc64_realfault_common+0x10/0x20
[    0.000000]  [0000000000000004] 0x4
[    0.000000]  [000000000045c510] add_taint+0x24/0x5c
[    0.000000]  [0000000000427a0c] die_if_kernel+0x68/0x290
[    0.000000]  [0000000000427d78] do_fpieee_tl1+0x14/0x20
[    0.000000]  [000000000042442c] tl1_fpieee+0xc/0x20
[    0.000000]  [00000000005ae3ac] __bzero+0x20/0xc0
[    0.000000]  [00000000008a7558] prom_create_node+0x10/0xe8
[    0.000000]  [00000000008a7770] prom_build_devicetree+0xc/0x80
[    0.000000]  [00000000008ab1ac] paging_init+0xa20/0xe18
[    0.000000]  [00000000008a6dc0] setup_arch+0x394/0x3a4
[    0.000000]  [00000000008a4560] start_kernel+0x74/0x36c
[    0.000000]  [0000000000724104] tlb_fixup_done+0x80/0x88
[    0.000000]  [0000000000000000] (null)


ATB,

Mark.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]