Annotation of tme/machine/sun/sun-mmu.c, revision 1.1.1.1

1.1       root        1: /* $Id: sun-mmu.c,v 1.4 2003/05/16 21:48:13 fredette Exp $ */
                      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>
                     37: _TME_RCSID("$Id: sun-mmu.c,v 1.4 2003/05/16 21:48:13 fredette Exp $");
                     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: */
                     54:   TME_ATOMIC_POINTER_TYPE(struct tme_bus_tlb **) tme_sun_mmu_tlb_set_pointer;
                     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];
                    345:   if (tlb_old != NULL) {
                    346:     tme_bus_tlb_invalidate(tlb_old);
                    347:   }
                    348:   pmeg->tme_sun_mmu_pmeg_tlbs[tlb_i] = tlb;
                    349:   pmeg->tme_sun_mmu_pmeg_tlbs_head = (tlb_i + 1) & (TME_SUN_MMU_PMEG_TLBS - 1);
                    350: 
                    351:   /* if this page is invalid, return the page-invalid cycle handler,
                    352:      which is valid for reading and writing for the user and system: */
                    353:   if (!(pte->tme_sun_mmu_pte_flags & TME_SUN_MMU_PTE_VALID)) {
                    354:     tme_bus_tlb_initialize(tlb);
                    355:     TME_ATOMIC_WRITE(tme_bus_addr_t, tlb->tme_bus_tlb_addr_first, addr_first);
                    356:     TME_ATOMIC_WRITE(tme_bus_addr_t, tlb->tme_bus_tlb_addr_last, addr_last);
                    357:     tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE;
                    358:     tlb->tme_bus_tlb_cycle_private = mmu->tme_sun_mmu_info.tme_sun_mmu_info_invalid_private;
                    359:     tlb->tme_bus_tlb_cycle = mmu->tme_sun_mmu_info.tme_sun_mmu_info_invalid;
                    360:     return (TME_SUN_MMU_TLB_SYSTEM | TME_SUN_MMU_TLB_USER);
                    361:   }
                    362: 
                    363:   /* otherwise, this page is valid.  get the relevant part of the
                    364:      protection for this accessor (system or user), the part of the
                    365:      protection covering the other accessor (system or user), adjust
                    366:      "access" to be an unshifted TME_SUN_MMU_PTE_PROT_ value, and get
                    367:      the accessor (user or system) that this TLB entry will definitely
                    368:      be valid for: */
                    369:   protection = pte->tme_sun_mmu_pte_flags;
                    370:   if (access & TME_SUN_MMU_PTE_PROT_SYSTEM(TME_SUN_MMU_PTE_PROT_MASK)) {
                    371:     protection_other = protection / TME_SUN_MMU_PTE_PROT_USER(1);
                    372:     access /= TME_SUN_MMU_PTE_PROT_SYSTEM(1);
                    373:     protection /= TME_SUN_MMU_PTE_PROT_SYSTEM(1);
                    374:     tlb_valid_for = TME_SUN_MMU_TLB_SYSTEM;
                    375:   }
                    376:   else {
                    377:     protection_other = protection / TME_SUN_MMU_PTE_PROT_SYSTEM(1);
                    378:     access /= TME_SUN_MMU_PTE_PROT_USER(1);
                    379:     protection /= TME_SUN_MMU_PTE_PROT_USER(1);
                    380:     tlb_valid_for = TME_SUN_MMU_TLB_USER;
                    381:   }
                    382: 
                    383:   /* NB that the following code assumes a particular ordering of
                    384:      TME_SUN_MMU_PTE_PROT_ values.  specifically, it assumes that
                    385:      ABORT < ERROR < RO < RW: */
                    386: 
                    387:   /* if the part of the protection covering the other accessor (system
                    388:      or user) allows at least as much access as the relevant part of
                    389:      the protection, this TLB entry will be valid for that other
                    390:      successor as well.  we rely on particular definitions of the
                    391:      TME_SUN_MMU_TLB_ macros to make this fast: */
                    392: #if (3 - TME_SUN_MMU_TLB_SYSTEM) != TME_SUN_MMU_TLB_USER
                    393: #error "TME_SUN_MMU_TLB_USER and TME_SUN_MMU_TLB_SYSTEM are incompatible"
                    394: #endif
                    395:   protection &= TME_SUN_MMU_PTE_PROT_MASK;
                    396:   protection_other &= TME_SUN_MMU_PTE_PROT_MASK;
                    397:   if (protection_other >= protection) {
                    398:     tlb_valid_for |= (3 - tlb_valid_for);
                    399:   }
                    400: 
                    401:   /* if the access is protected, return the protection-error cycle
                    402:      handler: */
                    403:   if (protection < access) {
                    404:     if (protection == TME_SUN_MMU_PTE_PROT_ABORT) {
                    405:       abort();
                    406:     }
                    407:     tme_bus_tlb_initialize(tlb);
                    408:     TME_ATOMIC_WRITE(tme_bus_addr_t, tlb->tme_bus_tlb_addr_first, addr_first);
                    409:     TME_ATOMIC_WRITE(tme_bus_addr_t, tlb->tme_bus_tlb_addr_last, addr_last);
                    410:     tlb->tme_bus_tlb_cycles_ok = (TME_BUS_CYCLE_WRITE
                    411:                                  | (protection == TME_SUN_MMU_PTE_PROT_ERROR
                    412:                                     ? TME_BUS_CYCLE_READ
                    413:                                     : 0));
                    414:     tlb->tme_bus_tlb_cycle_private = mmu->tme_sun_mmu_info.tme_sun_mmu_info_proterr_private;
                    415:     tlb->tme_bus_tlb_cycle = mmu->tme_sun_mmu_info.tme_sun_mmu_info_proterr;
                    416:     return (tlb_valid_for);
                    417:   }
                    418: 
                    419:   /* this access is OK.  fill the TLB with physical bus information.
                    420:      we pass in the virtual address as the initial physical address
                    421:      because sometimes the virtual part of the address can influence
                    422:      the physical address (as in the Sun-2 PROM mapping): */
                    423:   physical_address = address;
                    424:   (*mmu->_tme_sun_mmu_tlb_fill)
                    425:     (mmu->_tme_sun_mmu_tlb_fill_private, 
                    426:      tlb, 
                    427:      pte,
                    428:      &physical_address,
                    429:      ((access == TME_SUN_MMU_PTE_PROT_RW)
                    430:       ? TME_BUS_CYCLE_WRITE
                    431:       : TME_BUS_CYCLE_READ));
                    432: 
                    433:   /* create the mapping TLB entry, and update the PTE flags: */
                    434:   TME_ATOMIC_WRITE(tme_bus_addr_t, tlb_virtual.tme_bus_tlb_addr_first, addr_first);
                    435:   TME_ATOMIC_WRITE(tme_bus_addr_t, tlb_virtual.tme_bus_tlb_addr_last, addr_last);
                    436:   pte->tme_sun_mmu_pte_flags |= TME_SUN_MMU_PTE_REF;
                    437:   tlb_virtual.tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ;
                    438:   if (access == TME_SUN_MMU_PTE_PROT_RW) {
                    439:     pte->tme_sun_mmu_pte_flags |= TME_SUN_MMU_PTE_MOD;
                    440:   }
                    441:   if (pte->tme_sun_mmu_pte_flags & TME_SUN_MMU_PTE_MOD) {
                    442:     tlb_virtual.tme_bus_tlb_cycles_ok |= TME_BUS_CYCLE_WRITE;
                    443:   }
                    444:   
                    445:   /* map the filled TLB entry: */
                    446:   tme_bus_tlb_map(tlb, physical_address, &tlb_virtual, address);
                    447: 
                    448:   /* return who this TLB entry is good for: */
                    449:   return (tlb_valid_for);
                    450: }
                    451: 
                    452: /* this invalidates all TLB entries in all TLB sets: */
                    453: void
                    454: tme_sun_mmu_tlbs_invalidate(void *_mmu)
                    455: {
                    456:   struct tme_sun_mmu *mmu;
                    457:   struct tme_sun_mmu_tlb_set *tlb_set;
                    458:   struct tme_bus_tlb *tlb;
                    459:   unsigned long tlb_i;
                    460: 
                    461:   /* recover our MMU: */
                    462:   mmu = (struct tme_sun_mmu *) _mmu;
                    463: 
                    464:   /* invalidate all TLB entries in all sets: */
                    465:   for (tlb_set = mmu->tme_sun_mmu_tlb_sets;
                    466:        tlb_set != NULL;
                    467:        tlb_set = tlb_set->tme_sun_mmu_tlb_set_next) {
                    468:     tlb = tlb_set->tme_sun_mmu_tlb_set_base;
                    469:     tlb_i = ((unsigned long) tlb_set->tme_sun_mmu_tlb_set_count) * mmu->tme_sun_mmu_contexts;
                    470:     for (; tlb_i-- > 0; ) {
                    471:       tme_bus_tlb_invalidate(tlb);
                    472:       tlb = (struct tme_bus_tlb *) (((tme_uint8_t *) tlb) + tlb_set->tme_sun_mmu_tlb_set_sizeof_one);
                    473:     }
                    474:   }
                    475: }
                    476: 
                    477: /* this sets the user context register: */
                    478: void
                    479: tme_sun_mmu_tlbs_context_set(void *_mmu, tme_uint8_t context)
                    480: {
                    481:   struct tme_sun_mmu *mmu;
                    482:   struct tme_sun_mmu_tlb_set *tlb_set;
                    483: 
                    484:   /* recover our MMU: */
                    485:   mmu = (struct tme_sun_mmu *) _mmu;
                    486: 
                    487:   /* we have to update each TLB set to reflect the context change: */
                    488:   for (tlb_set = mmu->tme_sun_mmu_tlb_sets;
                    489:        tlb_set != NULL;
                    490:        tlb_set = tlb_set->tme_sun_mmu_tlb_set_next) {
                    491:     TME_ATOMIC_WRITE(struct tme_bus_tlb *,
                    492:                     *tlb_set->tme_sun_mmu_tlb_set_pointer,
                    493:                     (struct tme_bus_tlb *)
                    494:                     (((tme_uint8_t *) tlb_set->tme_sun_mmu_tlb_set_base)
                    495:                      + (((unsigned long) tlb_set->tme_sun_mmu_tlb_set_count)
                    496:                         * tlb_set->tme_sun_mmu_tlb_set_sizeof_one
                    497:                         * context)));
                    498:   }
                    499: }
                    500: 
                    501: /* this allocates a new TLB set: */
                    502: int
                    503: tme_sun_mmu_tlb_set_allocate(void *_mmu,
                    504:                             unsigned int count, unsigned int sizeof_one, 
                    505:                             TME_ATOMIC_POINTER_TYPE(struct tme_bus_tlb **) _tlbs)
                    506: {
                    507:   struct tme_sun_mmu *mmu;
                    508:   struct tme_bus_tlb *tlbs, *tlb;
                    509:   unsigned long tlb_i;
                    510:   struct tme_sun_mmu_tlb_set *tlb_set;
                    511: 
                    512:   /* recover our mmu: */
                    513:   mmu = (struct tme_sun_mmu *) _mmu;
                    514: 
                    515:   /* allocate and initialize a set of TLBs: */
                    516:   tlb_i = ((unsigned long) mmu->tme_sun_mmu_contexts) * count;
                    517:   tlbs = (struct tme_bus_tlb *) tme_malloc(tlb_i * sizeof_one);
                    518:   tlb = tlbs;
                    519:   for (; tlb_i-- > 0; ) {
                    520:     tme_bus_tlb_invalidate(tlb);
                    521:     tlb = (struct tme_bus_tlb *) (((tme_uint8_t *) tlb) + sizeof_one);
                    522:   }
                    523: 
                    524:   /* remember this set: */
                    525:   tlb_set = tme_new0(struct tme_sun_mmu_tlb_set, 1);
                    526:   tlb_set->tme_sun_mmu_tlb_set_next = mmu->tme_sun_mmu_tlb_sets;
                    527:   tlb_set->tme_sun_mmu_tlb_set_pointer = _tlbs;
                    528:   tlb_set->tme_sun_mmu_tlb_set_base = tlbs;
                    529:   tlb_set->tme_sun_mmu_tlb_set_sizeof_one = sizeof_one;
                    530:   tlb_set->tme_sun_mmu_tlb_set_count = count;
                    531:   mmu->tme_sun_mmu_tlb_sets = tlb_set;
                    532:   
                    533:   TME_ATOMIC_WRITE(struct tme_bus_tlb *, *_tlbs, tlbs);
                    534:   return (TME_OK);
                    535: }
                    536: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.