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/* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27#pragma ident "%Z%%M% %I% %E% SMI" 28 29#if !defined(lint) 30#include <sys/asm_linkage.h> 31#include "assym.h" 32#endif 33 34#include <sys/sun4asi.h> 35#include <sys/machparam.h> 36#include <vm/hat_sfmmu.h> 37 38/* 39 * This file contains a kmdb-support function which retrieves the TTE for a 40 * given VA/context pair, and returns it to the caller if the TTE is valid. 41 * The code here is essentially an assembly implementation of the unix-tte 42 * word used to allow OBP to do the same thing. 43 * 44 * Depending on the invocation context, the translator may be invoked either 45 * as a normal function (kdi_vatotte) or as a trap handler fragment 46 * (kdi_trap_vatotte). 47 */ 48 49/* 50 * uint64_t 51 * kdi_hme_hash_function(sfmmu_t *sfmmup, uintptr_t va, uint_t hmeshift) 52 * { 53 * uintptr_t hash = (uintptr_t)sfmmup ^ (va >> hmeshift); 54 * 55 * if (sfmmup == KHATID) { 56 * return (khme_hash_pa + (hash & KHMEHASH_SZ) * 57 * sizeof (struct hmehash_bucket)); 58 * } else { 59 * return (uhme_hash_pa + (hash & UHMEHASH_SZ) * 60 * sizeof (struct hmehash_bucket)); 61 * } 62 * } 63 */ 64 65/* 66 * Parameters: %g1: VA, %g2: sfmmup, %g4: hmeshift 67 * Scratch: %g4, %g5, %g6 available 68 * Return: Hash value in %g4 69 */ 70 71#define KDI_HME_HASH_FUNCTION \ 72 srlx %g1, %g4, %g4; /* va >> hmeshift */ \ 73 xor %g4, %g2, %g4; /* hash in g4 */ \ 74 set KHATID, %g5; \ 75 ldx [%g5], %g5; \ 76 cmp %g2, %g5; \ 77 be %xcc, is_khat; \ 78 nop; \ 79 \ 80 /* sfmmup != KHATID */ \ 81 set UHMEHASH_SZ, %g5; \ 82 ld [%g5], %g5; \ 83 and %g4, %g5, %g4; \ 84 mulx %g4, HMEBUCK_SIZE, %g4; /* g4 = off from hash_pa */ \ 85 set uhme_hash_pa, %g5; \ 86 ldx [%g5], %g5; \ 87 ba hash_done; \ 88 add %g4, %g5, %g4; \ 89 \ 90is_khat: /* sfmmup == KHATID */ \ 91 set KHMEHASH_SZ, %g5; \ 92 ld [%g5], %g5; \ 93 and %g4, %g5, %g4; \ 94 mulx %g4, HMEBUCK_SIZE, %g4; /* g4 = off from hash_pa */ \ 95 set khme_hash_pa, %g5; \ 96 ldx [%g5], %g5; \ 97 add %g4, %g5, %g4; \ 98 \ 99hash_done: 100 101/* 102 * uint64_t 103 * kdi_hme_hash_tag(uint64_t rehash, uintptr_t va) 104 * { 105 * uint_t hmeshift = HME_HASH_SHIFT(rehash); 106 * uint64_t bspage = HME_HASH_BSPAGE(va, hmeshift); 107 * return (rehash | (bspage << HTAG_REHASHSZ)); 108 * } 109 */ 110 111/* 112 * Parameters: %g1: VA, %g3: rehash 113 * Scratch: %g5, %g6 available 114 * Return: hmeblk tag in %g5 115 */ 116 117#define KDI_HME_HASH_TAG \ 118 cmp %g3, TTE8K; \ 119 be,a %xcc, bspage; \ 120 mov HBLK_RANGE_SHIFT, %g5; \ 121 mulx %g3, 3, %g5; \ 122 add %g5, MMU_PAGESHIFT, %g5; \ 123 \ 124bspage: /* TTE_PAGE_SHIFT in %g5 */ \ 125 srlx %g1, %g5, %g6; \ 126 sub %g5, MMU_PAGESHIFT, %g5; \ 127 sllx %g6, %g5, %g5; \ 128 \ 129 /* BSPAGE in %g5 */ \ 130 sllx %g5, HTAG_REHASHSZ, %g5; \ 131 or %g5, %g3, %g5 132 133/* 134 * uint64_t 135 * kdi_hme_hash_table_search(sfmmu_t *sfmmup, uint64_t hmebpa, uint64_t hblktag) 136 * { 137 * struct hme_blk *hblkp; 138 * uint64_t blkpap = hmebpa + HMEBP_HBLK; 139 * uint64_t blkpa; 140 * 141 * while ((blkpa = lddphys(blkpap)) != NULL) { 142 * if (lddphys(blkpa + HMEBLK_TAG) == hblktag) { 143 * if ((sfmmu_t *)lddphys(blkpa + HMEBLK_TAG + 8) == 144 * sfmmup) 145 * return (blkpa); 146 * } 147 * 148 * blkpap = blkpa + HMEBLK_NEXTPA; 149 * } 150 * 151 * return (NULL); 152 * } 153 */ 154 155/* 156 * Parameters: %g2: sfmmup, %g4: hmebp PA, %g5: hmeblk tag 157 * Scratch: %g4, %g5, %g6 available 158 * Return: hmeblk PA in %g4 159 */ 160 161#define KDI_HME_HASH_TABLE_SEARCH \ 162 add %g4, HMEBUCK_NEXTPA, %g4; /* %g4 is hmebucket PA */ \ 163search_loop: \ 164 ldxa [%g4]ASI_MEM, %g4; \ 165 brz %g4, search_done; \ 166 nop; \ 167 \ 168 add %g4, HMEBLK_TAG, %g4; /* %g4 is now hmeblk PA */ \ 169 ldxa [%g4]ASI_MEM, %g6; \ 170 sub %g4, HMEBLK_TAG, %g4; \ 171 cmp %g5, %g6; \ 172 bne,a %xcc, search_loop; \ 173 add %g4, HMEBLK_NEXTPA, %g4; \ 174 \ 175 /* Found a match. Is it in the right address space? */ \ 176 add %g4, (HMEBLK_TAG + 8), %g4; \ 177 ldxa [%g4]ASI_MEM, %g6; \ 178 sub %g4, (HMEBLK_TAG + 8), %g4; \ 179 cmp %g6, %g2; \ 180 bne,a %xcc, search_loop; \ 181 add %g4, HMEBLK_NEXTPA, %g4; \ 182 \ 183search_done: 184 185/* 186 * uint64_t 187 * kdi_hblk_to_ttep(uint64_t hmeblkpa, uintptr_t va) 188 * { 189 * size_t ttesz = ldphys(hmeblkpa + HMEBLK_MISC) & HBLK_SZMASK; 190 * uint_t idx; 191 * 192 * if (ttesz == TTE8K) 193 * idx = (va >> MMU_PAGESHIFT) & (NHMENTS - 1); 194 * else 195 * idx = 0; 196 * 197 * return (hmeblkpa + (idx * sizeof (struct sf_hment)) + 198 * HMEBLK_HME + SFHME_TTE); 199 * } 200 */ 201 202/* 203 * Parameters: %g1: VA, %g4: hmeblk PA 204 * Scratch: %g1, %g2, %g3, %g4, %g5, %g6 available 205 * Return: TTE PA in %g2 206 */ 207 208#define KDI_HBLK_TO_TTEP \ 209 add %g4, HMEBLK_MISC, %g3; \ 210 lda [%g3]ASI_MEM, %g3; \ 211 and %g3, HBLK_SZMASK, %g3; /* ttesz in %g3 */ \ 212 \ 213 cmp %g3, TTE8K; \ 214 bne,a ttep_calc; \ 215 clr %g1; \ 216 srlx %g1, MMU_PAGESHIFT, %g1; \ 217 and %g1, NHMENTS - 1, %g1; \ 218 \ 219ttep_calc: /* idx in %g1 */ \ 220 mulx %g1, SFHME_SIZE, %g2; \ 221 add %g2, %g4, %g2; \ 222 add %g2, (HMEBLK_HME1 + SFHME_TTE), %g2; 223 224/* 225 * uint64_t 226 * kdi_vatotte(uintptr_t va, int cnum) 227 * { 228 * sfmmu_t *sfmmup = ctxs[cnum].ctx_sfmmu; 229 * uint64_t hmebpa, hmetag, hmeblkpa; 230 * int i; 231 * 232 * for (i = 1; i < DEFAULT_MAX_HASHCNT + 1; i++) { 233 * hmebpa = kdi_c_hme_hash_function(sfmmup, va, HME_HASH_SHIFT(i)); 234 * hmetag = kdi_c_hme_hash_tag(i, va); 235 * hmeblkpa = kdi_c_hme_hash_table_search(sfmmup, hmebpa, hmetag); 236 * 237 * if (hmeblkpa != NULL) { 238 * uint64_t tte = lddphys(kdi_c_hblk_to_ttep(hmeblkpa, 239 * va)); 240 * 241 * if ((int64_t)tte < 0) 242 * return (tte); 243 * else 244 * return (0); 245 * } 246 * } 247 * 248 * return (0); 249 * } 250 */ 251 252#if defined(lint) 253/*ARGSUSED*/ 254int 255kdi_vatotte(uintptr_t va, int cnum, tte_t *ttep) 256{ 257 return (0); 258} 259 260void 261kdi_trap_vatotte(void) 262{ 263} 264 265#else 266 267 /* 268 * Invocation in normal context as a VA-to-TTE translator. 269 */ 270 ENTRY_NP(kdi_vatotte) 271 mov %o0, %g1 /* VA in %g1 */ 272 mov %o1, %g2 /* cnum in %g2 */ 273 274 set kdi_trap_vatotte, %g3 275 jmpl %g3, %g7 /* => %g1: TTE or 0 */ 276 add %g7, 8, %g7 277 278 brz %g1, 1f 279 nop 280 281 /* Got a valid TTE */ 282 stx %g1, [%o2] 283 retl 284 clr %o0 285 286 /* Failed translation */ 2871: retl 288 mov -1, %o0 289 SET_SIZE(kdi_vatotte) 290 291 ENTRY_NP(kdi_trap_vatotte) 292 set nctxs, %g3 293 ld [%g3], %g3 294 cmp %g2, %g3 295 bge,a %xcc, 6f 296 clr %g1 297 298 set ctxs, %g3 299 ldx [%g3], %g3 300 mulx %g2, CTX_SIZE, %g2 301 add %g2, %g3, %g2 302 add %g2, CTX_SFMMUP, %g2 303 ldx [%g2], %g2 /* VA %g1, sfmmup %g2 */ 304 305 mov 1, %g3 /* VA %g1, sfmmup %g2, idx %g3 */ 306 mov HBLK_RANGE_SHIFT, %g4 307 ba 3f 308 nop 309 3101: mulx %g3, 3, %g4 /* 3: see TTE_BSZS_SHIFT */ 311 add %g4, MMU_PAGESHIFT, %g4 312 3133: KDI_HME_HASH_FUNCTION /* %g1, %g2, %g4 => hash in %g4 */ 314 KDI_HME_HASH_TAG /* %g1, %g3 => tag in %g5 */ 315 KDI_HME_HASH_TABLE_SEARCH /* %g2, %g4, %g5 => hmeblk PA in %g4 */ 316 317 brz %g4, 5f 318 nop 319 320 KDI_HBLK_TO_TTEP /* %g1, %g4 => TTE PA in %g2 */ 321 ldxa [%g2]ASI_MEM, %g1 322 brgez,a %g1, 4f 323 clr %g1 3244: ba,a 6f 325 3265: add %g3, 1, %g3 327 set mmu_hashcnt, %g4 328 lduw [%g4], %g4 329 cmp %g3, %g4 330 ble 1b 331 nop 332 333 clr %g1 334 3356: jmp %g7 336 nop 337 SET_SIZE(kdi_trap_vatotte) 338 339#endif /* lint */ 340