Commit c6875f3a authored by Boris Ostrovsky's avatar Boris Ostrovsky
Browse files

x86/xen: Return from panic notifier



Currently execution of panic() continues until Xen's panic notifier
(xen_panic_event()) is called at which point we make a hypercall that
never returns.

This means that any notifier that is supposed to be called later as
well as significant part of panic() code (such as pstore writes from
kmsg_dump()) is never executed.

There is no reason for xen_panic_event() to be this last point in
execution since panic()'s emergency_restart() will call into
xen_emergency_restart() from where we can perform our hypercall.

Nevertheless, we will provide xen_legacy_crash boot option that will
preserve original behavior during crash. This option could be used,
for example, if running kernel dumper (which happens after panic
notifiers) is undesirable.

Reported-by: default avatarJames Dingwall <james@dingwall.me.uk>
Signed-off-by: default avatarBoris Ostrovsky <boris.ostrovsky@oracle.com>
Reviewed-by: default avatarJuergen Gross <jgross@suse.com>
parent a8fabb38
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -5267,6 +5267,10 @@
				the unplug protocol
			never -- do not unplug even if version check succeeds

	xen_legacy_crash	[X86,XEN]
			Crash from Xen panic notifier, without executing late
			panic() code such as dumping handler.

	xen_nopvspin	[X86,XEN]
			Disables the ticketlock slowpath using Xen PV
			optimizations.
+25 −3
Original line number Diff line number Diff line
@@ -269,19 +269,41 @@ void xen_reboot(int reason)
		BUG();
}

static int reboot_reason = SHUTDOWN_reboot;
static bool xen_legacy_crash;
void xen_emergency_restart(void)
{
	xen_reboot(SHUTDOWN_reboot);
	xen_reboot(reboot_reason);
}

static int
xen_panic_event(struct notifier_block *this, unsigned long event, void *ptr)
{
	if (!kexec_crash_loaded())
	if (!kexec_crash_loaded()) {
		if (xen_legacy_crash)
			xen_reboot(SHUTDOWN_crash);

		reboot_reason = SHUTDOWN_crash;

		/*
		 * If panic_timeout==0 then we are supposed to wait forever.
		 * However, to preserve original dom0 behavior we have to drop
		 * into hypervisor. (domU behavior is controlled by its
		 * config file)
		 */
		if (panic_timeout == 0)
			panic_timeout = -1;
	}
	return NOTIFY_DONE;
}

static int __init parse_xen_legacy_crash(char *arg)
{
	xen_legacy_crash = true;
	return 0;
}
early_param("xen_legacy_crash", parse_xen_legacy_crash);

static struct notifier_block xen_panic_block = {
	.notifier_call = xen_panic_event,
	.priority = INT_MIN