Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c929500

Browse files
SeanHQFborntraeger
authored andcommitted
s390/nmi: s390: New low level handling for machine check happening in guest
Add the logic to check if the machine check happens when the guest is running. If yes, set the exit reason -EINTR in the machine check's interrupt handler. Refactor s390_do_machine_check to avoid panicing the host for some kinds of machine checks which happen when guest is running. Reinject the instruction processing damage's machine checks including Delayed Access Exception instead of damaging the host if it happens in the guest because it could be caused by improper update on TLB entry or other software case and impacts the guest only. Signed-off-by: QingFeng Hao <[email protected]> Acked-by: Martin Schwidefsky <[email protected]> Acked-by: Heiko Carstens <[email protected]> Acked-by: Christian Borntraeger <[email protected]> Signed-off-by: Christian Borntraeger <[email protected]>
1 parent 2ea659a commit c929500

File tree

5 files changed

+64
-11
lines changed

5 files changed

+64
-11
lines changed

arch/s390/include/asm/nmi.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,14 @@
1414
#include <linux/const.h>
1515
#include <linux/types.h>
1616

17+
#define MCIC_SUBCLASS_MASK (1ULL<<63 | 1ULL<<62 | 1ULL<<61 | \
18+
1ULL<<59 | 1ULL<<58 | 1ULL<<56 | \
19+
1ULL<<55 | 1ULL<<54 | 1ULL<<53 | \
20+
1ULL<<52 | 1ULL<<47 | 1ULL<<46 | \
21+
1ULL<<45 | 1ULL<<44)
1722
#define MCCK_CODE_SYSTEM_DAMAGE _BITUL(63)
23+
#define MCCK_CODE_EXT_DAMAGE _BITUL(63 - 5)
24+
#define MCCK_CODE_CP _BITUL(63 - 9)
1825
#define MCCK_CODE_CPU_TIMER_VALID _BITUL(63 - 46)
1926
#define MCCK_CODE_PSW_MWP_VALID _BITUL(63 - 20)
2027
#define MCCK_CODE_PSW_IA_VALID _BITUL(63 - 23)

arch/s390/include/asm/processor.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#define CIF_FPU 4 /* restore FPU registers */
2121
#define CIF_IGNORE_IRQ 5 /* ignore interrupt (for udelay) */
2222
#define CIF_ENABLED_WAIT 6 /* in enabled wait state */
23+
#define CIF_MCCK_GUEST 7 /* machine check happening in guest */
2324

2425
#define _CIF_MCCK_PENDING _BITUL(CIF_MCCK_PENDING)
2526
#define _CIF_ASCE_PRIMARY _BITUL(CIF_ASCE_PRIMARY)
@@ -28,6 +29,7 @@
2829
#define _CIF_FPU _BITUL(CIF_FPU)
2930
#define _CIF_IGNORE_IRQ _BITUL(CIF_IGNORE_IRQ)
3031
#define _CIF_ENABLED_WAIT _BITUL(CIF_ENABLED_WAIT)
32+
#define _CIF_MCCK_GUEST _BITUL(CIF_MCCK_GUEST)
3133

3234
#ifndef __ASSEMBLY__
3335

arch/s390/kernel/asm-offsets.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ int main(void)
5858
OFFSET(__SF_BACKCHAIN, stack_frame, back_chain);
5959
OFFSET(__SF_GPRS, stack_frame, gprs);
6060
OFFSET(__SF_EMPTY, stack_frame, empty1);
61+
OFFSET(__SF_SIE_CONTROL, stack_frame, empty1[0]);
62+
OFFSET(__SF_SIE_SAVEAREA, stack_frame, empty1[1]);
63+
OFFSET(__SF_SIE_REASON, stack_frame, empty1[2]);
6164
BLANK();
6265
/* timeval/timezone offsets for use by vdso */
6366
OFFSET(__VDSO_UPD_COUNT, vdso_data, tb_update_count);

arch/s390/kernel/entry.S

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ ENTRY(sie64a)
225225
jnz .Lsie_skip
226226
TSTMSK __LC_CPU_FLAGS,_CIF_FPU
227227
jo .Lsie_skip # exit if fp/vx regs changed
228+
.Lsie_entry:
228229
sie 0(%r14)
229230
.Lsie_skip:
230231
ni __SIE_PROG0C+3(%r14),0xfe # no longer in SIE
@@ -1102,7 +1103,13 @@ cleanup_critical:
11021103
.quad .Lsie_done
11031104

