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

s390/entry: add assembler macro to conveniently tests under mask

Various functions in entry.S perform test-under-mask instructions
to test for particular bits in memory. Because test-under-mask uses
a mask value of one byte, the mask value and the offset into the
memory must be calculated manually. This easily introduces errors
and is hard to review and read.

Introduce the TSTMSK assembler macro to specify a mask constant and
let the macro calculate the offset and the byte mask to generate a
test-under-mask instruction. The benefit is that existing symbolic
constants can now be used for tests. Also the macro checks for
zero mask values and mask values that consist of multiple bytes.

Signed-off-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
Reviewed-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>

authored by

Hendrik Brueckner and committed by
Martin Schwidefsky
83abeffb 0ac27779

+98 -64
+9
arch/s390/include/asm/nmi.h
··· 11 11 #ifndef _ASM_S390_NMI_H 12 12 #define _ASM_S390_NMI_H 13 13 14 + #include <linux/const.h> 14 15 #include <linux/types.h> 16 + 17 + #define MCCK_CODE_SYSTEM_DAMAGE _BITUL(63) 18 + #define MCCK_CODE_CPU_TIMER_VALID _BITUL(63 - 46) 19 + #define MCCK_CODE_PSW_MWP_VALID _BITUL(63 - 20) 20 + #define MCCK_CODE_PSW_IA_VALID _BITUL(63 - 23) 21 + 22 + #ifndef __ASSEMBLY__ 15 23 16 24 struct mci { 17 25 __u32 sd : 1; /* 00 system damage */ ··· 71 63 extern void s390_handle_mcck(void); 72 64 extern void s390_do_machine_check(struct pt_regs *regs); 73 65 66 + #endif /* __ASSEMBLY__ */ 74 67 #endif /* _ASM_S390_NMI_H */
+24 -23
arch/s390/include/asm/setup.h
··· 5 5 #ifndef _ASM_S390_SETUP_H 6 6 #define _ASM_S390_SETUP_H 7 7 8 + #include <linux/const.h> 8 9 #include <uapi/asm/setup.h> 9 10 10 11 11 12 #define PARMAREA 0x10400 13 + 14 + /* 15 + * Machine features detected in head.S 16 + */ 17 + 18 + #define MACHINE_FLAG_VM _BITUL(0) 19 + #define MACHINE_FLAG_IEEE _BITUL(1) 20 + #define MACHINE_FLAG_CSP _BITUL(2) 21 + #define MACHINE_FLAG_MVPG _BITUL(3) 22 + #define MACHINE_FLAG_DIAG44 _BITUL(4) 23 + #define MACHINE_FLAG_IDTE _BITUL(5) 24 + #define MACHINE_FLAG_DIAG9C _BITUL(6) 25 + #define MACHINE_FLAG_KVM _BITUL(8) 26 + #define MACHINE_FLAG_ESOP _BITUL(9) 27 + #define MACHINE_FLAG_EDAT1 _BITUL(10) 28 + #define MACHINE_FLAG_EDAT2 _BITUL(11) 29 + #define MACHINE_FLAG_LPAR _BITUL(12) 30 + #define MACHINE_FLAG_LPP _BITUL(13) 31 + #define MACHINE_FLAG_TOPOLOGY _BITUL(14) 32 + #define MACHINE_FLAG_TE _BITUL(15) 33 + #define MACHINE_FLAG_TLB_LC _BITUL(17) 34 + #define MACHINE_FLAG_VX _BITUL(18) 35 + #define MACHINE_FLAG_CAD _BITUL(19) 12 36 13 37 #ifndef __ASSEMBLY__ 14 38 ··· 51 27 extern unsigned long max_physmem_end; 52 28 53 29 extern void detect_memory_memblock(void); 54 - 55 - /* 56 - * Machine features detected in head.S 57 - */ 58 - 59 - #define MACHINE_FLAG_VM (1UL << 0) 60 - #define MACHINE_FLAG_IEEE (1UL << 1) 61 - #define MACHINE_FLAG_CSP (1UL << 2) 62 - #define MACHINE_FLAG_MVPG (1UL << 3) 63 - #define MACHINE_FLAG_DIAG44 (1UL << 4) 64 - #define MACHINE_FLAG_IDTE (1UL << 5) 65 - #define MACHINE_FLAG_DIAG9C (1UL << 6) 66 - #define MACHINE_FLAG_KVM (1UL << 8) 67 - #define MACHINE_FLAG_ESOP (1UL << 9) 68 - #define MACHINE_FLAG_EDAT1 (1UL << 10) 69 - #define MACHINE_FLAG_EDAT2 (1UL << 11) 70 - #define MACHINE_FLAG_LPAR (1UL << 12) 71 - #define MACHINE_FLAG_LPP (1UL << 13) 72 - #define MACHINE_FLAG_TOPOLOGY (1UL << 14) 73 - #define MACHINE_FLAG_TE (1UL << 15) 74 - #define MACHINE_FLAG_TLB_LC (1UL << 17) 75 - #define MACHINE_FLAG_VX (1UL << 18) 76 - #define MACHINE_FLAG_CAD (1UL << 19) 77 30 78 31 #define MACHINE_IS_VM (S390_lowcore.machine_flags & MACHINE_FLAG_VM) 79 32 #define MACHINE_IS_KVM (S390_lowcore.machine_flags & MACHINE_FLAG_KVM)
+65 -41
arch/s390/kernel/entry.S
··· 21 21 #include <asm/sigp.h> 22 22 #include <asm/irq.h> 23 23 #include <asm/vx-insn.h> 24 + #include <asm/setup.h> 25 + #include <asm/nmi.h> 24 26 25 27 __PT_R0 = __PT_GPRS 26 28 __PT_R1 = __PT_GPRS + 8 ··· 140 138 #endif 141 139 .endm 142 140 141 + /* 142 + * The TSTMSK macro generates a test-under-mask instruction by 143 + * calculating the memory offset for the specified mask value. 144 + * Mask value can be any constant. The macro shifts the mask 145 + * value to calculate the memory offset for the test-under-mask 146 + * instruction. 147 + */ 148 + .macro TSTMSK addr, mask, size=8, bytepos=0 149 + .if (\bytepos < \size) && (\mask >> 8) 150 + .if (\mask & 0xff) 151 + .error "Mask exceeds byte boundary" 152 + .endif 153 + TSTMSK \addr, "(\mask >> 8)", \size, "(\bytepos + 1)" 154 + .exitm 155 + .endif 156 + .ifeq \mask 157 + .error "Mask must not be zero" 158 + .endif 159 + off = \size - \bytepos - 1 160 + tm off+\addr, \mask 161 + .endm 162 + 143 163 .section .kprobes.text, "ax" 144 164 145 165 /* ··· 204 180 stg %r2,__SF_EMPTY(%r15) # save control block pointer 205 181 stg %r3,__SF_EMPTY+8(%r15) # save guest register save area 206 182 xc __SF_EMPTY+16(16,%r15),__SF_EMPTY+16(%r15) # host id & reason 207 - tm __LC_CPU_FLAGS+7,_CIF_FPU # load guest fp/vx registers ? 183 + TSTMSK __LC_CPU_FLAGS,_CIF_FPU # load guest fp/vx registers ? 208 184 jno .Lsie_load_guest_gprs 209 185 brasl %r14,load_fpu_regs # load guest fp/vx regs 210 186 .Lsie_load_guest_gprs: ··· 218 194 oi __SIE_PROG0C+3(%r14),1 # we are going into SIE now 219 195 tm __SIE_PROG20+3(%r14),3 # last exit... 220 196 jnz .Lsie_skip 221 - tm __LC_CPU_FLAGS+7,_CIF_FPU 197 + TSTMSK __LC_CPU_FLAGS,_CIF_FPU 222 198 jo .Lsie_skip # exit if fp/vx regs changed 223 - tm __LC_MACHINE_FLAGS+6,0x20 # MACHINE_FLAG_LPP 199 + TSTMSK __LC_MACHINE_FLAGS,MACHINE_FLAG_LPP 224 200 jz .Lsie_enter 225 201 .insn s,0xb2800000,__LC_CURRENT_PID # set guest id to pid 226 202 .Lsie_enter: 227 203 sie 0(%r14) 228 - tm __LC_MACHINE_FLAGS+6,0x20 # MACHINE_FLAG_LPP 204 + TSTMSK __LC_MACHINE_FLAGS,MACHINE_FLAG_LPP 229 205 jz .Lsie_skip 230 206 .insn s,0xb2800000,__SF_EMPTY+16(%r15)# set host id 231 207 .Lsie_skip: ··· 294 270 stg %r2,__PT_ORIG_GPR2(%r11) 295 271 stg %r7,STACK_FRAME_OVERHEAD(%r15) 296 272 lgf %r9,0(%r8,%r10) # get system call add. 297 - tm __TI_flags+7(%r12),_TIF_TRACE 273 + TSTMSK __TI_flags(%r12),_TIF_TRACE 298 274 jnz .Lsysc_tracesys 299 275 basr %r14,%r9 # call sys_xxxx 300 276 stg %r2,__PT_R2(%r11) # store return value ··· 302 278 .Lsysc_return: 303 279 LOCKDEP_SYS_EXIT 304 280 .Lsysc_tif: 305 - tm __PT_FLAGS+7(%r11),_PIF_WORK 281 + TSTMSK __PT_FLAGS(%r11),_PIF_WORK 306 282 jnz .Lsysc_work 307 - tm __TI_flags+7(%r12),_TIF_WORK 283 + TSTMSK __TI_flags(%r12),_TIF_WORK 308 284 jnz .Lsysc_work # check for work 309 - tm __LC_CPU_FLAGS+7,_CIF_WORK 285 + TSTMSK __LC_CPU_FLAGS,_CIF_WORK 310 286 jnz .Lsysc_work 311 287 .Lsysc_restore: 312 288 lg %r14,__LC_VDSO_PER_CPU ··· 322 298 # One of the work bits is on. Find out which one. 323 299 # 324 300 .Lsysc_work: 325 - tm __LC_CPU_FLAGS+7,_CIF_MCCK_PENDING 301 + TSTMSK __LC_CPU_FLAGS,_CIF_MCCK_PENDING 326 302 jo .Lsysc_mcck_pending 327 - tm __TI_flags+7(%r12),_TIF_NEED_RESCHED 303 + TSTMSK __TI_flags(%r12),_TIF_NEED_RESCHED 328 304 jo .Lsysc_reschedule 329 305 #ifdef CONFIG_UPROBES 330 - tm __TI_flags+7(%r12),_TIF_UPROBE 306 + TSTMSK __TI_flags(%r12),_TIF_UPROBE 331 307 jo .Lsysc_uprobe_notify 332 308 #endif 333 - tm __PT_FLAGS+7(%r11),_PIF_PER_TRAP 309 + TSTMSK __PT_FLAGS(%r11),_PIF_PER_TRAP 334 310 jo .Lsysc_singlestep 335 - tm __TI_flags+7(%r12),_TIF_SIGPENDING 311 + TSTMSK __TI_flags(%r12),_TIF_SIGPENDING 336 312 jo .Lsysc_sigpending 337 - tm __TI_flags+7(%r12),_TIF_NOTIFY_RESUME 313 + TSTMSK __TI_flags(%r12),_TIF_NOTIFY_RESUME 338 314 jo .Lsysc_notify_resume 339 - tm __LC_CPU_FLAGS+7,_CIF_FPU 315 + TSTMSK __LC_CPU_FLAGS,_CIF_FPU 340 316 jo .Lsysc_vxrs 341 - tm __LC_CPU_FLAGS+7,_CIF_ASCE 317 + TSTMSK __LC_CPU_FLAGS,_CIF_ASCE 342 318 jo .Lsysc_uaccess 343 319 j .Lsysc_return # beware of critical section cleanup 344 320 ··· 377 353 .Lsysc_sigpending: 378 354 lgr %r2,%r11 # pass pointer to pt_regs 379 355 brasl %r14,do_signal 380 - tm __PT_FLAGS+7(%r11),_PIF_SYSCALL 356 + TSTMSK __PT_FLAGS(%r11),_PIF_SYSCALL 381 357 jno .Lsysc_return 382 358 lmg %r2,%r7,__PT_R2(%r11) # load svc arguments 383 359 lg %r10,__TI_sysc_table(%r12) # address of system call table ··· 437 413 basr %r14,%r9 # call sys_xxx 438 414 stg %r2,__PT_R2(%r11) # store return value 439 415 .Lsysc_tracenogo: 440 - tm __TI_flags+7(%r12),_TIF_TRACE 416 + TSTMSK __TI_flags(%r12),_TIF_TRACE 441 417 jz .Lsysc_return 442 418 lgr %r2,%r11 # pass pointer to pt_regs 443 419 larl %r14,.Lsysc_return ··· 577 553 lghi %r3,THIN_INTERRUPT 578 554 .Lio_call: 579 555 brasl %r14,do_IRQ 580 - tm __LC_MACHINE_FLAGS+6,0x10 # MACHINE_FLAG_LPAR 556 + TSTMSK __LC_MACHINE_FLAGS,MACHINE_FLAG_LPAR 581 557 jz .Lio_return 582 558 tpi 0 583 559 jz .Lio_return ··· 587 563 LOCKDEP_SYS_EXIT 588 564 TRACE_IRQS_ON 589 565 .Lio_tif: 590 - tm __TI_flags+7(%r12),_TIF_WORK 566 + TSTMSK __TI_flags(%r12),_TIF_WORK 591 567 jnz .Lio_work # there is work to do (signals etc.) 592 - tm __LC_CPU_FLAGS+7,_CIF_WORK 568 + TSTMSK __LC_CPU_FLAGS,_CIF_WORK 593 569 jnz .Lio_work 594 570 .Lio_restore: 595 571 lg %r14,__LC_VDSO_PER_CPU ··· 617 593 # check for preemptive scheduling 618 594 icm %r0,15,__TI_precount(%r12) 619 595 jnz .Lio_restore # preemption is disabled 620 - tm __TI_flags+7(%r12),_TIF_NEED_RESCHED 596 + TSTMSK __TI_flags(%r12),_TIF_NEED_RESCHED 621 597 jno .Lio_restore 622 598 # switch to kernel stack 623 599 lg %r1,__PT_R15(%r11) ··· 649 625 # One of the work bits is on. Find out which one. 650 626 # 651 627 .Lio_work_tif: 652 - tm __LC_CPU_FLAGS+7,_CIF_MCCK_PENDING 628 + TSTMSK __LC_CPU_FLAGS,_CIF_MCCK_PENDING 653 629 jo .Lio_mcck_pending 654 - tm __TI_flags+7(%r12),_TIF_NEED_RESCHED 630 + TSTMSK __TI_flags(%r12),_TIF_NEED_RESCHED 655 631 jo .Lio_reschedule 656 - tm __TI_flags+7(%r12),_TIF_SIGPENDING 632 + TSTMSK __TI_flags(%r12),_TIF_SIGPENDING 657 633 jo .Lio_sigpending 658 - tm __TI_flags+7(%r12),_TIF_NOTIFY_RESUME 634 + TSTMSK __TI_flags(%r12),_TIF_NOTIFY_RESUME 659 635 jo .Lio_notify_resume 660 - tm __LC_CPU_FLAGS+7,_CIF_FPU 636 + TSTMSK __LC_CPU_FLAGS,_CIF_FPU 661 637 jo .Lio_vxrs 662 - tm __LC_CPU_FLAGS+7,_CIF_ASCE 638 + TSTMSK __LC_CPU_FLAGS,_CIF_ASCE 663 639 jo .Lio_uaccess 664 640 j .Lio_return # beware of critical section cleanup 665 641 ··· 781 757 ENTRY(save_fpu_regs) 782 758 lg %r2,__LC_CURRENT 783 759 aghi %r2,__TASK_thread 784 - tm __LC_CPU_FLAGS+7,_CIF_FPU 760 + TSTMSK __LC_CPU_FLAGS,_CIF_FPU 785 761 bor %r14 786 762 stfpc __THREAD_FPU_fpc(%r2) 787 763 .Lsave_fpu_regs_fpc_end: 788 764 lg %r3,__THREAD_FPU_regs(%r2) 789 - tm __LC_MACHINE_FLAGS+5,4 # MACHINE_HAS_VX 765 + TSTMSK __LC_MACHINE_FLAGS,MACHINE_FLAG_VX 790 766 jz .Lsave_fpu_regs_fp # no -> store FP regs 791 767 .Lsave_fpu_regs_vx_low: 792 768 VSTM %v0,%v15,0,%r3 # vstm 0,15,0(3) ··· 828 804 load_fpu_regs: 829 805 lg %r4,__LC_CURRENT 830 806 aghi %r4,__TASK_thread 831 - tm __LC_CPU_FLAGS+7,_CIF_FPU 807 + TSTMSK __LC_CPU_FLAGS,_CIF_FPU 832 808 bnor %r14 833 809 lfpc __THREAD_FPU_fpc(%r4) 834 - tm __LC_MACHINE_FLAGS+5,4 # MACHINE_HAS_VX 810 + TSTMSK __LC_MACHINE_FLAGS,MACHINE_FLAG_VX 835 811 lg %r4,__THREAD_FPU_regs(%r4) # %r4 <- reg save area 836 812 jz .Lload_fpu_regs_fp # -> no VX, load FP regs 837 813 .Lload_fpu_regs_vx: ··· 875 851 lg %r12,__LC_THREAD_INFO 876 852 larl %r13,cleanup_critical 877 853 lmg %r8,%r9,__LC_MCK_OLD_PSW 878 - tm __LC_MCCK_CODE,0x80 # system damage? 854 + TSTMSK __LC_MCCK_CODE,MCCK_CODE_SYSTEM_DAMAGE 879 855 jo .Lmcck_panic # yes -> rest of mcck code invalid 880 856 lghi %r14,__LC_CPU_TIMER_SAVE_AREA 881 857 mvc __LC_MCCK_ENTER_TIMER(8),0(%r14) 882 - tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid? 858 + TSTMSK __LC_MCCK_CODE,MCCK_CODE_CPU_TIMER_VALID 883 859 jo 3f 884 860 la %r14,__LC_SYNC_ENTER_TIMER 885 861 clc 0(8,%r14),__LC_ASYNC_ENTER_TIMER ··· 893 869 la %r14,__LC_LAST_UPDATE_TIMER 894 870 2: spt 0(%r14) 895 871 mvc __LC_MCCK_ENTER_TIMER(8),0(%r14) 896 - 3: tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? 872 + 3: TSTMSK __LC_MCCK_CODE,(MCCK_CODE_PSW_MWP_VALID|MCCK_CODE_PSW_IA_VALID) 897 873 jno .Lmcck_panic # no -> skip cleanup critical 898 874 SWITCH_ASYNC __LC_GPREGS_SAVE_AREA+64,__LC_MCCK_ENTER_TIMER 899 875 .Lmcck_skip: ··· 913 889 la %r11,STACK_FRAME_OVERHEAD(%r1) 914 890 lgr %r15,%r1 915 891 ssm __LC_PGM_NEW_PSW # turn dat on, keep irqs off 916 - tm __LC_CPU_FLAGS+7,_CIF_MCCK_PENDING 892 + TSTMSK __LC_CPU_FLAGS,_CIF_MCCK_PENDING 917 893 jno .Lmcck_return 918 894 TRACE_IRQS_OFF 919 895 brasl %r14,s390_handle_mcck ··· 1042 1018 1043 1019 .Lcleanup_sie: 1044 1020 lg %r9,__SF_EMPTY(%r15) # get control block pointer 1045 - tm __LC_MACHINE_FLAGS+6,0x20 # MACHINE_FLAG_LPP 1021 + TSTMSK __LC_MACHINE_FLAGS,MACHINE_FLAG_LPP 1046 1022 jz 0f 1047 1023 .insn s,0xb2800000,__SF_EMPTY+16(%r15)# set host id 1048 1024 0: ni __SIE_PROG0C+3(%r9),0xfe # no longer in SIE ··· 1197 1173 .quad .Lpsw_idle_lpsw 1198 1174 1199 1175 .Lcleanup_save_fpu_regs: 1200 - tm __LC_CPU_FLAGS+7,_CIF_FPU 1176 + TSTMSK __LC_CPU_FLAGS,_CIF_FPU 1201 1177 bor %r14 1202 1178 clg %r9,BASED(.Lcleanup_save_fpu_regs_done) 1203 1179 jhe 5f ··· 1215 1191 stfpc __THREAD_FPU_fpc(%r2) 1216 1192 1: # Load register save area and check if VX is active 1217 1193 lg %r3,__THREAD_FPU_regs(%r2) 1218 - tm __LC_MACHINE_FLAGS+5,4 # MACHINE_HAS_VX 1194 + TSTMSK __LC_MACHINE_FLAGS,MACHINE_FLAG_VX 1219 1195 jz 4f # no VX -> store FP regs 1220 1196 2: # Store vector registers (V0-V15) 1221 1197 VSTM %v0,%v15,0,%r3 # vstm 0,15,0(3) ··· 1255 1231 .quad .Lsave_fpu_regs_done 1256 1232 1257 1233 .Lcleanup_load_fpu_regs: 1258 - tm __LC_CPU_FLAGS+7,_CIF_FPU 1234 + TSTMSK __LC_CPU_FLAGS,_CIF_FPU 1259 1235 bnor %r14 1260 1236 clg %r9,BASED(.Lcleanup_load_fpu_regs_done) 1261 1237 jhe 1f ··· 1268 1244 lg %r4,__LC_CURRENT 1269 1245 aghi %r4,__TASK_thread 1270 1246 lfpc __THREAD_FPU_fpc(%r4) 1271 - tm __LC_MACHINE_FLAGS+5,4 # MACHINE_HAS_VX 1247 + TSTMSK __LC_MACHINE_FLAGS,MACHINE_FLAG_VX 1272 1248 lg %r4,__THREAD_FPU_regs(%r4) # %r4 <- reg save area 1273 1249 jz 2f # -> no VX, load FP regs 1274 1250 4: # Load V0 ..V15 registers