|
|
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.