linux/arch/frv/include/asm/system.h
<<
>>
Prefs
   1/* system.h: FR-V CPU control definitions
   2 *
   3 * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
   4 * Written by David Howells (dhowells@redhat.com)
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public License
   8 * as published by the Free Software Foundation; either version
   9 * 2 of the License, or (at your option) any later version.
  10 */
  11
  12#ifndef _ASM_SYSTEM_H
  13#define _ASM_SYSTEM_H
  14
  15#include <linux/types.h>
  16#include <linux/linkage.h>
  17#include <linux/kernel.h>
  18
  19struct thread_struct;
  20
  21/*
  22 * switch_to(prev, next) should switch from task `prev' to `next'
  23 * `prev' will never be the same as `next'.
  24 * The `mb' is to tell GCC not to cache `current' across this call.
  25 */
  26extern asmlinkage
  27struct task_struct *__switch_to(struct thread_struct *prev_thread,
  28                                struct thread_struct *next_thread,
  29                                struct task_struct *prev);
  30
  31#define switch_to(prev, next, last)                                     \
  32do {                                                                    \
  33        (prev)->thread.sched_lr =                                       \
  34                (unsigned long) __builtin_return_address(0);            \
  35        (last) = __switch_to(&(prev)->thread, &(next)->thread, (prev)); \
  36        mb();                                                           \
  37} while(0)
  38
  39/*
  40 * interrupt flag manipulation
  41 * - use virtual interrupt management since touching the PSR is slow
  42 *   - ICC2.Z: T if interrupts virtually disabled
  43 *   - ICC2.C: F if interrupts really disabled
  44 * - if Z==1 upon interrupt:
  45 *   - C is set to 0
  46 *   - interrupts are really disabled
  47 *   - entry.S returns immediately
  48 * - uses TIHI (TRAP if Z==0 && C==0) #2 to really reenable interrupts
  49 *   - if taken, the trap:
  50 *     - sets ICC2.C
  51 *     - enables interrupts
  52 */
  53#define local_irq_disable()                                     \
  54do {                                                            \
  55        /* set Z flag, but don't change the C flag */           \
  56        asm volatile("  andcc   gr0,gr0,gr0,icc2        \n"     \
  57                     :                                          \
  58                     :                                          \
  59                     : "memory", "icc2"                         \
  60                     );                                         \
  61} while(0)
  62
  63#define local_irq_enable()                                      \
  64do {                                                            \
  65        /* clear Z flag and then test the C flag */             \
  66        asm volatile("  oricc   gr0,#1,gr0,icc2         \n"     \
  67                     "  tihi    icc2,gr0,#2             \n"     \
  68                     :                                          \
  69                     :                                          \
  70                     : "memory", "icc2"                         \
  71                     );                                         \
  72} while(0)
  73
  74#define local_save_flags(flags)                                 \
  75do {                                                            \
  76        typecheck(unsigned long, flags);                        \
  77        asm volatile("movsg ccr,%0"                             \
  78                     : "=r"(flags)                              \
  79                     :                                          \
  80                     : "memory");                               \
  81                                                                \
  82        /* shift ICC2.Z to bit 0 */                             \
  83        flags >>= 26;                                           \
  84                                                                \
  85        /* make flags 1 if interrupts disabled, 0 otherwise */  \
  86        flags &= 1UL;                                           \
  87} while(0)
  88
  89#define irqs_disabled() \
  90        ({unsigned long flags; local_save_flags(flags); !!flags; })
  91
  92#define local_irq_save(flags)                   \
  93do {                                            \
  94        typecheck(unsigned long, flags);        \
  95        local_save_flags(flags);                \
  96        local_irq_disable();                    \
  97} while(0)
  98
  99#define local_irq_restore(flags)                                        \
 100do {                                                                    \
 101        typecheck(unsigned long, flags);                                \
 102                                                                        \
 103        /* load the Z flag by turning 1 if disabled into 0 if disabled  \
 104         * and thus setting the Z flag but not the C flag */            \
 105        asm volatile("  xoricc  %0,#1,gr0,icc2          \n"             \
 106                     /* then test Z=0 and C=0 */                        \
 107                     "  tihi    icc2,gr0,#2             \n"             \
 108                     :                                                  \
 109                     : "r"(flags)                                       \
 110                     : "memory", "icc2"                                 \
 111                     );                                                 \
 112                                                                        \
 113} while(0)
 114
 115/*
 116 * real interrupt flag manipulation
 117 */
 118#define __local_irq_disable()                           \
 119do {                                                    \
 120        unsigned long psr;                              \
 121        asm volatile("  movsg   psr,%0          \n"     \
 122                     "  andi    %0,%2,%0        \n"     \
 123                     "  ori     %0,%1,%0        \n"     \
 124                     "  movgs   %0,psr          \n"     \
 125                     : "=r"(psr)                        \
 126                     : "i" (PSR_PIL_14), "i" (~PSR_PIL) \
 127                     : "memory");                       \
 128} while(0)
 129
 130#define __local_irq_enable()                            \
 131do {                                                    \
 132        unsigned long psr;                              \
 133        asm volatile("  movsg   psr,%0          \n"     \
 134                     "  andi    %0,%1,%0        \n"     \
 135                     "  movgs   %0,psr          \n"     \
 136                     : "=r"(psr)                        \
 137                     : "i" (~PSR_PIL)                   \
 138                     : "memory");                       \
 139} while(0)
 140
 141#define __local_save_flags(flags)               \
 142do {                                            \
 143        typecheck(unsigned long, flags);        \
 144        asm("movsg psr,%0"                      \
 145            : "=r"(flags)                       \
 146            :                                   \
 147            : "memory");                        \
 148} while(0)
 149
 150#define __local_irq_save(flags)                         \
 151do {                                                    \
 152        unsigned long npsr;                             \
 153        typecheck(unsigned long, flags);                \
 154        asm volatile("  movsg   psr,%0          \n"     \
 155                     "  andi    %0,%3,%1        \n"     \
 156                     "  ori     %1,%2,%1        \n"     \
 157                     "  movgs   %1,psr          \n"     \
 158                     : "=r"(flags), "=r"(npsr)          \
 159                     : "i" (PSR_PIL_14), "i" (~PSR_PIL) \
 160                     : "memory");                       \
 161} while(0)
 162
 163#define __local_irq_restore(flags)                      \
 164do {                                                    \
 165        typecheck(unsigned long, flags);                \
 166        asm volatile("  movgs   %0,psr          \n"     \
 167                     :                                  \
 168                     : "r" (flags)                      \
 169                     : "memory");                       \
 170} while(0)
 171
 172#define __irqs_disabled() \
 173        ((__get_PSR() & PSR_PIL) >= PSR_PIL_14)
 174
 175/*
 176 * Force strict CPU ordering.
 177 */
 178#define nop()                   asm volatile ("nop"::)
 179#define mb()                    asm volatile ("membar" : : :"memory")
 180#define rmb()                   asm volatile ("membar" : : :"memory")
 181#define wmb()                   asm volatile ("membar" : : :"memory")
 182#define read_barrier_depends()  do { } while (0)
 183
 184#ifdef CONFIG_SMP
 185#define smp_mb()                        mb()
 186#define smp_rmb()                       rmb()
 187#define smp_wmb()                       wmb()
 188#define smp_read_barrier_depends()      read_barrier_depends()
 189#define set_mb(var, value) \
 190        do { xchg(&var, (value)); } while (0)
 191#else
 192#define smp_mb()                        barrier()
 193#define smp_rmb()                       barrier()
 194#define smp_wmb()                       barrier()
 195#define smp_read_barrier_depends()      do {} while(0)
 196#define set_mb(var, value) \
 197        do { var = (value); barrier(); } while (0)
 198#endif
 199
 200extern void die_if_kernel(const char *, ...) __attribute__((format(printf, 1, 2)));
 201extern void free_initmem(void);
 202
 203#define arch_align_stack(x) (x)
 204
 205/*****************************************************************************/
 206/*
 207 * compare and conditionally exchange value with memory
 208 * - if (*ptr == test) then orig = *ptr; *ptr = test;
 209 * - if (*ptr != test) then orig = *ptr;
 210 */
 211#ifndef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS
 212
 213#define cmpxchg(ptr, test, new)                                                 \
 214({                                                                              \
 215        __typeof__(ptr) __xg_ptr = (ptr);                                       \
 216        __typeof__(*(ptr)) __xg_orig, __xg_tmp;                                 \
 217        __typeof__(*(ptr)) __xg_test = (test);                                  \
 218        __typeof__(*(ptr)) __xg_new = (new);                                    \
 219                                                                                \
 220        switch (sizeof(__xg_orig)) {                                            \
 221        case 4:                                                                 \
 222                asm volatile(                                                   \
 223                        "0:                                             \n"     \
 224                        "       orcc            gr0,gr0,gr0,icc3        \n"     \
 225                        "       ckeq            icc3,cc7                \n"     \
 226                        "       ld.p            %M0,%1                  \n"     \
 227                        "       orcr            cc7,cc7,cc3             \n"     \
 228                        "       sub%I4cc        %1,%4,%2,icc0           \n"     \
 229                        "       bne             icc0,#0,1f              \n"     \
 230                        "       cst.p           %3,%M0          ,cc3,#1 \n"     \
 231                        "       corcc           gr29,gr29,gr0   ,cc3,#1 \n"     \
 232                        "       beq             icc3,#0,0b              \n"     \
 233                        "1:                                             \n"     \
 234                        : "+U"(*__xg_ptr), "=&r"(__xg_orig), "=&r"(__xg_tmp)    \
 235                        : "r"(__xg_new), "NPr"(__xg_test)                       \
 236                        : "memory", "cc7", "cc3", "icc3", "icc0"                \
 237                        );                                                      \
 238                break;                                                          \
 239                                                                                \
 240        default:                                                                \
 241                __xg_orig = (__typeof__(__xg_orig))0;                           \
 242                asm volatile("break");                                          \
 243                break;                                                          \
 244        }                                                                       \
 245                                                                                \
 246        __xg_orig;                                                              \
 247})
 248
 249#else
 250
 251extern uint32_t __cmpxchg_32(uint32_t *v, uint32_t test, uint32_t new);
 252
 253#define cmpxchg(ptr, test, new)                                                 \
 254({                                                                              \
 255        __typeof__(ptr) __xg_ptr = (ptr);                                       \
 256        __typeof__(*(ptr)) __xg_orig;                                           \
 257        __typeof__(*(ptr)) __xg_test = (test);                                  \
 258        __typeof__(*(ptr)) __xg_new = (new);                                    \
 259                                                                                \
 260        switch (sizeof(__xg_orig)) {                                            \
 261        case 4: __xg_orig = (__force __typeof__(*ptr))                          \
 262                        __cmpxchg_32((__force uint32_t *)__xg_ptr,              \
 263                                         (__force uint32_t)__xg_test,           \
 264                                         (__force uint32_t)__xg_new); break;    \
 265        default:                                                                \
 266                __xg_orig = (__typeof__(__xg_orig))0;                           \
 267                asm volatile("break");                                          \
 268                break;                                                          \
 269        }                                                                       \
 270                                                                                \
 271        __xg_orig;                                                              \
 272})
 273
 274#endif
 275
 276#include <asm-generic/cmpxchg-local.h>
 277
 278static inline unsigned long __cmpxchg_local(volatile void *ptr,
 279                                      unsigned long old,
 280                                      unsigned long new, int size)
 281{
 282        switch (size) {
 283        case 4:
 284                return cmpxchg((unsigned long *)ptr, old, new);
 285        default:
 286                return __cmpxchg_local_generic(ptr, old, new, size);
 287        }
 288
 289        return old;
 290}
 291
 292/*
 293 * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
 294 * them available.
 295 */
 296#define cmpxchg_local(ptr, o, n)                                        \
 297        ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o), \
 298                        (unsigned long)(n), sizeof(*(ptr))))
 299#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
 300
 301#endif /* _ASM_SYSTEM_H */
 302
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.