cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

spinlock-llsc.h (4149B)


      1/* SPDX-License-Identifier: GPL-2.0
      2 *
      3 * include/asm-sh/spinlock-llsc.h
      4 *
      5 * Copyright (C) 2002, 2003 Paul Mundt
      6 * Copyright (C) 2006, 2007 Akio Idehara
      7 */
      8#ifndef __ASM_SH_SPINLOCK_LLSC_H
      9#define __ASM_SH_SPINLOCK_LLSC_H
     10
     11#include <asm/barrier.h>
     12#include <asm/processor.h>
     13
     14/*
     15 * Your basic SMP spinlocks, allowing only a single CPU anywhere
     16 */
     17
     18#define arch_spin_is_locked(x)		((x)->lock <= 0)
     19
     20/*
     21 * Simple spin lock operations.  There are two variants, one clears IRQ's
     22 * on the local processor, one does not.
     23 *
     24 * We make no fairness assumptions.  They have a cost.
     25 */
     26static inline void arch_spin_lock(arch_spinlock_t *lock)
     27{
     28	unsigned long tmp;
     29	unsigned long oldval;
     30
     31	__asm__ __volatile__ (
     32		"1:						\n\t"
     33		"movli.l	@%2, %0	! arch_spin_lock	\n\t"
     34		"mov		%0, %1				\n\t"
     35		"mov		#0, %0				\n\t"
     36		"movco.l	%0, @%2				\n\t"
     37		"bf		1b				\n\t"
     38		"cmp/pl		%1				\n\t"
     39		"bf		1b				\n\t"
     40		: "=&z" (tmp), "=&r" (oldval)
     41		: "r" (&lock->lock)
     42		: "t", "memory"
     43	);
     44}
     45
     46static inline void arch_spin_unlock(arch_spinlock_t *lock)
     47{
     48	unsigned long tmp;
     49
     50	/* This could be optimised with ARCH_HAS_MMIOWB */
     51	mmiowb();
     52	__asm__ __volatile__ (
     53		"mov		#1, %0 ! arch_spin_unlock	\n\t"
     54		"mov.l		%0, @%1				\n\t"
     55		: "=&z" (tmp)
     56		: "r" (&lock->lock)
     57		: "t", "memory"
     58	);
     59}
     60
     61static inline int arch_spin_trylock(arch_spinlock_t *lock)
     62{
     63	unsigned long tmp, oldval;
     64
     65	__asm__ __volatile__ (
     66		"1:						\n\t"
     67		"movli.l	@%2, %0	! arch_spin_trylock	\n\t"
     68		"mov		%0, %1				\n\t"
     69		"mov		#0, %0				\n\t"
     70		"movco.l	%0, @%2				\n\t"
     71		"bf		1b				\n\t"
     72		"synco						\n\t"
     73		: "=&z" (tmp), "=&r" (oldval)
     74		: "r" (&lock->lock)
     75		: "t", "memory"
     76	);
     77
     78	return oldval;
     79}
     80
     81/*
     82 * Read-write spinlocks, allowing multiple readers but only one writer.
     83 *
     84 * NOTE! it is quite common to have readers in interrupts but no interrupt
     85 * writers. For those circumstances we can "mix" irq-safe locks - any writer
     86 * needs to get a irq-safe write-lock, but readers can get non-irqsafe
     87 * read-locks.
     88 */
     89
     90static inline void arch_read_lock(arch_rwlock_t *rw)
     91{
     92	unsigned long tmp;
     93
     94	__asm__ __volatile__ (
     95		"1:						\n\t"
     96		"movli.l	@%1, %0	! arch_read_lock	\n\t"
     97		"cmp/pl		%0				\n\t"
     98		"bf		1b				\n\t"
     99		"add		#-1, %0				\n\t"
    100		"movco.l	%0, @%1				\n\t"
    101		"bf		1b				\n\t"
    102		: "=&z" (tmp)
    103		: "r" (&rw->lock)
    104		: "t", "memory"
    105	);
    106}
    107
    108static inline void arch_read_unlock(arch_rwlock_t *rw)
    109{
    110	unsigned long tmp;
    111
    112	__asm__ __volatile__ (
    113		"1:						\n\t"
    114		"movli.l	@%1, %0	! arch_read_unlock	\n\t"
    115		"add		#1, %0				\n\t"
    116		"movco.l	%0, @%1				\n\t"
    117		"bf		1b				\n\t"
    118		: "=&z" (tmp)
    119		: "r" (&rw->lock)
    120		: "t", "memory"
    121	);
    122}
    123
    124static inline void arch_write_lock(arch_rwlock_t *rw)
    125{
    126	unsigned long tmp;
    127
    128	__asm__ __volatile__ (
    129		"1:						\n\t"
    130		"movli.l	@%1, %0	! arch_write_lock	\n\t"
    131		"cmp/hs		%2, %0				\n\t"
    132		"bf		1b				\n\t"
    133		"sub		%2, %0				\n\t"
    134		"movco.l	%0, @%1				\n\t"
    135		"bf		1b				\n\t"
    136		: "=&z" (tmp)
    137		: "r" (&rw->lock), "r" (RW_LOCK_BIAS)
    138		: "t", "memory"
    139	);
    140}
    141
    142static inline void arch_write_unlock(arch_rwlock_t *rw)
    143{
    144	__asm__ __volatile__ (
    145		"mov.l		%1, @%0 ! arch_write_unlock	\n\t"
    146		:
    147		: "r" (&rw->lock), "r" (RW_LOCK_BIAS)
    148		: "t", "memory"
    149	);
    150}
    151
    152static inline int arch_read_trylock(arch_rwlock_t *rw)
    153{
    154	unsigned long tmp, oldval;
    155
    156	__asm__ __volatile__ (
    157		"1:						\n\t"
    158		"movli.l	@%2, %0	! arch_read_trylock	\n\t"
    159		"mov		%0, %1				\n\t"
    160		"cmp/pl		%0				\n\t"
    161		"bf		2f				\n\t"
    162		"add		#-1, %0				\n\t"
    163		"movco.l	%0, @%2				\n\t"
    164		"bf		1b				\n\t"
    165		"2:						\n\t"
    166		"synco						\n\t"
    167		: "=&z" (tmp), "=&r" (oldval)
    168		: "r" (&rw->lock)
    169		: "t", "memory"
    170	);
    171
    172	return (oldval > 0);
    173}
    174
    175static inline int arch_write_trylock(arch_rwlock_t *rw)
    176{
    177	unsigned long tmp, oldval;
    178
    179	__asm__ __volatile__ (
    180		"1:						\n\t"
    181		"movli.l	@%2, %0	! arch_write_trylock	\n\t"
    182		"mov		%0, %1				\n\t"
    183		"cmp/hs		%3, %0				\n\t"
    184		"bf		2f				\n\t"
    185		"sub		%3, %0				\n\t"
    186		"2:						\n\t"
    187		"movco.l	%0, @%2				\n\t"
    188		"bf		1b				\n\t"
    189		"synco						\n\t"
    190		: "=&z" (tmp), "=&r" (oldval)
    191		: "r" (&rw->lock), "r" (RW_LOCK_BIAS)
    192		: "t", "memory"
    193	);
    194
    195	return (oldval > (RW_LOCK_BIAS - 1));
    196}
    197
    198#endif /* __ASM_SH_SPINLOCK_LLSC_H */