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