summaryrefslogtreecommitdiffstats
path: root/arch/s390/boot/head.S
diff options
context:
space:
mode:
authorHeiko Carstens <hca@linux.ibm.com>2022-05-11 14:05:30 +0200
committerHeiko Carstens <hca@linux.ibm.com>2022-05-17 15:16:29 +0200
commite9953b729b789c0e2984859e3b2170b7fa8520d5 (patch)
tree9b0ed9313105dcd2b3028bc598d23e9f010a8a61 /arch/s390/boot/head.S
parentadda746629b4a3950f313bc645fa0e54daee871c (diff)
downloadlinux-e9953b729b789c0e2984859e3b2170b7fa8520d5.tar.gz
linux-e9953b729b789c0e2984859e3b2170b7fa8520d5.tar.bz2
linux-e9953b729b789c0e2984859e3b2170b7fa8520d5.zip
s390/boot: workaround llvm IAS bug
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>
Diffstat (limited to 'arch/s390/boot/head.S')
-rw-r--r--arch/s390/boot/head.S34
1 files changed, 21 insertions, 13 deletions
diff --git a/arch/s390/boot/head.S b/arch/s390/boot/head.S
index 2ced90172680..8402e1cd133b 100644
--- a/arch/s390/boot/head.S
+++ b/arch/s390/boot/head.S
@@ -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