s390/boot: workaround llvm IAS bug
authorHeiko Carstens <hca@linux.ibm.com>
Wed, 11 May 2022 12:05:30 +0000 (14:05 +0200)
committerHeiko Carstens <hca@linux.ibm.com>
Tue, 17 May 2022 13:16:29 +0000 (15:16 +0200)
For at least the mvc and clc instructions llvm's integrated assembler can
generate incorrect code. In particular this happens with decompressor boot
code. The reason seems to be that relocations for the second displacement
of each instruction are at incorrect locations (-/+: gas vs llvm IAS):

mvc     __LC_IO_NEW_PSW(16),.Lnewpsw

results in

        4:      d2 0f 01 f0 00 00       mvc     496(16,%r0),0
-                       8: R_390_12     .head.text+0x10
+        6: R_390_12     .head.text+0x10

and
clc     0(3,%r4),.L_hdr
results in

      258:      d5 02 40 00 00 00       clc     0(3,%r4),0
-                       25c: R_390_12   .head.text+0x324
+        25a: R_390_12   .head.text+0x324

Workaround this by writing the code in a different way.

Tested-by: Nathan Chancellor <nathan@kernel.org>
Tested-by: Nick Desaulniers <ndesaulniers@google.com>
Link: https://github.com/llvm/llvm-project/issues/55411
Link: https://lore.kernel.org/r/20220511120532.2228616-7-hca@linux.ibm.com
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
arch/s390/boot/head.S

index 2ced901..8402e1c 100644 (file)
@@ -42,7 +42,8 @@ ipl_start:
 # subroutine to wait for end I/O
 #
 .Lirqwait:
-       mvc     __LC_IO_NEW_PSW(16),.Lnewpsw    # set up IO interrupt psw
+       larl    %r13,.Lnewpsw           # set up IO interrupt psw
+       mvc     __LC_IO_NEW_PSW(16),0(%r13)
        lpsw    .Lwaitpsw
 .Lioint:
        br      %r14
@@ -155,9 +156,11 @@ ipl_start:
        lr      %r2,%r3
 .Lnotrunc:
        l       %r4,.Linitrd
-       clc     0(3,%r4),.L_hdr         # if it is HDRx
+       larl    %r13,.L_hdr
+       clc     0(3,%r4),0(%r13)        # if it is HDRx
        bz      .Lagain1                # skip dataset header
-       clc     0(3,%r4),.L_eof         # if it is EOFx
+       larl    %r13,.L_eof
+       clc     0(3,%r4),0(%r13)        # if it is EOFx
        bz      .Lagain1                # skip dateset trailer
 
        lr      %r5,%r2
@@ -181,9 +184,11 @@ ipl_start:
 .Lrdcont:
        l       %r2,.Linitrd
 
-       clc     0(3,%r2),.L_hdr         # skip HDRx and EOFx
+       larl    %r13,.L_hdr             # skip HDRx and EOFx
+       clc     0(3,%r2),0(%r13)
        bz      .Lagain2
-       clc     0(3,%r2),.L_eof
+       larl    %r13,.L_eof
+       clc     0(3,%r2),0(%r13)
        bz      .Lagain2
 
 #
@@ -260,20 +265,23 @@ SYM_CODE_START_LOCAL(startup_normal)
        .fill   16,4,0x0
 0:     lmh     %r0,%r15,0(%r13)        # clear high-order half of gprs
        sam64                           # switch to 64 bit addressing mode
-       basr    %r13,0                  # get base
-.LPG0:
-       mvc     __LC_EXT_NEW_PSW(16),.Lext_new_psw-.LPG0(%r13)
-       mvc     __LC_PGM_NEW_PSW(16),.Lpgm_new_psw-.LPG0(%r13)
-       mvc     __LC_IO_NEW_PSW(16),.Lio_new_psw-.LPG0(%r13)
+       larl    %r13,.Lext_new_psw
+       mvc     __LC_EXT_NEW_PSW(16),0(%r13)
+       larl    %r13,.Lpgm_new_psw
+       mvc     __LC_PGM_NEW_PSW(16),0(%r13)
+       larl    %r13,.Lio_new_psw
+       mvc     __LC_IO_NEW_PSW(16),0(%r13)
        xc      0x200(256),0x200        # partially clear lowcore
        xc      0x300(256),0x300
        xc      0xe00(256),0xe00
        xc      0xf00(256),0xf00
-       lctlg   %c0,%c15,.Lctl-.LPG0(%r13)      # load control registers
+       larl    %r13,.Lctl
+       lctlg   %c0,%c15,0(%r13)        # load control registers
        stcke   __LC_BOOT_CLOCK
        mvc     __LC_LAST_UPDATE_CLOCK(8),__LC_BOOT_CLOCK+1
-       spt     6f-.LPG0(%r13)
-       mvc     __LC_LAST_UPDATE_TIMER(8),6f-.LPG0(%r13)
+       larl    %r13,6f
+       spt     0(%r13)
+       mvc     __LC_LAST_UPDATE_TIMER(8),0(%r13)
        larl    %r15,_stack_end-STACK_FRAME_OVERHEAD
        brasl   %r14,sclp_early_setup_buffer
        brasl   %r14,verify_facilities