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

cpu_mf.h (9620B)


      1/* SPDX-License-Identifier: GPL-2.0 */
      2/*
      3 * CPU-measurement facilities
      4 *
      5 *  Copyright IBM Corp. 2012, 2018
      6 *  Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
      7 *	       Jan Glauber <jang@linux.vnet.ibm.com>
      8 */
      9#ifndef _ASM_S390_CPU_MF_H
     10#define _ASM_S390_CPU_MF_H
     11
     12#include <linux/errno.h>
     13#include <asm/asm-extable.h>
     14#include <asm/facility.h>
     15
     16asm(".include \"asm/cpu_mf-insn.h\"\n");
     17
     18#define CPU_MF_INT_SF_IAE	(1 << 31)	/* invalid entry address */
     19#define CPU_MF_INT_SF_ISE	(1 << 30)	/* incorrect SDBT entry */
     20#define CPU_MF_INT_SF_PRA	(1 << 29)	/* program request alert */
     21#define CPU_MF_INT_SF_SACA	(1 << 23)	/* sampler auth. change alert */
     22#define CPU_MF_INT_SF_LSDA	(1 << 22)	/* loss of sample data alert */
     23#define CPU_MF_INT_CF_MTDA	(1 << 15)	/* loss of MT ctr. data alert */
     24#define CPU_MF_INT_CF_CACA	(1 <<  7)	/* counter auth. change alert */
     25#define CPU_MF_INT_CF_LCDA	(1 <<  6)	/* loss of counter data alert */
     26#define CPU_MF_INT_CF_MASK	(CPU_MF_INT_CF_MTDA|CPU_MF_INT_CF_CACA| \
     27				 CPU_MF_INT_CF_LCDA)
     28#define CPU_MF_INT_SF_MASK	(CPU_MF_INT_SF_IAE|CPU_MF_INT_SF_ISE|	\
     29				 CPU_MF_INT_SF_PRA|CPU_MF_INT_SF_SACA|	\
     30				 CPU_MF_INT_SF_LSDA)
     31
     32#define CPU_MF_SF_RIBM_NOTAV	0x1		/* Sampling unavailable */
     33
     34/* CPU measurement facility support */
     35static inline int cpum_cf_avail(void)
     36{
     37	return test_facility(40) && test_facility(67);
     38}
     39
     40static inline int cpum_sf_avail(void)
     41{
     42	return test_facility(40) && test_facility(68);
     43}
     44
     45
     46struct cpumf_ctr_info {
     47	u16   cfvn;
     48	u16   auth_ctl;
     49	u16   enable_ctl;
     50	u16   act_ctl;
     51	u16   max_cpu;
     52	u16   csvn;
     53	u16   max_cg;
     54	u16   reserved1;
     55	u32   reserved2[12];
     56} __packed;
     57
     58/* QUERY SAMPLING INFORMATION block */
     59struct hws_qsi_info_block {	    /* Bit(s) */
     60	unsigned int b0_13:14;	    /* 0-13: zeros			 */
     61	unsigned int as:1;	    /* 14: basic-sampling authorization	 */
     62	unsigned int ad:1;	    /* 15: diag-sampling authorization	 */
     63	unsigned int b16_21:6;	    /* 16-21: zeros			 */
     64	unsigned int es:1;	    /* 22: basic-sampling enable control */
     65	unsigned int ed:1;	    /* 23: diag-sampling enable control	 */
     66	unsigned int b24_29:6;	    /* 24-29: zeros			 */
     67	unsigned int cs:1;	    /* 30: basic-sampling activation control */
     68	unsigned int cd:1;	    /* 31: diag-sampling activation control */
     69	unsigned int bsdes:16;	    /* 4-5: size of basic sampling entry */
     70	unsigned int dsdes:16;	    /* 6-7: size of diagnostic sampling entry */
     71	unsigned long min_sampl_rate; /* 8-15: minimum sampling interval */
     72	unsigned long max_sampl_rate; /* 16-23: maximum sampling interval*/
     73	unsigned long tear;	    /* 24-31: TEAR contents		 */
     74	unsigned long dear;	    /* 32-39: DEAR contents		 */
     75	unsigned int rsvrd0:24;	    /* 40-42: reserved			 */
     76	unsigned int ribm:8;	    /* 43: Reserved by IBM		 */
     77	unsigned int cpu_speed;     /* 44-47: CPU speed			 */
     78	unsigned long long rsvrd1;  /* 48-55: reserved			 */
     79	unsigned long long rsvrd2;  /* 56-63: reserved			 */
     80} __packed;
     81
     82/* SET SAMPLING CONTROLS request block */
     83struct hws_lsctl_request_block {
     84	unsigned int s:1;	    /* 0: maximum buffer indicator	 */
     85	unsigned int h:1;	    /* 1: part. level reserved for VM use*/
     86	unsigned long long b2_53:52;/* 2-53: zeros			 */
     87	unsigned int es:1;	    /* 54: basic-sampling enable control */
     88	unsigned int ed:1;	    /* 55: diag-sampling enable control	 */
     89	unsigned int b56_61:6;	    /* 56-61: - zeros			 */
     90	unsigned int cs:1;	    /* 62: basic-sampling activation control */
     91	unsigned int cd:1;	    /* 63: diag-sampling activation control  */
     92	unsigned long interval;     /* 8-15: sampling interval		 */
     93	unsigned long tear;	    /* 16-23: TEAR contents		 */
     94	unsigned long dear;	    /* 24-31: DEAR contents		 */
     95	/* 32-63:							 */
     96	unsigned long rsvrd1;	    /* reserved				 */
     97	unsigned long rsvrd2;	    /* reserved				 */
     98	unsigned long rsvrd3;	    /* reserved				 */
     99	unsigned long rsvrd4;	    /* reserved				 */
    100} __packed;
    101
    102struct hws_basic_entry {
    103	unsigned int def:16;	    /* 0-15  Data Entry Format		 */
    104	unsigned int R:4;	    /* 16-19 reserved			 */
    105	unsigned int U:4;	    /* 20-23 Number of unique instruct.  */
    106	unsigned int z:2;	    /* zeros				 */
    107	unsigned int T:1;	    /* 26 PSW DAT mode			 */
    108	unsigned int W:1;	    /* 27 PSW wait state		 */
    109	unsigned int P:1;	    /* 28 PSW Problem state		 */
    110	unsigned int AS:2;	    /* 29-30 PSW address-space control	 */
    111	unsigned int I:1;	    /* 31 entry valid or invalid	 */
    112	unsigned int CL:2;	    /* 32-33 Configuration Level	 */
    113	unsigned int H:1;	    /* 34 Host Indicator		 */
    114	unsigned int LS:1;	    /* 35 Limited Sampling		 */
    115	unsigned int:12;
    116	unsigned int prim_asn:16;   /* primary ASN			 */
    117	unsigned long long ia;	    /* Instruction Address		 */
    118	unsigned long long gpp;     /* Guest Program Parameter		 */
    119	unsigned long long hpp;     /* Host Program Parameter		 */
    120} __packed;
    121
    122struct hws_diag_entry {
    123	unsigned int def:16;	    /* 0-15  Data Entry Format		 */
    124	unsigned int R:15;	    /* 16-19 and 20-30 reserved		 */
    125	unsigned int I:1;	    /* 31 entry valid or invalid	 */
    126	u8	     data[];	    /* Machine-dependent sample data	 */
    127} __packed;
    128
    129struct hws_combined_entry {
    130	struct hws_basic_entry	basic;	/* Basic-sampling data entry */
    131	struct hws_diag_entry	diag;	/* Diagnostic-sampling data entry */
    132} __packed;
    133
    134struct hws_trailer_entry {
    135	union {
    136		struct {
    137			unsigned int f:1;	/* 0 - Block Full Indicator   */
    138			unsigned int a:1;	/* 1 - Alert request control  */
    139			unsigned int t:1;	/* 2 - Timestamp format	      */
    140			unsigned int :29;	/* 3 - 31: Reserved	      */
    141			unsigned int bsdes:16;	/* 32-47: size of basic SDE   */
    142			unsigned int dsdes:16;	/* 48-63: size of diagnostic SDE */
    143		};
    144		unsigned long long flags;	/* 0 - 63: All indicators     */
    145	};
    146	unsigned long long overflow;	 /* 64 - sample Overflow count	      */
    147	unsigned char timestamp[16];	 /* 16 - 31 timestamp		      */
    148	unsigned long long reserved1;	 /* 32 -Reserved		      */
    149	unsigned long long reserved2;	 /*				      */
    150	union {				 /* 48 - reserved for programming use */
    151		struct {
    152			unsigned int clock_base:1; /* in progusage2 */
    153			unsigned long long progusage1:63;
    154			unsigned long long progusage2;
    155		};
    156		unsigned long long progusage[2];
    157	};
    158} __packed;
    159
    160/* Load program parameter */
    161static inline void lpp(void *pp)
    162{
    163	asm volatile("lpp 0(%0)\n" :: "a" (pp) : "memory");
    164}
    165
    166/* Query counter information */
    167static inline int qctri(struct cpumf_ctr_info *info)
    168{
    169	int rc = -EINVAL;
    170
    171	asm volatile (
    172		"0:	qctri	%1\n"
    173		"1:	lhi	%0,0\n"
    174		"2:\n"
    175		EX_TABLE(1b, 2b)
    176		: "+d" (rc), "=Q" (*info));
    177	return rc;
    178}
    179
    180/* Load CPU-counter-set controls */
    181static inline int lcctl(u64 ctl)
    182{
    183	int cc;
    184
    185	asm volatile (
    186		"	lcctl	%1\n"
    187		"	ipm	%0\n"
    188		"	srl	%0,28\n"
    189		: "=d" (cc) : "Q" (ctl) : "cc");
    190	return cc;
    191}
    192
    193/* Extract CPU counter */
    194static inline int __ecctr(u64 ctr, u64 *content)
    195{
    196	u64 _content;
    197	int cc;
    198
    199	asm volatile (
    200		"	ecctr	%0,%2\n"
    201		"	ipm	%1\n"
    202		"	srl	%1,28\n"
    203		: "=d" (_content), "=d" (cc) : "d" (ctr) : "cc");
    204	*content = _content;
    205	return cc;
    206}
    207
    208/* Extract CPU counter */
    209static inline int ecctr(u64 ctr, u64 *val)
    210{
    211	u64 content;
    212	int cc;
    213
    214	cc = __ecctr(ctr, &content);
    215	if (!cc)
    216		*val = content;
    217	return cc;
    218}
    219
    220/* Store CPU counter multiple for a particular counter set */
    221enum stcctm_ctr_set {
    222	EXTENDED = 0,
    223	BASIC = 1,
    224	PROBLEM_STATE = 2,
    225	CRYPTO_ACTIVITY = 3,
    226	MT_DIAG = 5,
    227	MT_DIAG_CLEARING = 9,	/* clears loss-of-MT-ctr-data alert */
    228};
    229
    230static __always_inline int stcctm(enum stcctm_ctr_set set, u64 range, u64 *dest)
    231{
    232	int cc;
    233
    234	asm volatile (
    235		"	STCCTM	%2,%3,%1\n"
    236		"	ipm	%0\n"
    237		"	srl	%0,28\n"
    238		: "=d" (cc)
    239		: "Q" (*dest), "d" (range), "i" (set)
    240		: "cc", "memory");
    241	return cc;
    242}
    243
    244/* Query sampling information */
    245static inline int qsi(struct hws_qsi_info_block *info)
    246{
    247	int cc = 1;
    248
    249	asm volatile(
    250		"0:	qsi	%1\n"
    251		"1:	lhi	%0,0\n"
    252		"2:\n"
    253		EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
    254		: "+d" (cc), "+Q" (*info));
    255	return cc ? -EINVAL : 0;
    256}
    257
    258/* Load sampling controls */
    259static inline int lsctl(struct hws_lsctl_request_block *req)
    260{
    261	int cc;
    262
    263	cc = 1;
    264	asm volatile(
    265		"0:	lsctl	0(%1)\n"
    266		"1:	ipm	%0\n"
    267		"	srl	%0,28\n"
    268		"2:\n"
    269		EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
    270		: "+d" (cc), "+a" (req)
    271		: "m" (*req)
    272		: "cc", "memory");
    273
    274	return cc ? -EINVAL : 0;
    275}
    276
    277/* Sampling control helper functions */
    278
    279#include <linux/time.h>
    280
    281static inline unsigned long freq_to_sample_rate(struct hws_qsi_info_block *qsi,
    282						unsigned long freq)
    283{
    284	return (USEC_PER_SEC / freq) * qsi->cpu_speed;
    285}
    286
    287static inline unsigned long sample_rate_to_freq(struct hws_qsi_info_block *qsi,
    288						unsigned long rate)
    289{
    290	return USEC_PER_SEC * qsi->cpu_speed / rate;
    291}
    292
    293#define SDB_TE_ALERT_REQ_MASK	0x4000000000000000UL
    294#define SDB_TE_BUFFER_FULL_MASK 0x8000000000000000UL
    295
    296/* Return TOD timestamp contained in an trailer entry */
    297static inline unsigned long long trailer_timestamp(struct hws_trailer_entry *te)
    298{
    299	/* TOD in STCKE format */
    300	if (te->t)
    301		return *((unsigned long long *) &te->timestamp[1]);
    302
    303	/* TOD in STCK format */
    304	return *((unsigned long long *) &te->timestamp[0]);
    305}
    306
    307/* Return pointer to trailer entry of an sample data block */
    308static inline unsigned long *trailer_entry_ptr(unsigned long v)
    309{
    310	void *ret;
    311
    312	ret = (void *) v;
    313	ret += PAGE_SIZE;
    314	ret -= sizeof(struct hws_trailer_entry);
    315
    316	return (unsigned long *) ret;
    317}
    318
    319/* Return true if the entry in the sample data block table (sdbt)
    320 * is a link to the next sdbt */
    321static inline int is_link_entry(unsigned long *s)
    322{
    323	return *s & 0x1ul ? 1 : 0;
    324}
    325
    326/* Return pointer to the linked sdbt */
    327static inline unsigned long *get_next_sdbt(unsigned long *s)
    328{
    329	return (unsigned long *) (*s & ~0x1ul);
    330}
    331#endif /* _ASM_S390_CPU_MF_H */