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

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: 
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: 
                    781:     if (no_mem_prot) return;
                    782: 
                    783: 
                    784: 
                    785:     oldlen = len;
                    786: 
                    787: 
                    788: 
                    789:     /*
                    790: 
1.1.1.3 ! root      791:      * a_index is always zero.  Only the first 256MB is mapped.
1.1       root      792: 
1.1.1.3 ! root      793:      * b_index is the 16MB number of the page.
1.1       root      794: 
1.1.1.3 ! root      795:      * c_index is the 1MB number of that page within the 16MB (0-15)
1.1       root      796: 
1.1.1.3 ! root      797:      * d_index is the 8K number within that 1MB (0-127).
1.1       root      798: 
                    799:      */
                    800: 
                    801: 
                    802: 
                    803:     b_index = (start >> LOG2_16_MEG);
                    804: 
                    805:     c_index = (start >> LOG2_ONE_MEG) & 0xf;
                    806: 
                    807:     d_index = (start >> LOG2_EIGHT_K) & 0x7f;
                    808: 
                    809: 
                    810: 
1.1.1.3 ! root      811:     /* precompute the table addresses */
        !           812: 
        !           813:     tbl_b = &base_tbl[0].tbl_address[b_index];
        !           814: 
        !           815:     tbl_c = &tbl_b->tbl_address[c_index];
        !           816: 
        !           817:     tbl = &tbl_c->tbl_address[d_index];
        !           818: 
        !           819: 
        !           820: 
        !           821: #ifdef MEMPROT_SHORTCUT
        !           822: 
        !           823:     /*
        !           824: 
        !           825:      * Take a shortcut here: we're done if first page of the region is
        !           826: 
        !           827:      * already right.
1.1       root      828: 
1.1.1.3 ! root      829:      */
1.1       root      830: 
1.1.1.3 ! root      831:     /* I don't think this shortcut is a good idea, since while we
1.1       root      832: 
1.1.1.3 ! root      833:      * are doing Mshrink or Srealloc we may very well have a region
        !           834: 
        !           835:      * with mixed page types -- ERS
        !           836: 
        !           837:      */
1.1       root      838: 
                    839: 
                    840: 
                    841:     if (tbl->page_type.dt == dt_val &&
                    842: 
                    843:        tbl->page_type.s == s_val &&
                    844: 
                    845:        tbl->page_type.wp == wp_val) {
                    846: 
                    847: /*
                    848: 
                    849:            TRACE(("mark_pages a:0 b:%d c:%d d:%d (same)",
                    850: 
                    851:                    b_index,c_index,d_index));
                    852: 
                    853: */
                    854: 
                    855:            return;
                    856: 
                    857:     }
                    858: 
                    859: 
                    860: 
                    861: #endif /* MEMPROT_SHORTCUT */
                    862: 
                    863: /*
                    864: 
                    865:     MP_DEBUG(("mark_pages a:0 b:%d c:%d d:%d (diff)",b_index,c_index,d_index));
                    866: 
                    867: */
                    868: 
                    869: 
                    870: 
1.1.1.3 ! root      871:     for (;;)
1.1       root      872: 
1.1.1.3 ! root      873:       {
1.1       root      874: 
1.1.1.3 ! root      875:        /* quickly loop through the 1MB-block */
1.1       root      876: 
1.1.1.3 ! root      877:        for (; len && tbl < &tbl_c->tbl_address[0x80]; tbl++)
1.1       root      878: 
1.1.1.3 ! root      879:          {
1.1       root      880: 
1.1.1.3 ! root      881:            tbl->page_type.dt = dt_val;
1.1       root      882: 
1.1.1.3 ! root      883:            tbl->page_type.s = s_val;
1.1       root      884: 
1.1.1.3 ! root      885:            tbl->page_type.wp = wp_val;
1.1       root      886: 
1.1.1.3 ! root      887:            len -= EIGHT_K;
1.1       root      888: 
1.1.1.3 ! root      889:          }
1.1       root      890: 
                    891: 
                    892: 
1.1.1.3 ! root      893:        if (len == 0L)
1.1       root      894: 
1.1.1.3 ! root      895:          break;
1.1       root      896: 
                    897: 
                    898: 
1.1.1.3 ! root      899:        /* get the next d-table */
1.1       root      900: 
1.1.1.3 ! root      901:        tbl_c++;
1.1       root      902: 
1.1.1.3 ! root      903:        /* if crossing a 16MB boundary, get the next c-table */
1.1       root      904: 
1.1.1.3 ! root      905:        if (tbl_c == &tbl_b->tbl_address[0x10])
1.1       root      906: 
1.1.1.3 ! root      907:          {
1.1       root      908: 
1.1.1.3 ! root      909:            tbl_b++;
1.1       root      910: 
1.1.1.3 ! root      911:            tbl_c = tbl_b->tbl_address;
1.1       root      912: 
1.1.1.3 ! root      913:          }
1.1       root      914: 
1.1.1.3 ! root      915:        tbl = tbl_c->tbl_address;
1.1       root      916: 
                    917:     }
                    918: 
                    919: 
                    920: 
