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