Annotation of coherent/b/kernel/i386/mmu.doc, revision 1.1.1.1

1.1       root        1: #undef ptable1_v
                      2: #undef ptable0_v
                      3: 
                      4: /* Put the page directory at the click before the start of kernel text.  */
                      5: #define        ptable0_v       ((long *)(&stext[ctob(-1)]))
                      6: 
                      7: /*
                      8:  * mchinit()
                      9:  * Initializes buddy system for (physical?) memory allocation.
                     10:  *     (See Knuth's Art of Computer Programming, Vol I.)
                     11:  * Initializes tables for the memory management unit (mmu).
                     12:  *     (See Intel i386 CPU documentation.)
                     13:  *
                     14:  */
                     15: 
                     16: 
                     17: 
                     18: mchinit()
                     19: {
                     20:        /* Symbols generated by linker.  */
                     21:        extern char     end[],   /* End of kernel bss (uninitialized data).  */
                     22:                        edata[], /* End of kernel initialized data.  */
                     23:                        etext[]; /* End of kernel text segment.  */
                     24: 
                     25:        /* Symbols from as.s.  */
                     26:        extern char     stext[],  /* Start of kernel text segment.  */
                     27:                        sdata[];  /* Start of kernel initialized data segment.  */
                     28: 
                     29:        register char *pe;      /* Working pointer meant for abuse.  */
                     30:        register zero = 0;      /* */
                     31:        register        i;      /* Miscellaneous counter.  */
                     32:        register long *lp;      /* Unused */
                     33: 
                     34:        register long *ptable1_v;       /* Abused slave page table pointer.  */
                     35: 
                     36:        register n,     /* Unused?  */
                     37:                 syse,  /* Unused.  */
                     38: /* Click addr */ base; /* Counter for freeing memory (low and extended).  */
                     39: 
                     40:        int     uaddr;  /* Unused.  */
                     41: 
                     42:        /* These point at the slave page tables for various segments.
                     43:         * They are in clicks.
                     44:         */
                     45:        int     sysseg,         /* System segment--the entire kernel.   */
                     46:                codeseg,        /* User code segment.                   */
                     47:                dataseg,        /* User data segment.                   */ 
                     48:                stackseg,       /* User stack segment.                  */
                     49:                ptable1;        /* Paging segment--most slave page tables
                     50:                                 * get mapped to this segment.
                     51:                                 */
                     52:                                 
                     53:        /* Low memory is 0-640K, extended is 1M and up.  */
                     54:        int     lo,     /* Number of bytes above kernel in low memory.  */
                     55:                hi,     /* Number of bytes in extended memory.  */
                     56:                nalloc, /* Number of allocatable clicks in all of memory.  */
                     57:                diff;   /* Buddy system overhead in clicks.  */
                     58: 
                     59:        extern char     digtab[]; /* Mystery kernel hangman.  :-) */
                     60: 
                     61:        static  SEG     uinit;  /* User area for /etc/init? */
                     62: 
                     63:        /*
                     64:         * 1.
                     65:         *   a. Relocate the data on a page boundary (4K bytes) the
                     66:         *      bootstrap relocates it on a paragraph boundary (16 bytes)
                     67:         *
                     68:         *   b. Verify that the data has been relocated correctly 
                     69:         */
                     70:        pe = edata;                                             /* 1.a */
                     71:        /* (((unsigned)etext+15) & ~15) is where the boot code put
                     72:         * the data segment.
                     73:         * (unsigned)sdata is where the linker wants it to be.
                     74:         * Thus "i" is the distance from where the data segment is, to
                     75:         * where the data segment should be.
                     76:         *
                     77:         * Note that i will be negative with this kernel.
                     78:         */
                     79:        i = (((unsigned)etext+15) & ~15) - (unsigned)sdata;
                     80: 
                     81:        /* Move a region to a (possibly overlapping) region above it.
                     82:         * SIC!
                     83:         */
                     84:        do {
                     85:                pe--;
                     86:                pe[0] = pe[i];
                     87:        } while (pe != sdata);                                  /* 1.a */
                     88: 
                     89:        /* The kernel will hang if digtab[] is not initialized such that
                     90:         * digtab[0] is the character '0'.  This is done by the
                     91:         * compiler.
                     92:         */
                     93:        while (digtab[0]!='0');         /* 1.b */
                     94: 
                     95:        /*
                     96:         * 2. Zero the bss
                     97:         *    Zero the level 0 page directory (Master page table)
                     98:         */ 
                     99:        pe = edata;
                    100:        do
                    101:                *pe++ = zero;
                    102:        while (pe != end);
                    103: 
                    104:        /* Note that ptable0_v is the click before the kernel text segment.  */
                    105:        pe = (char *) ptable0_v;
                    106:        do
                    107:                *pe++ = zero;
                    108:        while (pe != stext);
                    109: 
                    110:        /*
                    111:         * 3. Calculate total system memory in taking
                    112:         *    into account the space used by the system and the page
                    113:         *    descriptors, the interrupt stack, and the refresh work area
                    114:         *
                    115:         * a. initialize allocation area and adjust system size
                    116:         *      to take allocation area and free page area into account
                    117:         */
                    118:        /* SBASE is the click of the start of the kernel in virtual memory.
                    119:         * PBASE is the click of the start of the kernel in physical memory.
                    120:         *
                    121:         * SBASE is 0xFFC00, PBASE is 0x02
                    122:         *
                    123:         * Calculate the first click after the kernel in physical memory.
                    124:         * This is in low memory (below 640k).
                    125:         */
                    126:        sysmem.lo = (btoc((unsigned)end) - SBASE) + PBASE;
                    127: 
                    128:        /*
                    129:         * These calls to c_size() should be replaced by calls to a
                    130:         * routine that gets the memory size from the CMOS.
                    131:         */
                    132:        lo = c_size(sysmem.lo, btoc(640*1024));
                    133:        hi = c_size(btoc(1024*1024), btoc(4096*1024));
                    134: 
                    135:        /* This calculation is suspect.  It may be high by 1 click.
                    136:         * The problem is that a click split between extended and low
                    137:         * memory cannot be allocated as a single click.
                    138:         */
                    139:        nalloc = (lo+hi) / (sizeof(short) + SPLASH*sizeof(long) + ctob(1));
                    140:        areainit(SPLASH*nalloc*sizeof(long));
                    141:        sysmem.tfree = sysmem.pfree = 
                    142:                (unsigned short *)(end + SPLASH*nalloc*sizeof(long));
                    143: 
                    144:        sysmem.hi = btoc(hi+1024*1024);
                    145:        base = sysmem.lo + (lo>>BPCSHIFT);
                    146:        diff = ((lo + hi) >> BPCSHIFT) - nalloc;
                    147:        sysmem.lo += diff;      
                    148:        sysmem.vaddre = ctob(sysmem.lo+SBASE-PBASE);
                    149:                /* include in system area pages for arena, free area */
                    150:        /*
                    151:         * 4.
                    152:         *  Free the memory from [end, 640) kilobytes
                    153:         *  Free the memory from [1024, 16*1024) kilobytes
                    154:         */
                    155:        while (base > sysmem.lo)
                    156:                *sysmem.pfree++ = --base; /* push(--base) onto sysmem.pfree */
                    157: 
                    158:        base = btoc(1024*1024);
                    159:        while (base < sysmem.hi)
                    160:                *sysmem.pfree++ = base++; /* push(base++) onto sysmem.pfree */
                    161: 
                    162:        sysmem.efree = sysmem.pfree;
                    163: 
                    164:        /*
                    165:         * 5. allocate page entries and initialize level 0 ^'s
                    166:         * a. [ 00000000 .. 000400000 )         user code segment
                    167:         * b. [ 00400000 .. 000800000 )         user data & bss
                    168:         * c. [ 7FC00000 .. 800000000 )         user stack
                    169:         * d. [ FF800000 .. FFC000000 )         pointers to level 1 page table
                    170:         * e. [ FFC00000 ..1000000000 )         system process addresses
                    171:         */
                    172:        codeseg = clickseg(*--sysmem.pfree);            /* 5.a */
                    173:        ptable0_v[0x000] = codeseg  | DIR_RW; 
                    174: 
                    175:        dataseg = clickseg(*--sysmem.pfree);            /* 5.b */
                    176:        ptable0_v[0x001] = dataseg  | DIR_RW; 
                    177: 
                    178:        stackseg = clickseg(*--sysmem.pfree);           /* 5.c */
                    179:        ptable0_v[0x1FF] = stackseg  | DIR_RW; 
                    180: 
                    181:        ptable1 = clickseg(*--sysmem.pfree);            /* 5.d */
                    182:        ptable0_v[0x3FE] = ptable1 | DIR_RW; 
                    183: 
                    184:        sysseg = clickseg(*--sysmem.pfree);             /* 5.e */
                    185:        ptable0_v[0x3FF] = sysseg  | DIR_RW;
                    186: 
                    187:        /*
                    188:         * 6. initialize  level 2 ^'s to [5.d]
                    189:         */
                    190: 
                    191:        ptable1_v  = (long *)(ptable1 + ctob(SBASE-PBASE));
                    192:        ptable1_v[0x000] = codeseg | SEG_SRW;
                    193:        ptable1_v[0x001] = dataseg | SEG_SRW;
                    194:        ptable1_v[0x1FF] = stackseg| SEG_SRW;
                    195:        ptable1_v[0x3FF] = sysseg  | SEG_SRW;
                    196:        /*
                    197:         * 7.
                    198:         * b. map kernel code and data
                    199:         *      map ^ to:
                    200:         * c.   level 0 page table
                    201:         * d.   level 1 page table
                    202:         * e.   I/O segments (video RAM, ...) 
                    203:         */ 
                    204: 
                    205:        ptable1_v  = (long *)(sysseg + ctob(SBASE-PBASE));      /* 7.b */
                    206:        for (i = PBASE; i <sysmem.lo; i++)
                    207:                ptable1_v[i-PBASE] = clickseg(i) | SEG_SRW;
                    208: 
                    209:        ptable1_v[0x3FE] = clickseg(PTABLE0_P) | SEG_SRW;       /* 7.c */
                    210:        ptable1_v[0x3FD] = ptable1 | SEG_SRW;                   /* 7.d */
                    211: 
                    212:        init_phy_seg(ptable1_v, ROM-SBASE,   0x0000F0000);      /* 7.e. */
                    213:        init_phy_seg(ptable1_v, VIDEOa-SBASE,0x0000B0000);
                    214:        init_phy_seg(ptable1_v, VIDEOb-SBASE,0x0000B8000);
                    215:        /*
                    216:         * 8. allocate and map U area
                    217:         */
                    218: 
                    219:        uinit.s_flags = SFSYST|SFCORE;  /* System segment, Memory resident  */
                    220:        uinit.s_size = UPASIZE;         /* Size of user area in bytes.  */
                    221:        uinit.s_vmem = c_alloc(btoc(UPASIZE));  /* Breaks if UPASIZE > 4k?  */
                    222:        ptable1_v[0x3FF] = *uinit.s_vmem | SEG_SRW;     /* Map to the top of
                    223:                                                         * the kernel area.
                    224:                                                         */
                    225:        procq.p_segp[SIUSERP] = &uinit; /* Map the u area for /etc/init,
                    226:                                         * the first process.
                    227:                                         */
                    228: 
                    229:        /*
                    230:         * 9. make FFC00000 and 00002000 map to the same address
                    231:         * to prevent the prefetch after the instruction turning on
                    232:         * paging from causing a page fault
                    233:         */
                    234: 
                    235:        ptable1_v  = (long *)(codeseg + ctob(SBASE-PBASE));
                    236:        ptable1_v[PBASE] = clickseg(PBASE) | SEG_SRW;
                    237:        /*
                    238:         * 10. load page table base address into MMU
                    239:         *      fix up the interrupt vectors
                    240:         */
                    241: 
                    242:        mmuupd();
                    243:        idtinit();
                    244: }

unix.superglobalmegacorp.com

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