1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45:
46:
47: 48: 49: 50:
51:
52: #include <typedef.h>
53: #include "sysmgr.h"
54: #include "segmgr.h"
55: #include "pagedef.h"
56: #include "cache_info.h"
57: #include "mmu.h"
58: #include <sys/rominfo.h>
59: #include <sys/imalloc.h>
60: #include "cpu_conf.h"
61:
62: #define GET_SMB_MIN_USER_LEVEL MMU_MIN_USER_LEVEL
63:
64: 65: 66:
67: typedef struct {
68: VB mem[PAGESIZE];
69: } PAGE;
70:
71: typedef UINT PN;
72:
73: 74: 75:
76: EXPORT UW smPageCount( UW byte )
77: {
78: return PageCount(byte);
79: }
80:
81: 82: 83:
84: typedef struct {
85: BOOL cont:1;
86: BOOL use:1;
87: PN next:30;
88: UINT rsv:2;
89: PN prev:30;
90: } PAGEQUE;
91:
92: #define USE TRUE
93: #define FREE FALSE
94: #define CONT TRUE
95: #define ONE FALSE
96:
97: LOCAL CONST PAGEQUE _clrPageQue = { ONE, FREE, 0, 0, 0 };
98:
99: #define clrPageQue(q) ( (q) = _clrPageQue )
100:
101:
102: #define NumOfPages(q) ( ( (q)->cont )? ((q)+1)->next: 1 )
103:
104: 105: 106: 107: 108: 109:
110: typedef struct {
111: INT maxpage;
112: INT freepage;
113: PAGEQUE *pageque; 114:
115: PAGE *top_page;
116: } PAGETBL;
117:
118: #define freeque pageque[0]
119:
120: #define _PageAdr(pn, pt) ( (void*)((pt)->top_page + ((pn) - 1)) )
121: #define _PageNo(adr, pt) ( (PN)(((PAGE*)(adr) - (pt)->top_page) + 1) )
122:
123:
124:
125: 126: 127:
128: LOCAL PAGETBL SysMemTbl;
129:
130: 131: 132: 133: 134:
135: LOCAL FastLock MemLock = { -1, -1 };
136: #define LockMEM() Lock(&MemLock)
137: #define UnlockMEM() Unlock(&MemLock)
138:
139:
140: #define OBJNAME_MMLOCK "Mem"
141:
142:
143:
144: Inline void* PageAdr( PN pn, PAGETBL *pt )
145: {
146: return _PageAdr(pn, pt);
147: }
148: Inline PN PageNo( CONST void *adr, PAGETBL *pt )
149: {
150: adr = CachingAddr(adr);
151: return _PageNo(adr, pt);
152: }
153:
154: 155: 156: 157:
158: LOCAL BOOL chkadr( CONST void *adr, PAGETBL *pt )
159: {
160: adr = CachingAddr(adr);
161: if ( adr >= (void*)pt->top_page && adr < (void*)(pt->top_page + pt->maxpage) ) {
162: if ( ((UINT)adr % PAGESIZE) == 0 ) {
163: return TRUE;
164: }
165: }
166: return FALSE;
167: }
168:
169: 170: 171:
172: Inline PAGEQUE setPageQue( BOOL u, BOOL c, PN n, PN p )
173: {
174: PAGEQUE q;
175: q.use = u;
176: q.cont = c;
177: q.next = n;
178: q.prev = p;
179: return q;
180: }
181:
182: 183: 184:
185: Inline void initPageQue( PN pn, PAGETBL *pt )
186: {
187: pt->pageque[pn].next = pt->pageque[pn].prev = pn;
188: }
189:
190: 191: 192: 193:
194: Inline void insertPageQue( PN que, PN ent, PAGETBL *pt )
195: {
196: PAGEQUE *qp = &pt->pageque[que];
197: PAGEQUE *ep = &pt->pageque[ent];
198:
199: ep->prev = qp->prev;
200: ep->next = que;
201: pt->pageque[qp->prev].next = ent;
202: qp->prev = ent;
203: }
204:
205: 206: 207: 208:
209: LOCAL void removePageQue( PN ent, PAGETBL *pt )
210: {
211: PAGEQUE *ep = &pt->pageque[ent];
212:
213: if ( ep->next != ent ) {
214: pt->pageque[ep->prev].next = ep->next;
215: pt->pageque[ep->next].prev = ep->prev;
216: }
217: }
218:
219: 220: 221:
222: Inline BOOL isEmptyPageQue( PN que, PAGETBL *pt )
223: {
224: return ( pt->pageque[que].next == que );
225: }
226:
227: 228: 229: 230: 231: 232:
233: LOCAL PN searchFreeQue( INT n, PAGETBL *pt )
234: {
235: PAGEQUE *pageque = pt->pageque;
236: PN pn = 0;
237:
238: while ( (pn = pageque[pn].next) > 0 ) {
239: if ( NumOfPages(&pageque[pn]) >= n ) {
240: return pn;
241: }
242: }
243: return 0;
244: }
245:
246: 247: 248: 249: 250:
251: LOCAL void appendFreePages( PN pn, INT n, PAGETBL *pt )
252: {
253: PN ins;
254: PAGEQUE *pq = &pt->pageque[pn];
255:
256:
257: pq->use = FREE;
258: pq->cont = ( n > 1 )? CONT: ONE;
259: if ( n > 1 ) {
260: pq[1] = setPageQue(FREE, CONT, n, 0);
261: }
262: if ( n > 2 ) {
263: pq[n-1] = setPageQue(FREE, CONT, n, 0);
264: }
265:
266:
267: ins = searchFreeQue(n, pt);
268:
269:
270: insertPageQue(ins, pn, pt);
271: }
272:
273: 274: 275:
276: Inline void setUsePages( PN pn, INT n, UINT atr, PAGETBL *pt )
277: {
278: PAGEQUE *pq = &pt->pageque[pn];
279:
280:
281: pq->use = USE;
282: pq->cont = ( n > 1 )? CONT: ONE;
283: if ( n > 1 ) {
284: pq[1] = setPageQue(USE, CONT, n, 0);
285: }
286: if ( n > 2 ) {
287: pq[n-1] = setPageQue(USE, CONT, n, 0);
288: }
289:
290: initPageQue(pn, pt);
291: }
292:
293: 294: 295:
296: LOCAL void* getPage( INT nblk, UINT atr, PAGETBL *pt )
297: {
298: PN pn;
299: INT free;
300:
301:
302: pn = searchFreeQue(nblk, pt);
303: if ( pn == 0 ) {
304: return NULL;
305: }
306: free = NumOfPages(&pt->pageque[pn]);
307:
308: 309:
310: removePageQue(pn, pt);
311:
312:
313: setUsePages(pn, nblk, atr, pt);
314: free -= nblk;
315:
316: if ( free > 0 ) {
317:
318: appendFreePages(pn + (UINT)nblk, free, pt);
319: }
320:
321: pt->freepage -= nblk;
322:
323: return PageAdr(pn, pt);
324: }
325:
326: 327: 328: 329:
330: LOCAL INT relPage( CONST void *adr, PAGETBL *pt )
331: {
332: PN pn;
333: PAGEQUE *pq;
334: INT nblk, free;
335:
336: pn = PageNo(adr, pt);
337: pq = &pt->pageque[pn];
338:
339: if ( pq->use == FREE ) {
340: return E_PAR;
341: }
342:
343:
344: free = nblk = NumOfPages(pq);
345:
346:
347: if ( pn + (UINT)nblk <= pt->maxpage && (pq+(UINT)nblk)->use == FREE ) {
348:
349:
350: removePageQue(pn+(PN)nblk, pt);
351:
352:
353: nblk += NumOfPages(pq+nblk);
354: }
355:
356:
357: if ( pn > 1 && (pq-1)->use == FREE ) {
358:
359:
360: INT n = ( (pq-1)->cont )? (pq-1)->next: 1;
361:
362:
363: removePageQue(pn-(PN)n, pt);
364:
365:
366: pn -= (UINT)n;
367: nblk += n;
368:
369: 370: 371:
372: pq->use = FREE;
373: }
374:
375:
376: appendFreePages(pn, nblk, pt);
377:
378: pt->freepage += free;
379:
380: return free;
381: }
382:
383: 384: 385:
386: LOCAL ER initPageTbl( void *top, void *end, PAGETBL *pt )
387: {
388: ER ercd;
389: INT memsz, npage, tblpage;
390:
391:
392: top = (void*)(((UINT)top + 7) & ~0x00000007U);
393: memsz = (INT)((UINT)end - (UINT)top);
394:
395:
396: pt->pageque = (PAGEQUE*)top;
397:
398:
399: npage = (INT)(((UINT)memsz - sizeof(PAGEQUE)) / (PAGESIZE + sizeof(PAGEQUE)));
400:
401:
402: tblpage = PageCount(sizeof(PAGETBL) + sizeof(PAGEQUE) * npage);
403:
404:
405: ercd = _MakeSpace(top, tblpage, 0, PTE_SYS_RW);
406: if ( ercd < E_OK ) {
407: goto err_ret;
408: }
409:
410: 411:
412: pt->top_page = (PAGE*)(((UINT)(pt->pageque + npage + 1)
413: + (PAGESIZE-1)) / PAGESIZE * PAGESIZE);
414:
415:
416: npage = (INT)(((UINT)end - (UINT)pt->top_page) / (UINT)PAGESIZE);
417: pt->maxpage = npage;
418: pt->freepage = npage;
419:
420:
421: clrPageQue(pt->freeque);
422: appendFreePages(1, npage, pt);
423:
424: return E_OK;
425:
426: err_ret:
427: return ercd;
428: }
429:
430:
431:
432: 433: 434: 435:
436: EXPORT void* GetSysMemBlk( INT nblk, UINT attr )
437: {
438: ER ercd;
439: PAGETBL *pt = &SysMemTbl;
440: void *adr;
441: UW pte;
442:
443: LockMEM();
444:
445:
446: adr = getPage(nblk, 0, pt);
447: if ( adr == NULL ) {
448: goto err_ret0;
449: }
450:
451:
452: pte = ( ((attr & TA_RNG3) >> 8) < GET_SMB_MIN_USER_LEVEL )? PTE_SYS_RW: PTE_USR_RW;
453: if ( (attr & TA_NOCACHE) != 0 ) pte = PTE_CacheOff(pte);
454: ercd = _MakeSpace(adr, nblk, 0, pte);
455: if ( ercd < E_OK ) {
456: goto err_ret1;
457: }
458:
459: UnlockMEM();
460: return adr;
461:
462: err_ret1:
463: relPage(adr, pt);
464:
465: err_ret0:
466: UnlockMEM();
467: TM_DEBUG_PRINT(("GetSysMemBlk E_NOMEM\n"));
468: return NULL;
469: }
470:
471: 472: 473:
474: EXPORT ER RelSysMemBlk( CONST void *addr )
475: {
476: PAGETBL *pt;
477: INT free;
478: ER ercd;
479:
480: pt = ( chkadr(addr, &SysMemTbl) )? &SysMemTbl: NULL;
481: if ( pt == NULL ) {
482: ercd = E_PAR;
483: goto err_ret0;
484: }
485:
486: LockMEM();
487:
488:
489: free = relPage(addr, pt);
490: if ( free < E_OK ) {
491: ercd = free;
492: goto err_ret1;
493: }
494:
495:
496: FlushCache(addr, free * (W)PAGESIZE);
497:
498:
499: ercd = _UnmakeSpace((void *)addr, free, 0);
500: if ( ercd < E_OK ) {
501: goto err_ret1;
502: }
503:
504: UnlockMEM();
505:
506: return E_OK;
507:
508: err_ret1:
509: UnlockMEM();
510: err_ret0:
511: TM_DEBUG_PRINT(("RelSysMemBlk ercd = %d\n", ercd));
512: return ercd;
513: }
514:
515: 516: 517:
518: EXPORT ER RefSysMemInfo( T_RSMB *pk_rsmb )
519: {
520: LockMEM();
521: pk_rsmb->blksz = PAGESIZE;
522: pk_rsmb->total = SysMemTbl.maxpage;
523: pk_rsmb->free = SysMemTbl.freepage;
524: UnlockMEM();
525:
526: return E_OK;
527: }
528:
529:
530:
531: 532: 533: 534:
535: EXPORT ER init_memmgr( void )
536: {
537:
538: IMPORT void *lowmem_top, *lowmem_limit;
539: void *memend;
540: ER ercd;
541:
542:
543: ercd = _tk_get_cfn(SCTAG_REALMEMEND, (INT*)&memend, 1);
544: if ( ercd < 1 || (UINT)memend > (UINT)lowmem_limit ) {
545: memend = lowmem_limit;
546: }
547:
548:
549: ercd = initPageTbl(lowmem_top, memend, &SysMemTbl);
550: if ( ercd < E_OK ) {
551: goto err_ret;
552: }
553:
554: lowmem_top = memend;
555:
556: return E_OK;
557:
558: err_ret:
559: TM_DEBUG_PRINT(("init_memmgr ercd = %d\n", ercd));
560: return ercd;
561: }
562:
563: 564: 565: 566:
567: EXPORT ER start_memmgr( void )
568: {
569: ER ercd;
570:
571:
572: ercd = CreateLock(&MemLock, OBJNAME_MMLOCK);
573: if ( ercd < E_OK ) {
574: goto err_ret;
575: }
576:
577: return E_OK;
578:
579: err_ret:
580: TM_DEBUG_PRINT(("start_memmgr ercd = %d\n", ercd));
581: return ercd;
582: }
583:
584: 585: 586:
587: EXPORT ER finish_memmgr( void )
588: {
589: return E_OK;
590: }