s390x/kvm: Log unmanageable external interruptions

Interception code 0x14 only drops to userspace when an unmanageable
external interruption interception occured (e.g. if the External New
PSW does not disable external interruptions). Instead of bailing out
via the default handler, it is better to inform the user with a
proper error message that also includes the bad PSW, and to stop
the affected CPU with a panic event instead.

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
master
Thomas Huth 2014-03-20 21:49:18 +01:00 committed by Cornelia Huck
parent 4cb88c3c37
commit a2689242b1
1 changed files with 29 additions and 6 deletions

View File

@ -83,6 +83,7 @@
#define DIAG_KVM_BREAKPOINT 0x501
#define ICPT_INSTRUCTION 0x04
#define ICPT_EXT_INT 0x14
#define ICPT_WAITPSW 0x1c
#define ICPT_SOFT_INTERCEPT 0x24
#define ICPT_CPU_STOP 0x28
@ -930,6 +931,28 @@ static bool is_special_wait_psw(CPUState *cs)
return cs->kvm_run->psw_addr == 0xfffUL;
}
static void guest_panicked(void)
{
QObject *data;
data = qobject_from_jsonf("{ 'action': %s }", "pause");
monitor_protocol_event(QEVENT_GUEST_PANICKED, data);
qobject_decref(data);
vm_stop(RUN_STATE_GUEST_PANICKED);
}
static void unmanageable_intercept(S390CPU *cpu, const char *str, int pswoffset)
{
CPUState *cs = CPU(cpu);
error_report("Unmanageable %s! CPU%i new PSW: 0x%016lx:%016lx",
str, cs->cpu_index, ldq_phys(cs->as, cpu->env.psa + pswoffset),
ldq_phys(cs->as, cpu->env.psa + pswoffset + 8));
s390_del_running_cpu(cpu);
guest_panicked();
}
static int handle_intercept(S390CPU *cpu)
{
CPUState *cs = CPU(cpu);
@ -943,18 +966,18 @@ static int handle_intercept(S390CPU *cpu)
case ICPT_INSTRUCTION:
r = handle_instruction(cpu, run);
break;
case ICPT_EXT_INT:
unmanageable_intercept(cpu, "external interrupt",
offsetof(LowCore, external_new_psw));
r = EXCP_HALTED;
break;
case ICPT_WAITPSW:
/* disabled wait, since enabled wait is handled in kernel */
if (s390_del_running_cpu(cpu) == 0) {
if (is_special_wait_psw(cs)) {
qemu_system_shutdown_request();
} else {
QObject *data;
data = qobject_from_jsonf("{ 'action': %s }", "pause");
monitor_protocol_event(QEVENT_GUEST_PANICKED, data);
qobject_decref(data);
vm_stop(RUN_STATE_GUEST_PANICKED);
guest_panicked();
}
}
r = EXCP_HALTED;