Annotation of MiNT/src/memprot.c, revision 1.1

1.1     ! root        1: /*
        !             2: 
        !             3:  * Copyright 1991,1992,1993 Atari Corporation.
        !             4: 
        !             5:  * All rights reserved.
        !             6: 
        !             7:  */
        !             8: 
        !             9: 
        !            10: 
        !            11: /*
        !            12: 
        !            13:  * page-table data structures
        !            14: 
        !            15:  *
        !            16: 
        !            17:  *
        !            18: 
        !            19:  * The root pointer points to a list of pointers to top-level pointer tables.
        !            20: 
        !            21:  * 
        !            22: 
        !            23:  * Each entry in a pointer table points to another pointer table or to
        !            24: 
        !            25:  * a page table, or is a page descriptor.
        !            26: 
        !            27:  * 
        !            28: 
        !            29:  * Since, initially, the logical address space is the physical address space,
        !            30: 
        !            31:  * we only need to worry about 26MB plus 32K for I/O space.
        !            32: 
        !            33:  * 
        !            34: 
        !            35:  * Since we want some pages to be supervisor-accessible, but we don't want
        !            36: 
        !            37:  * a whole separate table for that, we use long-format descriptors.
        !            38: 
        !            39:  * 
        !            40: 
        !            41:  * Initial memory map:
        !            42: 
        !            43:  * 
        !            44: 
        !            45:  * 0    - membot: S (supervisor only)
        !            46: 
        !            47:  * membot       - memtop: P (protected TPA)
        !            48: 
        !            49:  * memtop       - phystop: G (screen)
        !            50: 
        !            51:  * phystop      - $00E00000: bus error
        !            52: 
        !            53:  * $00E00000- $00E3FFFF: G (ROM)
        !            54: 
        !            55:  * $00E40000- $00FF7FFF: bus error
        !            56: 
        !            57:  * $00FF8000- $00FFFFFF: G (mostly S: I/O space, but that's done in hardware)
        !            58: 
        !            59:  * $01000000- ramtop: P
        !            60: 
        !            61:  * ramtop       - $7FFFFFFF: G (A32/D32 VME, cacheable)
        !            62: 
        !            63:  * $80000000- $FEFFFFFF: G (A32/D32 VME, non cacheable)
        !            64: 
        !            65:  * $FFxxxxxx         just like $00xxxxxx.
        !            66: 
        !            67:  * 
        !            68: 
        !            69:  * Here's a final choice of layouts: IS=0, PS=13 (8K), TIA=4, TIB=4, TIC=4,
        !            70: 
        !            71:  * TID=7.  This lets us map out entire unused megabytes at level C, and gives
        !            72: 
        !            73:  * us an 8K page size, which is the largest the '040 can deal with.
        !            74: 
        !            75:  * 
        !            76: 
        !            77:  * This code implements 4+4+4+7, as follows:
        !            78: 
        !            79:  * 
        !            80: 
        !            81:  * tbl_a
        !            82: 
        !            83:  *     0 -> tbl_b0
        !            84: 
        !            85:  *     1-7 -> Cacheable direct (VME) page descriptors
        !            86: 
        !            87:  *     8-E -> Non-cacheable direct (VME) page descriptors
        !            88: 
        !            89:  *     F -> tbl_bf
        !            90: 
        !            91:  * 
        !            92: 
        !            93:  * tbl_b0 table: 16 entries (assumes only 16MB of TT RAM)
        !            94: 
        !            95:  *     0 -> tbl_c00 (16MB of ST RAM address space)
        !            96: 
        !            97:  *     1 -> tbl_c01 (16MB of TT RAM address space)
        !            98: 
        !            99:  *     2-F -> cacheable direct (VME) page descriptors
        !           100: 
        !           101:  * 
        !           102: 
        !           103:  * tbl_bF table: 16 entries (deals with $FF mapping to $00)
        !           104: 
        !           105:  *     0-E -> Non-cacheable direct (VME) page descriptors
        !           106: 
        !           107:  *     F -> tbl_c00 (16MB of ST RAM address space, repeated here as $FF)
        !           108: 
        !           109:  * 
        !           110: 
        !           111:  * tbl_c00 table: ST RAM address space (example assuming 4MB ST RAM)
        !           112: 
        !           113:  *     0-3 -> RAM page tables
        !           114: 
        !           115:  *     4-D -> invalid
        !           116: 
        !           117:  *     E -> direct map, cache enable (ROM)
        !           118: 
        !           119:  *     F -> direct map, cache inhibit (I/O)
        !           120: 
        !           121:  * 
        !           122: 
        !           123:  * For each 16MB containing any TT RAM, there's a tbl_c.  Within those,
        !           124: 
        !           125:  * for each MB that actually has TT RAM, there's another table, containing
        !           126: 
        !           127:  * 128 RAM page tables.  Where there isn't RAM, there are "global"
        !           128: 
        !           129:  * pages, to let the hardware bus error or not as it sees fit.
        !           130: 
        !           131:  * 
        !           132: 
        !           133:  * One RAM page table is allocated per megabyte of real RAM; each table has
        !           134: 
        !           135:  * 128 entries, which is 8K per page.  For a TT with 4MB ST RAM and 4MB TT RAM
        !           136: 
        !           137:  * that's 8K in page tables.  You can cut this down by not allocating page
        !           138: 
        !           139:  * tables for which the entire megabyte is not accessible (i.e. it's all
        !           140: 
        !           141:  * private memory and it's not YOUR private memory).
        !           142: 
        !           143:  * 
        !           144: 
        !           145:  * You have one of these per process.  When somebody loads into G or S memory
        !           146: 
        !           147:  * or leaves it, you have to go through the page tables of every process
        !           148: 
        !           149:  * updating S bits (for S) and DT (for G) bits.
        !           150: 
        !           151:  * 
        !           152: 
        !           153:  * The top levels are small & easy so replicating them once per process
        !           154: 
        !           155:  * doesn't really hurt us.
        !           156: 
        !           157:  * 
        !           158: 
        !           159:  */
        !           160: 
        !           161: 
        !           162: 
        !           163: #include "mint.h"
        !           164: 
        !           165: 
        !           166: 
        !           167: #if 0
        !           168: 
        !           169: #define MP_DEBUG(x) DEBUG(x)
        !           170: 
        !           171: #else
        !           172: 
        !           173: #define MP_DEBUG(x)
        !           174: 
        !           175: #endif
        !           176: 
        !           177: 
        !           178: 
        !           179: void *memset P_((void *s, int ucharfill, unsigned long size));
        !           180: 
        !           181: static void _dump_tree P_((long_desc tbl, int level));
        !           182: 
        !           183: 
        !           184: 
        !           185: extern int debug_level;                /* see debug.c */
        !           186: 
        !           187: 
        !           188: 
        !           189: /*
        !           190: 
        !           191:  * You can turn this whole module off, and the stuff in context.s,
        !           192: 
        !           193:  * by setting no_mem_prot to 1.
        !           194: 
        !           195:  */
        !           196: 
        !           197: 
        !           198: 
        !           199: int no_mem_prot;
        !           200: 
        !           201: long page_table_size;
        !           202: 
        !           203: 
        !           204: 
        !           205: /*
        !           206: 
        !           207:  * PMMU stuff
        !           208: 
        !           209:  */
        !           210: 
        !           211: #if 1
        !           212: 
        !           213: #define flush_pmmu(start, end) __asm("pflusha")
        !           214: 
        !           215: #else
        !           216: 
        !           217: /* in cpu.spp is a new "cpush" function that can selectively flush
        !           218: 
        !           219:  * the cache
        !           220: 
        !           221:  */
        !           222: 
        !           223: #define flush_pmmu(start, len) cpush((void *)(start), (long)(len))
        !           224: 
        !           225: #endif
        !           226: 
        !           227: 
        !           228: 
        !           229: /*
        !           230: 
        !           231:  * This is one global TC register that is copied into every process'
        !           232: 
        !           233:  * context, even though it never changes.  It's also used by the
        !           234: 
        !           235:  * functions that dump page tables.
        !           236: 
        !           237:  */
        !           238: 
        !           239: 
        !           240: 
        !           241: tc_reg tc;
        !           242: 
        !           243: 
        !           244: 
        !           245: /* mint_top_* get used in mem.c also */
        !           246: 
        !           247: ulong mint_top_tt;
        !           248: 
        !           249: ulong mint_top_st;
        !           250: 
        !           251: 
        !           252: 
        !           253: int tt_mbytes;         /* number of megabytds of TT RAM */
        !           254: 
        !           255: 
        !           256: 
        !           257: /*
        !           258: 
        !           259:  * global_mode_table: one byte per page in the system.  Initially all pages
        !           260: 
        !           261:  * are set to "global" but then the TPA pages are set to "invalid" in
        !           262: 
        !           263:  * init_mem.  This has to be allocated and initialized in init_tables,
        !           264: 
        !           265:  * when you know how much memory there is.  You need a byte per page,
        !           266: 
        !           267:  * from zero to the end of TT RAM, including the space between STRAM
        !           268: 
        !           269:  * and TTRAM.  That is, you need 16MB/pagesize plus (tt_mbytes/pagesize)
        !           270: 
        !           271:  * bytes here.
        !           272: 
        !           273:  */
        !           274: 
        !           275: 
        !           276: 
        !           277: unsigned char *global_mode_table;
        !           278: 
        !           279: 
        !           280: 
        !           281: /*
        !           282: 
        !           283:  * prototype descriptors; field u1 must be all ones, other u? are zero.
        !           284: 
        !           285:  * This is just the first long of a full descriptor; the ".page_type" part
        !           286: 
        !           287:  * of the union.  These are initialized by init_tables.
        !           288: 
        !           289:  *
        !           290: 
        !           291:  * The proto_page_type table yields the value to stuff into the page_type
        !           292: 
        !           293:  * field of a new process' page table.  It is the "non-owner" mode for
        !           294: 
        !           295:  * a page with the corresponding value in global_mode_table.
        !           296: 
        !           297:  */
        !           298: 
        !           299: 
        !           300: 
        !           301: page_type g_page;
        !           302: 
        !           303: page_type g_ci_page;
        !           304: 
        !           305: page_type s_page;
        !           306: 
        !           307: page_type readable_page;
        !           308: 
        !           309: page_type invalid_page;
        !           310: 
        !           311: page_type page_ptr;
        !           312: 
        !           313: 
        !           314: 
        !           315: page_type *proto_page_type[] =
        !           316: 
        !           317:     { &invalid_page, &g_page, &s_page, &readable_page, &invalid_page };
        !           318: 
        !           319: /*     private      global    super    private/read    invalid */
        !           320: 
        !           321: 
        !           322: 
        !           323: /*
        !           324: 
        !           325:  * Init_tables: called sometime in initialization.  We set up some
        !           326: 
        !           327:  * constants here, but that's all.  The first new_proc call will set up the
        !           328: 
        !           329:  * page table for the root process and switch it in; from then on, we're
        !           330: 
        !           331:  * always under some process' control.
        !           332: 
        !           333:  * 
        !           334: 
        !           335:  * The master page-mode table is initialized here, and some constants like
        !           336: 
        !           337:  * the size needed for future page tables.
        !           338: 
        !           339:  *
        !           340: 
        !           341:  * One important constant initialized here is page_table_size, which is
        !           342: 
        !           343:  * the amount of memory required per page table.  new_proc allocates
        !           344: 
        !           345:  * this much memory for each process' page table.  This number will be
        !           346: 
        !           347:  * 1K/megabyte plus page table overhead.  There are TBL_PAGES_OFFS
        !           348: 
        !           349:  * tables at TBL_SIZE_BYTES each before the main tables begin; then
        !           350: 
        !           351:  * there is 1024 bytes per megabyte of memory being mapped.
        !           352: 
        !           353:  */
        !           354: 
        !           355: 
        !           356: 
        !           357: void
        !           358: 
        !           359: init_tables()
        !           360: 
        !           361: {
        !           362: 
        !           363:     int n_megabytes;
        !           364: 
        !           365:     long global_mode_table_size;
        !           366: 
        !           367: 
        !           368: 
        !           369:     if (no_mem_prot) return;
        !           370: 
        !           371: 
        !           372: 
        !           373:     TRACE(("init_tables"));
        !           374: 
        !           375: 
        !           376: 
        !           377: #define phys_top_tt (*(ulong *)0x5a4L)
        !           378: 
        !           379:     if (phys_top_tt == 0x01000000L) mint_top_tt = 0;
        !           380: 
        !           381:     else mint_top_tt = phys_top_tt;
        !           382: 
        !           383: 
        !           384: 
        !           385: #define phys_top_st (*(ulong *)0x42eL)
        !           386: 
        !           387:     mint_top_st = phys_top_st;
        !           388: 
        !           389: 
        !           390: 
        !           391:     if (mint_top_tt)
        !           392: 
        !           393:        tt_mbytes = (int) ((mint_top_tt - 0x01000000L) / ONE_MEG);
        !           394: 
        !           395:     else
        !           396: 
        !           397:        tt_mbytes = 0;
        !           398: 
        !           399: 
        !           400: 
        !           401:     n_megabytes = (int) ((mint_top_st / ONE_MEG) + tt_mbytes);
        !           402: 
        !           403: 
        !           404: 
        !           405:     /*
        !           406: 
        !           407:      * page table size: room for A table, B0 table, BF table, STRAM C
        !           408: 
        !           409:      * table, one TTRAM C table per 16MB (or fraction) of TTRAM, and 1024
        !           410: 
        !           411:      * bytes per megabyte.
        !           412: 
        !           413:      */
        !           414: 
        !           415: 
        !           416: 
        !           417:     page_table_size = (4L * TBL_SIZE_BYTES) +
        !           418: 
        !           419:                      (((tt_mbytes+15L)/16L) * TBL_SIZE_BYTES) +
        !           420: 
        !           421:                      (n_megabytes*1024L);
        !           422: 
        !           423: 
        !           424: 
        !           425:     global_mode_table_size = ((SIXTEEN_MEG / QUANTUM) +
        !           426: 
        !           427:                            (((ulong)tt_mbytes * ONE_MEG) / QUANTUM));
        !           428: 
        !           429: 
        !           430: 
        !           431:     global_mode_table = kmalloc(global_mode_table_size);
        !           432: 
        !           433: 
        !           434: 
        !           435:     assert(global_mode_table);
        !           436: 
        !           437: 
        !           438: 
        !           439:     TRACELOW(("mint_top_st is $%lx; mint_top_tt is $%lx, n_megabytes is %d",
        !           440: 
        !           441:        mint_top_st, mint_top_tt, n_megabytes));
        !           442: 
        !           443:     TRACELOW(("page_table_size is %ld, global_mode_table_size %ld",
        !           444: 
        !           445:            page_table_size,
        !           446: 
        !           447:            global_mode_table_size));
        !           448: 
        !           449: 
        !           450: 
        !           451:     g_page.limit = 0x7fff;     /* set nonzero fields: disabled limit */
        !           452: 
        !           453:     g_page.unused1 = 0x3f;     /* ones in this reserved field */
        !           454: 
        !           455:     g_page.unused2 = 0;
        !           456: 
        !           457:     g_page.s = 0;
        !           458: 
        !           459:     g_page.unused3 = 0;
        !           460: 
        !           461:     g_page.ci = 0;
        !           462: 
        !           463:     g_page.unused4 = 0;
        !           464: 
        !           465:     g_page.m = 1;              /* set m and u to 1 so CPU won't do writes */
        !           466: 
        !           467:     g_page.u = 1;
        !           468: 
        !           469:     g_page.wp = 0;             /* not write-protected */
        !           470: 
        !           471:     g_page.dt = 1;             /* descriptor type 1: page descriptor */
        !           472: 
        !           473: 
        !           474: 
        !           475:     g_ci_page = g_page;
        !           476: 
        !           477:     g_ci_page.ci = 1;
        !           478: 
        !           479: 
        !           480: 
        !           481:     readable_page = g_page;    /* a page which is globally readable */
        !           482: 
        !           483:     readable_page.wp = 1;      /* but write protected */
        !           484: 
        !           485: 
        !           486: 
        !           487:     s_page = g_page;           /* a page which is globally accessible */
        !           488: 
        !           489:     s_page.s = 1;              /* if you're supervisor */
        !           490: 
        !           491: 
        !           492: 
        !           493:     invalid_page = g_page;
        !           494: 
        !           495:     invalid_page.dt = 0;
        !           496: 
        !           497: 
        !           498: 
        !           499:     page_ptr = g_page;
        !           500: 
        !           501:     page_ptr.m = 0;            /* this must be zero in page pointers */
        !           502: 
        !           503:     page_ptr.dt = 3;
        !           504: 
        !           505: 
        !           506: 
        !           507:     tc.enable = 1;
        !           508: 
        !           509:     tc.zeros = 0;
        !           510: 
        !           511:     tc.sre = 0;
        !           512: 
        !           513:     tc.fcl = 0;
        !           514: 
        !           515:     tc.is = 0;
        !           516: 
        !           517:     tc.tia = 4;
        !           518: 
        !           519:     tc.tib = 4;
        !           520: 
        !           521:     tc.tic = 4;
        !           522: 
        !           523:     tc.tid = 7;                        /* 0+4+4+4+7+13 == 32 */
        !           524: 
        !           525:     tc.ps = 13;                        /* 8K page size */
        !           526: 
        !           527: 
        !           528: 
        !           529:     /* set the whole global_mode_table to "global" */
        !           530: 
        !           531:     memset(global_mode_table,PROT_G,global_mode_table_size);
        !           532: 
        !           533: }
        !           534: 
        !           535: 
        !           536: 
        !           537: /*
        !           538: 
        !           539:  * mark_region: mark a region of memory as having a particular type.
        !           540: 
        !           541:  * The arguments are the memory region in question and the new type.
        !           542: 
        !           543:  * If the new type is zero then the old type is preserved.  The
        !           544: 
        !           545:  * type of each page is kept in a global place for this purpose,
        !           546: 
        !           547:  * among others.
        !           548: 
        !           549:  *
        !           550: 
        !           551:  * The types are:
        !           552: 
        !           553:  *  0  private
        !           554: 
        !           555:  *  1  global
        !           556: 
        !           557:  *  2  private, but super-accessible
        !           558: 
        !           559:  *  3  private, but world readable
        !           560: 
        !           561:  *  4   invalid
        !           562: 
        !           563:  *
        !           564: 
        !           565: 
        !           566: 
        !           567: The idea is this:
        !           568: 
        !           569: 
        !           570: 
        !           571:     for (each process) {
        !           572: 
        !           573:        if (you're an owner or you're special) {
        !           574: 
        !           575:            set up owner modes
        !           576: 
        !           577:        }
        !           578: 
        !           579:        else {
        !           580: 
        !           581:            set up non-owner modes
        !           582: 
        !           583:        }
        !           584: 
        !           585: 
        !           586: 
        !           587:        mark_pages(pagetbl,start,len,modes);
        !           588: 
        !           589:     }
        !           590: 
        !           591: 
        !           592: 
        !           593:  */
        !           594: 
        !           595: 
        !           596: 
        !           597: /*
        !           598: 
        !           599:                        invalid---v
        !           600: 
        !           601:                  private/gr---v  |
        !           602: 
        !           603:                super-------v  |  |
        !           604: 
        !           605:            global-------v  |  |  |
        !           606: 
        !           607:        private-------v  |  |  |  |
        !           608: 
        !           609:                      |  |  |  |  |
        !           610: 
        !           611: */
        !           612: 
        !           613: ushort other_dt[] = { 0, 1, 1, 1, 0 };
        !           614: 
        !           615: ushort other_s[] = {  0, 0, 1, 0, 0 };
        !           616: 
        !           617: ushort other_wp[] = { 0, 0, 0, 1, 0 };
        !           618: 
        !           619: 
        !           620: 
        !           621: 
        !           622: 
        !           623: /*
        !           624: 
        !           625:  * get_page_cookie: return a cookie representing the protection status
        !           626: 
        !           627:  * of some memory.
        !           628: 
        !           629:  *
        !           630: 
        !           631:  * Returns ((wp << 3) | (s << 2) | (dt) | 0x8000) when it wins.
        !           632: 
        !           633:  * Returns 1 if the pages are not all controlled, 0 if they're not all the same.
        !           634: 
        !           635:  */
        !           636: 
        !           637: 
        !           638: 
        !           639: static short
        !           640: 
        !           641: get_page_cookie(long_desc *base_tbl,ulong start,ulong len)
        !           642: 
        !           643: {
        !           644: 
        !           645:     int b_index, c_index, d_index;
        !           646: 
        !           647:     long_desc *tbl;
        !           648: 
        !           649:     int dt, s, wp;
        !           650: 
        !           651: 
        !           652: 
        !           653:     if (start < mint_top_st) {
        !           654: 
        !           655:        /* start is in ST RAM; fail if not entirely in ST RAM */
        !           656: 
        !           657:        if (start+len > mint_top_st) {
        !           658: 
        !           659:            return 1;
        !           660: 
        !           661:        }
        !           662: 
        !           663:     }
        !           664: 
        !           665:     else if (start >= 0x01000000L && start < mint_top_tt) {
        !           666: 
        !           667:        /* start is in TT RAM; fail if not entirely in TT RAM */
        !           668: 
        !           669:        if (start+len > mint_top_tt) {
        !           670: 
        !           671:            return 1;
        !           672: 
        !           673:        }
        !           674: 
        !           675:     }
        !           676: 
        !           677: 
        !           678: 
        !           679:     b_index = (int)(start >> LOG2_16_MEG);
        !           680: 
        !           681:     c_index = (int)(start >> LOG2_ONE_MEG) & 0xf;
        !           682: 
        !           683:     d_index = (int)(start >> LOG2_EIGHT_K) & 0x7f;
        !           684: 
        !           685: 
        !           686: 
        !           687:     tbl = &(base_tbl[0].
        !           688: 
        !           689:            tbl_address[b_index].
        !           690: 
        !           691:                tbl_address[c_index].
        !           692: 
        !           693:                    tbl_address[d_index]);
        !           694: 
        !           695: 
        !           696: 
        !           697:     dt = tbl->page_type.dt;
        !           698: 
        !           699:     wp = tbl->page_type.wp;
        !           700: 
        !           701:     s = tbl->page_type.s;
        !           702: 
        !           703: 
        !           704: 
        !           705:     /*
        !           706: 
        !           707:      * This can be optimized: while in a single megabyte, a quick loop on
        !           708: 
        !           709:      * successive long_desc's will work; similarly, while in a single 16MB,
        !           710: 
        !           711:      * an outer loop on the same C-level table works.
        !           712: 
        !           713:      */
        !           714: 
        !           715: 
        !           716: 
        !           717:     while (len) {
        !           718: 
        !           719:        /*
        !           720: 
        !           721:         * a_index is always zero.  Only the first 256MB is mapped.
        !           722: 
        !           723:         * b_index is the 16MB number of the page.
        !           724: 
        !           725:         * c_index is the 1MB number of that page within the 16MB (0-15)
        !           726: 
        !           727:         * d_index is the 8K number within that 1MB (0-127).
        !           728: 
        !           729:         */
        !           730: 
        !           731:        b_index = (int)(start >> LOG2_16_MEG);
        !           732: 
        !           733:        c_index = (int)(start >> LOG2_ONE_MEG) & 0xf;
        !           734: 
        !           735:        d_index = (int)(start >> LOG2_EIGHT_K) & 0x7f;
        !           736: 
        !           737: 
        !           738: 
        !           739:        tbl = base_tbl;                 /* tbl := start of A table  */
        !           740: 
        !           741:        tbl = tbl[0].tbl_address;       /*                 B table  */
        !           742: 
        !           743:        tbl = tbl[b_index].tbl_address; /*                 C table  */
        !           744: 
        !           745:        tbl = tbl[c_index].tbl_address; /*                 D table  */
        !           746: 
        !           747:        tbl = &tbl[d_index];            /* tbl := addr of page entry */
        !           748: 
        !           749: 
        !           750: 
        !           751:        if ((tbl->page_type.dt != dt) ||
        !           752: 
        !           753:            (tbl->page_type.s != s) ||
        !           754: 
        !           755:            (tbl->page_type.wp != wp)) {
        !           756: 
        !           757:                /* fail because it's not all the same protection */
        !           758: 
        !           759:                return 0;
        !           760: 
        !           761:        }
        !           762: 
        !           763:        len -= EIGHT_K;
        !           764: 
        !           765:        start += EIGHT_K;
        !           766: 
        !           767:     }
        !           768: 
        !           769:     /* we passed -- all the pages in question have the same prot. status */
        !           770: 
        !           771:     return (wp << 3) | (s << 2) | dt | 0x8000;
        !           772: 
        !           773: }
        !           774: 
        !           775: 
        !           776: 
        !           777: static void
        !           778: 
        !           779: mark_pages(long_desc *base_tbl,ulong start,ulong len,
        !           780: 
        !           781:            ushort dt_val, ushort s_val, ushort wp_val, PROC *proc)
        !           782: 
        !           783: {
        !           784: 
        !           785:     int b_index, c_index, d_index;
        !           786: 
        !           787:     long_desc *tbl;
        !           788: 
        !           789:     ulong oldstart, oldlen;
        !           790: 
        !           791: 
        !           792: 
        !           793:     if (no_mem_prot) return;
        !           794: 
        !           795: 
        !           796: 
        !           797:     oldstart = start;
        !           798: 
        !           799:     oldlen = len;
        !           800: 
        !           801: 
        !           802: 
        !           803: #ifdef MEMPROT_SHORTCUT
        !           804: 
        !           805:     /*
        !           806: 
        !           807:      * Take a shortcut here: we're done if first page of the region is
        !           808: 
        !           809:      * already right. We duplicate the top of the "while" loop to do it,
        !           810: 
        !           811:      * but what the heck.
        !           812: 
        !           813:      */
        !           814: 
        !           815:     /* I don't think this shortcut is a good idea, since while we
        !           816: 
        !           817:      * are doing Mshrink or Srealloc we may very well have a region
        !           818: 
        !           819:      * with mixed page types -- ERS
        !           820: 
        !           821:      */
        !           822: 
        !           823: 
        !           824: 
        !           825:     b_index = (start >> LOG2_16_MEG);
        !           826: 
        !           827:     c_index = (start >> LOG2_ONE_MEG) & 0xf;
        !           828: 
        !           829:     d_index = (start >> LOG2_EIGHT_K) & 0x7f;
        !           830: 
        !           831: 
        !           832: 
        !           833:     tbl = &(base_tbl[0].
        !           834: 
        !           835:            tbl_address[b_index].
        !           836: 
        !           837:                tbl_address[c_index].
        !           838: 
        !           839:                    tbl_address[d_index]);
        !           840: 
        !           841: 
        !           842: 
        !           843:     if (tbl->page_type.dt == dt_val &&
        !           844: 
        !           845:        tbl->page_type.s == s_val &&
        !           846: 
        !           847:        tbl->page_type.wp == wp_val) {
        !           848: 
        !           849: /*
        !           850: 
        !           851:            TRACE(("mark_pages a:0 b:%d c:%d d:%d (same)",
        !           852: 
        !           853:                    b_index,c_index,d_index));
        !           854: 
        !           855: */
        !           856: 
        !           857:            return;
        !           858: 
        !           859:     }
        !           860: 
        !           861: 
        !           862: 
        !           863: #endif /* MEMPROT_SHORTCUT */
        !           864: 
        !           865: /*
        !           866: 
        !           867:     MP_DEBUG(("mark_pages a:0 b:%d c:%d d:%d (diff)",b_index,c_index,d_index));
        !           868: 
        !           869: */
        !           870: 
        !           871: 
        !           872: 
        !           873:     /*
        !           874: 
        !           875:      * This can be optimized: while in a single megabyte, a quick loop on
        !           876: 
        !           877:      * successive long_desc's will work; similarly, while in a single 16MB,
        !           878: 
        !           879:      * an outer loop on the same C-level table works.
        !           880: 
        !           881:      */
        !           882: 
        !           883: 
        !           884: 
        !           885:     while (len) {
        !           886: 
        !           887:        /*
        !           888: 
        !           889:         * a_index is always zero.  Only the first 256MB is mapped.
        !           890: 
        !           891:         * b_index is the 16MB number of the page.
        !           892: 
        !           893:         * c_index is the 1MB number of that page within the 16MB (0-15)
        !           894: 
        !           895:         * d_index is the 8K number within that 1MB (0-127).
        !           896: 
        !           897:         */
        !           898: 
        !           899:        b_index = (int)(start >> LOG2_16_MEG);
        !           900: 
        !           901:        c_index = (int)(start >> LOG2_ONE_MEG) & 0xf;
        !           902: 
        !           903:        d_index = (int)(start >> LOG2_EIGHT_K) & 0x7f;
        !           904: 
        !           905: 
        !           906: 
        !           907:        tbl = base_tbl;                 /* tbl := start of A table  */
        !           908: 
        !           909:        tbl = tbl[0].tbl_address;       /*                 B table  */
        !           910: 
        !           911:        tbl = tbl[b_index].tbl_address; /*                 C table  */
        !           912: 
        !           913:        tbl = tbl[c_index].tbl_address; /*                 D table  */
        !           914: 
        !           915:        tbl = &tbl[d_index];            /* tbl := addr of page entry */
        !           916: 
        !           917: 
        !           918: 
        !           919:        tbl->page_type.dt = dt_val;
        !           920: 
        !           921:        tbl->page_type.s = s_val;
        !           922: 
        !           923:        tbl->page_type.wp = wp_val;
        !           924: 
        !           925:        len -= EIGHT_K;
        !           926: 
        !           927:        start += EIGHT_K;
        !           928: 
        !           929:     }
        !           930: 
        !           931: 
        !           932: 
        !           933: #if 0
        !           934: 
        !           935:     /*
        !           936: 
        !           937:      * Flush the mmu address translation cache only if we changed curproc's
        !           938: 
        !           939:      * table.
        !           940: 
        !           941:      */
        !           942: 
        !           943: 
        !           944: 
        !           945:     if (proc == curproc) flush_pmmu(oldstart, oldlen);
        !           946: 
        !           947: #else
        !           948: 
        !           949:     flush_pmmu(oldstart, oldlen);
        !           950: 
        !           951: #endif
        !           952: 
        !           953: }
        !           954: 
        !           955: 
        !           956: 
        !           957: /* get_prot_mode(r): returns the type of protection region r
        !           958: 
        !           959:  * has
        !           960: 
        !           961:  */
        !           962: 
        !           963: 
        !           964: 
        !           965: int
        !           966: 
        !           967: get_prot_mode(r)
        !           968: 
        !           969:        MEMREGION *r;
        !           970: 
        !           971: {
        !           972: 
        !           973:        ulong start = r->loc;
        !           974: 
        !           975: 
        !           976: 
        !           977:        if (no_mem_prot)
        !           978: 
        !           979:                return PROT_G;
        !           980: 
        !           981:        return global_mode_table[(start >> 13)];
        !           982: 
        !           983: }
        !           984: 
        !           985: 
        !           986: 
        !           987: void
        !           988: 
        !           989: mark_region(region,mode)
        !           990: 
        !           991: MEMREGION *region;
        !           992: 
        !           993: short mode;
        !           994: 
        !           995: {
        !           996: 
        !           997:     ulong start = region->loc;
        !           998: 
        !           999:     ulong len = region->len;
        !          1000: 
        !          1001:     ulong i;
        !          1002: 
        !          1003:     ushort dt_val, s_val, wp_val;
        !          1004: 
        !          1005:     PROC *proc;
        !          1006: 
        !          1007:     MEMREGION **mr;
        !          1008: 
        !          1009:     int change;
        !          1010: 
        !          1011: 
        !          1012: 
        !          1013:     if (no_mem_prot) return;
        !          1014: 
        !          1015: 
        !          1016: 
        !          1017:     MP_DEBUG(("mark_region %lx len %lx mode %d",start,len,mode));
        !          1018: 
        !          1019:     
        !          1020: 
        !          1021:     if (mode == PROT_NOCHANGE) {
        !          1022: 
        !          1023:        mode = global_mode_table[(start >> 13)];
        !          1024: 
        !          1025:     }
        !          1026: 
        !          1027: 
        !          1028: 
        !          1029:     if (global_mode_table[(start >> 13)] == mode) {
        !          1030: 
        !          1031:        change = 0;
        !          1032: 
        !          1033:     }
        !          1034: 
        !          1035:     else change = 1;
        !          1036: 
        !          1037: 
        !          1038: 
        !          1039:     /* mark the global page table */
        !          1040: 
        !          1041: 
        !          1042: 
        !          1043:     memset(&global_mode_table[start >> 13],mode,(len >> 13));
        !          1044: 
        !          1045: 
        !          1046: 
        !          1047:     for (proc = proclist; proc; proc = proc->gl_next) {
        !          1048: 
        !          1049:        assert(proc->page_table);
        !          1050: 
        !          1051:        if (mode == PROT_I || mode == PROT_G) {
        !          1052: 
        !          1053:            /* everybody gets the same flags */
        !          1054: 
        !          1055:            goto notowner;
        !          1056: 
        !          1057:        }
        !          1058: 
        !          1059:        if (proc->memflags & F_OS_SPECIAL) {
        !          1060: 
        !          1061:            /* you're special; you get owner flags */
        !          1062: 
        !          1063:            MP_DEBUG(("mark_region: pid %d is an OS special!",proc->pid));
        !          1064: 
        !          1065:            goto owner;
        !          1066: 
        !          1067:        }
        !          1068: 
        !          1069:        if (0 != (mr = proc->mem)) {
        !          1070: 
        !          1071:            for (i = 0; i < proc->num_reg; i++, mr++) {
        !          1072: 
        !          1073:                if (*mr == region) {
        !          1074: 
        !          1075:                    MP_DEBUG(("mark_region: pid %d is an owner",proc->pid));
        !          1076: 
        !          1077: owner:
        !          1078: 
        !          1079:                    dt_val = 1;
        !          1080: 
        !          1081:                    s_val = 0;
        !          1082: 
        !          1083:                    wp_val = 0;
        !          1084: 
        !          1085:                    goto gotvals;
        !          1086: 
        !          1087:                }
        !          1088: 
        !          1089:            }
        !          1090: 
        !          1091:        }
        !          1092: 
        !          1093: 
        !          1094: 
        !          1095: notowner:
        !          1096: 
        !          1097: 
        !          1098: 
        !          1099: /* if you get here you're not an owner, or mode is G or I */
        !          1100: 
        !          1101:        MP_DEBUG(("mark_region: pid %d gets non-owner modes",proc->pid));
        !          1102: 
        !          1103: 
        !          1104: 
        !          1105:        dt_val = other_dt[mode];
        !          1106: 
        !          1107:        s_val = other_s[mode];
        !          1108: 
        !          1109:        wp_val = other_wp[mode];
        !          1110: 
        !          1111: 
        !          1112: 
        !          1113: gotvals:
        !          1114: 
        !          1115:        mark_pages(proc->page_table,start,len,dt_val,s_val,wp_val,proc);
        !          1116: 
        !          1117:     }
        !          1118: 
        !          1119: }
        !          1120: 
        !          1121: 
        !          1122: 
        !          1123: /*
        !          1124: 
        !          1125:  * prot_temp: temporarily alter curproc's access to memory.
        !          1126: 
        !          1127:  * Pass in a -1 to give curproc global access; returns a cookie.  Call
        !          1128: 
        !          1129:  * again with that cookie to return the memory to the old mode.
        !          1130: 
        !          1131:  * There should be no context switches or memory protection changes
        !          1132: 
        !          1133:  * in the meantime.
        !          1134: 
        !          1135:  *
        !          1136: 
        !          1137:  * If called with mode == -1, returns...
        !          1138: 
        !          1139:  *     -1 if mem prot is off -- no error, no action.
        !          1140: 
        !          1141:  *      0 if the pages are not all the same.
        !          1142: 
        !          1143:  *      1 if the pages are not all controlled by the page tables.
        !          1144: 
        !          1145:  *
        !          1146: 
        !          1147:  * When mode != -1, returns...
        !          1148: 
        !          1149:  *     0 for success (should never fail).  There is little checking.
        !          1150: 
        !          1151:  * Calling with mode == 0 or 1 results in zero to spoof success, but in fact
        !          1152: 
        !          1153:  * this is an error.  Mode is only really valid if (mode & 0x8000).
        !          1154: 
        !          1155:  */
        !          1156: 
        !          1157: 
        !          1158: 
        !          1159: int
        !          1160: 
        !          1161: prot_temp(loc,len,mode)
        !          1162: 
        !          1163: ulong loc;
        !          1164: 
        !          1165: ulong len;
        !          1166: 
        !          1167: int mode;
        !          1168: 
        !          1169: {
        !          1170: 
        !          1171:     int cookie;
        !          1172: 
        !          1173: 
        !          1174: 
        !          1175:     if (no_mem_prot) return -1;
        !          1176: 
        !          1177: 
        !          1178: 
        !          1179:     /* round start down to the previous page and len up to the next one. */
        !          1180: 
        !          1181:     loc &= ~MASKBITS;
        !          1182: 
        !          1183:     len = ROUND(len);
        !          1184: 
        !          1185: 
        !          1186: 
        !          1187:     if (mode == 0 || mode == 1) return 0;      /* do nothing */
        !          1188: 
        !          1189:     if (mode == -1) {
        !          1190: 
        !          1191:        cookie = get_page_cookie(curproc->page_table,loc,len);
        !          1192: 
        !          1193: 
        !          1194: 
        !          1195:        /* if not all controlled, return status */
        !          1196: 
        !          1197:        if (cookie == 0 || cookie == 1) return cookie;
        !          1198: 
        !          1199: 
        !          1200: 
        !          1201:        mark_pages(curproc->page_table,loc,len,1,0,0,curproc);
        !          1202: 
        !          1203: 
        !          1204: 
        !          1205:        return cookie;
        !          1206: 
        !          1207:     }
        !          1208: 
        !          1209:     else {
        !          1210: 
        !          1211:        mark_pages(curproc->page_table,loc,len,
        !          1212: 
        !          1213:                    mode&3,mode&4,mode&8,curproc);
        !          1214: 
        !          1215:        return 0;
        !          1216: 
        !          1217:     }
        !          1218: 
        !          1219: }
        !          1220: 
        !          1221: 
        !          1222: 
        !          1223: /*
        !          1224: 
        !          1225:  * init_page_table: fill in the page table for the indicated process. The
        !          1226: 
        !          1227:  * master page map is consulted for the modes of all pages, and the memory
        !          1228: 
        !          1229:  * region data structures are consulted to see if this process is the owner
        !          1230: 
        !          1231:  * of any of those tables.
        !          1232: 
        !          1233:  *
        !          1234: 
        !          1235:  * This also sets crp and tc in both ctxts of the process.  If this is the
        !          1236: 
        !          1237:  * first call, then the CPU tc is cleared, the TT0 and TT1 regs are zapped,
        !          1238: 
        !          1239:  * and then this proc's crp and tc are loaded into it.
        !          1240: 
        !          1241:  */
        !          1242: 
        !          1243: 
        !          1244: 
        !          1245: static short mmu_is_set_up = 0;
        !          1246: 
        !          1247: 
        !          1248: 
        !          1249: void
        !          1250: 
        !          1251: init_page_table(proc)
        !          1252: 
        !          1253: PROC *proc;
        !          1254: 
        !          1255: {
        !          1256: 
        !          1257:     long_desc *tptr;
        !          1258: 
        !          1259:     long_desc *tbl_a;          /* top-level table */
        !          1260: 
        !          1261:     long_desc *tbl_b0;         /* second level, handles $0 nybble */
        !          1262: 
        !          1263:     long_desc *tbl_bf;         /* handles $F nybble */
        !          1264: 
        !          1265:     long_desc *tbl_c;          /* temp pointer to start of 16MB */
        !          1266: 
        !          1267:     ulong p, q, r;
        !          1268: 
        !          1269:     ulong i, j, k;
        !          1270: 
        !          1271:     int g;
        !          1272: 
        !          1273:     MEMREGION **mr;
        !          1274: 
        !          1275: 
        !          1276: 
        !          1277:     if (no_mem_prot) return;
        !          1278: 
        !          1279: 
        !          1280: 
        !          1281:     if (proc->pid)
        !          1282: 
        !          1283:         TRACELOW(("init_page_table(proc=%lx, pid %d)",proc,proc->pid));
        !          1284: 
        !          1285: 
        !          1286: 
        !          1287:     assert(proc && proc->page_table);
        !          1288: 
        !          1289: 
        !          1290: 
        !          1291:     tptr = proc->page_table;
        !          1292: 
        !          1293:     tbl_a = tptr;
        !          1294: 
        !          1295:     tptr += TBL_SIZE;
        !          1296: 
        !          1297:     tbl_b0 = tptr;
        !          1298: 
        !          1299:     tptr += TBL_SIZE;
        !          1300: 
        !          1301:     tbl_bf = tptr;
        !          1302: 
        !          1303:     tptr += TBL_SIZE;
        !          1304: 
        !          1305: 
        !          1306: 
        !          1307:     /*
        !          1308: 
        !          1309:      * table A indexes by the first nybble: $0 and $F refer to their tables,
        !          1310: 
        !          1311:      * $1-$7 are uncontrolled, cacheable; $8-$E are uncontrolled, ci.
        !          1312: 
        !          1313:      */
        !          1314: 
        !          1315: 
        !          1316: 
        !          1317:     tbl_a[0].page_type = page_ptr;
        !          1318: 
        !          1319:     tbl_a[0].tbl_address = tbl_b0;
        !          1320: 
        !          1321: 
        !          1322: 
        !          1323:     for (i=1; i<0xf; i++) {
        !          1324: 
        !          1325:        if (i < 8)  tbl_a[i].page_type = g_page;
        !          1326: 
        !          1327:        else        tbl_a[i].page_type = g_ci_page;
        !          1328: 
        !          1329:        tbl_a[i].tbl_address = (long_desc *)(i << 28);
        !          1330: 
        !          1331:     }
        !          1332: 
        !          1333: 
        !          1334: 
        !          1335:     /* $F entry of table A refers to table BF */
        !          1336: 
        !          1337:     tbl_a[0xf].page_type = page_ptr;
        !          1338: 
        !          1339:     tbl_a[0xf].tbl_address = tbl_bf;
        !          1340: 
        !          1341: 
        !          1342: 
        !          1343:     /*
        !          1344: 
        !          1345:      * table B0: entry 0 is $00, the 16MB of ST address space.
        !          1346: 
        !          1347:      */
        !          1348: 
        !          1349: 
        !          1350: 
        !          1351:     tbl_b0[0].page_type = page_ptr;
        !          1352: 
        !          1353:     tbl_b0[0].tbl_address = tptr;
        !          1354: 
        !          1355:     tbl_c = tptr;
        !          1356: 
        !          1357:     tptr += TBL_SIZE;
        !          1358: 
        !          1359: 
        !          1360: 
        !          1361:     /* for each megabyte that is RAM, allocate a table */
        !          1362: 
        !          1363:     for (i = 0, k = 0, p = 0; p < mint_top_st; i++, p += 0x00100000L) {
        !          1364: 
        !          1365:        tbl_c[i].page_type = page_ptr;
        !          1366: 
        !          1367:        tbl_c[i].tbl_address = tptr;
        !          1368: 
        !          1369: 
        !          1370: 
        !          1371:        /* for each page in this megabyte, write a page entry */
        !          1372: 
        !          1373:        for (q = p, j = 0; j < 128; j++, q += 0x2000, k++) {
        !          1374: 
        !          1375:            tptr->page_type = *proto_page_type[global_mode_table[k]];
        !          1376: 
        !          1377:            tptr->tbl_address = (long_desc *)q;
        !          1378: 
        !          1379:            tptr++;
        !          1380: 
        !          1381:        }
        !          1382: 
        !          1383:     }
        !          1384: 
        !          1385: 
        !          1386: 
        !          1387:     /* now for each megabyte from mint_top_st to ROM, mark global */
        !          1388: 
        !          1389:     for ( ; p < 0x00E00000L; i++, p += 0x00100000L) {
        !          1390: 
        !          1391:        tbl_c[i].page_type = g_page;
        !          1392: 
        !          1393:        tbl_c[i].tbl_address = (long_desc *)p;
        !          1394: 
        !          1395:     }
        !          1396: 
        !          1397: 
        !          1398: 
        !          1399:     /* fill in the E and F tables: 00Ex is ROM, 00Fx is I/O  */
        !          1400: 
        !          1401:     tbl_c[i].page_type = g_page;
        !          1402: 
        !          1403:     tbl_c[i].tbl_address = (long_desc *)p;
        !          1404: 
        !          1405:     i++, p += 0x00100000L;
        !          1406: 
        !          1407:     tbl_c[i].page_type = g_ci_page;
        !          1408: 
        !          1409:     tbl_c[i].tbl_address = (long_desc *)p;
        !          1410: 
        !          1411: 
        !          1412: 
        !          1413:         /* Done with tbl_c for 0th 16MB; go on to TT RAM */
        !          1414: 
        !          1415: 
        !          1416: 
        !          1417: /* 
        !          1418: 
        !          1419:     structure:
        !          1420: 
        !          1421: 
        !          1422: 
        !          1423:     for (i = each 16MB that has any TT RAM in it)
        !          1424: 
        !          1425:        allocate a table tbl_c, point tbl_b0[i] at it
        !          1426: 
        !          1427:        for (j = each 1MB that is RAM)
        !          1428: 
        !          1429:            allocate a table, point tbl_c[j] at it
        !          1430: 
        !          1431:            for (k = each page in the megabyte)
        !          1432: 
        !          1433:                fill in tbl_c[j][k] with page entry from global_mode_table
        !          1434: 
        !          1435:        for (j = the rest of the 16MB)
        !          1436: 
        !          1437:            set tbl_c[j] to "global, cacheable"
        !          1438: 
        !          1439: 
        !          1440: 
        !          1441:     for (i = the rest of the 16MBs from here to $7F)
        !          1442: 
        !          1443:        set tbl_b0[i] to "global, cacheable"
        !          1444: 
        !          1445: 
        !          1446: 
        !          1447:     for (i = the rest of the 16MBs from $80 up to but not incl. $FF)
        !          1448: 
        !          1449:        set tbl_b0[i] to "global, not cacheable"
        !          1450: 
        !          1451: */
        !          1452: 
        !          1453: 
        !          1454: 
        !          1455:     /* i counts 16MBs */
        !          1456: 
        !          1457:     for (i = 1, p = 0x01000000L, g = 2048;
        !          1458: 
        !          1459:         p < mint_top_tt;
        !          1460: 
        !          1461:         p += SIXTEEN_MEG, i++) {
        !          1462: 
        !          1463:            tbl_b0[i].page_type = page_ptr;
        !          1464: 
        !          1465:            tbl_b0[i].tbl_address = tptr;
        !          1466: 
        !          1467:            tbl_c = tptr;
        !          1468: 
        !          1469:            tptr += TBL_SIZE;
        !          1470: 
        !          1471: 
        !          1472: 
        !          1473:            /* j counts MBs */
        !          1474: 
        !          1475:            for (j = 0, q = p; j < 16 && q < mint_top_tt; q += ONE_MEG, j++) {
        !          1476: 
        !          1477:                tbl_c[j].page_type = page_ptr;
        !          1478: 
        !          1479:                tbl_c[j].tbl_address = tptr;
        !          1480: 
        !          1481:                /* k counts pages (8K) */
        !          1482: 
        !          1483:                for (r = q, k = 0; k < 128; k++, r += 0x2000, g++) {
        !          1484: 
        !          1485:                    tptr->page_type = *proto_page_type[global_mode_table[g]];
        !          1486: 
        !          1487:                    tptr->tbl_address = (long_desc *)r;
        !          1488: 
        !          1489:                    tptr++;
        !          1490: 
        !          1491:                }
        !          1492: 
        !          1493:            }
        !          1494: 
        !          1495:            for ( ; j < 16; j++, q += ONE_MEG) {
        !          1496: 
        !          1497:                /* fill in the rest of this 16MB */
        !          1498: 
        !          1499:                tbl_c[j].page_type = g_page;
        !          1500: 
        !          1501:                tbl_c[j].tbl_address = (long_desc *)q;
        !          1502: 
        !          1503:            }
        !          1504: 
        !          1505:     }
        !          1506: 
        !          1507: 
        !          1508: 
        !          1509:     /* fill in the rest of $00-$0F as cacheable */
        !          1510: 
        !          1511:     for ( ; i < 16; i++, p += SIXTEEN_MEG) {
        !          1512: 
        !          1513:        tbl_b0[i].page_type = g_page;
        !          1514: 
        !          1515:        tbl_b0[i].tbl_address = (long_desc *)p;
        !          1516: 
        !          1517:     }
        !          1518: 
        !          1519: 
        !          1520: 
        !          1521:     /* done with TT RAM in table b0; do table bf */
        !          1522: 
        !          1523: 
        !          1524: 
        !          1525:     /*
        !          1526: 
        !          1527:      * Table BF: translates addresses starting with $F.  First 15 are
        !          1528: 
        !          1529:      * uncontrolled, cacheable; last one translates $FF, which
        !          1530: 
        !          1531:      * which shadows $00 (the 16MB ST address space).  The rest
        !          1532: 
        !          1533:      * are uncontrolled, not cacheable.
        !          1534: 
        !          1535:      *
        !          1536: 
        !          1537:      * The table address of the copy has a 1 in the low (unused) bit, which
        !          1538: 
        !          1539:      * is a signal to the table dumper not to dump this, as it's a copy
        !          1540: 
        !          1541:      * of tbl_b0[0].
        !          1542: 
        !          1543:      */
        !          1544: 
        !          1545: 
        !          1546: 
        !          1547:     for (i=0; i<0xf; i++) {
        !          1548: 
        !          1549:        tbl_bf[i].page_type = g_ci_page;
        !          1550: 
        !          1551:        tbl_bf[i].tbl_address = (long_desc *)((i << 24) | 0xf0000000L);
        !          1552: 
        !          1553:     }
        !          1554: 
        !          1555:     tbl_bf[0xf] = tbl_b0[0];
        !          1556: 
        !          1557:     *(ulong *)(&(tbl_bf[0xf].tbl_address)) |= 1;
        !          1558: 
        !          1559: 
        !          1560: 
        !          1561:     proc->ctxt[0].crp.limit = 0x7fff;  /* disable limit function */
        !          1562: 
        !          1563:     proc->ctxt[0].crp.dt = 3;          /* points to valid 8-byte entries */
        !          1564: 
        !          1565:     proc->ctxt[0].crp.tbl_address = tbl_a;
        !          1566: 
        !          1567:     proc->ctxt[1].crp = proc->ctxt[0].crp;
        !          1568: 
        !          1569:     proc->ctxt[0].tc = tc;
        !          1570: 
        !          1571:     proc->ctxt[1].tc = tc;
        !          1572: 
        !          1573: 
        !          1574: 
        !          1575:     /*
        !          1576: 
        !          1577:      * OK, memory tables are now there as if you're a non-owner of every
        !          1578: 
        !          1579:      * page.  Now for each region you ARE an owner of, mark with owner
        !          1580: 
        !          1581:      * modes.
        !          1582: 
        !          1583:      */
        !          1584: 
        !          1585: 
        !          1586: 
        !          1587:     mr = proc->mem;
        !          1588: 
        !          1589:     for (i=0; i < proc->num_reg; i++, mr++) {
        !          1590: 
        !          1591:        if (*mr) {
        !          1592: 
        !          1593:            mark_pages(proc->page_table,(*mr)->loc,(*mr)->len,1,0,0,proc);
        !          1594: 
        !          1595:        }
        !          1596: 
        !          1597:     }
        !          1598: 
        !          1599: 
        !          1600: 
        !          1601:     if (!mmu_is_set_up) {
        !          1602: 
        !          1603:        set_mmu(proc->ctxt[0].crp,proc->ctxt[0].tc);
        !          1604: 
        !          1605:        mmu_is_set_up = 1;
        !          1606: 
        !          1607:     }
        !          1608: 
        !          1609: }
        !          1610: 
        !          1611: 
        !          1612: 
        !          1613: /*
        !          1614: 
        !          1615:  * This routine is called when procfs detects that a process wants to be an
        !          1616: 
        !          1617:  * OS SPECIAL.  The AES, SCRENMGR, and DESKTOP do this, and so does FSMGDOS
        !          1618: 
        !          1619:  * and possibly some other stuff. It has to re-mark every page in that
        !          1620: 
        !          1621:  * process' page table based on its new special status. The "special
        !          1622: 
        !          1623:  * status" is "you get global access to all of memory" and "everybody
        !          1624: 
        !          1625:  * gets Super access to yours."  It is the caller's responsibility
        !          1626: 
        !          1627:  * to set proc's memflags, usually to (F_OS_SPECIAL | F_PROT_S).
        !          1628: 
        !          1629:  */
        !          1630: 
        !          1631: 
        !          1632: 
        !          1633: void
        !          1634: 
        !          1635: mem_prot_special(proc)
        !          1636: 
        !          1637: PROC *proc;
        !          1638: 
        !          1639: {
        !          1640: 
        !          1641:     MEMREGION **mr;
        !          1642: 
        !          1643:     int i;
        !          1644: 
        !          1645: 
        !          1646: 
        !          1647:     if (no_mem_prot) return;
        !          1648: 
        !          1649: 
        !          1650: 
        !          1651:     TRACE(("mem_prot_special(pid %d)",proc->pid));
        !          1652: 
        !          1653: 
        !          1654: 
        !          1655:     /*
        !          1656: 
        !          1657:      * This marks ALL memory, allocated or not, as accessible. When memory
        !          1658: 
        !          1659:      * is freed even F_OS_SPECIAL processes lose access to it. So one or
        !          1660: 
        !          1661:      * the other of these is a bug, depending on how you want it to work.
        !          1662: 
        !          1663:      */
        !          1664: 
        !          1665:     mark_pages(proc->page_table,0,mint_top_st,1,0,0,proc);
        !          1666: 
        !          1667:     if (mint_top_tt) {
        !          1668: 
        !          1669:        mark_pages(proc->page_table,
        !          1670: 
        !          1671:                    0x01000000L,
        !          1672: 
        !          1673:                    mint_top_tt - 0x01000000L,
        !          1674: 
        !          1675:                    1,0,0,
        !          1676: 
        !          1677:                    proc);
        !          1678: 
        !          1679:     }
        !          1680: 
        !          1681: 
        !          1682: 
        !          1683:     /*
        !          1684: 
        !          1685:      * In addition, mark all the pages the process already owns as "super"
        !          1686: 
        !          1687:      * in all other processes.  Thus the "special" process can access all
        !          1688: 
        !          1689:      * of memory, and any process can access the "special" process' memory
        !          1690: 
        !          1691:      * when in super mode.
        !          1692: 
        !          1693:      */
        !          1694: 
        !          1695: 
        !          1696: 
        !          1697:     mr = proc->mem;
        !          1698: 
        !          1699: 
        !          1700: 
        !          1701:     for (i=0; i < proc->num_reg; i++, mr++) {
        !          1702: 
        !          1703:        if (*mr) {
        !          1704: 
        !          1705:            mark_region(*mr,PROT_S);
        !          1706: 
        !          1707:        }
        !          1708: 
        !          1709:     }
        !          1710: 
        !          1711: }
        !          1712: 
        !          1713:     
        !          1714: 
        !          1715: /*----------------------------------------------------------------------------
        !          1716: 
        !          1717:  * DEBUGGING SECTION
        !          1718: 
        !          1719:  *--------------------------------------------------------------------------*/
        !          1720: 
        !          1721: 
        !          1722: 
        !          1723: static void
        !          1724: 
        !          1725: _dump_tree(tbl,level)
        !          1726: 
        !          1727: long_desc tbl;
        !          1728: 
        !          1729: int level;
        !          1730: 
        !          1731: {
        !          1732: 
        !          1733:     int i, j;
        !          1734: 
        !          1735:     long_desc *p;
        !          1736: 
        !          1737:     static char spaces[9] = "        ";
        !          1738: 
        !          1739: 
        !          1740: 
        !          1741:     /* print the level and display the table descriptor */
        !          1742: 
        !          1743:     FORCE("\r%s s:%x wp:%x dt:%x a:%08lx",
        !          1744: 
        !          1745:        &spaces[8-(level*2)],
        !          1746: 
        !          1747:        tbl.page_type.s,
        !          1748: 
        !          1749:        tbl.page_type.wp,
        !          1750: 
        !          1751:        tbl.page_type.dt,
        !          1752: 
        !          1753:        tbl.tbl_address);
        !          1754: 
        !          1755: 
        !          1756: 
        !          1757:     if (tbl.page_type.dt == 3) {
        !          1758: 
        !          1759:        if (level == 0) {
        !          1760: 
        !          1761:            j = (1 << tc.tia);
        !          1762: 
        !          1763:        }
        !          1764: 
        !          1765:        else if (level == 1) {
        !          1766: 
        !          1767:            j = (1 << tc.tib);
        !          1768: 
        !          1769:        }
        !          1770: 
        !          1771:        else if (level == 2) {
        !          1772: 
        !          1773:            j = (1 << tc.tic);
        !          1774: 
        !          1775:        }
        !          1776: 
        !          1777:        else {
        !          1778: 
        !          1779:            j = (1 << tc.tid);
        !          1780: 
        !          1781:        }
        !          1782: 
        !          1783: 
        !          1784: 
        !          1785:        /* don't show table if it's the duplicate */
        !          1786: 
        !          1787:        if ((ulong)tbl.tbl_address & 1) return;
        !          1788: 
        !          1789: 
        !          1790: 
        !          1791:        ++level;
        !          1792: 
        !          1793:        p = tbl.tbl_address;
        !          1794: 
        !          1795:        for (i=0; i<j; i++, p++) {
        !          1796: 
        !          1797:            _dump_tree(*p,level);
        !          1798: 
        !          1799:        }
        !          1800: 
        !          1801:     }
        !          1802: 
        !          1803: }
        !          1804: 
        !          1805: 
        !          1806: 
        !          1807: static char modesym[] = { 'p', 'g', 's', 'r', 'i' };
        !          1808: 
        !          1809: 
        !          1810: 
        !          1811: void
        !          1812: 
        !          1813: QUICKDUMP()
        !          1814: 
        !          1815: {
        !          1816: 
        !          1817:     char outstr[33];
        !          1818: 
        !          1819:     ulong i, j, end;
        !          1820: 
        !          1821: 
        !          1822: 
        !          1823:     if (no_mem_prot) return;
        !          1824: 
        !          1825: 
        !          1826: 
        !          1827:     FORCE("STRAM global table:");
        !          1828: 
        !          1829:     outstr[32] = '\0';
        !          1830: 
        !          1831:     end = mint_top_st / QUANTUM;
        !          1832: 
        !          1833:     for (i = 0; i < end; i += 32) {
        !          1834: 
        !          1835:        for (j=0; j<32; j++) {
        !          1836: 
        !          1837:            outstr[j] = modesym[global_mode_table[j+i]];
        !          1838: 
        !          1839:        }
        !          1840: 
        !          1841:        FORCE("%08lx: %s",i*8192L,outstr);
        !          1842: 
        !          1843:     }
        !          1844: 
        !          1845: 
        !          1846: 
        !          1847:     if (mint_top_tt) {
        !          1848: 
        !          1849:        FORCE("TTRAM global table:");
        !          1850: 
        !          1851:        end = mint_top_tt / QUANTUM;
        !          1852: 
        !          1853:        for (i = 2048; i < end; i += 32) {
        !          1854: 
        !          1855:            for (j=0; j<32; j++) {
        !          1856: 
        !          1857:                outstr[j] = modesym[global_mode_table[j+i]];
        !          1858: 
        !          1859:            }
        !          1860: 
        !          1861:            FORCE("%08lx: %s",i*8192L,outstr);
        !          1862: 
        !          1863:        }
        !          1864: 
        !          1865:     }
        !          1866: 
        !          1867: }
        !          1868: 
        !          1869: 
        !          1870: 
        !          1871: const char *berr_msg[] = { 
        !          1872: 
        !          1873: /*  "........." */
        !          1874: 
        !          1875:     "private  ",
        !          1876: 
        !          1877:     "global   ",    /* turned into "hardware" for violation reports */
        !          1878: 
        !          1879:     "super    ",
        !          1880: 
        !          1881:     "readable ",
        !          1882: 
        !          1883:     "free     ",
        !          1884: 
        !          1885:     "hardware "            /* used when the memory is not controlled by us */
        !          1886: 
        !          1887: };
        !          1888: 
        !          1889: 
        !          1890: 
        !          1891: void
        !          1892: 
        !          1893: report_buserr()
        !          1894: 
        !          1895: {
        !          1896: 
        !          1897:     long_desc *tbl;
        !          1898: 
        !          1899:     const char *vmsg = NULL;
        !          1900: 
        !          1901:     short mode;
        !          1902: 
        !          1903:     ulong aa, pc;
        !          1904: 
        !          1905:     char alertbuf[5*32+16];    /* enough for an alert */
        !          1906: 
        !          1907:     char *aptr;
        !          1908: 
        !          1909: 
        !          1910: 
        !          1911:     if (no_mem_prot) return;
        !          1912: 
        !          1913: 
        !          1914: 
        !          1915:     tbl = (long_desc *)curproc->exception_tbl;
        !          1916: 
        !          1917:     aa = curproc->exception_addr;
        !          1918: 
        !          1919:     pc = curproc->exception_pc;
        !          1920: 
        !          1921:     if ((mint_top_tt && aa < mint_top_tt) || (aa < mint_top_st)) {
        !          1922: 
        !          1923:        mode = global_mode_table[(curproc->exception_addr >> 13)];
        !          1924: 
        !          1925:        if (mode == PROT_G) {
        !          1926: 
        !          1927:            /* page is global: obviously a hardware bus error */
        !          1928: 
        !          1929:            mode = 5;
        !          1930: 
        !          1931:        }
        !          1932: 
        !          1933:     }
        !          1934: 
        !          1935:     else {
        !          1936: 
        !          1937:        /* (addr is > mint_top_tt) set mode = 5 so we don't look for owners */
        !          1938: 
        !          1939:        mode = 5;
        !          1940: 
        !          1941:     }
        !          1942: 
        !          1943:     vmsg = berr_msg[mode];
        !          1944: 
        !          1945: 
        !          1946: 
        !          1947:     /* construct an AES alert box for this error:
        !          1948: 
        !          1949:        | PROCESS  "buserrxx"  KILLED: |
        !          1950: 
        !          1951:        | MEMORY VIOLATION.  (PID 000) |
        !          1952: 
        !          1953:        |                              |
        !          1954: 
        !          1955:        | Type: ......... PC: pc...... |
        !          1956: 
        !          1957:        | Addr: ........  BP: ........ |
        !          1958: 
        !          1959:     */
        !          1960: 
        !          1961: 
        !          1962: 
        !          1963:     /* we play games to get around 128-char max for ksprintf */
        !          1964: 
        !          1965:     ksprintf(alertbuf,"[1][ PROCESS  \"%s\"  KILLED: |",curproc->name);
        !          1966: 
        !          1967:     aptr = alertbuf + strlen(alertbuf);
        !          1968: 
        !          1969:     ksprintf(aptr," MEMORY VIOLATION.  (PID %03d) | |",curproc->pid);
        !          1970: 
        !          1971:     aptr = alertbuf + strlen(alertbuf);
        !          1972: 
        !          1973:     ksprintf(aptr," Type: %s PC: %08lx |",vmsg,pc);
        !          1974: 
        !          1975:     aptr = alertbuf + strlen(alertbuf);
        !          1976: 
        !          1977:     ksprintf(aptr," Addr: %08lx  BP: %08lx ][ OK ]",aa,curproc->base);
        !          1978: 
        !          1979:     if (!_ALERT(alertbuf)) {
        !          1980: 
        !          1981:        /* this will call _alert again, but it will just fail again */
        !          1982: 
        !          1983:        ALERT("MEMORY VIOLATION: type=%s AA=%lx PC=%lx BP=%lx",
        !          1984: 
        !          1985:                vmsg,aa,pc,curproc->base);
        !          1986: 
        !          1987:     }
        !          1988: 
        !          1989:        
        !          1990: 
        !          1991:     if (curproc->pid == 0 || curproc->memflags & F_OS_SPECIAL) {
        !          1992: 
        !          1993:     /* the system is so thoroughly hosed that anything we try will
        !          1994: 
        !          1995:      * likely cause another bus error; so let's just hang up
        !          1996: 
        !          1997:      */
        !          1998: 
        !          1999:        FATAL("Operating system killed");
        !          2000: 
        !          2001:     }
        !          2002: 
        !          2003: }
        !          2004: 
        !          2005: 
        !          2006: 
        !          2007: /*
        !          2008: 
        !          2009:  * big_mem_dump is a biggie: for each page in the system, it
        !          2010: 
        !          2011:  * displays the PID of the (first) owner and the protection mode.
        !          2012: 
        !          2013:  * The output has three chars per page, and eight chars per line.
        !          2014: 
        !          2015:  * The first page of a region is marked with the mode, and the
        !          2016: 
        !          2017:  * rest with a space.
        !          2018: 
        !          2019:  *
        !          2020: 
        !          2021:  * Logic:
        !          2022: 
        !          2023:     for (mp = *core; mp; mp++) {
        !          2024: 
        !          2025:        for (each page of this region) {
        !          2026: 
        !          2027:            if (start of line) {
        !          2028: 
        !          2029:                output line starter;
        !          2030: 
        !          2031:            }
        !          2032: 
        !          2033:            if (start of region) {
        !          2034: 
        !          2035:                output mode of this page;
        !          2036: 
        !          2037:                determine owner;
        !          2038: 
        !          2039:                output owner;
        !          2040: 
        !          2041:            }
        !          2042: 
        !          2043:            else {
        !          2044: 
        !          2045:                output space;
        !          2046: 
        !          2047:                output owner;
        !          2048: 
        !          2049:            }
        !          2050: 
        !          2051:         }
        !          2052: 
        !          2053:     }
        !          2054: 
        !          2055:  */
        !          2056: 
        !          2057: 
        !          2058: 
        !          2059: void
        !          2060: 
        !          2061: BIG_MEM_DUMP(bigone,proc)
        !          2062: 
        !          2063: int bigone;
        !          2064: 
        !          2065: PROC *proc;
        !          2066: 
        !          2067: {
        !          2068: 
        !          2069: #ifndef NO_DEBUG_INFO
        !          2070: 
        !          2071:     char linebuf[128];
        !          2072: 
        !          2073:     char *lp = linebuf;
        !          2074: 
        !          2075:     MEMREGION *mp, **mr, **map;
        !          2076: 
        !          2077:     PROC *p;
        !          2078: 
        !          2079:     ulong loc;
        !          2080: 
        !          2081:     short owner = 0;
        !          2082: 
        !          2083:     short i;
        !          2084: 
        !          2085:     short first;
        !          2086: 
        !          2087: 
        !          2088: 
        !          2089: 
        !          2090: 
        !          2091:   if (no_mem_prot) return;
        !          2092: 
        !          2093: 
        !          2094: 
        !          2095:   for (map = core; map != 0; ((map == core) ? (map = alt) : (map = 0))) {
        !          2096: 
        !          2097:     FORCE("Annotated memory dump for %s",(map == core ? "core" : "alt"));
        !          2098: 
        !          2099:     first = 1;
        !          2100: 
        !          2101:     *linebuf = '\0';
        !          2102: 
        !          2103:     for (mp = *map; mp; mp = mp->next) {
        !          2104: 
        !          2105:        for (loc = mp->loc; loc < (mp->loc + mp->len); loc += EIGHT_K) {
        !          2106: 
        !          2107:            if (first || ((loc & 0x1ffff) == 0)) {
        !          2108: 
        !          2109:                if (*linebuf) FORCE(linebuf);
        !          2110: 
        !          2111:                ksprintf(linebuf,"\r%08lx: ",loc);
        !          2112: 
        !          2113:                lp = &linebuf[11];
        !          2114: 
        !          2115:                first = 0;
        !          2116: 
        !          2117:            }
        !          2118: 
        !          2119:            if (loc == mp->loc) {
        !          2120: 
        !          2121:                *lp++ = modesym[global_mode_table[loc / EIGHT_K]];
        !          2122: 
        !          2123: 
        !          2124: 
        !          2125:                for (p = proclist; p; p = p->gl_next) {
        !          2126: 
        !          2127:                    if (p->mem) {
        !          2128: 
        !          2129:                        mr = p->mem;
        !          2130: 
        !          2131:                        for (i=0; i < p->num_reg; i++, mr++) {
        !          2132: 
        !          2133:                            if (*mr == mp) {
        !          2134: 
        !          2135:                                owner = p->pid;
        !          2136: 
        !          2137:                                goto gotowner;
        !          2138: 
        !          2139:                            }
        !          2140: 
        !          2141:                        }
        !          2142: 
        !          2143:                    }
        !          2144: 
        !          2145:                }
        !          2146: 
        !          2147:                owner = 000;
        !          2148: 
        !          2149: gotowner:
        !          2150: 
        !          2151:                ksprintf(lp,"%03d",owner);
        !          2152: 
        !          2153:                lp += 3;
        !          2154: 
        !          2155:            }
        !          2156: 
        !          2157:            else {
        !          2158: 
        !          2159:                *lp++ = ' ';
        !          2160: 
        !          2161:                *lp++ = '-';
        !          2162: 
        !          2163:                *lp++ = '-';
        !          2164: 
        !          2165:                *lp++ = '-';
        !          2166: 
        !          2167:                *lp = '\0';     /* string is always null-terminated */
        !          2168: 
        !          2169:            }
        !          2170: 
        !          2171:         }
        !          2172: 
        !          2173:     }
        !          2174: 
        !          2175:     FORCE(linebuf);
        !          2176: 
        !          2177:   }
        !          2178: 
        !          2179: 
        !          2180: 
        !          2181:     if (bigone) {
        !          2182: 
        !          2183:        long_desc tbl;
        !          2184: 
        !          2185: 
        !          2186: 
        !          2187:        /* fill in tbl with the only parts used at the top level */
        !          2188: 
        !          2189:        tbl.page_type.dt = proc->ctxt[CURRENT].crp.dt;
        !          2190: 
        !          2191:        tbl.tbl_address = proc->ctxt[CURRENT].crp.tbl_address;
        !          2192: 
        !          2193:        _dump_tree(tbl,0);
        !          2194: 
        !          2195:     }
        !          2196: 
        !          2197: #endif /* NO_DEBUG_INFO */
        !          2198: 
        !          2199: }
        !          2200: 
        !          2201: 
        !          2202: 
        !          2203: 
        !          2204: 
        !          2205: /*
        !          2206: 
        !          2207:  * Can the process "p" access the "nbytes" long
        !          2208: 
        !          2209:  * block of memory starting at "start"?
        !          2210: 
        !          2211:  * If it would be a legal access, the current
        !          2212: 
        !          2213:  * process is given temporary access via
        !          2214: 
        !          2215:  * prot_temp.
        !          2216: 
        !          2217:  * Returns a cookie like the one prot_temp
        !          2218: 
        !          2219:  * returns; if the process shouldn't have
        !          2220: 
        !          2221:  * access to the memory, returns 1.
        !          2222: 
        !          2223:  *
        !          2224: 
        !          2225:  * BUG: should actually read p's page table to
        !          2226: 
        !          2227:  * determine access
        !          2228: 
        !          2229:  */
        !          2230: 
        !          2231: 
        !          2232: 
        !          2233: int
        !          2234: 
        !          2235: mem_access_for(p, start, nbytes)
        !          2236: 
        !          2237:        PROC *p;
        !          2238: 
        !          2239:        ulong start;
        !          2240: 
        !          2241:        long nbytes;
        !          2242: 
        !          2243: {
        !          2244: 
        !          2245:        MEMREGION **mr;
        !          2246: 
        !          2247:        int i;
        !          2248: 
        !          2249: 
        !          2250: 
        !          2251:        if (no_mem_prot) return -1;
        !          2252: 
        !          2253:        if (start >= (ulong)p && start+nbytes <= (ulong)(p+1))
        !          2254: 
        !          2255:                return -1;
        !          2256: 
        !          2257:        if (p == rootproc)
        !          2258: 
        !          2259:                goto win_and_mark;
        !          2260: 
        !          2261: 
        !          2262: 
        !          2263:        mr = p->mem;
        !          2264: 
        !          2265:        if (mr) {
        !          2266: 
        !          2267:            for (i = 0; i < p->num_reg; i++, mr++) {
        !          2268: 
        !          2269:                if (*mr) {
        !          2270: 
        !          2271:                    if (((*mr)->loc <= start) &&
        !          2272: 
        !          2273:                        ((*mr)->loc + (*mr)->len >= start + nbytes))
        !          2274: 
        !          2275:                            goto win_and_mark;
        !          2276: 
        !          2277:                }
        !          2278: 
        !          2279:            }
        !          2280: 
        !          2281:        }
        !          2282: 
        !          2283: 
        !          2284: 
        !          2285:        return 0;       /* we don't own this memory */
        !          2286: 
        !          2287: 
        !          2288: 
        !          2289: win_and_mark:
        !          2290: 
        !          2291:        return prot_temp(start, nbytes, -1);
        !          2292: 
        !          2293: }
        !          2294: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.