mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-26 22:24:09 +08:00
3a6bfbc91d
The arch_mutex_cpu_relax() function, introduced by 34b133f
, is
hacky and ugly. It was added a few years ago to address the fact
that common cpu_relax() calls include yielding on s390, and thus
impact the optimistic spinning functionality of mutexes. Nowadays
we use this function well beyond mutexes: rwsem, qrwlock, mcs and
lockref. Since the macro that defines the call is in the mutex header,
any users must include mutex.h and the naming is misleading as well.
This patch (i) renames the call to cpu_relax_lowlatency ("relax, but
only if you can do it with very low latency") and (ii) defines it in
each arch's asm/processor.h local header, just like for regular cpu_relax
functions. On all archs, except s390, cpu_relax_lowlatency is simply cpu_relax,
and thus we can take it out of mutex.h. While this can seem redundant,
I believe it is a good choice as it allows us to move out arch specific
logic from generic locking primitives and enables future(?) archs to
transparently define it, similarly to System Z.
Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
Signed-off-by: Peter Zijlstra <peterz@infradead.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Anton Blanchard <anton@samba.org>
Cc: Aurelien Jacquiot <a-jacquiot@ti.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Bharat Bhushan <r65777@freescale.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Chen Liqin <liqin.linux@gmail.com>
Cc: Chris Metcalf <cmetcalf@tilera.com>
Cc: Christian Borntraeger <borntraeger@de.ibm.com>
Cc: Chris Zankel <chris@zankel.net>
Cc: David Howells <dhowells@redhat.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: Deepthi Dharwar <deepthi@linux.vnet.ibm.com>
Cc: Dominik Dingel <dingel@linux.vnet.ibm.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Guan Xuetao <gxt@mprc.pku.edu.cn>
Cc: Haavard Skinnemoen <hskinnemoen@gmail.com>
Cc: Hans-Christian Egtvedt <egtvedt@samfundet.no>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: Helge Deller <deller@gmx.de>
Cc: Hirokazu Takata <takata@linux-m32r.org>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: James E.J. Bottomley <jejb@parisc-linux.org>
Cc: James Hogan <james.hogan@imgtec.com>
Cc: Jason Wang <jasowang@redhat.com>
Cc: Jesper Nilsson <jesper.nilsson@axis.com>
Cc: Joe Perches <joe@perches.com>
Cc: Jonas Bonn <jonas@southpole.se>
Cc: Joseph Myers <joseph@codesourcery.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Koichi Yasutake <yasutake.koichi@jp.panasonic.com>
Cc: Lennox Wu <lennox.wu@gmail.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mark Salter <msalter@redhat.com>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Matt Turner <mattst88@gmail.com>
Cc: Max Filippov <jcmvbkbc@gmail.com>
Cc: Michael Neuling <mikey@neuling.org>
Cc: Michal Simek <monstr@monstr.eu>
Cc: Mikael Starvik <starvik@axis.com>
Cc: Nicolas Pitre <nico@linaro.org>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Paul Burton <paul.burton@imgtec.com>
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Qais Yousef <qais.yousef@imgtec.com>
Cc: Qiaowei Ren <qiaowei.ren@intel.com>
Cc: Rafael Wysocki <rafael.j.wysocki@intel.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Richard Kuo <rkuo@codeaurora.org>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Steven Miao <realmz6@gmail.com>
Cc: Steven Rostedt <srostedt@redhat.com>
Cc: Stratos Karafotis <stratosk@semaphore.gr>
Cc: Tim Chen <tim.c.chen@linux.intel.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Vasily Kulikov <segoon@openwall.com>
Cc: Vineet Gupta <vgupta@synopsys.com>
Cc: Vineet Gupta <Vineet.Gupta1@synopsys.com>
Cc: Waiman Long <Waiman.Long@hp.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Wolfram Sang <wsa@the-dreams.de>
Cc: adi-buildroot-devel@lists.sourceforge.net
Cc: linux390@de.ibm.com
Cc: linux-alpha@vger.kernel.org
Cc: linux-am33-list@redhat.com
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-c6x-dev@linux-c6x.org
Cc: linux-cris-kernel@axis.com
Cc: linux-hexagon@vger.kernel.org
Cc: linux-ia64@vger.kernel.org
Cc: linux@lists.openrisc.net
Cc: linux-m32r-ja@ml.linux-m32r.org
Cc: linux-m32r@ml.linux-m32r.org
Cc: linux-m68k@lists.linux-m68k.org
Cc: linux-metag@vger.kernel.org
Cc: linux-mips@linux-mips.org
Cc: linux-parisc@vger.kernel.org
Cc: linuxppc-dev@lists.ozlabs.org
Cc: linux-s390@vger.kernel.org
Cc: linux-sh@vger.kernel.org
Cc: linux-xtensa@linux-xtensa.org
Cc: sparclinux@vger.kernel.org
Link: http://lkml.kernel.org/r/1404079773.2619.4.camel@buesod1.americas.hpqcorp.net
Signed-off-by: Ingo Molnar <mingo@kernel.org>
217 lines
6.1 KiB
C
217 lines
6.1 KiB
C
/*
|
|
* include/asm-xtensa/processor.h
|
|
*
|
|
* This file is subject to the terms and conditions of the GNU General Public
|
|
* License. See the file "COPYING" in the main directory of this archive
|
|
* for more details.
|
|
*
|
|
* Copyright (C) 2001 - 2008 Tensilica Inc.
|
|
*/
|
|
|
|
#ifndef _XTENSA_PROCESSOR_H
|
|
#define _XTENSA_PROCESSOR_H
|
|
|
|
#include <variant/core.h>
|
|
#include <platform/hardware.h>
|
|
|
|
#include <linux/compiler.h>
|
|
#include <asm/ptrace.h>
|
|
#include <asm/types.h>
|
|
#include <asm/regs.h>
|
|
|
|
/* Assertions. */
|
|
|
|
#if (XCHAL_HAVE_WINDOWED != 1)
|
|
# error Linux requires the Xtensa Windowed Registers Option.
|
|
#endif
|
|
|
|
#define ARCH_SLAB_MINALIGN XCHAL_DATA_WIDTH
|
|
|
|
/*
|
|
* User space process size: 1 GB.
|
|
* Windowed call ABI requires caller and callee to be located within the same
|
|
* 1 GB region. The C compiler places trampoline code on the stack for sources
|
|
* that take the address of a nested C function (a feature used by glibc), so
|
|
* the 1 GB requirement applies to the stack as well.
|
|
*/
|
|
|
|
#ifdef CONFIG_MMU
|
|
#define TASK_SIZE __XTENSA_UL_CONST(0x40000000)
|
|
#else
|
|
#define TASK_SIZE (PLATFORM_DEFAULT_MEM_START + PLATFORM_DEFAULT_MEM_SIZE)
|
|
#endif
|
|
|
|
#define STACK_TOP TASK_SIZE
|
|
#define STACK_TOP_MAX STACK_TOP
|
|
|
|
/*
|
|
* General exception cause assigned to debug exceptions. Debug exceptions go
|
|
* to their own vector, rather than the general exception vectors (user,
|
|
* kernel, double); and their specific causes are reported via DEBUGCAUSE
|
|
* rather than EXCCAUSE. However it is sometimes convenient to redirect debug
|
|
* exceptions to the general exception mechanism. To do this, an otherwise
|
|
* unused EXCCAUSE value was assigned to debug exceptions for this purpose.
|
|
*/
|
|
|
|
#define EXCCAUSE_MAPPED_DEBUG 63
|
|
|
|
/*
|
|
* We use DEPC also as a flag to distinguish between double and regular
|
|
* exceptions. For performance reasons, DEPC might contain the value of
|
|
* EXCCAUSE for regular exceptions, so we use this definition to mark a
|
|
* valid double exception address.
|
|
* (Note: We use it in bgeui, so it should be 64, 128, or 256)
|
|
*/
|
|
|
|
#define VALID_DOUBLE_EXCEPTION_ADDRESS 64
|
|
|
|
/* LOCKLEVEL defines the interrupt level that masks all
|
|
* general-purpose interrupts.
|
|
*/
|
|
#define LOCKLEVEL XCHAL_EXCM_LEVEL
|
|
|
|
/* WSBITS and WBBITS are the width of the WINDOWSTART and WINDOWBASE
|
|
* registers
|
|
*/
|
|
#define WSBITS (XCHAL_NUM_AREGS / 4) /* width of WINDOWSTART in bits */
|
|
#define WBBITS (XCHAL_NUM_AREGS_LOG2 - 2) /* width of WINDOWBASE in bits */
|
|
|
|
#ifndef __ASSEMBLY__
|
|
|
|
/* Build a valid return address for the specified call winsize.
|
|
* winsize must be 1 (call4), 2 (call8), or 3 (call12)
|
|
*/
|
|
#define MAKE_RA_FOR_CALL(ra,ws) (((ra) & 0x3fffffff) | (ws) << 30)
|
|
|
|
/* Convert return address to a valid pc
|
|
* Note: We assume that the stack pointer is in the same 1GB ranges as the ra
|
|
*/
|
|
#define MAKE_PC_FROM_RA(ra,sp) (((ra) & 0x3fffffff) | ((sp) & 0xc0000000))
|
|
|
|
typedef struct {
|
|
unsigned long seg;
|
|
} mm_segment_t;
|
|
|
|
struct thread_struct {
|
|
|
|
/* kernel's return address and stack pointer for context switching */
|
|
unsigned long ra; /* kernel's a0: return address and window call size */
|
|
unsigned long sp; /* kernel's a1: stack pointer */
|
|
|
|
mm_segment_t current_ds; /* see uaccess.h for example uses */
|
|
|
|
/* struct xtensa_cpuinfo info; */
|
|
|
|
unsigned long bad_vaddr; /* last user fault */
|
|
unsigned long bad_uaddr; /* last kernel fault accessing user space */
|
|
unsigned long error_code;
|
|
|
|
unsigned long ibreak[XCHAL_NUM_IBREAK];
|
|
unsigned long dbreaka[XCHAL_NUM_DBREAK];
|
|
unsigned long dbreakc[XCHAL_NUM_DBREAK];
|
|
|
|
/* Make structure 16 bytes aligned. */
|
|
int align[0] __attribute__ ((aligned(16)));
|
|
};
|
|
|
|
|
|
/*
|
|
* Default implementation of macro that returns current
|
|
* instruction pointer ("program counter").
|
|
*/
|
|
#define current_text_addr() ({ __label__ _l; _l: &&_l;})
|
|
|
|
|
|
/* This decides where the kernel will search for a free chunk of vm
|
|
* space during mmap's.
|
|
*/
|
|
#define TASK_UNMAPPED_BASE (TASK_SIZE / 2)
|
|
|
|
#define INIT_THREAD \
|
|
{ \
|
|
ra: 0, \
|
|
sp: sizeof(init_stack) + (long) &init_stack, \
|
|
current_ds: {0}, \
|
|
/*info: {0}, */ \
|
|
bad_vaddr: 0, \
|
|
bad_uaddr: 0, \
|
|
error_code: 0, \
|
|
}
|
|
|
|
|
|
/*
|
|
* Do necessary setup to start up a newly executed thread.
|
|
* Note: We set-up ps as if we did a call4 to the new pc.
|
|
* set_thread_state in signal.c depends on it.
|
|
*/
|
|
#define USER_PS_VALUE ((1 << PS_WOE_BIT) | \
|
|
(1 << PS_CALLINC_SHIFT) | \
|
|
(USER_RING << PS_RING_SHIFT) | \
|
|
(1 << PS_UM_BIT) | \
|
|
(1 << PS_EXCM_BIT))
|
|
|
|
/* Clearing a0 terminates the backtrace. */
|
|
#define start_thread(regs, new_pc, new_sp) \
|
|
memset(regs, 0, sizeof(*regs)); \
|
|
regs->pc = new_pc; \
|
|
regs->ps = USER_PS_VALUE; \
|
|
regs->areg[1] = new_sp; \
|
|
regs->areg[0] = 0; \
|
|
regs->wmask = 1; \
|
|
regs->depc = 0; \
|
|
regs->windowbase = 0; \
|
|
regs->windowstart = 1;
|
|
|
|
/* Forward declaration */
|
|
struct task_struct;
|
|
struct mm_struct;
|
|
|
|
/* Free all resources held by a thread. */
|
|
#define release_thread(thread) do { } while(0)
|
|
|
|
/* Copy and release all segment info associated with a VM */
|
|
#define copy_segments(p, mm) do { } while(0)
|
|
#define release_segments(mm) do { } while(0)
|
|
#define forget_segments() do { } while (0)
|
|
|
|
#define thread_saved_pc(tsk) (task_pt_regs(tsk)->pc)
|
|
|
|
extern unsigned long get_wchan(struct task_struct *p);
|
|
|
|
#define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc)
|
|
#define KSTK_ESP(tsk) (task_pt_regs(tsk)->areg[1])
|
|
|
|
#define cpu_relax() barrier()
|
|
#define cpu_relax_lowlatency() cpu_relax()
|
|
|
|
/* Special register access. */
|
|
|
|
#define WSR(v,sr) __asm__ __volatile__ ("wsr %0,"__stringify(sr) :: "a"(v));
|
|
#define RSR(v,sr) __asm__ __volatile__ ("rsr %0,"__stringify(sr) : "=a"(v));
|
|
|
|
#define set_sr(x,sr) ({unsigned int v=(unsigned int)x; WSR(v,sr);})
|
|
#define get_sr(sr) ({unsigned int v; RSR(v,sr); v; })
|
|
|
|
#ifndef XCHAL_HAVE_EXTERN_REGS
|
|
#define XCHAL_HAVE_EXTERN_REGS 0
|
|
#endif
|
|
|
|
#if XCHAL_HAVE_EXTERN_REGS
|
|
|
|
static inline void set_er(unsigned long value, unsigned long addr)
|
|
{
|
|
asm volatile ("wer %0, %1" : : "a" (value), "a" (addr) : "memory");
|
|
}
|
|
|
|
static inline unsigned long get_er(unsigned long addr)
|
|
{
|
|
register unsigned long value;
|
|
asm volatile ("rer %0, %1" : "=a" (value) : "a" (addr) : "memory");
|
|
return value;
|
|
}
|
|
|
|
#endif /* XCHAL_HAVE_EXTERN_REGS */
|
|
|
|
#endif /* __ASSEMBLY__ */
|
|
#endif /* _XTENSA_PROCESSOR_H */
|