MIPS: mipsregs.h: Add read const Cop0 macros
authorJames Hogan <jhogan@kernel.org>
Mon, 11 Dec 2017 16:13:14 +0000 (16:13 +0000)
committerJames Hogan <jhogan@kernel.org>
Tue, 9 Jan 2018 22:26:16 +0000 (22:26 +0000)
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/

arch/mips/include/asm/mipsregs.h

index 6b1f1ad..9c409f2 100644 (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"                        \