|
|
coherent
#undef ptable1_v
#undef ptable0_v
/* Put the page directory at the click before the start of kernel text. */
#define ptable0_v ((long *)(&stext[ctob(-1)]))
/*
* mchinit()
* Initializes buddy system for (physical?) memory allocation.
* (See Knuth's Art of Computer Programming, Vol I.)
* Initializes tables for the memory management unit (mmu).
* (See Intel i386 CPU documentation.)
*
*/
mchinit()
{
/* Symbols generated by linker. */
extern char end[], /* End of kernel bss (uninitialized data). */
edata[], /* End of kernel initialized data. */
etext[]; /* End of kernel text segment. */
/* Symbols from as.s. */
extern char stext[], /* Start of kernel text segment. */
sdata[]; /* Start of kernel initialized data segment. */
register char *pe; /* Working pointer meant for abuse. */
register zero = 0; /* */
register i; /* Miscellaneous counter. */
register long *lp; /* Unused */
register long *ptable1_v; /* Abused slave page table pointer. */
register n, /* Unused? */
syse, /* Unused. */
/* Click addr */ base; /* Counter for freeing memory (low and extended). */
int uaddr; /* Unused. */
/* These point at the slave page tables for various segments.
* They are in clicks.
*/
int sysseg, /* System segment--the entire kernel. */
codeseg, /* User code segment. */
dataseg, /* User data segment. */
stackseg, /* User stack segment. */
ptable1; /* Paging segment--most slave page tables
* get mapped to this segment.
*/
/* Low memory is 0-640K, extended is 1M and up. */
int lo, /* Number of bytes above kernel in low memory. */
hi, /* Number of bytes in extended memory. */
nalloc, /* Number of allocatable clicks in all of memory. */
diff; /* Buddy system overhead in clicks. */
extern char digtab[]; /* Mystery kernel hangman. :-) */
static SEG uinit; /* User area for /etc/init? */
/*
* 1.
* a. Relocate the data on a page boundary (4K bytes) the
* bootstrap relocates it on a paragraph boundary (16 bytes)
*
* b. Verify that the data has been relocated correctly
*/
pe = edata; /* 1.a */
/* (((unsigned)etext+15) & ~15) is where the boot code put
* the data segment.
* (unsigned)sdata is where the linker wants it to be.
* Thus "i" is the distance from where the data segment is, to
* where the data segment should be.
*
* Note that i will be negative with this kernel.
*/
i = (((unsigned)etext+15) & ~15) - (unsigned)sdata;
/* Move a region to a (possibly overlapping) region above it.
* SIC!
*/
do {
pe--;
pe[0] = pe[i];
} while (pe != sdata); /* 1.a */
/* The kernel will hang if digtab[] is not initialized such that
* digtab[0] is the character '0'. This is done by the
* compiler.
*/
while (digtab[0]!='0'); /* 1.b */
/*
* 2. Zero the bss
* Zero the level 0 page directory (Master page table)
*/
pe = edata;
do
*pe++ = zero;
while (pe != end);
/* Note that ptable0_v is the click before the kernel text segment. */
pe = (char *) ptable0_v;
do
*pe++ = zero;
while (pe != stext);
/*
* 3. Calculate total system memory in taking
* into account the space used by the system and the page
* descriptors, the interrupt stack, and the refresh work area
*
* a. initialize allocation area and adjust system size
* to take allocation area and free page area into account
*/
/* SBASE is the click of the start of the kernel in virtual memory.
* PBASE is the click of the start of the kernel in physical memory.
*
* SBASE is 0xFFC00, PBASE is 0x02
*
* Calculate the first click after the kernel in physical memory.
* This is in low memory (below 640k).
*/
sysmem.lo = (btoc((unsigned)end) - SBASE) + PBASE;
/*
* These calls to c_size() should be replaced by calls to a
* routine that gets the memory size from the CMOS.
*/
lo = c_size(sysmem.lo, btoc(640*1024));
hi = c_size(btoc(1024*1024), btoc(4096*1024));
/* This calculation is suspect. It may be high by 1 click.
* The problem is that a click split between extended and low
* memory cannot be allocated as a single click.
*/
nalloc = (lo+hi) / (sizeof(short) + SPLASH*sizeof(long) + ctob(1));
areainit(SPLASH*nalloc*sizeof(long));
sysmem.tfree = sysmem.pfree =
(unsigned short *)(end + SPLASH*nalloc*sizeof(long));
sysmem.hi = btoc(hi+1024*1024);
base = sysmem.lo + (lo>>BPCSHIFT);
diff = ((lo + hi) >> BPCSHIFT) - nalloc;
sysmem.lo += diff;
sysmem.vaddre = ctob(sysmem.lo+SBASE-PBASE);
/* include in system area pages for arena, free area */
/*
* 4.
* Free the memory from [end, 640) kilobytes
* Free the memory from [1024, 16*1024) kilobytes
*/
while (base > sysmem.lo)
*sysmem.pfree++ = --base; /* push(--base) onto sysmem.pfree */
base = btoc(1024*1024);
while (base < sysmem.hi)
*sysmem.pfree++ = base++; /* push(base++) onto sysmem.pfree */
sysmem.efree = sysmem.pfree;
/*
* 5. allocate page entries and initialize level 0 ^'s
* a. [ 00000000 .. 000400000 ) user code segment
* b. [ 00400000 .. 000800000 ) user data & bss
* c. [ 7FC00000 .. 800000000 ) user stack
* d. [ FF800000 .. FFC000000 ) pointers to level 1 page table
* e. [ FFC00000 ..1000000000 ) system process addresses
*/
codeseg = clickseg(*--sysmem.pfree); /* 5.a */
ptable0_v[0x000] = codeseg | DIR_RW;
dataseg = clickseg(*--sysmem.pfree); /* 5.b */
ptable0_v[0x001] = dataseg | DIR_RW;
stackseg = clickseg(*--sysmem.pfree); /* 5.c */
ptable0_v[0x1FF] = stackseg | DIR_RW;
ptable1 = clickseg(*--sysmem.pfree); /* 5.d */
ptable0_v[0x3FE] = ptable1 | DIR_RW;
sysseg = clickseg(*--sysmem.pfree); /* 5.e */
ptable0_v[0x3FF] = sysseg | DIR_RW;
/*
* 6. initialize level 2 ^'s to [5.d]
*/
ptable1_v = (long *)(ptable1 + ctob(SBASE-PBASE));
ptable1_v[0x000] = codeseg | SEG_SRW;
ptable1_v[0x001] = dataseg | SEG_SRW;
ptable1_v[0x1FF] = stackseg| SEG_SRW;
ptable1_v[0x3FF] = sysseg | SEG_SRW;
/*
* 7.
* b. map kernel code and data
* map ^ to:
* c. level 0 page table
* d. level 1 page table
* e. I/O segments (video RAM, ...)
*/
ptable1_v = (long *)(sysseg + ctob(SBASE-PBASE)); /* 7.b */
for (i = PBASE; i <sysmem.lo; i++)
ptable1_v[i-PBASE] = clickseg(i) | SEG_SRW;
ptable1_v[0x3FE] = clickseg(PTABLE0_P) | SEG_SRW; /* 7.c */
ptable1_v[0x3FD] = ptable1 | SEG_SRW; /* 7.d */
init_phy_seg(ptable1_v, ROM-SBASE, 0x0000F0000); /* 7.e. */
init_phy_seg(ptable1_v, VIDEOa-SBASE,0x0000B0000);
init_phy_seg(ptable1_v, VIDEOb-SBASE,0x0000B8000);
/*
* 8. allocate and map U area
*/
uinit.s_flags = SFSYST|SFCORE; /* System segment, Memory resident */
uinit.s_size = UPASIZE; /* Size of user area in bytes. */
uinit.s_vmem = c_alloc(btoc(UPASIZE)); /* Breaks if UPASIZE > 4k? */
ptable1_v[0x3FF] = *uinit.s_vmem | SEG_SRW; /* Map to the top of
* the kernel area.
*/
procq.p_segp[SIUSERP] = &uinit; /* Map the u area for /etc/init,
* the first process.
*/
/*
* 9. make FFC00000 and 00002000 map to the same address
* to prevent the prefetch after the instruction turning on
* paging from causing a page fault
*/
ptable1_v = (long *)(codeseg + ctob(SBASE-PBASE));
ptable1_v[PBASE] = clickseg(PBASE) | SEG_SRW;
/*
* 10. load page table base address into MMU
* fix up the interrupt vectors
*/
mmuupd();
idtinit();
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.