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 2007 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_BSPAGE_SHIFT)); 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_BSPAGE_SHIFT, %g5; \ 131 sllx %g3, HTAG_REHASH_SHIFT, %g6; \ 132 or %g6, SFMMU_INVALID_SHMERID, %g6; \ 133 or %g5, %g6, %g5 134 135/* 136 * uint64_t 137 * kdi_hme_hash_table_search(sfmmu_t *sfmmup, uint64_t hmebpa, uint64_t hblktag) 138 * { 139 * struct hme_blk *hblkp; 140 * uint64_t blkpap = hmebpa + HMEBP_HBLK; 141 * uint64_t blkpa; 142 * 143 * while ((blkpa = lddphys(blkpap)) != NULL) { 144 * if (lddphys(blkpa + HMEBLK_TAG) == hblktag) { 145 * if ((sfmmu_t *)lddphys(blkpa + HMEBLK_TAG + 8) == 146 * sfmmup) 147 * return (blkpa); 148 * } 149 * 150 * blkpap = blkpa + HMEBLK_NEXTPA; 151 * } 152 * 153 * return (NULL); 154 * } 155 */ 156 157/* 158 * Parameters: %g2: sfmmup, %g4: hmebp PA, %g5: hmeblk tag 159 * Scratch: %g4, %g5, %g6 available 160 * Return: hmeblk PA in %g4 161 */ 162 163#define KDI_HME_HASH_TABLE_SEARCH \ 164 add %g4, HMEBUCK_NEXTPA, %g4; /* %g4 is hmebucket PA */ \ 165search_loop: \ 166 ldxa [%g4]ASI_MEM, %g4; \ 167 brz %g4, search_done; \ 168 nop; \ 169 \ 170 add %g4, HMEBLK_TAG, %g4; /* %g4 is now hmeblk PA */ \ 171 ldxa [%g4]ASI_MEM, %g6; \ 172 sub %g4, HMEBLK_TAG, %g4; \ 173 cmp %g5, %g6; \ 174 bne,a %xcc, search_loop; \ 175 add %g4, HMEBLK_NEXTPA, %g4; \ 176 \ 177 /* Found a match. Is it in the right address space? */ \ 178 add %g4, (HMEBLK_TAG + 8), %g4; \ 179 ldxa [%g4]ASI_MEM, %g6; \ 180 sub %g4, (HMEBLK_TAG + 8), %g4; \ 181 cmp %g6, %g2; \ 182 bne,a %xcc, search_loop; \ 183 add %g4, HMEBLK_NEXTPA, %g4; \ 184 \ 185search_done: 186 187/* 188 * uint64_t 189 * kdi_hblk_to_ttep(uint64_t hmeblkpa, uintptr_t va) 190 * { 191 * size_t ttesz = ldphys(hmeblkpa + HMEBLK_MISC) & HBLK_SZMASK; 192 * uint_t idx; 193 * 194 * if (ttesz == TTE8K) 195 * idx = (va >> MMU_PAGESHIFT) & (NHMENTS - 1); 196 * else 197 * idx = 0; 198 * 199 * return (hmeblkpa + (idx * sizeof (struct sf_hment)) + 200 * HMEBLK_HME + SFHME_TTE); 201 * } 202 */ 203 204/* 205 * Parameters: %g1: VA, %g4: hmeblk PA 206 * Scratch: %g1, %g2, %g3, %g4, %g5, %g6 available 207 * Return: TTE PA in %g2 208 */ 209 210#define KDI_HBLK_TO_TTEP \ 211 add %g4, HMEBLK_MISC, %g3; \ 212 lda [%g3]ASI_MEM, %g3; \ 213 and %g3, HBLK_SZMASK, %g3; /* ttesz in %g3 */ \ 214 \ 215 cmp %g3, TTE8K; \ 216 bne,a ttep_calc; \ 217 clr %g1; \ 218 srlx %g1, MMU_PAGESHIFT, %g1; \ 219 and %g1, NHMENTS - 1, %g1; \ 220 \ 221ttep_calc: /* idx in %g1 */ \ 222 mulx %g1, SFHME_SIZE, %g2; \ 223 add %g2, %g4, %g2; \ 224 add %g2, (HMEBLK_HME1 + SFHME_TTE), %g2; 225 226/* 227 * uint64_t 228 * kdi_vatotte(uintptr_t va, int cnum) 229 * { 230 * sfmmu_t *sfmmup = ksfmmup; 231 * uint64_t hmebpa, hmetag, hmeblkpa; 232 * int i; 233 * 234 * for (i = 1; i < DEFAULT_MAX_HASHCNT + 1; i++) { 235 * hmebpa = kdi_c_hme_hash_function(sfmmup, va, HME_HASH_SHIFT(i)); 236 * hmetag = kdi_c_hme_hash_tag(i, va); 237 * hmeblkpa = kdi_c_hme_hash_table_search(sfmmup, hmebpa, hmetag); 238 * 239 * if (hmeblkpa != NULL) { 240 * uint64_t tte = lddphys(kdi_c_hblk_to_ttep(hmeblkpa, 241 * va)); 242 * 243 * if ((int64_t)tte < 0) 244 * return (tte); 245 * else 246 * return (0); 247 * } 248 * } 249 * 250 * return (0); 251 * } 252 */ 253 254#if defined(lint) 255/*ARGSUSED*/ 256int 257kdi_vatotte(uintptr_t va, int cnum, tte_t *ttep) 258{ 259 return (0); 260} 261 262void 263kdi_trap_vatotte(void) 264{ 265} 266 267#else 268 269 /* 270 * Invocation in normal context as a VA-to-TTE translator 271 * for kernel context only. This routine returns 0 on 272 * success and -1 on error. 273 * 274 * %o0 = VA, input register 275 * %o1 = KCONTEXT 276 * %o2 = ttep, output register 277 */ 278 ENTRY_NP(kdi_vatotte) 279 mov %o0, %g1 /* VA in %g1 */ 280 mov %o1, %g2 /* cnum in %g2 */ 281 282 set kdi_trap_vatotte, %g3 283 jmpl %g3, %g7 /* => %g1: TTE or 0 */ 284 add %g7, 8, %g7 285 286 brz %g1, 1f 287 nop 288 289 /* Got a valid TTE */ 290 stx %g1, [%o2] 291 retl 292 clr %o0 293 294 /* Failed translation */ 2951: retl 296 mov -1, %o0 297 SET_SIZE(kdi_vatotte) 298 299 /* 300 * %g1 = vaddr passed in, tte or 0 (error) when return 301 * %g2 = KCONTEXT 302 * %g7 = return address 303 */ 304 ENTRY_NP(kdi_trap_vatotte) 305 306 cmp %g2, KCONTEXT /* make sure called in kernel ctx */ 307 bne,a,pn %icc, 6f 308 clr %g1 309 310 sethi %hi(ksfmmup), %g2 311 ldx [%g2 + %lo(ksfmmup)], %g2 312 313 mov 1, %g3 /* VA %g1, ksfmmup %g2, idx %g3 */ 314 mov HBLK_RANGE_SHIFT, %g4 315 ba 3f 316 nop 317 3181: mulx %g3, 3, %g4 /* 3: see TTE_BSZS_SHIFT */ 319 add %g4, MMU_PAGESHIFT, %g4 320 3213: KDI_HME_HASH_FUNCTION /* %g1, %g2, %g4 => hash in %g4 */ 322 KDI_HME_HASH_TAG /* %g1, %g3 => tag in %g5 */ 323 KDI_HME_HASH_TABLE_SEARCH /* %g2, %g4, %g5 => hmeblk PA in %g4 */ 324 325 brz %g4, 5f 326 nop 327 328 KDI_HBLK_TO_TTEP /* %g1, %g4 => TTE PA in %g2 */ 329 ldxa [%g2]ASI_MEM, %g1 330 brgez,a %g1, 4f 331 clr %g1 3324: ba,a 6f 333 3345: add %g3, 1, %g3 335 set mmu_hashcnt, %g4 336 lduw [%g4], %g4 337 cmp %g3, %g4 338 ble 1b 339 nop 340 341 clr %g1 342 3436: jmp %g7 344 nop 345 SET_SIZE(kdi_trap_vatotte) 346 347#endif /* lint */ 348