home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
drdobbs
/
1991
/
07
/
386bsd.791
next >
Wrap
Text File
|
1991-06-11
|
35KB
|
800 lines
_PORTING UNIX TO THE 386: A STRIPPED-DOWN KERNEL_
by William Frederick Jolitz and Lynne Greer Jolitz
[LISTING ONE]
/* locore.s: Copyright (c) 1990,1991 William Jolitz. All rights reserved.
* Written by William Jolitz 1/90
* Redistribution and use in source and binary forms are freely permitted
* provided that the above copyright notice and attribution and date of work
* and this paragraph are duplicated in all such forms.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
/* [Excerpted from i386/locore.s] */
#define R(s) s - KERNEL_BASE /* relocate references until mapping enabled */
/* Per-process region virtual address space is located at the top of user
* space, growing down to the top of the user stack [set in the "high" kernel].
* At kernel startup time, the only per-process data we need is a kernel stack,
* so we allocate SPAGES of stack pages for the purpose before calling the
* kernel initialization code. */
.data
.globl _boothowto, _bootdev, _cyloffset
/* Temporary stack */
.space 128
tmpstk:
_boothowto: .long 0 /* bootstrap options */
_bootdev: .long 0 /* bootstrap device */
_cyloffset: .long 0 /* cylinder offset of bootstrap partition */
.text
.globl start
start:
/* arrange for a warm boot from the BIOS at some point in the future */
movw $0x1234, 0x472
jmp 1f
.space 0x500 # skip over BIOS data areas
/* pass parameters on stack (howto, bootdev, cyloffset)
* note: 0(%esp) is return address of bootstrap that loaded this kernel. */
1: movl 4(%esp), %eax
movl %eax, R(_boothowto)
movl 8(%esp), %eax
movl %eax, R(_bootdev)
movl 12(%esp), %eax
movl %eax, R(_cyloffset)
/* use temporary stack till mapping enabled to insure it falls within map */
movl $R(tmpstk), %esp
/* find end of kernel image */
movl $R(_end), %ecx
addl $NBPG-1, %ecx
andl $~(NBPG-1), %ecx
movl %ecx, %esi
/* clear bss and memory for bootstrap page tables. */
movl $R(_edata), %edi
subl %edi, %ecx
addl $(SPAGES+1+1+1)*NBPG, %ecx
# stack + page directory + kernel page table + stack page table
xorl %eax, %eax # pattern
cld
rep
stosb
/* Map Kernel--N.B. don't bother with making kernel text RO, as 386
* ignores R/W AND U/S bits on kernel access (only valid bit works) !
* First step - build page tables */
movl %esi, %ecx # this much memory,
shrl $PGSHIFT, %ecx # for this many ptes
movl $PG_V, %eax # having these bits set,
leal (2+SPAGES)*NBPG(%esi), %ebx # physical address of Sysmap
movl %ebx, R(_KPTphys) # in the kernel page table,
call fillpt
/* map proc 0's kernel stack into user page table page */
movl $SPAGES, %ecx # for this many ptes,
leal 1*NBPG(%esi), %eax # physical address of stack in proc 0
orl $PG_V|PG_URKW, %eax # having these bits set,
leal (1+SPAGES)*NBPG(%esi), %ebx # physical address of stack pt
addl $(ptei(_PTmap)-1)*4, %ebx
call fillpt
/* Construct an initial page table directory */
/* install a pde for temporary double map of bottom of VA */
leal (SPAGES+2)*NBPG(%esi), %eax # physical address of kernel pt
orl $PG_V, %eax
movl %eax, (%esi)
/* kernel pde - same contents */
leal pdei(KERNEL_BASE)*4(%esi), %ebx # offset of pde for kernel
movl %eax, (%ebx)
/* install a pde recursively mapping page directory as a page table! */
movl %esi, %eax # phys address of ptd in proc 0
orl $PG_V, %eax
movl %eax, pdei(_PTD)*4(%esi)
/* install a pde to map stack for proc 0 */
leal (SPAGES+1)*NBPG(%esi), %eax # physical address of pt in proc 0
orl $PG_V, %eax
movl %eax, (pdei(_PTD)-1)*4(%esi) # which is where per-process maps!
/* load base of page directory, and enable mapping */
movl %esi, %eax # phys address of ptd in proc 0
orl $I386_CR3PAT, %eax
movl %eax, %cr3 # load ptd addr into mmu
movl %cr0, %eax # get control word
orl $0x80000001, %eax # and let s page!
movl %eax, %cr0 # NOW!
/* now running mapped */
pushl $begin # jump to high mem!
ret
/* now running relocated at SYSTEM where the system is linked to run */
begin:
/* set up bootstrap stack */
movl $_PTD-SPAGES*NBPG, %esp # kernel stack virtual address top
xorl %eax, %eax # mark end of frames with a sentinal
movl %eax, %ebp
movl %eax, _PTD # clear lower address space mapping
leal (SPAGES+3)*NBPG(%esi), %esi # skip past stack + page tables.
pushl %esi
/* init386(startphys) main(startphys) */
call _init386 # wire 386 chip for unix operation
call _main
popl %eax
/* find process (proc 0) to be run */
movl _curproc, %eax
movl P_PCB(%eax), %eax
/* build outer stack frame */
pushl PCB_SS(%eax) # user ss
pushl PCB_ESP(%eax) # user esp
pushl PCB_CS(%eax) # user cs
pushl PCB_EIP(%eax) # user pc
movw PCB_DS(%eax), %ds
movw PCB_ES(%eax), %es
lret # goto user!
/* fill in pte/pde tables */
fillpt:
movl %eax, (%ebx) /* stuff pte */
addl $NBPG, %eax /* increment physical address */
addl $4, %ebx /* next pte */
loop fillpt
ret
[LISTING TWO]
/* machdep.c: Copyright (c) 1989,1991 William Jolitz. All rights reserved.
* Written by William Jolitz 7/89
* Redistribution and use in source and binary forms are freely permitted
* provided that the above copyright notice and attribution and date of work
* and this paragraph are duplicated in all such forms.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
/* [excerpted from i386/i386/machdep.c] * /
/* Initialize segments & interrupt table */
#define GNULL_SEL 0 /* Null Descriptor */
#define GCODE_SEL 1 /* Kernel Code Descriptor */
#define GDATA_SEL 2 /* Kernel Data Descriptor */
#define GLDT_SEL 3 /* LDT - eventually one per process */
#define GTGATE_SEL 4 /* Process task switch gate */
#define GPANIC_SEL 5 /* Task state to consider panic from */
#define GPROC0_SEL 6 /* Task state process slot zero and up */
#define NGDT GPROC0_SEL+1
union descriptor gdt[GPROC0_SEL+1];
/* interrupt descriptor table */
struct gate_descriptor idt[32+16];
/* local descriptor table */
union descriptor ldt[5];
#define LSYS5CALLS_SEL 0 /* forced by intel BCS */
#define LSYS5SIGR_SEL 1
#define L43BSDCALLS_SEL 2 /* notyet */
#define LUCODE_SEL 3
#define LUDATA_SEL 4
/* #define LPOSIXCALLS_SEL 5 /* notyet */
struct i386tss tss, panic_tss;
/* software prototypes -- in more palitable form */
struct soft_segment_descriptor gdt_segs[] = {
/* Null Descriptor */
{ 0x0, /* segment base address */
0x0, /* length - all address space */
0, /* segment type */
0, /* segment descriptor priority level */
0, /* segment descriptor present */
0,0,
0, /* default 32 vs 16 bit size */
0 /* limit granularity (byte/page units)*/ },
/* Code Descriptor for kernel */
{ 0x0, /* segment base address */
0xfffff, /* length - all address space */
SDT_MEMERA, /* segment type */
0, /* segment descriptor priority level */
1, /* segment descriptor present */
0,0,
1, /* default 32 vs 16 bit size */
1 /* limit granularity (byte/page units)*/ },
/* Data Descriptor for kernel */
{ 0x0, /* segment base address */
0xfffff, /* length - all address space */
SDT_MEMRWA, /* segment type */
0, /* segment descriptor priority level */
1, /* segment descriptor present */
0,0,
1, /* default 32 vs 16 bit size */
1 /* limit granularity (byte/page units)*/ },
/* LDT Descriptor */
{ (int) ldt, /* segment base address */
sizeof(ldt)-1, /* length - all address space */
SDT_SYSLDT, /* segment type */
0, /* segment descriptor priority level */
1, /* segment descriptor present */
0,0,
0, /* unused - default 32 vs 16 bit size */
0 /* limit granularity (byte/page units)*/ },
/* Null Descriptor - Placeholder */
{ 0x0, /* segment base address */
0x0, /* length - all address space */
0, /* segment type */
0, /* segment descriptor priority level */
0, /* segment descriptor present */
0,0,
0, /* default 32 vs 16 bit size */
0 /* limit granularity (byte/page units)*/ },
/* Panic Tss Descriptor */
{ (int) &panic_tss, /* segment base address */
sizeof(tss)-1, /* length - all address space */
SDT_SYS386TSS, /* segment type */
0, /* segment descriptor priority level */
1, /* segment descriptor present */
0,0,
0, /* unused - default 32 vs 16 bit size */
0 /* limit granularity (byte/page units)*/ },
/* Proc 0 Tss Descriptor */
{ 0, /* segment base address */
sizeof(tss)-1, /* length - all address space */
SDT_SYS386TSS, /* segment type */
0, /* segment descriptor priority level */
1, /* segment descriptor present */
0,0,
0, /* unused - default 32 vs 16 bit size */
0 /* limit granularity (byte/page units)*/ }};
struct soft_segment_descriptor ldt_segs[] = {
/* Null Descriptor - overwritten by call gate */
{ 0x0, /* segment base address */
0x0, /* length - all address space */
0, /* segment type */
0, /* segment descriptor priority level */
0, /* segment descriptor present */
0,0,
0, /* default 32 vs 16 bit size */
0 /* limit granularity (byte/page units)*/ },
/* Null Descriptor - overwritten by call gate */
{ 0x0, /* segment base address */
0x0, /* length - all address space */
0, /* segment type */
0, /* segment descriptor priority level */
0, /* segment descriptor present */
0,0,
0, /* default 32 vs 16 bit size */
0 /* limit granularity (byte/page units)*/ },
/* Null Descriptor - overwritten by call gate */
{ 0x0, /* segment base address */
0x0, /* length - all address space */
0, /* segment type */
0, /* segment descriptor priority level */
0, /* segment descriptor present */
0,0,
0, /* default 32 vs 16 bit size */
0 /* limit granularity (byte/page units)*/ },
/* Code Descriptor for user */
{ 0x0, /* segment base address */
0xfffff, /* length - all address space */
SDT_MEMERA, /* segment type */
SEL_UPL, /* segment descriptor priority level */
1, /* segment descriptor present */
0,0,
1, /* default 32 vs 16 bit size */
1 /* limit granularity (byte/page units)*/ },
/* Data Descriptor for user */
{ 0x0, /* segment base address */
0xfffff, /* length - all address space */
SDT_MEMRWA, /* segment type */
SEL_UPL, /* segment descriptor priority level */
1, /* segment descriptor present */
0,0,
1, /* default 32 vs 16 bit size */
1 /* limit granularity (byte/page units)*/ } };
/* table descriptors - used to load tables by microp */
struct region_descriptor r_gdt = {
sizeof(gdt)-1,(char *)gdt
};
struct region_descriptor r_idt = {
sizeof(idt)-1,(char *)idt
};
setidt(idx, func, typ, dpl) char *func; {
struct gate_descriptor *ip = idt + idx;
ip->gd_looffset = (int)func;
ip->gd_selector = GSEL(GCODE_SEL,SEL_KPL);
ip->gd_stkcpy = 0;
ip->gd_xx = 0;
ip->gd_type = typ;
ip->gd_dpl = dpl;
ip->gd_p = 1;
ip->gd_hioffset = ((int)func)>>16 ;
}
#define IDTVEC(name) X/**/name
extern IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt), IDTVEC(ofl),
IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(dble), IDTVEC(fpusegm),
IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot),
IDTVEC(page), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(rsvd0),
IDTVEC(rsvd1), IDTVEC(rsvd2), IDTVEC(rsvd3), IDTVEC(rsvd4),
IDTVEC(rsvd5), IDTVEC(rsvd6), IDTVEC(rsvd7), IDTVEC(rsvd8),
IDTVEC(rsvd9), IDTVEC(rsvd10), IDTVEC(rsvd11), IDTVEC(rsvd12),
IDTVEC(rsvd13), IDTVEC(rsvd14), IDTVEC(rsvd14), IDTVEC(syscall);
int lcr0(), lcr3(), rcr0(), rcr2();
int _udatasel, _ucodesel, _gsel_tss;
init386() { extern ssdtosd(), lgdt(), lidt(), lldt(), etext;
int x;
unsigned biosbasemem, biosextmem;
struct gate_descriptor *gdp;
extern int sigcode,szsigcode;
struct pcb *pb = proc0.p_addr;
/* initialize console */
cninit ();
/* make gdt memory segments */
gdt_segs[GCODE_SEL].ssd_limit = btoc((int) &etext + NBPG);
gdt_segs[GPROC0_SEL].ssd_base = pb;
for (x=0; x < NGDT; x++) ssdtosd(gdt_segs+x, gdt+x);
/* make ldt memory segments */
ldt_segs[LUCODE_SEL].ssd_limit = btoc(UPT_MIN_ADDRESS);
ldt_segs[LUDATA_SEL].ssd_limit = btoc(UPT_MIN_ADDRESS);
/* Note. eventually want private ldts per process */
for (x=0; x < 5; x++) ssdtosd(ldt_segs+x, ldt+x);
/* exceptions */
setidt(0, &IDTVEC(div), SDT_SYS386TGT, SEL_KPL);
setidt(1, &IDTVEC(dbg), SDT_SYS386TGT, SEL_KPL);
setidt(2, &IDTVEC(nmi), SDT_SYS386TGT, SEL_KPL);
setidt(3, &IDTVEC(bpt), SDT_SYS386TGT, SEL_UPL);
setidt(4, &IDTVEC(ofl), SDT_SYS386TGT, SEL_KPL);
setidt(5, &IDTVEC(bnd), SDT_SYS386TGT, SEL_KPL);
setidt(6, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL);
setidt(7, &IDTVEC(dna), SDT_SYS386TGT, SEL_KPL);
setidt(8, &IDTVEC(dble), SDT_SYS386TGT, SEL_KPL);
setidt(9, &IDTVEC(fpusegm), SDT_SYS386TGT, SEL_KPL);
setidt(10, &IDTVEC(tss), SDT_SYS386TGT, SEL_KPL);
setidt(11, &IDTVEC(missing), SDT_SYS386TGT, SEL_KPL);
setidt(12, &IDTVEC(stk), SDT_SYS386TGT, SEL_KPL);
setidt(13, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL);
setidt(14, &IDTVEC(page), SDT_SYS386TGT, SEL_KPL);
setidt(15, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL);
setidt(16, &IDTVEC(fpu), SDT_SYS386TGT, SEL_KPL);
setidt(17, &IDTVEC(rsvd0), SDT_SYS386TGT, SEL_KPL);
setidt(18, &IDTVEC(rsvd1), SDT_SYS386TGT, SEL_KPL);
setidt(19, &IDTVEC(rsvd2), SDT_SYS386TGT, SEL_KPL);
setidt(20, &IDTVEC(rsvd3), SDT_SYS386TGT, SEL_KPL);
setidt(21, &IDTVEC(rsvd4), SDT_SYS386TGT, SEL_KPL);
setidt(22, &IDTVEC(rsvd5), SDT_SYS386TGT, SEL_KPL);
setidt(23, &IDTVEC(rsvd6), SDT_SYS386TGT, SEL_KPL);
setidt(24, &IDTVEC(rsvd7), SDT_SYS386TGT, SEL_KPL);
setidt(25, &IDTVEC(rsvd8), SDT_SYS386TGT, SEL_KPL);
setidt(26, &IDTVEC(rsvd9), SDT_SYS386TGT, SEL_KPL);
setidt(27, &IDTVEC(rsvd10), SDT_SYS386TGT, SEL_KPL);
setidt(28, &IDTVEC(rsvd11), SDT_SYS386TGT, SEL_KPL);
setidt(29, &IDTVEC(rsvd12), SDT_SYS386TGT, SEL_KPL);
setidt(30, &IDTVEC(rsvd13), SDT_SYS386TGT, SEL_KPL);
setidt(31, &IDTVEC(rsvd14), SDT_SYS386TGT, SEL_KPL);
#include "isa.h"
#if NISA >0
isa_defaultirq();
#endif
/* load descriptor tables into 386 */
lgdt(gdt, sizeof(gdt)-1);
lidt(idt, sizeof(idt)-1);
lldt(GSEL(GLDT_SEL, SEL_KPL));
/* resolve amount of memory present so we can scale kernel PT */
maxmem = probemem();
biosbasemem = rtcin(RTC_BASELO)+ (rtcin(RTC_BASEHI)<<8);
biosextmem = rtcin(RTC_EXTLO)+ (rtcin(RTC_EXTHI)<<8);
if (biosbasemem == 0xffff || biosextmem == 0xffff) {
if (biosbasemem == 0xffff && maxmem > RAM_END)
maxmem = IOM_BEGIN;
if (biosextmem == 0xffff && maxmem > RAM_END)
maxmem = IOM_BEGIN;
} else if (biosextmem > 0 && biosbasemem == IOM_BEGIN/1024) {
int totbios = (biosbasemem + 0x60000 + biosextmem);
if (totbios < maxmem) maxmem = totbios;
} else maxmem = IOM_BEGIN;
/* call pmap initialization to make new kernel address space */
pmap_bootstrap ();
/* now running on new page tables, configured,and u/iom is accessible */
/* make a initial tss so microp can get interrupt stack on syscall! */
pb->pcbtss.tss_esp0 = UPT_MIN_ADDRESS;
pb->pcbtss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL) ;
_gsel_tss = GSEL(GPROC0_SEL, SEL_KPL);
ltr(_gsel_tss);
/* make a call gate to reenter kernel with */
gdp = &ldt[LSYS5CALLS_SEL].gd;
gdp->gd_looffset = (int) &IDTVEC(syscall);
gdp->gd_selector = GSEL(GCODE_SEL,SEL_KPL);
gdp->gd_stkcpy = 0;
gdp->gd_type = SDT_SYS386CGT;
gdp->gd_dpl = SEL_UPL;
gdp->gd_p = 1;
gdp->gd_hioffset = ((int) &IDTVEC(syscall)) >>16;
/* transfer to user mode */
_ucodesel = LSEL(LUCODE_SEL, SEL_UPL);
_udatasel = LSEL(LUDATA_SEL, SEL_UPL);
/* setup per-process */
bcopy(&sigcode, pb->pcb_sigc, szsigcode);
pb->pcb_flags = 0;
pb->pcb_ptd = IdlePTD;
}
[LISTING THREE]
/* Machine dependent constants for 386. */
/* user map constants */
#define VM_MIN_ADDRESS ((vm_offset_t)0)
#define UPT_MIN_ADDRESS ((vm_offset_t)0xFDC00000)
#define UPT_MAX_ADDRESS ((vm_offset_t)0xFDFF7000)
#define VM_MAX_ADDRESS UPT_MAX_ADDRESS
/* kernel map constants */
#define VM_MIN_KERNEL_ADDRESS ((vm_offset_t)0xFDFF7000)
#define KPT_MIN_ADDRESS ((vm_offset_t)0xFDFF8000)
#define KPT_MAX_ADDRESS ((vm_offset_t)0xFDFFF000)
#define KERNEL_BASE 0xFE000000
#define VM_MAX_KERNEL_ADDRESS ((vm_offset_t)0xFF7FF000)
/* # of kernel PT pages (initial only, can grow dynamically) */
#define VM_KERNEL_PT_PAGES ((vm_size_t)1)
[LISTING FOUR]
/* param.h: Copyright (c) 1989,1990,1991 William Jolitz. All rights reserved.
* Written by William Jolitz 6/89
* Redistribution and use in source and binary forms are freely permitted
* provided that the above copyright notice and attribution and date of work
* and this paragraph are duplicated in all such forms.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
/* Machine dependent constants for Intel 386. */
#define MACHINE "i386"
#define NBPG 4096 /* bytes/page */
#define PGOFSET (NBPG-1) /* byte offset into page */
#define PGSHIFT 12 /* LOG2(NBPG) */
#define NPTEPG (NBPG/(sizeof (struct pte)))
#define NBPDR (1024*NBPG) /* bytes/page dir */
#define PDROFSET (NBPDR-1) /* byte offset into page dir */
#define PDRSHIFT 22 /* LOG2(NBPDR) */
#define KERNBASE 0xFE000000 /* start of kernel virtual */
#define DEV_BSIZE 512
#define DEV_BSHIFT 9 /* log2(DEV_BSIZE) */
#define CLSIZE 1
#define CLSIZELOG2 0
#define SSIZE 1 /* initial stack size/NBPG */
#define SINCR 1 /* increment of stack/NBPG */
#define SPAGES 2 /* pages of kernel stack area */
/* clicks to bytes */
#define ctob(x) ((x)<<PGSHIFT)
/* bytes to clicks */
#define btoc(x) (((unsigned)(x)+(NBPG-1))>>PGSHIFT)
#define btodb(bytes) /* calculates (bytes / DEV_BSIZE) */ \
((unsigned)(bytes) >> DEV_BSHIFT)
#define dbtob(db) /* calculates (db * DEV_BSIZE) */ \
((unsigned)(db) << DEV_BSHIFT)
/* Map a ``block device block'' to a file system block. This should be device
* dependent, and will be if we add an entry to cdevsw/bdevsw for that purpose.
* For now though just use DEV_BSIZE. */
#define bdbtofsb(bn) ((bn) / (BLKDEV_IOSIZE/DEV_BSIZE))
/* Mach derived conversion macros */
#define i386_round_pdr(x) ((((unsigned)(x)) + NBPDR - 1) & ~(NBPDR-1))
#define i386_trunc_pdr(x) ((unsigned)(x) & ~(NBPDR-1))
#define i386_round_page(x) ((((unsigned)(x)) + NBPG - 1) & ~(NBPG-1))
#define i386_trunc_page(x) ((unsigned)(x) & ~(NBPG-1))
#define i386_btod(x) ((unsigned)(x) >> PDRSHIFT)
#define i386_dtob(x) ((unsigned)(x) << PDRSHIFT)
#define i386_btop(x) ((unsigned)(x) >> PGSHIFT)
#define i386_ptob(x) ((unsigned)(x) << PGSHIFT)
[LISTING FIVE]
/* param.h: Copyright (c) 1989,1990,1991 William Jolitz. All rights reserved.
* Written by William Jolitz 6/89
* Redistribution and use in source and binary forms are freely permitted
* provided that the above copyright notice and attribution and date of work
* and this paragraph are duplicated in all such forms.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
/* Machine dependent constants for Intel 386. */
#define MACHINE "i386"
#define NBPG 4096 /* bytes/page */
#define PGOFSET (NBPG-1) /* byte offset into page */
#define PGSHIFT 12 /* LOG2(NBPG) */
#define NPTEPG (NBPG/(sizeof (struct pte)))
#define NBPDR (1024*NBPG) /* bytes/page dir */
#define PDROFSET (NBPDR-1) /* byte offset into page dir */
#define PDRSHIFT 22 /* LOG2(NBPDR) */
#define KERNBASE 0xFE000000 /* start of kernel virtual */
#define DEV_BSIZE 512
#define DEV_BSHIFT 9 /* log2(DEV_BSIZE) */
#define CLSIZE 1
#define CLSIZELOG2 0
#define SSIZE 1 /* initial stack size/NBPG */
#define SINCR 1 /* increment of stack/NBPG */
#define SPAGES 2 /* pages of kernel stack area */
/* clicks to bytes */
#define ctob(x) ((x)<<PGSHIFT)
/* bytes to clicks */
#define btoc(x) (((unsigned)(x)+(NBPG-1))>>PGSHIFT)
#define btodb(bytes) /* calculates (bytes / DEV_BSIZE) */ \
((unsigned)(bytes) >> DEV_BSHIFT)
#define dbtob(db) /* calculates (db * DEV_BSIZE) */ \
((unsigned)(db) << DEV_BSHIFT)
/* Map a ``block device block'' to a file system block. This should be device
* dependent, and will be if we add an entry to cdevsw/bdevsw for that purpose.
* For now though just use DEV_BSIZE. */
#define bdbtofsb(bn) ((bn) / (BLKDEV_IOSIZE/DEV_BSIZE))
/* Mach derived conversion macros */
#define i386_round_pdr(x) ((((unsigned)(x)) + NBPDR - 1) & ~(NBPDR-1))
#define i386_trunc_pdr(x) ((unsigned)(x) & ~(NBPDR-1))
#define i386_round_page(x) ((((unsigned)(x)) + NBPG - 1) & ~(NBPG-1))
#define i386_trunc_page(x) ((unsigned)(x) & ~(NBPG-1))
#define i386_btod(x) ((unsigned)(x) >> PDRSHIFT)
#define i386_dtob(x) ((unsigned)(x) << PDRSHIFT)
#define i386_btop(x) ((unsigned)(x) >> PGSHIFT)
#define i386_ptob(x) ((unsigned)(x) << PGSHIFT)
Figure 1(a):
Minimal Kernel Breakdown (by module)
vmunix: text data bss module name
1152 32 0 clock.o
0 500 0 conf.o
4548 740 32 cons.o
1508 24 0 init_main.o
0 1212 0 init_sysent.o
1588 28 0 kern_clock.o
2044 12 0 kern_descrip.o
3296 80 0 kern_exec.o
1840 48 0 kern_exit.o
1600 36 0 kern_fork.o
956 0 0 kern_mman.o
312 0 0 kern_proc.o
1280 0 0 kern_prot.o
1216 0 0 kern_resource.o
3564 32 0 kern_sig.o
684 16 0 kern_subr.o
1808 24 0 kern_synch.o
1864 4 0 kern_time.o
248 0 0 kern_xxx.o
6176 20508 0 locore.o
5596 596 0 machdep.o
0 148 0 param.o
2184 84 8 subr_prf.o
1092 72 0 subr_rmap.o
244 0 0 subr_xxx.o
184 72 0 swapgeneric.o
3340 0 0 sys_generic.o
4156 68 0 sys_inode.o
1096 56 0 sys_process.o
784 16 0 sys_socket.o
2260 224 0 trap.o
9480 516 0 tty.o
12 204 0 tty_conf.o
3928 4 0 tty_pty.o
1924 0 0 tty_subr.o
8680 1220 0 ufs_alloc.o
3312 116 0 ufs_bio.o
1668 0 0 ufs_bmap.o
1248 48 0 ufs_disksubr.o
416 0 0 ufs_fio.o
3968 68 0 ufs_inode.o
436 0 0 ufs_machdep.o
2048 0 0 ufs_mount.o
6020 220 0 ufs_namei.o
2288 208 0 ufs_subr.o
7100 112 0 ufs_syscalls.o
0 620 0 ufs_tables.o
0 152 0 vers.o
2280 48 0 vm_drum.o
2964 52 0 vm_machdep.o
4364 180 0 vm_mem.o
8280 188 0 vm_page.o
2056 20 0 vm_proc.o
3060 24 0 vm_pt.o
2788 72 0 vm_sched.o
528 0 0 vm_subr.o
1052 32 0 vm_sw.o
1836 44 0 vm_swap.o
1536 152 0 vm_swp.o
2048 68 0 vm_text.o
3768 1492 1024 wd.o
totals: 145708 30492 1064
Figure 1(b):
Fully Loaded Kernel Breakdown (by module)
vmunix: text data bss module
0 4 0 af.o
592 16 0 autoconf.o
844 0 0 clock.o
2584 168 0 com.o
0 640 0 conf.o
4096 676 40 cons.o
540 132 0 dead_vnops.o
1440 28 0 device_pager.o
3180 152 48 fd.o
1264 140 0 fifo_vnops.o
2812 12 0 if.o
2600 12 0 if_ether.o
1056 24 18 if_ethersubr.o
464 0 0 if_loop.o
5044 12 12 if_ne.o
3184 16 0 if_sl.o
3852 12 4 if_we.o
2844 4 0 in.o
356 0 0 in_cksum.o
1684 0 0 in_pcb.o
12 320 0 in_proto.o
1496 12 0 init_main.o
0 1532 0 init_sysent.o
0 468 0 ioconf.o
2056 68 0 ip_icmp.o
4564 60 48 ip_input.o
2616 0 0 ip_output.o
1372 4 0 isa.o
1204 16 0 kern_acct.o
1280 4 0 kern_clock.o
3184 0 0 kern_descrip.o
3176 0 0 kern_exec.o
1424 0 0 kern_exit.o
996 8 4 kern_fork.o
1204 0 0 kern_kinfo.o
1772 0 0 kern_ktrace.o
1028 4 0 kern_lock.o
1892 268 0 kern_malloc.o
796 0 0 kern_physio.o
1180 0 0 kern_proc.o
1844 0 0 kern_prot.o
1140 0 0 kern_resource.o
4172 132 0 kern_sig.o
684 0 0 kern_subr.o
1988 4 0 kern_synch.o
1408 4 0 kern_time.o
264 0 0 kern_xxx.o
7076 684 0 locore.o
4684 192 0 machdep.o
552 0 0 mem.o
708 44 4 mfs_vfsops.o
656 132 0 mfs_vnops.o
1600 0 0 nfs_bio.o
1020 0 0 nfs_node.o
21700 36 0 nfs_serv.o
7748 152 0 nfs_socket.o
1040 144 21672 nfs_srvcache.o
10284 40 4 nfs_subs.o
1956 72 80 nfs_syscalls.o
2996 40 1 nfs_vfsops.o
21304 424 0 nfs_vnops.o
348 12 16 npx.o
0 152 0 param.o
6308 16 0 pmap.o
2908 4 36 radix.o
164 8 0 raw_cb.o
1072 36 0 raw_ip.o
812 0 0 raw_usrreq.o
2304 8 0 route.o
4552 116 0 rtsock.o
2584 60 0 slcompress.o
2296 180 0 spec_vnops.o
716 0 0 subr_log.o
1764 8 0 subr_prf.o
888 0 0 subr_rmap.o
340 0 0 subr_xxx.o
5456 28 0 swap_pager.o
0 40 0 swapvmunix.o
3344 0 0 sys_generic.o
0 0 0 sys_machdep.o
904 56 0 sys_process.o
604 20 0 sys_socket.o
228 0 0 tcp_debug.o
5820 8 0 tcp_input.o
1896 16 0 tcp_output.o
1504 12 0 tcp_subr.o
832 60 0 tcp_timer.o
1620 8 0 tcp_usrreq.o
2912 0 0 trap.o
9488 316 0 tty.o
1864 204 0 tty_compat.o
12 204 0 tty_conf.o
3452 4 0 tty_pty.o
1988 0 0 tty_subr.o
504 0 0 tty_tty.o
1980 36 0 udp_usrreq.o
9644 0 0 ufs_alloc.o
2012 0 0 ufs_bmap.o
1424 0 0 ufs_disksubr.o
3756 0 0 ufs_inode.o
1668 12 0 ufs_lockf.o
3832 4 0 ufs_lookup.o
4572 20 0 ufs_quota.o
732 0 0 ufs_subr.o
0 620 0 ufs_tables.o
3948 64 0 ufs_vfsops.o
8264 524 0 ufs_vnops.o
620 0 0 uipc_domain.o
2672 64 4 uipc_mbuf.o
8 176 0 uipc_proto.o
6164 0 0 uipc_socket.o
3184 24 0 uipc_socket2.o
5520 0 0 uipc_syscalls.o
3320 32 0 uipc_usrreq.o
0 232 0 vers.o
3644 0 0 vfs_bio.o
1108 4 0 vfs_cache.o
0 24 0 vfs_conf.o
1776 0 0 vfs_lookup.o
3940 44 0 vfs_subr.o
7544 0 0 vfs_syscalls.o
1684 20 0 vfs_vnops.o
3524 0 0 vm_fault.o
1964 20 0 vm_glue.o
84 0 0 vm_init.o
1848 0 0 vm_kern.o
944 0 308 vm_machdep.o
7624 16 0 vm_map.o
384 20 0 vm_meter.o
3196 4 0 vm_mmap.o
3588 16 0 vm_object.o
2500 32 0 vm_page.o
824 8 0 vm_pageout.o
636 20 0 vm_pager.o
1160 0 0 vm_swap.o
416 0 0 vm_unix.o
304 0 0 vm_user.o
2200 28 0 vnode_pager.o
6176 1648 524 wd.o
5252 48 9 wt.o
totals: 359636 12248 22832