|
|
1.1 root 1: /* $Header: /kernel/kersrc/i286/RCS/mmu.c,v 1.1 92/07/17 15:21:33 bin Exp Locker: bin $
2: *
3: * The information contained herein is a trade secret of INETCO
4: * Systems, and is confidential information. It is provided under
5: * a license agreement, and may be copied or disclosed only under
6: * the terms of that agreement. Any reproduction or disclosure of
7: * this material without the express written authorization of
8: * INETCO Systems or persuant to the license agreement is unlawful.
9: *
10: * Copyright (c) 1987
11: * An unpublished work by INETCO Systems, Ltd.
12: * All rights reserved.
13: */
14:
15: /*
16: * Coherent.
17: * Memory Management Unit.
18: *
19: * $Log: mmu.c,v $
20: * Revision 1.1 92/07/17 15:21:33 bin
21: * Initial revision
22: *
23: * Revision 1.1 88/03/24 17:33:41 src
24: * Initial revision
25: *
26: * 88/03/04 Allan Cornish /usr/src/sys/i8086/ibm_at/mmu.c
27: * Real-mode code ifdef'ed out [REAL_MODE].
28: *
29: * 88/02/16 Allan Cornish /usr/src/sys/i8086/ibm_at/mmu.c
30: * vtop() now incorporates offset from virtual address into physical address.
31: *
32: * 87/11/13 Allan Cornish /usr/src/sys/i8086/ibm_at/mmu.c
33: * Initial version.
34: */
35: #include <sys/coherent.h>
36: #include <sys/seg.h>
37: #include <sys/mmu.h>
38:
39: /**
40: *
41: * static faddr_t
42: * gdtalloc() -- search for empty global descriptor table entry
43: */
44: static faddr_t
45: gdtalloc()
46: {
47: register saddr_t sel;
48: static saddr_t osel;
49: faddr_t fp;
50: int s;
51:
52: /*
53: * Disable interrupts.
54: */
55: s = sphi();
56:
57: /*
58: * Search for idle virtual selector.
59: */
60: for ( fp = 0, sel = osel + 8; sel != osel; sel += 8 ) {
61:
62: /*
63: * Selector 0 is NOT usable.
64: */
65: if ( sel == 0 )
66: continue;
67:
68: /*
69: * Selector is available.
70: */
71: if ( ffbyte( sel+5, gdtsel ) != 0 )
72: continue;
73:
74: /*
75: * Mark selector as being Descriptor[10].
76: */
77: sfbyte( sel+5, gdtsel, 0x10 );
78:
79: /*
80: * Record selector for next search.
81: */
82: osel = sel;
83:
84: FP_SEL(fp) = sel;
85: break;
86: }
87:
88: /*
89: * Enable interrupts.
90: */
91: spl( s );
92:
93: return( fp );
94: }
95:
96: /**
97: *
98: * void
99: * vprint( fp ) -- print virtual address information.
100: * faddr_t fp;
101: *
102: * Input: fp = segment:offset pair for virtual address in question.
103: *
104: * Action: Print information about virtual address.
105: */
106:
107: void
108: vprint( fp )
109: faddr_t fp;
110: {
111: faddr_t gp;
112: paddr_t paddr;
113:
114: #if REAL_MODE > 0
115: /*
116: * Virtual Address Mode Disabled.
117: */
118: if ( gdtsel == 0 )
119: return;
120: #endif
121:
122: /*
123: * Create far pointer to appropriate gdt entry.
124: */
125: FP_SEL(gp) = gdtsel;
126: FP_OFF(gp) = FP_SEL(fp) & ~7;
127:
128: FP_OFF(paddr) = ffword(gp+2);
129: FP_SEL(paddr) = ffbyte(gp+4);
130:
131: /*
132: * Print information about gdt entry.
133: */
134: printf("sel=%x paddr=%X lim=%x flags=%x\n",
135: FP_OFF(gp), paddr, ffword(gp), ffbyte(gp+5) );
136: }
137:
138: /**
139: *
140: * void
141: * vremap( sp ) -- (re)map segment virtual address
142: * SEG * sp;
143: *
144: * Input: sp = pointer to segment structure to be (re)mapped.
145: *
146: * Action: Update segment information.
147: */
148: void
149: vremap( segp )
150: SEG * segp;
151: {
152: register SEG * sp = segp;
153: register int m;
154: faddr_t gp;
155: int s;
156:
157: #if REAL_MODE > 0
158: /*
159: * Virtual Address Mode disabled.
160: */
161: if ( gdtsel == 0 ) {
162: /*
163: * Calculate virtual address as shifted physical address.
164: */
165: FP_SEL(sp->s_faddr) = sp->s_paddr >> 4;
166: FP_OFF(sp->s_faddr) = sp->s_paddr & 15;
167: return;
168: }
169: #endif
170:
171: /*
172: * Create far pointer to appropriate gdt entry.
173: */
174: FP_SEL(gp) = gdtsel;
175: FP_OFF(gp) = FP_SEL(sp->s_faddr);
176:
177: /*
178: * Allocate virtual selector if not already specified.
179: */
180: if ( FP_SEL(sp->s_faddr) == 0 ) {
181: if ( (sp->s_faddr = gdtalloc()) == 0 )
182: panic( "vremap: out of gdt's\n" );
183: FP_OFF(gp) = FP_SEL(sp->s_faddr);
184: }
185:
186: /*
187: * Ensure selector is valid gdt at privilege level 0.
188: */
189: if ( FP_SEL(sp->s_faddr) & 7 ) {
190: panic("vremap( faddr=%X, ip=%x ) - not gdt at level 0\n",
191: sp->s_faddr, (&segp)[-1] );
192: }
193:
194: /*
195: * Verify selector is not free.
196: */
197: if ( ffbyte( gp+5 ) == 0 ) {
198: panic("vremap( faddr=%X, ip=%x ) - selector is free\n",
199: sp->s_faddr, (&segp)[-1] );
200: }
201:
202: /*
203: * Disable interrupts.
204: */
205: s = sphi();
206:
207: /*
208: * Set limit.
209: */
210: sfword( gp+0, (unsigned) (sp->s_size - 1) );
211:
212: /*
213: * Set low word of base, high byte of base.
214: */
215: sfword( gp+2, FP_OFF(sp->s_paddr) );
216: sfbyte( gp+4, FP_SEL(sp->s_paddr) );
217:
218: /*
219: * Set access byte:
220: * Code = Present[80],Descriptor[10],Executable[08],Readable[02].
221: * Data = Present[80],Descriptor[10], Writable[02].
222: */
223: m = 0x12;
224: if ( sp->s_flags & SFCORE )
225: m |= 0x80;
226: if ( sp->s_flags & SFTEXT )
227: m |= 0x08;
228: sfbyte( gp+5, m );
229:
230: /*
231: * Clear reserved word.
232: */
233: sfword( gp+6, 0 );
234:
235: /*
236: * Enable interrupts.
237: */
238: spl(s);
239: }
240:
241: /**
242: *
243: * faddr_t
244: * ptov( paddr, n ) -- physical to virtual [address]
245: * paddr_t paddr;
246: * fsize_t n;
247: *
248: * Input: paddr = physical address.
249: * n = size in bytes.
250: *
251: * Return: Corresponding segment:offset virtual address, or 0.
252: *
253: * Notes: Limited to 20 bit physical addresses.
254: * This routine is not functional in protected mode.
255: */
256:
257: faddr_t
258: ptov( paddr, n )
259: paddr_t paddr;
260: fsize_t n;
261: {
262: faddr_t fp;
263: faddr_t gp;
264: int s;
265:
266: #if REAL_MODE > 0
267: /*
268: * Virtual Address Mode Disabled.
269: */
270: if ( gdtsel == 0 )
271: return( ((paddr >> 4) << 16) + (paddr % 16) );
272: #endif
273:
274: /*
275: * Allocate virtual selector.
276: */
277: if ( (fp = gdtalloc()) == 0 )
278: panic( "ptov:ip=%x: out of gdt's\n", ((char*) &paddr)[-1] );
279:
280: /*
281: * Create far pointer to appropriate gdt entry.
282: */
283: FP_SEL(gp) = gdtsel;
284: FP_OFF(gp) = FP_SEL(fp);
285:
286: /*printf("ptov: gp=%lx, paddr=%lx, n=%lx\n", gp, paddr, n); */
287:
288: /*
289: * Disable interrupts.
290: */
291: s = sphi();
292:
293: /*
294: * Set limit.
295: */
296: sfword( gp+0, (unsigned) (n - 1) );
297:
298: /*
299: * Set low word of base, high byte of base.
300: */
301: sfword( gp+2, FP_OFF(paddr) );
302: sfbyte( gp+4, FP_SEL(paddr) );
303:
304: /*
305: * Set access byte: Present[80], Descriptor[10], Writable[02].
306: */
307: sfbyte( gp+5, 0x92 );
308:
309: /*
310: * Clear reserved word.
311: */
312: sfword( gp+6, 0 );
313:
314: /*
315: * Enable interrupts.
316: */
317: spl( s );
318:
319: /*
320: * Return virtual address.
321: */
322: return( fp );
323: }
324:
325: /**
326: *
327: * faddr_t
328: * ptovx(paddr) -- physical to virtual [address] for executable segment
329: * paddr_t paddr;
330: *
331: * Input: paddr = physical address.
332: *
333: * Return: Corresponding segment:offset virtual address, or 0.
334: *
335: */
336:
337: faddr_t
338: ptovx(paddr)
339: paddr_t paddr;
340: {
341: faddr_t fp;
342: faddr_t gp;
343: int s;
344:
345: #if REAL_MODE > 0
346: /*
347: * Virtual Address Mode Disabled.
348: */
349: if ( gdtsel == 0 )
350: return( ((paddr >> 4) << 16) + (paddr % 16) );
351: #endif
352:
353: /*
354: * Allocate virtual selector.
355: */
356: if ( (fp = gdtalloc()) == 0 )
357: panic( "ptov:ip=%x: out of gdt's\n", ((char*) &paddr)[-1] );
358:
359: /*
360: * Create far pointer to appropriate gdt entry.
361: */
362: FP_SEL(gp) = gdtsel;
363: FP_OFF(gp) = FP_SEL(fp);
364:
365: /*
366: * Disable interrupts.
367: */
368: s = sphi();
369:
370: /*
371: * Set limit.
372: */
373: sfword( gp+0, (unsigned) (0xffff) );
374:
375: /*
376: * Set low word of base, high byte of base.
377: */
378: sfword( gp+2, FP_OFF(paddr) );
379: sfbyte( gp+4, FP_SEL(paddr) );
380:
381: /*
382: * Set access byte: Present[80], Descriptor[10], Conforming[4]
383: * Executable[08], Readable[02].
384: */
385: sfbyte( gp+5, 0x9a );
386:
387: /*
388: * Clear reserved word.
389: */
390: sfword( gp+6, 0 );
391:
392: /*
393: * Enable interrupts.
394: */
395: spl( s );
396:
397: /*
398: * Return virtual address.
399: */
400: return( fp );
401: }
402:
403: /**
404: *
405: * paddr_t
406: * vtop( fp ) -- virtual to physical [address]
407: * faddr_t fp;
408: *
409: * Input: fp = segment:offset virtual address.
410: *
411: * Return: * = corresponding physical address.
412: * -1 = invalid virtual address.
413: */
414: paddr_t
415: vtop( fp )
416: faddr_t fp;
417: {
418: faddr_t gp;
419: paddr_t paddr;
420:
421: #if REAL_MODE > 0
422: /*
423: * Virtual Address Mode Disabled.
424: */
425: if ( gdtsel == 0 )
426: return( (FP_SEL(fp) << 4L) + FP_OFF(fp) );
427: #endif
428:
429: /*
430: * Convert virtual address to point to appropriate gdt entry.
431: */
432: FP_SEL(gp) = gdtsel;
433: FP_OFF(gp) = FP_SEL(fp);
434:
435: /*
436: * Validity check - Selector must be Present[80] and Descriptor[10].
437: */
438: if ( (ffbyte(gp+5) & 0x90) != 0x90 ) {
439: panic( "vtop:ip=%x: sel %x invalid\n",
440: ((char **) &fp)[-1],
441: FP_SEL(fp) );
442: }
443:
444: /*
445: * Extract physical address from gdt entry.
446: */
447: FP_OFF(paddr) = ffword(gp+2);
448: FP_SEL(paddr) = ffbyte(gp+4);
449:
450: /*
451: * Adjust physical address by virtual address offset.
452: */
453: paddr += FP_OFF(fp);
454:
455: /*
456: * Return physical address.
457: */
458: return( paddr );
459: }
460:
461: /**
462: *
463: * void
464: * vrelse( fp ) -- release virtual address
465: * faddr_t fp;
466: *
467: */
468:
469: void
470: vrelse( fp )
471: faddr_t fp;
472: {
473: faddr_t gp;
474:
475: #if REAL_MODE > 0
476: /*
477: * Virtual Address Mode Disabled.
478: */
479: if ( gdtsel == 0 )
480: return;
481: #endif
482:
483: /*
484: * Validity check.
485: */
486: if ( (FP_SEL(fp) == 0) || (FP_SEL(fp) & 7) )
487: panic( "vrelse: sel %x invalid\n", FP_SEL(fp) );
488:
489: /*
490: * Construct virtual address to point to appropriate gdt entry.
491: */
492: FP_SEL(gp) = gdtsel;
493: FP_OFF(gp) = FP_SEL(fp);
494:
495: /*
496: * Virtual selector already released, or not a segment descriptor.
497: */
498: if ( (ffbyte(gp+5) & 0x10) != 0x10 ) {
499: panic( "vrelse:ip=%x: sel %x already released\n",
500: ((char **) &fp)[-1],
501: FP_SEL(fp) );
502: }
503:
504: /*
505: * Release virtual selector.
506: */
507: sfbyte( gp+5, 0 );
508: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.