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

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

unix.superglobalmegacorp.com

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