1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #ifndef _SYS_TRAPSTAT_H 27 #define _SYS_TRAPSTAT_H 28 29 #ifndef _ASM 30 #include <sys/processor.h> 31 #endif 32 33 #ifdef __cplusplus 34 extern "C" { 35 #endif 36 37 #define TSTATIOC (('t' << 16) | ('s' << 8)) 38 39 #define TSTATIOC_READ (TSTATIOC | 1) 40 #define TSTATIOC_GO (TSTATIOC | 2) 41 #define TSTATIOC_NOGO (TSTATIOC | 3) 42 #define TSTATIOC_STOP (TSTATIOC | 4) 43 #define TSTATIOC_CPU (TSTATIOC | 5) 44 #define TSTATIOC_NOCPU (TSTATIOC | 6) 45 #define TSTATIOC_ENTRY (TSTATIOC | 7) 46 #define TSTATIOC_NOENTRY (TSTATIOC | 8) 47 #define TSTATIOC_TLBDATA (TSTATIOC | 9) 48 49 #define TSTAT_NENT 512 50 51 #ifndef _ASM 52 53 /* 54 * tstat_missdata_t must be of size 2^n, for some value of n. This allows 55 * tstat_tlbdata_t to be of size 2^(n+2), and tstat_pgszdata_t to be of 56 * size 2^(n+3) -- a constraint which greatly simplifies the TLB return 57 * entry. 58 */ 59 typedef struct tstat_missdata { 60 uint64_t tmiss_count; 61 hrtime_t tmiss_time; 62 } tstat_missdata_t; 63 64 typedef struct tstat_tlbdata { 65 tstat_missdata_t ttlb_tlb; 66 tstat_missdata_t ttlb_tsb; 67 } tstat_tlbdata_t; 68 69 typedef struct tstat_modedata { 70 tstat_tlbdata_t tmode_itlb; 71 tstat_tlbdata_t tmode_dtlb; 72 } tstat_modedata_t; 73 74 typedef struct tstat_pgszdata { 75 tstat_modedata_t tpgsz_user; 76 tstat_modedata_t tpgsz_kernel; 77 } tstat_pgszdata_t; 78 79 #ifdef sun4v 80 /* 81 * For sun4v, we optimized by using a smaller 4K data area 82 * per-cpu. We use separate structures for data collection, 83 * one for normal trapstat collection and one for collecting 84 * TLB stats. Note that we either collect normal trapstats 85 * or TLB stats, never both. For TLB stats, we are only 86 * interested in the MMU/TLB miss traps (which are trap #s 87 * 0x9, 0x32, 0x64 & 0x68) 88 */ 89 #define TSTAT_TLB_NENT 200 /* max trap entries for tlb stats */ 90 91 typedef struct tstat_ndata { 92 uint64_t tdata_traps[TSTAT_NENT]; 93 } tstat_ndata_t; 94 95 typedef struct tstat_tdata { 96 uint64_t tdata_traps[TSTAT_TLB_NENT]; 97 hrtime_t tdata_tmptick; 98 tstat_pgszdata_t tdata_pgsz[1]; 99 } tstat_tdata_t; 100 #endif /* sun4v */ 101 102 typedef struct tstat_data { 103 processorid_t tdata_cpuid; 104 hrtime_t tdata_snapts; 105 hrtime_t tdata_snaptick; 106 hrtime_t tdata_tmptick; 107 hrtime_t tdata_peffect; 108 uint64_t tdata_traps[TSTAT_NENT]; 109 tstat_pgszdata_t tdata_pgsz[1]; 110 } tstat_data_t; 111 112 #endif 113 114 #ifdef _KERNEL 115 116 #define TSTAT_TLGT0_NENT 256 117 #define TSTAT_TOTAL_NENT (TSTAT_NENT + TSTAT_TLGT0_NENT) 118 119 #define TSTAT_ENT_NINSTR 8 /* 8 instructions/entry */ 120 #define TSTAT_ENT_SHIFT 5 /* 32 bytes/entry */ 121 #define TSTAT_ENT_ITLBMISS 0x64 122 #define TSTAT_ENT_DTLBMISS 0x68 123 124 #define TSTAT_TLBRET_NINSTR 32 125 126 #define TSTAT_PROBE_NPAGES 2048 127 #define TSTAT_PROBE_SIZE (TSTAT_PROBE_NPAGES * MMU_PAGESIZE) 128 #define TSTAT_PROBE_NLAPS 10 129 130 #ifdef sun4v 131 #define TSTAT_TRAPCNT_NINSTR 8 132 #define TSTAT_TLBENT_NINSTR 64 133 #define TSTAT_ENT_IMMUMISS 0x09 134 #define TSTAT_ENT_DMMUMISS 0x31 135 #endif 136 137 #ifndef _ASM 138 139 typedef struct tstat_tlbretent { 140 uint32_t ttlbrent_instr[TSTAT_TLBRET_NINSTR]; 141 } tstat_tlbretent_t; 142 143 #ifdef sun4v 144 typedef struct tstat_tlbent { 145 uint32_t ttlbent_instr[TSTAT_TLBENT_NINSTR]; 146 } tstat_tlbent_t; 147 #endif /* sun4v */ 148 149 150 typedef struct tstat_tlbret { 151 tstat_tlbretent_t ttlbr_ktlb; 152 tstat_tlbretent_t ttlbr_ktsb; 153 tstat_tlbretent_t ttlbr_utlb; 154 tstat_tlbretent_t ttlbr_utsb; 155 } tstat_tlbret_t; 156 157 typedef struct tstat_instr { 158 uint32_t tinst_traptab[TSTAT_TOTAL_NENT * TSTAT_ENT_NINSTR]; 159 tstat_tlbret_t tinst_itlbret; 160 tstat_tlbret_t tinst_dtlbret; 161 #ifdef sun4v 162 tstat_tlbent_t tinst_immumiss; 163 tstat_tlbent_t tinst_dmmumiss; 164 uint32_t tinst_trapcnt[TSTAT_TRAPCNT_NINSTR]; 165 #endif 166 } tstat_instr_t; 167 168 typedef struct tstat_tsbmiss_patch_entry { 169 uint32_t *tpe_addr; 170 uint32_t tpe_instr; 171 } tstat_tsbmiss_patch_entry_t; 172 173 #endif 174 175 #ifdef sun4v 176 177 #define TSTAT_TLB_STATS 0x1 /* cpu_tstat_flags */ 178 #define TSTAT_INSTR_SIZE \ 179 ((sizeof (tstat_instr_t) + MMU_PAGESIZE - 1) & ~(MMU_PAGESIZE - 1)) 180 #define TSTAT_DATA_SHIFT 12 181 #define TSTAT_DATA_SIZE (1 << TSTAT_DATA_SHIFT) /* 4K per CPU */ 182 #define TSTAT_TBA_MASK ~((1 << 15) - 1) /* 32K boundary */ 183 184 #define TSTAT_CPU0_DATA_OFFS(tcpu, mem) \ 185 ((uintptr_t)(tcpu)->tcpu_ibase + TSTAT_INSTR_SIZE + \ 186 offsetof(tstat_ndata_t, mem)) 187 188 #define TSTAT_CPU0_TLBDATA_OFFS(tcpu, mem) \ 189 ((uintptr_t)(tcpu)->tcpu_ibase + TSTAT_INSTR_SIZE + \ 190 offsetof(tstat_tdata_t, mem)) 191 192 /* 193 * Sun4v trapstat can use up to 3 4MB pages to support 194 * 3064 cpus. Each cpu needs 4K of data page for stats collection. 195 * The first 32K (TSTAT_TRAPTBLE_SIZE) in the first 4 MB page is 196 * use for the traptable leaving 4MB - 32K = 4064K for cpu data 197 * which work out to be 4064/4K = 1016 cpus. Each additional 198 * 4MB page (2nd and 3rd ones) can support 4096/4 = 1024 cpus. 199 * This works out to be a total of 1016 + 1024 + 1024 = 3064 cpus. 200 */ 201 #define ROUNDUP(a, n) (((a) + ((n) - 1)) & ~((n) - 1)) 202 #define TSTAT_MAXNUM4M_MAPPING 3 203 #define TSTAT_TRAPTBL_SIZE (32 * 1024) 204 #define TSTAT_NUM4M_LIMIT \ 205 (ROUNDUP((NCPU * TSTAT_DATA_SIZE) + TSTAT_TRAPTBL_SIZE, \ 206 MMU_PAGESIZE4M) >> MMU_PAGESHIFT4M) 207 208 #if (TSTAT_NUM4M_LIMIT > TSTAT_MAXNUM4M_MAPPING) 209 #error "NCPU is too large for trapstat" 210 #endif 211 212 /* 213 * Note that the macro below is almost identical to the 214 * one for TSTAT_NUM4M_LIMIT with one difference. Instead of 215 * using TSTAT_TRAPTBL_SIZE constant, it uses TSTAT_INSTR_SIZE which 216 * has a runtime sizeof() expression. The result should be 217 * the same. This macro is used at runtime as an extra 218 * validation for correctness. 219 */ 220 #define TSTAT_NUM4M_MACRO(ncpu) \ 221 (ROUNDUP(((ncpu) * TSTAT_DATA_SIZE) + TSTAT_INSTR_SIZE, \ 222 MMU_PAGESIZE4M) >> MMU_PAGESHIFT4M) 223 224 #else /* sun4v */ 225 226 #define TSTAT_INSTR_PAGES ((sizeof (tstat_instr_t) >> MMU_PAGESHIFT) + 1) 227 #define TSTAT_INSTR_SIZE (TSTAT_INSTR_PAGES * MMU_PAGESIZE) 228 #define TSTAT_TBA_MASK ~((1 << 16) - 1) /* 64K per cpu */ 229 230 #define TSTAT_DATA_OFFS(tcpu, mem) \ 231 ((uintptr_t)(tcpu)->tcpu_dbase + offsetof(tstat_data_t, mem)) 232 233 #endif /* sun4v */ 234 235 #define TSTAT_INSTR_OFFS(tcpu, mem) \ 236 ((uintptr_t)(tcpu)->tcpu_ibase + offsetof(tstat_instr_t, mem)) 237 238 #define TSTAT_CPU_SELECTED 0x0001 239 #define TSTAT_CPU_ALLOCATED 0x0002 240 #define TSTAT_CPU_ENABLED 0x0004 241 242 #define TSTAT_OPT_CPU 0x0001 243 #define TSTAT_OPT_NOGO 0x0002 244 #define TSTAT_OPT_TLBDATA 0x0004 245 #define TSTAT_OPT_ENTRY 0x0008 246 247 #define TSTAT_TSBMISS_INSTR 0x8e01e000 /* add %g7, 0, %g7 */ 248 249 #ifndef _ASM 250 251 typedef struct tstat_percpu { 252 uint32_t tcpu_flags; 253 caddr_t tcpu_tba; 254 caddr_t tcpu_vabase; 255 caddr_t tcpu_ibase; 256 caddr_t tcpu_dbase; 257 pfn_t *tcpu_pfn; 258 tstat_instr_t *tcpu_instr; 259 tstat_data_t *tcpu_data; 260 #ifdef sun4v 261 hrtime_t tcpu_tdata_peffect; 262 #endif /* sun4v */ 263 } tstat_percpu_t; 264 265 #endif 266 267 #endif 268 #ifdef __cplusplus 269 } 270 #endif 271 272 #endif /* _SYS_TRAPSTAT_H */ 273