File:  [MW Coherent from dump] / coherent / b / kernel / i386 / mmu.doc
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed May 29 04:56:37 2019 UTC (7 years ago) by root
Branches: MarkWilliams, MAIN
CVS tags: relic, HEAD
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();
}

unix.superglobalmegacorp.com

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