1.1.1.2   root      921:     flush_pmmu();
1.1       root      922: 
1.1.1.2   root      923:     if (mcpu <= 30) {
1.1       root      924: 
1.1.1.2   root      925:     /* On the '020 & '030 we have a logical cache, i.e. the DC & IC are on
1.1       root      926: 
1.1.1.2   root      927:      * the CPU side of the MMU, hence on an MMU context switch we must flush
1.1       root      928: 
1.1.1.2   root      929:      * them too. On the '040, by comparison, we have a physical cache, i.e.
1.1       root      930: 
1.1.1.2   root      931:      * the DC & IC are on the memory side of the MMU, so no DC/IC cache flush
1.1       root      932: 
1.1.1.2   root      933:      * is needed.
1.1       root      934: 
1.1.1.2   root      935:      */
1.1       root      936: 
1.1.1.3 ! root      937:        cpush((void *)start, oldlen);
1.1       root      938: 
1.1.1.2   root      939:     }
1.1       root      940: 
                    941: }
                    942: 
                    943: 
                    944: 
                    945: /* get_prot_mode(r): returns the type of protection region r
                    946: 
                    947:  * has
                    948: 
                    949:  */
                    950: 
                    951: 
                    952: 
                    953: int
                    954: 
                    955: get_prot_mode(r)
                    956: 
                    957:        MEMREGION *r;
                    958: 
                    959: {
                    960: 
                    961:        ulong start = r->loc;
                    962: 
                    963: 
                    964: 
                    965:        if (no_mem_prot)
                    966: 
                    967:                return PROT_G;
                    968: 
                    969:        return global_mode_table[(start >> 13)];
                    970: 
                    971: }
                    972: 
                    973: 
                    974: 
                    975: void
                    976: 
                    977: mark_region(region,mode)
                    978: 
                    979: MEMREGION *region;
                    980: 
                    981: short mode;
                    982: 
                    983: {
                    984: 
                    985:     ulong start = region->loc;
                    986: 
                    987:     ulong len = region->len;
                    988: 
                    989:     ulong i;
                    990: 
                    991:     ushort dt_val, s_val, wp_val;
                    992: 
                    993:     PROC *proc;
                    994: 
                    995:     MEMREGION **mr;
                    996: 
                    997: 
                    998: 
                    999:     if (no_mem_prot) return;
                   1000: 
                   1001: 
                   1002: 
                   1003:     MP_DEBUG(("mark_region %lx len %lx mode %d",start,len,mode));
                   1004: 
                   1005:     
                   1006: 
1.1.1.3 ! root     1007: #if 0 /* this should not occur any more */
        !          1008: 
1.1       root     1009:     if (mode == PROT_NOCHANGE) {
                   1010: 
                   1011:        mode = global_mode_table[(start >> 13)];
                   1012: 
                   1013:     }
                   1014: 
1.1.1.3 ! root     1015: #else
        !          1016: 
        !          1017:     assert(mode != PROT_NOCHANGE);
        !          1018: 
        !          1019: #endif
        !          1020: 
1.1       root     1021: 
                   1022: 
                   1023:     /* mark the global page table */
                   1024: 
                   1025: 
                   1026: 
                   1027:     memset(&global_mode_table[start >> 13],mode,(len >> 13));
                   1028: 
                   1029: 
                   1030: 
                   1031:     for (proc = proclist; proc; proc = proc->gl_next) {
                   1032: 
                   1033:        assert(proc->page_table);
                   1034: 
                   1035:        if (mode == PROT_I || mode == PROT_G) {
                   1036: 
                   1037:            /* everybody gets the same flags */
                   1038: 
                   1039:            goto notowner;
                   1040: 
                   1041:        }
                   1042: 
                   1043:        if (proc->memflags & F_OS_SPECIAL) {
                   1044: 
                   1045:            /* you're special; you get owner flags */
                   1046: 
                   1047:            MP_DEBUG(("mark_region: pid %d is an OS special!",proc->pid));
                   1048: 
                   1049:            goto owner;
                   1050: 
                   1051:        }
                   1052: 
1.1.1.2   root     1053:        if ((mr = proc->mem) != 0) {
1.1       root     1054: 
                   1055:            for (i = 0; i < proc->num_reg; i++, mr++) {
                   1056: 
                   1057:                if (*mr == region) {
                   1058: 
                   1059:                    MP_DEBUG(("mark_region: pid %d is an owner",proc->pid));
                   1060: 
                   1061: owner:
                   1062: 
                   1063:                    dt_val = 1;
                   1064: 
                   1065:                    s_val = 0;
                   1066: 
                   1067:                    wp_val = 0;
                   1068: 
                   1069:                    goto gotvals;
                   1070: 
                   1071:                }
                   1072: 
                   1073:            }
                   1074: 
                   1075:        }
                   1076: 
                   1077: 
                   1078: 
                   1079: notowner:
                   1080: 
                   1081: 
                   1082: 
                   1083: /* if you get here you're not an owner, or mode is G or I */
                   1084: 
                   1085:        MP_DEBUG(("mark_region: pid %d gets non-owner modes",proc->pid));
                   1086: 
                   1087: 
                   1088: 
                   1089:        dt_val = other_dt[mode];
                   1090: 
                   1091:        s_val = other_s[mode];
                   1092: 
                   1093:        wp_val = other_wp[mode];
                   1094: 
                   1095: 
                   1096: 
                   1097: gotvals:
                   1098: 
                   1099:        mark_pages(proc->page_table,start,len,dt_val,s_val,wp_val,proc);
                   1100: 
                   1101:     }
                   1102: 
                   1103: }
                   1104: 
                   1105: 
                   1106: 
1.1.1.3 ! root     1107: /* special version of mark_region, used for attaching (mode == PROT_P)
        !          1108: 
        !          1109:    and detaching (mode == PROT_I) a memory region to/from a process. */
        !          1110: 
        !          1111: void
        !          1112: 
        !          1113: mark_proc_region(proc,region,mode)
        !          1114: 
        !          1115: PROC *proc;
        !          1116: 
        !          1117: MEMREGION *region;
        !          1118: 
        !          1119: short mode;
        !          1120: 
        !          1121: {
        !          1122: 
        !          1123:     ulong start = region->loc;
        !          1124: 
        !          1125:     ulong len = region->len;
        !          1126: 
        !          1127:     ushort dt_val, s_val, wp_val;
        !          1128: 
        !          1129:     short global_mode;
        !          1130: 
        !          1131: 
        !          1132: 
        !          1133:     if (no_mem_prot) return;
        !          1134: 
        !          1135: 
        !          1136: 
        !          1137:     MP_DEBUG(("mark_region %lx len %lx mode %d for pid %d",
        !          1138: 
        !          1139:              start, len, mode, proc->pid));
        !          1140: 
        !          1141: 
        !          1142: 
        !          1143:     global_mode = global_mode_table[(start >> 13)];
        !          1144: 
        !          1145: 
        !          1146: 
        !          1147:     assert(proc->page_table);
        !          1148: 
        !          1149:     if (global_mode == PROT_I || global_mode == PROT_G)
        !          1150: 
        !          1151:       mode = global_mode;
        !          1152: 
        !          1153:     else {
        !          1154: 
        !          1155:        if (proc->memflags & F_OS_SPECIAL) {
        !          1156: 
        !          1157:            /* you're special; you get owner flags */
        !          1158: 
        !          1159:            MP_DEBUG(("mark_region: pid %d is an OS special!",proc->pid));
        !          1160: 
        !          1161:            goto owner;
        !          1162: 
        !          1163:        }
        !          1164: 
        !          1165:        if (mode == PROT_P) {
        !          1166: 
        !          1167:            MP_DEBUG(("mark_region: pid %d is an owner",proc->pid));
        !          1168: 
        !          1169: owner:
        !          1170: 
        !          1171:            dt_val = 1;
        !          1172: 
        !          1173:            s_val = 0;
        !          1174: 
        !          1175:            wp_val = 0;
        !          1176: 
        !          1177:            goto gotvals;
        !          1178: 
        !          1179:        }
        !          1180: 
        !          1181:     }
        !          1182: 
        !          1183: 
        !          1184: 
        !          1185: /* if you get here you're not an owner, or mode is G or I */
        !          1186: 
        !          1187:     MP_DEBUG(("mark_region: pid %d gets non-owner modes",proc->pid));
        !          1188: 
        !          1189: 
        !          1190: 
        !          1191:     dt_val = other_dt[mode];
        !          1192: 
        !          1193:     s_val = other_s[mode];
        !          1194: 
        !          1195:     wp_val = other_wp[mode];
        !          1196: 
        !          1197: 
        !          1198: 
        !          1199: gotvals:
        !          1200: 
        !          1201:     mark_pages(proc->page_table,start,len,dt_val,s_val,wp_val,proc);
        !          1202: 
        !          1203: }
        !          1204: 
        !          1205: 
        !          1206: 
