|
|
1.1.1.2 ! root 1: /* $Id: sun-mmu.c,v 1.8 2005/02/17 13:26:57 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.2 ! root 37: _TME_RCSID("$Id: sun-mmu.c,v 1.8 2005/02/17 13:26:57 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.2 ! root 54: TME_ATOMIC_POINTER_TYPE(struct tme_bus_tlb *) tme_sun_mmu_tlb_set_pointer; 1.1 root 55: 56: /* the base of this TLB set: */ 57: struct tme_bus_tlb *tme_sun_mmu_tlb_set_base; 58: 59: /* the size of one TLB entry: */ 60: unsigned int tme_sun_mmu_tlb_set_sizeof_one; 61: 62: /* the number of TLB entries per context in the set: */ 63: unsigned int tme_sun_mmu_tlb_set_count; 64: }; 65: 66: /* one PMEG in a classic two-level Sun MMU: */ 67: struct tme_sun_mmu_pmeg { 68: 69: /* the current list of TLBs using a page table entry in this PMEG, and 70: the head within that list: */ 71: struct tme_bus_tlb *tme_sun_mmu_pmeg_tlbs[TME_SUN_MMU_PMEG_TLBS]; 72: unsigned int tme_sun_mmu_pmeg_tlbs_head; 73: }; 74: 75: /* the private structure for a classic two-level Sun MMU: */ 76: struct tme_sun_mmu { 77: 78: /* the information provided by the user: */ 79: struct tme_sun_mmu_info tme_sun_mmu_info; 80: #define tme_sun_mmu_element tme_sun_mmu_info.tme_sun_mmu_info_element 81: #define tme_sun_mmu_address_bits tme_sun_mmu_info.tme_sun_mmu_info_address_bits 82: #define tme_sun_mmu_pgoffset_bits tme_sun_mmu_info.tme_sun_mmu_info_pgoffset_bits 83: #define tme_sun_mmu_pteindex_bits tme_sun_mmu_info.tme_sun_mmu_info_pteindex_bits 84: #define tme_sun_mmu_contexts tme_sun_mmu_info.tme_sun_mmu_info_contexts 85: #define tme_sun_mmu_pmegs_count tme_sun_mmu_info.tme_sun_mmu_info_pmegs 86: #define tme_sun_mmu_seginv tme_sun_mmu_info.tme_sun_mmu_info_seginv 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: 90: /* the number of bits in a segment map index: */ 91: tme_uint8_t tme_sun_mmu_segment_bits; 92: 93: /* the segment map: */ 94: unsigned short *tme_sun_mmu_segment_map; 95: 96: /* the PMEGs: */ 97: struct tme_sun_mmu_pmeg *tme_sun_mmu_pmegs; 98: 99: /* the PTEs: */ 100: struct tme_sun_mmu_pte *tme_sun_mmu_ptes; 101: 102: /* the allocated TLB sets: */ 103: struct tme_sun_mmu_tlb_set *tme_sun_mmu_tlb_sets; 104: }; 105: 106: /* this creates a classic two-level Sun MMU: */ 107: void * 108: tme_sun_mmu_new(struct tme_sun_mmu_info *info) 109: { 110: struct tme_sun_mmu *mmu; 111: unsigned int segmap_count; 112: unsigned int segmap_i; 113: 114: /* allocate the new private structure: */ 115: mmu = tme_new0(struct tme_sun_mmu, 1); 116: 117: /* copy the user-provided information: */ 118: mmu->tme_sun_mmu_info = *info; 119: 120: /* allocate the segment map and initialize it to all invalid: */ 121: mmu->tme_sun_mmu_segment_bits = (mmu->tme_sun_mmu_address_bits 122: - (mmu->tme_sun_mmu_pteindex_bits 123: + mmu->tme_sun_mmu_pgoffset_bits)); 124: segmap_count = (mmu->tme_sun_mmu_contexts 125: * (1 << mmu->tme_sun_mmu_segment_bits)); 126: mmu->tme_sun_mmu_segment_map = tme_new(unsigned short, segmap_count); 127: for (segmap_i = 0; segmap_i < segmap_count; segmap_i++) { 128: mmu->tme_sun_mmu_segment_map[segmap_i] = mmu->tme_sun_mmu_seginv; 129: } 130: 131: /* allocate the PMEGs: */ 132: mmu->tme_sun_mmu_pmegs = tme_new0(struct tme_sun_mmu_pmeg, mmu->tme_sun_mmu_pmegs_count); 133: 134: /* allocate the PTEs: */ 135: mmu->tme_sun_mmu_ptes = 136: tme_new0(struct tme_sun_mmu_pte, 137: mmu->tme_sun_mmu_pmegs_count 138: * (1 << mmu->tme_sun_mmu_pteindex_bits)); 139: 140: /* done: */ 141: return (mmu); 142: } 143: 144: /* given a context and an address, returns the segment map index and 145: PTE: */ 146: static unsigned short 147: _tme_sun_mmu_lookup(struct tme_sun_mmu *mmu, tme_uint8_t context, tme_uint32_t address, 148: struct tme_sun_mmu_pte **_pte) 149: { 150: unsigned short pteindex; 151: unsigned short segment; 152: unsigned short segment_map_index; 153: unsigned short pmeg; 154: 155: /* lose the page offset bits: */ 156: address >>= mmu->tme_sun_mmu_pgoffset_bits; 157: 158: /* get the PTE index: */ 159: pteindex = (address 160: & (TME_BIT(mmu->tme_sun_mmu_pteindex_bits) - 1)); 161: address >>= mmu->tme_sun_mmu_pteindex_bits; 162: 163: /* get the segment number: */ 164: segment = (address 165: & (TME_BIT(mmu->tme_sun_mmu_segment_bits) - 1)); 166: 167: /* get the segment map index: */ 168: segment_map_index = ((context << mmu->tme_sun_mmu_segment_bits) 169: | segment); 170: 171: /* get the PMEG: */ 172: pmeg = mmu->tme_sun_mmu_segment_map[segment_map_index]; 173: 174: /* return the segment map index and the PTE: */ 175: *_pte = (mmu->tme_sun_mmu_ptes + (pmeg << mmu->tme_sun_mmu_pteindex_bits) + pteindex); 176: return (segment_map_index); 177: } 178: 179: /* this invalidates all TLB entries that may be affected by changes to 180: a PMEG: */ 181: static void 182: _tme_sun_mmu_pmeg_invalidate(struct tme_sun_mmu *mmu, unsigned short segment_map_index) 183: { 184: struct tme_sun_mmu_pmeg *pmeg; 185: int tlb_i; 186: struct tme_bus_tlb *tlb; 187: 188: /* get the PMEG: */ 189: pmeg = mmu->tme_sun_mmu_pmegs + mmu->tme_sun_mmu_segment_map[segment_map_index]; 190: 191: /* invalidate all of the TLBs: */ 192: for (tlb_i = 0; tlb_i < TME_SUN_MMU_PMEG_TLBS; tlb_i++) { 193: tlb = pmeg->tme_sun_mmu_pmeg_tlbs[tlb_i]; 194: pmeg->tme_sun_mmu_pmeg_tlbs[tlb_i] = NULL; 195: if (tlb != NULL) { 196: tme_bus_tlb_invalidate(tlb); 197: } 198: } 199: } 200: 201: /* this gets a PTE: */ 202: int 203: tme_sun_mmu_pte_get(void *_mmu, tme_uint8_t context, tme_uint32_t address, 204: struct tme_sun_mmu_pte *_pte) 205: { 206: struct tme_sun_mmu *mmu; 207: unsigned short segment_map_index; 208: struct tme_sun_mmu_pte *pte; 209: 210: /* lookup this address: */ 211: mmu = (struct tme_sun_mmu *) _mmu; 212: segment_map_index = _tme_sun_mmu_lookup(mmu, context, address, &pte); 213: 214: #if 0 215: /* if this segment is invalid, return failure: */ 216: if (mmu->tme_sun_mmu_segment_map[segment_map_index] 217: == mmu->tme_sun_mmu_seginv) { 218: return (ENOENT); 219: } 220: #endif 221: 222: /* otherwise, copy the PTE: */ 223: *_pte = *pte; 224: return (TME_OK); 225: } 226: 227: /* this sets a PTE: */ 228: int 229: tme_sun_mmu_pte_set(void *_mmu, tme_uint8_t context, tme_uint32_t address, 230: struct tme_sun_mmu_pte *_pte) 231: { 232: struct tme_sun_mmu *mmu; 233: unsigned short segment_map_index; 234: struct tme_sun_mmu_pte *pte; 235: 236: /* lookup this address: */ 237: mmu = (struct tme_sun_mmu *) _mmu; 238: segment_map_index = _tme_sun_mmu_lookup(mmu, context, address, &pte); 239: 240: #if 0 241: /* if this segment is invalid, return failure: */ 242: if (mmu->tme_sun_mmu_segment_map[segment_map_index] 243: == mmu->tme_sun_mmu_seginv) { 244: return (ENOENT); 245: } 246: #endif 247: 248: /* invalidate all TLB entries that are affected by changes to this PMEG: */ 249: _tme_sun_mmu_pmeg_invalidate(mmu, segment_map_index); 250: 251: /* otherwise, copy the PTE: */ 252: *pte = *_pte; 253: return (TME_OK); 254: } 255: 256: /* this gets a segment map entry: */ 257: unsigned short 258: tme_sun_mmu_segmap_get(void *_mmu, tme_uint8_t context, tme_uint32_t address) 259: { 260: struct tme_sun_mmu *mmu; 261: struct tme_sun_mmu_pte *pte; 262: unsigned short segment_map_index, pmeg; 263: 264: /* lookup this address: */ 265: mmu = (struct tme_sun_mmu *) _mmu; 266: segment_map_index = _tme_sun_mmu_lookup(mmu, context, address, &pte); 267: pmeg = mmu->tme_sun_mmu_segment_map[segment_map_index]; 268: tme_log(&mmu->tme_sun_mmu_element->tme_element_log_handle, 1000, TME_OK, 269: (&mmu->tme_sun_mmu_element->tme_element_log_handle, 270: "segmap_get: SEGMAP[%d:0x%08x] -> 0x%04x", 271: context, 272: address, 273: pmeg)); 274: return (pmeg); 275: } 276: 277: /* this sets a segment map entry: */ 278: void 279: tme_sun_mmu_segmap_set(void *_mmu, tme_uint8_t context, tme_uint32_t address, unsigned short pmeg) 280: { 281: struct tme_sun_mmu *mmu; 282: unsigned short segment_map_index; 283: struct tme_sun_mmu_pte *pte; 284: 285: /* lookup this address: */ 286: mmu = (struct tme_sun_mmu *) _mmu; 287: segment_map_index = _tme_sun_mmu_lookup(mmu, context, address, &pte); 288: 289: /* if the old segment is valid, invalidate all TLB entries that 290: are affected by changes to this PMEG - losing a spot in the 291: segment map counts as such a change: */ 292: if ( 293: #if 0 294: mmu->tme_sun_mmu_segment_map[segment_map_index] 295: != mmu->tme_sun_mmu_seginv 296: #else 297: TRUE 298: #endif 299: ) { 300: _tme_sun_mmu_pmeg_invalidate(mmu, segment_map_index); 301: } 302: 303: /* set the new segment: */ 304: mmu->tme_sun_mmu_segment_map[segment_map_index] = pmeg; 305: tme_log(&mmu->tme_sun_mmu_element->tme_element_log_handle, 1000, TME_OK, 306: (&mmu->tme_sun_mmu_element->tme_element_log_handle, 307: "segmap_set: SEGMAP[%d:0x%08x] <- 0x%04x", 308: context, 309: address, 310: pmeg)); 311: } 312: 313: /* this fills a TLB entry: */ 314: unsigned short 315: tme_sun_mmu_tlb_fill(void *_mmu, struct tme_bus_tlb *tlb, 316: tme_uint8_t context, tme_uint32_t address, unsigned short access) 317: { 318: struct tme_sun_mmu *mmu; 319: unsigned short segment_map_index; 320: struct tme_sun_mmu_pte *pte; 321: tme_bus_addr_t addr_first, addr_last; 322: unsigned short protection, protection_other, tlb_valid_for; 323: tme_uint32_t physical_address; 324: struct tme_sun_mmu_pmeg *pmeg; 325: struct tme_bus_tlb tlb_virtual, *tlb_old; 326: int tlb_i; 327: 328: /* the access must be a read or write by the system or user: */ 329: assert(access != 0 330: && (access == TME_SUN_MMU_PTE_PROT_SYSTEM(TME_SUN_MMU_PTE_PROT_RO) 331: || access == TME_SUN_MMU_PTE_PROT_SYSTEM(TME_SUN_MMU_PTE_PROT_RW) 332: || access == TME_SUN_MMU_PTE_PROT_USER(TME_SUN_MMU_PTE_PROT_RO) 333: || access == TME_SUN_MMU_PTE_PROT_USER(TME_SUN_MMU_PTE_PROT_RW))); 334: 335: /* lookup this address: */ 336: mmu = (struct tme_sun_mmu *) _mmu; 337: segment_map_index = _tme_sun_mmu_lookup(mmu, context, address, &pte); 338: addr_first = (address & ~(TME_BIT(mmu->tme_sun_mmu_pgoffset_bits) - 1)); 339: addr_last = (address | (TME_BIT(mmu->tme_sun_mmu_pgoffset_bits) - 1)); 340: 341: /* remember this TLB entry in the PMEG: */ 342: pmeg = mmu->tme_sun_mmu_pmegs + mmu->tme_sun_mmu_segment_map[segment_map_index]; 343: tlb_i = pmeg->tme_sun_mmu_pmeg_tlbs_head; 344: tlb_old = pmeg->tme_sun_mmu_pmeg_tlbs[tlb_i]; 1.1.1.2 ! root 345: if (tlb_old != NULL ! 346: && tlb_old != TME_ATOMIC_READ(struct tme_bus_tlb *, ! 347: tlb->tme_bus_tlb_backing_reservation)) { 1.1 root 348: tme_bus_tlb_invalidate(tlb_old); 349: } 1.1.1.2 ! root 350: pmeg->tme_sun_mmu_pmeg_tlbs[tlb_i] ! 351: = TME_ATOMIC_READ(struct tme_bus_tlb *, ! 352: tlb->tme_bus_tlb_backing_reservation); 1.1 root 353: pmeg->tme_sun_mmu_pmeg_tlbs_head = (tlb_i + 1) & (TME_SUN_MMU_PMEG_TLBS - 1); 354: 355: /* if this page is invalid, return the page-invalid cycle handler, 356: which is valid for reading and writing for the user and system: */ 357: if (!(pte->tme_sun_mmu_pte_flags & TME_SUN_MMU_PTE_VALID)) { 358: tme_bus_tlb_initialize(tlb); 359: TME_ATOMIC_WRITE(tme_bus_addr_t, tlb->tme_bus_tlb_addr_first, addr_first); 360: TME_ATOMIC_WRITE(tme_bus_addr_t, tlb->tme_bus_tlb_addr_last, addr_last); 361: tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE; 362: tlb->tme_bus_tlb_cycle_private = mmu->tme_sun_mmu_info.tme_sun_mmu_info_invalid_private; 363: tlb->tme_bus_tlb_cycle = mmu->tme_sun_mmu_info.tme_sun_mmu_info_invalid; 364: return (TME_SUN_MMU_TLB_SYSTEM | TME_SUN_MMU_TLB_USER); 365: } 366: 367: /* otherwise, this page is valid. get the relevant part of the 368: protection for this accessor (system or user), the part of the 369: protection covering the other accessor (system or user), adjust 370: "access" to be an unshifted TME_SUN_MMU_PTE_PROT_ value, and get 371: the accessor (user or system) that this TLB entry will definitely 372: be valid for: */ 373: protection = pte->tme_sun_mmu_pte_flags; 374: if (access & TME_SUN_MMU_PTE_PROT_SYSTEM(TME_SUN_MMU_PTE_PROT_MASK)) { 375: protection_other = protection / TME_SUN_MMU_PTE_PROT_USER(1); 376: access /= TME_SUN_MMU_PTE_PROT_SYSTEM(1); 377: protection /= TME_SUN_MMU_PTE_PROT_SYSTEM(1); 378: tlb_valid_for = TME_SUN_MMU_TLB_SYSTEM; 379: } 380: else { 381: protection_other = protection / TME_SUN_MMU_PTE_PROT_SYSTEM(1); 382: access /= TME_SUN_MMU_PTE_PROT_USER(1); 383: protection /= TME_SUN_MMU_PTE_PROT_USER(1); 384: tlb_valid_for = TME_SUN_MMU_TLB_USER; 385: } 386: 387: /* NB that the following code assumes a particular ordering of 388: TME_SUN_MMU_PTE_PROT_ values. specifically, it assumes that 389: ABORT < ERROR < RO < RW: */ 390: 391: /* if the part of the protection covering the other accessor (system 392: or user) allows at least as much access as the relevant part of 393: the protection, this TLB entry will be valid for that other 394: successor as well. we rely on particular definitions of the 395: TME_SUN_MMU_TLB_ macros to make this fast: */ 396: #if (3 - TME_SUN_MMU_TLB_SYSTEM) != TME_SUN_MMU_TLB_USER 397: #error "TME_SUN_MMU_TLB_USER and TME_SUN_MMU_TLB_SYSTEM are incompatible" 398: #endif 399: protection &= TME_SUN_MMU_PTE_PROT_MASK; 400: protection_other &= TME_SUN_MMU_PTE_PROT_MASK; 401: if (protection_other >= protection) { 402: tlb_valid_for |= (3 - tlb_valid_for); 403: } 404: 405: /* if the access is protected, return the protection-error cycle 406: handler: */ 407: if (protection < access) { 408: if (protection == TME_SUN_MMU_PTE_PROT_ABORT) { 409: abort(); 410: } 411: tme_bus_tlb_initialize(tlb); 412: TME_ATOMIC_WRITE(tme_bus_addr_t, tlb->tme_bus_tlb_addr_first, addr_first); 413: TME_ATOMIC_WRITE(tme_bus_addr_t, tlb->tme_bus_tlb_addr_last, addr_last); 414: tlb->tme_bus_tlb_cycles_ok = (TME_BUS_CYCLE_WRITE 415: | (protection == TME_SUN_MMU_PTE_PROT_ERROR 416: ? TME_BUS_CYCLE_READ 417: : 0)); 418: tlb->tme_bus_tlb_cycle_private = mmu->tme_sun_mmu_info.tme_sun_mmu_info_proterr_private; 419: tlb->tme_bus_tlb_cycle = mmu->tme_sun_mmu_info.tme_sun_mmu_info_proterr; 420: return (tlb_valid_for); 421: } 422: 423: /* this access is OK. fill the TLB with physical bus information. 424: we pass in the virtual address as the initial physical address 425: because sometimes the virtual part of the address can influence 426: the physical address (as in the Sun-2 PROM mapping): */ 427: physical_address = address; 428: (*mmu->_tme_sun_mmu_tlb_fill) 429: (mmu->_tme_sun_mmu_tlb_fill_private, 430: tlb, 431: pte, 432: &physical_address, 433: ((access == TME_SUN_MMU_PTE_PROT_RW) 434: ? TME_BUS_CYCLE_WRITE 435: : TME_BUS_CYCLE_READ)); 436: 437: /* create the mapping TLB entry, and update the PTE flags: */ 438: TME_ATOMIC_WRITE(tme_bus_addr_t, tlb_virtual.tme_bus_tlb_addr_first, addr_first); 439: TME_ATOMIC_WRITE(tme_bus_addr_t, tlb_virtual.tme_bus_tlb_addr_last, addr_last); 440: pte->tme_sun_mmu_pte_flags |= TME_SUN_MMU_PTE_REF; 441: tlb_virtual.tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ; 442: if (access == TME_SUN_MMU_PTE_PROT_RW) { 443: pte->tme_sun_mmu_pte_flags |= TME_SUN_MMU_PTE_MOD; 444: } 1.1.1.2 ! root 445: if (protection == TME_SUN_MMU_PTE_PROT_RW ! 446: && (pte->tme_sun_mmu_pte_flags & TME_SUN_MMU_PTE_MOD)) { 1.1 root 447: tlb_virtual.tme_bus_tlb_cycles_ok |= TME_BUS_CYCLE_WRITE; 448: } 449: 450: /* map the filled TLB entry: */ 451: tme_bus_tlb_map(tlb, physical_address, &tlb_virtual, address); 452: 453: /* return who this TLB entry is good for: */ 454: return (tlb_valid_for); 455: } 456: 457: /* this invalidates all TLB entries in all TLB sets: */ 458: void 459: tme_sun_mmu_tlbs_invalidate(void *_mmu) 460: { 461: struct tme_sun_mmu *mmu; 462: struct tme_sun_mmu_tlb_set *tlb_set; 463: struct tme_bus_tlb *tlb; 464: unsigned long tlb_i; 465: 466: /* recover our MMU: */ 467: mmu = (struct tme_sun_mmu *) _mmu; 468: 469: /* invalidate all TLB entries in all sets: */ 470: for (tlb_set = mmu->tme_sun_mmu_tlb_sets; 471: tlb_set != NULL; 472: tlb_set = tlb_set->tme_sun_mmu_tlb_set_next) { 473: tlb = tlb_set->tme_sun_mmu_tlb_set_base; 474: tlb_i = ((unsigned long) tlb_set->tme_sun_mmu_tlb_set_count) * mmu->tme_sun_mmu_contexts; 475: for (; tlb_i-- > 0; ) { 476: tme_bus_tlb_invalidate(tlb); 477: tlb = (struct tme_bus_tlb *) (((tme_uint8_t *) tlb) + tlb_set->tme_sun_mmu_tlb_set_sizeof_one); 478: } 479: } 480: } 481: 482: /* this sets the user context register: */ 483: void 484: tme_sun_mmu_tlbs_context_set(void *_mmu, tme_uint8_t context) 485: { 486: struct tme_sun_mmu *mmu; 487: struct tme_sun_mmu_tlb_set *tlb_set; 488: 489: /* recover our MMU: */ 490: mmu = (struct tme_sun_mmu *) _mmu; 491: 492: /* we have to update each TLB set to reflect the context change: */ 493: for (tlb_set = mmu->tme_sun_mmu_tlb_sets; 494: tlb_set != NULL; 495: tlb_set = tlb_set->tme_sun_mmu_tlb_set_next) { 496: TME_ATOMIC_WRITE(struct tme_bus_tlb *, 497: *tlb_set->tme_sun_mmu_tlb_set_pointer, 498: (struct tme_bus_tlb *) 499: (((tme_uint8_t *) tlb_set->tme_sun_mmu_tlb_set_base) 500: + (((unsigned long) tlb_set->tme_sun_mmu_tlb_set_count) 501: * tlb_set->tme_sun_mmu_tlb_set_sizeof_one 502: * context))); 503: } 504: } 505: 506: /* this allocates a new TLB set: */ 507: int 508: tme_sun_mmu_tlb_set_allocate(void *_mmu, 509: unsigned int count, unsigned int sizeof_one, 1.1.1.2 ! root 510: TME_ATOMIC_POINTER_TYPE(struct tme_bus_tlb *) _tlbs) 1.1 root 511: { 512: struct tme_sun_mmu *mmu; 513: struct tme_bus_tlb *tlbs, *tlb; 514: unsigned long tlb_i; 515: struct tme_sun_mmu_tlb_set *tlb_set; 516: 517: /* recover our mmu: */ 518: mmu = (struct tme_sun_mmu *) _mmu; 519: 520: /* allocate and initialize a set of TLBs: */ 521: tlb_i = ((unsigned long) mmu->tme_sun_mmu_contexts) * count; 522: tlbs = (struct tme_bus_tlb *) tme_malloc(tlb_i * sizeof_one); 523: tlb = tlbs; 524: for (; tlb_i-- > 0; ) { 525: tme_bus_tlb_invalidate(tlb); 526: tlb = (struct tme_bus_tlb *) (((tme_uint8_t *) tlb) + sizeof_one); 527: } 528: 529: /* remember this set: */ 530: tlb_set = tme_new0(struct tme_sun_mmu_tlb_set, 1); 531: tlb_set->tme_sun_mmu_tlb_set_next = mmu->tme_sun_mmu_tlb_sets; 532: tlb_set->tme_sun_mmu_tlb_set_pointer = _tlbs; 533: tlb_set->tme_sun_mmu_tlb_set_base = tlbs; 534: tlb_set->tme_sun_mmu_tlb_set_sizeof_one = sizeof_one; 535: tlb_set->tme_sun_mmu_tlb_set_count = count; 536: mmu->tme_sun_mmu_tlb_sets = tlb_set; 537: 538: TME_ATOMIC_WRITE(struct tme_bus_tlb *, *_tlbs, tlbs); 539: return (TME_OK); 540: } 541:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.