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

trigger.h (2013B)


      1/* SPDX-License-Identifier: GPL-2.0 */
      2#ifndef __TRIGGER_H_
      3#define __TRIGGER_H_ 1
      4
      5#include "asm/bug.h"
      6
      7/*
      8 * Use trigger to model operations which need to be executed when
      9 * an event (a signal, for example) is observed.
     10 *
     11 * States and transits:
     12 *
     13 *
     14 *  OFF--> ON --> READY --(hit)--> HIT
     15 *                 ^               |
     16 *                 |            (ready)
     17 *                 |               |
     18 *                  \_____________/
     19 *
     20 * is_hit and is_ready are two key functions to query the state of
     21 * a trigger. is_hit means the event already happen; is_ready means the
     22 * trigger is waiting for the event.
     23 */
     24
     25struct trigger {
     26	volatile enum {
     27		TRIGGER_ERROR		= -2,
     28		TRIGGER_OFF		= -1,
     29		TRIGGER_ON		= 0,
     30		TRIGGER_READY		= 1,
     31		TRIGGER_HIT		= 2,
     32	} state;
     33	const char *name;
     34};
     35
     36#define TRIGGER_WARN_ONCE(t, exp) \
     37	WARN_ONCE(t->state != exp, "trigger '%s' state transist error: %d in %s()\n", \
     38		  t->name, t->state, __func__)
     39
     40static inline bool trigger_is_available(struct trigger *t)
     41{
     42	return t->state >= 0;
     43}
     44
     45static inline bool trigger_is_error(struct trigger *t)
     46{
     47	return t->state <= TRIGGER_ERROR;
     48}
     49
     50static inline void trigger_on(struct trigger *t)
     51{
     52	TRIGGER_WARN_ONCE(t, TRIGGER_OFF);
     53	t->state = TRIGGER_ON;
     54}
     55
     56static inline void trigger_ready(struct trigger *t)
     57{
     58	if (!trigger_is_available(t))
     59		return;
     60	t->state = TRIGGER_READY;
     61}
     62
     63static inline void trigger_hit(struct trigger *t)
     64{
     65	if (!trigger_is_available(t))
     66		return;
     67	TRIGGER_WARN_ONCE(t, TRIGGER_READY);
     68	t->state = TRIGGER_HIT;
     69}
     70
     71static inline void trigger_off(struct trigger *t)
     72{
     73	if (!trigger_is_available(t))
     74		return;
     75	t->state = TRIGGER_OFF;
     76}
     77
     78static inline void trigger_error(struct trigger *t)
     79{
     80	t->state = TRIGGER_ERROR;
     81}
     82
     83static inline bool trigger_is_ready(struct trigger *t)
     84{
     85	return t->state == TRIGGER_READY;
     86}
     87
     88static inline bool trigger_is_hit(struct trigger *t)
     89{
     90	return t->state == TRIGGER_HIT;
     91}
     92
     93#define DEFINE_TRIGGER(n) \
     94struct trigger n = {.state = TRIGGER_OFF, .name = #n}
     95#endif