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
---
arch/mips/include/asm/mipsregs.h | 37 ++++++++++++++++++++++++---------
1 file changed, 27 insertions(+), 10 deletions(-)
diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index 6b1f1ad0542c..74c931104714 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -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" \
--
git-series 0.9.1
|