|
|
1.1.1.3 ! root 1: /* $Id: sun-mmu.c,v 1.11 2006/11/16 02:37:05 fredette Exp $ */ 1.1 root 2: 3: /* machine/sun/sun-mmu.c - classic Sun MMU emulation implementation: */ 4: 5: /* 6: * Copyright (c) 2003 Matt Fredette 7: * All rights reserved. 8: * 9: * Redistribution and use in source and binary forms, with or without 10: * modification, are permitted provided that the following conditions 11: * are met: 12: * 1. Redistributions of source code must retain the above copyright 13: * notice, this list of conditions and the following disclaimer. 14: * 2. Redistributions in binary form must reproduce the above copyright 15: * notice, this list of conditions and the following disclaimer in the 16: * documentation and/or other materials provided with the distribution. 17: * 3. All advertising materials mentioning features or use of this software 18: * must display the following acknowledgement: 19: * This product includes software developed by Matt Fredette. 20: * 4. The name of the author may not be used to endorse or promote products 21: * derived from this software without specific prior written permission. 22: * 23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 25: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 26: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 27: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 28: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 29: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 31: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 32: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33: * POSSIBILITY OF SUCH DAMAGE. 34: */ 35: 36: #include <tme/common.h> 1.1.1.3 ! root 37: _TME_RCSID("$Id: sun-mmu.c,v 1.11 2006/11/16 02:37:05 fredette Exp $"); 1.1 root 38: 39: /* includes: */ 40: #include <tme/machine/sun.h> 41: 42: /* macros: */ 43: #define TME_SUN_MMU_PMEG_TLBS (16) 44: 45: /* structures: */ 46: 47: /* an allocated TLB set in a classic two-level Sun MMU: */ 48: struct tme_sun_mmu_tlb_set { 49: 50: /* the next allocated TLB set: */ 51: struct tme_sun_mmu_tlb_set *tme_sun_mmu_tlb_set_next; 52: 53: /* the user's pointer into the TLB set: */ 1.1.1.3 ! root 54: struct tme_bus_tlb * tme_shared *tme_sun_mmu_tlb_set_pointer; ! 55: tme_rwlock_t *tme_sun_mmu_tlb_set_pointer_rwlock; 1.1 root 56: 57: /* the base of this TLB set: */ 58: struct tme_bus_tlb *tme_sun_mmu_tlb_set_base; 59: 60: /* the size of one TLB entry: */ 61: unsigned int tme_sun_mmu_tlb_set_sizeof_one; 62: 63: /* the number of TLB entries per context in the set: */ 64: unsigned int tme_sun_mmu_tlb_set_count; 65: }; 66: 67: /* one PMEG in a classic two-level Sun MMU: */ 68: struct tme_sun_mmu_pmeg { 69: 70: /* the current list of TLBs using a page table entry in this PMEG, and 71: the head within that list: */ 72: struct tme_bus_tlb *tme_sun_mmu_pmeg_tlbs[TME_SUN_MMU_PMEG_TLBS]; 73: unsigned int tme_sun_mmu_pmeg_tlbs_head; 74: }; 75: 76: /* the private structure for a classic two-level Sun MMU: */ 77: struct tme_sun_mmu { 78: 79: /* the information provided by the user: */ 80: struct tme_sun_mmu_info tme_sun_mmu_info; 81: #define tme_sun_mmu_element tme_sun_mmu_info.tme_sun_mmu_info_element 82: #define tme_sun_mmu_address_bits tme_sun_mmu_info.tme_sun_mmu_info_address_bits 83: #define tme_sun_mmu_pgoffset_bits tme_sun_mmu_info.tme_sun_mmu_info_pgoffset_bits 84: #define tme_sun_mmu_pteindex_bits tme_sun_mmu_info.tme_sun_mmu_info_pteindex_bits 85: #define tme_sun_mmu_contexts tme_sun_mmu_info.tme_sun_mmu_info_contexts 86: #define tme_sun_mmu_pmegs_count tme_sun_mmu_info.tme_sun_mmu_info_pmegs 87: #define _tme_sun_mmu_tlb_fill_private tme_sun_mmu_info.tme_sun_mmu_info_tlb_fill_private 88: #define _tme_sun_mmu_tlb_fill tme_sun_mmu_info.tme_sun_mmu_info_tlb_fill 89: 1.1.1.3 ! root 90: /* if nonzero, this address space has a hole, and this has only the ! 91: last true address bit set: */ ! 92: tme_uint32_t tme_sun_mmu_address_hole_bit; ! 93: ! 94: /* a PTE for addresses in the hole. this is always all-bits-zero: */ ! 95: struct tme_sun_mmu_pte tme_sun_mmu_address_hole_pte; ! 96: 1.1 root 97: /* the number of bits in a segment map index: */ 98: tme_uint8_t tme_sun_mmu_segment_bits; 99: 100: /* the segment map: */ 101: unsigned short *tme_sun_mmu_segment_map; 102: 103: /* the PMEGs: */ 104: struct tme_sun_mmu_pmeg *tme_sun_mmu_pmegs; 105: 106: /* the PTEs: */ 107: struct tme_sun_mmu_pte *tme_sun_mmu_ptes; 108: 109: /* the allocated TLB sets: */ 110: struct tme_sun_mmu_tlb_set *tme_sun_mmu_tlb_sets; 111: }; 112: 113: /* this creates a classic two-level Sun MMU: */ 114: void * 115: tme_sun_mmu_new(struct tme_sun_mmu_info *info) 116: { 117: struct tme_sun_mmu *mmu; 118: unsigned int segmap_count; 119: unsigned int segmap_i; 120: 121: /* allocate the new private structure: */ 122: mmu = tme_new0(struct tme_sun_mmu, 1); 123: 124: /* copy the user-provided information: */ 125: mmu->tme_sun_mmu_info = *info; 126: 1.1.1.3 ! root 127: /* if there is an address hole: */ ! 128: if (mmu->tme_sun_mmu_info.tme_sun_mmu_info_topindex_bits < 0) { ! 129: ! 130: /* there must be 32 address bits: */ ! 131: assert (mmu->tme_sun_mmu_address_bits == 32); ! 132: ! 133: /* adjust the number of address bits for the hole: */ ! 134: mmu->tme_sun_mmu_address_bits += (mmu->tme_sun_mmu_info.tme_sun_mmu_info_topindex_bits + 1); ! 135: ! 136: /* make the hole address bit: */ ! 137: mmu->tme_sun_mmu_address_hole_bit = TME_BIT(mmu->tme_sun_mmu_address_bits - 1); ! 138: ! 139: /* zero the number of top index bits: */ ! 140: mmu->tme_sun_mmu_info.tme_sun_mmu_info_topindex_bits = 0; ! 141: } ! 142: 1.1 root 143: /* allocate the segment map and initialize it to all invalid: */ 144: mmu->tme_sun_mmu_segment_bits = (mmu->tme_sun_mmu_address_bits 145: - (mmu->tme_sun_mmu_pteindex_bits 146: + mmu->tme_sun_mmu_pgoffset_bits)); 147: segmap_count = (mmu->tme_sun_mmu_contexts 148: * (1 << mmu->tme_sun_mmu_segment_bits)); 149: mmu->tme_sun_mmu_segment_map = tme_new(unsigned short, segmap_count); 150: for (segmap_i = 0; segmap_i < segmap_count; segmap_i++) { 1.1.1.3 ! root 151: mmu->tme_sun_mmu_segment_map[segmap_i] = mmu->tme_sun_mmu_pmegs_count - 1; 1.1 root 152: } 153: 154: /* allocate the PMEGs: */ 155: mmu->tme_sun_mmu_pmegs = tme_new0(struct tme_sun_mmu_pmeg, mmu->tme_sun_mmu_pmegs_count); 156: 157: /* allocate the PTEs: */ 158: mmu->tme_sun_mmu_ptes = 159: tme_new0(struct tme_sun_mmu_pte, 160: mmu->tme_sun_mmu_pmegs_count 161: * (1 << mmu->tme_sun_mmu_pteindex_bits)); 162: 163: /* done: */ 164: return (mmu); 165: } 166: 167: /* given a context and an address, returns the segment map index and 168: PTE: */ 169: static unsigned short 170: _tme_sun_mmu_lookup(struct tme_sun_mmu *mmu, tme_uint8_t context, tme_uint32_t address, 171: struct tme_sun_mmu_pte **_pte) 172: { 173: unsigned short pteindex; 174: unsigned short segment; 175: unsigned short segment_map_index; 176: unsigned short pmeg; 177: 1.1.1.3 ! root 178: /* if there is an address hole, and this address is in it: */ ! 179: if (__tme_predict_false(((address ! 180: + (address & mmu->tme_sun_mmu_address_hole_bit)) ! 181: & (((tme_uint32_t) 0) ! 182: - mmu->tme_sun_mmu_address_hole_bit)) != 0)) { ! 183: ! 184: /* return the hole PTE, and zero for the segment map index: */ ! 185: *_pte = &mmu->tme_sun_mmu_address_hole_pte; ! 186: return (0); ! 187: } ! 188: 1.1 root 189: /* lose the page offset bits: */ 190: address >>= mmu->tme_sun_mmu_pgoffset_bits; 191: 192: /* get the PTE index: */ 193: pteindex = (address 194: & (TME_BIT(mmu->tme_sun_mmu_pteindex_bits) - 1)); 195: address >>= mmu->tme_sun_mmu_pteindex_bits; 196: 197: /* get the segment number: */ 198: segment = (address 199: & (TME_BIT(mmu->tme_sun_mmu_segment_bits) - 1)); 200: 201: /* get the segment map index: */ 202: segment_map_index = ((context << mmu->tme_sun_mmu_segment_bits) 203: | segment); 204: 205: /* get the PMEG: */ 206: pmeg = mmu->tme_sun_mmu_segment_map[segment_map_index]; 207: 208: /* return the segment map index and the PTE: */ 209: *_pte = (mmu->tme_sun_mmu_ptes + (pmeg << mmu->tme_sun_mmu_pteindex_bits) + pteindex); 210: return (segment_map_index); 211: } 212: 213: /* this invalidates all TLB entries that may be affected by changes to 214: a PMEG: */ 215: static void 216: _tme_sun_mmu_pmeg_invalidate(struct tme_sun_mmu *mmu, unsigned short segment_map_index) 217: { 218: struct tme_sun_mmu_pmeg *pmeg; 219: int tlb_i; 220: struct tme_bus_tlb *tlb; 221: 222: /* get the PMEG: */ 223: pmeg = mmu->tme_sun_mmu_pmegs + mmu->tme_sun_mmu_segment_map[segment_map_index]; 224: 225: /* invalidate all of the TLBs: */ 226: for (tlb_i = 0; tlb_i < TME_SUN_MMU_PMEG_TLBS; tlb_i++) { 227: tlb = pmeg->tme_sun_mmu_pmeg_tlbs[tlb_i]; 228: pmeg->tme_sun_mmu_pmeg_tlbs[tlb_i] = NULL; 229: if (tlb != NULL) { 230: tme_bus_tlb_invalidate(tlb); 231: } 232: } 233: } 234: 235: /* this gets a PTE: */ 236: int 237: tme_sun_mmu_pte_get(void *_mmu, tme_uint8_t context, tme_uint32_t address, 238: struct tme_sun_mmu_pte *_pte) 239: { 240: struct tme_sun_mmu *mmu; 241: unsigned short segment_map_index; 242: struct tme_sun_mmu_pte *pte; 243: 244: /* lookup this address: */ 245: mmu = (struct tme_sun_mmu *) _mmu; 246: segment_map_index = _tme_sun_mmu_lookup(mmu, context, address, &pte); 247: 248: /* otherwise, copy the PTE: */ 249: *_pte = *pte; 250: return (TME_OK); 251: } 252: 253: /* this sets a PTE: */ 254: int 255: tme_sun_mmu_pte_set(void *_mmu, tme_uint8_t context, tme_uint32_t address, 256: struct tme_sun_mmu_pte *_pte) 257: { 258: struct tme_sun_mmu *mmu; 259: unsigned short segment_map_index; 260: struct tme_sun_mmu_pte *pte; 261: 262: /* lookup this address: */ 263: mmu = (struct tme_sun_mmu *) _mmu; 264: segment_map_index = _tme_sun_mmu_lookup(mmu, context, address, &pte); 1.1.1.3 ! root 265: if (__tme_predict_false(pte == &mmu->tme_sun_mmu_address_hole_pte)) { ! 266: return (TME_OK); 1.1 root 267: } 268: 269: /* invalidate all TLB entries that are affected by changes to this PMEG: */ 270: _tme_sun_mmu_pmeg_invalidate(mmu, segment_map_index); 271: 272: /* otherwise, copy the PTE: */ 273: *pte = *_pte; 274: return (TME_OK); 275: } 276: 277: /* this gets a segment map entry: */ 278: unsigned short 279: tme_sun_mmu_segmap_get(void *_mmu, tme_uint8_t context, tme_uint32_t address) 280: { 281: struct tme_sun_mmu *mmu; 282: struct tme_sun_mmu_pte *pte; 283: unsigned short segment_map_index, pmeg; 284: 285: /* lookup this address: */ 286: mmu = (struct tme_sun_mmu *) _mmu; 287: segment_map_index = _tme_sun_mmu_lookup(mmu, context, address, &pte); 1.1.1.3 ! root 288: if (__tme_predict_false(pte == &mmu->tme_sun_mmu_address_hole_pte)) { ! 289: return (mmu->tme_sun_mmu_pmegs_count - 1); ! 290: } 1.1 root 291: pmeg = mmu->tme_sun_mmu_segment_map[segment_map_index]; 292: tme_log(&mmu->tme_sun_mmu_element->tme_element_log_handle, 1000, TME_OK, 293: (&mmu->tme_sun_mmu_element->tme_element_log_handle, 294: "segmap_get: SEGMAP[%d:0x%08x] -> 0x%04x", 295: context, 296: address, 297: pmeg)); 298: return (pmeg); 299: } 300: 301: /* this sets a segment map entry: */ 302: void 303: tme_sun_mmu_segmap_set(void *_mmu, tme_uint8_t context, tme_uint32_t address, unsigned short pmeg) 304: { 305: struct tme_sun_mmu *mmu; 306: unsigned short segment_map_index; 307: struct tme_sun_mmu_pte *pte; 308: 309: /* lookup this address: */ 310: mmu = (struct tme_sun_mmu *) _mmu; 311: segment_map_index = _tme_sun_mmu_lookup(mmu, context, address, &pte); 1.1.1.3 ! root 312: if (__tme_predict_false(pte == &mmu->tme_sun_mmu_address_hole_pte)) { ! 313: return; 1.1 root 314: } 315: 1.1.1.3 ! root 316: /* invalidate all TLB entries that are affected by changes to this ! 317: PMEG - losing a spot in the segment map counts as such a change: */ ! 318: _tme_sun_mmu_pmeg_invalidate(mmu, segment_map_index); ! 319: 1.1 root 320: /* set the new segment: */ 321: mmu->tme_sun_mmu_segment_map[segment_map_index] = pmeg; 322: tme_log(&mmu->tme_sun_mmu_element->tme_element_log_handle, 1000, TME_OK, 323: (&mmu->tme_sun_mmu_element->tme_element_log_handle, 324: "segmap_set: SEGMAP[%d:0x%08x] <- 0x%04x", 325: context, 326: address, 327: pmeg)); 328: } 329: 330: /* this fills a TLB entry: */ 331: unsigned short 332: tme_sun_mmu_tlb_fill(void *_mmu, struct tme_bus_tlb *tlb, 333: tme_uint8_t context, tme_uint32_t address, unsigned short access) 334: { 335: struct tme_sun_mmu *mmu; 336: unsigned short segment_map_index; 337: struct tme_sun_mmu_pte *pte; 338: tme_bus_addr_t addr_first, addr_last; 339: unsigned short protection, protection_other, tlb_valid_for; 340: tme_uint32_t physical_address; 341: struct tme_sun_mmu_pmeg *pmeg; 342: struct tme_bus_tlb tlb_virtual, *tlb_old; 343: int tlb_i; 344: 345: /* the access must be a read or write by the system or user: */ 346: assert(access != 0 347: && (access == TME_SUN_MMU_PTE_PROT_SYSTEM(TME_SUN_MMU_PTE_PROT_RO) 348: || access == TME_SUN_MMU_PTE_PROT_SYSTEM(TME_SUN_MMU_PTE_PROT_RW) 349: || access == TME_SUN_MMU_PTE_PROT_USER(TME_SUN_MMU_PTE_PROT_RO) 350: || access == TME_SUN_MMU_PTE_PROT_USER(TME_SUN_MMU_PTE_PROT_RW))); 351: 352: /* lookup this address: */ 353: mmu = (struct tme_sun_mmu *) _mmu; 354: segment_map_index = _tme_sun_mmu_lookup(mmu, context, address, &pte); 355: addr_first = (address & ~(TME_BIT(mmu->tme_sun_mmu_pgoffset_bits) - 1)); 356: addr_last = (address | (TME_BIT(mmu->tme_sun_mmu_pgoffset_bits) - 1)); 357: 358: /* remember this TLB entry in the PMEG: */ 1.1.1.3 ! root 359: if (__tme_predict_true(pte != &mmu->tme_sun_mmu_address_hole_pte)) { ! 360: pmeg = mmu->tme_sun_mmu_pmegs + mmu->tme_sun_mmu_segment_map[segment_map_index]; ! 361: tlb_i = pmeg->tme_sun_mmu_pmeg_tlbs_head; ! 362: tlb_old = pmeg->tme_sun_mmu_pmeg_tlbs[tlb_i]; ! 363: if (tlb_old != NULL ! 364: && tlb_old != tlb->tme_bus_tlb_global) { ! 365: tme_bus_tlb_invalidate(tlb_old); ! 366: } ! 367: pmeg->tme_sun_mmu_pmeg_tlbs[tlb_i] ! 368: = tlb->tme_bus_tlb_global; ! 369: pmeg->tme_sun_mmu_pmeg_tlbs_head = (tlb_i + 1) & (TME_SUN_MMU_PMEG_TLBS - 1); ! 370: } 1.1 root 371: 372: /* if this page is invalid, return the page-invalid cycle handler, 373: which is valid for reading and writing for the user and system: */ 374: if (!(pte->tme_sun_mmu_pte_flags & TME_SUN_MMU_PTE_VALID)) { 375: tme_bus_tlb_initialize(tlb); 1.1.1.3 ! root 376: tlb->tme_bus_tlb_addr_first = addr_first; ! 377: tlb->tme_bus_tlb_addr_last = addr_last; 1.1 root 378: tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE; 379: tlb->tme_bus_tlb_cycle_private = mmu->tme_sun_mmu_info.tme_sun_mmu_info_invalid_private; 380: tlb->tme_bus_tlb_cycle = mmu->tme_sun_mmu_info.tme_sun_mmu_info_invalid; 381: return (TME_SUN_MMU_TLB_SYSTEM | TME_SUN_MMU_TLB_USER); 382: } 383: 384: /* otherwise, this page is valid. get the relevant part of the 385: protection for this accessor (system or user), the part of the 386: protection covering the other accessor (system or user), adjust 387: "access" to be an unshifted TME_SUN_MMU_PTE_PROT_ value, and get 388: the accessor (user or system) that this TLB entry will definitely 389: be valid for: */ 390: protection = pte->tme_sun_mmu_pte_flags; 391: if (access & TME_SUN_MMU_PTE_PROT_SYSTEM(TME_SUN_MMU_PTE_PROT_MASK)) { 392: protection_other = protection / TME_SUN_MMU_PTE_PROT_USER(1); 393: access /= TME_SUN_MMU_PTE_PROT_SYSTEM(1); 394: protection /= TME_SUN_MMU_PTE_PROT_SYSTEM(1); 395: tlb_valid_for = TME_SUN_MMU_TLB_SYSTEM; 396: } 397: else { 398: protection_other = protection / TME_SUN_MMU_PTE_PROT_SYSTEM(1); 399: access /= TME_SUN_MMU_PTE_PROT_USER(1); 400: protection /= TME_SUN_MMU_PTE_PROT_USER(1); 401: tlb_valid_for = TME_SUN_MMU_TLB_USER; 402: } 403: 404: /* NB that the following code assumes a particular ordering of 405: TME_SUN_MMU_PTE_PROT_ values. specifically, it assumes that 406: ABORT < ERROR < RO < RW: */ 407: 408: /* if the part of the protection covering the other accessor (system 409: or user) allows at least as much access as the relevant part of 410: the protection, this TLB entry will be valid for that other 411: successor as well. we rely on particular definitions of the 412: TME_SUN_MMU_TLB_ macros to make this fast: */ 413: #if (3 - TME_SUN_MMU_TLB_SYSTEM) != TME_SUN_MMU_TLB_USER 414: #error "TME_SUN_MMU_TLB_USER and TME_SUN_MMU_TLB_SYSTEM are incompatible" 415: #endif 416: protection &= TME_SUN_MMU_PTE_PROT_MASK; 417: protection_other &= TME_SUN_MMU_PTE_PROT_MASK; 418: if (protection_other >= protection) { 419: tlb_valid_for |= (3 - tlb_valid_for); 420: } 421: 422: /* if the access is protected, return the protection-error cycle 423: handler: */ 424: if (protection < access) { 425: if (protection == TME_SUN_MMU_PTE_PROT_ABORT) { 426: abort(); 427: } 428: tme_bus_tlb_initialize(tlb); 1.1.1.3 ! root 429: tlb->tme_bus_tlb_addr_first = addr_first; ! 430: tlb->tme_bus_tlb_addr_last = addr_last; 1.1 root 431: tlb->tme_bus_tlb_cycles_ok = (TME_BUS_CYCLE_WRITE 432: | (protection == TME_SUN_MMU_PTE_PROT_ERROR 433: ? TME_BUS_CYCLE_READ 434: : 0)); 435: tlb->tme_bus_tlb_cycle_private = mmu->tme_sun_mmu_info.tme_sun_mmu_info_proterr_private; 436: tlb->tme_bus_tlb_cycle = mmu->tme_sun_mmu_info.tme_sun_mmu_info_proterr; 437: return (tlb_valid_for); 438: } 439: 440: /* this access is OK. fill the TLB with physical bus information. 441: we pass in the virtual address as the initial physical address 442: because sometimes the virtual part of the address can influence 443: the physical address (as in the Sun-2 PROM mapping): */ 444: physical_address = address; 445: (*mmu->_tme_sun_mmu_tlb_fill) 446: (mmu->_tme_sun_mmu_tlb_fill_private, 447: tlb, 448: pte, 449: &physical_address, 450: ((access == TME_SUN_MMU_PTE_PROT_RW) 451: ? TME_BUS_CYCLE_WRITE 452: : TME_BUS_CYCLE_READ)); 453: 454: /* create the mapping TLB entry, and update the PTE flags: */ 1.1.1.3 ! root 455: tlb_virtual.tme_bus_tlb_addr_first = addr_first; ! 456: tlb_virtual.tme_bus_tlb_addr_last = addr_last; 1.1 root 457: pte->tme_sun_mmu_pte_flags |= TME_SUN_MMU_PTE_REF; 458: tlb_virtual.tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ; 459: if (access == TME_SUN_MMU_PTE_PROT_RW) { 460: pte->tme_sun_mmu_pte_flags |= TME_SUN_MMU_PTE_MOD; 461: } 1.1.1.2 root 462: if (protection == TME_SUN_MMU_PTE_PROT_RW 463: && (pte->tme_sun_mmu_pte_flags & TME_SUN_MMU_PTE_MOD)) { 1.1 root 464: tlb_virtual.tme_bus_tlb_cycles_ok |= TME_BUS_CYCLE_WRITE; 465: } 466: 467: /* map the filled TLB entry: */ 468: tme_bus_tlb_map(tlb, physical_address, &tlb_virtual, address); 469: 470: /* return who this TLB entry is good for: */ 471: return (tlb_valid_for); 472: } 473: 474: /* this invalidates all TLB entries in all TLB sets: */ 475: void 476: tme_sun_mmu_tlbs_invalidate(void *_mmu) 477: { 478: struct tme_sun_mmu *mmu; 479: struct tme_sun_mmu_tlb_set *tlb_set; 480: struct tme_bus_tlb *tlb; 481: unsigned long tlb_i; 482: 483: /* recover our MMU: */ 484: mmu = (struct tme_sun_mmu *) _mmu; 485: 486: /* invalidate all TLB entries in all sets: */ 487: for (tlb_set = mmu->tme_sun_mmu_tlb_sets; 488: tlb_set != NULL; 489: tlb_set = tlb_set->tme_sun_mmu_tlb_set_next) { 490: tlb = tlb_set->tme_sun_mmu_tlb_set_base; 491: tlb_i = ((unsigned long) tlb_set->tme_sun_mmu_tlb_set_count) * mmu->tme_sun_mmu_contexts; 492: for (; tlb_i-- > 0; ) { 493: tme_bus_tlb_invalidate(tlb); 494: tlb = (struct tme_bus_tlb *) (((tme_uint8_t *) tlb) + tlb_set->tme_sun_mmu_tlb_set_sizeof_one); 495: } 496: } 497: } 498: 499: /* this sets the user context register: */ 500: void 501: tme_sun_mmu_tlbs_context_set(void *_mmu, tme_uint8_t context) 502: { 503: struct tme_sun_mmu *mmu; 504: struct tme_sun_mmu_tlb_set *tlb_set; 505: 506: /* recover our MMU: */ 507: mmu = (struct tme_sun_mmu *) _mmu; 508: 509: /* we have to update each TLB set to reflect the context change: */ 510: for (tlb_set = mmu->tme_sun_mmu_tlb_sets; 511: tlb_set != NULL; 512: tlb_set = tlb_set->tme_sun_mmu_tlb_set_next) { 1.1.1.3 ! root 513: tme_memory_atomic_pointer_write(struct tme_bus_tlb *, ! 514: *tlb_set->tme_sun_mmu_tlb_set_pointer, ! 515: (struct tme_bus_tlb *) ! 516: (((tme_uint8_t *) tlb_set->tme_sun_mmu_tlb_set_base) ! 517: + (((unsigned long) tlb_set->tme_sun_mmu_tlb_set_count) ! 518: * tlb_set->tme_sun_mmu_tlb_set_sizeof_one ! 519: * context)), ! 520: tlb_set->tme_sun_mmu_tlb_set_pointer_rwlock); 1.1 root 521: } 522: } 523: 524: /* this allocates a new TLB set: */ 525: int 526: tme_sun_mmu_tlb_set_allocate(void *_mmu, 527: unsigned int count, unsigned int sizeof_one, 1.1.1.3 ! root 528: struct tme_bus_tlb * tme_shared *_tlbs, ! 529: tme_rwlock_t *_tlbs_rwlock) 1.1 root 530: { 531: struct tme_sun_mmu *mmu; 532: struct tme_bus_tlb *tlbs, *tlb; 533: unsigned long tlb_i; 534: struct tme_sun_mmu_tlb_set *tlb_set; 535: 536: /* recover our mmu: */ 537: mmu = (struct tme_sun_mmu *) _mmu; 538: 539: /* allocate and initialize a set of TLBs: */ 540: tlb_i = ((unsigned long) mmu->tme_sun_mmu_contexts) * count; 541: tlbs = (struct tme_bus_tlb *) tme_malloc(tlb_i * sizeof_one); 542: tlb = tlbs; 543: for (; tlb_i-- > 0; ) { 1.1.1.3 ! root 544: tme_bus_tlb_construct(tlb); 1.1 root 545: tlb = (struct tme_bus_tlb *) (((tme_uint8_t *) tlb) + sizeof_one); 546: } 547: 548: /* remember this set: */ 549: tlb_set = tme_new0(struct tme_sun_mmu_tlb_set, 1); 550: tlb_set->tme_sun_mmu_tlb_set_next = mmu->tme_sun_mmu_tlb_sets; 551: tlb_set->tme_sun_mmu_tlb_set_pointer = _tlbs; 1.1.1.3 ! root 552: tlb_set->tme_sun_mmu_tlb_set_pointer_rwlock = _tlbs_rwlock; 1.1 root 553: tlb_set->tme_sun_mmu_tlb_set_base = tlbs; 554: tlb_set->tme_sun_mmu_tlb_set_sizeof_one = sizeof_one; 555: tlb_set->tme_sun_mmu_tlb_set_count = count; 556: mmu->tme_sun_mmu_tlb_sets = tlb_set; 557: 1.1.1.3 ! root 558: tme_memory_atomic_pointer_write(struct tme_bus_tlb *, ! 559: *_tlbs, ! 560: tlbs, ! 561: _tlbs_rwlock); 1.1 root 562: return (TME_OK); 563: } 564:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.