mips: MAAR: Add XPA mode support
authorSerge Semin <Sergey.Semin@baikalelectronics.ru>
Wed, 6 May 2020 17:42:30 +0000 (20:42 +0300)
committerThomas Bogendoerfer <tsbogend@alpha.franken.de>
Tue, 19 May 2020 15:39:32 +0000 (17:39 +0200)
When XPA mode is enabled the normally 32-bits MAAR pair registers
are extended to be of 64-bits width as in pure 64-bits MIPS
architecture. In this case the MAAR registers can enable the
speculative loads/stores for addresses of up to 39-bits width.
But in this case the process of the MAAR initialization changes a bit.
The upper 32-bits of the registers are supposed to be accessed by mean
of the dedicated instructions mfhc0/mthc0 and there is a CP0.MAAR.VH
bit which should be set together with CP0.MAAR.VL as indication
of the boundary validity. All of these peculiarities were taken into
account in this commit so the speculative loads/stores would work
when XPA mode is enabled.

Co-developed-by: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
Signed-off-by: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: Paul Burton <paulburton@kernel.org>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: linux-pm@vger.kernel.org
Cc: devicetree@vger.kernel.org
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
arch/mips/include/asm/maar.h
arch/mips/include/asm/mipsregs.h
arch/mips/mm/init.c

index 6908b93..99f1c3e 100644 (file)
@@ -32,7 +32,7 @@ unsigned platform_maar_init(unsigned num_pairs);
  * @upper:     The highest address that the MAAR pair will affect. Must be
  *             aligned to one byte before a 2^16 byte boundary.
  * @attrs:     The accessibility attributes to program, eg. MIPS_MAAR_S. The
- *             MIPS_MAAR_VL attribute will automatically be set.
+ *             MIPS_MAAR_VL/MIPS_MAAR_VH attributes will automatically be set.
  *
  * Program the pair of MAAR registers specified by idx to apply the attributes
  * specified by attrs to the range of addresses from lower to higher.
@@ -48,17 +48,30 @@ static inline void write_maar_pair(unsigned idx, phys_addr_t lower,
        /* Automatically set MIPS_MAAR_VL */
        attrs |= MIPS_MAAR_VL;
 
-       /* Write the upper address & attributes (only MIPS_MAAR_VL matters) */
+       /*
+        * Write the upper address & attributes (both MIPS_MAAR_VL and
+        * MIPS_MAAR_VH matter)
+        */
        write_c0_maari(idx << 1);
        back_to_back_c0_hazard();
        write_c0_maar(((upper >> 4) & MIPS_MAAR_ADDR) | attrs);
        back_to_back_c0_hazard();
+#ifdef CONFIG_XPA
+       upper >>= MIPS_MAARX_ADDR_SHIFT;
+       writex_c0_maar(((upper >> 4) & MIPS_MAARX_ADDR) | MIPS_MAARX_VH);
+       back_to_back_c0_hazard();
+#endif
 
        /* Write the lower address & attributes */
        write_c0_maari((idx << 1) | 0x1);
        back_to_back_c0_hazard();
        write_c0_maar((lower >> 4) | attrs);
        back_to_back_c0_hazard();
+#ifdef CONFIG_XPA
+       lower >>= MIPS_MAARX_ADDR_SHIFT;
+       writex_c0_maar(((lower >> 4) & MIPS_MAARX_ADDR) | MIPS_MAARX_VH);
+       back_to_back_c0_hazard();
+#endif
 }
 
 /**
index 90f843c..238adce 100644 (file)
 #define MIPS_MAAR_ADDR_SHIFT   12
 #define MIPS_MAAR_S            (_ULCAST_(1) << 1)
 #define MIPS_MAAR_VL           (_ULCAST_(1) << 0)
+#ifdef CONFIG_XPA
+#define MIPS_MAAR_V            (MIPS_MAAR_VH | MIPS_MAAR_VL)
+#else
+#define MIPS_MAAR_V            MIPS_MAAR_VL
+#endif
+#define MIPS_MAARX_VH          (_ULCAST_(1) << 31)
+#define MIPS_MAARX_ADDR                0xF
+#define MIPS_MAARX_ADDR_SHIFT  32
 
 /* MAARI bit definitions */
 #define MIPS_MAARI_INDEX       (_ULCAST_(0x3f) << 0)
@@ -1723,6 +1731,8 @@ do {                                                                      \
 #define write_c0_lladdr(val)   __write_ulong_c0_register($17, 0, val)
 #define read_c0_maar()         __read_ulong_c0_register($17, 1)
 #define write_c0_maar(val)     __write_ulong_c0_register($17, 1, val)
+#define readx_c0_maar()                __readx_32bit_c0_register($17, 1)
+#define writex_c0_maar(val)    __writex_32bit_c0_register($17, 1, val)
 #define read_c0_maari()                __read_32bit_c0_register($17, 2)
 #define write_c0_maari(val)    __write_32bit_c0_register($17, 2, val)
 
index 7968400..620ebfa 100644 (file)
@@ -358,17 +358,23 @@ void maar_init(void)
                write_c0_maari(i);
                back_to_back_c0_hazard();
                upper = read_c0_maar();
+#ifdef CONFIG_XPA
+               upper |= (phys_addr_t)readx_c0_maar() << MIPS_MAARX_ADDR_SHIFT;
+#endif
 
                write_c0_maari(i + 1);
                back_to_back_c0_hazard();
                lower = read_c0_maar();
+#ifdef CONFIG_XPA
+               lower |= (phys_addr_t)readx_c0_maar() << MIPS_MAARX_ADDR_SHIFT;
+#endif
 
                attr = lower & upper;
                lower = (lower & MIPS_MAAR_ADDR) << 4;
                upper = ((upper & MIPS_MAAR_ADDR) << 4) | 0xffff;
 
                pr_info("  [%d]: ", i / 2);
-               if (!(attr & MIPS_MAAR_VL)) {
+               if ((attr & MIPS_MAAR_V) != MIPS_MAAR_V) {
                        pr_cont("disabled\n");
                        continue;
                }