Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>

authored by

Michael Holzheu and committed by
Martin Schwidefsky
37e37c20 af0ee94e

+2 -3
+1 -2
arch/s390/include/asm/facility.h
··· 38 38 unsigned long nr; 39 39 40 40 preempt_disable(); 41 - S390_lowcore.stfl_fac_list = 0; 42 41 asm volatile( 43 42 " .insn s,0xb2b10000,0(0)\n" /* stfl */ 44 43 "0:\n" 45 44 EX_TABLE(0b, 0b) 46 - : "=m" (S390_lowcore.stfl_fac_list)); 45 + : "+m" (S390_lowcore.stfl_fac_list)); 47 46 nr = 4; /* bytes stored by stfl */ 48 47 memcpy(stfle_fac_list, &S390_lowcore.stfl_fac_list, 4); 49 48 if (S390_lowcore.stfl_fac_list & 0x01000000) {
+1 -1
arch/s390/kernel/head.S
··· 474 474 stck __LC_LAST_UPDATE_CLOCK 475 475 spt 5f-.LPG0(%r13) 476 476 mvc __LC_LAST_UPDATE_TIMER(8),5f-.LPG0(%r13) 477 + xc __LC_STFL_FAC_LIST(8),__LC_STFL_FAC_LIST 477 478 #ifndef CONFIG_MARCH_G5 478 479 # check capabilities against MARCH_{G5,Z900,Z990,Z9_109,Z10} 479 - xc __LC_STFL_FAC_LIST(8),__LC_STFL_FAC_LIST 480 480 .insn s,0xb2b10000,__LC_STFL_FAC_LIST # store facility list 481 481 tm __LC_STFL_FAC_LIST,0x01 # stfle available ? 482 482 jz 0f