|
|
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: /*
287: * Disable interrupts.
288: */
289: s = sphi();
290:
291: /*
292: * Set limit.
293: */
294: sfword( gp+0, (unsigned) (n - 1) );
295:
296: /*
297: * Set low word of base, high byte of base.
298: */
299: sfword( gp+2, FP_OFF(paddr) );
300: sfbyte( gp+4, FP_SEL(paddr) );
301:
302: /*
303: * Set access byte: Present[80], Descriptor[10], Writable[02].
304: */
305: sfbyte( gp+5, 0x92 );
306:
307: /*
308: * Clear reserved word.
309: */
310: sfword( gp+6, 0 );
311:
312: /*
313: * Enable interrupts.
314: */
315: spl( s );
316:
317: /*
318: * Return virtual address.
319: */
320: return( fp );
321: }
322:
323: /**
324: *
325: * paddr_t
326: * vtop( fp ) -- virtual to physical [address]
327: * faddr_t fp;
328: *
329: * Input: fp = segment:offset virtual address.
330: *
331: * Return: * = corresponding physical address.
332: * -1 = invalid virtual address.
333: */
334: paddr_t
335: vtop( fp )
336: faddr_t fp;
337: {
338: faddr_t gp;
339: paddr_t paddr;
340:
341: #if REAL_MODE > 0
342: /*
343: * Virtual Address Mode Disabled.
344: */
345: if ( gdtsel == 0 )
346: return( (FP_SEL(fp) << 4L) + FP_OFF(fp) );
347: #endif
348:
349: /*
350: * Convert virtual address to point to appropriate gdt entry.
351: */
352: FP_SEL(gp) = gdtsel;
353: FP_OFF(gp) = FP_SEL(fp);
354:
355: /*
356: * Validity check - Selector must be Present[80] and Descriptor[10].
357: */
358: if ( (ffbyte(gp+5) & 0x90) != 0x90 ) {
359: panic( "vtop:ip=%x: sel %x invalid\n",
360: ((char **) &fp)[-1],
361: FP_SEL(fp) );
362: }
363:
364: /*
365: * Extract physical address from gdt entry.
366: */
367: FP_OFF(paddr) = ffword(gp+2);
368: FP_SEL(paddr) = ffbyte(gp+4);
369:
370: /*
371: * Adjust physical address by virtual address offset.
372: */
373: paddr += FP_OFF(fp);
374:
375: /*
376: * Return physical address.
377: */
378: return( paddr );
379: }
380:
381: /**
382: *
383: * void
384: * vrelse( fp ) -- release virtual address
385: * faddr_t fp;
386: *
387: */
388:
389: void
390: vrelse( fp )
391: faddr_t fp;
392: {
393: faddr_t gp;
394:
395: #if REAL_MODE > 0
396: /*
397: * Virtual Address Mode Disabled.
398: */
399: if ( gdtsel == 0 )
400: return;
401: #endif
402:
403: /*
404: * Validity check.
405: */
406: if ( (FP_SEL(fp) == 0) || (FP_SEL(fp) & 7) )
407: panic( "vrelse: sel %x invalid\n", FP_SEL(fp) );
408:
409: /*
410: * Construct virtual address to point to appropriate gdt entry.
411: */
412: FP_SEL(gp) = gdtsel;
413: FP_OFF(gp) = FP_SEL(fp);
414:
415: /*
416: * Virtual selector already released, or not a segment descriptor.
417: */
418: if ( (ffbyte(gp+5) & 0x10) != 0x10 ) {
419: panic( "vrelse:ip=%x: sel %x already released\n",
420: ((char **) &fp)[-1],
421: FP_SEL(fp) );
422: }
423:
424: /*
425: * Release virtual selector.
426: */
427: sfbyte( gp+5, 0 );
428: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.