|
|
1.1 ! root 1: /* ! 2: * MMU dependent code for Coherent 386 ! 3: * ! 4: * Copyright (c) Ciaran O'Donnell, Bievres (FRANCE), 1991 ! 5: */ ! 6: ! 7: #include <kernel/alloc.h> ! 8: ! 9: #include <sys/coherent.h> ! 10: #include <sys/clist.h> ! 11: #include <sys/errno.h> ! 12: #include <sys/inode.h> ! 13: #include <sys/seg.h> ! 14: #include <signal.h> ! 15: #include <sys/buf.h> ! 16: #include <l.out.h> ! 17: #include <ieeefp.h> ! 18: ! 19: /* These defines belong somewhere else: */ ! 20: #define LOMEM 0x15 /* CMOS address of size in K of memory below 1MB. */ ! 21: #define EXTMEM 0x17 /* CMOS address of size in K of memory above 1MB. */ ! 22: #define ONE_K 1024 ! 23: #define ONE_MEG 1048576 ! 24: #define USE_NDATA 1 ! 25: ! 26: /* ! 27: * DMA will not work to memory above 16M, so limit the amount of memory ! 28: * above 1M to 15M. A much cleverer scheme should be implemented. ! 29: */ ! 30: int HACK_LIMIT = (15*ONE_MEG); ! 31: ! 32: /* ! 33: * For 0 < i < 64, buddysize[i] is log(base 2) of nearest power of two ! 34: * which is greater than or equal to i. ! 35: */ ! 36: char buddysize[64] = { ! 37: -1, 0, 1, 2, 2, 3, 3, 3, ! 38: 3, 4, 4, 4, 4, 4, 4, 4, ! 39: 4, 5, 5, 5, 5, 5, 5, 5, ! 40: 5, 5, 5, 5, 5, 5, 5, 5, ! 41: 5, 6, 6, 6, 6, 6, 6, 6, ! 42: 6, 6, 6, 6, 6, 6, 6, 6, ! 43: 6, 6, 6, 6, 6, 6, 6, 6, ! 44: 6, 6, 6, 6, 6, 6, 6, 6 }; ! 45: ! 46: #define min(a, b) ((a) < (b) ? (a) : (b)) ! 47: ! 48: /* ! 49: * Functions. ! 50: * Import. ! 51: * Export. ! 52: * Local. ! 53: */ ! 54: void areacheck(); ! 55: void areafree(); ! 56: void areainit(); ! 57: BLOCKLIST * arealloc(); ! 58: int areasize(); ! 59: cseg_t * c_alloc(); ! 60: cseg_t * c_extend(); ! 61: void c_free(); ! 62: int c_grow(); ! 63: int countsize(); ! 64: void doload(); ! 65: char * getPhysMem(); ! 66: void i8086(); ! 67: void idtinit(); ! 68: void init_phy_seg(); ! 69: void mchinit(); ! 70: void msigend(); ! 71: void physMemInit(); ! 72: SR *loaded(); ! 73: unsigned int read16_cmos(); ! 74: void segload(); ! 75: void sunload(); ! 76: void unload(); ! 77: void valloc(); ! 78: ! 79: ! 80: /* ! 81: * "load" a handle "hp" to a segment into the space tree for a process ! 82: */ ! 83: void ! 84: doload(srp) ! 85: register SR *srp; ! 86: { ! 87: register int n; ! 88: register cseg_t *pp; ! 89: register int base1, flags; ! 90: register int akey; ! 91: ! 92: pp = srp->sr_segp->s_vmem; ! 93: flags = srp->sr_segp->s_flags; ! 94: base1 = btocrd(srp->sr_base); ! 95: n = btoc(srp->sr_size); ! 96: ! 97: /* ! 98: * we load all pages ! 99: */ ! 100: /* a shm segment ref may be Read-Write or Read-Only */ ! 101: if (srp->sr_flag & SRFRODT) ! 102: akey = SEG_RO; ! 103: else { ! 104: switch (flags&(SFSYST|SFTEXT)) { ! 105: case SFTEXT: akey = SEG_RO; break; ! 106: case SFSYST: akey = SEG_SRW; break; ! 107: default: akey = SEG_RW; break; ! 108: } ! 109: } ! 110: ! 111: do ! 112: ptable1_v[base1++] = (*pp++ & ~SEG_NPL) | akey; ! 113: while (--n); ! 114: mmuupd(); ! 115: } ! 116: ! 117: /* ! 118: * unload a handle key "key" to a segment from the MMU hardware ! 119: */ ! 120: void ! 121: unload(srp) ! 122: register SR *srp; ! 123: { ! 124: register int n, base1; ! 125: ! 126: base1 = btocrd(srp->sr_base); ! 127: ! 128: n = btoc(srp->sr_size); ! 129: do { ! 130: ptable1_v[base1++] = SEG_ILL; ! 131: } while (--n); ! 132: mmuupd(); ! 133: } ! 134: ! 135: /* ! 136: * Allocate 'clicks_wanted' clicks of core space. ! 137: * Returns physical segment descriptor if success, else NULL. ! 138: * The physical segment descriptor is a table of page table entries ! 139: * suitable for insertion into a page table. ! 140: */ ! 141: cseg_t * ! 142: c_alloc(clicks_wanted) ! 143: unsigned clicks_wanted; ! 144: { ! 145: unsigned pno; ! 146: cseg_t *pp; ! 147: register cseg_t *qp; ! 148: ! 149: /* Do we have enough free physical clicks for this request? */ ! 150: if (clicks_wanted > allocno()) ! 151: goto no_c_alloc; ! 152: ! 153: /* Allocate some space for the table to return. */ ! 154: if ((pp = (cseg_t *)arealloc(clicks_wanted)) == 0) ! 155: goto no_c_alloc; ! 156: qp = pp; ! 157: ! 158: /* fill in entries in the requested table */ ! 159: do { ! 160: pno = *--sysmem.pfree; ! 161: if (!pvalid(pno)) ! 162: panic("c_alloc"); ! 163: *qp++ = (clickseg(pno) & ~SEG_BITS) | SEG_PRE; ! 164: } while (--clicks_wanted); ! 165: return pp; ! 166: ! 167: no_c_alloc: ! 168: return 0; ! 169: } ! 170: ! 171: /* ! 172: * Given an array "pp" containing "numClicks" click descriptors, ! 173: * if "pp" is the click list for a user segment currently loaded ! 174: * invalidate click entries for "pp" in the current page table ! 175: * return each click in "pp" to the sysmem pool, if it came from there. ! 176: * return the array "pp" to the buddy pool. ! 177: */ ! 178: void ! 179: c_free(pp, numClicks) ! 180: cseg_t *pp; ! 181: unsigned numClicks; ! 182: { ! 183: unsigned pno; ! 184: register cseg_t *qp; ! 185: register int sz; ! 186: SR *srp; ! 187: ! 188: if (srp = loaded(pp)) { ! 189: unload(srp); ! 190: srp->sr_segp = 0; ! 191: } ! 192: sz = numClicks; ! 193: if (&sysmem.pfree[sz] > sysmem.efree) ! 194: panic("c_free - nalloc"); ! 195: qp = pp; ! 196: do { ! 197: if ((*qp & SEG_NPL) == 0) { ! 198: pno = segclick(*qp); ! 199: if (!pvalid(pno)) ! 200: panic("c_free"); ! 201: *sysmem.pfree++ = pno; ! 202: } else { ! 203: T_HAL(0x40000, printf("c_free NPL %x ", *qp)); ! 204: } ! 205: qp++; ! 206: } while (--sz); ! 207: areafree((BLOCKLIST *)pp, numClicks); ! 208: } ! 209: ! 210: /* ! 211: * Given a user virtual address, a physical address, and a byte ! 212: * count, map the specified virtual address into the user data ! 213: * page table for the current process. ! 214: * ! 215: * This is meant to be called from the console ioctl, KDMAPDISP. ! 216: * The user virtual address must be click aligned. ! 217: * The range of physical addresses must lie outside installed RAM ! 218: * or within the "PHYS_MEM" pool. ! 219: * ! 220: * Return 1 on success, else 0. ! 221: */ ! 222: int ! 223: mapPhysUser(virtAddr, physAddr, numBytes) ! 224: { ! 225: int ret = 0; ! 226: SR * srp = u.u_segl + SIPDATA; ! 227: SEG * sp = srp->sr_segp; ! 228: cseg_t * pp = sp->s_vmem, * qp; ! 229: int pno, clickOffset, numClicks, i; ! 230: ! 231: /* Check alignment. */ ! 232: if ((virtAddr & (NBPC-1)) || (physAddr & (NBPC-1))) { ! 233: T_HAL(0x40000, printf("mPU: failed alignment ")); ! 234: goto mPUdone; ! 235: } ! 236: ! 237: /* Check validity of range of virtual addresses. */ ! 238: if (virtAddr < srp->sr_base || ! 239: (virtAddr + numBytes) >= (srp->sr_base + srp->sr_size)) { ! 240: T_HAL(0x40000, printf("mPU: bad vaddr ")); ! 241: goto mPUdone; ! 242: } ! 243: ! 244: /* Check validity of range of physical addresses. */ ! 245: /* if not in PHYS_MEM pool... */ ! 246: if (!physValid(physAddr, numBytes)) { ! 247: ! 248: /* get installed RAM physical addresses */ ! 249: unsigned int physLow = ctob((read16_cmos(LOMEM) + 3) >> 2); ! 250: unsigned int physHigh = ctob((read16_cmos(EXTMEM) + 3) >> 2) ! 251: + ONE_MEG; ! 252: ! 253: T_HAL(0x40000, printf("physLow=%x physHigh=%x ", ! 254: physLow, physHigh)); ! 255: ! 256: /* Fail if physical range overlaps installed base RAM. */ ! 257: if (physAddr < physLow) { ! 258: T_HAL(0x40000, printf("mPU: overlap base RAM ")); ! 259: goto mPUdone; ! 260: } ! 261: ! 262: /* Fail if physical range overlaps installed extended RAM. */ ! 263: if (physAddr < physHigh && (physAddr + numBytes) >= ONE_MEG) { ! 264: T_HAL(0x40000, printf("mPU: overlap extended RAM ")); ! 265: goto mPUdone; ! 266: } ! 267: } ! 268: ! 269: /* ! 270: * For each click in user data segment which is to be remapped ! 271: * if current click was taken from sysmem pool ! 272: * return current click to sysmem pool ! 273: * write new physical address into current click entry ! 274: * mark current click as not coming from sysmem pool ! 275: * map current click into page table ! 276: */ ! 277: clickOffset = btocrd(virtAddr - srp->sr_base); ! 278: numClicks = numBytes >> BPCSHIFT; ! 279: for (qp = pp + clickOffset, i = 0; i < numClicks; i++, qp++) { ! 280: if ((*qp & SEG_NPL) == 0) { ! 281: pno = segclick(*qp); ! 282: if (!pvalid(pno)) { ! 283: T_HAL(0x40000, printf("mPU: bad release ")); ! 284: } else { ! 285: *sysmem.pfree++ = pno; ! 286: T_HAL(0x40000, ! 287: printf("mPU: freeing virtual click %x ", ! 288: virtAddr + ctob(i))); ! 289: } ! 290: } else { ! 291: T_HAL(0x40000, ! 292: printf("mPU: rewriting virtual NPL click %x ", ! 293: virtAddr + ctob(i))); ! 294: } ! 295: *qp = (physAddr + ctob(i)) | (SEG_RW | SEG_NPL); ! 296: ptable1_v[btocrd(virtAddr) + i] = *qp; ! 297: } ! 298: mmuupd(); ! 299: ret = 1; ! 300: ! 301: mPUdone: ! 302: return ret; ! 303: } ! 304: ! 305: /* ! 306: * Add a click to a segment. ! 307: * Enlarge buddy table for segment, if needed. ! 308: * ! 309: * Arguments: ! 310: * pp points to segment reference table (segp->s_vmem, e.g.) ! 311: * osz is old segment size, in clicks ! 312: * ! 313: * Return pointer to enlarged segment reference table, or NULL if failed. ! 314: */ ! 315: cseg_t * ! 316: c_extend(pp, osz) ! 317: register cseg_t *pp; ! 318: int osz; ! 319: { ! 320: register cseg_t *pp1; ! 321: register unsigned pno; ! 322: register int i; ! 323: SR *srp; ! 324: ! 325: /* Fail if no more free clicks available. */ ! 326: if (sysmem.pfree < &sysmem.tfree[1]) ! 327: goto no_c_extend; ! 328: ! 329: /* Don't grow segment beyond hardware segment size (4 megabytes). */ ! 330: if (osz >= (NBPS/NBPC)) ! 331: goto no_c_extend; ! 332: ! 333: if (srp = loaded(pp)) { ! 334: unload(srp); ! 335: srp->sr_segp = 0; ! 336: } ! 337: ! 338: /* ! 339: * If the old size was a power of 2, it has used up an entire ! 340: * buddy area, so we will need to allocate more space. ! 341: */ ! 342: if (IS_POW2(osz)) { ! 343: if ((pp1 = (cseg_t*) arealloc(osz+1))==0) ! 344: goto no_c_extend; ! 345: for (i=0; i < osz; i++) ! 346: pp1[i] = pp[i]; ! 347: areafree(pp, osz); ! 348: pp = pp1; ! 349: } ! 350: ! 351: for (i=osz; --i >= 0;) ! 352: pp[i+1] = pp[i]; ! 353: ! 354: pno = *--sysmem.pfree; ! 355: if (!pvalid(pno)) ! 356: panic("c_extend"); ! 357: pp[0] = clickseg(pno) | SEG_RW; ! 358: return pp; ! 359: ! 360: no_c_extend: ! 361: return 0; ! 362: } ! 363: ! 364: /* ! 365: * Given segment size in bytes, estimate total space needed ! 366: * to keep track of the segment (I think - hws). ! 367: * ! 368: * return value is num_bytes plus some overhead... ! 369: */ ! 370: int ! 371: countsize(num_bytes) ! 372: int num_bytes; ! 373: { ! 374: int ret; ! 375: ! 376: if (num_bytes <= NBPC/sizeof(long)) ! 377: ret = num_bytes+1; ! 378: else ! 379: ret = num_bytes ! 380: + ((num_bytes + NBPC/sizeof(long) - 1) >> BPC1SHIFT) + 1; ! 381: return ret; ! 382: } ! 383: ! 384: /* ! 385: * buddy allocation ! 386: */ ! 387: ! 388: /* ! 389: * Deallocate a segment descriptor area. ! 390: * "sp" is not really a BLOCKLIST*, rather a cseg_t *. ! 391: * "numClicks" is the number of clicks referenced in the area. ! 392: */ ! 393: void ! 394: areafree(sp, numClicks) ! 395: BLOCKLIST *sp; ! 396: int numClicks; ! 397: { ! 398: register int n; /* adresse du buddy, taille du reste */ ! 399: register int ix, nx; ! 400: register BLOCKLIST *buddy; ! 401: ! 402: areacheck(2, sp); ! 403: ! 404: /* ! 405: * Pointer "sp" points to an element in the sysmem table of ! 406: * free clicks. ! 407: * Integer "ix" is the index of "sp" into that table. ! 408: * Will use "ix" to index into one or more buddy tables. ! 409: */ ! 410: ix = sp - sysmem.u.budtab; ! 411: n = areasize(numClicks); ! 412: do { ! 413: /* "nx" is index of buddy element to the one at "ix". */ ! 414: nx = BUDDY(ix, n); ! 415: if (sysmem.budfree[nx>>WSHIFT] & 1<<(nx&(WCOUNT-1))) { ! 416: /* coalesce two buddies */ ! 417: buddy = sysmem.u.budtab + nx; ! 418: if (buddy->kval != n) ! 419: break; ! 420: sysmem.budfree[nx>>WSHIFT] &= ~ (1<<(nx & (WCOUNT-1))); ! 421: DELETE2(buddy); ! 422: if (nx < ix) ! 423: ix = nx; ! 424: } else ! 425: break; ! 426: } while (++n < NBUDDY); ! 427: sysmem.budfree[ix>>WSHIFT] |= 1 << (ix & (WCOUNT-1)); ! 428: buddy = sysmem.u.budtab + ix; ! 429: INSERT2(BLOCKLIST, buddy, &sysmem.bfree[n]); ! 430: buddy->kval = n; ! 431: areacheck(3, buddy); ! 432: } ! 433: ! 434: /* ! 435: * arealloc() ! 436: * ! 437: * Given size in "clicks" of a segment to manage, ! 438: * return pointer to an array of enough descriptors. ! 439: * If not enough free descriptors available, return 0. ! 440: */ ! 441: BLOCKLIST * ! 442: arealloc(clicks) ! 443: register int clicks; ! 444: { ! 445: register BLOCKLIST *sp; ! 446: register BLOCKLIST *p, *q; ! 447: register int size; ! 448: BLOCKLIST *rsp; ! 449: register int nx; ! 450: ! 451: areacheck(0, 0); ! 452: size = areasize(clicks); ! 453: /* ! 454: * 1. Find little end, bloc p, free >= size ! 455: */ ! 456: for (q = p = sysmem.bfree + size;p->forw == p; size++, p++) ! 457: if (p >= sysmem.bfree + NBUDDY - 1) { ! 458: return(0); /* y en a pas */ ! 459: } ! 460: ! 461: rsp = p->forw; ! 462: DELETE2(rsp); ! 463: nx = rsp - sysmem.u.budtab; ! 464: sysmem.budfree[nx>>WSHIFT] &= ~(1 << (nx & (WCOUNT-1))); ! 465: size = 1<<size; ! 466: sp = rsp + size; /* buddy address */ ! 467: while (p-- != q) { ! 468: /* ! 469: * 2.1 The block is too big, uncouple & free buddy ! 470: */ ! 471: sp -= (size >>= 1); ! 472: nx = sp - sysmem.u.budtab; ! 473: sysmem.budfree[nx>>WSHIFT] |= 1 << (nx & (WCOUNT-1)); ! 474: INSERT2(BLOCKLIST, sp, p); ! 475: sp->kval = p - sysmem.bfree; ! 476: } ! 477: areacheck(1, rsp); ! 478: return rsp; ! 479: } ! 480: ! 481: void ! 482: areainit(n) ! 483: { ! 484: extern char __end[]; ! 485: register int i; ! 486: ! 487: for (i=0; i < (1<<(NBUDDY-WSHIFT)); i++) ! 488: sysmem.budfree[i] = 0; ! 489: for (i=0; i<NBUDDY; i++) ! 490: INIT2(&sysmem.bfree[i]); ! 491: sysmem.u.budtab = (BLOCKLIST *)__end; ! 492: n /= sizeof(BLOCKLIST); ! 493: if (n > (1 << NBUDDY)) ! 494: panic("areainit"); ! 495: for (i=0; i<n; i++) ! 496: areafree(&sysmem.u.budtab[i], sizeof(BLOCKLIST)/sizeof(long)); ! 497: } ! 498: ! 499: /* ! 500: * areasize() ! 501: * ! 502: * Do a log(base 2) calculation on n. ! 503: * If n is zero, return -1. ! 504: * ! 505: * Else, consider the nearest power of two which is greater than or ! 506: * equal to n ! 507: * p/2 < n <= p ! 508: * Then set p = 4 * (2**x). Note BLKSZ is 2. ! 509: * Return max(x,0). ! 510: * ! 511: * If n is too large (more than 3F00), we will go beyond the limits of ! 512: * table buddysize[]. ! 513: * ! 514: * In practice, n is the total number of clicks needed in a segment, ! 515: * and the return value will be used to access a buddy system list. ! 516: */ ! 517: int ! 518: areasize(n) ! 519: register unsigned int n; ! 520: { ! 521: register int m; ! 522: #ifdef FROTZ ! 523: int ret, oldn = n; ! 524: #endif ! 525: ! 526: if (n > 0x3F00) ! 527: panic("areasize"); ! 528: ! 529: n = (n + (1 << BLKSZ) - 1) >> BLKSZ; ! 530: m = n & 0x3F; ! 531: #ifdef FROTZ ! 532: if ((n >>= 6) == 0) ! 533: ret = buddysize[m]; ! 534: else { ! 535: int index; ! 536: ! 537: index = n; ! 538: if (m) ! 539: index++; ! 540: ret = buddysize[index] + 6; ! 541: } ! 542: return ret; ! 543: #else ! 544: if ((n >>= 6) == 0) ! 545: return buddysize[m]; ! 546: return buddysize[n + ((m!=0)?1:0)] + 6; ! 547: #endif ! 548: } ! 549: ! 550: #define MAXBUDDY 2048 ! 551: #define CHECK(p) ((p>=&sysmem.bfree[0] && p<&sysmem.bfree[NBUDDY]) || \ ! 552: (p>=sysmem.u.budtab && p<&sysmem.u.budtab[1<<NBUDDY])) ! 553: void ! 554: areacheck(flag, sp) ! 555: register BLOCKLIST *sp; ! 556: { ! 557: register BLOCKLIST *next, *start; ! 558: register int i, nx; ! 559: ! 560: if (sp) { ! 561: if (&sysmem.u.budtab[sp-sysmem.u.budtab] != sp) ! 562: printf("*check* %d %x %x\n", flag, sp, sysmem.u.budtab); ! 563: } ! 564: ! 565: for (i=0; i<NBUDDY; i++) { ! 566: start = next = &sysmem.bfree[i]; ! 567: do { ! 568: next = next->forw; ! 569: if (!CHECK(next)) ! 570: printf("next = %x (%d)\n", next, flag); ! 571: if (next->back != start) ! 572: printf("%x->forw->back != %x\n", next, start); ! 573: if (next != &sysmem.bfree[i]) { ! 574: if (next->kval != i) ! 575: printf("bad kval %x, %d (%d)\n", ! 576: next, next->kval, flag); ! 577: nx = next - sysmem.u.budtab; ! 578: if ((sysmem.budfree[nx>>WSHIFT] & (1 << (nx & (WCOUNT-1)))) == 0) ! 579: printf("in bfree but not budfree %x (%d)\n", next, flag); ! 580: } ! 581: start = next; ! 582: } while (next != &sysmem.bfree[i]); ! 583: } ! 584: } ! 585: ! 586: MAKESR(physMem, _physMem); ! 587: extern int PHYS_MEM; /* Number of bytes of contiguous RAM needed */ ! 588: ! 589: /* ! 590: * A block of contiguous physical memory has been allocated for special ! 591: * i/o devices. ! 592: * Problem: clicks of physical memory are in reverse order in the ! 593: * page table. ! 594: * This routine reverses the page table entries for the pages ! 595: * involved. It relies *heavily* on all pages having virtual addresses ! 596: * in the FFCx xxxx segment. ! 597: * ! 598: * If all goes well, assign physAvailStart to the virtual address of ! 599: * the beginning of the region, and physAvailBytes to the number of bytes ! 600: * in the region. Otherwise, leave physAvailStart and physAvailBytes at 0. ! 601: * ! 602: * As memory is allocated, physAvailStart advances to point to the next ! 603: * available byte of contiguous memory, physAvailBytes is decremented, ! 604: * and physPoolStart remains set to the virtual address of the start of ! 605: * the contiguous pool. ! 606: */ ! 607: static int physPoolStart; /* start of contiguous memory area */ ! 608: static int physAvailStart; /* next free byte in contiguous memory area */ ! 609: static int physAvailBytes; /* number of bytes in contiguous memory area */ ! 610: ! 611: /* ! 612: * Check whether a range of physical addresses lies within the ! 613: * pool of contiguous physical memory. ! 614: */ ! 615: int ! 616: physValid(base, numBytes) ! 617: unsigned int base, numBytes; ! 618: { ! 619: int vpool; ! 620: int ret = 0; ! 621: ! 622: if (PHYS_MEM) { ! 623: vpool = vtop(physPoolStart); ! 624: T_HAL(0x40000, printf("PHYS_MEM phys addrs %x to %x ", ! 625: vpool, vpool + PHYS_MEM)); ! 626: if (base >= vpool && (base + numBytes) <= (vpool + PHYS_MEM)) ! 627: ret = 1; ! 628: } else { ! 629: T_HAL(0x40000, printf("No PHYS_MEM ")); ! 630: } ! 631: ! 632: T_HAL(0x40000, printf("physValid(%x, %x) = %d ", base, numBytes, ret)); ! 633: return ret; ! 634: } ! 635: ! 636: void ! 637: physMemInit() ! 638: { ! 639: int m, vaddr; ! 640: int err = 0, num_clicks = btoc(PHYS_MEM); ! 641: int prevPaddr, paddr; ! 642: ! 643: /* ! 644: * Going half way into page table for physMem ! 645: * If entry and its complementary entry aren't both in top segment ! 646: * Error exit (no phys mem will be available). ! 647: * Get page table entries and swap them. ! 648: */ ! 649: for (m = 0; m < num_clicks/2; m++) { ! 650: int m2 = num_clicks - 1 - m; /* complementary index */ ! 651: ! 652: /* compute virtual addresses */ ! 653: int lo_addr = physMem.sr_base + ctob(m); ! 654: int hi_addr = physMem.sr_base + ctob(m2); ! 655: ! 656: /* compute indices into page table (ptable1_v) */ ! 657: int lo_p1ix = btocrd(lo_addr); ! 658: int hi_p1ix = btocrd(hi_addr); ! 659: ! 660: /* fetch physical addresses from page table */ ! 661: int lo_paddr = ptable1_v[lo_p1ix]; ! 662: int hi_paddr = ptable1_v[hi_p1ix]; ! 663: ! 664: /* abort if either address is not in top segment */ ! 665: if (btosrd(lo_addr) != 0x3FF) { ! 666: err = 1; ! 667: break; ! 668: } ! 669: if (btosrd(hi_addr) != 0x3FF) { ! 670: err = 1; ! 671: break; ! 672: } ! 673: ! 674: /* exchange page table entries */ ! 675: ptable1_v[lo_p1ix] = hi_paddr; ! 676: ptable1_v[hi_p1ix] = lo_paddr; ! 677: } ! 678: ! 679: /* ! 680: * Final sanity check. ! 681: * In case someone gets creative with startup code, check ! 682: * again here that the memory is actually contiguous. ! 683: */ ! 684: prevPaddr = vtop(physMem.sr_base); ! 685: for (m = 0; m < num_clicks - 1; m++) { ! 686: paddr = vtop(physMem.sr_base + ctob(m + 1)); ! 687: if (paddr - prevPaddr != NBPC) { ! 688: err = 1; ! 689: break; ! 690: } ! 691: prevPaddr = paddr; ! 692: } ! 693: ! 694: if (!err) { ! 695: physPoolStart = physAvailStart = physMem.sr_base; ! 696: physAvailBytes = PHYS_MEM; ! 697: } ! 698: } ! 699: ! 700: /* ! 701: * Return virtual address of block of contiguous physical memory. ! 702: * If request cannot be granted, return 0. ! 703: * ! 704: * Expect physMem resource to be granted during load routine of device ! 705: * drivers. Once allocated, memory is not returned to the physMem pool. ! 706: */ ! 707: char * ! 708: getPhysMem(numBytes) ! 709: unsigned int numBytes; ! 710: { ! 711: char * ret = NULL; ! 712: ! 713: if (numBytes <= physAvailBytes) { ! 714: ret = (char *)physAvailStart; ! 715: physAvailStart += numBytes; ! 716: physAvailBytes -= numBytes; ! 717: } else ! 718: printf("getPhysMem failed - %d additional bytes " ! 719: "PHYS_MEM needed\n", physAvailBytes - numBytes); ! 720: return ret; ! 721: } ! 722: ! 723: /* ! 724: * Return virtual address of aligned block of contiguous physical memory. ! 725: * Mainly for devices using the stupid Intel DMA hardware without ! 726: * scatter/gather. ! 727: * If request cannot be granted, return 0. ! 728: * ! 729: * Argument "align" says what physical boundary we need alignment on. ! 730: * It must be a power of 2. ! 731: * For 4k alignment, align = 4k, etc. ! 732: * Sorry, but will throw away memory to get to the next acceptable address. ! 733: * ! 734: * Once allocated, memory is not returned to the physMem pool. ! 735: */ ! 736: char * ! 737: getDmaMem(numBytes, align) ! 738: unsigned int numBytes; ! 739: unsigned int align; ! 740: { ! 741: char * ret = NULL; ! 742: int wastedBytes, neededBytes; ! 743: ! 744: if (align == 0) { ! 745: printf("getDmaMem(0) (?)\n"); ! 746: goto getDmaMemDone; ! 747: } ! 748: ! 749: if (!IS_POW2(align)) { ! 750: printf("getDmaMem(%x) (?)\n", align); ! 751: goto getDmaMemDone; ! 752: } ! 753: ! 754: /* ! 755: * Waste RAM from bottom of pool up to physical ! 756: * address with desired alignment. ! 757: */ ! 758: wastedBytes = align - (vtop(physAvailStart) % align); ! 759: neededBytes = numBytes + wastedBytes; ! 760: ! 761: if (neededBytes <= physAvailBytes) { ! 762: ret = (char *)physAvailStart + wastedBytes; ! 763: physAvailStart += neededBytes; ! 764: physAvailBytes -= neededBytes; ! 765: } else ! 766: printf("getDmaMem failed - %d additional bytes " ! 767: "PHYS_MEM needed\n", physAvailBytes - neededBytes); ! 768: ! 769: getDmaMemDone: ! 770: return ret; ! 771: } ! 772: /***************/ ! 773: ! 774: #undef ptable1_v ! 775: ! 776: /* ! 777: * pageDir is the physical address of the click in use for the page ! 778: * directory, offset by ctob(SBASE - PBASE) ! 779: */ ! 780: #define pageDir ((long *)(&stext[ctob(-1)])) ! 781: ! 782: int total_clicks; /* How many clicks did we start with? */ ! 783: ! 784: void ! 785: mchinit() ! 786: { ! 787: extern char __end[], __end_data[], stext[], __end_text[], sdata[]; ! 788: extern int RAM0, RAMSIZE; ! 789: ! 790: int lo; /* Number of bytes of physical memory below 640K. */ ! 791: int hi; /* Number of bytes of physical memory above 1M. */ ! 792: register char *pe; ! 793: register int zero = 0; ! 794: register int i; ! 795: register long *ptable1_v; ! 796: register unsigned short base; ! 797: int sysseg, codeseg, stackseg, ramseg, ptable1; ! 798: int ptoff; /* An offset into pageDir[] */ ! 799: #if USE_NDATA ! 800: int dataseg[NDATA]; ! 801: #else ! 802: int dataseg; ! 803: #endif ! 804: int nalloc; ! 805: extern char digtab[]; ! 806: static SEG uinit; ! 807: int budArenaBytes; /* number of bytes in buddy pool */ ! 808: int kerBytes; /* number of bytes in kernel text and data */ ! 809: ! 810: /* ! 811: * 1. ! 812: * a. Relocate the data on a page boundary (4K bytes) the ! 813: * bootstrap relocates it on a paragraph boundary (16 bytes) ! 814: * ! 815: * b. Verify that the data has been relocated correctly ! 816: */ ! 817: pe = __end_data; /* 1.a */ ! 818: i = (((unsigned)__end_text+15) & ~15) - (unsigned)sdata; ! 819: do { ! 820: pe--; ! 821: pe[0] = pe[i]; ! 822: } while (pe != sdata); /* 1.b */ ! 823: ! 824: /* ! 825: * Can now access the .data segment from C. ! 826: * If not, next loop will hang the kernel. ! 827: */ ! 828: CHIRP('A'); ! 829: while (digtab[0]!='0'); ! 830: CHIRP('*'); ! 831: ! 832: /* Zero the bss. */ ! 833: pe = __end_data; ! 834: do ! 835: *pe++ = zero; ! 836: while (pe != __end); ! 837: ! 838: /* ! 839: * Zero the level 0 page directory, which occupies the click ! 840: * of virtual space immediately below kernel text. ! 841: */ ! 842: pe = (char *) pageDir; ! 843: do ! 844: *pe++ = zero; ! 845: while (pe != stext); ! 846: ! 847: CHIRP('2'); ! 848: ! 849: /* ! 850: * 3. Calculate total system memory. ! 851: * Count the space used by the system and the page ! 852: * descriptors, the interrupt stack, and the refresh work area ! 853: * ! 854: * a. initialize allocation area and adjust system size ! 855: * to take allocation area and free page area into account ! 856: */ ! 857: ! 858: /* ! 859: * btoc(__end) - SBASE is the number of clicks in kernel text ! 860: * plus data, rounded up. ! 861: * PBASE is the starting physical click number of the kernel. ! 862: * ! 863: * Set sysmem.lo to the physical click address just past the kernel. ! 864: */ ! 865: DV(__end); ! 866: ! 867: kerBytes = __end - ((SBASE - PBASE)<<BPCSHIFT); ! 868: DV(kerBytes); ! 869: ! 870: sysmem.lo = btoc(kerBytes); ! 871: DV(sysmem.lo); ! 872: ! 873: /* ! 874: * lo is the size in bytes of memory between the end of the kernel ! 875: * and the end of memory below 640K. ! 876: * hi is the size in bytes of memory over 1 Megabyte (Extended memory). ! 877: * ! 878: * Round the sizes from the CMOS down to the next click. This ! 879: * compensates for systems where the CMOS reports sizes that are ! 880: * not multiples of 4K. ! 881: */ ! 882: DV(read16_cmos(LOMEM)); ! 883: lo = ctob(read16_cmos(LOMEM) >> 2) - ctob(sysmem.lo); ! 884: DV(lo); ! 885: ! 886: DV(read16_cmos(EXTMEM)); ! 887: hi = ctob(read16_cmos(EXTMEM) >> 2); ! 888: DV(hi); ! 889: ! 890: /* ! 891: * Sometimes, we die horribly if there is too much memory. ! 892: * Artificially limit hi to HACK_LIMIT. ! 893: */ ! 894: if (hi > HACK_LIMIT) ! 895: hi = HACK_LIMIT; ! 896: ! 897: /* clear base memory above the kernel */ ! 898: #if 0 ! 899: CHIRP('z'); ! 900: memset (ctob (sysmem.lo + SBASE - PBASE), 0, lo); ! 901: CHIRP('Z'); ! 902: ! 903: /* clear extended memory */ ! 904: memset (ONE_MEG + ctob (SBASE - PBASE), 0, hi); ! 905: CHIRP('Y'); ! 906: #endif ! 907: ! 908: /* Record total memory for later use. */ ! 909: total_mem = ctob(sysmem.lo) + lo + hi; ! 910: DV(total_mem); ! 911: ! 912: /* ! 913: * sysmem.pfree and relatives will keep track of a pool of 4k pages ! 914: * assigned to processes, hereinafter known as the sysmem pool. ! 915: * How many clicks can go into this pool? nalloc. ! 916: * Allow NBPC for the click itself, a short for the sysmem pointer, ! 917: * and SPLASH*sizeof(long) for buddy system overhead. ! 918: */ ! 919: nalloc = (lo+hi) / (sizeof(short) + SPLASH*sizeof(long) + NBPC); ! 920: DV(nalloc); ! 921: ! 922: /* ! 923: * ASSERT: ! 924: * For the moment we want only to assure that the ! 925: * BUDDY arena and the stack of free pages will fit below ! 926: * 640K. ! 927: */ ! 928: budArenaBytes = SPLASH*nalloc*sizeof(long); ! 929: DV(budArenaBytes); ! 930: ! 931: #define SIZEOF_FREE_PAGES ((btoc(hi) + btoc(lo))* sizeof(short)) ! 932: T_PIGGY(0x800, budArenaBytes + SIZEOF_FREE_PAGES >= lo ? ! 933: panic("Too much memory") : 0); ! 934: ! 935: /* ! 936: * Initialize the buddy system arena. This memory is used ! 937: * for the compressed page tables. ! 938: */ ! 939: areainit(budArenaBytes); ! 940: ! 941: /* ! 942: * Initialize the stack of free pages. ! 943: * __end is the virtual address just past kernel data ! 944: * Point sysmem.tfree to the lowest virtual address just above ! 945: * the buddy pool, and initialize sysmem.pfree there. ! 946: */ ! 947: sysmem.tfree = sysmem.pfree = ! 948: (unsigned short *)(__end + budArenaBytes); ! 949: DV(sysmem.tfree); ! 950: ! 951: /* sysmem.hi is the physical click number just past high RAM */ ! 952: sysmem.hi = btoc(hi+ONE_MEG); ! 953: DV(sysmem.hi); ! 954: ! 955: /* base is the physical click number just past base RAM */ ! 956: base = sysmem.lo + (lo>>BPCSHIFT); ! 957: DV(base); ! 958: ! 959: /* ! 960: * Adjust sysmem.lo to be the physical click number just above ! 961: * not just the kernel, but above sysmem overhead as well. ! 962: */ ! 963: sysmem.lo = btoc(kerBytes + budArenaBytes + nalloc*sizeof(short)); ! 964: DV(sysmem.lo); ! 965: ! 966: /* ! 967: * sysmem.vaddre is the virtual address of the next click after the ! 968: * kernel. ! 969: */ ! 970: sysmem.vaddre = ctob(sysmem.lo+SBASE-PBASE); ! 971: DV(sysmem.vaddre); ! 972: ! 973: /* include in system area pages for arena, free area */ ! 974: ! 975: CHIRP('3'); ! 976: ! 977: /* ! 978: * 4. ! 979: * Free the memory from [end, 640) kilobytes ! 980: * Free the memory from [1024, 16*1024) kilobytes ! 981: * ! 982: * We are building a stack of free pages bounded below ! 983: * by sysmem.tfree and above by sysmem.efree. sysmem.pfree ! 984: * is the top of the stack. The stack grows upwards. ! 985: */ ! 986: total_clicks = 0; ! 987: ! 988: /* ! 989: * Initialize the sysmem table (phase 1 - base RAM). ! 990: * Put base RAM above the kernel and sysmem overhead area into ! 991: * sysmem pool. ! 992: */ ! 993: while (base > sysmem.lo) { ! 994: *sysmem.pfree++ = --base; ! 995: ++total_clicks; ! 996: } ! 997: ! 998: /* ! 999: * Initialize the sysmem table (phase 2 - extended RAM). ! 1000: * Put all extended RAM into the sysmem pool. ! 1001: */ ! 1002: base = btoc(ONE_MEG); ! 1003: while (base < sysmem.hi && total_clicks < nalloc) { ! 1004: *sysmem.pfree++ = base++; ! 1005: ++total_clicks; ! 1006: } ! 1007: DV(total_clicks); ! 1008: ! 1009: /* ! 1010: * Roundoff error may have made nalloc smaller than necessary. ! 1011: */ ! 1012: while(base < sysmem.hi) { ! 1013: if (sysmem.pfree + 1 >= sysmem.vaddre) ! 1014: break; ! 1015: *sysmem.pfree++ = base++; ! 1016: ++total_clicks; ! 1017: nalloc++; ! 1018: } ! 1019: DV(total_clicks); ! 1020: DV(nalloc); ! 1021: ! 1022: /* ! 1023: * sysmem.efree points just past the last pointer in the sysmem ! 1024: * table. ! 1025: */ ! 1026: sysmem.efree = sysmem.pfree; ! 1027: DV(sysmem.efree); ! 1028: DV(allocno()); ! 1029: ! 1030: #if 0 ! 1031: /* ! 1032: * NIGEL: Trace macros must now be given expressions. This one isn't ! 1033: * worth cleaning up. ! 1034: */ ! 1035: ! 1036: T_PIGGY(0x800, { ! 1037: /* ! 1038: * ASSERT: The stack of free pages should end within a click ! 1039: * of the lowest available memory. ! 1040: */ ! 1041: if ((cseg_t *)ctob(sysmem.lo+SBASE-PBASE) < sysmem.efree) { ! 1042: panic("sysmem.lo is too low"); ! 1043: } ! 1044: ! 1045: if (sysmem.efree < (cseg_t *)ctob(sysmem.lo+SBASE-PBASE - 1)){ ! 1046: panic("sysmem.efree is too low"); ! 1047: } ! 1048: ! 1049: /* ! 1050: * ASSERT: There should be nalloc total_clicks. ! 1051: */ ! 1052: if (nalloc != total_clicks) { ! 1053: panic("nalloc != total_clicks "); ! 1054: } ! 1055: }); ! 1056: #endif ! 1057: ! 1058: CHIRP('4'); ! 1059: ! 1060: /* ! 1061: * 5. allocate page entries and initialize level 0 ^'s ! 1062: * a. [ 00000000 .. 003FFFFF) user code segment ! 1063: * b. [ 00400000 .. 007FFFFF) user data & bss ! 1064: * c. [ 7FC00000 .. 7FFFFFFF) user stack ! 1065: *c.i.[ 80000000 .. 80FFFFFF) ram disk ! 1066: * d. [ FF800000 .. FFBFFFFF) pointers to level 1 page table ! 1067: * e. [ FFC00000 .. FFFFFFFF) system process addresses ! 1068: */ ! 1069: codeseg = clickseg(*--sysmem.pfree); /* 5.a */ ! 1070: pageDir[0x000] = codeseg | DIR_RW; ! 1071: ! 1072: #if USE_NDATA ! 1073: for (i = 0; i < NDATA; i++) { ! 1074: dataseg[i] = clickseg(*--sysmem.pfree); /* 5.b */ ! 1075: pageDir[0x001+i] = dataseg[i] | DIR_RW; ! 1076: } ! 1077: #else ! 1078: dataseg = clickseg(*--sysmem.pfree); /* 5.b */ ! 1079: pageDir[0x001] = dataseg | DIR_RW; ! 1080: #endif ! 1081: ! 1082: stackseg = clickseg(*--sysmem.pfree); /* 5.c */ ! 1083: pageDir[0x1FF] = stackseg | DIR_RW; ! 1084: ! 1085: /* ! 1086: * ptable1 is a handle for the click containing page table ! 1087: * entries for the page table. ! 1088: * ! 1089: * allocate a click for ptable1 ! 1090: * Then point at it from the page directory. ! 1091: */ ! 1092: ptable1 = clickseg(*--sysmem.pfree); /* 5.d */ ! 1093: pageDir[0x3FE] = ptable1 | DIR_RW; ! 1094: ! 1095: sysseg = clickseg(*--sysmem.pfree); /* 5.e */ ! 1096: pageDir[0x3FF] = sysseg | DIR_RW; ! 1097: ! 1098: CHIRP('5'); ! 1099: ! 1100: /* ! 1101: * 6. initialize level 2 ^'s to [5.d] ! 1102: */ ! 1103: ! 1104: ptable1_v = (long *)(ptable1 + ctob(SBASE-PBASE)); ! 1105: DV(pageDir); ! 1106: DV(ptable1_v); ! 1107: ptable1_v[0x000] = codeseg | SEG_SRW; ! 1108: #if USE_NDATA ! 1109: for (i = 0; i < NDATA; i++) ! 1110: ptable1_v[0x001+i] = dataseg[i] | SEG_SRW; ! 1111: #else ! 1112: ptable1_v[0x001] = dataseg | SEG_SRW; ! 1113: #endif ! 1114: ptable1_v[0x1FF] = stackseg| SEG_SRW; ! 1115: ! 1116: /* ! 1117: * This ram disk stuff should go away once the scheme ! 1118: * for allocating pieces of virtual memory space is in place. ! 1119: */ ! 1120: for (ptoff = btosrd(RAM0) & 0x3ff; ! 1121: ptoff < (btosrd(RAM0 + 2 * RAMSIZE) & 0x3ff); ++ptoff) { ! 1122: ramseg = clickseg(*--sysmem.pfree); /* 5.c.i */ ! 1123: pageDir[ptoff] = ramseg | DIR_RW; ! 1124: ptable1_v[ptoff] = ramseg | SEG_SRW; ! 1125: } ! 1126: ! 1127: ptable1_v[0x3FF] = sysseg | SEG_SRW; ! 1128: ! 1129: CHIRP('6'); ! 1130: ! 1131: /* ! 1132: * 7. ! 1133: * b. map kernel code and data ! 1134: * map ^ to: ! 1135: * c. level 0 page table ! 1136: * d. level 1 page table ! 1137: * e. I/O segments (video RAM, ...) ! 1138: */ ! 1139: ! 1140: ptable1_v = (long *)(sysseg + ctob(SBASE-PBASE)); /* 7.b */ ! 1141: DV(ptable1_v); ! 1142: for (i = PBASE; i <sysmem.lo; i++) ! 1143: ptable1_v[i-PBASE] = clickseg(i) | SEG_SRW; ! 1144: ! 1145: ptable1_v[0x3FE] = clickseg(PTABLE0_P) | SEG_SRW; /* 7.c */ ! 1146: ptable1_v[0x3FD] = ptable1 | SEG_SRW; /* 7.d */ ! 1147: ! 1148: init_phy_seg(ptable1_v, ROM-SBASE, 0x0000F0000); /* 7.e. */ ! 1149: init_phy_seg(ptable1_v, VIDEOa-SBASE,0x0000B0000); ! 1150: init_phy_seg(ptable1_v, VIDEOb-SBASE,0x0000B8000); ! 1151: ! 1152: CHIRP('7'); ! 1153: ! 1154: /* ! 1155: * 8. allocate and map U area ! 1156: */ ! 1157: ! 1158: uinit.s_flags = SFSYST|SFCORE; ! 1159: uinit.s_size = UPASIZE; ! 1160: uinit.s_vmem = c_alloc(btoc(UPASIZE)); ! 1161: ptable1_v[0x3FF] = *uinit.s_vmem | SEG_SRW; ! 1162: procq.p_segp[SIUSERP] = &uinit; ! 1163: ! 1164: CHIRP('8'); ! 1165: ! 1166: /* ! 1167: * 9. make FFC00000 and 00002000 map to the same address ! 1168: * to prevent the prefetch after the instruction turning on ! 1169: * paging from causing a page fault ! 1170: */ ! 1171: ptable1_v = (long *)(codeseg + ctob(SBASE-PBASE)); ! 1172: DV(ptable1_v); ! 1173: ptable1_v[PBASE] = clickseg(PBASE) | SEG_SRW; ! 1174: ! 1175: CHIRP('9'); ! 1176: ! 1177: /* ! 1178: * 10. load page table base address into MMU ! 1179: * fix up the interrupt vectors ! 1180: */ ! 1181: mmuupdnR0(); ! 1182: CHIRP('U'); ! 1183: idtinit(); ! 1184: CHIRP('I'); ! 1185: } ! 1186: ! 1187: typedef struct ! 1188: { ! 1189: unsigned short off_lo; ! 1190: unsigned short seg; ! 1191: unsigned short flags; ! 1192: unsigned short off_hi; ! 1193: } IDT; ! 1194: ! 1195: /* ! 1196: * ldtinit() ! 1197: * ! 1198: * Fix up descriptors which are hard to create properly at compile/link time. ! 1199: * Apply to idt and ldt. ! 1200: * ! 1201: * Swap 16-bit words at descriptor+2, descriptor+6. ! 1202: */ ! 1203: void ! 1204: idtinit() ! 1205: { ! 1206: extern IDT idt[], idtend[]; ! 1207: extern IDT ldt[], ldtend[]; ! 1208: extern IDT gdtFixBegin[], gdtFixEnd[]; ! 1209: ! 1210: register IDT *ip; ! 1211: register unsigned short tmp; ! 1212: ! 1213: for (ip = idt; ip < idtend; ip++) { ! 1214: tmp = ip->off_hi; ! 1215: ip->off_hi = ip->seg; ! 1216: ip->seg = tmp; ! 1217: } ! 1218: ! 1219: for (ip = ldt; ip < ldtend; ip++) { ! 1220: tmp = ip->off_hi; ! 1221: ip->off_hi = ip->seg; ! 1222: ip->seg = tmp; ! 1223: } ! 1224: ! 1225: for (ip = gdtFixBegin; ip < gdtFixEnd; ip++) { ! 1226: tmp = ip->off_hi; ! 1227: ip->off_hi = ip->seg; ! 1228: ip->seg = tmp; ! 1229: } ! 1230: } ! 1231: ! 1232: void ! 1233: init_phy_seg(ptable1_v, addr, base) ! 1234: long *ptable1_v; ! 1235: { ! 1236: register int i; ! 1237: ! 1238: for (i=0; i<btoc(0x10000); i++) { ! 1239: ptable1_v[addr+i] = base | SEG_SRW; ! 1240: base += NBPC; ! 1241: } ! 1242: } ! 1243: ! 1244: /* ! 1245: * Load up segmentation registers. ! 1246: */ ! 1247: SR ugmtab[NUSEG]; ! 1248: ! 1249: void ! 1250: segload() ! 1251: { ! 1252: register int i; ! 1253: register SR *start; ! 1254: ! 1255: /* ! 1256: * 1. unprogram the currently active UGM user segments ! 1257: * reset ugmtab ! 1258: */ ! 1259: for (start = &ugmtab[1]; start < &ugmtab[NUSEG]; start++) { ! 1260: if (start->sr_segp) ! 1261: unload(start); ! 1262: start->sr_segp = 0; ! 1263: } ! 1264: ! 1265: /* ! 1266: * 2. Load each segment in the p->p_region list into the MMU ! 1267: * Remember values in ugmtab. ! 1268: */ ! 1269: start = &ugmtab[1]; ! 1270: for (i = 1; i < NUSEG; i++) { ! 1271: if (u.u_segl[i].sr_segp) { ! 1272: *start = u.u_segl[i]; ! 1273: switch (i) { ! 1274: case SIPDATA: ! 1275: if (u.u_segl[SISTACK].sr_base) ! 1276: start->sr_size = min(start->sr_size, ! 1277: (long)u.u_segl[SISTACK].sr_base- ! 1278: u.u_segl[SISTACK].sr_size); ! 1279: break; ! 1280: case SISTACK: ! 1281: start->sr_base -= start->sr_size; ! 1282: break; ! 1283: } ! 1284: ! 1285: start->sr_segp = 0; ! 1286: if (SELF->p_segp[i]) { ! 1287: start->sr_segp = SELF->p_segp[i]; ! 1288: doload(start); ! 1289: } ! 1290: start++; ! 1291: } ! 1292: } ! 1293: ! 1294: /* 3. Update shm segment information. */ ! 1295: shmLoad(); ! 1296: } ! 1297: ! 1298: SR * ! 1299: loaded(pp) ! 1300: register cseg_t *pp; ! 1301: { ! 1302: register SR *start; ! 1303: ! 1304: for (start = ugmtab; start < ugmtab + NUSEG; start++) { ! 1305: if (start->sr_segp && start->sr_segp->s_vmem == pp) { ! 1306: return start; ! 1307: } ! 1308: } ! 1309: return 0; ! 1310: } ! 1311: ! 1312: MAKESR(r0stk, _r0stk); ! 1313: extern int tss_sp0; ! 1314: ! 1315: /* ! 1316: * General initialization ! 1317: */ ! 1318: void ! 1319: i8086() ! 1320: { ! 1321: unsigned csize, isize, ssize, allsize; ! 1322: caddr_t base; ! 1323: unsigned int calc_mem, boost; ! 1324: ! 1325: /* This is the first C code executed after paging is turned on. */ ! 1326: ! 1327: workPoolInit(); ! 1328: ! 1329: /* ! 1330: * Allocate contiguous physical memory if PHYS_MEM is patched ! 1331: * to a nonzero value. ! 1332: */ ! 1333: if (PHYS_MEM) { ! 1334: physMem.sr_size = (PHYS_MEM+NBPC-1)&~(NBPC-1); ! 1335: valloc(&physMem); ! 1336: physMemInit(); ! 1337: } ! 1338: ! 1339: /* ! 1340: * Allocate a click for ring 0 stack. ! 1341: */ ! 1342: r0stk.sr_size = NBPC; ! 1343: valloc(&r0stk); ! 1344: tss_sp0 = r0stk.sr_base + NBPC; ! 1345: ! 1346: /* ! 1347: * calc_mem is used for autosizing buffer cache and kalloc pool. ! 1348: * It is total_mem, limited below by 1 meg and above by 12 meg. ! 1349: * The upper limit is a temporary move to allow booting on 16 Meg ! 1350: * systems. ! 1351: * ! 1352: * "boost" is used in autosizing buffer cache and kalloc pool. ! 1353: * It is the number of megabytes of calc_mem above 1 meg, i.e., ! 1354: * a number between 0 and 11. ! 1355: */ ! 1356: if (total_mem < ONE_MEG) ! 1357: calc_mem = ONE_MEG; ! 1358: else if (total_mem > 12 * ONE_MEG) ! 1359: calc_mem = 12 * ONE_MEG; ! 1360: else ! 1361: calc_mem = total_mem; ! 1362: ! 1363: boost = (calc_mem - ONE_MEG) / ONE_MEG; ! 1364: ! 1365: /* ! 1366: * If the number of cache buffers was not explicitly set (i.e., !0) ! 1367: * then calculate the number of buffers using the simple heuristic: ! 1368: * 128 minimum + 400 per MB of available RAM (i.e., after 1MB) ! 1369: */ ! 1370: if (NBUF == 0) ! 1371: NBUF = 128 + (400 * boost); ! 1372: ! 1373: /* ! 1374: * Calculate NHASH as the next lower prime number from NBUF. ! 1375: */ ! 1376: NHASH = nlp(NBUF); ! 1377: ! 1378: /* ! 1379: * If the amount of kalloc() space was not explicitly set (i.e., !0) ! 1380: * then calculate using the simple heuristic: ! 1381: * 64k minimum + 32k per MB of available RAM (i.e., after 1MB) ! 1382: */ ! 1383: if (ALLSIZE == 0) ! 1384: ALLSIZE = 65536 + (32768 * boost); ! 1385: ! 1386: blockp.sr_size = NBUF*BSIZE; ! 1387: valloc(&blockp); ! 1388: ! 1389: allocp.sr_size= allsize = NBUF*sizeof(BUF) + ALLSIZE; ! 1390: #if USE_SLOT ! 1391: allocp.sr_size += ssize = NSLOT * (sizeof(int) + slotsz); ! 1392: #else ! 1393: ssize = 0; ! 1394: #endif ! 1395: allocp.sr_size += isize = NINODE* sizeof(INODE); ! 1396: allocp.sr_size += csize = NCLIST* sizeof(CLIST); ! 1397: valloc(&allocp); ! 1398: base = allocp.sr_base; ! 1399: allkp = setarena(base, allsize); ! 1400: base += allsize; ! 1401: #if USE_SLOT ! 1402: slotp = (int *)base; ! 1403: base += ssize; ! 1404: #endif ! 1405: inodep = (INODE*) base; ! 1406: base += isize; ! 1407: clistp = (paddr_t)base; ! 1408: } ! 1409: ! 1410: /* ! 1411: * Allocate srp->sr_size bytes of physical memory, and map it into ! 1412: * virtual memory space. At the end, the struct at srp will describe ! 1413: * the new segment. ! 1414: */ ! 1415: void ! 1416: valloc(srp) ! 1417: SR *srp; ! 1418: { ! 1419: register int npage; ! 1420: ! 1421: /* ! 1422: * If we've run out of virtual memory space, panic(). ! 1423: * ! 1424: * A more graceful solution is needed, but valloc() does ! 1425: * not provide a return value. ! 1426: */ ! 1427: if (sysmem.vaddre + srp->sr_size > MAX_VADDR) { ! 1428: panic("valloc: out of virtual memory space"); ! 1429: } ! 1430: ! 1431: npage = btoc(srp->sr_size); ! 1432: ! 1433: srp->sr_base = sysmem.vaddre; ! 1434: srp->sr_segp->s_size = srp->sr_size; ! 1435: srp->sr_segp->s_vmem = c_alloc(npage); ! 1436: srp->sr_segp->s_flags = SFSYST|SFCORE; ! 1437: doload(srp); ! 1438: ! 1439: sysmem.vaddre += ctob(npage); ! 1440: } ! 1441: ! 1442: /* ! 1443: * See if the given process may fit in core. ! 1444: */ ! 1445: int ! 1446: testcore(pp) ! 1447: register PROC *pp; ! 1448: { ! 1449: return 1; ! 1450: } ! 1451: ! 1452: /* ! 1453: * Calculate segmentation for a ! 1454: * new program. If there is a stack segment ! 1455: * present merge it into the data segment and ! 1456: * relocate the argument list. ! 1457: * Make sure that the changes are reflected in the u.u_segl array ! 1458: * which sproto sets up. ! 1459: */ ! 1460: int ! 1461: mproto() ! 1462: { ! 1463: return 1; ! 1464: } ! 1465: ! 1466: int ! 1467: accdata(base, count) ! 1468: unsigned base, count; ! 1469: { ! 1470: SR *srp; ! 1471: ! 1472: srp = &u.u_segl[SIPDATA]; ! 1473: return base>=srp->sr_base && base+count <= srp->sr_base+srp->sr_size; ! 1474: } ! 1475: ! 1476: int ! 1477: accstack(base, count) ! 1478: unsigned base; ! 1479: { ! 1480: SR *srp; ! 1481: ! 1482: srp = &u.u_segl[SISTACK]; ! 1483: return base>=srp->sr_base-srp->sr_size && base+count<=srp->sr_base; ! 1484: } ! 1485: ! 1486: int ! 1487: acctext(base, count) ! 1488: unsigned base; ! 1489: { ! 1490: SR *srp; ! 1491: ! 1492: srp = &u.u_segl[SISTEXT]; ! 1493: return base>=srp->sr_base && base+count <= srp->sr_base+srp->sr_size; ! 1494: } ! 1495: ! 1496: printhex(v, max) ! 1497: unsigned long v; ! 1498: { ! 1499: register int i; ! 1500: ! 1501: for (i = max-1; i>=0; --i) ! 1502: putchar(digtab[(v >> (i*4)) & 0xF]); ! 1503: } ! 1504: ! 1505: /* Read a 16 byte number from the CMOS. */ ! 1506: unsigned int ! 1507: read16_cmos(addr) ! 1508: unsigned int addr; ! 1509: { ! 1510: unsigned char read_cmos(); ! 1511: ! 1512: return((read_cmos(addr+1)<<8) + read_cmos(addr)); ! 1513: } /* read16_cmos() */ ! 1514: ! 1515: int ! 1516: c_grow(sp, new_bytes) ! 1517: SEG *sp; ! 1518: int new_bytes; ! 1519: { ! 1520: register int i; ! 1521: register cseg_t *pp; ! 1522: int new_clicks, pno, nsize, old_clicks; ! 1523: SR *srp; ! 1524: ! 1525: T_PIGGY(0x8000000, printf("c_grow(sp: %x, new: %x)", sp, new_bytes)); ! 1526: ! 1527: new_clicks = btoc(new_bytes); ! 1528: old_clicks = btoc(sp->s_size); ! 1529: ! 1530: if (new_clicks == old_clicks) { ! 1531: goto ok_c_grow; ! 1532: } ! 1533: ! 1534: if (new_clicks < old_clicks) { ! 1535: printf("%s:can't contract segment\n",u.u_comm); ! 1536: goto no_c_grow; ! 1537: } ! 1538: ! 1539: if (new_clicks - old_clicks > allocno()) { ! 1540: goto no_c_grow; ! 1541: } ! 1542: ! 1543: T_PIGGY(0x8000000, printf("nc: %x, oc: %x,",new_clicks,old_clicks)); ! 1544: ! 1545: /* ! 1546: * Allocate a new descriptor vector if necessary. ! 1547: * pp is the element corresponding to the virtual address ! 1548: * "0"(sr_base) ! 1549: */ ! 1550: pp = sp->s_vmem; ! 1551: nsize = areasize(new_clicks); ! 1552: if (nsize != areasize(old_clicks) ! 1553: && !(pp = (cseg_t*)arealloc(new_clicks))) { ! 1554: T_PIGGY(0x8000000, ! 1555: printf("Can not allocate new descriptor.")); ! 1556: goto no_c_grow; ! 1557: } ! 1558: ! 1559: T_PIGGY(0x8000000, printf("new pp: %x", pp)); ! 1560: ! 1561: if (0 != (srp = loaded(sp->s_vmem))) { ! 1562: T_PIGGY(0x8000000, printf("unloading srp: %x, ", srp)); ! 1563: unload(srp); ! 1564: srp->sr_segp = 0; ! 1565: } ! 1566: ! 1567: /* ! 1568: * Allocate new descriptors. ! 1569: */ ! 1570: T_PIGGY(0x8000000, printf("new desc: [")); ! 1571: for (i = old_clicks; i < new_clicks; i++) { ! 1572: pno = *--sysmem.pfree; ! 1573: pp[i] = clickseg(pno) | SEG_RW; ! 1574: T_PIGGY(0x8000000, printf("%x, ", pp[i])); ! 1575: } ! 1576: T_PIGGY(0x8000000, printf("]")); ! 1577: ! 1578: /* ! 1579: * Copy unchanged descriptors and free old vector if necessary. ! 1580: */ ! 1581: if (pp != sp->s_vmem) { ! 1582: T_PIGGY(0x8000000, printf("old desc: [")); ! 1583: for (i = 0; i < old_clicks; i++) { ! 1584: pp[i] = sp->s_vmem[i]; ! 1585: T_PIGGY(0x8000000, printf("%x, ", pp[i])); ! 1586: } ! 1587: T_PIGGY(0x8000000, printf("]")); ! 1588: areafree((BLOCKLIST*)sp->s_vmem, old_clicks); ! 1589: } ! 1590: ! 1591: sp->s_vmem = pp; ! 1592: ! 1593: /* ! 1594: * clear the added clicks ! 1595: * ! 1596: * MAPIO macro - convert array of page descriptors, offset ! 1597: * into system global address. ! 1598: */ ! 1599: T_PIGGY(0x8000000, printf("dmaclear(%x, %x, 0)", ! 1600: ctob(new_clicks - old_clicks), ! 1601: MAPIO(sp->s_vmem, ctob(old_clicks)) ! 1602: )); /* T_PIGGY() */ ! 1603: ! 1604: dmaclear (ctob (new_clicks - old_clicks), ! 1605: MAPIO(sp->s_vmem, ctob(old_clicks))); ! 1606: ! 1607: ok_c_grow: ! 1608: return 0; ! 1609: ! 1610: no_c_grow: ! 1611: return -1; ! 1612: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.