~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/xtensa/kernel/s32c1i_selftest.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * S32C1I selftest.
  3  *
  4  * This file is subject to the terms and conditions of the GNU General Public
  5  * License.  See the file "COPYING" in the main directory of this archive
  6  * for more details.
  7  *
  8  * Copyright (C) 2016 Cadence Design Systems Inc.
  9  */
 10 
 11 #include <linux/init.h>
 12 #include <linux/kernel.h>
 13 
 14 #include <asm/traps.h>
 15 
 16 #if XCHAL_HAVE_S32C1I
 17 
 18 static int __initdata rcw_word, rcw_probe_pc, rcw_exc;
 19 
 20 /*
 21  * Basic atomic compare-and-swap, that records PC of S32C1I for probing.
 22  *
 23  * If *v == cmp, set *v = set.  Return previous *v.
 24  */
 25 static inline int probed_compare_swap(int *v, int cmp, int set)
 26 {
 27         int tmp;
 28 
 29         __asm__ __volatile__(
 30                         "       movi    %1, 1f\n"
 31                         "       s32i    %1, %4, 0\n"
 32                         "       wsr     %2, scompare1\n"
 33                         "1:     s32c1i  %0, %3, 0\n"
 34                         : "=a" (set), "=&a" (tmp)
 35                         : "a" (cmp), "a" (v), "a" (&rcw_probe_pc), "" (set)
 36                         : "memory"
 37                         );
 38         return set;
 39 }
 40 
 41 /* Handle probed exception */
 42 
 43 static void __init do_probed_exception(struct pt_regs *regs)
 44 {
 45         if (regs->pc == rcw_probe_pc) { /* exception on s32c1i ? */
 46                 regs->pc += 3;          /* skip the s32c1i instruction */
 47                 rcw_exc = regs->exccause;
 48         } else {
 49                 do_unhandled(regs);
 50         }
 51 }
 52 
 53 /* Simple test of S32C1I (soc bringup assist) */
 54 
 55 static int __init check_s32c1i(void)
 56 {
 57         int n, cause1, cause2;
 58         void *handbus, *handdata, *handaddr; /* temporarily saved handlers */
 59 
 60         rcw_probe_pc = 0;
 61         handbus  = trap_set_handler(EXCCAUSE_LOAD_STORE_ERROR,
 62                         do_probed_exception);
 63         handdata = trap_set_handler(EXCCAUSE_LOAD_STORE_DATA_ERROR,
 64                         do_probed_exception);
 65         handaddr = trap_set_handler(EXCCAUSE_LOAD_STORE_ADDR_ERROR,
 66                         do_probed_exception);
 67 
 68         /* First try an S32C1I that does not store: */
 69         rcw_exc = 0;
 70         rcw_word = 1;
 71         n = probed_compare_swap(&rcw_word, 0, 2);
 72         cause1 = rcw_exc;
 73 
 74         /* took exception? */
 75         if (cause1 != 0) {
 76                 /* unclean exception? */
 77                 if (n != 2 || rcw_word != 1)
 78                         panic("S32C1I exception error");
 79         } else if (rcw_word != 1 || n != 1) {
 80                 panic("S32C1I compare error");
 81         }
 82 
 83         /* Then an S32C1I that stores: */
 84         rcw_exc = 0;
 85         rcw_word = 0x1234567;
 86         n = probed_compare_swap(&rcw_word, 0x1234567, 0xabcde);
 87         cause2 = rcw_exc;
 88 
 89         if (cause2 != 0) {
 90                 /* unclean exception? */
 91                 if (n != 0xabcde || rcw_word != 0x1234567)
 92                         panic("S32C1I exception error (b)");
 93         } else if (rcw_word != 0xabcde || n != 0x1234567) {
 94                 panic("S32C1I store error");
 95         }
 96 
 97         /* Verify consistency of exceptions: */
 98         if (cause1 || cause2) {
 99                 pr_warn("S32C1I took exception %d, %d\n", cause1, cause2);
100                 /* If emulation of S32C1I upon bus error gets implemented,
101                  * we can get rid of this panic for single core (not SMP)
102                  */
103                 panic("S32C1I exceptions not currently supported");
104         }
105         if (cause1 != cause2)
106                 panic("inconsistent S32C1I exceptions");
107 
108         trap_set_handler(EXCCAUSE_LOAD_STORE_ERROR, handbus);
109         trap_set_handler(EXCCAUSE_LOAD_STORE_DATA_ERROR, handdata);
110         trap_set_handler(EXCCAUSE_LOAD_STORE_ADDR_ERROR, handaddr);
111         return 0;
112 }
113 
114 #else /* XCHAL_HAVE_S32C1I */
115 
116 /* This condition should not occur with a commercially deployed processor.
117  * Display reminder for early engr test or demo chips / FPGA bitstreams
118  */
119 static int __init check_s32c1i(void)
120 {
121         pr_warn("Processor configuration lacks atomic compare-and-swap support!\n");
122         return 0;
123 }
124 
125 #endif /* XCHAL_HAVE_S32C1I */
126 
127 early_initcall(check_s32c1i);
128 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php