1.1       root     1207: /*
                   1208: 
                   1209:  * prot_temp: temporarily alter curproc's access to memory.
                   1210: 
                   1211:  * Pass in a -1 to give curproc global access; returns a cookie.  Call
                   1212: 
                   1213:  * again with that cookie to return the memory to the old mode.
                   1214: 
                   1215:  * There should be no context switches or memory protection changes
                   1216: 
                   1217:  * in the meantime.
                   1218: 
                   1219:  *
                   1220: 
                   1221:  * If called with mode == -1, returns...
                   1222: 
                   1223:  *     -1 if mem prot is off -- no error, no action.
                   1224: 
                   1225:  *      0 if the pages are not all the same.
                   1226: 
                   1227:  *      1 if the pages are not all controlled by the page tables.
                   1228: 
                   1229:  *
                   1230: 
                   1231:  * When mode != -1, returns...
                   1232: 
                   1233:  *     0 for success (should never fail).  There is little checking.
                   1234: 
                   1235:  * Calling with mode == 0 or 1 results in zero to spoof success, but in fact
                   1236: 
                   1237:  * this is an error.  Mode is only really valid if (mode & 0x8000).
                   1238: 
                   1239:  */
                   1240: 
                   1241: 
                   1242: 
                   1243: int
                   1244: 
                   1245: prot_temp(loc,len,mode)
                   1246: 
                   1247: ulong loc;
                   1248: 
                   1249: ulong len;
                   1250: 
                   1251: int mode;
                   1252: 
                   1253: {
                   1254: 
                   1255:     int cookie;
                   1256: 
                   1257: 
                   1258: 
                   1259:     if (no_mem_prot) return -1;
                   1260: 
                   1261: 
                   1262: 
                   1263:     /* round start down to the previous page and len up to the next one. */
                   1264: 
1.1.1.3 ! root     1265:     len += loc & MASKBITS;
        !          1266: 
1.1       root     1267:     loc &= ~MASKBITS;
                   1268: 
                   1269:     len = ROUND(len);
                   1270: 
                   1271: 
                   1272: 
                   1273:     if (mode == 0 || mode == 1) return 0;      /* do nothing */
                   1274: 
                   1275:     if (mode == -1) {
                   1276: 
                   1277:        cookie = get_page_cookie(curproc->page_table,loc,len);
                   1278: 
                   1279: 
                   1280: 
                   1281:        /* if not all controlled, return status */
                   1282: 
                   1283:        if (cookie == 0 || cookie == 1) return cookie;
                   1284: 
                   1285: 
                   1286: 
                   1287:        mark_pages(curproc->page_table,loc,len,1,0,0,curproc);
                   1288: 
                   1289: 
                   1290: 
                   1291:        return cookie;
                   1292: 
                   1293:     }
                   1294: 
                   1295:     else {
                   1296: 
                   1297:        mark_pages(curproc->page_table,loc,len,
                   1298: 
1.1.1.2   root     1299:                    mode&3,(mode&4)>>2,(mode&8)>>3,curproc);
1.1       root     1300: 
                   1301:        return 0;
                   1302: 
                   1303:     }
                   1304: 
                   1305: }
                   1306: 
                   1307: 
                   1308: 
                   1309: /*
                   1310: 
                   1311:  * init_page_table: fill in the page table for the indicated process. The
                   1312: 
                   1313:  * master page map is consulted for the modes of all pages, and the memory
                   1314: 
                   1315:  * region data structures are consulted to see if this process is the owner
                   1316: 
                   1317:  * of any of those tables.
                   1318: 
                   1319:  *
                   1320: 
                   1321:  * This also sets crp and tc in both ctxts of the process.  If this is the
                   1322: 
                   1323:  * first call, then the CPU tc is cleared, the TT0 and TT1 regs are zapped,
                   1324: 
                   1325:  * and then this proc's crp and tc are loaded into it.
                   1326: 
                   1327:  */
                   1328: 
                   1329: 
                   1330: 
                   1331: static short mmu_is_set_up = 0;
                   1332: 
                   1333: 
                   1334: 
                   1335: void
                   1336: 
                   1337: init_page_table(proc)
                   1338: 
                   1339: PROC *proc;
                   1340: 
                   1341: {
                   1342: 
                   1343:     long_desc *tptr;
                   1344: 
                   1345:     long_desc *tbl_a;          /* top-level table */
                   1346: 
                   1347:     long_desc *tbl_b0;         /* second level, handles $0 nybble */
                   1348: 
                   1349:     long_desc *tbl_bf;         /* handles $F nybble */
                   1350: 
                   1351:     long_desc *tbl_c;          /* temp pointer to start of 16MB */
                   1352: 
                   1353:     ulong p, q, r;
                   1354: 
                   1355:     ulong i, j, k;
                   1356: 
                   1357:     int g;
                   1358: 
                   1359:     MEMREGION **mr;
                   1360: 
                   1361: 
                   1362: 
                   1363:     if (no_mem_prot) return;
                   1364: 
                   1365: 
                   1366: 
1.1.1.3 ! root     1367:     assert(proc && proc->page_table);
1.1       root     1368: 
                   1369: 
                   1370: 
1.1.1.3 ! root     1371:     if (proc->pid)
1.1       root     1372: 
1.1.1.3 ! root     1373:         TRACELOW(("init_page_table(proc=%lx, pid %d)",proc,proc->pid));
1.1       root     1374: 
                   1375: 
                   1376: 
                   1377:     tptr = proc->page_table;
                   1378: 
                   1379:     tbl_a = tptr;
                   1380: 
                   1381:     tptr += TBL_SIZE;
                   1382: 
                   1383:     tbl_b0 = tptr;
                   1384: 
                   1385:     tptr += TBL_SIZE;
                   1386: 
                   1387:     tbl_bf = tptr;
                   1388: 
                   1389:     tptr += TBL_SIZE;
                   1390: 
                   1391: 
                   1392: 
                   1393:     /*
                   1394: 
                   1395:      * table A indexes by the first nybble: $0 and $F refer to their tables,
                   1396: 
                   1397:      * $1-$7 are uncontrolled, cacheable; $8-$E are uncontrolled, ci.
                   1398: 
                   1399:      */
                   1400: 
                   1401: 
                   1402: 
                   1403:     tbl_a[0].page_type = page_ptr;
                   1404: 
                   1405:     tbl_a[0].tbl_address = tbl_b0;
                   1406: 
                   1407: 
                   1408: 
                   1409:     for (i=1; i<0xf; i++) {
                   1410: 
                   1411:        if (i < 8)  tbl_a[i].page_type = g_page;
                   1412: 
                   1413:        else        tbl_a[i].page_type = g_ci_page;
                   1414: 
                   1415:        tbl_a[i].tbl_address = (long_desc *)(i << 28);
                   1416: 
                   1417:     }
                   1418: 
                   1419: 
                   1420: 
                   1421:     /* $F entry of table A refers to table BF */
                   1422: 
                   1423:     tbl_a[0xf].page_type = page_ptr;
                   1424: 
                   1425:     tbl_a[0xf].tbl_address = tbl_bf;
                   1426: 
                   1427: 
                   1428: 
                   1429:     /*
                   1430: 
                   1431:      * table B0: entry 0 is $00, the 16MB of ST address space.
                   1432: 
                   1433:      */
                   1434: 
                   1435: 
                   1436: 
                   1437:     tbl_b0[0].page_type = page_ptr;
                   1438: 
                   1439:     tbl_b0[0].tbl_address = tptr;
                   1440: 
                   1441:     tbl_c = tptr;
                   1442: 
                   1443:     tptr += TBL_SIZE;
                   1444: 
                   1445: 
                   1446: 
                   1447:     /* for each megabyte that is RAM, allocate a table */
                   1448: 
                   1449:     for (i = 0, k = 0, p = 0; p < mint_top_st; i++, p += 0x00100000L) {
                   1450: 
                   1451:        tbl_c[i].page_type = page_ptr;
                   1452: 
                   1453:        tbl_c[i].tbl_address = tptr;
                   1454: 
                   1455: 
                   1456: 
                   1457:        /* for each page in this megabyte, write a page entry */
                   1458: 
                   1459:        for (q = p, j = 0; j < 128; j++, q += 0x2000, k++) {
                   1460: 
                   1461:            tptr->page_type = *proto_page_type[global_mode_table[k]];
                   1462: 
                   1463:            tptr->tbl_address = (long_desc *)q;
                   1464: 
                   1465:            tptr++;
                   1466: 
                   1467:        }
                   1468: 
                   1469:     }
                   1470: 
                   1471: 
                   1472: 
                   1473:     /* now for each megabyte from mint_top_st to ROM, mark global */
                   1474: 
                   1475:     for ( ; p < 0x00E00000L; i++, p += 0x00100000L) {
                   1476: 
                   1477:        tbl_c[i].page_type = g_page;
                   1478: 
                   1479:        tbl_c[i].tbl_address = (long_desc *)p;
                   1480: 
                   1481:     }
                   1482: 
                   1483: 
                   1484: 
                   1485:     /* fill in the E and F tables: 00Ex is ROM, 00Fx is I/O  */
                   1486: 
                   1487:     tbl_c[i].page_type = g_page;
                   1488: 
                   1489:     tbl_c[i].tbl_address = (long_desc *)p;
                   1490: 
                   1491:     i++, p += 0x00100000L;
                   1492: 
                   1493:     tbl_c[i].page_type = g_ci_page;
                   1494: 
                   1495:     tbl_c[i].tbl_address = (long_desc *)p;
                   1496: 
                   1497: 
                   1498: 
                   1499:         /* Done with tbl_c for 0th 16MB; go on to TT RAM */
                   1500: 
                   1501: 
                   1502: 
                   1503: /* 
                   1504: 
                   1505:     structure:
                   1506: 
                   1507: 
                   1508: 
                   1509:     for (i = each 16MB that has any TT RAM in it)
                   1510: 
                   1511:        allocate a table tbl_c, point tbl_b0[i] at it
                   1512: 
                   1513:        for (j = each 1MB that is RAM)
                   1514: 
                   1515:            allocate a table, point tbl_c[j] at it
                   1516: 
                   1517:            for (k = each page in the megabyte)
                   1518: 
                   1519:                fill in tbl_c[j][k] with page entry from global_mode_table
                   1520: 
                   1521:        for (j = the rest of the 16MB)
                   1522: 
                   1523:            set tbl_c[j] to "global, cacheable"
                   1524: 
                   1525: 
                   1526: 
                   1527:     for (i = the rest of the 16MBs from here to $7F)
                   1528: 
                   1529:        set tbl_b0[i] to "global, cacheable"
                   1530: 
                   1531: 
                   1532: 
                   1533:     for (i = the rest of the 16MBs from $80 up to but not incl. $FF)
                   1534: 
                   1535:        set tbl_b0[i] to "global, not cacheable"
                   1536: 
                   1537: */
                   1538: 
                   1539: 
                   1540: 
                   1541:     /* i counts 16MBs */
                   1542: 
                   1543:     for (i = 1, p = 0x01000000L, g = 2048;
                   1544: 
                   1545:         p < mint_top_tt;
                   1546: 
                   1547:         p += SIXTEEN_MEG, i++) {
                   1548: 
                   1549:            tbl_b0[i].page_type = page_ptr;
                   1550: 
                   1551:            tbl_b0[i].tbl_address = tptr;
                   1552: 
                   1553:            tbl_c = tptr;
                   1554: 
                   1555:            tptr += TBL_SIZE;
                   1556: 
                   1557: 
                   1558: 
                   1559:            /* j counts MBs */
                   1560: 
                   1561:            for (j = 0, q = p; j < 16 && q < mint_top_tt; q += ONE_MEG, j++) {
                   1562: 
                   1563:                tbl_c[j].page_type = page_ptr;
                   1564: 
                   1565:                tbl_c[j].tbl_address = tptr;
                   1566: 
                   1567:                /* k counts pages (8K) */
                   1568: 
                   1569:                for (r = q, k = 0; k < 128; k++, r += 0x2000, g++) {
                   1570: 
                   1571:                    tptr->page_type = *proto_page_type[global_mode_table[g]];
                   1572: 
                   1573:                    tptr->tbl_address = (long_desc *)r;
                   1574: 
                   1575:                    tptr++;
                   1576: 
                   1577:                }
                   1578: 
                   1579:            }
                   1580: 
                   1581:            for ( ; j < 16; j++, q += ONE_MEG) {
                   1582: 
                   1583:                /* fill in the rest of this 16MB */
                   1584: 
                   1585:                tbl_c[j].page_type = g_page;
                   1586: 
                   1587:                tbl_c[j].tbl_address = (long_desc *)q;
                   1588: 
                   1589:            }
                   1590: 
                   1591:     }
                   1592: 
                   1593: 
                   1594: 
                   1595:     /* fill in the rest of $00-$0F as cacheable */
                   1596: 
                   1597:     for ( ; i < 16; i++, p += SIXTEEN_MEG) {
                   1598: 
                   1599:        tbl_b0[i].page_type = g_page;
                   1600: 
                   1601:        tbl_b0[i].tbl_address = (long_desc *)p;
                   1602: 
                   1603:     }
                   1604: 
                   1605: 
                   1606: 
                   1607:     /* done with TT RAM in table b0; do table bf */
                   1608: 
                   1609: 
                   1610: 
                   1611:     /*
                   1612: 
                   1613:      * Table BF: translates addresses starting with $F.  First 15 are
                   1614: 
                   1615:      * uncontrolled, cacheable; last one translates $FF, which
                   1616: 
                   1617:      * which shadows $00 (the 16MB ST address space).  The rest
                   1618: 
                   1619:      * are uncontrolled, not cacheable.
                   1620: 
                   1621:      *
                   1622: 
                   1623:      * The table address of the copy has a 1 in the low (unused) bit, which
                   1624: 
                   1625:      * is a signal to the table dumper not to dump this, as it's a copy
                   1626: 
                   1627:      * of tbl_b0[0].
                   1628: 
                   1629:      */
                   1630: 
                   1631: 
                   1632: 
                   1633:     for (i=0; i<0xf; i++) {
                   1634: 
                   1635:        tbl_bf[i].page_type = g_ci_page;
                   1636: 
                   1637:        tbl_bf[i].tbl_address = (long_desc *)((i << 24) | 0xf0000000L);
                   1638: 
                   1639:     }
                   1640: 
                   1641:     tbl_bf[0xf] = tbl_b0[0];
                   1642: 
                   1643:     *(ulong *)(&(tbl_bf[0xf].tbl_address)) |= 1;
                   1644: 
                   1645: 
                   1646: 
                   1647:     proc->ctxt[0].crp.limit = 0x7fff;  /* disable limit function */
                   1648: 
                   1649:     proc->ctxt[0].crp.dt = 3;          /* points to valid 8-byte entries */
                   1650: 
                   1651:     proc->ctxt[0].crp.tbl_address = tbl_a;
                   1652: 
                   1653:     proc->ctxt[1].crp = proc->ctxt[0].crp;
                   1654: 
                   1655:     proc->ctxt[0].tc = tc;
                   1656: 
                   1657:     proc->ctxt[1].tc = tc;
                   1658: 
                   1659: 
                   1660: 
                   1661:     /*
                   1662: 
                   1663:      * OK, memory tables are now there as if you're a non-owner of every
                   1664: 
                   1665:      * page.  Now for each region you ARE an owner of, mark with owner
                   1666: 
                   1667:      * modes.
                   1668: 
                   1669:      */
                   1670: 
                   1671: 
                   1672: 
                   1673:     mr = proc->mem;
                   1674: 
                   1675:     for (i=0; i < proc->num_reg; i++, mr++) {
                   1676: 
                   1677:        if (*mr) {
                   1678: 
                   1679:            mark_pages(proc->page_table,(*mr)->loc,(*mr)->len,1,0,0,proc);
                   1680: 
                   1681:        }
                   1682: 
                   1683:     }
                   1684: 
                   1685: 
                   1686: 
                   1687:     if (!mmu_is_set_up) {
                   1688: 
                   1689:        set_mmu(proc->ctxt[0].crp,proc->ctxt[0].tc);
                   1690: 
                   1691:        mmu_is_set_up = 1;
                   1692: 
                   1693:     }
                   1694: 
                   1695: }
                   1696: 
                   1697: 
                   1698: 
                   1699: /*
                   1700: 
                   1701:  * This routine is called when procfs detects that a process wants to be an
                   1702: 
                   1703:  * OS SPECIAL.  The AES, SCRENMGR, and DESKTOP do this, and so does FSMGDOS
                   1704: 
                   1705:  * and possibly some other stuff. It has to re-mark every page in that
                   1706: 
                   1707:  * process' page table based on its new special status. The "special
                   1708: 
                   1709:  * status" is "you get global access to all of memory" and "everybody
                   1710: 
                   1711:  * gets Super access to yours."  It is the caller's responsibility
                   1712: 
                   1713:  * to set proc's memflags, usually to (F_OS_SPECIAL | F_PROT_S).
                   1714: 
                   1715:  */
                   1716: 
                   1717: 
                   1718: 
                   1719: void
                   1720: 
                   1721: mem_prot_special(proc)
                   1722: 
                   1723: PROC *proc;
                   1724: 
                   1725: {
                   1726: 
                   1727:     MEMREGION **mr;
                   1728: 
                   1729:     int i;
                   1730: 
                   1731: 
                   1732: 
                   1733:     if (no_mem_prot) return;
                   1734: 
                   1735: 
                   1736: 
                   1737:     TRACE(("mem_prot_special(pid %d)",proc->pid));
                   1738: 
                   1739: 
                   1740: 
                   1741:     /*
                   1742: 
                   1743:      * This marks ALL memory, allocated or not, as accessible. When memory
                   1744: 
                   1745:      * is freed even F_OS_SPECIAL processes lose access to it. So one or
                   1746: 
                   1747:      * the other of these is a bug, depending on how you want it to work.
                   1748: 
                   1749:      */
                   1750: 
                   1751:     mark_pages(proc->page_table,0,mint_top_st,1,0,0,proc);
                   1752: 
                   1753:     if (mint_top_tt) {
                   1754: 
                   1755:        mark_pages(proc->page_table,
                   1756: 
                   1757:                    0x01000000L,
                   1758: 
                   1759:                    mint_top_tt - 0x01000000L,
                   1760: 
                   1761:                    1,0,0,
                   1762: 
                   1763:                    proc);
                   1764: 
                   1765:     }
                   1766: 
                   1767: 
                   1768: 
                   1769:     /*
                   1770: 
                   1771:      * In addition, mark all the pages the process already owns as "super"
                   1772: 
                   1773:      * in all other processes.  Thus the "special" process can access all
                   1774: 
                   1775:      * of memory, and any process can access the "special" process' memory
                   1776: 
                   1777:      * when in super mode.
                   1778: 
                   1779:      */
                   1780: 
                   1781: 
                   1782: 
                   1783:     mr = proc->mem;
                   1784: 
                   1785: 
                   1786: 
                   1787:     for (i=0; i < proc->num_reg; i++, mr++) {
                   1788: 
                   1789:        if (*mr) {
                   1790: 
                   1791:            mark_region(*mr,PROT_S);
                   1792: 
                   1793:        }
                   1794: 
                   1795:     }
                   1796: 
                   1797: }
                   1798: 
                   1799:     
                   1800: 
                   1801: /*----------------------------------------------------------------------------
                   1802: 
                   1803:  * DEBUGGING SECTION
                   1804: 
                   1805:  *--------------------------------------------------------------------------*/
                   1806: 
                   1807: 
                   1808: 
                   1809: static void
                   1810: 
                   1811: _dump_tree(tbl,level)
                   1812: 
                   1813: long_desc tbl;
                   1814: 
                   1815: int level;
                   1816: 
                   1817: {
                   1818: 
                   1819:     int i, j;
                   1820: 
                   1821:     long_desc *p;
                   1822: 
1.1.1.2   root     1823:     static const char spaces[9] = "        ";
1.1       root     1824: 
                   1825: 
                   1826: 
                   1827:     /* print the level and display the table descriptor */
                   1828: 
                   1829:     FORCE("\r%s s:%x wp:%x dt:%x a:%08lx",
                   1830: 
                   1831:        &spaces[8-(level*2)],
                   1832: 
                   1833:        tbl.page_type.s,
                   1834: 
                   1835:        tbl.page_type.wp,
                   1836: 
                   1837:        tbl.page_type.dt,
                   1838: 
                   1839:        tbl.tbl_address);
                   1840: 
                   1841: 
                   1842: 
                   1843:     if (tbl.page_type.dt == 3) {
                   1844: 
                   1845:        if (level == 0) {
                   1846: 
                   1847:            j = (1 << tc.tia);
                   1848: 
                   1849:        }
                   1850: 
                   1851:        else if (level == 1) {
                   1852: 
                   1853:            j = (1 << tc.tib);
                   1854: 
                   1855:        }
                   1856: 
                   1857:        else if (level == 2) {
                   1858: 
                   1859:            j = (1 << tc.tic);
                   1860: 
                   1861:        }
                   1862: 
                   1863:        else {
                   1864: 
                   1865:            j = (1 << tc.tid);
                   1866: 
                   1867:        }
                   1868: 
                   1869: 
                   1870: 
                   1871:        /* don't show table if it's the duplicate */
                   1872: 
                   1873:        if ((ulong)tbl.tbl_address & 1) return;
                   1874: 
                   1875: 
                   1876: 
                   1877:        ++level;
                   1878: 
                   1879:        p = tbl.tbl_address;
                   1880: 
                   1881:        for (i=0; i<j; i++, p++) {
                   1882: 
                   1883:            _dump_tree(*p,level);
                   1884: 
                   1885:        }
                   1886: 
                   1887:     }
                   1888: 
                   1889: }
                   1890: 
                   1891: 
                   1892: 
