MIPS: mipsregs.h: Add read const Cop0 macros

Some Cop0 registers are constant and have no side effects when read.
There is no need for the inline asm to read these to be marked
__volatile__, and doing so prevents them from being removed by the
compiler.

Add a few new accessor macros to handle these registers more efficiently
(especially for the sake of running in a guest where redundant access to
the register may trap to the hypervisor):
  __read_const_32bit_c0_register()
  __read_const_64bit_c0_register()
  __read_const_ulong_c0_register()

Signed-off-by: James Hogan <jhogan@kernel.org>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Maciej W. Rozycki <macro@mips.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/17922/
This commit is contained in:
James Hogan 2017-12-11 16:13:14 +00:00
parent ffe1f9356f
commit cd1e0737ef
No known key found for this signature in database
GPG key ID: 6C0B6993DE38767A

View file

@ -1245,14 +1245,14 @@ do { \
* Macros to access the system control coprocessor
*/
#define __read_32bit_c0_register(source, sel) \
#define ___read_32bit_c0_register(source, sel, vol) \
({ unsigned int __res; \
if (sel == 0) \
__asm__ __volatile__( \
__asm__ vol( \
"mfc0\t%0, " #source "\n\t" \
: "=r" (__res)); \
else \
__asm__ __volatile__( \
__asm__ vol( \
".set\tmips32\n\t" \
"mfc0\t%0, " #source ", " #sel "\n\t" \
".set\tmips0\n\t" \
@ -1260,18 +1260,18 @@ do { \
__res; \
})
#define __read_64bit_c0_register(source, sel) \
#define ___read_64bit_c0_register(source, sel, vol) \
({ unsigned long long __res; \
if (sizeof(unsigned long) == 4) \
__res = __read_64bit_c0_split(source, sel); \
__res = __read_64bit_c0_split(source, sel, vol); \
else if (sel == 0) \
__asm__ __volatile__( \
__asm__ vol( \
".set\tmips3\n\t" \
"dmfc0\t%0, " #source "\n\t" \
".set\tmips0" \
: "=r" (__res)); \
else \
__asm__ __volatile__( \
__asm__ vol( \
".set\tmips64\n\t" \
"dmfc0\t%0, " #source ", " #sel "\n\t" \
".set\tmips0" \
@ -1279,6 +1279,18 @@ do { \
__res; \
})
#define __read_32bit_c0_register(source, sel) \
___read_32bit_c0_register(source, sel, __volatile__)
#define __read_const_32bit_c0_register(source, sel) \
___read_32bit_c0_register(source, sel,)
#define __read_64bit_c0_register(source, sel) \
___read_64bit_c0_register(source, sel, __volatile__)
#define __read_const_64bit_c0_register(source, sel) \
___read_64bit_c0_register(source, sel,)
#define __write_32bit_c0_register(register, sel, value) \
do { \
if (sel == 0) \
@ -1316,6 +1328,11 @@ do { \
(unsigned long) __read_32bit_c0_register(reg, sel) : \
(unsigned long) __read_64bit_c0_register(reg, sel))
#define __read_const_ulong_c0_register(reg, sel) \
((sizeof(unsigned long) == 4) ? \
(unsigned long) __read_const_32bit_c0_register(reg, sel) : \
(unsigned long) __read_const_64bit_c0_register(reg, sel))
#define __write_ulong_c0_register(reg, sel, val) \
do { \
if (sizeof(unsigned long) == 4) \
@ -1346,14 +1363,14 @@ do { \
* These versions are only needed for systems with more than 38 bits of
* physical address space running the 32-bit kernel. That's none atm :-)
*/
#define __read_64bit_c0_split(source, sel) \
#define __read_64bit_c0_split(source, sel, vol) \
({ \
unsigned long long __val; \
unsigned long __flags; \
\
local_irq_save(__flags); \
if (sel == 0) \
__asm__ __volatile__( \
__asm__ vol( \
".set\tmips64\n\t" \
"dmfc0\t%L0, " #source "\n\t" \
"dsra\t%M0, %L0, 32\n\t" \
@ -1361,7 +1378,7 @@ do { \
".set\tmips0" \
: "=r" (__val)); \
else \
__asm__ __volatile__( \
__asm__ vol( \
".set\tmips64\n\t" \
"dmfc0\t%L0, " #source ", " #sel "\n\t" \
"dsra\t%M0, %L0, 32\n\t" \