|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.