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

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: 

unix.superglobalmegacorp.com

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