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 (2887B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Simple heartbeat STM source driver
      4 * Copyright (c) 2016, Intel Corporation.
      5 *
      6 * Heartbeat STM source will send repetitive messages over STM devices to a
      7 * trace host.
      8 */
      9
     10#include <linux/kernel.h>
     11#include <linux/module.h>
     12#include <linux/hrtimer.h>
     13#include <linux/slab.h>
     14#include <linux/stm.h>
     15
     16#define STM_HEARTBEAT_MAX	32
     17
     18static int nr_devs = 4;
     19static int interval_ms = 10;
     20
     21module_param(nr_devs, int, 0400);
     22module_param(interval_ms, int, 0600);
     23
     24static struct stm_heartbeat {
     25	struct stm_source_data	data;
     26	struct hrtimer		hrtimer;
     27	unsigned int		active;
     28} stm_heartbeat[STM_HEARTBEAT_MAX];
     29
     30static const char str[] = "heartbeat stm source driver is here to serve you";
     31
     32static enum hrtimer_restart stm_heartbeat_hrtimer_handler(struct hrtimer *hr)
     33{
     34	struct stm_heartbeat *heartbeat = container_of(hr, struct stm_heartbeat,
     35						       hrtimer);
     36
     37	stm_source_write(&heartbeat->data, 0, str, sizeof str);
     38	if (heartbeat->active)
     39		hrtimer_forward_now(hr, ms_to_ktime(interval_ms));
     40
     41	return heartbeat->active ? HRTIMER_RESTART : HRTIMER_NORESTART;
     42}
     43
     44static int stm_heartbeat_link(struct stm_source_data *data)
     45{
     46	struct stm_heartbeat *heartbeat =
     47		container_of(data, struct stm_heartbeat, data);
     48
     49	heartbeat->active = 1;
     50	hrtimer_start(&heartbeat->hrtimer, ms_to_ktime(interval_ms),
     51		      HRTIMER_MODE_ABS);
     52
     53	return 0;
     54}
     55
     56static void stm_heartbeat_unlink(struct stm_source_data *data)
     57{
     58	struct stm_heartbeat *heartbeat =
     59		container_of(data, struct stm_heartbeat, data);
     60
     61	heartbeat->active = 0;
     62	hrtimer_cancel(&heartbeat->hrtimer);
     63}
     64
     65static int stm_heartbeat_init(void)
     66{
     67	int i, ret;
     68
     69	if (nr_devs < 0 || nr_devs > STM_HEARTBEAT_MAX)
     70		return -EINVAL;
     71
     72	for (i = 0; i < nr_devs; i++) {
     73		stm_heartbeat[i].data.name =
     74			kasprintf(GFP_KERNEL, "heartbeat.%d", i);
     75		if (!stm_heartbeat[i].data.name) {
     76			ret = -ENOMEM;
     77			goto fail_unregister;
     78		}
     79
     80		stm_heartbeat[i].data.nr_chans	= 1;
     81		stm_heartbeat[i].data.link	= stm_heartbeat_link;
     82		stm_heartbeat[i].data.unlink	= stm_heartbeat_unlink;
     83		hrtimer_init(&stm_heartbeat[i].hrtimer, CLOCK_MONOTONIC,
     84			     HRTIMER_MODE_ABS);
     85		stm_heartbeat[i].hrtimer.function =
     86			stm_heartbeat_hrtimer_handler;
     87
     88		ret = stm_source_register_device(NULL, &stm_heartbeat[i].data);
     89		if (ret)
     90			goto fail_free;
     91	}
     92
     93	return 0;
     94
     95fail_unregister:
     96	for (i--; i >= 0; i--) {
     97		stm_source_unregister_device(&stm_heartbeat[i].data);
     98fail_free:
     99		kfree(stm_heartbeat[i].data.name);
    100	}
    101
    102	return ret;
    103}
    104
    105static void stm_heartbeat_exit(void)
    106{
    107	int i;
    108
    109	for (i = 0; i < nr_devs; i++) {
    110		stm_source_unregister_device(&stm_heartbeat[i].data);
    111		kfree(stm_heartbeat[i].data.name);
    112	}
    113}
    114
    115module_init(stm_heartbeat_init);
    116module_exit(stm_heartbeat_exit);
    117
    118MODULE_LICENSE("GPL v2");
    119MODULE_DESCRIPTION("stm_heartbeat driver");
    120MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@linux.intel.com>");