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

fsm.c (4850B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * A generic FSM based on fsm used in isdn4linux
      4 *
      5 */
      6
      7#include "fsm.h"
      8#include <linux/module.h>
      9#include <linux/slab.h>
     10#include <linux/timer.h>
     11
     12MODULE_AUTHOR("(C) 2000 IBM Corp. by Fritz Elfert (felfert@millenux.com)");
     13MODULE_DESCRIPTION("Finite state machine helper functions");
     14MODULE_LICENSE("GPL");
     15
     16fsm_instance *
     17init_fsm(char *name, const char **state_names, const char **event_names, int nr_states,
     18		int nr_events, const fsm_node *tmpl, int tmpl_len, gfp_t order)
     19{
     20	int i;
     21	fsm_instance *this;
     22	fsm_function_t *m;
     23	fsm *f;
     24
     25	this = kzalloc(sizeof(fsm_instance), order);
     26	if (this == NULL) {
     27		printk(KERN_WARNING
     28			"fsm(%s): init_fsm: Couldn't alloc instance\n", name);
     29		return NULL;
     30	}
     31	strlcpy(this->name, name, sizeof(this->name));
     32	init_waitqueue_head(&this->wait_q);
     33
     34	f = kzalloc(sizeof(fsm), order);
     35	if (f == NULL) {
     36		printk(KERN_WARNING
     37			"fsm(%s): init_fsm: Couldn't alloc fsm\n", name);
     38		kfree_fsm(this);
     39		return NULL;
     40	}
     41	f->nr_events = nr_events;
     42	f->nr_states = nr_states;
     43	f->event_names = event_names;
     44	f->state_names = state_names;
     45	this->f = f;
     46
     47	m = kcalloc(nr_states*nr_events, sizeof(fsm_function_t), order);
     48	if (m == NULL) {
     49		printk(KERN_WARNING
     50			"fsm(%s): init_fsm: Couldn't alloc jumptable\n", name);
     51		kfree_fsm(this);
     52		return NULL;
     53	}
     54	f->jumpmatrix = m;
     55
     56	for (i = 0; i < tmpl_len; i++) {
     57		if ((tmpl[i].cond_state >= nr_states) ||
     58		    (tmpl[i].cond_event >= nr_events)   ) {
     59			printk(KERN_ERR
     60				"fsm(%s): init_fsm: Bad template l=%d st(%ld/%ld) ev(%ld/%ld)\n",
     61				name, i, (long)tmpl[i].cond_state, (long)f->nr_states,
     62				(long)tmpl[i].cond_event, (long)f->nr_events);
     63			kfree_fsm(this);
     64			return NULL;
     65		} else
     66			m[nr_states * tmpl[i].cond_event + tmpl[i].cond_state] =
     67				tmpl[i].function;
     68	}
     69	return this;
     70}
     71
     72void
     73kfree_fsm(fsm_instance *this)
     74{
     75	if (this) {
     76		if (this->f) {
     77			kfree(this->f->jumpmatrix);
     78			kfree(this->f);
     79		}
     80		kfree(this);
     81	} else
     82		printk(KERN_WARNING
     83			"fsm: kfree_fsm called with NULL argument\n");
     84}
     85
     86#if FSM_DEBUG_HISTORY
     87void
     88fsm_print_history(fsm_instance *fi)
     89{
     90	int idx = 0;
     91	int i;
     92
     93	if (fi->history_size >= FSM_HISTORY_SIZE)
     94		idx = fi->history_index;
     95
     96	printk(KERN_DEBUG "fsm(%s): History:\n", fi->name);
     97	for (i = 0; i < fi->history_size; i++) {
     98		int e = fi->history[idx].event;
     99		int s = fi->history[idx++].state;
    100		idx %= FSM_HISTORY_SIZE;
    101		if (e == -1)
    102			printk(KERN_DEBUG "  S=%s\n",
    103			       fi->f->state_names[s]);
    104		else
    105			printk(KERN_DEBUG "  S=%s E=%s\n",
    106			       fi->f->state_names[s],
    107			       fi->f->event_names[e]);
    108	}
    109	fi->history_size = fi->history_index = 0;
    110}
    111
    112void
    113fsm_record_history(fsm_instance *fi, int state, int event)
    114{
    115	fi->history[fi->history_index].state = state;
    116	fi->history[fi->history_index++].event = event;
    117	fi->history_index %= FSM_HISTORY_SIZE;
    118	if (fi->history_size < FSM_HISTORY_SIZE)
    119		fi->history_size++;
    120}
    121#endif
    122
    123const char *
    124fsm_getstate_str(fsm_instance *fi)
    125{
    126	int st = atomic_read(&fi->state);
    127	if (st >= fi->f->nr_states)
    128		return "Invalid";
    129	return fi->f->state_names[st];
    130}
    131
    132static void
    133fsm_expire_timer(struct timer_list *t)
    134{
    135	fsm_timer *this = from_timer(this, t, tl);
    136#if FSM_TIMER_DEBUG
    137	printk(KERN_DEBUG "fsm(%s): Timer %p expired\n",
    138	       this->fi->name, this);
    139#endif
    140	fsm_event(this->fi, this->expire_event, this->event_arg);
    141}
    142
    143void
    144fsm_settimer(fsm_instance *fi, fsm_timer *this)
    145{
    146	this->fi = fi;
    147#if FSM_TIMER_DEBUG
    148	printk(KERN_DEBUG "fsm(%s): Create timer %p\n", fi->name,
    149	       this);
    150#endif
    151	timer_setup(&this->tl, fsm_expire_timer, 0);
    152}
    153
    154void
    155fsm_deltimer(fsm_timer *this)
    156{
    157#if FSM_TIMER_DEBUG
    158	printk(KERN_DEBUG "fsm(%s): Delete timer %p\n", this->fi->name,
    159		this);
    160#endif
    161	del_timer(&this->tl);
    162}
    163
    164int
    165fsm_addtimer(fsm_timer *this, int millisec, int event, void *arg)
    166{
    167
    168#if FSM_TIMER_DEBUG
    169	printk(KERN_DEBUG "fsm(%s): Add timer %p %dms\n",
    170	       this->fi->name, this, millisec);
    171#endif
    172
    173	timer_setup(&this->tl, fsm_expire_timer, 0);
    174	this->expire_event = event;
    175	this->event_arg = arg;
    176	this->tl.expires = jiffies + (millisec * HZ) / 1000;
    177	add_timer(&this->tl);
    178	return 0;
    179}
    180
    181/* FIXME: this function is never used, why */
    182void
    183fsm_modtimer(fsm_timer *this, int millisec, int event, void *arg)
    184{
    185
    186#if FSM_TIMER_DEBUG
    187	printk(KERN_DEBUG "fsm(%s): Restart timer %p %dms\n",
    188		this->fi->name, this, millisec);
    189#endif
    190
    191	del_timer(&this->tl);
    192	timer_setup(&this->tl, fsm_expire_timer, 0);
    193	this->expire_event = event;
    194	this->event_arg = arg;
    195	this->tl.expires = jiffies + (millisec * HZ) / 1000;
    196	add_timer(&this->tl);
    197}
    198
    199EXPORT_SYMBOL(init_fsm);
    200EXPORT_SYMBOL(kfree_fsm);
    201EXPORT_SYMBOL(fsm_settimer);
    202EXPORT_SYMBOL(fsm_deltimer);
    203EXPORT_SYMBOL(fsm_addtimer);
    204EXPORT_SYMBOL(fsm_modtimer);
    205EXPORT_SYMBOL(fsm_getstate_str);
    206
    207#if FSM_DEBUG_HISTORY
    208EXPORT_SYMBOL(fsm_print_history);
    209EXPORT_SYMBOL(fsm_record_history);
    210#endif