cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

heartbeat.c (2565B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2
      3/*
      4 * IBM ASM Service Processor Device Driver
      5 *
      6 * Copyright (C) IBM Corporation, 2004
      7 *
      8 * Author: Max Asböck <amax@us.ibm.com>
      9 */
     10
     11#include <linux/notifier.h>
     12#include <linux/panic_notifier.h>
     13#include "ibmasm.h"
     14#include "dot_command.h"
     15#include "lowlevel.h"
     16
     17static int suspend_heartbeats = 0;
     18
     19/*
     20 * Once the driver indicates to the service processor that it is running
     21 * - see send_os_state() - the service processor sends periodic heartbeats
     22 * to the driver. The driver must respond to the heartbeats or else the OS
     23 * will be rebooted.
     24 * In the case of a panic the interrupt handler continues to work and thus
     25 * continues to respond to heartbeats, making the service processor believe
     26 * the OS is still running and thus preventing a reboot.
     27 * To prevent this from happening a callback is added the panic_notifier_list.
     28 * Before responding to a heartbeat the driver checks if a panic has happened,
     29 * if yes it suspends heartbeat, causing the service processor to reboot as
     30 * expected.
     31 */
     32static int panic_happened(struct notifier_block *n, unsigned long val, void *v)
     33{
     34	suspend_heartbeats = 1;
     35	return 0;
     36}
     37
     38static struct notifier_block panic_notifier = { panic_happened, NULL, 1 };
     39
     40void ibmasm_register_panic_notifier(void)
     41{
     42	atomic_notifier_chain_register(&panic_notifier_list, &panic_notifier);
     43}
     44
     45void ibmasm_unregister_panic_notifier(void)
     46{
     47	atomic_notifier_chain_unregister(&panic_notifier_list,
     48			&panic_notifier);
     49}
     50
     51
     52int ibmasm_heartbeat_init(struct service_processor *sp)
     53{
     54	sp->heartbeat = ibmasm_new_command(sp, HEARTBEAT_BUFFER_SIZE);
     55	if (sp->heartbeat == NULL)
     56		return -ENOMEM;
     57
     58	return 0;
     59}
     60
     61void ibmasm_heartbeat_exit(struct service_processor *sp)
     62{
     63	char tsbuf[32];
     64
     65	dbg("%s:%d at %s\n", __func__, __LINE__, get_timestamp(tsbuf));
     66	ibmasm_wait_for_response(sp->heartbeat, IBMASM_CMD_TIMEOUT_NORMAL);
     67	dbg("%s:%d at %s\n", __func__, __LINE__, get_timestamp(tsbuf));
     68	suspend_heartbeats = 1;
     69	command_put(sp->heartbeat);
     70}
     71
     72void ibmasm_receive_heartbeat(struct service_processor *sp,  void *message, size_t size)
     73{
     74	struct command *cmd = sp->heartbeat;
     75	struct dot_command_header *header = (struct dot_command_header *)cmd->buffer;
     76	char tsbuf[32];
     77
     78	dbg("%s:%d at %s\n", __func__, __LINE__, get_timestamp(tsbuf));
     79	if (suspend_heartbeats)
     80		return;
     81
     82	/* return the received dot command to sender */
     83	cmd->status = IBMASM_CMD_PENDING;
     84	size = min(size, cmd->buffer_size);
     85	memcpy_fromio(cmd->buffer, message, size);
     86	header->type = sp_write;
     87	ibmasm_exec_command(sp, cmd);
     88}