11041105
.Lcleanup_sie:
1105-
lg %r9,__SF_EMPTY(%r15) # get control block pointer
1106+
cghi %r11,__LC_SAVE_AREA_ASYNC #Is this in normal interrupt?
1107+
je 1f
1108+
slg %r9,BASED(.Lsie_crit_mcck_start)
1109+
clg %r9,BASED(.Lsie_crit_mcck_length)
1110+
jh 1f
1111+
oi __LC_CPU_FLAGS+7, _CIF_MCCK_GUEST
1112+
1: lg %r9,__SF_EMPTY(%r15) # get control block pointer
11061113
ni __SIE_PROG0C+3(%r9),0xfe # no longer in SIE
11071114
lctlg %c1,%c1,__LC_USER_ASCE # load primary asce
11081115
larl %r9,sie_exit # skip forward to sie_exit
@@ -1274,6 +1281,10 @@ cleanup_critical:
12741281
.quad .Lsie_gmap
12751282
.Lsie_critical_length:
12761283
.quad .Lsie_done - .Lsie_gmap
1284+
.Lsie_crit_mcck_start:
1285+
.quad .Lsie_entry
1286+
.Lsie_crit_mcck_length:
1287+
.quad .Lsie_skip - .Lsie_entry
12771288
#endif
12781289

12791290
.section .rodata, "a"

arch/s390/kernel/nmi.c

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <asm/crw.h>
2626
#include <asm/switch_to.h>
2727
#include <asm/ctl_reg.h>
28+
#include <asm/asm-offsets.h>
2829

2930
struct mcck_struct {
3031
unsigned int kill_task : 1;
@@ -280,6 +281,8 @@ static int notrace s390_validate_registers(union mci mci, int umode)
280281
#define ED_STP_ISLAND 6 /* External damage STP island check */
281282
#define ED_STP_SYNC 7 /* External damage STP sync check */
282283

284+
#define MCCK_CODE_NO_GUEST (MCCK_CODE_CP | MCCK_CODE_EXT_DAMAGE)
285+
283286
/*
284287
* machine check handler.
285288
*/
@@ -291,6 +294,7 @@ void notrace s390_do_machine_check(struct pt_regs *regs)
291294
struct mcck_struct *mcck;
292295
unsigned long long tmp;
293296
union mci mci;
297+
unsigned long mcck_dam_code;
294298

295299
nmi_enter();
296300
inc_irq_stat(NMI_NMI);
@@ -301,7 +305,13 @@ void notrace s390_do_machine_check(struct pt_regs *regs)
301305
/* System damage -> stopping machine */
302306
s390_handle_damage();
303307
}
304-
if (mci.pd) {
308+
309+
/*
310+
* Reinject the instruction processing damages' machine checks
311+
* including Delayed Access Exception into the guest
312+
* instead of damaging the host if they happen in the guest.
313+
*/
314+
if (mci.pd && !test_cpu_flag(CIF_MCCK_GUEST)) {
305315
if (mci.b) {
306316
/* Processing backup -> verify if we can survive this */
307317
u64 z_mcic, o_mcic, t_mcic;
@@ -358,15 +368,22 @@ void notrace s390_do_machine_check(struct pt_regs *regs)
358368
if (mcck->stp_queue)
359369
set_cpu_flag(CIF_MCCK_PENDING);
360370
}
361-
if (mci.se)
362-
/* Storage error uncorrected */
363-
s390_handle_damage();
364-
if (mci.ke)
365-
/* Storage key-error uncorrected */
366-
s390_handle_damage();
367-
if (mci.ds && mci.fa)
368-
/* Storage degradation */
369-
s390_handle_damage();
371+
372+
/*
373+
* Reinject storage related machine checks into the guest if they
374+
* happen when the guest is running.
375+
*/
376+
if (!test_cpu_flag(CIF_MCCK_GUEST)) {
377+
if (mci.se)
378+
/* Storage error uncorrected */
379+
s390_handle_damage();
380+
if (mci.ke)
381+
/* Storage key-error uncorrected */
382+
s390_handle_damage();
383+
if (mci.ds && mci.fa)
384+
/* Storage degradation */
385+
s390_handle_damage();
386+
}
370387
if (mci.cp) {
371388
/* Channel report word pending */
372389
mcck->channel_report = 1;
@@ -377,6 +394,19 @@ void notrace s390_do_machine_check(struct pt_regs *regs)
377394
mcck->warning = 1;
378395
set_cpu_flag(CIF_MCCK_PENDING);
379396
}
397+
398+
/*
399+
* If there are only Channel Report Pending and External Damage
400+
* machine checks, they will not be reinjected into the guest
401+
* because they refer to host conditions only.
402+
*/
403+
mcck_dam_code = (mci.val & MCIC_SUBCLASS_MASK);
404+
if (test_cpu_flag(CIF_MCCK_GUEST) &&
405+
(mcck_dam_code & MCCK_CODE_NO_GUEST) != mcck_dam_code) {
406+
/* Set exit reason code for host's later handling */
407+
*((long *)(regs->gprs[15] + __SF_SIE_REASON)) = -EINTR;
408+
}
409+
clear_cpu_flag(CIF_MCCK_GUEST);
380410
nmi_exit();
381411
}
382412

0 commit comments

Comments
 (0)