162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *     signal quiesce handler
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci *  Copyright IBM Corp. 1999, 2004
662306a36Sopenharmony_ci *  Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
762306a36Sopenharmony_ci *             Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/types.h>
1162306a36Sopenharmony_ci#include <linux/cpumask.h>
1262306a36Sopenharmony_ci#include <linux/smp.h>
1362306a36Sopenharmony_ci#include <linux/init.h>
1462306a36Sopenharmony_ci#include <linux/reboot.h>
1562306a36Sopenharmony_ci#include <linux/atomic.h>
1662306a36Sopenharmony_ci#include <asm/ptrace.h>
1762306a36Sopenharmony_ci#include <asm/smp.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#include "sclp.h"
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci/* Shutdown handler. Signal completion of shutdown by loading special PSW. */
2262306a36Sopenharmony_cistatic void do_machine_quiesce(void)
2362306a36Sopenharmony_ci{
2462306a36Sopenharmony_ci	psw_t quiesce_psw;
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci	smp_send_stop();
2762306a36Sopenharmony_ci	quiesce_psw.mask =
2862306a36Sopenharmony_ci		PSW_MASK_BASE | PSW_MASK_EA | PSW_MASK_BA | PSW_MASK_WAIT;
2962306a36Sopenharmony_ci	quiesce_psw.addr = 0xfff;
3062306a36Sopenharmony_ci	__load_psw(quiesce_psw);
3162306a36Sopenharmony_ci}
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci/* Handler for quiesce event. Start shutdown procedure. */
3462306a36Sopenharmony_cistatic void sclp_quiesce_handler(struct evbuf_header *evbuf)
3562306a36Sopenharmony_ci{
3662306a36Sopenharmony_ci	_machine_restart = (void *) do_machine_quiesce;
3762306a36Sopenharmony_ci	_machine_halt = do_machine_quiesce;
3862306a36Sopenharmony_ci	_machine_power_off = do_machine_quiesce;
3962306a36Sopenharmony_ci	ctrl_alt_del();
4062306a36Sopenharmony_ci}
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_cistatic struct sclp_register sclp_quiesce_event = {
4362306a36Sopenharmony_ci	.receive_mask = EVTYP_SIGQUIESCE_MASK,
4462306a36Sopenharmony_ci	.receiver_fn = sclp_quiesce_handler,
4562306a36Sopenharmony_ci};
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci/* Initialize quiesce driver. */
4862306a36Sopenharmony_cistatic int __init sclp_quiesce_init(void)
4962306a36Sopenharmony_ci{
5062306a36Sopenharmony_ci	return sclp_register(&sclp_quiesce_event);
5162306a36Sopenharmony_ci}
5262306a36Sopenharmony_cidevice_initcall(sclp_quiesce_init);
53