1.1.1.2   root     1893: static const char modesym[] = { 'p', 'g', 's', 'r', 'i' };
1.1       root     1894: 
                   1895: 
                   1896: 
                   1897: void
                   1898: 
                   1899: QUICKDUMP()
                   1900: 
                   1901: {
                   1902: 
                   1903:     char outstr[33];
                   1904: 
                   1905:     ulong i, j, end;
                   1906: 
                   1907: 
                   1908: 
                   1909:     if (no_mem_prot) return;
                   1910: 
                   1911: 
                   1912: 
                   1913:     FORCE("STRAM global table:");
                   1914: 
                   1915:     outstr[32] = '\0';
                   1916: 
                   1917:     end = mint_top_st / QUANTUM;
                   1918: 
                   1919:     for (i = 0; i < end; i += 32) {
                   1920: 
                   1921:        for (j=0; j<32; j++) {
                   1922: 
                   1923:            outstr[j] = modesym[global_mode_table[j+i]];
                   1924: 
                   1925:        }
                   1926: 
                   1927:        FORCE("%08lx: %s",i*8192L,outstr);
                   1928: 
                   1929:     }
                   1930: 
                   1931: 
                   1932: 
                   1933:     if (mint_top_tt) {
                   1934: 
                   1935:        FORCE("TTRAM global table:");
                   1936: 
                   1937:        end = mint_top_tt / QUANTUM;
                   1938: 
                   1939:        for (i = 2048; i < end; i += 32) {
                   1940: 
                   1941:            for (j=0; j<32; j++) {
                   1942: 
                   1943:                outstr[j] = modesym[global_mode_table[j+i]];
                   1944: 
                   1945:            }
                   1946: 
                   1947:            FORCE("%08lx: %s",i*8192L,outstr);
                   1948: 
                   1949:        }
                   1950: 
                   1951:     }
                   1952: 
                   1953: }
                   1954: 
                   1955: 
                   1956: 
                   1957: const char *berr_msg[] = { 
                   1958: 
                   1959: /*  "........." */
                   1960: 
                   1961:     "private  ",
                   1962: 
                   1963:     "global   ",    /* turned into "hardware" for violation reports */
                   1964: 
                   1965:     "super    ",
                   1966: 
                   1967:     "readable ",
                   1968: 
                   1969:     "free     ",
                   1970: 
                   1971:     "hardware "            /* used when the memory is not controlled by us */
                   1972: 
                   1973: };
                   1974: 
                   1975: 
                   1976: 
                   1977: void
                   1978: 
                   1979: report_buserr()
                   1980: 
                   1981: {
                   1982: 
1.1.1.2   root     1983:     const char *vmsg;
1.1       root     1984: 
                   1985:     short mode;
                   1986: 
                   1987:     ulong aa, pc;
                   1988: 
                   1989:     char alertbuf[5*32+16];    /* enough for an alert */
                   1990: 
                   1991:     char *aptr;
                   1992: 
                   1993: 
                   1994: 
                   1995:     if (no_mem_prot) return;
                   1996: 
                   1997: 
                   1998: 
                   1999:     aa = curproc->exception_addr;
                   2000: 
                   2001:     pc = curproc->exception_pc;
                   2002: 
                   2003:     if ((mint_top_tt && aa < mint_top_tt) || (aa < mint_top_st)) {
                   2004: 
                   2005:        mode = global_mode_table[(curproc->exception_addr >> 13)];
                   2006: 
                   2007:        if (mode == PROT_G) {
                   2008: 
                   2009:            /* page is global: obviously a hardware bus error */
                   2010: 
                   2011:            mode = 5;
                   2012: 
                   2013:        }
                   2014: 
                   2015:     }
                   2016: 
                   2017:     else {
                   2018: 
                   2019:        /* (addr is > mint_top_tt) set mode = 5 so we don't look for owners */
                   2020: 
                   2021:        mode = 5;
                   2022: 
                   2023:     }
                   2024: 
                   2025:     vmsg = berr_msg[mode];
                   2026: 
                   2027: 
                   2028: 
                   2029:     /* construct an AES alert box for this error:
                   2030: 
                   2031:        | PROCESS  "buserrxx"  KILLED: |
                   2032: 
                   2033:        | MEMORY VIOLATION.  (PID 000) |
                   2034: 
                   2035:        |                              |
                   2036: 
                   2037:        | Type: ......... PC: pc...... |
                   2038: 
                   2039:        | Addr: ........  BP: ........ |
                   2040: 
                   2041:     */
                   2042: 
                   2043: 
                   2044: 
                   2045:     /* we play games to get around 128-char max for ksprintf */
                   2046: 
                   2047:     ksprintf(alertbuf,"[1][ PROCESS  \"%s\"  KILLED: |",curproc->name);
                   2048: 
                   2049:     aptr = alertbuf + strlen(alertbuf);
                   2050: 
                   2051:     ksprintf(aptr," MEMORY VIOLATION.  (PID %03d) | |",curproc->pid);
                   2052: 
                   2053:     aptr = alertbuf + strlen(alertbuf);
                   2054: 
                   2055:     ksprintf(aptr," Type: %s PC: %08lx |",vmsg,pc);
                   2056: 
                   2057:     aptr = alertbuf + strlen(alertbuf);
                   2058: 
                   2059:     ksprintf(aptr," Addr: %08lx  BP: %08lx ][ OK ]",aa,curproc->base);
                   2060: 
                   2061:     if (!_ALERT(alertbuf)) {
                   2062: 
                   2063:        /* this will call _alert again, but it will just fail again */
                   2064: 
                   2065:        ALERT("MEMORY VIOLATION: type=%s AA=%lx PC=%lx BP=%lx",
                   2066: 
                   2067:                vmsg,aa,pc,curproc->base);
                   2068: 
                   2069:     }
                   2070: 
                   2071:        
                   2072: 
                   2073:     if (curproc->pid == 0 || curproc->memflags & F_OS_SPECIAL) {
                   2074: 
                   2075:     /* the system is so thoroughly hosed that anything we try will
                   2076: 
                   2077:      * likely cause another bus error; so let's just hang up
                   2078: 
                   2079:      */
                   2080: 
                   2081:        FATAL("Operating system killed");
                   2082: 
                   2083:     }
                   2084: 
                   2085: }
                   2086: 
                   2087: 
                   2088: 
                   2089: /*
                   2090: 
                   2091:  * big_mem_dump is a biggie: for each page in the system, it
                   2092: 
                   2093:  * displays the PID of the (first) owner and the protection mode.
                   2094: 
                   2095:  * The output has three chars per page, and eight chars per line.
                   2096: 
                   2097:  * The first page of a region is marked with the mode, and the
                   2098: 
                   2099:  * rest with a space.
                   2100: 
                   2101:  *
                   2102: 
                   2103:  * Logic:
                   2104: 
                   2105:     for (mp = *core; mp; mp++) {
                   2106: 
                   2107:        for (each page of this region) {
                   2108: 
                   2109:            if (start of line) {
                   2110: 
                   2111:                output line starter;
                   2112: 
                   2113:            }
                   2114: 
                   2115:            if (start of region) {
                   2116: 
                   2117:                output mode of this page;
                   2118: 
                   2119:                determine owner;
                   2120: 
                   2121:                output owner;
                   2122: 
                   2123:            }
                   2124: 
                   2125:            else {
                   2126: 
                   2127:                output space;
                   2128: 
                   2129:                output owner;
                   2130: 
                   2131:            }
                   2132: 
                   2133:         }
                   2134: 
                   2135:     }
                   2136: 
                   2137:  */
                   2138: 
                   2139: 
                   2140: 
                   2141: void
                   2142: 
                   2143: BIG_MEM_DUMP(bigone,proc)
                   2144: 
                   2145: int bigone;
                   2146: 
                   2147: PROC *proc;
                   2148: 
                   2149: {
                   2150: 
1.1.1.2   root     2151: #ifdef DEBUG_INFO
1.1       root     2152: 
                   2153:     char linebuf[128];
                   2154: 
                   2155:     char *lp = linebuf;
                   2156: 
                   2157:     MEMREGION *mp, **mr, **map;
                   2158: 
                   2159:     PROC *p;
                   2160: 
                   2161:     ulong loc;
                   2162: 
1.1.1.2   root     2163:     short owner;
1.1       root     2164: 
                   2165:     short i;
                   2166: 
                   2167:     short first;
                   2168: 
                   2169: 
                   2170: 
                   2171: 
                   2172: 
                   2173:   if (no_mem_prot) return;
                   2174: 
                   2175: 
                   2176: 
                   2177:   for (map = core; map != 0; ((map == core) ? (map = alt) : (map = 0))) {
                   2178: 
                   2179:     FORCE("Annotated memory dump for %s",(map == core ? "core" : "alt"));
                   2180: 
                   2181:     first = 1;
                   2182: 
                   2183:     *linebuf = '\0';
                   2184: 
                   2185:     for (mp = *map; mp; mp = mp->next) {
                   2186: 
                   2187:        for (loc = mp->loc; loc < (mp->loc + mp->len); loc += EIGHT_K) {
                   2188: 
                   2189:            if (first || ((loc & 0x1ffff) == 0)) {
                   2190: 
                   2191:                if (*linebuf) FORCE(linebuf);
                   2192: 
                   2193:                ksprintf(linebuf,"\r%08lx: ",loc);
                   2194: 
                   2195:                lp = &linebuf[11];
                   2196: 
                   2197:                first = 0;
                   2198: 
                   2199:            }
                   2200: 
                   2201:            if (loc == mp->loc) {
                   2202: 
                   2203:                *lp++ = modesym[global_mode_table[loc / EIGHT_K]];
                   2204: 
                   2205: 
                   2206: 
                   2207:                for (p = proclist; p; p = p->gl_next) {
                   2208: 
                   2209:                    if (p->mem) {
                   2210: 
                   2211:                        mr = p->mem;
                   2212: 
                   2213:                        for (i=0; i < p->num_reg; i++, mr++) {
                   2214: 
                   2215:                            if (*mr == mp) {
                   2216: 
                   2217:                                owner = p->pid;
                   2218: 
                   2219:                                goto gotowner;
                   2220: 
                   2221:                            }
                   2222: 
                   2223:                        }
                   2224: 
                   2225:                    }
                   2226: 
                   2227:                }
                   2228: 
                   2229:                owner = 000;
                   2230: 
                   2231: gotowner:
                   2232: 
                   2233:                ksprintf(lp,"%03d",owner);
                   2234: 
                   2235:                lp += 3;
                   2236: 
                   2237:            }
                   2238: 
                   2239:            else {
                   2240: 
                   2241:                *lp++ = ' ';
                   2242: 
                   2243:                *lp++ = '-';
                   2244: 
                   2245:                *lp++ = '-';
                   2246: 
                   2247:                *lp++ = '-';
                   2248: 
                   2249:                *lp = '\0';     /* string is always null-terminated */
                   2250: 
                   2251:            }
                   2252: 
                   2253:         }
                   2254: 
                   2255:     }
                   2256: 
                   2257:     FORCE(linebuf);
                   2258: 
                   2259:   }
                   2260: 
                   2261: 
                   2262: 
                   2263:     if (bigone) {
                   2264: 
                   2265:        long_desc tbl;
                   2266: 
                   2267: 
                   2268: 
                   2269:        /* fill in tbl with the only parts used at the top level */
                   2270: 
                   2271:        tbl.page_type.dt = proc->ctxt[CURRENT].crp.dt;
                   2272: 
                   2273:        tbl.tbl_address = proc->ctxt[CURRENT].crp.tbl_address;
                   2274: 
                   2275:        _dump_tree(tbl,0);
                   2276: 
                   2277:     }
                   2278: 
1.1.1.2   root     2279: #endif /* DEBUG_INFO */
1.1       root     2280: 
                   2281: }
                   2282: 
                   2283: 
                   2284: 
                   2285: 
                   2286: 
                   2287: /*
                   2288: 
                   2289:  * Can the process "p" access the "nbytes" long
                   2290: 
                   2291:  * block of memory starting at "start"?
                   2292: 
                   2293:  * If it would be a legal access, the current
                   2294: 
                   2295:  * process is given temporary access via
                   2296: 
                   2297:  * prot_temp.
                   2298: 
                   2299:  * Returns a cookie like the one prot_temp
                   2300: 
                   2301:  * returns; if the process shouldn't have
                   2302: 
                   2303:  * access to the memory, returns 1.
                   2304: 
                   2305:  *
                   2306: 
                   2307:  * BUG: should actually read p's page table to
                   2308: 
                   2309:  * determine access
                   2310: 
                   2311:  */
                   2312: 
                   2313: 
                   2314: 
                   2315: int
                   2316: 
                   2317: mem_access_for(p, start, nbytes)
                   2318: 
                   2319:        PROC *p;
                   2320: 
                   2321:        ulong start;
                   2322: 
                   2323:        long nbytes;
                   2324: 
                   2325: {
                   2326: 
                   2327:        MEMREGION **mr;
                   2328: 
                   2329:        int i;
                   2330: 
                   2331: 
                   2332: 
                   2333:        if (no_mem_prot) return -1;
                   2334: 
                   2335:        if (start >= (ulong)p && start+nbytes <= (ulong)(p+1))
                   2336: 
                   2337:                return -1;
                   2338: 
                   2339:        if (p == rootproc)
                   2340: 
                   2341:                goto win_and_mark;
                   2342: 
                   2343: 
                   2344: 
                   2345:        mr = p->mem;
                   2346: 
                   2347:        if (mr) {
                   2348: 
                   2349:            for (i = 0; i < p->num_reg; i++, mr++) {
                   2350: 
                   2351:                if (*mr) {
                   2352: 
                   2353:                    if (((*mr)->loc <= start) &&
                   2354: 
                   2355:                        ((*mr)->loc + (*mr)->len >= start + nbytes))
                   2356: 
                   2357:                            goto win_and_mark;
                   2358: 
                   2359:                }
                   2360: 
                   2361:            }
                   2362: 
                   2363:        }
                   2364: 
                   2365: 
                   2366: 
                   2367:        return 0;       /* we don't own this memory */
                   2368: 
                   2369: 
                   2370: 
                   2371: win_and_mark:
                   2372: 
                   2373:        return prot_temp(start, nbytes, -1);
                   2374: 
                   2375: }
                   2376: 

unix.superglobalmegacorp.com

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