s390: avoid extable collisions
authorHeiko Carstens <heiko.carstens@de.ibm.com>
Fri, 10 Jun 2016 07:57:05 +0000 (09:57 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Mon, 13 Jun 2016 13:58:26 +0000 (15:58 +0200)
We have some inline assemblies where the extable entry points to a
label at the end of an inline assembly which is not followed by an
instruction.

On the other hand we have also inline assemblies where the extable
entry points to the first instruction of an inline assembly.

If a first type inline asm (extable point to empty label at the end)
would be directly followed by a second type inline asm (extable points
to first instruction) then we would have two different extable entries
that point to the same instruction but would have a different target
address.

This can lead to quite random behaviour, depending on sorting order.

I verified that we currently do not have such collisions within the
kernel. However to avoid such subtle bugs add a couple of nop
instructions to those inline assemblies which contain an extable that
points to an empty label.

Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/hypfs/hypfs_diag.c
arch/s390/hypfs/hypfs_vm.c
arch/s390/include/asm/diag.h
arch/s390/kernel/ipl.c
arch/s390/mm/fault.c

index 045035796ca7d59f196740078b4ae4c0f0243717..27779f0743ac9ebb0c6c6d874a75c902df281a1a 100644 (file)
@@ -344,7 +344,7 @@ static inline int __diag204(unsigned long subcode, unsigned long size, void *add
 
        asm volatile(
                "       diag    %2,%0,0x204\n"
-               "0:\n"
+               "0:     nopr    %%r7\n"
                EX_TABLE(0b,0b)
                : "+d" (_subcode), "+d" (_size) : "d" (addr) : "memory");
        if (_subcode)
index 44feac38ccfc26dacaf57fae0463922bdafb10dd..012919d9833bbee66e4c993a54d562cdfef6a333 100644 (file)
@@ -70,7 +70,7 @@ static int diag2fc(int size, char* query, void *addr)
        diag_stat_inc(DIAG_STAT_X2FC);
        asm volatile(
                "       diag    %0,%1,0x2fc\n"
-               "0:\n"
+               "0:     nopr    %%r7\n"
                EX_TABLE(0b,0b)
                : "=d" (residual_cnt), "+d" (rc) : "0" (&parm_list) : "memory");
 
index 5fac921c1c4210c66b8cb3f3a6b4ca4f4bf71ed9..86cae09e076af3048fda8045c05779233e264617 100644 (file)
@@ -49,7 +49,7 @@ static inline void diag10_range(unsigned long start_pfn, unsigned long num_pfn)
        diag_stat_inc(DIAG_STAT_X010);
        asm volatile(
                "0:     diag    %0,%1,0x10\n"
-               "1:\n"
+               "1:     nopr    %%r7\n"
                EX_TABLE(0b, 1b)
                EX_TABLE(1b, 1b)
                : : "a" (start_addr), "a" (end_addr));
index a6d2a998e328a2c0da9c6666b337c783a4272f8d..44317398b77bbe8d1b095305286f8277d8a1e62c 100644 (file)
@@ -174,7 +174,7 @@ static inline int __diag308(unsigned long subcode, void *addr)
 
        asm volatile(
                "       diag    %0,%2,0x308\n"
-               "0:\n"
+               "0:     nopr    %%r7\n"
                EX_TABLE(0b,0b)
                : "+d" (_addr), "+d" (_rc)
                : "d" (subcode) : "cc", "memory");
index 19288c1b36d32bfed0013e6a90385d8d4c82d08c..6ad7eff84c8237fb74747ac9850157cf5e693db9 100644 (file)
@@ -624,7 +624,7 @@ void pfault_fini(void)
        diag_stat_inc(DIAG_STAT_X258);
        asm volatile(
                "       diag    %0,0,0x258\n"
-               "0:\n"
+               "0:     nopr    %%r7\n"
                EX_TABLE(0b,0b)
                : : "a" (&refbk), "m" (refbk) : "cc");
 }