]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
parisc: Fix alignment of pa_tlb_lock in assembly on 32-bit SMP kernel
authorHelge Deller <deller@gmx.de>
Tue, 2 Jan 2018 19:36:44 +0000 (20:36 +0100)
committerHelge Deller <deller@gmx.de>
Tue, 2 Jan 2018 21:21:54 +0000 (22:21 +0100)
Qemu for PARISC reported on a 32bit SMP parisc kernel strange failures
about "Not-handled unaligned insn 0x0e8011d6 and 0x0c2011c9."

Those opcodes evaluate to the ldcw() assembly instruction which requires
(on 32bit) an alignment of 16 bytes to ensure atomicity.

As it turns out, qemu is correct and in our assembly code in entry.S and
pacache.S we don't pay attention to the required alignment.

This patch fixes the problem by aligning the lock offset in assembly
code in the same manner as we do in our C-code.

Signed-off-by: Helge Deller <deller@gmx.de>
Cc: <stable@vger.kernel.org> # v4.0+
arch/parisc/include/asm/ldcw.h
arch/parisc/kernel/entry.S
arch/parisc/kernel/pacache.S

index dd5a08aaa4da746ff09b19cf5f93e9d58489ff14..3eb4bfc1fb365478f11c9c87bfb3b3124fab567a 100644 (file)
@@ -12,6 +12,7 @@
    for the semaphore.  */
 
 #define __PA_LDCW_ALIGNMENT    16
+#define __PA_LDCW_ALIGN_ORDER  4
 #define __ldcw_align(a) ({                                     \
        unsigned long __ret = (unsigned long) &(a)->lock[0];    \
        __ret = (__ret + __PA_LDCW_ALIGNMENT - 1)               \
@@ -29,6 +30,7 @@
    ldcd). */
 
 #define __PA_LDCW_ALIGNMENT    4
+#define __PA_LDCW_ALIGN_ORDER  2
 #define __ldcw_align(a) (&(a)->slock)
 #define __LDCW "ldcw,co"
 
index f3cecf5117cf8ab14724f0ea3535220c3224d569..e95207c0565eb12308e12d48c45bd5309ae6e2ae 100644 (file)
@@ -35,6 +35,7 @@
 #include <asm/pgtable.h>
 #include <asm/signal.h>
 #include <asm/unistd.h>
+#include <asm/ldcw.h>
 #include <asm/thread_info.h>
 
 #include <linux/linkage.h>
 #endif
 
        .import         pa_tlb_lock,data
+       .macro  load_pa_tlb_lock reg
+#if __PA_LDCW_ALIGNMENT > 4
+       load32  PA(pa_tlb_lock) + __PA_LDCW_ALIGNMENT-1, \reg
+       depi    0,31,__PA_LDCW_ALIGN_ORDER, \reg
+#else
+       load32  PA(pa_tlb_lock), \reg
+#endif
+       .endm
 
        /* space_to_prot macro creates a prot id from a space id */
 
        .macro          tlb_lock        spc,ptp,pte,tmp,tmp1,fault
 #ifdef CONFIG_SMP
        cmpib,COND(=),n 0,\spc,2f
-       load32          PA(pa_tlb_lock),\tmp
+       load_pa_tlb_lock \tmp
 1:     LDCW            0(\tmp),\tmp1
        cmpib,COND(=)   0,\tmp1,1b
        nop
        /* Release pa_tlb_lock lock. */
        .macro          tlb_unlock1     spc,tmp
 #ifdef CONFIG_SMP
-       load32          PA(pa_tlb_lock),\tmp
+       load_pa_tlb_lock \tmp
        tlb_unlock0     \spc,\tmp
 #endif
        .endm
index adf7187f89515ec69b19461f60ce379e552397dc..2d40c4ff3f6918ae9b2e2c6af71e20658a9850e1 100644 (file)
@@ -36,6 +36,7 @@
 #include <asm/assembly.h>
 #include <asm/pgtable.h>
 #include <asm/cache.h>
+#include <asm/ldcw.h>
 #include <linux/linkage.h>
 
        .text
@@ -333,8 +334,12 @@ ENDPROC_CFI(flush_data_cache_local)
 
        .macro  tlb_lock        la,flags,tmp
 #ifdef CONFIG_SMP
-       ldil            L%pa_tlb_lock,%r1
-       ldo             R%pa_tlb_lock(%r1),\la
+#if __PA_LDCW_ALIGNMENT > 4
+       load32          pa_tlb_lock + __PA_LDCW_ALIGNMENT-1, \la
+       depi            0,31,__PA_LDCW_ALIGN_ORDER, \la
+#else
+       load32          pa_tlb_lock, \la
+#endif
        rsm             PSW_SM_I,\flags
 1:     LDCW            0(\la),\tmp
        cmpib,<>,n      0,\tmp,3f