linux/include/asm-arm/system.h
<<
>>
Prefs
   1#ifndef __ASM_ARM_SYSTEM_H
   2#define __ASM_ARM_SYSTEM_H
   3
   4#ifdef __KERNEL__
   5
   6#include <asm/memory.h>
   7
   8#define CPU_ARCH_UNKNOWN        0
   9#define CPU_ARCH_ARMv3          1
  10#define CPU_ARCH_ARMv4          2
  11#define CPU_ARCH_ARMv4T         3
  12#define CPU_ARCH_ARMv5          4
  13#define CPU_ARCH_ARMv5T         5
  14#define CPU_ARCH_ARMv5TE        6
  15#define CPU_ARCH_ARMv5TEJ       7
  16#define CPU_ARCH_ARMv6          8
  17#define CPU_ARCH_ARMv7          9
  18
  19/*
  20 * CR1 bits (CP#15 CR1)
  21 */
  22#define CR_M    (1 << 0)        /* MMU enable                           */
  23#define CR_A    (1 << 1)        /* Alignment abort enable               */
  24#define CR_C    (1 << 2)        /* Dcache enable                        */
  25#define CR_W    (1 << 3)        /* Write buffer enable                  */
  26#define CR_P    (1 << 4)        /* 32-bit exception handler             */
  27#define CR_D    (1 << 5)        /* 32-bit data address range            */
  28#define CR_L    (1 << 6)        /* Implementation defined               */
  29#define CR_B    (1 << 7)        /* Big endian                           */
  30#define CR_S    (1 << 8)        /* System MMU protection                */
  31#define CR_R    (1 << 9)        /* ROM MMU protection                   */
  32#define CR_F    (1 << 10)       /* Implementation defined               */
  33#define CR_Z    (1 << 11)       /* Implementation defined               */
  34#define CR_I    (1 << 12)       /* Icache enable                        */
  35#define CR_V    (1 << 13)       /* Vectors relocated to 0xffff0000      */
  36#define CR_RR   (1 << 14)       /* Round Robin cache replacement        */
  37#define CR_L4   (1 << 15)       /* LDR pc can set T bit                 */
  38#define CR_DT   (1 << 16)
  39#define CR_IT   (1 << 18)
  40#define CR_ST   (1 << 19)
  41#define CR_FI   (1 << 21)       /* Fast interrupt (lower latency mode)  */
  42#define CR_U    (1 << 22)       /* Unaligned access operation           */
  43#define CR_XP   (1 << 23)       /* Extended page tables                 */
  44#define CR_VE   (1 << 24)       /* Vectored interrupts                  */
  45
  46#define CPUID_ID        0
  47#define CPUID_CACHETYPE 1
  48#define CPUID_TCM       2
  49#define CPUID_TLBTYPE   3
  50
  51#ifdef CONFIG_CPU_CP15
  52#define read_cpuid(reg)                                                 \
  53        ({                                                              \
  54                unsigned int __val;                                     \
  55                asm("mrc        p15, 0, %0, c0, c0, " __stringify(reg)  \
  56                    : "=r" (__val)                                      \
  57                    :                                                   \
  58                    : "cc");                                            \
  59                __val;                                                  \
  60        })
  61#else
  62#define read_cpuid(reg) (processor_id)
  63#endif
  64
  65/*
  66 * This is used to ensure the compiler did actually allocate the register we
  67 * asked it for some inline assembly sequences.  Apparently we can't trust
  68 * the compiler from one version to another so a bit of paranoia won't hurt.
  69 * This string is meant to be concatenated with the inline asm string and
  70 * will cause compilation to stop on mismatch.
  71 * (for details, see gcc PR 15089)
  72 */
  73#define __asmeq(x, y)  ".ifnc " x "," y " ; .err ; .endif\n\t"
  74
  75#ifndef __ASSEMBLY__
  76
  77#include <linux/linkage.h>
  78#include <linux/irqflags.h>
  79
  80#define __exception     __attribute__((section(".exception.text")))
  81
  82struct thread_info;
  83struct task_struct;
  84
  85/* information about the system we're running on */
  86extern unsigned int system_rev;
  87extern unsigned int system_serial_low;
  88extern unsigned int system_serial_high;
  89extern unsigned int mem_fclk_21285;
  90
  91struct pt_regs;
  92
  93void die(const char *msg, struct pt_regs *regs, int err)
  94                __attribute__((noreturn));
  95
  96struct siginfo;
  97void arm_notify_die(const char *str, struct pt_regs *regs, struct siginfo *info,
  98                unsigned long err, unsigned long trap);
  99
 100void hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
 101                                       struct pt_regs *),
 102                     int sig, const char *name);
 103
 104#define xchg(ptr,x) \
 105        ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
 106
 107extern asmlinkage void __backtrace(void);
 108extern asmlinkage void c_backtrace(unsigned long fp, int pmode);
 109
 110struct mm_struct;
 111extern void show_pte(struct mm_struct *mm, unsigned long addr);
 112extern void __show_regs(struct pt_regs *);
 113
 114extern int cpu_architecture(void);
 115extern void cpu_init(void);
 116
 117void arm_machine_restart(char mode);
 118extern void (*arm_pm_restart)(char str);
 119
 120/*
 121 * Intel's XScale3 core supports some v6 features (supersections, L2)
 122 * but advertises itself as v5 as it does not support the v6 ISA.  For
 123 * this reason, we need a way to explicitly test for this type of CPU.
 124 */
 125#ifndef CONFIG_CPU_XSC3
 126#define cpu_is_xsc3()   0
 127#else
 128static inline int cpu_is_xsc3(void)
 129{
 130        extern unsigned int processor_id;
 131
 132        if ((processor_id & 0xffffe000) == 0x69056000)
 133                return 1;
 134
 135        return 0;
 136}
 137#endif
 138
 139#if !defined(CONFIG_CPU_XSCALE) && !defined(CONFIG_CPU_XSC3)
 140#define cpu_is_xscale() 0
 141#else
 142#define cpu_is_xscale() 1
 143#endif
 144
 145#define UDBG_UNDEFINED  (1 << 0)
 146#define UDBG_SYSCALL    (1 << 1)
 147#define UDBG_BADABORT   (1 << 2)
 148#define UDBG_SEGV       (1 << 3)
 149#define UDBG_BUS        (1 << 4)
 150
 151extern unsigned int user_debug;
 152
 153#if __LINUX_ARM_ARCH__ >= 4
 154#define vectors_high()  (cr_alignment & CR_V)
 155#else
 156#define vectors_high()  (0)
 157#endif
 158
 159#if __LINUX_ARM_ARCH__ >= 7
 160#define isb() __asm__ __volatile__ ("isb" : : : "memory")
 161#define dsb() __asm__ __volatile__ ("dsb" : : : "memory")
 162#define dmb() __asm__ __volatile__ ("dmb" : : : "memory")
 163#elif defined(CONFIG_CPU_XSC3) || __LINUX_ARM_ARCH__ == 6
 164#define isb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c5, 4" \
 165                                    : : "r" (0) : "memory")
 166#define dsb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \
 167                                    : : "r" (0) : "memory")
 168#define dmb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" \
 169                                    : : "r" (0) : "memory")
 170#else
 171#define isb() __asm__ __volatile__ ("" : : : "memory")
 172#define dsb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \
 173                                    : : "r" (0) : "memory")
 174#define dmb() __asm__ __volatile__ ("" : : : "memory")
 175#endif
 176
 177#ifndef CONFIG_SMP
 178#define mb()    do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)
 179#define rmb()   do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)
 180#define wmb()   do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)
 181#define smp_mb()        barrier()
 182#define smp_rmb()       barrier()
 183#define smp_wmb()       barrier()
 184#else
 185#define mb()            dmb()
 186#define rmb()           dmb()
 187#define wmb()           dmb()
 188#define smp_mb()        dmb()
 189#define smp_rmb()       dmb()
 190#define smp_wmb()       dmb()
 191#endif
 192#define read_barrier_depends()          do { } while(0)
 193#define smp_read_barrier_depends()      do { } while(0)
 194
 195#define set_mb(var, value)      do { var = value; smp_mb(); } while (0)
 196#define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
 197
 198extern unsigned long cr_no_alignment;   /* defined in entry-armv.S */
 199extern unsigned long cr_alignment;      /* defined in entry-armv.S */
 200
 201static inline unsigned int get_cr(void)
 202{
 203        unsigned int val;
 204        asm("mrc p15, 0, %0, c1, c0, 0  @ get CR" : "=r" (val) : : "cc");
 205        return val;
 206}
 207
 208static inline void set_cr(unsigned int val)
 209{
 210        asm volatile("mcr p15, 0, %0, c1, c0, 0 @ set CR"
 211          : : "r" (val) : "cc");
 212        isb();
 213}
 214
 215#ifndef CONFIG_SMP
 216extern void adjust_cr(unsigned long mask, unsigned long set);
 217#endif
 218
 219#define CPACC_FULL(n)           (3 << (n * 2))
 220#define CPACC_SVC(n)            (1 << (n * 2))
 221#define CPACC_DISABLE(n)        (0 << (n * 2))
 222
 223static inline unsigned int get_copro_access(void)
 224{
 225        unsigned int val;
 226        asm("mrc p15, 0, %0, c1, c0, 2 @ get copro access"
 227          : "=r" (val) : : "cc");
 228        return val;
 229}
 230
 231static inline void set_copro_access(unsigned int val)
 232{
 233        asm volatile("mcr p15, 0, %0, c1, c0, 2 @ set copro access"
 234          : : "r" (val) : "cc");
 235        isb();
 236}
 237
 238/*
 239 * switch_mm() may do a full cache flush over the context switch,
 240 * so enable interrupts over the context switch to avoid high
 241 * latency.
 242 */
 243#define __ARCH_WANT_INTERRUPTS_ON_CTXSW
 244
 245/*
 246 * switch_to(prev, next) should switch from task `prev' to `next'
 247 * `prev' will never be the same as `next'.  schedule() itself
 248 * contains the memory barrier to tell GCC not to cache `current'.
 249 */
 250extern struct task_struct *__switch_to(struct task_struct *, struct thread_info *, struct thread_info *);
 251
 252#define switch_to(prev,next,last)                                       \
 253do {                                                                    \
 254        last = __switch_to(prev,task_thread_info(prev), task_thread_info(next));        \
 255} while (0)
 256
 257/*
 258 * On SMP systems, when the scheduler does migration-cost autodetection,
 259 * it needs a way to flush as much of the CPU's caches as possible.
 260 *
 261 * TODO: fill this in!
 262 */
 263static inline void sched_cacheflush(void)
 264{
 265}
 266
 267#if defined(CONFIG_CPU_SA1100) || defined(CONFIG_CPU_SA110)
 268/*
 269 * On the StrongARM, "swp" is terminally broken since it bypasses the
 270 * cache totally.  This means that the cache becomes inconsistent, and,
 271 * since we use normal loads/stores as well, this is really bad.
 272 * Typically, this causes oopsen in filp_close, but could have other,
 273 * more disasterous effects.  There are two work-arounds:
 274 *  1. Disable interrupts and emulate the atomic swap
 275 *  2. Clean the cache, perform atomic swap, flush the cache
 276 *
 277 * We choose (1) since its the "easiest" to achieve here and is not
 278 * dependent on the processor type.
 279 *
 280 * NOTE that this solution won't work on an SMP system, so explcitly
 281 * forbid it here.
 282 */
 283#define swp_is_buggy
 284#endif
 285
 286static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
 287{
 288        extern void __bad_xchg(volatile void *, int);
 289        unsigned long ret;
 290#ifdef swp_is_buggy
 291        unsigned long flags;
 292#endif
 293#if __LINUX_ARM_ARCH__ >= 6
 294        unsigned int tmp;
 295#endif
 296
 297        switch (size) {
 298#if __LINUX_ARM_ARCH__ >= 6
 299        case 1:
 300                asm volatile("@ __xchg1\n"
 301                "1:     ldrexb  %0, [%3]\n"
 302                "       strexb  %1, %2, [%3]\n"
 303                "       teq     %1, #0\n"
 304                "       bne     1b"
 305                        : "=&r" (ret), "=&r" (tmp)
 306                        : "r" (x), "r" (ptr)
 307                        : "memory", "cc");
 308                break;
 309        case 4:
 310                asm volatile("@ __xchg4\n"
 311                "1:     ldrex   %0, [%3]\n"
 312                "       strex   %1, %2, [%3]\n"
 313                "       teq     %1, #0\n"
 314                "       bne     1b"
 315                        : "=&r" (ret), "=&r" (tmp)
 316                        : "r" (x), "r" (ptr)
 317                        : "memory", "cc");
 318                break;
 319#elif defined(swp_is_buggy)
 320#ifdef CONFIG_SMP
 321#error SMP is not supported on this platform
 322#endif
 323        case 1:
 324                raw_local_irq_save(flags);
 325                ret = *(volatile unsigned char *)ptr;
 326                *(volatile unsigned char *)ptr = x;
 327                raw_local_irq_restore(flags);
 328                break;
 329
 330        case 4:
 331                raw_local_irq_save(flags);
 332                ret = *(volatile unsigned long *)ptr;
 333                *(volatile unsigned long *)ptr = x;
 334                raw_local_irq_restore(flags);
 335                break;
 336#else
 337        case 1:
 338                asm volatile("@ __xchg1\n"
 339                "       swpb    %0, %1, [%2]"
 340                        : "=&r" (ret)
 341                        : "r" (x), "r" (ptr)
 342                        : "memory", "cc");
 343                break;
 344        case 4:
 345                asm volatile("@ __xchg4\n"
 346                "       swp     %0, %1, [%2]"
 347                        : "=&r" (ret)
 348                        : "r" (x), "r" (ptr)
 349                        : "memory", "cc");
 350                break;
 351#endif
 352        default:
 353                __bad_xchg(ptr, size), ret = 0;
 354                break;
 355        }
 356
 357        return ret;
 358}
 359
 360extern void disable_hlt(void);
 361extern void enable_hlt(void);
 362
 363#endif /* __ASSEMBLY__ */
 364
 365#define arch_align_stack(x) (x)
 366
 367#endif /* __KERNEL__ */
 368
 369#endif
 370
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.