Commit 37e37c20 authored by Michael Holzheu's avatar Michael Holzheu Committed by Martin Schwidefsky
Browse files

[S390] Fix stfle() lowcore protection problem



The stfle() function writes into lowcore memory when stfl_fac_list
is initialized with "S390_lowcore.stfl_fac_list = 0". For older
compilers this triggers a lowcore exception. With newer compilers
and "-OXX" compile option the bug does not show up because
the "S390_lowcore.stfl_fac_list" initialization is removed by the
compiler. The reason for thatis the incorrect "=m"
(S390_lowcore.stfl_fac_list) constraint in the stfl inline assembly.

The following shows the disassembly of the stfle() optimized code
that is inlined in the lgr_info_get() function:

000000000011325c <lgr_info_get>:
  11325c:       eb 9f f0 60 00 24       stmg    %r9,%r15,96(%r15)
  113262:       c0 d0 00 29 0e 47       larl    %r13,634ef0 <servi..>
  113268:       a7 f1 3f c0             tml     %r15,16320
  11326c:       b9 04 00 ef             lgr     %r14,%r15
  113270:       a7 84 00 01             je      113272 <lgr_info_g..>
  113274:       a7 fb ff c0             aghi    %r15,-64
  113278:       b9 04 00 c2             lgr     %r12,%r2
  11327c:       a7 29 00 01             lghi    %r2,1
  113280:       e3 e0 f0 98 00 24       stg     %r14,152(%r15)
  113286:       d7 97 c0 00 c0 00       xc      0(152,%r12),0(%r12)
  11328c:       c0 e5 00 28 db 4c       brasl   %r14,62e924 <add_e..>
  113292:       b2 b1 00 00             stfl    0

To fix the problem we now clear the S390_lowcore.stfl_fac_list at
startup in "head.S" for all machine types before lowcore protection
is enabled.

In addition to that the "=m" constraint is replaced by "+m".
Signed-off-by: default avatarMichael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent af0ee94e
...@@ -38,12 +38,11 @@ static inline void stfle(u64 *stfle_fac_list, int size) ...@@ -38,12 +38,11 @@ static inline void stfle(u64 *stfle_fac_list, int size)
unsigned long nr; unsigned long nr;
preempt_disable(); preempt_disable();
S390_lowcore.stfl_fac_list = 0;
asm volatile( asm volatile(
" .insn s,0xb2b10000,0(0)\n" /* stfl */ " .insn s,0xb2b10000,0(0)\n" /* stfl */
"0:\n" "0:\n"
EX_TABLE(0b, 0b) EX_TABLE(0b, 0b)
: "=m" (S390_lowcore.stfl_fac_list)); : "+m" (S390_lowcore.stfl_fac_list));
nr = 4; /* bytes stored by stfl */ nr = 4; /* bytes stored by stfl */
memcpy(stfle_fac_list, &S390_lowcore.stfl_fac_list, 4); memcpy(stfle_fac_list, &S390_lowcore.stfl_fac_list, 4);
if (S390_lowcore.stfl_fac_list & 0x01000000) { if (S390_lowcore.stfl_fac_list & 0x01000000) {
......
...@@ -474,9 +474,9 @@ ENTRY(startup_kdump) ...@@ -474,9 +474,9 @@ ENTRY(startup_kdump)
stck __LC_LAST_UPDATE_CLOCK stck __LC_LAST_UPDATE_CLOCK
spt 5f-.LPG0(%r13) spt 5f-.LPG0(%r13)
mvc __LC_LAST_UPDATE_TIMER(8),5f-.LPG0(%r13) mvc __LC_LAST_UPDATE_TIMER(8),5f-.LPG0(%r13)
xc __LC_STFL_FAC_LIST(8),__LC_STFL_FAC_LIST
#ifndef CONFIG_MARCH_G5 #ifndef CONFIG_MARCH_G5
# check capabilities against MARCH_{G5,Z900,Z990,Z9_109,Z10} # check capabilities against MARCH_{G5,Z900,Z990,Z9_109,Z10}
xc __LC_STFL_FAC_LIST(8),__LC_STFL_FAC_LIST
.insn s,0xb2b10000,__LC_STFL_FAC_LIST # store facility list .insn s,0xb2b10000,__LC_STFL_FAC_LIST # store facility list
tm __LC_STFL_FAC_LIST,0x01 # stfle available ? tm __LC_STFL_FAC_LIST,0x01 # stfle available ?
jz 0f jz 0f
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment