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

1.1       root        1: /*
                      2: 
                      3:  * Copyright 1991,1992,1993 Atari Corporation.
                      4: 
                      5:  * All rights reserved.
                      6: 
                      7:  */
                      8: 
                      9: 
                     10: 
                     11: /*
                     12: 
                     13:  * page-table data structures
                     14: 
                     15:  *
                     16: 
                     17:  *
                     18: 
                     19:  * The root pointer points to a list of pointers to top-level pointer tables.
                     20: 
                     21:  * 
                     22: 
                     23:  * Each entry in a pointer table points to another pointer table or to
                     24: 
                     25:  * a page table, or is a page descriptor.
                     26: 
                     27:  * 
                     28: 
                     29:  * Since, initially, the logical address space is the physical address space,
                     30: 
                     31:  * we only need to worry about 26MB plus 32K for I/O space.
                     32: 
                     33:  * 
                     34: 
                     35:  * Since we want some pages to be supervisor-accessible, but we don't want
                     36: 
                     37:  * a whole separate table for that, we use long-format descriptors.
                     38: 
                     39:  * 
                     40: 
                     41:  * Initial memory map:
                     42: 
                     43:  * 
                     44: 
                     45:  * 0    - membot: S (supervisor only)
                     46: 
                     47:  * membot       - memtop: P (protected TPA)
                     48: 
                     49:  * memtop       - phystop: G (screen)
                     50: 
                     51:  * phystop      - $00E00000: bus error
                     52: 
                     53:  * $00E00000- $00E3FFFF: G (ROM)
                     54: 
                     55:  * $00E40000- $00FF7FFF: bus error
                     56: 
                     57:  * $00FF8000- $00FFFFFF: G (mostly S: I/O space, but that's done in hardware)
                     58: 
                     59:  * $01000000- ramtop: P
                     60: 
                     61:  * ramtop       - $7FFFFFFF: G (A32/D32 VME, cacheable)
                     62: 
                     63:  * $80000000- $FEFFFFFF: G (A32/D32 VME, non cacheable)
                     64: 
                     65:  * $FFxxxxxx         just like $00xxxxxx.
                     66: 
                     67:  * 
                     68: 
                     69:  * Here's a final choice of layouts: IS=0, PS=13 (8K), TIA=4, TIB=4, TIC=4,
                     70: 
                     71:  * TID=7.  This lets us map out entire unused megabytes at level C, and gives
                     72: 
                     73:  * us an 8K page size, which is the largest the '040 can deal with.
                     74: 
                     75:  * 
                     76: 
                     77:  * This code implements 4+4+4+7, as follows:
                     78: 
                     79:  * 
                     80: 
                     81:  * tbl_a
                     82: 
                     83:  *     0 -> tbl_b0
                     84: 
                     85:  *     1-7 -> Cacheable direct (VME) page descriptors
                     86: 
                     87:  *     8-E -> Non-cacheable direct (VME) page descriptors
                     88: 
                     89:  *     F -> tbl_bf
                     90: 
                     91:  * 
                     92: 
                     93:  * tbl_b0 table: 16 entries (assumes only 16MB of TT RAM)
                     94: 
                     95:  *     0 -> tbl_c00 (16MB of ST RAM address space)
                     96: 
                     97:  *     1 -> tbl_c01 (16MB of TT RAM address space)
                     98: 
                     99:  *     2-F -> cacheable direct (VME) page descriptors
                    100: 
                    101:  * 
                    102: 
                    103:  * tbl_bF table: 16 entries (deals with $FF mapping to $00)
                    104: 
                    105:  *     0-E -> Non-cacheable direct (VME) page descriptors
                    106: 
                    107:  *     F -> tbl_c00 (16MB of ST RAM address space, repeated here as $FF)
                    108: 
                    109:  * 
                    110: 
                    111:  * tbl_c00 table: ST RAM address space (example assuming 4MB ST RAM)
                    112: 
                    113:  *     0-3 -> RAM page tables
                    114: 
                    115:  *     4-D -> invalid
                    116: 
                    117:  *     E -> direct map, cache enable (ROM)
                    118: 
                    119:  *     F -> direct map, cache inhibit (I/O)
                    120: 
                    121:  * 
                    122: 
                    123:  * For each 16MB containing any TT RAM, there's a tbl_c.  Within those,
                    124: 
                    125:  * for each MB that actually has TT RAM, there's another table, containing
                    126: 
                    127:  * 128 RAM page tables.  Where there isn't RAM, there are "global"
                    128: 
                    129:  * pages, to let the hardware bus error or not as it sees fit.
                    130: 
                    131:  * 
                    132: 
                    133:  * One RAM page table is allocated per megabyte of real RAM; each table has
                    134: 
                    135:  * 128 entries, which is 8K per page.  For a TT with 4MB ST RAM and 4MB TT RAM
                    136: 
                    137:  * that's 8K in page tables.  You can cut this down by not allocating page
                    138: 
                    139:  * tables for which the entire megabyte is not accessible (i.e. it's all
                    140: 
                    141:  * private memory and it's not YOUR private memory).
                    142: 
                    143:  * 
                    144: 
                    145:  * You have one of these per process.  When somebody loads into G or S memory
                    146: 
                    147:  * or leaves it, you have to go through the page tables of every process
                    148: 
                    149:  * updating S bits (for S) and DT (for G) bits.
                    150: 
                    151:  * 
                    152: 
                    153:  * The top levels are small & easy so replicating them once per process
                    154: 
                    155:  * doesn't really hurt us.
                    156: 
                    157:  * 
                    158: 
                    159:  */
                    160: 
                    161: 
                    162: 
                    163: #include "mint.h"
                    164: 
                    165: 
                    166: 
                    167: #if 0
                    168: 
                    169: #define MP_DEBUG(x) DEBUG(x)
                    170: 
                    171: #else
                    172: 
                    173: #define MP_DEBUG(x)
                    174: 
                    175: #endif
                    176: 
                    177: 
                    178: 
                    179: void *memset P_((void *s, int ucharfill, unsigned long size));
                    180: 
                    181: static void _dump_tree P_((long_desc tbl, int level));
                    182: 
                    183: 
                    184: 
                    185: extern int debug_level;                /* see debug.c */
                    186: 
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: 
                    633:     long_desc *tbl;
                    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: 
                    665:     b_index = (int)(start >> LOG2_16_MEG);
                    666: 
                    667:     c_index = (int)(start >> LOG2_ONE_MEG) & 0xf;
                    668: 
                    669:     d_index = (int)(start >> LOG2_EIGHT_K) & 0x7f;
                    670: 
                    671: 
                    672: 
                    673:     tbl = &(base_tbl[0].
                    674: 
                    675:            tbl_address[b_index].
                    676: 
                    677:                tbl_address[c_index].
                    678: 
                    679:                    tbl_address[d_index]);
                    680: 
                    681: 
                    682: 
                    683:     dt = tbl->page_type.dt;
                    684: 
                    685:     wp = tbl->page_type.wp;
                    686: 
                    687:     s = tbl->page_type.s;
                    688: 
                    689: 
                    690: 
                    691:     /*
                    692: 
                    693:      * This can be optimized: while in a single megabyte, a quick loop on
                    694: 
                    695:      * successive long_desc's will work; similarly, while in a single 16MB,
                    696: 
                    697:      * an outer loop on the same C-level table works.
                    698: 
                    699:      */
                    700: 
                    701: 
                    702: 
                    703:     while (len) {
                    704: 
                    705:        /*
                    706: 
                    707:         * a_index is always zero.  Only the first 256MB is mapped.
                    708: 
                    709:         * b_index is the 16MB number of the page.
                    710: 
                    711:         * c_index is the 1MB number of that page within the 16MB (0-15)
                    712: 
                    713:         * d_index is the 8K number within that 1MB (0-127).
                    714: 
                    715:         */
                    716: 
                    717:        b_index = (int)(start >> LOG2_16_MEG);
                    718: 
                    719:        c_index = (int)(start >> LOG2_ONE_MEG) & 0xf;
                    720: 
                    721:        d_index = (int)(start >> LOG2_EIGHT_K) & 0x7f;
                    722: 
                    723: 
                    724: 
                    725:        tbl = base_tbl;                 /* tbl := start of A table  */
                    726: 
                    727:        tbl = tbl[0].tbl_address;       /*                 B table  */
                    728: 
                    729:        tbl = tbl[b_index].tbl_address; /*                 C table  */
                    730: 
                    731:        tbl = tbl[c_index].tbl_address; /*                 D table  */
                    732: 
                    733:        tbl = &tbl[d_index];            /* tbl := addr of page entry */
                    734: 
                    735: 
                    736: 
                    737:        if ((tbl->page_type.dt != dt) ||
                    738: 
                    739:            (tbl->page_type.s != s) ||
                    740: 
                    741:            (tbl->page_type.wp != wp)) {
                    742: 
                    743:                /* fail because it's not all the same protection */
                    744: 
                    745:                return 0;
                    746: 
                    747:        }
                    748: 
                    749:        len -= EIGHT_K;
                    750: 
                    751:        start += EIGHT_K;
                    752: 
                    753:     }
                    754: 
                    755:     /* we passed -- all the pages in question have the same prot. status */
                    756: 
                    757:     return (wp << 3) | (s << 2) | dt | 0x8000;
                    758: 
                    759: }
                    760: 
                    761: 
                    762: 
                    763: static void
                    764: 
                    765: mark_pages(long_desc *base_tbl,ulong start,ulong len,
                    766: 
                    767:            ushort dt_val, ushort s_val, ushort wp_val, PROC *proc)
                    768: 
                    769: {
                    770: 
                    771:     int b_index, c_index, d_index;
                    772: 
                    773:     long_desc *tbl;
                    774: 
                    775:     ulong oldstart, oldlen;
                    776: 
                    777: 
                    778: 
                    779:     if (no_mem_prot) return;
                    780: 
                    781: 
                    782: 
                    783:     oldstart = start;
                    784: 
                    785:     oldlen = len;
                    786: 
                    787: 
                    788: 
                    789: #ifdef MEMPROT_SHORTCUT
                    790: 
                    791:     /*
                    792: 
                    793:      * Take a shortcut here: we're done if first page of the region is
                    794: 
                    795:      * already right. We duplicate the top of the "while" loop to do it,
                    796: 
                    797:      * but what the heck.
                    798: 
                    799:      */
                    800: 
                    801:     /* I don't think this shortcut is a good idea, since while we
                    802: 
                    803:      * are doing Mshrink or Srealloc we may very well have a region
                    804: 
                    805:      * with mixed page types -- ERS
                    806: 
                    807:      */
                    808: 
                    809: 
                    810: 
                    811:     b_index = (start >> LOG2_16_MEG);
                    812: 
                    813:     c_index = (start >> LOG2_ONE_MEG) & 0xf;
                    814: 
                    815:     d_index = (start >> LOG2_EIGHT_K) & 0x7f;
                    816: 
                    817: 
                    818: 
                    819:     tbl = &(base_tbl[0].
                    820: 
                    821:            tbl_address[b_index].
                    822: 
                    823:                tbl_address[c_index].
                    824: 
                    825:                    tbl_address[d_index]);
                    826: 
                    827: 
                    828: 
                    829:     if (tbl->page_type.dt == dt_val &&
                    830: 
                    831:        tbl->page_type.s == s_val &&
                    832: 
                    833:        tbl->page_type.wp == wp_val) {
                    834: 
                    835: /*
                    836: 
                    837:            TRACE(("mark_pages a:0 b:%d c:%d d:%d (same)",
                    838: 
                    839:                    b_index,c_index,d_index));
                    840: 
                    841: */
                    842: 
                    843:            return;
                    844: 
                    845:     }
                    846: 
                    847: 
                    848: 
                    849: #endif /* MEMPROT_SHORTCUT */
                    850: 
                    851: /*
                    852: 
                    853:     MP_DEBUG(("mark_pages a:0 b:%d c:%d d:%d (diff)",b_index,c_index,d_index));
                    854: 
                    855: */
                    856: 
                    857: 
                    858: 
                    859:     /*
                    860: 
                    861:      * This can be optimized: while in a single megabyte, a quick loop on
                    862: 
                    863:      * successive long_desc's will work; similarly, while in a single 16MB,
                    864: 
                    865:      * an outer loop on the same C-level table works.
                    866: 
                    867:      */
                    868: 
                    869: 
                    870: 
                    871:     while (len) {
                    872: 
                    873:        /*
                    874: 
                    875:         * a_index is always zero.  Only the first 256MB is mapped.
                    876: 
                    877:         * b_index is the 16MB number of the page.
                    878: 
                    879:         * c_index is the 1MB number of that page within the 16MB (0-15)
                    880: 
                    881:         * d_index is the 8K number within that 1MB (0-127).
                    882: 
                    883:         */
                    884: 
                    885:        b_index = (int)(start >> LOG2_16_MEG);
                    886: 
                    887:        c_index = (int)(start >> LOG2_ONE_MEG) & 0xf;
                    888: 
                    889:        d_index = (int)(start >> LOG2_EIGHT_K) & 0x7f;
                    890: 
                    891: 
                    892: 
                    893:        tbl = base_tbl;                 /* tbl := start of A table  */
                    894: 
                    895:        tbl = tbl[0].tbl_address;       /*                 B table  */
                    896: 
                    897:        tbl = tbl[b_index].tbl_address; /*                 C table  */
                    898: 
                    899:        tbl = tbl[c_index].tbl_address; /*                 D table  */
                    900: 
                    901:        tbl = &tbl[d_index];            /* tbl := addr of page entry */
                    902: 
                    903: 
                    904: 
                    905:        tbl->page_type.dt = dt_val;
                    906: 
                    907:        tbl->page_type.s = s_val;
                    908: 
                    909:        tbl->page_type.wp = wp_val;
                    910: 
                    911:        len -= EIGHT_K;
                    912: 
                    913:        start += EIGHT_K;
                    914: 
                    915:     }
                    916: 
                    917: 
                    918: 
1.1.1.2 ! root      919:     flush_pmmu();
1.1       root      920: 
1.1.1.2 ! root      921:     if (mcpu <= 30) {
1.1       root      922: 
1.1.1.2 ! root      923:     /* On the '020 & '030 we have a logical cache, i.e. the DC & IC are on
1.1       root      924: 
1.1.1.2 ! root      925:      * the CPU side of the MMU, hence on an MMU context switch we must flush
1.1       root      926: 
1.1.1.2 ! root      927:      * them too. On the '040, by comparison, we have a physical cache, i.e.
1.1       root      928: 
1.1.1.2 ! root      929:      * the DC & IC are on the memory side of the MMU, so no DC/IC cache flush
1.1       root      930: 
1.1.1.2 ! root      931:      * is needed.
1.1       root      932: 
1.1.1.2 ! root      933:      */
1.1       root      934: 
1.1.1.2 ! root      935:        cpush((void *)oldstart, oldlen);
1.1       root      936: 
1.1.1.2 ! root      937:     }
1.1       root      938: 
                    939: }
                    940: 
                    941: 
                    942: 
                    943: /* get_prot_mode(r): returns the type of protection region r
                    944: 
                    945:  * has
                    946: 
                    947:  */
                    948: 
                    949: 
                    950: 
                    951: int
                    952: 
                    953: get_prot_mode(r)
                    954: 
                    955:        MEMREGION *r;
                    956: 
                    957: {
                    958: 
                    959:        ulong start = r->loc;
                    960: 
                    961: 
                    962: 
                    963:        if (no_mem_prot)
                    964: 
                    965:                return PROT_G;
                    966: 
                    967:        return global_mode_table[(start >> 13)];
                    968: 
                    969: }
                    970: 
                    971: 
                    972: 
                    973: void
                    974: 
                    975: mark_region(region,mode)
                    976: 
                    977: MEMREGION *region;
                    978: 
                    979: short mode;
                    980: 
                    981: {
                    982: 
                    983:     ulong start = region->loc;
                    984: 
                    985:     ulong len = region->len;
                    986: 
                    987:     ulong i;
                    988: 
                    989:     ushort dt_val, s_val, wp_val;
                    990: 
                    991:     PROC *proc;
                    992: 
                    993:     MEMREGION **mr;
                    994: 
                    995: 
                    996: 
                    997:     if (no_mem_prot) return;
                    998: 
                    999: 
                   1000: 
                   1001:     MP_DEBUG(("mark_region %lx len %lx mode %d",start,len,mode));
                   1002: 
                   1003:     
                   1004: 
                   1005:     if (mode == PROT_NOCHANGE) {
                   1006: 
                   1007:        mode = global_mode_table[(start >> 13)];
                   1008: 
                   1009:     }
                   1010: 
                   1011: 
                   1012: 
                   1013:     /* mark the global page table */
                   1014: 
                   1015: 
                   1016: 
                   1017:     memset(&global_mode_table[start >> 13],mode,(len >> 13));
                   1018: 
                   1019: 
                   1020: 
                   1021:     for (proc = proclist; proc; proc = proc->gl_next) {
                   1022: 
                   1023:        assert(proc->page_table);
                   1024: 
                   1025:        if (mode == PROT_I || mode == PROT_G) {
                   1026: 
                   1027:            /* everybody gets the same flags */
                   1028: 
                   1029:            goto notowner;
                   1030: 
                   1031:        }
                   1032: 
                   1033:        if (proc->memflags & F_OS_SPECIAL) {
                   1034: 
                   1035:            /* you're special; you get owner flags */
                   1036: 
                   1037:            MP_DEBUG(("mark_region: pid %d is an OS special!",proc->pid));
                   1038: 
                   1039:            goto owner;
                   1040: 
                   1041:        }
                   1042: 
1.1.1.2 ! root     1043:        if ((mr = proc->mem) != 0) {
1.1       root     1044: 
                   1045:            for (i = 0; i < proc->num_reg; i++, mr++) {
                   1046: 
                   1047:                if (*mr == region) {
                   1048: 
                   1049:                    MP_DEBUG(("mark_region: pid %d is an owner",proc->pid));
                   1050: 
                   1051: owner:
                   1052: 
                   1053:                    dt_val = 1;
                   1054: 
                   1055:                    s_val = 0;
                   1056: 
                   1057:                    wp_val = 0;
                   1058: 
                   1059:                    goto gotvals;
                   1060: 
                   1061:                }
                   1062: 
                   1063:            }
                   1064: 
                   1065:        }
                   1066: 
                   1067: 
                   1068: 
                   1069: notowner:
                   1070: 
                   1071: 
                   1072: 
                   1073: /* if you get here you're not an owner, or mode is G or I */
                   1074: 
                   1075:        MP_DEBUG(("mark_region: pid %d gets non-owner modes",proc->pid));
                   1076: 
                   1077: 
                   1078: 
                   1079:        dt_val = other_dt[mode];
                   1080: 
                   1081:        s_val = other_s[mode];
                   1082: 
                   1083:        wp_val = other_wp[mode];
                   1084: 
                   1085: 
                   1086: 
                   1087: gotvals:
                   1088: 
                   1089:        mark_pages(proc->page_table,start,len,dt_val,s_val,wp_val,proc);
                   1090: 
                   1091:     }
                   1092: 
                   1093: }
                   1094: 
                   1095: 
                   1096: 
                   1097: /*
                   1098: 
                   1099:  * prot_temp: temporarily alter curproc's access to memory.
                   1100: 
                   1101:  * Pass in a -1 to give curproc global access; returns a cookie.  Call
                   1102: 
                   1103:  * again with that cookie to return the memory to the old mode.
                   1104: 
                   1105:  * There should be no context switches or memory protection changes
                   1106: 
                   1107:  * in the meantime.
                   1108: 
                   1109:  *
                   1110: 
                   1111:  * If called with mode == -1, returns...
                   1112: 
                   1113:  *     -1 if mem prot is off -- no error, no action.
                   1114: 
                   1115:  *      0 if the pages are not all the same.
                   1116: 
                   1117:  *      1 if the pages are not all controlled by the page tables.
                   1118: 
                   1119:  *
                   1120: 
                   1121:  * When mode != -1, returns...
                   1122: 
                   1123:  *     0 for success (should never fail).  There is little checking.
                   1124: 
                   1125:  * Calling with mode == 0 or 1 results in zero to spoof success, but in fact
                   1126: 
                   1127:  * this is an error.  Mode is only really valid if (mode & 0x8000).
                   1128: 
                   1129:  */
                   1130: 
                   1131: 
                   1132: 
                   1133: int
                   1134: 
                   1135: prot_temp(loc,len,mode)
                   1136: 
                   1137: ulong loc;
                   1138: 
                   1139: ulong len;
                   1140: 
                   1141: int mode;
                   1142: 
                   1143: {
                   1144: 
                   1145:     int cookie;
                   1146: 
                   1147: 
                   1148: 
                   1149:     if (no_mem_prot) return -1;
                   1150: 
                   1151: 
                   1152: 
                   1153:     /* round start down to the previous page and len up to the next one. */
                   1154: 
                   1155:     loc &= ~MASKBITS;
                   1156: 
                   1157:     len = ROUND(len);
                   1158: 
                   1159: 
                   1160: 
                   1161:     if (mode == 0 || mode == 1) return 0;      /* do nothing */
                   1162: 
                   1163:     if (mode == -1) {
                   1164: 
                   1165:        cookie = get_page_cookie(curproc->page_table,loc,len);
                   1166: 
                   1167: 
                   1168: 
                   1169:        /* if not all controlled, return status */
                   1170: 
                   1171:        if (cookie == 0 || cookie == 1) return cookie;
                   1172: 
                   1173: 
                   1174: 
                   1175:        mark_pages(curproc->page_table,loc,len,1,0,0,curproc);
                   1176: 
                   1177: 
                   1178: 
                   1179:        return cookie;
                   1180: 
                   1181:     }
                   1182: 
                   1183:     else {
                   1184: 
                   1185:        mark_pages(curproc->page_table,loc,len,
                   1186: 
1.1.1.2 ! root     1187:                    mode&3,(mode&4)>>2,(mode&8)>>3,curproc);
1.1       root     1188: 
                   1189:        return 0;
                   1190: 
                   1191:     }
                   1192: 
                   1193: }
                   1194: 
                   1195: 
                   1196: 
                   1197: /*
                   1198: 
                   1199:  * init_page_table: fill in the page table for the indicated process. The
                   1200: 
                   1201:  * master page map is consulted for the modes of all pages, and the memory
                   1202: 
                   1203:  * region data structures are consulted to see if this process is the owner
                   1204: 
                   1205:  * of any of those tables.
                   1206: 
                   1207:  *
                   1208: 
                   1209:  * This also sets crp and tc in both ctxts of the process.  If this is the
                   1210: 
                   1211:  * first call, then the CPU tc is cleared, the TT0 and TT1 regs are zapped,
                   1212: 
                   1213:  * and then this proc's crp and tc are loaded into it.
                   1214: 
                   1215:  */
                   1216: 
                   1217: 
                   1218: 
                   1219: static short mmu_is_set_up = 0;
                   1220: 
                   1221: 
                   1222: 
                   1223: void
                   1224: 
                   1225: init_page_table(proc)
                   1226: 
                   1227: PROC *proc;
                   1228: 
                   1229: {
                   1230: 
                   1231:     long_desc *tptr;
                   1232: 
                   1233:     long_desc *tbl_a;          /* top-level table */
                   1234: 
                   1235:     long_desc *tbl_b0;         /* second level, handles $0 nybble */
                   1236: 
                   1237:     long_desc *tbl_bf;         /* handles $F nybble */
                   1238: 
                   1239:     long_desc *tbl_c;          /* temp pointer to start of 16MB */
                   1240: 
                   1241:     ulong p, q, r;
                   1242: 
                   1243:     ulong i, j, k;
                   1244: 
                   1245:     int g;
                   1246: 
                   1247:     MEMREGION **mr;
                   1248: 
                   1249: 
                   1250: 
                   1251:     if (no_mem_prot) return;
                   1252: 
                   1253: 
                   1254: 
                   1255:     if (proc->pid)
                   1256: 
                   1257:         TRACELOW(("init_page_table(proc=%lx, pid %d)",proc,proc->pid));
                   1258: 
                   1259: 
                   1260: 
                   1261:     assert(proc && proc->page_table);
                   1262: 
                   1263: 
                   1264: 
                   1265:     tptr = proc->page_table;
                   1266: 
                   1267:     tbl_a = tptr;
                   1268: 
                   1269:     tptr += TBL_SIZE;
                   1270: 
                   1271:     tbl_b0 = tptr;
                   1272: 
                   1273:     tptr += TBL_SIZE;
                   1274: 
                   1275:     tbl_bf = tptr;
                   1276: 
                   1277:     tptr += TBL_SIZE;
                   1278: 
                   1279: 
                   1280: 
                   1281:     /*
                   1282: 
                   1283:      * table A indexes by the first nybble: $0 and $F refer to their tables,
                   1284: 
                   1285:      * $1-$7 are uncontrolled, cacheable; $8-$E are uncontrolled, ci.
                   1286: 
                   1287:      */
                   1288: 
                   1289: 
                   1290: 
                   1291:     tbl_a[0].page_type = page_ptr;
                   1292: 
                   1293:     tbl_a[0].tbl_address = tbl_b0;
                   1294: 
                   1295: 
                   1296: 
                   1297:     for (i=1; i<0xf; i++) {
                   1298: 
                   1299:        if (i < 8)  tbl_a[i].page_type = g_page;
                   1300: 
                   1301:        else        tbl_a[i].page_type = g_ci_page;
                   1302: 
                   1303:        tbl_a[i].tbl_address = (long_desc *)(i << 28);
                   1304: 
                   1305:     }
                   1306: 
                   1307: 
                   1308: 
                   1309:     /* $F entry of table A refers to table BF */
                   1310: 
                   1311:     tbl_a[0xf].page_type = page_ptr;
                   1312: 
                   1313:     tbl_a[0xf].tbl_address = tbl_bf;
                   1314: 
                   1315: 
                   1316: 
                   1317:     /*
                   1318: 
                   1319:      * table B0: entry 0 is $00, the 16MB of ST address space.
                   1320: 
                   1321:      */
                   1322: 
                   1323: 
                   1324: 
                   1325:     tbl_b0[0].page_type = page_ptr;
                   1326: 
                   1327:     tbl_b0[0].tbl_address = tptr;
                   1328: 
                   1329:     tbl_c = tptr;
                   1330: 
                   1331:     tptr += TBL_SIZE;
                   1332: 
                   1333: 
                   1334: 
                   1335:     /* for each megabyte that is RAM, allocate a table */
                   1336: 
                   1337:     for (i = 0, k = 0, p = 0; p < mint_top_st; i++, p += 0x00100000L) {
                   1338: 
                   1339:        tbl_c[i].page_type = page_ptr;
                   1340: 
                   1341:        tbl_c[i].tbl_address = tptr;
                   1342: 
                   1343: 
                   1344: 
                   1345:        /* for each page in this megabyte, write a page entry */
                   1346: 
                   1347:        for (q = p, j = 0; j < 128; j++, q += 0x2000, k++) {
                   1348: 
                   1349:            tptr->page_type = *proto_page_type[global_mode_table[k]];
                   1350: 
                   1351:            tptr->tbl_address = (long_desc *)q;
                   1352: 
                   1353:            tptr++;
                   1354: 
                   1355:        }
                   1356: 
                   1357:     }
                   1358: 
                   1359: 
                   1360: 
                   1361:     /* now for each megabyte from mint_top_st to ROM, mark global */
                   1362: 
                   1363:     for ( ; p < 0x00E00000L; i++, p += 0x00100000L) {
                   1364: 
                   1365:        tbl_c[i].page_type = g_page;
                   1366: 
                   1367:        tbl_c[i].tbl_address = (long_desc *)p;
                   1368: 
                   1369:     }
                   1370: 
                   1371: 
                   1372: 
                   1373:     /* fill in the E and F tables: 00Ex is ROM, 00Fx is I/O  */
                   1374: 
                   1375:     tbl_c[i].page_type = g_page;
                   1376: 
                   1377:     tbl_c[i].tbl_address = (long_desc *)p;
                   1378: 
                   1379:     i++, p += 0x00100000L;
                   1380: 
                   1381:     tbl_c[i].page_type = g_ci_page;
                   1382: 
                   1383:     tbl_c[i].tbl_address = (long_desc *)p;
                   1384: 
                   1385: 
                   1386: 
                   1387:         /* Done with tbl_c for 0th 16MB; go on to TT RAM */
                   1388: 
                   1389: 
                   1390: 
                   1391: /* 
                   1392: 
                   1393:     structure:
                   1394: 
                   1395: 
                   1396: 
                   1397:     for (i = each 16MB that has any TT RAM in it)
                   1398: 
                   1399:        allocate a table tbl_c, point tbl_b0[i] at it
                   1400: 
                   1401:        for (j = each 1MB that is RAM)
                   1402: 
                   1403:            allocate a table, point tbl_c[j] at it
                   1404: 
                   1405:            for (k = each page in the megabyte)
                   1406: 
                   1407:                fill in tbl_c[j][k] with page entry from global_mode_table
                   1408: 
                   1409:        for (j = the rest of the 16MB)
                   1410: 
                   1411:            set tbl_c[j] to "global, cacheable"
                   1412: 
                   1413: 
                   1414: 
                   1415:     for (i = the rest of the 16MBs from here to $7F)
                   1416: 
                   1417:        set tbl_b0[i] to "global, cacheable"
                   1418: 
                   1419: 
                   1420: 
                   1421:     for (i = the rest of the 16MBs from $80 up to but not incl. $FF)
                   1422: 
                   1423:        set tbl_b0[i] to "global, not cacheable"
                   1424: 
                   1425: */
                   1426: 
                   1427: 
                   1428: 
                   1429:     /* i counts 16MBs */
                   1430: 
                   1431:     for (i = 1, p = 0x01000000L, g = 2048;
                   1432: 
                   1433:         p < mint_top_tt;
                   1434: 
                   1435:         p += SIXTEEN_MEG, i++) {
                   1436: 
                   1437:            tbl_b0[i].page_type = page_ptr;
                   1438: 
                   1439:            tbl_b0[i].tbl_address = tptr;
                   1440: 
                   1441:            tbl_c = tptr;
                   1442: 
                   1443:            tptr += TBL_SIZE;
                   1444: 
                   1445: 
                   1446: 
                   1447:            /* j counts MBs */
                   1448: 
                   1449:            for (j = 0, q = p; j < 16 && q < mint_top_tt; q += ONE_MEG, j++) {
                   1450: 
                   1451:                tbl_c[j].page_type = page_ptr;
                   1452: 
                   1453:                tbl_c[j].tbl_address = tptr;
                   1454: 
                   1455:                /* k counts pages (8K) */
                   1456: 
                   1457:                for (r = q, k = 0; k < 128; k++, r += 0x2000, g++) {
                   1458: 
                   1459:                    tptr->page_type = *proto_page_type[global_mode_table[g]];
                   1460: 
                   1461:                    tptr->tbl_address = (long_desc *)r;
                   1462: 
                   1463:                    tptr++;
                   1464: 
                   1465:                }
                   1466: 
                   1467:            }
                   1468: 
                   1469:            for ( ; j < 16; j++, q += ONE_MEG) {
                   1470: 
                   1471:                /* fill in the rest of this 16MB */
                   1472: 
                   1473:                tbl_c[j].page_type = g_page;
                   1474: 
                   1475:                tbl_c[j].tbl_address = (long_desc *)q;
                   1476: 
                   1477:            }
                   1478: 
                   1479:     }
                   1480: 
                   1481: 
                   1482: 
                   1483:     /* fill in the rest of $00-$0F as cacheable */
                   1484: 
                   1485:     for ( ; i < 16; i++, p += SIXTEEN_MEG) {
                   1486: 
                   1487:        tbl_b0[i].page_type = g_page;
                   1488: 
                   1489:        tbl_b0[i].tbl_address = (long_desc *)p;
                   1490: 
                   1491:     }
                   1492: 
                   1493: 
                   1494: 
                   1495:     /* done with TT RAM in table b0; do table bf */
                   1496: 
                   1497: 
                   1498: 
                   1499:     /*
                   1500: 
                   1501:      * Table BF: translates addresses starting with $F.  First 15 are
                   1502: 
                   1503:      * uncontrolled, cacheable; last one translates $FF, which
                   1504: 
                   1505:      * which shadows $00 (the 16MB ST address space).  The rest
                   1506: 
                   1507:      * are uncontrolled, not cacheable.
                   1508: 
                   1509:      *
                   1510: 
                   1511:      * The table address of the copy has a 1 in the low (unused) bit, which
                   1512: 
                   1513:      * is a signal to the table dumper not to dump this, as it's a copy
                   1514: 
                   1515:      * of tbl_b0[0].
                   1516: 
                   1517:      */
                   1518: 
                   1519: 
                   1520: 
                   1521:     for (i=0; i<0xf; i++) {
                   1522: 
                   1523:        tbl_bf[i].page_type = g_ci_page;
                   1524: 
                   1525:        tbl_bf[i].tbl_address = (long_desc *)((i << 24) | 0xf0000000L);
                   1526: 
                   1527:     }
                   1528: 
                   1529:     tbl_bf[0xf] = tbl_b0[0];
                   1530: 
                   1531:     *(ulong *)(&(tbl_bf[0xf].tbl_address)) |= 1;
                   1532: 
                   1533: 
                   1534: 
                   1535:     proc->ctxt[0].crp.limit = 0x7fff;  /* disable limit function */
                   1536: 
                   1537:     proc->ctxt[0].crp.dt = 3;          /* points to valid 8-byte entries */
                   1538: 
                   1539:     proc->ctxt[0].crp.tbl_address = tbl_a;
                   1540: 
                   1541:     proc->ctxt[1].crp = proc->ctxt[0].crp;
                   1542: 
                   1543:     proc->ctxt[0].tc = tc;
                   1544: 
                   1545:     proc->ctxt[1].tc = tc;
                   1546: 
                   1547: 
                   1548: 
                   1549:     /*
                   1550: 
                   1551:      * OK, memory tables are now there as if you're a non-owner of every
                   1552: 
                   1553:      * page.  Now for each region you ARE an owner of, mark with owner
                   1554: 
                   1555:      * modes.
                   1556: 
                   1557:      */
                   1558: 
                   1559: 
                   1560: 
                   1561:     mr = proc->mem;
                   1562: 
                   1563:     for (i=0; i < proc->num_reg; i++, mr++) {
                   1564: 
                   1565:        if (*mr) {
                   1566: 
                   1567:            mark_pages(proc->page_table,(*mr)->loc,(*mr)->len,1,0,0,proc);
                   1568: 
                   1569:        }
                   1570: 
                   1571:     }
                   1572: 
                   1573: 
                   1574: 
                   1575:     if (!mmu_is_set_up) {
                   1576: 
                   1577:        set_mmu(proc->ctxt[0].crp,proc->ctxt[0].tc);
                   1578: 
                   1579:        mmu_is_set_up = 1;
                   1580: 
                   1581:     }
                   1582: 
                   1583: }
                   1584: 
                   1585: 
                   1586: 
                   1587: /*
                   1588: 
                   1589:  * This routine is called when procfs detects that a process wants to be an
                   1590: 
                   1591:  * OS SPECIAL.  The AES, SCRENMGR, and DESKTOP do this, and so does FSMGDOS
                   1592: 
                   1593:  * and possibly some other stuff. It has to re-mark every page in that
                   1594: 
                   1595:  * process' page table based on its new special status. The "special
                   1596: 
                   1597:  * status" is "you get global access to all of memory" and "everybody
                   1598: 
                   1599:  * gets Super access to yours."  It is the caller's responsibility
                   1600: 
                   1601:  * to set proc's memflags, usually to (F_OS_SPECIAL | F_PROT_S).
                   1602: 
                   1603:  */
                   1604: 
                   1605: 
                   1606: 
                   1607: void
                   1608: 
                   1609: mem_prot_special(proc)
                   1610: 
                   1611: PROC *proc;
                   1612: 
                   1613: {
                   1614: 
                   1615:     MEMREGION **mr;
                   1616: 
                   1617:     int i;
                   1618: 
                   1619: 
                   1620: 
                   1621:     if (no_mem_prot) return;
                   1622: 
                   1623: 
                   1624: 
                   1625:     TRACE(("mem_prot_special(pid %d)",proc->pid));
                   1626: 
                   1627: 
                   1628: 
                   1629:     /*
                   1630: 
                   1631:      * This marks ALL memory, allocated or not, as accessible. When memory
                   1632: 
                   1633:      * is freed even F_OS_SPECIAL processes lose access to it. So one or
                   1634: 
                   1635:      * the other of these is a bug, depending on how you want it to work.
                   1636: 
                   1637:      */
                   1638: 
                   1639:     mark_pages(proc->page_table,0,mint_top_st,1,0,0,proc);
                   1640: 
                   1641:     if (mint_top_tt) {
                   1642: 
                   1643:        mark_pages(proc->page_table,
                   1644: 
                   1645:                    0x01000000L,
                   1646: 
                   1647:                    mint_top_tt - 0x01000000L,
                   1648: 
                   1649:                    1,0,0,
                   1650: 
                   1651:                    proc);
                   1652: 
                   1653:     }
                   1654: 
                   1655: 
                   1656: 
                   1657:     /*
                   1658: 
                   1659:      * In addition, mark all the pages the process already owns as "super"
                   1660: 
                   1661:      * in all other processes.  Thus the "special" process can access all
                   1662: 
                   1663:      * of memory, and any process can access the "special" process' memory
                   1664: 
                   1665:      * when in super mode.
                   1666: 
                   1667:      */
                   1668: 
                   1669: 
                   1670: 
                   1671:     mr = proc->mem;
                   1672: 
                   1673: 
                   1674: 
                   1675:     for (i=0; i < proc->num_reg; i++, mr++) {
                   1676: 
                   1677:        if (*mr) {
                   1678: 
                   1679:            mark_region(*mr,PROT_S);
                   1680: 
                   1681:        }
                   1682: 
                   1683:     }
                   1684: 
                   1685: }
                   1686: 
                   1687:     
                   1688: 
                   1689: /*----------------------------------------------------------------------------
                   1690: 
                   1691:  * DEBUGGING SECTION
                   1692: 
                   1693:  *--------------------------------------------------------------------------*/
                   1694: 
                   1695: 
                   1696: 
                   1697: static void
                   1698: 
                   1699: _dump_tree(tbl,level)
                   1700: 
                   1701: long_desc tbl;
                   1702: 
                   1703: int level;
                   1704: 
                   1705: {
                   1706: 
                   1707:     int i, j;
                   1708: 
                   1709:     long_desc *p;
                   1710: 
1.1.1.2 ! root     1711:     static const char spaces[9] = "        ";
1.1       root     1712: 
                   1713: 
                   1714: 
                   1715:     /* print the level and display the table descriptor */
                   1716: 
                   1717:     FORCE("\r%s s:%x wp:%x dt:%x a:%08lx",
                   1718: 
                   1719:        &spaces[8-(level*2)],
                   1720: 
                   1721:        tbl.page_type.s,
                   1722: 
                   1723:        tbl.page_type.wp,
                   1724: 
                   1725:        tbl.page_type.dt,
                   1726: 
                   1727:        tbl.tbl_address);
                   1728: 
                   1729: 
                   1730: 
                   1731:     if (tbl.page_type.dt == 3) {
                   1732: 
                   1733:        if (level == 0) {
                   1734: 
                   1735:            j = (1 << tc.tia);
                   1736: 
                   1737:        }
                   1738: 
                   1739:        else if (level == 1) {
                   1740: 
                   1741:            j = (1 << tc.tib);
                   1742: 
                   1743:        }
                   1744: 
                   1745:        else if (level == 2) {
                   1746: 
                   1747:            j = (1 << tc.tic);
                   1748: 
                   1749:        }
                   1750: 
                   1751:        else {
                   1752: 
                   1753:            j = (1 << tc.tid);
                   1754: 
                   1755:        }
                   1756: 
                   1757: 
                   1758: 
                   1759:        /* don't show table if it's the duplicate */
                   1760: 
                   1761:        if ((ulong)tbl.tbl_address & 1) return;
                   1762: 
                   1763: 
                   1764: 
                   1765:        ++level;
                   1766: 
                   1767:        p = tbl.tbl_address;
                   1768: 
                   1769:        for (i=0; i<j; i++, p++) {
                   1770: 
                   1771:            _dump_tree(*p,level);
                   1772: 
                   1773:        }
                   1774: 
                   1775:     }
                   1776: 
                   1777: }
                   1778: 
                   1779: 
                   1780: 
1.1.1.2 ! root     1781: static const char modesym[] = { 'p', 'g', 's', 'r', 'i' };
1.1       root     1782: 
                   1783: 
                   1784: 
                   1785: void
                   1786: 
                   1787: QUICKDUMP()
                   1788: 
                   1789: {
                   1790: 
                   1791:     char outstr[33];
                   1792: 
                   1793:     ulong i, j, end;
                   1794: 
                   1795: 
                   1796: 
                   1797:     if (no_mem_prot) return;
                   1798: 
                   1799: 
                   1800: 
                   1801:     FORCE("STRAM global table:");
                   1802: 
                   1803:     outstr[32] = '\0';
                   1804: 
                   1805:     end = mint_top_st / QUANTUM;
                   1806: 
                   1807:     for (i = 0; i < end; i += 32) {
                   1808: 
                   1809:        for (j=0; j<32; j++) {
                   1810: 
                   1811:            outstr[j] = modesym[global_mode_table[j+i]];
                   1812: 
                   1813:        }
                   1814: 
                   1815:        FORCE("%08lx: %s",i*8192L,outstr);
                   1816: 
                   1817:     }
                   1818: 
                   1819: 
                   1820: 
                   1821:     if (mint_top_tt) {
                   1822: 
                   1823:        FORCE("TTRAM global table:");
                   1824: 
                   1825:        end = mint_top_tt / QUANTUM;
                   1826: 
                   1827:        for (i = 2048; i < end; i += 32) {
                   1828: 
                   1829:            for (j=0; j<32; j++) {
                   1830: 
                   1831:                outstr[j] = modesym[global_mode_table[j+i]];
                   1832: 
                   1833:            }
                   1834: 
                   1835:            FORCE("%08lx: %s",i*8192L,outstr);
                   1836: 
                   1837:        }
                   1838: 
                   1839:     }
                   1840: 
                   1841: }
                   1842: 
                   1843: 
                   1844: 
                   1845: const char *berr_msg[] = { 
                   1846: 
                   1847: /*  "........." */
                   1848: 
                   1849:     "private  ",
                   1850: 
                   1851:     "global   ",    /* turned into "hardware" for violation reports */
                   1852: 
                   1853:     "super    ",
                   1854: 
                   1855:     "readable ",
                   1856: 
                   1857:     "free     ",
                   1858: 
                   1859:     "hardware "            /* used when the memory is not controlled by us */
                   1860: 
                   1861: };
                   1862: 
                   1863: 
                   1864: 
                   1865: void
                   1866: 
                   1867: report_buserr()
                   1868: 
                   1869: {
                   1870: 
1.1.1.2 ! root     1871:     const char *vmsg;
1.1       root     1872: 
                   1873:     short mode;
                   1874: 
                   1875:     ulong aa, pc;
                   1876: 
                   1877:     char alertbuf[5*32+16];    /* enough for an alert */
                   1878: 
                   1879:     char *aptr;
                   1880: 
                   1881: 
                   1882: 
                   1883:     if (no_mem_prot) return;
                   1884: 
                   1885: 
                   1886: 
                   1887:     aa = curproc->exception_addr;
                   1888: 
                   1889:     pc = curproc->exception_pc;
                   1890: 
                   1891:     if ((mint_top_tt && aa < mint_top_tt) || (aa < mint_top_st)) {
                   1892: 
                   1893:        mode = global_mode_table[(curproc->exception_addr >> 13)];
                   1894: 
                   1895:        if (mode == PROT_G) {
                   1896: 
                   1897:            /* page is global: obviously a hardware bus error */
                   1898: 
                   1899:            mode = 5;
                   1900: 
                   1901:        }
                   1902: 
                   1903:     }
                   1904: 
                   1905:     else {
                   1906: 
                   1907:        /* (addr is > mint_top_tt) set mode = 5 so we don't look for owners */
                   1908: 
                   1909:        mode = 5;
                   1910: 
                   1911:     }
                   1912: 
                   1913:     vmsg = berr_msg[mode];
                   1914: 
                   1915: 
                   1916: 
                   1917:     /* construct an AES alert box for this error:
                   1918: 
                   1919:        | PROCESS  "buserrxx"  KILLED: |
                   1920: 
                   1921:        | MEMORY VIOLATION.  (PID 000) |
                   1922: 
                   1923:        |                              |
                   1924: 
                   1925:        | Type: ......... PC: pc...... |
                   1926: 
                   1927:        | Addr: ........  BP: ........ |
                   1928: 
                   1929:     */
                   1930: 
                   1931: 
                   1932: 
                   1933:     /* we play games to get around 128-char max for ksprintf */
                   1934: 
                   1935:     ksprintf(alertbuf,"[1][ PROCESS  \"%s\"  KILLED: |",curproc->name);
                   1936: 
                   1937:     aptr = alertbuf + strlen(alertbuf);
                   1938: 
                   1939:     ksprintf(aptr," MEMORY VIOLATION.  (PID %03d) | |",curproc->pid);
                   1940: 
                   1941:     aptr = alertbuf + strlen(alertbuf);
                   1942: 
                   1943:     ksprintf(aptr," Type: %s PC: %08lx |",vmsg,pc);
                   1944: 
                   1945:     aptr = alertbuf + strlen(alertbuf);
                   1946: 
                   1947:     ksprintf(aptr," Addr: %08lx  BP: %08lx ][ OK ]",aa,curproc->base);
                   1948: 
                   1949:     if (!_ALERT(alertbuf)) {
                   1950: 
                   1951:        /* this will call _alert again, but it will just fail again */
                   1952: 
                   1953:        ALERT("MEMORY VIOLATION: type=%s AA=%lx PC=%lx BP=%lx",
                   1954: 
                   1955:                vmsg,aa,pc,curproc->base);
                   1956: 
                   1957:     }
                   1958: 
                   1959:        
                   1960: 
                   1961:     if (curproc->pid == 0 || curproc->memflags & F_OS_SPECIAL) {
                   1962: 
                   1963:     /* the system is so thoroughly hosed that anything we try will
                   1964: 
                   1965:      * likely cause another bus error; so let's just hang up
                   1966: 
                   1967:      */
                   1968: 
                   1969:        FATAL("Operating system killed");
                   1970: 
                   1971:     }
                   1972: 
                   1973: }
                   1974: 
                   1975: 
                   1976: 
                   1977: /*
                   1978: 
                   1979:  * big_mem_dump is a biggie: for each page in the system, it
                   1980: 
                   1981:  * displays the PID of the (first) owner and the protection mode.
                   1982: 
                   1983:  * The output has three chars per page, and eight chars per line.
                   1984: 
                   1985:  * The first page of a region is marked with the mode, and the
                   1986: 
                   1987:  * rest with a space.
                   1988: 
                   1989:  *
                   1990: 
                   1991:  * Logic:
                   1992: 
                   1993:     for (mp = *core; mp; mp++) {
                   1994: 
                   1995:        for (each page of this region) {
                   1996: 
                   1997:            if (start of line) {
                   1998: 
                   1999:                output line starter;
                   2000: 
                   2001:            }
                   2002: 
                   2003:            if (start of region) {
                   2004: 
                   2005:                output mode of this page;
                   2006: 
                   2007:                determine owner;
                   2008: 
                   2009:                output owner;
                   2010: 
                   2011:            }
                   2012: 
                   2013:            else {
                   2014: 
                   2015:                output space;
                   2016: 
                   2017:                output owner;
                   2018: 
                   2019:            }
                   2020: 
                   2021:         }
                   2022: 
                   2023:     }
                   2024: 
                   2025:  */
                   2026: 
                   2027: 
                   2028: 
                   2029: void
                   2030: 
                   2031: BIG_MEM_DUMP(bigone,proc)
                   2032: 
                   2033: int bigone;
                   2034: 
                   2035: PROC *proc;
                   2036: 
                   2037: {
                   2038: 
1.1.1.2 ! root     2039: #ifdef DEBUG_INFO
1.1       root     2040: 
                   2041:     char linebuf[128];
                   2042: 
                   2043:     char *lp = linebuf;
                   2044: 
                   2045:     MEMREGION *mp, **mr, **map;
                   2046: 
                   2047:     PROC *p;
                   2048: 
                   2049:     ulong loc;
                   2050: 
1.1.1.2 ! root     2051:     short owner;
1.1       root     2052: 
                   2053:     short i;
                   2054: 
                   2055:     short first;
                   2056: 
                   2057: 
                   2058: 
                   2059: 
                   2060: 
                   2061:   if (no_mem_prot) return;
                   2062: 
                   2063: 
                   2064: 
                   2065:   for (map = core; map != 0; ((map == core) ? (map = alt) : (map = 0))) {
                   2066: 
                   2067:     FORCE("Annotated memory dump for %s",(map == core ? "core" : "alt"));
                   2068: 
                   2069:     first = 1;
                   2070: 
                   2071:     *linebuf = '\0';
                   2072: 
                   2073:     for (mp = *map; mp; mp = mp->next) {
                   2074: 
                   2075:        for (loc = mp->loc; loc < (mp->loc + mp->len); loc += EIGHT_K) {
                   2076: 
                   2077:            if (first || ((loc & 0x1ffff) == 0)) {
                   2078: 
                   2079:                if (*linebuf) FORCE(linebuf);
                   2080: 
                   2081:                ksprintf(linebuf,"\r%08lx: ",loc);
                   2082: 
                   2083:                lp = &linebuf[11];
                   2084: 
                   2085:                first = 0;
                   2086: 
                   2087:            }
                   2088: 
                   2089:            if (loc == mp->loc) {
                   2090: 
                   2091:                *lp++ = modesym[global_mode_table[loc / EIGHT_K]];
                   2092: 
                   2093: 
                   2094: 
                   2095:                for (p = proclist; p; p = p->gl_next) {
                   2096: 
                   2097:                    if (p->mem) {
                   2098: 
                   2099:                        mr = p->mem;
                   2100: 
                   2101:                        for (i=0; i < p->num_reg; i++, mr++) {
                   2102: 
                   2103:                            if (*mr == mp) {
                   2104: 
                   2105:                                owner = p->pid;
                   2106: 
                   2107:                                goto gotowner;
                   2108: 
                   2109:                            }
                   2110: 
                   2111:                        }
                   2112: 
                   2113:                    }
                   2114: 
                   2115:                }
                   2116: 
                   2117:                owner = 000;
                   2118: 
                   2119: gotowner:
                   2120: 
                   2121:                ksprintf(lp,"%03d",owner);
                   2122: 
                   2123:                lp += 3;
                   2124: 
                   2125:            }
                   2126: 
                   2127:            else {
                   2128: 
                   2129:                *lp++ = ' ';
                   2130: 
                   2131:                *lp++ = '-';
                   2132: 
                   2133:                *lp++ = '-';
                   2134: 
                   2135:                *lp++ = '-';
                   2136: 
                   2137:                *lp = '\0';     /* string is always null-terminated */
                   2138: 
                   2139:            }
                   2140: 
                   2141:         }
                   2142: 
                   2143:     }
                   2144: 
                   2145:     FORCE(linebuf);
                   2146: 
                   2147:   }
                   2148: 
                   2149: 
                   2150: 
                   2151:     if (bigone) {
                   2152: 
                   2153:        long_desc tbl;
                   2154: 
                   2155: 
                   2156: 
                   2157:        /* fill in tbl with the only parts used at the top level */
                   2158: 
                   2159:        tbl.page_type.dt = proc->ctxt[CURRENT].crp.dt;
                   2160: 
                   2161:        tbl.tbl_address = proc->ctxt[CURRENT].crp.tbl_address;
                   2162: 
                   2163:        _dump_tree(tbl,0);
                   2164: 
                   2165:     }
                   2166: 
1.1.1.2 ! root     2167: #endif /* DEBUG_INFO */
1.1       root     2168: 
                   2169: }
                   2170: 
                   2171: 
                   2172: 
                   2173: 
                   2174: 
                   2175: /*
                   2176: 
                   2177:  * Can the process "p" access the "nbytes" long
                   2178: 
                   2179:  * block of memory starting at "start"?
                   2180: 
                   2181:  * If it would be a legal access, the current
                   2182: 
                   2183:  * process is given temporary access via
                   2184: 
                   2185:  * prot_temp.
                   2186: 
                   2187:  * Returns a cookie like the one prot_temp
                   2188: 
                   2189:  * returns; if the process shouldn't have
                   2190: 
                   2191:  * access to the memory, returns 1.
                   2192: 
                   2193:  *
                   2194: 
                   2195:  * BUG: should actually read p's page table to
                   2196: 
                   2197:  * determine access
                   2198: 
                   2199:  */
                   2200: 
                   2201: 
                   2202: 
                   2203: int
                   2204: 
                   2205: mem_access_for(p, start, nbytes)
                   2206: 
                   2207:        PROC *p;
                   2208: 
                   2209:        ulong start;
                   2210: 
                   2211:        long nbytes;
                   2212: 
                   2213: {
                   2214: 
                   2215:        MEMREGION **mr;
                   2216: 
                   2217:        int i;
                   2218: 
                   2219: 
                   2220: 
                   2221:        if (no_mem_prot) return -1;
                   2222: 
                   2223:        if (start >= (ulong)p && start+nbytes <= (ulong)(p+1))
                   2224: 
                   2225:                return -1;
                   2226: 
                   2227:        if (p == rootproc)
                   2228: 
                   2229:                goto win_and_mark;
                   2230: 
                   2231: 
                   2232: 
                   2233:        mr = p->mem;
                   2234: 
                   2235:        if (mr) {
                   2236: 
                   2237:            for (i = 0; i < p->num_reg; i++, mr++) {
                   2238: 
                   2239:                if (*mr) {
                   2240: 
                   2241:                    if (((*mr)->loc <= start) &&
                   2242: 
                   2243:                        ((*mr)->loc + (*mr)->len >= start + nbytes))
                   2244: 
                   2245:                            goto win_and_mark;
                   2246: 
                   2247:                }
                   2248: 
                   2249:            }
                   2250: 
                   2251:        }
                   2252: 
                   2253: 
                   2254: 
                   2255:        return 0;       /* we don't own this memory */
                   2256: 
                   2257: 
                   2258: 
                   2259: win_and_mark:
                   2260: 
                   2261:        return prot_temp(start, nbytes, -1);
                   2262: 
                   2263: }
                   2264: 

unix.superglobalmegacorp.com

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