diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2018-01-16 01:36:46 -0500 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2018-02-05 08:48:50 -0500 |
commit | 6b73044b2b0081ee3dd1cd6eaab7dee552601efb (patch) | |
tree | 25a142770f34cb0b7ba27e691d02509902a1974d | |
parent | d768bd892fc8f066cd3aa000eb1867bcf32db0ee (diff) |
s390: run user space and KVM guests with modified branch prediction
Define TIF_ISOLATE_BP and TIF_ISOLATE_BP_GUEST and add the necessary
plumbing in entry.S to be able to run user space and KVM guests with
limited branch prediction.
To switch a user space process to limited branch prediction the
s390_isolate_bp() function has to be call, and to run a vCPU of a KVM
guest associated with the current task with limited branch prediction
call s390_isolate_bp_guest().
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r-- | arch/s390/include/asm/processor.h | 3 | ||||
-rw-r--r-- | arch/s390/include/asm/thread_info.h | 4 | ||||
-rw-r--r-- | arch/s390/kernel/entry.S | 51 | ||||
-rw-r--r-- | arch/s390/kernel/processor.c | 18 |
4 files changed, 71 insertions, 5 deletions
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h index 5f37f9ceef5e..7f2953c15c37 100644 --- a/arch/s390/include/asm/processor.h +++ b/arch/s390/include/asm/processor.h | |||
@@ -378,6 +378,9 @@ extern void memcpy_absolute(void *, void *, size_t); | |||
378 | memcpy_absolute(&(dest), &__tmp, sizeof(__tmp)); \ | 378 | memcpy_absolute(&(dest), &__tmp, sizeof(__tmp)); \ |
379 | } while (0) | 379 | } while (0) |
380 | 380 | ||
381 | extern int s390_isolate_bp(void); | ||
382 | extern int s390_isolate_bp_guest(void); | ||
383 | |||
381 | #endif /* __ASSEMBLY__ */ | 384 | #endif /* __ASSEMBLY__ */ |
382 | 385 | ||
383 | #endif /* __ASM_S390_PROCESSOR_H */ | 386 | #endif /* __ASM_S390_PROCESSOR_H */ |
diff --git a/arch/s390/include/asm/thread_info.h b/arch/s390/include/asm/thread_info.h index 25d6ec3aaddd..83ba57533ce6 100644 --- a/arch/s390/include/asm/thread_info.h +++ b/arch/s390/include/asm/thread_info.h | |||
@@ -58,6 +58,8 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src); | |||
58 | #define TIF_GUARDED_STORAGE 4 /* load guarded storage control block */ | 58 | #define TIF_GUARDED_STORAGE 4 /* load guarded storage control block */ |
59 | #define TIF_PATCH_PENDING 5 /* pending live patching update */ | 59 | #define TIF_PATCH_PENDING 5 /* pending live patching update */ |
60 | #define TIF_PGSTE 6 /* New mm's will use 4K page tables */ | 60 | #define TIF_PGSTE 6 /* New mm's will use 4K page tables */ |
61 | #define TIF_ISOLATE_BP 8 /* Run process with isolated BP */ | ||
62 | #define TIF_ISOLATE_BP_GUEST 9 /* Run KVM guests with isolated BP */ | ||
61 | 63 | ||
62 | #define TIF_31BIT 16 /* 32bit process */ | 64 | #define TIF_31BIT 16 /* 32bit process */ |
63 | #define TIF_MEMDIE 17 /* is terminating due to OOM killer */ | 65 | #define TIF_MEMDIE 17 /* is terminating due to OOM killer */ |
@@ -78,6 +80,8 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src); | |||
78 | #define _TIF_UPROBE _BITUL(TIF_UPROBE) | 80 | #define _TIF_UPROBE _BITUL(TIF_UPROBE) |
79 | #define _TIF_GUARDED_STORAGE _BITUL(TIF_GUARDED_STORAGE) | 81 | #define _TIF_GUARDED_STORAGE _BITUL(TIF_GUARDED_STORAGE) |
80 | #define _TIF_PATCH_PENDING _BITUL(TIF_PATCH_PENDING) | 82 | #define _TIF_PATCH_PENDING _BITUL(TIF_PATCH_PENDING) |
83 | #define _TIF_ISOLATE_BP _BITUL(TIF_ISOLATE_BP) | ||
84 | #define _TIF_ISOLATE_BP_GUEST _BITUL(TIF_ISOLATE_BP_GUEST) | ||
81 | 85 | ||
82 | #define _TIF_31BIT _BITUL(TIF_31BIT) | 86 | #define _TIF_31BIT _BITUL(TIF_31BIT) |
83 | #define _TIF_SINGLE_STEP _BITUL(TIF_SINGLE_STEP) | 87 | #define _TIF_SINGLE_STEP _BITUL(TIF_SINGLE_STEP) |
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index e6d7550a3af8..53145b5d987d 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S | |||
@@ -107,6 +107,7 @@ _PIF_WORK = (_PIF_PER_TRAP | _PIF_SYSCALL_RESTART) | |||
107 | aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) | 107 | aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) |
108 | j 3f | 108 | j 3f |
109 | 1: UPDATE_VTIME %r14,%r15,\timer | 109 | 1: UPDATE_VTIME %r14,%r15,\timer |
110 | BPENTER __TI_flags(%r12),_TIF_ISOLATE_BP | ||
110 | 2: lg %r15,__LC_ASYNC_STACK # load async stack | 111 | 2: lg %r15,__LC_ASYNC_STACK # load async stack |
111 | 3: la %r11,STACK_FRAME_OVERHEAD(%r15) | 112 | 3: la %r11,STACK_FRAME_OVERHEAD(%r15) |
112 | .endm | 113 | .endm |
@@ -187,6 +188,40 @@ _PIF_WORK = (_PIF_PER_TRAP | _PIF_SYSCALL_RESTART) | |||
187 | .popsection | 188 | .popsection |
188 | .endm | 189 | .endm |
189 | 190 | ||
191 | .macro BPENTER tif_ptr,tif_mask | ||
192 | .pushsection .altinstr_replacement, "ax" | ||
193 | 662: .word 0xc004, 0x0000, 0x0000 # 6 byte nop | ||
194 | .word 0xc004, 0x0000, 0x0000 # 6 byte nop | ||
195 | .popsection | ||
196 | 664: TSTMSK \tif_ptr,\tif_mask | ||
197 | jz . + 8 | ||
198 | .long 0xb2e8d000 | ||
199 | .pushsection .altinstructions, "a" | ||
200 | .long 664b - . | ||
201 | .long 662b - . | ||
202 | .word 82 | ||
203 | .byte 12 | ||
204 | .byte 12 | ||
205 | .popsection | ||
206 | .endm | ||
207 | |||
208 | .macro BPEXIT tif_ptr,tif_mask | ||
209 | TSTMSK \tif_ptr,\tif_mask | ||
210 | .pushsection .altinstr_replacement, "ax" | ||
211 | 662: jnz . + 8 | ||
212 | .long 0xb2e8d000 | ||
213 | .popsection | ||
214 | 664: jz . + 8 | ||
215 | .long 0xb2e8c000 | ||
216 | .pushsection .altinstructions, "a" | ||
217 | .long 664b - . | ||
218 | .long 662b - . | ||
219 | .word 82 | ||
220 | .byte 8 | ||
221 | .byte 8 | ||
222 | .popsection | ||
223 | .endm | ||
224 | |||
190 | .section .kprobes.text, "ax" | 225 | .section .kprobes.text, "ax" |
191 | .Ldummy: | 226 | .Ldummy: |
192 | /* | 227 | /* |
@@ -240,9 +275,11 @@ ENTRY(__switch_to) | |||
240 | */ | 275 | */ |
241 | ENTRY(sie64a) | 276 | ENTRY(sie64a) |
242 | stmg %r6,%r14,__SF_GPRS(%r15) # save kernel registers | 277 | stmg %r6,%r14,__SF_GPRS(%r15) # save kernel registers |
278 | lg %r12,__LC_CURRENT | ||
243 | stg %r2,__SF_EMPTY(%r15) # save control block pointer | 279 | stg %r2,__SF_EMPTY(%r15) # save control block pointer |
244 | stg %r3,__SF_EMPTY+8(%r15) # save guest register save area | 280 | stg %r3,__SF_EMPTY+8(%r15) # save guest register save area |
245 | xc __SF_EMPTY+16(8,%r15),__SF_EMPTY+16(%r15) # reason code = 0 | 281 | xc __SF_EMPTY+16(8,%r15),__SF_EMPTY+16(%r15) # reason code = 0 |
282 | mvc __SF_EMPTY+24(8,%r15),__TI_flags(%r12) # copy thread flags | ||
246 | TSTMSK __LC_CPU_FLAGS,_CIF_FPU # load guest fp/vx registers ? | 283 | TSTMSK __LC_CPU_FLAGS,_CIF_FPU # load guest fp/vx registers ? |
247 | jno .Lsie_load_guest_gprs | 284 | jno .Lsie_load_guest_gprs |
248 | brasl %r14,load_fpu_regs # load guest fp/vx regs | 285 | brasl %r14,load_fpu_regs # load guest fp/vx regs |
@@ -259,11 +296,12 @@ ENTRY(sie64a) | |||
259 | jnz .Lsie_skip | 296 | jnz .Lsie_skip |
260 | TSTMSK __LC_CPU_FLAGS,_CIF_FPU | 297 | TSTMSK __LC_CPU_FLAGS,_CIF_FPU |
261 | jo .Lsie_skip # exit if fp/vx regs changed | 298 | jo .Lsie_skip # exit if fp/vx regs changed |
262 | BPON | 299 | BPEXIT __SF_EMPTY+24(%r15),(_TIF_ISOLATE_BP|_TIF_ISOLATE_BP_GUEST) |
263 | .Lsie_entry: | 300 | .Lsie_entry: |
264 | sie 0(%r14) | 301 | sie 0(%r14) |
265 | .Lsie_exit: | 302 | .Lsie_exit: |
266 | BPOFF | 303 | BPOFF |
304 | BPENTER __SF_EMPTY+24(%r15),(_TIF_ISOLATE_BP|_TIF_ISOLATE_BP_GUEST) | ||
267 | .Lsie_skip: | 305 | .Lsie_skip: |
268 | ni __SIE_PROG0C+3(%r14),0xfe # no longer in SIE | 306 | ni __SIE_PROG0C+3(%r14),0xfe # no longer in SIE |
269 | lctlg %c1,%c1,__LC_USER_ASCE # load primary asce | 307 | lctlg %c1,%c1,__LC_USER_ASCE # load primary asce |
@@ -324,6 +362,7 @@ ENTRY(system_call) | |||
324 | la %r11,STACK_FRAME_OVERHEAD(%r15) # pointer to pt_regs | 362 | la %r11,STACK_FRAME_OVERHEAD(%r15) # pointer to pt_regs |
325 | .Lsysc_vtime: | 363 | .Lsysc_vtime: |
326 | UPDATE_VTIME %r8,%r9,__LC_SYNC_ENTER_TIMER | 364 | UPDATE_VTIME %r8,%r9,__LC_SYNC_ENTER_TIMER |
365 | BPENTER __TI_flags(%r12),_TIF_ISOLATE_BP | ||
327 | stmg %r0,%r7,__PT_R0(%r11) | 366 | stmg %r0,%r7,__PT_R0(%r11) |
328 | # clear user controlled register to prevent speculative use | 367 | # clear user controlled register to prevent speculative use |
329 | xgr %r0,%r0 | 368 | xgr %r0,%r0 |
@@ -362,7 +401,7 @@ ENTRY(system_call) | |||
362 | jnz .Lsysc_work # check for work | 401 | jnz .Lsysc_work # check for work |
363 | TSTMSK __LC_CPU_FLAGS,_CIF_WORK | 402 | TSTMSK __LC_CPU_FLAGS,_CIF_WORK |
364 | jnz .Lsysc_work | 403 | jnz .Lsysc_work |
365 | BPON | 404 | BPEXIT __TI_flags(%r12),_TIF_ISOLATE_BP |
366 | .Lsysc_restore: | 405 | .Lsysc_restore: |
367 | lg %r14,__LC_VDSO_PER_CPU | 406 | lg %r14,__LC_VDSO_PER_CPU |
368 | lmg %r0,%r10,__PT_R0(%r11) | 407 | lmg %r0,%r10,__PT_R0(%r11) |
@@ -597,6 +636,7 @@ ENTRY(pgm_check_handler) | |||
597 | aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) | 636 | aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) |
598 | j 4f | 637 | j 4f |
599 | 2: UPDATE_VTIME %r14,%r15,__LC_SYNC_ENTER_TIMER | 638 | 2: UPDATE_VTIME %r14,%r15,__LC_SYNC_ENTER_TIMER |
639 | BPENTER __TI_flags(%r12),_TIF_ISOLATE_BP | ||
600 | lg %r15,__LC_KERNEL_STACK | 640 | lg %r15,__LC_KERNEL_STACK |
601 | lgr %r14,%r12 | 641 | lgr %r14,%r12 |
602 | aghi %r14,__TASK_thread # pointer to thread_struct | 642 | aghi %r14,__TASK_thread # pointer to thread_struct |
@@ -729,7 +769,7 @@ ENTRY(io_int_handler) | |||
729 | mvc __LC_RETURN_PSW(16),__PT_PSW(%r11) | 769 | mvc __LC_RETURN_PSW(16),__PT_PSW(%r11) |
730 | tm __PT_PSW+1(%r11),0x01 # returning to user ? | 770 | tm __PT_PSW+1(%r11),0x01 # returning to user ? |
731 | jno .Lio_exit_kernel | 771 | jno .Lio_exit_kernel |
732 | BPON | 772 | BPEXIT __TI_flags(%r12),_TIF_ISOLATE_BP |
733 | .Lio_exit_timer: | 773 | .Lio_exit_timer: |
734 | stpt __LC_EXIT_TIMER | 774 | stpt __LC_EXIT_TIMER |
735 | mvc __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER | 775 | mvc __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER |
@@ -1165,7 +1205,7 @@ ENTRY(mcck_int_handler) | |||
1165 | mvc __LC_RETURN_MCCK_PSW(16),__PT_PSW(%r11) # move return PSW | 1205 | mvc __LC_RETURN_MCCK_PSW(16),__PT_PSW(%r11) # move return PSW |
1166 | tm __LC_RETURN_MCCK_PSW+1,0x01 # returning to user ? | 1206 | tm __LC_RETURN_MCCK_PSW+1,0x01 # returning to user ? |
1167 | jno 0f | 1207 | jno 0f |
1168 | BPON | 1208 | BPEXIT __TI_flags(%r12),_TIF_ISOLATE_BP |
1169 | stpt __LC_EXIT_TIMER | 1209 | stpt __LC_EXIT_TIMER |
1170 | mvc __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER | 1210 | mvc __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER |
1171 | 0: lmg %r11,%r15,__PT_R11(%r11) | 1211 | 0: lmg %r11,%r15,__PT_R11(%r11) |
@@ -1292,7 +1332,8 @@ cleanup_critical: | |||
1292 | clg %r9,BASED(.Lsie_crit_mcck_length) | 1332 | clg %r9,BASED(.Lsie_crit_mcck_length) |
1293 | jh 1f | 1333 | jh 1f |
1294 | oi __LC_CPU_FLAGS+7, _CIF_MCCK_GUEST | 1334 | oi __LC_CPU_FLAGS+7, _CIF_MCCK_GUEST |
1295 | 1: lg %r9,__SF_EMPTY(%r15) # get control block pointer | 1335 | 1: BPENTER __SF_EMPTY+24(%r15),(_TIF_ISOLATE_BP|_TIF_ISOLATE_BP_GUEST) |
1336 | lg %r9,__SF_EMPTY(%r15) # get control block pointer | ||
1296 | ni __SIE_PROG0C+3(%r9),0xfe # no longer in SIE | 1337 | ni __SIE_PROG0C+3(%r9),0xfe # no longer in SIE |
1297 | lctlg %c1,%c1,__LC_USER_ASCE # load primary asce | 1338 | lctlg %c1,%c1,__LC_USER_ASCE # load primary asce |
1298 | larl %r9,sie_exit # skip forward to sie_exit | 1339 | larl %r9,sie_exit # skip forward to sie_exit |
diff --git a/arch/s390/kernel/processor.c b/arch/s390/kernel/processor.c index 5362fd868d0d..6fe2e1875058 100644 --- a/arch/s390/kernel/processor.c +++ b/arch/s390/kernel/processor.c | |||
@@ -197,3 +197,21 @@ const struct seq_operations cpuinfo_op = { | |||
197 | .stop = c_stop, | 197 | .stop = c_stop, |
198 | .show = show_cpuinfo, | 198 | .show = show_cpuinfo, |
199 | }; | 199 | }; |
200 | |||
201 | int s390_isolate_bp(void) | ||
202 | { | ||
203 | if (!test_facility(82)) | ||
204 | return -EOPNOTSUPP; | ||
205 | set_thread_flag(TIF_ISOLATE_BP); | ||
206 | return 0; | ||
207 | } | ||
208 | EXPORT_SYMBOL(s390_isolate_bp); | ||
209 | |||
210 | int s390_isolate_bp_guest(void) | ||
211 | { | ||
212 | if (!test_facility(82)) | ||
213 | return -EOPNOTSUPP; | ||
214 | set_thread_flag(TIF_ISOLATE_BP_GUEST); | ||
215 | return 0; | ||
216 | } | ||
217 | EXPORT_SYMBOL(s390_isolate_bp_guest); | ||