|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.