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

srf.c (10014B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/******************************************************************************
      3 *
      4 *	(C)Copyright 1998,1999 SysKonnect,
      5 *	a business unit of Schneider & Koch & Co. Datensysteme GmbH.
      6 *
      7 *	See the file "skfddi.c" for further information.
      8 *
      9 *	The information in this file is provided "AS IS" without warranty.
     10 *
     11 ******************************************************************************/
     12
     13/*
     14	SMT 7.2 Status Response Frame Implementation
     15	SRF state machine and frame generation
     16*/
     17
     18#include "h/types.h"
     19#include "h/fddi.h"
     20#include "h/smc.h"
     21#include "h/smt_p.h"
     22
     23#define KERNEL
     24#include "h/smtstate.h"
     25
     26#ifndef	SLIM_SMT
     27#ifndef	BOOT
     28
     29/*
     30 * function declarations
     31 */
     32static void clear_all_rep(struct s_smc *smc);
     33static void clear_reported(struct s_smc *smc);
     34static void smt_send_srf(struct s_smc *smc);
     35static struct s_srf_evc *smt_get_evc(struct s_smc *smc, int code, int index);
     36
     37#define MAX_EVCS	ARRAY_SIZE(smc->evcs)
     38
     39struct evc_init {
     40	u_char code ;
     41	u_char index ;
     42	u_char n ;
     43	u_short	para ;
     44}  ;
     45
     46static const struct evc_init evc_inits[] = {
     47	{ SMT_COND_SMT_PEER_WRAP,		0,1,SMT_P1048	} ,
     48
     49	{ SMT_COND_MAC_DUP_ADDR,		INDEX_MAC, NUMMACS,SMT_P208C } ,
     50	{ SMT_COND_MAC_FRAME_ERROR,		INDEX_MAC, NUMMACS,SMT_P208D } ,
     51	{ SMT_COND_MAC_NOT_COPIED,		INDEX_MAC, NUMMACS,SMT_P208E } ,
     52	{ SMT_EVENT_MAC_NEIGHBOR_CHANGE,	INDEX_MAC, NUMMACS,SMT_P208F } ,
     53	{ SMT_EVENT_MAC_PATH_CHANGE,		INDEX_MAC, NUMMACS,SMT_P2090 } ,
     54
     55	{ SMT_COND_PORT_LER,			INDEX_PORT,NUMPHYS,SMT_P4050 } ,
     56	{ SMT_COND_PORT_EB_ERROR,		INDEX_PORT,NUMPHYS,SMT_P4052 } ,
     57	{ SMT_EVENT_PORT_CONNECTION,		INDEX_PORT,NUMPHYS,SMT_P4051 } ,
     58	{ SMT_EVENT_PORT_PATH_CHANGE,		INDEX_PORT,NUMPHYS,SMT_P4053 } ,
     59} ;
     60
     61#define MAX_INIT_EVC	ARRAY_SIZE(evc_inits)
     62
     63void smt_init_evc(struct s_smc *smc)
     64{
     65	struct s_srf_evc	*evc ;
     66	const struct evc_init 	*init ;
     67	unsigned int		i ;
     68	int			index ;
     69	int			offset ;
     70
     71	static u_char		fail_safe = FALSE ;
     72
     73	memset((char *)smc->evcs,0,sizeof(smc->evcs)) ;
     74
     75	evc = smc->evcs ;
     76	init = evc_inits ;
     77
     78	for (i = 0 ; i < MAX_INIT_EVC ; i++) {
     79		for (index = 0 ; index < init->n ; index++) {
     80			evc->evc_code = init->code ;
     81			evc->evc_para = init->para ;
     82			evc->evc_index = init->index + index ;
     83#ifndef	DEBUG
     84			evc->evc_multiple = &fail_safe ;
     85			evc->evc_cond_state = &fail_safe ;
     86#endif
     87			evc++ ;
     88		}
     89		init++ ;
     90	}
     91
     92	if ((unsigned int) (evc - smc->evcs) > MAX_EVCS) {
     93		SMT_PANIC(smc,SMT_E0127, SMT_E0127_MSG) ;
     94	}
     95
     96	/*
     97	 * conditions
     98	 */
     99	smc->evcs[0].evc_cond_state = &smc->mib.fddiSMTPeerWrapFlag ;
    100	smc->evcs[1].evc_cond_state =
    101		&smc->mib.m[MAC0].fddiMACDuplicateAddressCond ;
    102	smc->evcs[2].evc_cond_state =
    103		&smc->mib.m[MAC0].fddiMACFrameErrorFlag ;
    104	smc->evcs[3].evc_cond_state =
    105		&smc->mib.m[MAC0].fddiMACNotCopiedFlag ;
    106
    107	/*
    108	 * events
    109	 */
    110	smc->evcs[4].evc_multiple = &smc->mib.m[MAC0].fddiMACMultiple_N ;
    111	smc->evcs[5].evc_multiple = &smc->mib.m[MAC0].fddiMACMultiple_P ;
    112
    113	offset = 6 ;
    114	for (i = 0 ; i < NUMPHYS ; i++) {
    115		/*
    116		 * conditions
    117		 */
    118		smc->evcs[offset + 0*NUMPHYS].evc_cond_state =
    119			&smc->mib.p[i].fddiPORTLerFlag ;
    120		smc->evcs[offset + 1*NUMPHYS].evc_cond_state =
    121			&smc->mib.p[i].fddiPORTEB_Condition ;
    122
    123		/*
    124		 * events
    125		 */
    126		smc->evcs[offset + 2*NUMPHYS].evc_multiple =
    127			&smc->mib.p[i].fddiPORTMultiple_U ;
    128		smc->evcs[offset + 3*NUMPHYS].evc_multiple =
    129			&smc->mib.p[i].fddiPORTMultiple_P ;
    130		offset++ ;
    131	}
    132#ifdef	DEBUG
    133	for (i = 0, evc = smc->evcs ; i < MAX_EVCS ; i++, evc++) {
    134		if (SMT_IS_CONDITION(evc->evc_code)) {
    135			if (!evc->evc_cond_state) {
    136				SMT_PANIC(smc,SMT_E0128, SMT_E0128_MSG) ;
    137			}
    138			evc->evc_multiple = &fail_safe ;
    139		}
    140		else {
    141			if (!evc->evc_multiple) {
    142				SMT_PANIC(smc,SMT_E0129, SMT_E0129_MSG) ;
    143			}
    144			evc->evc_cond_state = &fail_safe ;
    145		}
    146	}
    147#endif
    148	smc->srf.TSR = smt_get_time() ;
    149	smc->srf.sr_state = SR0_WAIT ;
    150}
    151
    152static struct s_srf_evc *smt_get_evc(struct s_smc *smc, int code, int index)
    153{
    154	unsigned int		i ;
    155	struct s_srf_evc	*evc ;
    156
    157	for (i = 0, evc = smc->evcs ; i < MAX_EVCS ; i++, evc++) {
    158		if (evc->evc_code == code && evc->evc_index == index)
    159			return evc;
    160	}
    161	return NULL;
    162}
    163
    164#define THRESHOLD_2	(2*TICKS_PER_SECOND)
    165#define THRESHOLD_32	(32*TICKS_PER_SECOND)
    166
    167static const char * const srf_names[] = {
    168	"None","MACPathChangeEvent",	"MACNeighborChangeEvent",
    169	"PORTPathChangeEvent",		"PORTUndesiredConnectionAttemptEvent",
    170	"SMTPeerWrapCondition",		"SMTHoldCondition",
    171	"MACFrameErrorCondition",	"MACDuplicateAddressCondition",
    172	"MACNotCopiedCondition",	"PORTEBErrorCondition",
    173	"PORTLerCondition"
    174} ;
    175
    176void smt_srf_event(struct s_smc *smc, int code, int index, int cond)
    177{
    178	struct s_srf_evc	*evc ;
    179	int			cond_asserted = 0 ;
    180	int			cond_deasserted = 0 ;
    181	int			event_occurred = 0 ;
    182	int			tsr ;
    183	int			T_Limit = 2*TICKS_PER_SECOND ;
    184
    185	if (code == SMT_COND_MAC_DUP_ADDR && cond) {
    186		RS_SET(smc,RS_DUPADDR) ;
    187	}
    188
    189	if (code) {
    190		DB_SMT("SRF: %s index %d", srf_names[code], index);
    191
    192		if (!(evc = smt_get_evc(smc,code,index))) {
    193			DB_SMT("SRF : smt_get_evc() failed");
    194			return ;
    195		}
    196		/*
    197		 * ignore condition if no change
    198		 */
    199		if (SMT_IS_CONDITION(code)) {
    200			if (*evc->evc_cond_state == cond)
    201				return ;
    202		}
    203
    204		/*
    205		 * set transition time stamp
    206		 */
    207		smt_set_timestamp(smc,smc->mib.fddiSMTTransitionTimeStamp) ;
    208		if (SMT_IS_CONDITION(code)) {
    209			DB_SMT("SRF: condition is %s", cond ? "ON" : "OFF");
    210			if (cond) {
    211				*evc->evc_cond_state = TRUE ;
    212				evc->evc_rep_required = TRUE ;
    213				smc->srf.any_report = TRUE ;
    214				cond_asserted = TRUE ;
    215			}
    216			else {
    217				*evc->evc_cond_state = FALSE ;
    218				cond_deasserted = TRUE ;
    219			}
    220		}
    221		else {
    222			if (evc->evc_rep_required) {
    223				*evc->evc_multiple  = TRUE ;
    224			}
    225			else {
    226				evc->evc_rep_required = TRUE ;
    227				*evc->evc_multiple  = FALSE ;
    228			}
    229			smc->srf.any_report = TRUE ;
    230			event_occurred = TRUE ;
    231		}
    232#ifdef	FDDI_MIB
    233		snmp_srf_event(smc,evc) ;
    234#endif	/* FDDI_MIB */
    235	}
    236	tsr = smt_get_time() - smc->srf.TSR ;
    237
    238	switch (smc->srf.sr_state) {
    239	case SR0_WAIT :
    240		/* SR01a */
    241		if (cond_asserted && tsr < T_Limit) {
    242			smc->srf.SRThreshold = THRESHOLD_2 ;
    243			smc->srf.sr_state = SR1_HOLDOFF ;
    244			break ;
    245		}
    246		/* SR01b */
    247		if (cond_deasserted && tsr < T_Limit) {
    248			smc->srf.sr_state = SR1_HOLDOFF ;
    249			break ;
    250		}
    251		/* SR01c */
    252		if (event_occurred && tsr < T_Limit) {
    253			smc->srf.sr_state = SR1_HOLDOFF ;
    254			break ;
    255		}
    256		/* SR00b */
    257		if (cond_asserted && tsr >= T_Limit) {
    258			smc->srf.SRThreshold = THRESHOLD_2 ;
    259			smc->srf.TSR = smt_get_time() ;
    260			smt_send_srf(smc) ;
    261			break ;
    262		}
    263		/* SR00c */
    264		if (cond_deasserted && tsr >= T_Limit) {
    265			smc->srf.TSR = smt_get_time() ;
    266			smt_send_srf(smc) ;
    267			break ;
    268		}
    269		/* SR00d */
    270		if (event_occurred && tsr >= T_Limit) {
    271			smc->srf.TSR = smt_get_time() ;
    272			smt_send_srf(smc) ;
    273			break ;
    274		}
    275		/* SR00e */
    276		if (smc->srf.any_report && (u_long) tsr >=
    277			smc->srf.SRThreshold) {
    278			smc->srf.SRThreshold *= 2 ;
    279			if (smc->srf.SRThreshold > THRESHOLD_32)
    280				smc->srf.SRThreshold = THRESHOLD_32 ;
    281			smc->srf.TSR = smt_get_time() ;
    282			smt_send_srf(smc) ;
    283			break ;
    284		}
    285		/* SR02 */
    286		if (!smc->mib.fddiSMTStatRptPolicy) {
    287			smc->srf.sr_state = SR2_DISABLED ;
    288			break ;
    289		}
    290		break ;
    291	case SR1_HOLDOFF :
    292		/* SR10b */
    293		if (tsr >= T_Limit) {
    294			smc->srf.sr_state = SR0_WAIT ;
    295			smc->srf.TSR = smt_get_time() ;
    296			smt_send_srf(smc) ;
    297			break ;
    298		}
    299		/* SR11a */
    300		if (cond_asserted) {
    301			smc->srf.SRThreshold = THRESHOLD_2 ;
    302		}
    303		/* SR11b */
    304		/* SR11c */
    305		/* handled above */
    306		/* SR12 */
    307		if (!smc->mib.fddiSMTStatRptPolicy) {
    308			smc->srf.sr_state = SR2_DISABLED ;
    309			break ;
    310		}
    311		break ;
    312	case SR2_DISABLED :
    313		if (smc->mib.fddiSMTStatRptPolicy) {
    314			smc->srf.sr_state = SR0_WAIT ;
    315			smc->srf.TSR = smt_get_time() ;
    316			smc->srf.SRThreshold = THRESHOLD_2 ;
    317			clear_all_rep(smc) ;
    318			break ;
    319		}
    320		break ;
    321	}
    322}
    323
    324static void clear_all_rep(struct s_smc *smc)
    325{
    326	struct s_srf_evc	*evc ;
    327	unsigned int		i ;
    328
    329	for (i = 0, evc = smc->evcs ; i < MAX_EVCS ; i++, evc++) {
    330		evc->evc_rep_required = FALSE ;
    331		if (SMT_IS_CONDITION(evc->evc_code))
    332			*evc->evc_cond_state = FALSE ;
    333	}
    334	smc->srf.any_report = FALSE ;
    335}
    336
    337static void clear_reported(struct s_smc *smc)
    338{
    339	struct s_srf_evc	*evc ;
    340	unsigned int		i ;
    341
    342	smc->srf.any_report = FALSE ;
    343	for (i = 0, evc = smc->evcs ; i < MAX_EVCS ; i++, evc++) {
    344		if (SMT_IS_CONDITION(evc->evc_code)) {
    345			if (*evc->evc_cond_state == FALSE)
    346				evc->evc_rep_required = FALSE ;
    347			else
    348				smc->srf.any_report = TRUE ;
    349		}
    350		else {
    351			evc->evc_rep_required = FALSE ;
    352			*evc->evc_multiple = FALSE ;
    353		}
    354	}
    355}
    356
    357/*
    358 * build and send SMT SRF frame
    359 */
    360static void smt_send_srf(struct s_smc *smc)
    361{
    362
    363	struct smt_header	*smt ;
    364	struct s_srf_evc	*evc ;
    365	SK_LOC_DECL(struct s_pcon,pcon) ;
    366	SMbuf			*mb ;
    367	unsigned int		i ;
    368
    369	static const struct fddi_addr SMT_SRF_DA = {
    370		{ 0x80, 0x01, 0x43, 0x00, 0x80, 0x08 }
    371	} ;
    372
    373	/*
    374	 * build SMT header
    375	 */
    376	if (!smc->r.sm_ma_avail)
    377		return ;
    378	if (!(mb = smt_build_frame(smc,SMT_SRF,SMT_ANNOUNCE,0)))
    379		return ;
    380
    381	RS_SET(smc,RS_SOFTERROR) ;
    382
    383	smt = smtod(mb, struct smt_header *) ;
    384	smt->smt_dest = SMT_SRF_DA ;		/* DA == SRF multicast */
    385
    386	/*
    387	 * setup parameter status
    388	 */
    389	pcon.pc_len = SMT_MAX_INFO_LEN ;	/* max para length */
    390	pcon.pc_err = 0 ;			/* no error */
    391	pcon.pc_badset = 0 ;			/* no bad set count */
    392	pcon.pc_p = (void *) (smt + 1) ;	/* paras start here */
    393
    394	smt_add_para(smc,&pcon,(u_short) SMT_P1033,0,0) ;
    395	smt_add_para(smc,&pcon,(u_short) SMT_P1034,0,0) ;
    396
    397	for (i = 0, evc = smc->evcs ; i < MAX_EVCS ; i++, evc++) {
    398		if (evc->evc_rep_required) {
    399			smt_add_para(smc,&pcon,evc->evc_para,
    400				(int)evc->evc_index,0) ;
    401		}
    402	}
    403	smt->smt_len = SMT_MAX_INFO_LEN - pcon.pc_len ;
    404	mb->sm_len = smt->smt_len + sizeof(struct smt_header) ;
    405
    406	DB_SMT("SRF: sending SRF at %p, len %d", smt, mb->sm_len);
    407	DB_SMT("SRF: state SR%d Threshold %lu",
    408	       smc->srf.sr_state, smc->srf.SRThreshold / TICKS_PER_SECOND);
    409#ifdef	DEBUG
    410	dump_smt(smc,smt,"SRF Send") ;
    411#endif
    412	smt_send_frame(smc,mb,FC_SMT_INFO,0) ;
    413	clear_reported(smc) ;
    414}
    415
    416#endif	/* no BOOT */
    417#endif	/* no SLIM_SMT */
    418