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