Commit | Line | Data |
---|---|---|
15637ed4 RG |
1 | /*- |
2 | * Copyright (c) 1990 The Regents of the University of California. | |
3 | * All rights reserved. | |
4 | * | |
5 | * This code is derived from software contributed to Berkeley by | |
6 | * William Jolitz. | |
7 | * | |
8 | * Redistribution and use in source and binary forms, with or without | |
9 | * modification, are permitted provided that the following conditions | |
10 | * are met: | |
11 | * 1. Redistributions of source code must retain the above copyright | |
12 | * notice, this list of conditions and the following disclaimer. | |
13 | * 2. Redistributions in binary form must reproduce the above copyright | |
14 | * notice, this list of conditions and the following disclaimer in the | |
15 | * documentation and/or other materials provided with the distribution. | |
16 | * 3. All advertising materials mentioning features or use of this software | |
17 | * must display the following acknowledgement: | |
18 | * This product includes software developed by the University of | |
19 | * California, Berkeley and its contributors. | |
20 | * 4. Neither the name of the University nor the names of its contributors | |
21 | * may be used to endorse or promote products derived from this software | |
22 | * without specific prior written permission. | |
23 | * | |
24 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
25 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
29 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
30 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
31 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
32 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
33 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
34 | * SUCH DAMAGE. | |
35 | * | |
ad94c378 | 36 | * from: @(#)locore.s 7.3 (Berkeley) 5/13/91 |
18dbbd0c | 37 | * $Id: locore.s,v 1.7 1993/10/13 07:11:11 rgrimes Exp $ |
15637ed4 RG |
38 | */ |
39 | ||
40 | ||
41 | /* | |
42 | * locore.s: 4BSD machine support for the Intel 386 | |
43 | * Preliminary version | |
44 | * Written by William F. Jolitz, 386BSD Project | |
45 | */ | |
46 | ||
ad94c378 RG |
47 | #include "npx.h" |
48 | ||
15637ed4 RG |
49 | #include "assym.s" |
50 | #include "machine/psl.h" | |
51 | #include "machine/pte.h" | |
52 | ||
53 | #include "errno.h" | |
54 | ||
55 | #include "machine/trap.h" | |
56 | ||
57 | #include "machine/specialreg.h" | |
58 | #include "i386/isa/debug.h" | |
ad94c378 | 59 | #include "machine/cputypes.h" |
15637ed4 RG |
60 | |
61 | #define KDSEL 0x10 | |
62 | #define SEL_RPL_MASK 0x0003 | |
63 | #define TRAPF_CS_OFF (13 * 4) | |
64 | ||
65 | /* | |
66 | * Note: This version greatly munged to avoid various assembler errors | |
67 | * that may be fixed in newer versions of gas. Perhaps newer versions | |
68 | * will have more pleasant appearance. | |
69 | */ | |
70 | ||
71 | .set IDXSHIFT,10 | |
b2a82d1f | 72 | |
15637ed4 RG |
73 | #define ALIGN_DATA .align 2 |
74 | #define ALIGN_TEXT .align 2,0x90 /* 4-byte boundaries, NOP-filled */ | |
75 | #define SUPERALIGN_TEXT .align 4,0x90 /* 16-byte boundaries better for 486 */ | |
76 | ||
dd18dc33 DG |
77 | #define GEN_ENTRY(name) ALIGN_TEXT; .globl name; name: |
78 | #define NON_GPROF_ENTRY(name) GEN_ENTRY(_/**/name) | |
79 | ||
80 | #ifdef GPROF | |
81 | /* | |
82 | * ALTENTRY() must be before a corresponding ENTRY() so that it can jump | |
83 | * over the mcounting. | |
84 | */ | |
85 | #define ALTENTRY(name) GEN_ENTRY(_/**/name); MCOUNT; jmp 2f | |
86 | #define ENTRY(name) GEN_ENTRY(_/**/name); MCOUNT; 2: | |
87 | /* | |
88 | * The call to mcount supports the usual (bad) conventions. We allocate | |
89 | * some data and pass a pointer to it although the 386BSD doesn't use | |
90 | * the data. We set up a frame before calling mcount because that is | |
91 | * the standard convention although it makes work for both mcount and | |
92 | * callers. | |
93 | */ | |
94 | #define MCOUNT .data; ALIGN_DATA; 1:; .long 0; .text; \ | |
57cfd936 | 95 | pushl %ebp; movl %esp,%ebp; \ |
dd18dc33 DG |
96 | movl $1b,%eax; call mcount; popl %ebp |
97 | #else | |
98 | /* | |
99 | * ALTENTRY() has to align because it is before a corresponding ENTRY(). | |
100 | * ENTRY() has to align to because there may be no ALTENTRY() before it. | |
101 | * If there is a previous ALTENTRY() then the alignment code is empty. | |
102 | */ | |
103 | #define ALTENTRY(name) GEN_ENTRY(_/**/name) | |
104 | #define ENTRY(name) GEN_ENTRY(_/**/name) | |
105 | #endif | |
b2a82d1f | 106 | |
15637ed4 RG |
107 | /* NB: NOP now preserves registers so NOPs can be inserted anywhere */ |
108 | /* XXX: NOP and FASTER_NOP are misleadingly named */ | |
ad94c378 | 109 | #ifdef DUMMY_NOPS /* this will break some older machines */ |
15637ed4 RG |
110 | #define FASTER_NOP |
111 | #define NOP | |
ad94c378 RG |
112 | #else |
113 | #define FASTER_NOP pushl %eax ; inb $0x84,%al ; popl %eax | |
114 | #define NOP pushl %eax ; inb $0x84,%al ; inb $0x84,%al ; popl %eax | |
15637ed4 RG |
115 | #endif |
116 | ||
117 | /* | |
118 | * PTmap is recursive pagemap at top of virtual address space. | |
119 | * Within PTmap, the page directory can be found (third indirection). | |
120 | */ | |
42aacf6f RG |
121 | .globl _PTmap,_PTD,_PTDpde,_Sysmap |
122 | .set _PTmap,PTDPTDI << PDRSHIFT | |
123 | .set _PTD,_PTmap + (PTDPTDI * NBPG) | |
18dbbd0c | 124 | .set _PTDpde,_PTD + (PTDPTDI * 4) /* XXX 4=sizeof pde */ |
42aacf6f | 125 | |
18dbbd0c | 126 | .set _Sysmap,_PTmap + (KPTDI * NBPG) |
15637ed4 RG |
127 | |
128 | /* | |
129 | * APTmap, APTD is the alternate recursive pagemap. | |
130 | * It's used when modifying another process's page tables. | |
131 | */ | |
42aacf6f RG |
132 | .globl _APTmap,_APTD,_APTDpde |
133 | .set _APTmap,APTDPTDI << PDRSHIFT | |
134 | .set _APTD,_APTmap + (APTDPTDI * NBPG) | |
18dbbd0c | 135 | .set _APTDpde,_PTD + (APTDPTDI * 4) /* XXX 4=sizeof pde */ |
15637ed4 RG |
136 | |
137 | /* | |
138 | * Access to each processes kernel stack is via a region of | |
139 | * per-process address space (at the beginning), immediatly above | |
140 | * the user process stack. | |
141 | */ | |
57cfd936 | 142 | .set _kstack,USRSTACK |
ad94c378 | 143 | .globl _kstack |
15637ed4 | 144 | .set PPDROFF,0x3F6 |
57cfd936 | 145 | .set PPTEOFF,0x400-UPAGES /* 0x3FE */ |
15637ed4 | 146 | |
15637ed4 | 147 | |
ad94c378 RG |
148 | /* |
149 | * Globals | |
150 | */ | |
15637ed4 | 151 | .data |
ad94c378 | 152 | .globl _esym |
57cfd936 | 153 | _esym: .long 0 /* ptr to end of syms */ |
ad94c378 | 154 | |
42aacf6f | 155 | .globl _boothowto,_bootdev,_curpcb |
b2a82d1f | 156 | |
42aacf6f | 157 | .globl _cpu,_cold,_atdevbase |
57cfd936 RG |
158 | _cpu: .long 0 /* are we 386, 386sx, or 486 */ |
159 | _cold: .long 1 /* cold till we are not */ | |
160 | _atdevbase: .long 0 /* location of start of iomem in virtual */ | |
161 | _atdevphys: .long 0 /* location of device mapping ptes (phys) */ | |
15637ed4 | 162 | |
42aacf6f | 163 | .globl _IdlePTD,_KPTphys |
15637ed4 RG |
164 | _IdlePTD: .long 0 |
165 | _KPTphys: .long 0 | |
166 | ||
42aacf6f | 167 | .globl _cyloffset,_proc0paddr |
b2a82d1f DG |
168 | _cyloffset: .long 0 |
169 | _proc0paddr: .long 0 | |
170 | ||
15637ed4 RG |
171 | .space 512 |
172 | tmpstk: | |
b2a82d1f DG |
173 | |
174 | ||
ad94c378 RG |
175 | /* |
176 | * System Initialization | |
177 | */ | |
15637ed4 | 178 | .text |
b2a82d1f DG |
179 | |
180 | /* | |
dd18dc33 DG |
181 | * btext: beginning of text section. |
182 | * Also the entry point (jumped to directly from the boot blocks). | |
b2a82d1f | 183 | */ |
dd18dc33 | 184 | ENTRY(btext) |
57cfd936 | 185 | movw $0x1234,0x472 /* warm boot */ |
15637ed4 | 186 | jmp 1f |
57cfd936 | 187 | .space 0x500 /* skip over warm boot shit */ |
15637ed4 RG |
188 | |
189 | /* | |
ad94c378 | 190 | * pass parameters on stack (howto, bootdev, unit, cyloffset, esym) |
15637ed4 RG |
191 | * note: (%esp) is return address of boot |
192 | * ( if we want to hold onto /boot, it's physical %esp up to _end) | |
193 | */ | |
194 | ||
195 | 1: movl 4(%esp),%eax | |
57cfd936 | 196 | movl %eax,_boothowto-KERNBASE |
15637ed4 | 197 | movl 8(%esp),%eax |
57cfd936 | 198 | movl %eax,_bootdev-KERNBASE |
15637ed4 | 199 | movl 12(%esp),%eax |
57cfd936 | 200 | movl %eax,_cyloffset-KERNBASE |
ad94c378 | 201 | movl 16(%esp),%eax |
57cfd936 RG |
202 | addl $KERNBASE,%eax |
203 | movl %eax,_esym-KERNBASE | |
ad94c378 RG |
204 | |
205 | /* find out our CPU type. */ | |
206 | pushfl | |
207 | popl %eax | |
208 | movl %eax,%ecx | |
209 | xorl $0x40000,%eax | |
210 | pushl %eax | |
211 | popfl | |
212 | pushfl | |
213 | popl %eax | |
214 | xorl %ecx,%eax | |
215 | shrl $18,%eax | |
216 | andl $1,%eax | |
217 | push %ecx | |
218 | popfl | |
219 | ||
220 | cmpl $0,%eax | |
221 | jne 1f | |
57cfd936 | 222 | movl $CPU_386,_cpu-KERNBASE |
ad94c378 | 223 | jmp 2f |
57cfd936 | 224 | 1: movl $CPU_486,_cpu-KERNBASE |
ad94c378 | 225 | 2: |
15637ed4 RG |
226 | |
227 | /* | |
228 | * Finished with old stack; load new %esp now instead of later so | |
229 | * we can trace this code without having to worry about the trace | |
230 | * trap clobbering the memory test or the zeroing of the bss+bootstrap | |
231 | * page tables. | |
232 | * | |
233 | * XXX - wdboot clears the bss after testing that this is safe. | |
234 | * This is too wasteful - memory below 640K is scarce. The boot | |
235 | * program should check: | |
236 | * text+data <= &stack_variable - more_space_for_stack | |
237 | * text+data+bss+pad+space_for_page_tables <= end_of_memory | |
238 | * Oops, the gdt is in the carcass of the boot program so clearing | |
239 | * the rest of memory is still not possible. | |
240 | */ | |
57cfd936 | 241 | movl $tmpstk-KERNBASE,%esp /* bootstrap stack end location */ |
15637ed4 | 242 | |
57cfd936 RG |
243 | /* |
244 | * Virtual address space of kernel: | |
245 | * | |
246 | * text | data | bss | [syms] | page dir | proc0 kernel stack | usr stk map | Sysmap | |
247 | * 0 1 2 3 4 | |
248 | */ | |
249 | ||
15637ed4 | 250 | /* find end of kernel image */ |
57cfd936 RG |
251 | movl $_end-KERNBASE,%ecx |
252 | addl $NBPG-1,%ecx /* page align up */ | |
15637ed4 | 253 | andl $~(NBPG-1),%ecx |
57cfd936 | 254 | movl %ecx,%esi /* esi=start of tables */ |
15637ed4 RG |
255 | |
256 | /* clear bss and memory for bootstrap pagetables. */ | |
57cfd936 | 257 | movl $_edata-KERNBASE,%edi |
15637ed4 | 258 | subl %edi,%ecx |
57cfd936 RG |
259 | addl $(UPAGES+5)*NBPG,%ecx /* size of tables */ |
260 | ||
261 | xorl %eax,%eax /* pattern */ | |
15637ed4 RG |
262 | cld |
263 | rep | |
264 | stosb | |
265 | ||
18dbbd0c RG |
266 | /* |
267 | * If we are loaded at 0x0 check to see if we have space for the | |
268 | * page tables pages after the kernel and before the 640K ISA memory | |
269 | * hole. If we do not have space relocate the page table pages and | |
270 | * the kernel stack to start at 1MB. The value that ends up in esi | |
271 | * is used by the rest of locore to build the tables. Locore adjusts | |
272 | * esi each time it allocates a structure and then passes the final | |
273 | * value to init386(first) as the value first. esi should ALWAYS | |
274 | * be page aligned!! | |
275 | */ | |
276 | movl %esi,%ecx /* Get current first availiable address */ | |
277 | cmpl $0x100000,%ecx /* Lets see if we are already above 1MB */ | |
278 | jge 1f /* yep, don't need to check for room */ | |
279 | addl $(NKPDE + 4) * NBPG,%ecx /* XXX the 4 is for kstack */ | |
280 | /* space for kstack, PTD and PTE's */ | |
281 | cmpl $(640*1024),%ecx | |
282 | /* see if it fits in low memory */ | |
283 | jle 1f /* yep, don't need to relocate it */ | |
284 | movl $0x100000,%esi /* won't fit, so start it at 1MB */ | |
285 | 1: | |
286 | ||
57cfd936 RG |
287 | /* physical address of Idle Address space */ |
288 | movl %esi,_IdlePTD-KERNBASE | |
15637ed4 | 289 | |
42aacf6f RG |
290 | /* |
291 | * fillkpt | |
292 | * eax = (page frame address | control | status) == pte | |
293 | * ebx = address of page table | |
294 | * ecx = how many pages to map | |
295 | */ | |
15637ed4 RG |
296 | #define fillkpt \ |
297 | 1: movl %eax,(%ebx) ; \ | |
57cfd936 | 298 | addl $NBPG,%eax ; /* increment physical address */ \ |
15637ed4 RG |
299 | addl $4,%ebx ; /* next pte */ \ |
300 | loop 1b ; | |
301 | ||
302 | /* | |
303 | * Map Kernel | |
304 | * N.B. don't bother with making kernel text RO, as 386 | |
305 | * ignores R/W AND U/S bits on kernel access (only v works) ! | |
306 | * | |
307 | * First step - build page tables | |
308 | */ | |
57cfd936 RG |
309 | movl %esi,%ecx /* this much memory, */ |
310 | shrl $PGSHIFT,%ecx /* for this many pte s */ | |
311 | addl $UPAGES+4,%ecx /* including our early context */ | |
312 | cmpl $0xa0,%ecx /* XXX - cover debugger pages */ | |
dd18dc33 DG |
313 | jae 1f |
314 | movl $0xa0,%ecx | |
315 | 1: | |
57cfd936 RG |
316 | movl $PG_V|PG_KW,%eax /* having these bits set, */ |
317 | lea (4*NBPG)(%esi),%ebx /* physical address of KPT in proc 0, */ | |
318 | movl %ebx,_KPTphys-KERNBASE /* in the kernel page table, */ | |
15637ed4 RG |
319 | fillkpt |
320 | ||
321 | /* map I/O memory map */ | |
322 | ||
57cfd936 RG |
323 | movl $0x100-0xa0,%ecx /* for this many pte s, */ |
324 | movl $(0xa0000|PG_V|PG_UW),%eax /* having these bits set,(perhaps URW?) XXX 06 Aug 92 */ | |
325 | movl %ebx,_atdevphys-KERNBASE /* remember phys addr of ptes */ | |
15637ed4 RG |
326 | fillkpt |
327 | ||
328 | /* map proc 0's kernel stack into user page table page */ | |
329 | ||
57cfd936 RG |
330 | movl $UPAGES,%ecx /* for this many pte s, */ |
331 | lea (1*NBPG)(%esi),%eax /* physical address in proc 0 */ | |
332 | lea (KERNBASE)(%eax),%edx | |
42aacf6f RG |
333 | movl %edx,_proc0paddr-KERNBASE |
334 | /* remember VA for 0th process init */ | |
57cfd936 RG |
335 | orl $PG_V|PG_KW,%eax /* having these bits set, */ |
336 | lea (3*NBPG)(%esi),%ebx /* physical address of stack pt in proc 0 */ | |
15637ed4 RG |
337 | addl $(PPTEOFF*4),%ebx |
338 | fillkpt | |
339 | ||
340 | /* | |
341 | * Construct a page table directory | |
342 | * (of page directory elements - pde's) | |
343 | */ | |
344 | /* install a pde for temporary double map of bottom of VA */ | |
57cfd936 RG |
345 | lea (4*NBPG)(%esi),%eax /* physical address of kernel page table */ |
346 | orl $PG_V|PG_UW,%eax /* pde entry is valid XXX 06 Aug 92 */ | |
347 | movl %eax,(%esi) /* which is where temp maps! */ | |
15637ed4 RG |
348 | |
349 | /* kernel pde's */ | |
42aacf6f RG |
350 | movl $(NKPDE),%ecx /* for this many pde s, */ |
351 | lea (KPTDI*4)(%esi),%ebx /* offset of pde for kernel */ | |
15637ed4 RG |
352 | fillkpt |
353 | ||
354 | /* install a pde recursively mapping page directory as a page table! */ | |
57cfd936 RG |
355 | movl %esi,%eax /* phys address of ptd in proc 0 */ |
356 | orl $PG_V|PG_UW,%eax /* pde entry is valid XXX 06 Aug 92 */ | |
42aacf6f | 357 | movl %eax,PTDPTDI*4(%esi) /* which is where PTmap maps! */ |
15637ed4 RG |
358 | |
359 | /* install a pde to map kernel stack for proc 0 */ | |
57cfd936 RG |
360 | lea (3*NBPG)(%esi),%eax /* physical address of pt in proc 0 */ |
361 | orl $PG_V|PG_KW,%eax /* pde entry is valid */ | |
362 | movl %eax,PPDROFF*4(%esi) /* which is where kernel stack maps! */ | |
15637ed4 RG |
363 | |
364 | /* copy and convert stuff from old gdt and idt for debugger */ | |
365 | ||
57cfd936 | 366 | cmpl $0x0375c339,0x96104 /* XXX - debugger signature */ |
15637ed4 | 367 | jne 1f |
57cfd936 | 368 | movb $1,_bdb_exists-KERNBASE |
15637ed4 RG |
369 | 1: |
370 | pushal | |
371 | subl $2*6,%esp | |
372 | ||
373 | sgdt (%esp) | |
57cfd936 RG |
374 | movl 2(%esp),%esi /* base address of current gdt */ |
375 | movl $_gdt-KERNBASE,%edi | |
15637ed4 RG |
376 | movl %edi,2(%esp) |
377 | movl $8*18/4,%ecx | |
57cfd936 | 378 | rep /* copy gdt */ |
15637ed4 | 379 | movsl |
57cfd936 | 380 | movl $_gdt-KERNBASE,-8+2(%edi) /* adjust gdt self-ptr */ |
15637ed4 RG |
381 | movb $0x92,-8+5(%edi) |
382 | ||
383 | sidt 6(%esp) | |
57cfd936 RG |
384 | movl 6+2(%esp),%esi /* base address of current idt */ |
385 | movl 8+4(%esi),%eax /* convert dbg descriptor to ... */ | |
15637ed4 | 386 | movw 8(%esi),%ax |
57cfd936 | 387 | movl %eax,bdb_dbg_ljmp+1-KERNBASE /* ... immediate offset ... */ |
15637ed4 | 388 | movl 8+2(%esi),%eax |
57cfd936 RG |
389 | movw %ax,bdb_dbg_ljmp+5-KERNBASE /* ... and selector for ljmp */ |
390 | movl 24+4(%esi),%eax /* same for bpt descriptor */ | |
15637ed4 | 391 | movw 24(%esi),%ax |
57cfd936 | 392 | movl %eax,bdb_bpt_ljmp+1-KERNBASE |
15637ed4 | 393 | movl 24+2(%esi),%eax |
57cfd936 | 394 | movw %ax,bdb_bpt_ljmp+5-KERNBASE |
15637ed4 | 395 | |
57cfd936 | 396 | movl $_idt-KERNBASE,%edi |
15637ed4 RG |
397 | movl %edi,6+2(%esp) |
398 | movl $8*4/4,%ecx | |
57cfd936 | 399 | rep /* copy idt */ |
15637ed4 RG |
400 | movsl |
401 | ||
402 | lgdt (%esp) | |
403 | lidt 6(%esp) | |
404 | ||
405 | addl $2*6,%esp | |
406 | popal | |
407 | ||
42aacf6f | 408 | /* load base of page directory and enable mapping */ |
57cfd936 RG |
409 | movl %esi,%eax /* phys address of ptd in proc 0 */ |
410 | orl $I386_CR3PAT,%eax | |
411 | movl %eax,%cr3 /* load ptd addr into mmu */ | |
412 | movl %cr0,%eax /* get control word */ | |
dd18dc33 DG |
413 | /* |
414 | * XXX it is now safe to always (attempt to) set CR0_WP and to set up | |
415 | * the page tables assuming it works, so USE_486_WRITE_PROTECT will go | |
416 | * away. The special 386 PTE checking needs to be conditional on | |
417 | * whatever distingiushes 486-only kernels from 386-486 kernels. | |
418 | */ | |
15637ed4 | 419 | #ifdef USE_486_WRITE_PROTECT |
57cfd936 | 420 | orl $CR0_PE|CR0_PG|CR0_WP,%eax /* enable paging */ |
15637ed4 | 421 | #else |
57cfd936 | 422 | orl $CR0_PE|CR0_PG,%eax /* enable paging */ |
15637ed4 | 423 | #endif |
57cfd936 | 424 | movl %eax,%cr0 /* and let's page NOW! */ |
15637ed4 | 425 | |
57cfd936 | 426 | pushl $begin /* jump to high mem */ |
15637ed4 RG |
427 | ret |
428 | ||
57cfd936 | 429 | begin: /* now running relocated at KERNBASE where the system is linked to run */ |
15637ed4 | 430 | |
42aacf6f RG |
431 | .globl _Crtat /* XXX - locore should not know about */ |
432 | movl _Crtat,%eax /* variables of device drivers (pccons)! */ | |
433 | subl $(KERNBASE+0xA0000),%eax | |
57cfd936 RG |
434 | movl _atdevphys,%edx /* get pte PA */ |
435 | subl _KPTphys,%edx /* remove base of ptes, now have phys offset */ | |
436 | shll $PGSHIFT-2,%edx /* corresponding to virt offset */ | |
437 | addl $KERNBASE,%edx /* add virtual base */ | |
438 | movl %edx,_atdevbase | |
15637ed4 RG |
439 | addl %eax,%edx |
440 | movl %edx,_Crtat | |
441 | ||
442 | /* set up bootstrap stack */ | |
57cfd936 RG |
443 | movl $_kstack+UPAGES*NBPG-4*12,%esp /* bootstrap stack end location */ |
444 | xorl %eax,%eax /* mark end of frames */ | |
15637ed4 | 445 | movl %eax,%ebp |
57cfd936 RG |
446 | movl _proc0paddr,%eax |
447 | movl %esi,PCB_CR3(%eax) | |
15637ed4 | 448 | |
15637ed4 RG |
449 | /* relocate debugger gdt entries */ |
450 | ||
57cfd936 | 451 | movl $_gdt+8*9,%eax /* adjust slots 9-17 */ |
15637ed4 RG |
452 | movl $9,%ecx |
453 | reloc_gdt: | |
57cfd936 RG |
454 | movb $0xfe,7(%eax) /* top byte of base addresses, was 0, */ |
455 | addl $8,%eax /* now KERNBASE>>24 */ | |
15637ed4 RG |
456 | loop reloc_gdt |
457 | ||
458 | cmpl $0,_bdb_exists | |
459 | je 1f | |
460 | int $3 | |
461 | 1: | |
462 | ||
18dbbd0c RG |
463 | /* |
464 | * Skip over the page tables and the kernel stack | |
465 | * XXX 4 is kstack size | |
466 | */ | |
467 | lea (NKPDE + 4) * NBPG(%esi),%esi | |
468 | ||
469 | pushl %esi /* value of first for init386(first) */ | |
57cfd936 | 470 | call _init386 /* wire 386 chip for unix operation */ |
dd18dc33 | 471 | |
15637ed4 | 472 | movl $0,_PTD |
57cfd936 | 473 | call _main /* autoconfiguration, mountroot etc */ |
15637ed4 RG |
474 | popl %esi |
475 | ||
b2a82d1f | 476 | /* |
57cfd936 RG |
477 | * now we've run main() and determined what cpu-type we are, we can |
478 | * enable WP mode on i486 cpus and above. | |
b2a82d1f DG |
479 | * on return from main(), we are process 1 |
480 | * set up address space and stack so that we can 'return' to user mode | |
481 | */ | |
482 | ||
57cfd936 | 483 | .globl __ucodesel,__udatasel |
15637ed4 RG |
484 | movl __ucodesel,%eax |
485 | movl __udatasel,%ecx | |
57cfd936 RG |
486 | /* build outer stack frame */ |
487 | pushl %ecx /* user ss */ | |
488 | pushl $USRSTACK /* user esp */ | |
489 | pushl %eax /* user cs */ | |
490 | pushl $0 /* user ip */ | |
15637ed4 RG |
491 | movl %cx,%ds |
492 | movl %cx,%es | |
57cfd936 RG |
493 | movl %ax,%fs /* double map cs to fs */ |
494 | movl %cx,%gs /* and ds to gs */ | |
495 | lret /* goto user! */ | |
15637ed4 RG |
496 | |
497 | pushl $lretmsg1 /* "should never get here!" */ | |
498 | call _panic | |
499 | lretmsg1: | |
500 | .asciz "lret: toinit\n" | |
501 | ||
502 | ||
503 | .set exec,59 | |
504 | .set exit,1 | |
505 | ||
506 | #define LCALL(x,y) .byte 0x9a ; .long y; .word x | |
507 | /* | |
b2a82d1f DG |
508 | * Icode is copied out to process 1 and executed in user mode: |
509 | * execve("/sbin/init", argv, envp); exit(0); | |
dd18dc33 | 510 | * If the execve fails, process 1 exits and the system panics. |
15637ed4 | 511 | */ |
dd18dc33 | 512 | NON_GPROF_ENTRY(icode) |
57cfd936 | 513 | pushl $0 /* envp for execve() */ |
dd18dc33 | 514 | |
57cfd936 | 515 | # pushl $argv-_icode /* can't do this 'cos gas 1.38 is broken */ |
15637ed4 RG |
516 | movl $argv,%eax |
517 | subl $_icode,%eax | |
57cfd936 | 518 | pushl %eax /* argp for execve() */ |
15637ed4 | 519 | |
57cfd936 | 520 | # pushl $init-_icode |
15637ed4 RG |
521 | movl $init,%eax |
522 | subl $_icode,%eax | |
57cfd936 | 523 | pushl %eax /* fname for execve() */ |
15637ed4 | 524 | |
57cfd936 | 525 | pushl %eax /* dummy return address */ |
dd18dc33 | 526 | |
15637ed4 RG |
527 | movl $exec,%eax |
528 | LCALL(0x7,0x0) | |
dd18dc33 | 529 | |
57cfd936 RG |
530 | /* exit if something botches up in the above execve() */ |
531 | pushl %eax /* execve failed, the errno will do for an */ | |
532 | /* exit code because errnos are < 128 */ | |
533 | pushl %eax /* dummy return address */ | |
15637ed4 | 534 | movl $exit,%eax |
15637ed4 RG |
535 | LCALL(0x7,0x0) |
536 | ||
537 | init: | |
538 | .asciz "/sbin/init" | |
539 | ALIGN_DATA | |
540 | argv: | |
57cfd936 RG |
541 | .long init+6-_icode /* argv[0] = "init" ("/sbin/init" + 6) */ |
542 | .long eicode-_icode /* argv[1] follows icode after copyout */ | |
15637ed4 RG |
543 | .long 0 |
544 | eicode: | |
545 | ||
546 | .globl _szicode | |
547 | _szicode: | |
548 | .long _szicode-_icode | |
549 | ||
dd18dc33 | 550 | NON_GPROF_ENTRY(sigcode) |
42aacf6f RG |
551 | call SIGF_HANDLER(%esp) |
552 | lea SIGF_SC(%esp),%eax /* scp (the call may have clobbered the */ | |
553 | /* copy at 8(%esp)) */ | |
15637ed4 | 554 | pushl %eax |
57cfd936 | 555 | pushl %eax /* junk to fake return address */ |
42aacf6f | 556 | movl $103,%eax /* XXX sigreturn() */ |
57cfd936 RG |
557 | LCALL(0x7,0) /* enter kernel with args on stack */ |
558 | hlt /* never gets here */ | |
15637ed4 RG |
559 | |
560 | .globl _szsigcode | |
561 | _szsigcode: | |
562 | .long _szsigcode-_sigcode | |
563 | ||
57cfd936 RG |
564 | /* |
565 | * Support routines for GCC, general C-callable functions | |
566 | */ | |
15637ed4 RG |
567 | ENTRY(__udivsi3) |
568 | movl 4(%esp),%eax | |
569 | xorl %edx,%edx | |
570 | divl 8(%esp) | |
571 | ret | |
572 | ||
573 | ENTRY(__divsi3) | |
574 | movl 4(%esp),%eax | |
575 | cltd | |
576 | idivl 8(%esp) | |
577 | ret | |
578 | ||
579 | /* | |
580 | * I/O bus instructions via C | |
581 | */ | |
57cfd936 | 582 | ENTRY(inb) /* val = inb(port) */ |
15637ed4 | 583 | movl 4(%esp),%edx |
57cfd936 | 584 | subl %eax,%eax |
15637ed4 | 585 | NOP |
57cfd936 | 586 | inb %dx,%al |
15637ed4 RG |
587 | ret |
588 | ||
57cfd936 | 589 | ENTRY(inw) /* val = inw(port) */ |
15637ed4 | 590 | movl 4(%esp),%edx |
57cfd936 | 591 | subl %eax,%eax |
15637ed4 | 592 | NOP |
57cfd936 | 593 | inw %dx,%ax |
15637ed4 RG |
594 | ret |
595 | ||
57cfd936 RG |
596 | ENTRY(insb) /* insb(port, addr, cnt) */ |
597 | pushl %edi | |
b2a82d1f | 598 | movw 8(%esp),%dx |
57cfd936 | 599 | movl 12(%esp),%edi |
b2a82d1f DG |
600 | movl 16(%esp),%ecx |
601 | cld | |
602 | NOP | |
603 | rep | |
57cfd936 | 604 | insb |
b2a82d1f | 605 | NOP |
57cfd936 RG |
606 | movl %edi,%eax |
607 | popl %edi | |
b2a82d1f DG |
608 | ret |
609 | ||
57cfd936 RG |
610 | ENTRY(insw) /* insw(port, addr, cnt) */ |
611 | pushl %edi | |
b2a82d1f | 612 | movw 8(%esp),%dx |
57cfd936 | 613 | movl 12(%esp),%edi |
b2a82d1f DG |
614 | movl 16(%esp),%ecx |
615 | cld | |
616 | NOP | |
617 | rep | |
57cfd936 | 618 | insw |
b2a82d1f | 619 | NOP |
57cfd936 RG |
620 | movl %edi,%eax |
621 | popl %edi | |
b2a82d1f DG |
622 | ret |
623 | ||
57cfd936 RG |
624 | ENTRY(rtcin) /* rtcin(val) */ |
625 | movl 4(%esp),%eax | |
626 | outb %al,$0x70 | |
627 | subl %eax,%eax | |
628 | inb $0x71,%al | |
629 | ret | |
b2a82d1f | 630 | |
57cfd936 | 631 | ENTRY(outb) /* outb(port, val) */ |
b2a82d1f | 632 | movl 4(%esp),%edx |
b2a82d1f | 633 | NOP |
57cfd936 RG |
634 | movl 8(%esp),%eax |
635 | outb %al,%dx | |
636 | NOP | |
15637ed4 RG |
637 | ret |
638 | ||
57cfd936 | 639 | ENTRY(outw) /* outw(port, val) */ |
15637ed4 RG |
640 | movl 4(%esp),%edx |
641 | NOP | |
57cfd936 RG |
642 | movl 8(%esp),%eax |
643 | outw %ax,%dx | |
644 | NOP | |
b2a82d1f DG |
645 | ret |
646 | ||
57cfd936 RG |
647 | ENTRY(outsb) /* outsb(port, addr, cnt) */ |
648 | pushl %esi | |
b2a82d1f | 649 | movw 8(%esp),%dx |
57cfd936 | 650 | movl 12(%esp),%esi |
b2a82d1f DG |
651 | movl 16(%esp),%ecx |
652 | cld | |
15637ed4 | 653 | NOP |
b2a82d1f | 654 | rep |
57cfd936 | 655 | outsb |
b2a82d1f | 656 | NOP |
57cfd936 RG |
657 | movl %esi,%eax |
658 | popl %esi | |
15637ed4 RG |
659 | ret |
660 | ||
57cfd936 RG |
661 | ENTRY(outsw) /* outsw(port, addr, cnt) */ |
662 | pushl %esi | |
b2a82d1f | 663 | movw 8(%esp),%dx |
57cfd936 | 664 | movl 12(%esp),%esi |
b2a82d1f DG |
665 | movl 16(%esp),%ecx |
666 | cld | |
15637ed4 | 667 | NOP |
b2a82d1f | 668 | rep |
57cfd936 | 669 | outsw |
15637ed4 | 670 | NOP |
57cfd936 RG |
671 | movl %esi,%eax |
672 | popl %esi | |
15637ed4 RG |
673 | ret |
674 | ||
675 | /* | |
b2a82d1f | 676 | * bcopy family |
15637ed4 | 677 | */ |
57cfd936 | 678 | ENTRY(bzero) /* void bzero(void *base, u_int cnt) */ |
15637ed4 RG |
679 | pushl %edi |
680 | movl 8(%esp),%edi | |
681 | movl 12(%esp),%ecx | |
682 | xorl %eax,%eax | |
dd18dc33 | 683 | shrl $2,%ecx |
15637ed4 RG |
684 | cld |
685 | rep | |
686 | stosl | |
687 | movl 12(%esp),%ecx | |
688 | andl $3,%ecx | |
689 | rep | |
690 | stosb | |
691 | popl %edi | |
692 | ret | |
693 | ||
57cfd936 | 694 | ENTRY(fillw) /* fillw(pat, base, cnt) */ |
15637ed4 RG |
695 | pushl %edi |
696 | movl 8(%esp),%eax | |
697 | movl 12(%esp),%edi | |
698 | movl 16(%esp),%ecx | |
699 | cld | |
700 | rep | |
701 | stosw | |
702 | popl %edi | |
703 | ret | |
704 | ||
705 | ENTRY(bcopyb) | |
dd18dc33 | 706 | bcopyb: |
15637ed4 RG |
707 | pushl %esi |
708 | pushl %edi | |
709 | movl 12(%esp),%esi | |
710 | movl 16(%esp),%edi | |
711 | movl 20(%esp),%ecx | |
712 | cmpl %esi,%edi /* potentially overlapping? */ | |
713 | jnb 1f | |
714 | cld /* nope, copy forwards */ | |
dd18dc33 | 715 | rep |
15637ed4 RG |
716 | movsb |
717 | popl %edi | |
718 | popl %esi | |
719 | ret | |
720 | ||
721 | ALIGN_TEXT | |
722 | 1: | |
723 | addl %ecx,%edi /* copy backwards. */ | |
724 | addl %ecx,%esi | |
725 | std | |
726 | decl %edi | |
727 | decl %esi | |
728 | rep | |
729 | movsb | |
730 | popl %edi | |
731 | popl %esi | |
732 | cld | |
733 | ret | |
734 | ||
735 | ENTRY(bcopyw) | |
dd18dc33 | 736 | bcopyw: |
15637ed4 RG |
737 | pushl %esi |
738 | pushl %edi | |
739 | movl 12(%esp),%esi | |
740 | movl 16(%esp),%edi | |
741 | movl 20(%esp),%ecx | |
742 | cmpl %esi,%edi /* potentially overlapping? */ | |
743 | jnb 1f | |
744 | cld /* nope, copy forwards */ | |
745 | shrl $1,%ecx /* copy by 16-bit words */ | |
746 | rep | |
747 | movsw | |
748 | adc %ecx,%ecx /* any bytes left? */ | |
749 | rep | |
750 | movsb | |
751 | popl %edi | |
752 | popl %esi | |
753 | ret | |
754 | ||
755 | ALIGN_TEXT | |
756 | 1: | |
757 | addl %ecx,%edi /* copy backwards */ | |
758 | addl %ecx,%esi | |
759 | std | |
760 | andl $1,%ecx /* any fractional bytes? */ | |
761 | decl %edi | |
762 | decl %esi | |
763 | rep | |
764 | movsb | |
765 | movl 20(%esp),%ecx /* copy remainder by 16-bit words */ | |
766 | shrl $1,%ecx | |
767 | decl %esi | |
768 | decl %edi | |
769 | rep | |
770 | movsw | |
771 | popl %edi | |
772 | popl %esi | |
773 | cld | |
774 | ret | |
775 | ||
776 | ENTRY(bcopyx) | |
777 | movl 16(%esp),%eax | |
778 | cmpl $2,%eax | |
dd18dc33 | 779 | je bcopyw /* not _bcopyw, to avoid multiple mcounts */ |
15637ed4 | 780 | cmpl $4,%eax |
dd18dc33 DG |
781 | je bcopy |
782 | jmp bcopyb | |
b2a82d1f | 783 | |
15637ed4 | 784 | /* |
57cfd936 | 785 | * (ov)bcopy(src, dst, cnt) |
15637ed4 | 786 | * ws@tools.de (Wolfgang Solfrank, TooLs GmbH) +49-228-985800 |
15637ed4 | 787 | */ |
b2a82d1f | 788 | ALTENTRY(ovbcopy) |
dd18dc33 DG |
789 | ENTRY(bcopy) |
790 | bcopy: | |
15637ed4 RG |
791 | pushl %esi |
792 | pushl %edi | |
793 | movl 12(%esp),%esi | |
794 | movl 16(%esp),%edi | |
795 | movl 20(%esp),%ecx | |
796 | cmpl %esi,%edi /* potentially overlapping? */ | |
797 | jnb 1f | |
798 | cld /* nope, copy forwards */ | |
799 | shrl $2,%ecx /* copy by 32-bit words */ | |
800 | rep | |
801 | movsl | |
802 | movl 20(%esp),%ecx | |
803 | andl $3,%ecx /* any bytes left? */ | |
804 | rep | |
805 | movsb | |
806 | popl %edi | |
807 | popl %esi | |
808 | ret | |
809 | ||
810 | ALIGN_TEXT | |
811 | 1: | |
812 | addl %ecx,%edi /* copy backwards */ | |
813 | addl %ecx,%esi | |
814 | std | |
815 | andl $3,%ecx /* any fractional bytes? */ | |
816 | decl %edi | |
817 | decl %esi | |
818 | rep | |
819 | movsb | |
820 | movl 20(%esp),%ecx /* copy remainder by 32-bit words */ | |
821 | shrl $2,%ecx | |
822 | subl $3,%esi | |
823 | subl $3,%edi | |
824 | rep | |
825 | movsl | |
826 | popl %edi | |
827 | popl %esi | |
828 | cld | |
829 | ret | |
830 | ||
dd18dc33 DG |
831 | ALTENTRY(ntohl) |
832 | ENTRY(htonl) | |
b2a82d1f DG |
833 | movl 4(%esp),%eax |
834 | #ifdef i486 | |
835 | /* XXX */ | |
836 | /* Since Gas 1.38 does not grok bswap this has been coded as the | |
837 | * equivalent bytes. This can be changed back to bswap when we | |
838 | * upgrade to a newer version of Gas */ | |
839 | /* bswap %eax */ | |
dd18dc33 | 840 | .byte 0x0f |
b2a82d1f DG |
841 | .byte 0xc8 |
842 | #else | |
843 | xchgb %al,%ah | |
844 | roll $16,%eax | |
845 | xchgb %al,%ah | |
846 | #endif | |
847 | ret | |
848 | ||
dd18dc33 DG |
849 | ALTENTRY(ntohs) |
850 | ENTRY(htons) | |
b2a82d1f DG |
851 | movzwl 4(%esp),%eax |
852 | xchgb %al,%ah | |
853 | ret | |
854 | ||
b2a82d1f DG |
855 | /*****************************************************************************/ |
856 | /* copyout and fubyte family */ | |
857 | /*****************************************************************************/ | |
858 | /* | |
859 | * Access user memory from inside the kernel. These routines and possibly | |
860 | * the math- and DOS emulators should be the only places that do this. | |
861 | * | |
862 | * We have to access the memory with user's permissions, so use a segment | |
863 | * selector with RPL 3. For writes to user space we have to additionally | |
864 | * check the PTE for write permission, because the 386 does not check | |
865 | * write permissions when we are executing with EPL 0. The 486 does check | |
866 | * this if the WP bit is set in CR0, so we can use a simpler version here. | |
867 | * | |
868 | * These routines set curpcb->onfault for the time they execute. When a | |
869 | * protection violation occurs inside the functions, the trap handler | |
870 | * returns to *curpcb->onfault instead of the function. | |
871 | */ | |
b2a82d1f DG |
872 | |
873 | ||
57cfd936 RG |
874 | ENTRY(copyout) /* copyout(from_kernel, to_user, len) */ |
875 | movl _curpcb,%eax | |
876 | movl $copyout_fault,PCB_ONFAULT(%eax) | |
15637ed4 RG |
877 | pushl %esi |
878 | pushl %edi | |
879 | pushl %ebx | |
57cfd936 RG |
880 | movl 16(%esp),%esi |
881 | movl 20(%esp),%edi | |
882 | movl 24(%esp),%ebx | |
883 | orl %ebx,%ebx /* anything to do? */ | |
b2a82d1f | 884 | jz done_copyout |
15637ed4 | 885 | |
dd18dc33 DG |
886 | /* |
887 | * Check explicitly for non-user addresses. If 486 write protection | |
888 | * is being used, this check is essential because we are in kernel | |
889 | * mode so the h/w does not provide any protection against writing | |
890 | * kernel addresses. | |
891 | * | |
892 | * Otherwise, it saves having to load and restore %es to get the | |
893 | * usual segment-based protection (the destination segment for movs | |
894 | * is always %es). The other explicit checks for user-writablility | |
895 | * are not quite sufficient. They fail for the user area because | |
896 | * we mapped the user area read/write to avoid having an #ifdef in | |
897 | * vm_machdep.c. They fail for user PTEs and/or PTDs! (107 | |
898 | * addresses including 0xff800000 and 0xfc000000). I'm not sure if | |
899 | * this can be fixed. Marking the PTEs supervisor mode and the | |
900 | * PDE's user mode would almost work, but there may be a problem | |
901 | * with the self-referential PDE. | |
902 | */ | |
57cfd936 RG |
903 | movl %edi,%eax |
904 | addl %ebx,%eax | |
dd18dc33 DG |
905 | jc copyout_fault |
906 | #define VM_END_USER_ADDRESS 0xFDBFE000 /* XXX */ | |
57cfd936 | 907 | cmpl $VM_END_USER_ADDRESS,%eax |
dd18dc33 | 908 | ja copyout_fault |
b2a82d1f | 909 | |
dd18dc33 DG |
910 | #ifndef USE_486_WRITE_PROTECT |
911 | /* | |
912 | * We have to check each PTE for user write permission. | |
913 | * The checking may cause a page fault, so it is important to set | |
914 | * up everything for return via copyout_fault before here. | |
915 | */ | |
b2a82d1f | 916 | /* compute number of pages */ |
57cfd936 RG |
917 | movl %edi,%ecx |
918 | andl $NBPG-1,%ecx | |
919 | addl %ebx,%ecx | |
b2a82d1f | 920 | decl %ecx |
57cfd936 | 921 | shrl $IDXSHIFT+2,%ecx |
b2a82d1f DG |
922 | incl %ecx |
923 | ||
924 | /* compute PTE offset for start address */ | |
57cfd936 RG |
925 | movl %edi,%edx |
926 | shrl $IDXSHIFT,%edx | |
927 | andb $0xfc,%dl | |
15637ed4 | 928 | |
b2a82d1f | 929 | 1: /* check PTE for each page */ |
57cfd936 RG |
930 | movb _PTmap(%edx),%al |
931 | andb $0x07,%al /* Pages must be VALID + USERACC + WRITABLE */ | |
932 | cmpb $0x07,%al | |
b2a82d1f | 933 | je 2f |
dd18dc33 | 934 | |
b2a82d1f DG |
935 | /* simulate a trap */ |
936 | pushl %edx | |
937 | pushl %ecx | |
57cfd936 | 938 | shll $IDXSHIFT,%edx |
b2a82d1f | 939 | pushl %edx |
57cfd936 | 940 | call _trapwrite /* trapwrite(addr) */ |
b2a82d1f DG |
941 | popl %edx |
942 | popl %ecx | |
15637ed4 RG |
943 | popl %edx |
944 | ||
57cfd936 | 945 | orl %eax,%eax /* if not ok, return EFAULT */ |
b2a82d1f DG |
946 | jnz copyout_fault |
947 | ||
15637ed4 | 948 | 2: |
57cfd936 | 949 | addl $4,%edx |
b2a82d1f DG |
950 | decl %ecx |
951 | jnz 1b /* check next page */ | |
dd18dc33 | 952 | #endif /* ndef USE_486_WRITE_PROTECT */ |
b2a82d1f | 953 | |
57cfd936 | 954 | /* bcopy(%esi, %edi, %ebx) */ |
15637ed4 | 955 | cld |
57cfd936 RG |
956 | movl %ebx,%ecx |
957 | shrl $2,%ecx | |
15637ed4 RG |
958 | rep |
959 | movsl | |
57cfd936 RG |
960 | movb %bl,%cl |
961 | andb $3,%cl /* XXX can we trust the rest of %ecx on clones? */ | |
15637ed4 RG |
962 | rep |
963 | movsb | |
15637ed4 | 964 | |
b2a82d1f | 965 | done_copyout: |
15637ed4 RG |
966 | popl %ebx |
967 | popl %edi | |
968 | popl %esi | |
969 | xorl %eax,%eax | |
970 | movl _curpcb,%edx | |
971 | movl %eax,PCB_ONFAULT(%edx) | |
972 | ret | |
973 | ||
dd18dc33 | 974 | ALIGN_TEXT |
b2a82d1f | 975 | copyout_fault: |
15637ed4 RG |
976 | popl %ebx |
977 | popl %edi | |
978 | popl %esi | |
57cfd936 RG |
979 | movl _curpcb,%edx |
980 | movl $0,PCB_ONFAULT(%edx) | |
981 | movl $EFAULT,%eax | |
15637ed4 RG |
982 | ret |
983 | ||
57cfd936 | 984 | ENTRY(copyin) /* copyin(from_user, to_kernel, len) */ |
15637ed4 | 985 | movl _curpcb,%eax |
57cfd936 | 986 | movl $copyin_fault,PCB_ONFAULT(%eax) |
15637ed4 RG |
987 | pushl %esi |
988 | pushl %edi | |
57cfd936 RG |
989 | movl 12(%esp),%esi /* caddr_t from */ |
990 | movl 16(%esp),%edi /* caddr_t to */ | |
991 | movl 20(%esp),%ecx /* size_t len */ | |
b2a82d1f DG |
992 | |
993 | movb %cl,%al | |
57cfd936 | 994 | shrl $2,%ecx /* copy longword-wise */ |
15637ed4 | 995 | cld |
dd18dc33 | 996 | gs |
15637ed4 RG |
997 | rep |
998 | movsl | |
b2a82d1f | 999 | movb %al,%cl |
57cfd936 | 1000 | andb $3,%cl /* copy remaining bytes */ |
dd18dc33 | 1001 | gs |
15637ed4 RG |
1002 | rep |
1003 | movsb | |
b2a82d1f | 1004 | |
15637ed4 RG |
1005 | popl %edi |
1006 | popl %esi | |
57cfd936 RG |
1007 | xorl %eax,%eax |
1008 | movl _curpcb,%edx | |
1009 | movl %eax,PCB_ONFAULT(%edx) | |
15637ed4 RG |
1010 | ret |
1011 | ||
dd18dc33 | 1012 | ALIGN_TEXT |
b2a82d1f | 1013 | copyin_fault: |
15637ed4 RG |
1014 | popl %edi |
1015 | popl %esi | |
57cfd936 RG |
1016 | movl _curpcb,%edx |
1017 | movl $0,PCB_ONFAULT(%edx) | |
1018 | movl $EFAULT,%eax | |
b2a82d1f DG |
1019 | ret |
1020 | ||
1021 | /* | |
57cfd936 | 1022 | * fu{byte,sword,word} : fetch a byte(sword, word) from user memory |
b2a82d1f | 1023 | */ |
b2a82d1f | 1024 | ALTENTRY(fuiword) |
dd18dc33 | 1025 | ENTRY(fuword) |
b2a82d1f DG |
1026 | movl _curpcb,%ecx |
1027 | movl $fusufault,PCB_ONFAULT(%ecx) | |
1028 | movl 4(%esp),%edx | |
1029 | gs | |
1030 | movl (%edx),%eax | |
1031 | movl $0,PCB_ONFAULT(%ecx) | |
1032 | ret | |
dd18dc33 | 1033 | |
b2a82d1f | 1034 | ENTRY(fusword) |
b2a82d1f DG |
1035 | movl _curpcb,%ecx |
1036 | movl $fusufault,PCB_ONFAULT(%ecx) | |
1037 | movl 4(%esp),%edx | |
1038 | gs | |
1039 | movzwl (%edx),%eax | |
1040 | movl $0,PCB_ONFAULT(%ecx) | |
1041 | ret | |
dd18dc33 | 1042 | |
b2a82d1f | 1043 | ALTENTRY(fuibyte) |
dd18dc33 | 1044 | ENTRY(fubyte) |
b2a82d1f DG |
1045 | movl _curpcb,%ecx |
1046 | movl $fusufault,PCB_ONFAULT(%ecx) | |
1047 | movl 4(%esp),%edx | |
1048 | gs | |
1049 | movzbl (%edx),%eax | |
1050 | movl $0,PCB_ONFAULT(%ecx) | |
1051 | ret | |
dd18dc33 DG |
1052 | |
1053 | ALIGN_TEXT | |
b2a82d1f DG |
1054 | fusufault: |
1055 | movl _curpcb,%ecx | |
15637ed4 | 1056 | xorl %eax,%eax |
b2a82d1f DG |
1057 | movl %eax,PCB_ONFAULT(%ecx) |
1058 | decl %eax | |
15637ed4 RG |
1059 | ret |
1060 | ||
b2a82d1f | 1061 | /* |
57cfd936 | 1062 | * su{byte,sword,word}: write a byte(word, longword) to user memory |
b2a82d1f DG |
1063 | */ |
1064 | #ifdef USE_486_WRITE_PROTECT | |
1065 | /* | |
1066 | * we only have to set the right segment selector. | |
1067 | */ | |
b2a82d1f | 1068 | ALTENTRY(suiword) |
dd18dc33 | 1069 | ENTRY(suword) |
b2a82d1f DG |
1070 | movl _curpcb,%ecx |
1071 | movl $fusufault,PCB_ONFAULT(%ecx) | |
1072 | movl 4(%esp),%edx | |
1073 | movl 8(%esp),%eax | |
1074 | gs | |
1075 | movl %eax,(%edx) | |
dd18dc33 DG |
1076 | xorl %eax,%eax |
1077 | movl %eax,PCB_ONFAULT(%ecx) | |
b2a82d1f | 1078 | ret |
dd18dc33 | 1079 | |
b2a82d1f | 1080 | ENTRY(susword) |
b2a82d1f DG |
1081 | movl _curpcb,%ecx |
1082 | movl $fusufault,PCB_ONFAULT(%ecx) | |
1083 | movl 4(%esp),%edx | |
1084 | movw 8(%esp),%ax | |
1085 | gs | |
1086 | movw %ax,(%edx) | |
dd18dc33 DG |
1087 | xorl %eax,%eax |
1088 | movl %eax,PCB_ONFAULT(%ecx) | |
b2a82d1f | 1089 | ret |
dd18dc33 | 1090 | |
b2a82d1f | 1091 | ALTENTRY(suibyte) |
dd18dc33 | 1092 | ENTRY(subyte) |
b2a82d1f DG |
1093 | movl _curpcb,%ecx |
1094 | movl $fusufault,PCB_ONFAULT(%ecx) | |
1095 | movl 4(%esp),%edx | |
1096 | movb 8(%esp),%al | |
1097 | gs | |
1098 | movb %al,(%edx) | |
dd18dc33 DG |
1099 | xorl %eax,%eax |
1100 | movl %eax,PCB_ONFAULT(%ecx) | |
b2a82d1f DG |
1101 | ret |
1102 | ||
1103 | ||
1104 | #else /* USE_486_WRITE_PROTECT */ | |
1105 | /* | |
1106 | * here starts the trouble again: check PTE, twice if word crosses | |
1107 | * a page boundary. | |
1108 | */ | |
57cfd936 | 1109 | /* XXX - page boundary crossing is not handled yet */ |
b2a82d1f | 1110 | |
dd18dc33 | 1111 | ALTENTRY(suibyte) |
b2a82d1f | 1112 | ENTRY(subyte) |
57cfd936 RG |
1113 | movl _curpcb,%ecx |
1114 | movl $fusufault,PCB_ONFAULT(%ecx) | |
1115 | movl 4(%esp),%edx | |
1116 | movl %edx,%eax | |
1117 | shrl $IDXSHIFT,%edx | |
1118 | andb $0xfc,%dl | |
1119 | movb _PTmap(%edx),%dl | |
1120 | andb $0x7,%dl /* must be VALID + USERACC + WRITE */ | |
1121 | cmpb $0x7,%dl | |
b2a82d1f DG |
1122 | je 1f |
1123 | /* simulate a trap */ | |
1124 | pushl %eax | |
1125 | call _trapwrite | |
1126 | popl %edx | |
57cfd936 | 1127 | orl %eax,%eax |
b2a82d1f DG |
1128 | jnz fusufault |
1129 | 1: | |
57cfd936 RG |
1130 | movl 4(%esp),%edx |
1131 | movl 8(%esp),%eax | |
dd18dc33 | 1132 | gs |
57cfd936 RG |
1133 | movb %al,(%edx) |
1134 | xorl %eax,%eax | |
1135 | movl _curpcb,%ecx | |
1136 | movl %eax,PCB_ONFAULT(%ecx) | |
b2a82d1f DG |
1137 | ret |
1138 | ||
1139 | ENTRY(susword) | |
57cfd936 RG |
1140 | movl _curpcb,%ecx |
1141 | movl $fusufault,PCB_ONFAULT(%ecx) | |
1142 | movl 4(%esp),%edx | |
1143 | movl %edx,%eax | |
1144 | shrl $IDXSHIFT,%edx | |
1145 | andb $0xfc,%dl | |
1146 | movb _PTmap(%edx),%dl | |
1147 | andb $0x7,%dl /* must be VALID + USERACC + WRITE */ | |
1148 | cmpb $0x7,%dl | |
b2a82d1f DG |
1149 | je 1f |
1150 | /* simulate a trap */ | |
1151 | pushl %eax | |
1152 | call _trapwrite | |
1153 | popl %edx | |
57cfd936 | 1154 | orl %eax,%eax |
b2a82d1f DG |
1155 | jnz fusufault |
1156 | 1: | |
57cfd936 RG |
1157 | movl 4(%esp),%edx |
1158 | movl 8(%esp),%eax | |
dd18dc33 | 1159 | gs |
57cfd936 RG |
1160 | movw %ax,(%edx) |
1161 | xorl %eax,%eax | |
1162 | movl _curpcb,%ecx | |
1163 | movl %eax,PCB_ONFAULT(%ecx) | |
b2a82d1f DG |
1164 | ret |
1165 | ||
dd18dc33 | 1166 | ALTENTRY(suiword) |
b2a82d1f | 1167 | ENTRY(suword) |
57cfd936 RG |
1168 | movl _curpcb,%ecx |
1169 | movl $fusufault,PCB_ONFAULT(%ecx) | |
1170 | movl 4(%esp),%edx | |
1171 | movl %edx,%eax | |
1172 | shrl $IDXSHIFT,%edx | |
1173 | andb $0xfc,%dl | |
1174 | movb _PTmap(%edx),%dl | |
1175 | andb $0x7,%dl /* must be VALID + USERACC + WRITE */ | |
1176 | cmpb $0x7,%dl | |
b2a82d1f DG |
1177 | je 1f |
1178 | /* simulate a trap */ | |
1179 | pushl %eax | |
1180 | call _trapwrite | |
1181 | popl %edx | |
57cfd936 | 1182 | orl %eax,%eax |
b2a82d1f DG |
1183 | jnz fusufault |
1184 | 1: | |
57cfd936 RG |
1185 | movl 4(%esp),%edx |
1186 | movl 8(%esp),%eax | |
dd18dc33 | 1187 | gs |
57cfd936 RG |
1188 | movl %eax,0(%edx) |
1189 | xorl %eax,%eax | |
1190 | movl _curpcb,%ecx | |
1191 | movl %eax,PCB_ONFAULT(%ecx) | |
15637ed4 RG |
1192 | ret |
1193 | ||
b2a82d1f | 1194 | #endif /* USE_486_WRITE_PROTECT */ |
dd18dc33 | 1195 | |
b2a82d1f DG |
1196 | /* |
1197 | * copyoutstr(from, to, maxlen, int *lencopied) | |
1198 | * copy a string from from to to, stop when a 0 character is reached. | |
1199 | * return ENAMETOOLONG if string is longer than maxlen, and | |
1200 | * EFAULT on protection violations. If lencopied is non-zero, | |
1201 | * return the actual length in *lencopied. | |
1202 | */ | |
1203 | #ifdef USE_486_WRITE_PROTECT | |
1204 | ||
1205 | ENTRY(copyoutstr) | |
1206 | pushl %esi | |
1207 | pushl %edi | |
57cfd936 RG |
1208 | movl _curpcb,%ecx |
1209 | movl $cpystrflt,PCB_ONFAULT(%ecx) | |
b2a82d1f | 1210 | |
57cfd936 RG |
1211 | movl 12(%esp),%esi /* %esi = from */ |
1212 | movl 16(%esp),%edi /* %edi = to */ | |
1213 | movl 20(%esp),%edx /* %edx = maxlen */ | |
b2a82d1f | 1214 | incl %edx |
15637ed4 | 1215 | |
b2a82d1f DG |
1216 | 1: |
1217 | decl %edx | |
1218 | jz 4f | |
dd18dc33 DG |
1219 | /* |
1220 | * gs override doesn't work for stosb. Use the same explicit check | |
1221 | * as in copyout(). It's much slower now because it is per-char. | |
1222 | * XXX - however, it would be faster to rewrite this function to use | |
1223 | * strlen() and copyout(). | |
1224 | */ | |
57cfd936 | 1225 | cmpl $VM_END_USER_ADDRESS,%edi |
dd18dc33 | 1226 | jae cpystrflt |
b2a82d1f DG |
1227 | lodsb |
1228 | gs | |
1229 | stosb | |
1230 | orb %al,%al | |
1231 | jnz 1b | |
1232 | /* Success -- 0 byte reached */ | |
1233 | decl %edx | |
57cfd936 | 1234 | xorl %eax,%eax |
b2a82d1f DG |
1235 | jmp 6f |
1236 | 4: | |
1237 | /* edx is zero -- return ENAMETOOLONG */ | |
57cfd936 | 1238 | movl $ENAMETOOLONG,%eax |
b2a82d1f DG |
1239 | jmp 6f |
1240 | ||
dd18dc33 | 1241 | #else /* ndef USE_486_WRITE_PROTECT */ |
b2a82d1f DG |
1242 | |
1243 | ENTRY(copyoutstr) | |
1244 | pushl %esi | |
15637ed4 | 1245 | pushl %edi |
57cfd936 RG |
1246 | movl _curpcb,%ecx |
1247 | movl $cpystrflt,PCB_ONFAULT(%ecx) | |
b2a82d1f | 1248 | |
57cfd936 RG |
1249 | movl 12(%esp),%esi /* %esi = from */ |
1250 | movl 16(%esp),%edi /* %edi = to */ | |
1251 | movl 20(%esp),%edx /* %edx = maxlen */ | |
b2a82d1f | 1252 | 1: |
dd18dc33 DG |
1253 | /* |
1254 | * It suffices to check that the first byte is in user space, because | |
1255 | * we look at a page at a time and the end address is on a page | |
1256 | * boundary. | |
1257 | */ | |
57cfd936 | 1258 | cmpl $VM_END_USER_ADDRESS,%edi |
dd18dc33 | 1259 | jae cpystrflt |
57cfd936 RG |
1260 | movl %edi,%eax |
1261 | shrl $IDXSHIFT,%eax | |
1262 | andb $0xfc,%al | |
1263 | movb _PTmap(%eax),%al | |
1264 | andb $7,%al | |
1265 | cmpb $7,%al | |
b2a82d1f | 1266 | je 2f |
15637ed4 | 1267 | |
b2a82d1f DG |
1268 | /* simulate trap */ |
1269 | pushl %edx | |
15637ed4 | 1270 | pushl %edi |
b2a82d1f | 1271 | call _trapwrite |
15637ed4 | 1272 | popl %edi |
b2a82d1f | 1273 | popl %edx |
57cfd936 | 1274 | orl %eax,%eax |
b2a82d1f DG |
1275 | jnz cpystrflt |
1276 | ||
1277 | 2: /* copy up to end of this page */ | |
57cfd936 RG |
1278 | movl %edi,%eax |
1279 | andl $NBPG-1,%eax | |
1280 | movl $NBPG,%ecx | |
1281 | subl %eax,%ecx /* ecx = NBPG - (src % NBPG) */ | |
1282 | cmpl %ecx,%edx | |
b2a82d1f | 1283 | jge 3f |
57cfd936 | 1284 | movl %edx,%ecx /* ecx = min(ecx, edx) */ |
b2a82d1f | 1285 | 3: |
57cfd936 | 1286 | orl %ecx,%ecx |
b2a82d1f DG |
1287 | jz 4f |
1288 | decl %ecx | |
1289 | decl %edx | |
1290 | lodsb | |
1291 | stosb | |
57cfd936 | 1292 | orb %al,%al |
b2a82d1f DG |
1293 | jnz 3b |
1294 | ||
1295 | /* Success -- 0 byte reached */ | |
1296 | decl %edx | |
57cfd936 | 1297 | xorl %eax,%eax |
b2a82d1f DG |
1298 | jmp 6f |
1299 | ||
1300 | 4: /* next page */ | |
57cfd936 | 1301 | orl %edx,%edx |
b2a82d1f DG |
1302 | jnz 1b |
1303 | /* edx is zero -- return ENAMETOOLONG */ | |
57cfd936 | 1304 | movl $ENAMETOOLONG,%eax |
b2a82d1f | 1305 | jmp 6f |
dd18dc33 | 1306 | |
b2a82d1f | 1307 | #endif /* USE_486_WRITE_PROTECT */ |
15637ed4 | 1308 | |
b2a82d1f DG |
1309 | /* |
1310 | * copyinstr(from, to, maxlen, int *lencopied) | |
1311 | * copy a string from from to to, stop when a 0 character is reached. | |
1312 | * return ENAMETOOLONG if string is longer than maxlen, and | |
1313 | * EFAULT on protection violations. If lencopied is non-zero, | |
1314 | * return the actual length in *lencopied. | |
1315 | */ | |
1316 | ENTRY(copyinstr) | |
15637ed4 | 1317 | pushl %esi |
b2a82d1f | 1318 | pushl %edi |
57cfd936 RG |
1319 | movl _curpcb,%ecx |
1320 | movl $cpystrflt,PCB_ONFAULT(%ecx) | |
b2a82d1f | 1321 | |
57cfd936 RG |
1322 | movl 12(%esp),%esi /* %esi = from */ |
1323 | movl 16(%esp),%edi /* %edi = to */ | |
1324 | movl 20(%esp),%edx /* %edx = maxlen */ | |
b2a82d1f DG |
1325 | incl %edx |
1326 | ||
1327 | 1: | |
1328 | decl %edx | |
1329 | jz 4f | |
1330 | gs | |
1331 | lodsb | |
1332 | stosb | |
1333 | orb %al,%al | |
1334 | jnz 1b | |
1335 | /* Success -- 0 byte reached */ | |
1336 | decl %edx | |
57cfd936 | 1337 | xorl %eax,%eax |
b2a82d1f DG |
1338 | jmp 6f |
1339 | 4: | |
1340 | /* edx is zero -- return ENAMETOOLONG */ | |
57cfd936 | 1341 | movl $ENAMETOOLONG,%eax |
b2a82d1f DG |
1342 | jmp 6f |
1343 | ||
1344 | cpystrflt: | |
57cfd936 | 1345 | movl $EFAULT,%eax |
b2a82d1f | 1346 | 6: /* set *lencopied and return %eax */ |
57cfd936 RG |
1347 | movl _curpcb,%ecx |
1348 | movl $0,PCB_ONFAULT(%ecx) | |
1349 | movl 20(%esp),%ecx | |
1350 | subl %edx,%ecx | |
1351 | movl 24(%esp),%edx | |
1352 | orl %edx,%edx | |
b2a82d1f | 1353 | jz 7f |
57cfd936 | 1354 | movl %ecx,(%edx) |
b2a82d1f DG |
1355 | 7: |
1356 | popl %edi | |
15637ed4 RG |
1357 | popl %esi |
1358 | ret | |
1359 | ||
b2a82d1f DG |
1360 | |
1361 | /* | |
1362 | * copystr(from, to, maxlen, int *lencopied) | |
1363 | */ | |
1364 | ENTRY(copystr) | |
15637ed4 | 1365 | pushl %esi |
b2a82d1f DG |
1366 | pushl %edi |
1367 | ||
57cfd936 RG |
1368 | movl 12(%esp),%esi /* %esi = from */ |
1369 | movl 16(%esp),%edi /* %edi = to */ | |
1370 | movl 20(%esp),%edx /* %edx = maxlen */ | |
b2a82d1f DG |
1371 | incl %edx |
1372 | ||
1373 | 1: | |
1374 | decl %edx | |
1375 | jz 4f | |
1376 | lodsb | |
1377 | stosb | |
1378 | orb %al,%al | |
1379 | jnz 1b | |
1380 | /* Success -- 0 byte reached */ | |
1381 | decl %edx | |
57cfd936 | 1382 | xorl %eax,%eax |
b2a82d1f DG |
1383 | jmp 6f |
1384 | 4: | |
1385 | /* edx is zero -- return ENAMETOOLONG */ | |
57cfd936 | 1386 | movl $ENAMETOOLONG,%eax |
b2a82d1f DG |
1387 | |
1388 | 6: /* set *lencopied and return %eax */ | |
57cfd936 RG |
1389 | movl 20(%esp),%ecx |
1390 | subl %edx,%ecx | |
1391 | movl 24(%esp),%edx | |
1392 | orl %edx,%edx | |
b2a82d1f | 1393 | jz 7f |
57cfd936 | 1394 | movl %ecx,(%edx) |
b2a82d1f DG |
1395 | 7: |
1396 | popl %edi | |
15637ed4 RG |
1397 | popl %esi |
1398 | ret | |
1399 | ||
57cfd936 RG |
1400 | /* |
1401 | * Handling of special 386 registers and descriptor tables etc | |
1402 | */ | |
1403 | ENTRY(lgdt) /* void lgdt(struct region_descriptor *rdp); */ | |
15637ed4 RG |
1404 | /* reload the descriptor table */ |
1405 | movl 4(%esp),%eax | |
1406 | lgdt (%eax) | |
1407 | /* flush the prefetch q */ | |
1408 | jmp 1f | |
1409 | nop | |
1410 | 1: | |
1411 | /* reload "stale" selectors */ | |
1412 | movl $KDSEL,%eax | |
1413 | movl %ax,%ds | |
1414 | movl %ax,%es | |
1415 | movl %ax,%ss | |
1416 | ||
1417 | /* reload code selector by turning return into intersegmental return */ | |
1418 | movl (%esp),%eax | |
1419 | pushl %eax | |
57cfd936 | 1420 | # movl $KCSEL,4(%esp) |
15637ed4 RG |
1421 | movl $8,4(%esp) |
1422 | lret | |
1423 | ||
1424 | /* | |
1425 | * void lidt(struct region_descriptor *rdp); | |
1426 | */ | |
1427 | ENTRY(lidt) | |
1428 | movl 4(%esp),%eax | |
1429 | lidt (%eax) | |
1430 | ret | |
1431 | ||
1432 | /* | |
1433 | * void lldt(u_short sel) | |
1434 | */ | |
1435 | ENTRY(lldt) | |
1436 | lldt 4(%esp) | |
1437 | ret | |
1438 | ||
1439 | /* | |
1440 | * void ltr(u_short sel) | |
1441 | */ | |
1442 | ENTRY(ltr) | |
1443 | ltr 4(%esp) | |
1444 | ret | |
1445 | ||
57cfd936 | 1446 | ENTRY(ssdtosd) /* ssdtosd(*ssdp,*sdp) */ |
15637ed4 RG |
1447 | pushl %ebx |
1448 | movl 8(%esp),%ecx | |
1449 | movl 8(%ecx),%ebx | |
1450 | shll $16,%ebx | |
1451 | movl (%ecx),%edx | |
1452 | roll $16,%edx | |
1453 | movb %dh,%bl | |
1454 | movb %dl,%bh | |
1455 | rorl $8,%ebx | |
1456 | movl 4(%ecx),%eax | |
1457 | movw %ax,%dx | |
1458 | andl $0xf0000,%eax | |
1459 | orl %eax,%ebx | |
1460 | movl 12(%esp),%ecx | |
1461 | movl %edx,(%ecx) | |
1462 | movl %ebx,4(%ecx) | |
1463 | popl %ebx | |
1464 | ret | |
1465 | ||
b2a82d1f | 1466 | |
57cfd936 | 1467 | ENTRY(tlbflush) /* tlbflush() */ |
b2a82d1f | 1468 | movl %cr3,%eax |
57cfd936 | 1469 | orl $I386_CR3PAT,%eax |
b2a82d1f | 1470 | movl %eax,%cr3 |
15637ed4 RG |
1471 | ret |
1472 | ||
b2a82d1f | 1473 | |
57cfd936 | 1474 | ENTRY(load_cr0) /* load_cr0(cr0) */ |
b2a82d1f DG |
1475 | movl 4(%esp),%eax |
1476 | movl %eax,%cr0 | |
15637ed4 RG |
1477 | ret |
1478 | ||
15637ed4 | 1479 | |
57cfd936 | 1480 | ENTRY(rcr0) /* rcr0() */ |
b2a82d1f DG |
1481 | movl %cr0,%eax |
1482 | ret | |
15637ed4 | 1483 | |
b2a82d1f | 1484 | |
57cfd936 | 1485 | ENTRY(rcr2) /* rcr2() */ |
b2a82d1f | 1486 | movl %cr2,%eax |
15637ed4 | 1487 | ret |
b2a82d1f DG |
1488 | |
1489 | ||
57cfd936 | 1490 | ENTRY(rcr3) /* rcr3() */ |
b2a82d1f | 1491 | movl %cr3,%eax |
15637ed4 RG |
1492 | ret |
1493 | ||
b2a82d1f | 1494 | |
57cfd936 | 1495 | ENTRY(load_cr3) /* void load_cr3(caddr_t cr3) */ |
b2a82d1f | 1496 | movl 4(%esp),%eax |
57cfd936 | 1497 | orl $I386_CR3PAT,%eax |
b2a82d1f | 1498 | movl %eax,%cr3 |
15637ed4 RG |
1499 | ret |
1500 | ||
b2a82d1f DG |
1501 | |
1502 | /*****************************************************************************/ | |
1503 | /* setjump, longjump */ | |
1504 | /*****************************************************************************/ | |
1505 | ||
15637ed4 RG |
1506 | ENTRY(setjmp) |
1507 | movl 4(%esp),%eax | |
57cfd936 RG |
1508 | movl %ebx,(%eax) /* save ebx */ |
1509 | movl %esp,4(%eax) /* save esp */ | |
1510 | movl %ebp,8(%eax) /* save ebp */ | |
1511 | movl %esi,12(%eax) /* save esi */ | |
1512 | movl %edi,16(%eax) /* save edi */ | |
1513 | movl (%esp),%edx /* get rta */ | |
1514 | movl %edx,20(%eax) /* save eip */ | |
1515 | xorl %eax,%eax /* return(0); */ | |
15637ed4 RG |
1516 | ret |
1517 | ||
1518 | ENTRY(longjmp) | |
1519 | movl 4(%esp),%eax | |
57cfd936 RG |
1520 | movl (%eax),%ebx /* restore ebx */ |
1521 | movl 4(%eax),%esp /* restore esp */ | |
1522 | movl 8(%eax),%ebp /* restore ebp */ | |
1523 | movl 12(%eax),%esi /* restore esi */ | |
1524 | movl 16(%eax),%edi /* restore edi */ | |
1525 | movl 20(%eax),%edx /* get rta */ | |
1526 | movl %edx,(%esp) /* put in return frame */ | |
1527 | xorl %eax,%eax /* return(1); */ | |
15637ed4 RG |
1528 | incl %eax |
1529 | ret | |
b2a82d1f DG |
1530 | |
1531 | ||
1532 | /*****************************************************************************/ | |
1533 | /* Scheduling */ | |
1534 | /*****************************************************************************/ | |
1535 | ||
15637ed4 RG |
1536 | /* |
1537 | * The following primitives manipulate the run queues. | |
1538 | * _whichqs tells which of the 32 queues _qs | |
1539 | * have processes in them. Setrq puts processes into queues, Remrq | |
1540 | * removes them from queues. The running process is on no queue, | |
1541 | * other processes are on a queue related to p->p_pri, divided by 4 | |
1542 | * actually to shrink the 0-127 range of priorities into the 32 available | |
1543 | * queues. | |
1544 | */ | |
1545 | ||
1546 | .globl _whichqs,_qs,_cnt,_panic | |
1547 | .comm _noproc,4 | |
1548 | .comm _runrun,4 | |
1549 | ||
1550 | /* | |
1551 | * Setrq(p) | |
1552 | * | |
1553 | * Call should be made at spl6(), and p->p_stat should be SRUN | |
1554 | */ | |
1555 | ENTRY(setrq) | |
1556 | movl 4(%esp),%eax | |
57cfd936 | 1557 | cmpl $0,P_RLINK(%eax) /* should not be on q already */ |
15637ed4 RG |
1558 | je set1 |
1559 | pushl $set2 | |
1560 | call _panic | |
1561 | set1: | |
1562 | movzbl P_PRI(%eax),%edx | |
1563 | shrl $2,%edx | |
57cfd936 | 1564 | btsl %edx,_whichqs /* set q full bit */ |
15637ed4 | 1565 | shll $3,%edx |
57cfd936 RG |
1566 | addl $_qs,%edx /* locate q hdr */ |
1567 | movl %edx,P_LINK(%eax) /* link process on tail of q */ | |
15637ed4 RG |
1568 | movl P_RLINK(%edx),%ecx |
1569 | movl %ecx,P_RLINK(%eax) | |
1570 | movl %eax,P_RLINK(%edx) | |
1571 | movl %eax,P_LINK(%ecx) | |
1572 | ret | |
1573 | ||
1574 | set2: .asciz "setrq" | |
1575 | ||
1576 | /* | |
1577 | * Remrq(p) | |
1578 | * | |
1579 | * Call should be made at spl6(). | |
1580 | */ | |
1581 | ENTRY(remrq) | |
1582 | movl 4(%esp),%eax | |
1583 | movzbl P_PRI(%eax),%edx | |
1584 | shrl $2,%edx | |
57cfd936 | 1585 | btrl %edx,_whichqs /* clear full bit, panic if clear already */ |
15637ed4 RG |
1586 | jb rem1 |
1587 | pushl $rem3 | |
1588 | call _panic | |
1589 | rem1: | |
1590 | pushl %edx | |
57cfd936 | 1591 | movl P_LINK(%eax),%ecx /* unlink process */ |
15637ed4 RG |
1592 | movl P_RLINK(%eax),%edx |
1593 | movl %edx,P_RLINK(%ecx) | |
1594 | movl P_RLINK(%eax),%ecx | |
1595 | movl P_LINK(%eax),%edx | |
1596 | movl %edx,P_LINK(%ecx) | |
1597 | popl %edx | |
1598 | movl $_qs,%ecx | |
1599 | shll $3,%edx | |
1600 | addl %edx,%ecx | |
57cfd936 | 1601 | cmpl P_LINK(%ecx),%ecx /* q still has something? */ |
15637ed4 | 1602 | je rem2 |
57cfd936 | 1603 | shrl $3,%edx /* yes, set bit as still full */ |
15637ed4 RG |
1604 | btsl %edx,_whichqs |
1605 | rem2: | |
57cfd936 | 1606 | movl $0,P_RLINK(%eax) /* zap reverse link to indicate off list */ |
15637ed4 RG |
1607 | ret |
1608 | ||
1609 | rem3: .asciz "remrq" | |
1610 | sw0: .asciz "swtch" | |
1611 | ||
1612 | /* | |
1613 | * When no processes are on the runq, Swtch branches to idle | |
1614 | * to wait for something to come ready. | |
1615 | */ | |
dd18dc33 DG |
1616 | ALIGN_TEXT |
1617 | Idle: | |
15637ed4 RG |
1618 | sti |
1619 | SHOW_STI | |
dd18dc33 DG |
1620 | |
1621 | ALIGN_TEXT | |
b2a82d1f | 1622 | idle_loop: |
15637ed4 RG |
1623 | call _spl0 |
1624 | cmpl $0,_whichqs | |
1625 | jne sw1 | |
57cfd936 | 1626 | hlt /* wait for interrupt */ |
b2a82d1f | 1627 | jmp idle_loop |
15637ed4 | 1628 | |
15637ed4 RG |
1629 | badsw: |
1630 | pushl $sw0 | |
1631 | call _panic | |
1632 | /*NOTREACHED*/ | |
1633 | ||
1634 | /* | |
1635 | * Swtch() | |
1636 | */ | |
dd18dc33 | 1637 | SUPERALIGN_TEXT /* so profiling doesn't lump Idle with swtch().. */ |
15637ed4 RG |
1638 | ENTRY(swtch) |
1639 | ||
1640 | incl _cnt+V_SWTCH | |
1641 | ||
1642 | /* switch to new process. first, save context as needed */ | |
1643 | ||
1644 | movl _curproc,%ecx | |
1645 | ||
1646 | /* if no process to save, don't bother */ | |
1647 | testl %ecx,%ecx | |
1648 | je sw1 | |
1649 | ||
1650 | movl P_ADDR(%ecx),%ecx | |
1651 | ||
57cfd936 RG |
1652 | movl (%esp),%eax /* Hardware registers */ |
1653 | movl %eax,PCB_EIP(%ecx) | |
1654 | movl %ebx,PCB_EBX(%ecx) | |
1655 | movl %esp,PCB_ESP(%ecx) | |
1656 | movl %ebp,PCB_EBP(%ecx) | |
1657 | movl %esi,PCB_ESI(%ecx) | |
1658 | movl %edi,PCB_EDI(%ecx) | |
15637ed4 | 1659 | |
18dbbd0c | 1660 | #if NNPX > 0 |
15637ed4 RG |
1661 | /* have we used fp, and need a save? */ |
1662 | mov _curproc,%eax | |
1663 | cmp %eax,_npxproc | |
1664 | jne 1f | |
1665 | pushl %ecx /* h/w bugs make saving complicated */ | |
1666 | leal PCB_SAVEFPU(%ecx),%eax | |
1667 | pushl %eax | |
1668 | call _npxsave /* do it in a big C function */ | |
1669 | popl %eax | |
1670 | popl %ecx | |
1671 | 1: | |
18dbbd0c | 1672 | #endif /* NNPX > 0 */ |
15637ed4 | 1673 | |
57cfd936 RG |
1674 | movl _CMAP2,%eax /* save temporary map PTE */ |
1675 | movl %eax,PCB_CMAP2(%ecx) /* in our context */ | |
1676 | movl $0,_curproc /* out of process */ | |
15637ed4 | 1677 | |
57cfd936 RG |
1678 | # movw _cpl,%ax |
1679 | # movw %ax,PCB_IML(%ecx) /* save ipl */ | |
15637ed4 RG |
1680 | |
1681 | /* save is done, now choose a new process or idle */ | |
1682 | sw1: | |
1683 | cli | |
1684 | SHOW_CLI | |
1685 | movl _whichqs,%edi | |
1686 | 2: | |
57cfd936 RG |
1687 | /* XXX - bsf is sloow */ |
1688 | bsfl %edi,%eax /* find a full q */ | |
1689 | je Idle /* if none, idle */ | |
1690 | /* XX update whichqs? */ | |
15637ed4 | 1691 | swfnd: |
57cfd936 RG |
1692 | btrl %eax,%edi /* clear q full status */ |
1693 | jnb 2b /* if it was clear, look for another */ | |
1694 | movl %eax,%ebx /* save which one we are using */ | |
15637ed4 RG |
1695 | |
1696 | shll $3,%eax | |
57cfd936 | 1697 | addl $_qs,%eax /* select q */ |
15637ed4 RG |
1698 | movl %eax,%esi |
1699 | ||
1700 | #ifdef DIAGNOSTIC | |
57cfd936 RG |
1701 | cmpl P_LINK(%eax),%eax /* linked to self? (e.g. not on list) */ |
1702 | je badsw /* not possible */ | |
15637ed4 RG |
1703 | #endif |
1704 | ||
57cfd936 | 1705 | movl P_LINK(%eax),%ecx /* unlink from front of process q */ |
15637ed4 RG |
1706 | movl P_LINK(%ecx),%edx |
1707 | movl %edx,P_LINK(%eax) | |
1708 | movl P_RLINK(%ecx),%eax | |
1709 | movl %eax,P_RLINK(%edx) | |
1710 | ||
57cfd936 | 1711 | cmpl P_LINK(%ecx),%esi /* q empty */ |
15637ed4 | 1712 | je 3f |
57cfd936 | 1713 | btsl %ebx,%edi /* nope, set to indicate full */ |
15637ed4 | 1714 | 3: |
57cfd936 | 1715 | movl %edi,_whichqs /* update q status */ |
15637ed4 RG |
1716 | |
1717 | movl $0,%eax | |
1718 | movl %eax,_want_resched | |
1719 | ||
1720 | #ifdef DIAGNOSTIC | |
1721 | cmpl %eax,P_WCHAN(%ecx) | |
1722 | jne badsw | |
57cfd936 | 1723 | cmpb $SRUN,P_STAT(%ecx) |
15637ed4 RG |
1724 | jne badsw |
1725 | #endif | |
1726 | ||
1727 | movl %eax,P_RLINK(%ecx) /* isolate process to run */ | |
1728 | movl P_ADDR(%ecx),%edx | |
1729 | movl PCB_CR3(%edx),%ebx | |
1730 | ||
1731 | /* switch address space */ | |
1732 | movl %ebx,%cr3 | |
1733 | ||
1734 | /* restore context */ | |
57cfd936 RG |
1735 | movl PCB_EBX(%edx),%ebx |
1736 | movl PCB_ESP(%edx),%esp | |
1737 | movl PCB_EBP(%edx),%ebp | |
1738 | movl PCB_ESI(%edx),%esi | |
1739 | movl PCB_EDI(%edx),%edi | |
1740 | movl PCB_EIP(%edx),%eax | |
1741 | movl %eax,(%esp) | |
1742 | ||
1743 | movl PCB_CMAP2(%edx),%eax /* get temporary map */ | |
1744 | movl %eax,_CMAP2 /* reload temporary map PTE */ | |
1745 | ||
1746 | movl %ecx,_curproc /* into next process */ | |
15637ed4 RG |
1747 | movl %edx,_curpcb |
1748 | ||
57cfd936 | 1749 | pushl %edx /* save p to return */ |
15637ed4 RG |
1750 | /* |
1751 | * XXX - 0.0 forgot to save it - is that why this was commented out in 0.1? | |
1752 | * I think restoring the cpl is unnecessary, but we must turn off the cli | |
1753 | * now that spl*() don't do it as a side affect. | |
1754 | */ | |
1755 | pushl PCB_IML(%edx) | |
1756 | sti | |
1757 | SHOW_STI | |
1758 | #if 0 | |
1759 | call _splx | |
1760 | #endif | |
1761 | addl $4,%esp | |
1762 | /* | |
1763 | * XXX - 0.0 gets here via swtch_to_inactive(). I think 0.1 gets here in the | |
1764 | * same way. Better return a value. | |
1765 | */ | |
57cfd936 | 1766 | popl %eax /* return(p); */ |
15637ed4 RG |
1767 | ret |
1768 | ||
1769 | ENTRY(mvesp) | |
1770 | movl %esp,%eax | |
1771 | ret | |
1772 | /* | |
1773 | * struct proc *swtch_to_inactive(p) ; struct proc *p; | |
1774 | * | |
1775 | * At exit of a process, move off the address space of the | |
1776 | * process and onto a "safe" one. Then, on a temporary stack | |
1777 | * return and run code that disposes of the old state. | |
1778 | * Since this code requires a parameter from the "old" stack, | |
1779 | * pass it back as a return value. | |
1780 | */ | |
1781 | ENTRY(swtch_to_inactive) | |
57cfd936 RG |
1782 | popl %edx /* old pc */ |
1783 | popl %eax /* arg, our return value */ | |
15637ed4 | 1784 | movl _IdlePTD,%ecx |
57cfd936 | 1785 | movl %ecx,%cr3 /* good bye address space */ |
15637ed4 | 1786 | #write buffer? |
57cfd936 RG |
1787 | movl $tmpstk-4,%esp /* temporary stack, compensated for call */ |
1788 | jmp %edx /* return, execute remainder of cleanup */ | |
15637ed4 RG |
1789 | |
1790 | /* | |
1791 | * savectx(pcb, altreturn) | |
1792 | * Update pcb, saving current processor state and arranging | |
1793 | * for alternate return ala longjmp in swtch if altreturn is true. | |
1794 | */ | |
1795 | ENTRY(savectx) | |
57cfd936 RG |
1796 | movl 4(%esp),%ecx |
1797 | movw _cpl,%ax | |
1798 | movw %ax,PCB_IML(%ecx) | |
1799 | movl (%esp),%eax | |
1800 | movl %eax,PCB_EIP(%ecx) | |
1801 | movl %ebx,PCB_EBX(%ecx) | |
1802 | movl %esp,PCB_ESP(%ecx) | |
1803 | movl %ebp,PCB_EBP(%ecx) | |
1804 | movl %esi,PCB_ESI(%ecx) | |
1805 | movl %edi,PCB_EDI(%ecx) | |
15637ed4 | 1806 | |
18dbbd0c | 1807 | #if NNPX > 0 |
15637ed4 RG |
1808 | /* |
1809 | * If npxproc == NULL, then the npx h/w state is irrelevant and the | |
1810 | * state had better already be in the pcb. This is true for forks | |
1811 | * but not for dumps (the old book-keeping with FP flags in the pcb | |
1812 | * always lost for dumps because the dump pcb has 0 flags). | |
1813 | * | |
1814 | * If npxproc != NULL, then we have to save the npx h/w state to | |
1815 | * npxproc's pcb and copy it to the requested pcb, or save to the | |
1816 | * requested pcb and reload. Copying is easier because we would | |
1817 | * have to handle h/w bugs for reloading. We used to lose the | |
1818 | * parent's npx state for forks by forgetting to reload. | |
1819 | */ | |
1820 | mov _npxproc,%eax | |
1821 | testl %eax,%eax | |
1822 | je 1f | |
1823 | ||
1824 | pushl %ecx | |
1825 | movl P_ADDR(%eax),%eax | |
1826 | leal PCB_SAVEFPU(%eax),%eax | |
1827 | pushl %eax | |
1828 | pushl %eax | |
1829 | call _npxsave | |
1830 | popl %eax | |
1831 | popl %eax | |
1832 | popl %ecx | |
1833 | ||
1834 | pushl %ecx | |
1835 | pushl $108+8*2 /* XXX h/w state size + padding */ | |
1836 | leal PCB_SAVEFPU(%ecx),%ecx | |
1837 | pushl %ecx | |
1838 | pushl %eax | |
1839 | call _bcopy | |
1840 | addl $12,%esp | |
1841 | popl %ecx | |
1842 | 1: | |
18dbbd0c | 1843 | #endif /* NNPX > 0 */ |
15637ed4 | 1844 | |
57cfd936 RG |
1845 | movl _CMAP2,%edx /* save temporary map PTE */ |
1846 | movl %edx,PCB_CMAP2(%ecx) /* in our context */ | |
15637ed4 | 1847 | |
57cfd936 | 1848 | cmpl $0,8(%esp) |
15637ed4 | 1849 | je 1f |
57cfd936 RG |
1850 | movl %esp,%edx /* relocate current sp relative to pcb */ |
1851 | subl $_kstack,%edx /* (sp is relative to kstack): */ | |
1852 | addl %edx,%ecx /* pcb += sp - kstack; */ | |
1853 | movl %eax,(%ecx) /* write return pc at (relocated) sp@ */ | |
1854 | /* this mess deals with replicating register state gcc hides */ | |
15637ed4 RG |
1855 | movl 12(%esp),%eax |
1856 | movl %eax,12(%ecx) | |
1857 | movl 16(%esp),%eax | |
1858 | movl %eax,16(%ecx) | |
1859 | movl 20(%esp),%eax | |
1860 | movl %eax,20(%ecx) | |
1861 | movl 24(%esp),%eax | |
1862 | movl %eax,24(%ecx) | |
1863 | 1: | |
57cfd936 | 1864 | xorl %eax,%eax /* return 0 */ |
15637ed4 RG |
1865 | ret |
1866 | ||
1867 | /* | |
1868 | * addupc(int pc, struct uprof *up, int ticks): | |
1869 | * update profiling information for the user process. | |
1870 | */ | |
15637ed4 RG |
1871 | ENTRY(addupc) |
1872 | pushl %ebp | |
1873 | movl %esp,%ebp | |
1874 | movl 12(%ebp),%edx /* up */ | |
1875 | movl 8(%ebp),%eax /* pc */ | |
1876 | ||
1877 | subl PR_OFF(%edx),%eax /* pc -= up->pr_off */ | |
1878 | jl L1 /* if (pc < 0) return */ | |
1879 | ||
1880 | shrl $1,%eax /* praddr = pc >> 1 */ | |
1881 | imull PR_SCALE(%edx),%eax /* praddr *= up->pr_scale */ | |
1882 | shrl $15,%eax /* praddr = praddr << 15 */ | |
1883 | andl $-2,%eax /* praddr &= ~1 */ | |
1884 | ||
1885 | cmpl PR_SIZE(%edx),%eax /* if (praddr > up->pr_size) return */ | |
1886 | ja L1 | |
1887 | ||
1888 | /* addl %eax,%eax /* praddr -> word offset */ | |
1889 | addl PR_BASE(%edx),%eax /* praddr += up-> pr_base */ | |
1890 | movl 16(%ebp),%ecx /* ticks */ | |
1891 | ||
1892 | movl _curpcb,%edx | |
1893 | movl $proffault,PCB_ONFAULT(%edx) | |
1894 | addl %ecx,(%eax) /* storage location += ticks */ | |
1895 | movl $0,PCB_ONFAULT(%edx) | |
1896 | L1: | |
1897 | leave | |
1898 | ret | |
1899 | ||
1900 | ALIGN_TEXT | |
1901 | proffault: | |
1902 | /* if we get a fault, then kill profiling all together */ | |
1903 | movl $0,PCB_ONFAULT(%edx) /* squish the fault handler */ | |
dd18dc33 | 1904 | movl 12(%ebp),%ecx |
15637ed4 RG |
1905 | movl $0,PR_SCALE(%ecx) /* up->pr_scale = 0 */ |
1906 | leave | |
1907 | ret | |
1908 | ||
57cfd936 | 1909 | /* To be done: */ |
b2a82d1f | 1910 | ENTRY(astoff) |
15637ed4 RG |
1911 | ret |
1912 | ||
15637ed4 | 1913 | |
b2a82d1f DG |
1914 | /*****************************************************************************/ |
1915 | /* Trap handling */ | |
1916 | /*****************************************************************************/ | |
15637ed4 RG |
1917 | /* |
1918 | * Trap and fault vector routines | |
1919 | * | |
1920 | * XXX - debugger traps are now interrupt gates so at least bdb doesn't lose | |
1921 | * control. The sti's give the standard losing behaviour for ddb and kgdb. | |
dd18dc33 | 1922 | */ |
15637ed4 RG |
1923 | #define IDTVEC(name) ALIGN_TEXT; .globl _X/**/name; _X/**/name: |
1924 | #define TRAP(a) pushl $(a) ; jmp alltraps | |
1925 | #ifdef KGDB | |
b2a82d1f | 1926 | # define BPTTRAP(a) sti; pushl $(a) ; jmp bpttraps |
15637ed4 | 1927 | #else |
b2a82d1f | 1928 | # define BPTTRAP(a) sti; TRAP(a) |
15637ed4 RG |
1929 | #endif |
1930 | ||
15637ed4 RG |
1931 | IDTVEC(div) |
1932 | pushl $0; TRAP(T_DIVIDE) | |
1933 | IDTVEC(dbg) | |
1934 | #ifdef BDBTRAP | |
1935 | BDBTRAP(dbg) | |
1936 | #endif | |
1937 | pushl $0; BPTTRAP(T_TRCTRAP) | |
1938 | IDTVEC(nmi) | |
1939 | pushl $0; TRAP(T_NMI) | |
1940 | IDTVEC(bpt) | |
1941 | #ifdef BDBTRAP | |
1942 | BDBTRAP(bpt) | |
1943 | #endif | |
1944 | pushl $0; BPTTRAP(T_BPTFLT) | |
1945 | IDTVEC(ofl) | |
1946 | pushl $0; TRAP(T_OFLOW) | |
1947 | IDTVEC(bnd) | |
1948 | pushl $0; TRAP(T_BOUND) | |
1949 | IDTVEC(ill) | |
1950 | pushl $0; TRAP(T_PRIVINFLT) | |
1951 | IDTVEC(dna) | |
1952 | pushl $0; TRAP(T_DNA) | |
1953 | IDTVEC(dble) | |
1954 | TRAP(T_DOUBLEFLT) | |
1955 | /*PANIC("Double Fault");*/ | |
1956 | IDTVEC(fpusegm) | |
1957 | pushl $0; TRAP(T_FPOPFLT) | |
1958 | IDTVEC(tss) | |
1959 | TRAP(T_TSSFLT) | |
1960 | /*PANIC("TSS not valid");*/ | |
1961 | IDTVEC(missing) | |
1962 | TRAP(T_SEGNPFLT) | |
1963 | IDTVEC(stk) | |
1964 | TRAP(T_STKFLT) | |
1965 | IDTVEC(prot) | |
1966 | TRAP(T_PROTFLT) | |
1967 | IDTVEC(page) | |
1968 | TRAP(T_PAGEFLT) | |
1969 | IDTVEC(rsvd) | |
1970 | pushl $0; TRAP(T_RESERVED) | |
1971 | IDTVEC(fpu) | |
18dbbd0c | 1972 | #if NNPX > 0 |
15637ed4 RG |
1973 | /* |
1974 | * Handle like an interrupt so that we can call npxintr to clear the | |
1975 | * error. It would be better to handle npx interrupts as traps but | |
1976 | * this is difficult for nested interrupts. | |
1977 | */ | |
1978 | pushl $0 /* dummy error code */ | |
1979 | pushl $T_ASTFLT | |
1980 | pushal | |
1981 | nop /* silly, the bug is for popal and it only | |
1982 | * bites when the next instruction has a | |
1983 | * complicated address mode */ | |
1984 | pushl %ds | |
1985 | pushl %es /* now the stack frame is a trap frame */ | |
1986 | movl $KDSEL,%eax | |
1987 | movl %ax,%ds | |
1988 | movl %ax,%es | |
1989 | pushl _cpl | |
1990 | pushl $0 /* dummy unit to finish building intr frame */ | |
1991 | incl _cnt+V_TRAP | |
1992 | call _npxintr | |
1993 | jmp doreti | |
18dbbd0c | 1994 | #else /* NNPX > 0 */ |
15637ed4 | 1995 | pushl $0; TRAP(T_ARITHTRAP) |
18dbbd0c | 1996 | #endif /* NNPX > 0 */ |
15637ed4 RG |
1997 | /* 17 - 31 reserved for future exp */ |
1998 | IDTVEC(rsvd0) | |
1999 | pushl $0; TRAP(17) | |
2000 | IDTVEC(rsvd1) | |
2001 | pushl $0; TRAP(18) | |
2002 | IDTVEC(rsvd2) | |
2003 | pushl $0; TRAP(19) | |
2004 | IDTVEC(rsvd3) | |
2005 | pushl $0; TRAP(20) | |
2006 | IDTVEC(rsvd4) | |
2007 | pushl $0; TRAP(21) | |
2008 | IDTVEC(rsvd5) | |
2009 | pushl $0; TRAP(22) | |
2010 | IDTVEC(rsvd6) | |
2011 | pushl $0; TRAP(23) | |
2012 | IDTVEC(rsvd7) | |
2013 | pushl $0; TRAP(24) | |
2014 | IDTVEC(rsvd8) | |
2015 | pushl $0; TRAP(25) | |
2016 | IDTVEC(rsvd9) | |
2017 | pushl $0; TRAP(26) | |
2018 | IDTVEC(rsvd10) | |
2019 | pushl $0; TRAP(27) | |
2020 | IDTVEC(rsvd11) | |
2021 | pushl $0; TRAP(28) | |
2022 | IDTVEC(rsvd12) | |
2023 | pushl $0; TRAP(29) | |
2024 | IDTVEC(rsvd13) | |
2025 | pushl $0; TRAP(30) | |
2026 | IDTVEC(rsvd14) | |
2027 | pushl $0; TRAP(31) | |
2028 | ||
2029 | SUPERALIGN_TEXT | |
2030 | alltraps: | |
2031 | pushal | |
2032 | nop | |
2033 | pushl %ds | |
2034 | pushl %es | |
2035 | movl $KDSEL,%eax | |
2036 | movl %ax,%ds | |
2037 | movl %ax,%es | |
2038 | calltrap: | |
2039 | incl _cnt+V_TRAP | |
2040 | call _trap | |
2041 | /* | |
2042 | * Return through doreti to handle ASTs. Have to change trap frame | |
2043 | * to interrupt frame. | |
2044 | */ | |
2045 | movl $T_ASTFLT,4+4+32(%esp) /* new trap type (err code not used) */ | |
2046 | pushl _cpl | |
2047 | pushl $0 /* dummy unit */ | |
2048 | jmp doreti | |
2049 | ||
2050 | #ifdef KGDB | |
2051 | /* | |
2052 | * This code checks for a kgdb trap, then falls through | |
2053 | * to the regular trap code. | |
2054 | */ | |
b2a82d1f | 2055 | SUPERALIGN_TEXT |
15637ed4 RG |
2056 | bpttraps: |
2057 | pushal | |
2058 | nop | |
2059 | pushl %es | |
2060 | pushl %ds | |
2061 | movl $KDSEL,%eax | |
2062 | movl %ax,%ds | |
2063 | movl %ax,%es | |
2064 | testb $SEL_RPL_MASK,TRAPF_CS_OFF(%esp) | |
57cfd936 RG |
2065 | /* non-kernel mode? */ |
2066 | jne calltrap /* yes */ | |
dd18dc33 | 2067 | call _kgdb_trap_glue |
15637ed4 RG |
2068 | jmp calltrap |
2069 | #endif | |
2070 | ||
2071 | /* | |
2072 | * Call gate entry for syscall | |
2073 | */ | |
dd18dc33 | 2074 | SUPERALIGN_TEXT |
15637ed4 | 2075 | IDTVEC(syscall) |
57cfd936 RG |
2076 | pushfl /* only for stupid carry bit and more stupid wait3 cc kludge */ |
2077 | /* XXX - also for direction flag (bzero, etc. clear it) */ | |
2078 | pushal /* only need eax,ecx,edx - trap resaves others */ | |
15637ed4 | 2079 | nop |
57cfd936 | 2080 | movl $KDSEL,%eax /* switch to kernel segments */ |
15637ed4 RG |
2081 | movl %ax,%ds |
2082 | movl %ax,%es | |
57cfd936 | 2083 | incl _cnt+V_SYSCALL /* kml 3/25/93 */ |
15637ed4 RG |
2084 | call _syscall |
2085 | /* | |
2086 | * Return through doreti to handle ASTs. Have to change syscall frame | |
2087 | * to interrupt frame. | |
2088 | * | |
2089 | * XXX - we should have set up the frame earlier to avoid the | |
2090 | * following popal/pushal (not much can be done to avoid shuffling | |
2091 | * the flags). Consistent frames would simplify things all over. | |
2092 | */ | |
2093 | movl 32+0(%esp),%eax /* old flags, shuffle to above cs:eip */ | |
2094 | movl 32+4(%esp),%ebx /* `int' frame should have been ef, eip, cs */ | |
2095 | movl 32+8(%esp),%ecx | |
2096 | movl %ebx,32+0(%esp) | |
2097 | movl %ecx,32+4(%esp) | |
2098 | movl %eax,32+8(%esp) | |
2099 | popal | |
2100 | nop | |
2101 | pushl $0 /* dummy error code */ | |
2102 | pushl $T_ASTFLT | |
2103 | pushal | |
2104 | nop | |
2105 | movl __udatasel,%eax /* switch back to user segments */ | |
b2a82d1f DG |
2106 | pushl %eax /* XXX - better to preserve originals? */ |
2107 | pushl %eax | |
15637ed4 RG |
2108 | pushl _cpl |
2109 | pushl $0 | |
2110 | jmp doreti | |
2111 | ||
57cfd936 RG |
2112 | #ifdef SHOW_A_LOT |
2113 | /* | |
2114 | * 'show_bits' was too big when defined as a macro. The line length for some | |
2115 | * enclosing macro was too big for gas. Perhaps the code would have blown | |
2116 | * the cache anyway. | |
2117 | */ | |
2118 | ALIGN_TEXT | |
2119 | show_bits: | |
2120 | pushl %eax | |
2121 | SHOW_BIT(0) | |
2122 | SHOW_BIT(1) | |
2123 | SHOW_BIT(2) | |
2124 | SHOW_BIT(3) | |
2125 | SHOW_BIT(4) | |
2126 | SHOW_BIT(5) | |
2127 | SHOW_BIT(6) | |
2128 | SHOW_BIT(7) | |
2129 | SHOW_BIT(8) | |
2130 | SHOW_BIT(9) | |
2131 | SHOW_BIT(10) | |
2132 | SHOW_BIT(11) | |
2133 | SHOW_BIT(12) | |
2134 | SHOW_BIT(13) | |
2135 | SHOW_BIT(14) | |
2136 | SHOW_BIT(15) | |
2137 | popl %eax | |
2138 | ret | |
15637ed4 | 2139 | |
57cfd936 RG |
2140 | .data |
2141 | bit_colors: | |
2142 | .byte GREEN,RED,0,0 | |
2143 | .text | |
2144 | ||
2145 | #endif /* SHOW_A_LOT */ | |
15637ed4 | 2146 | |
57cfd936 RG |
2147 | |
2148 | /* | |
2149 | * include generated interrupt vectors and ISA intr code | |
2150 | */ | |
15637ed4 RG |
2151 | #include "i386/isa/vector.s" |
2152 | #include "i386/isa/icu.s" |