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