locore.s revision 608
14Srgrimes/*- 24Srgrimes * Copyright (c) 1990 The Regents of the University of California. 34Srgrimes * All rights reserved. 44Srgrimes * 54Srgrimes * This code is derived from software contributed to Berkeley by 64Srgrimes * William Jolitz. 74Srgrimes * 84Srgrimes * Redistribution and use in source and binary forms, with or without 94Srgrimes * modification, are permitted provided that the following conditions 104Srgrimes * are met: 114Srgrimes * 1. Redistributions of source code must retain the above copyright 124Srgrimes * notice, this list of conditions and the following disclaimer. 134Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 144Srgrimes * notice, this list of conditions and the following disclaimer in the 154Srgrimes * documentation and/or other materials provided with the distribution. 164Srgrimes * 3. All advertising materials mentioning features or use of this software 174Srgrimes * must display the following acknowledgement: 184Srgrimes * This product includes software developed by the University of 194Srgrimes * California, Berkeley and its contributors. 204Srgrimes * 4. Neither the name of the University nor the names of its contributors 214Srgrimes * may be used to endorse or promote products derived from this software 224Srgrimes * without specific prior written permission. 234Srgrimes * 244Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 254Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 264Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 274Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 284Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 294Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 304Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 314Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 324Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 334Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 344Srgrimes * SUCH DAMAGE. 354Srgrimes * 36556Srgrimes * from: @(#)locore.s 7.3 (Berkeley) 5/13/91 37608Srgrimes * $Id: locore.s,v 1.7 1993/10/13 07:11:11 rgrimes Exp $ 384Srgrimes */ 394Srgrimes 404Srgrimes 414Srgrimes/* 424Srgrimes * locore.s: 4BSD machine support for the Intel 386 434Srgrimes * Preliminary version 444Srgrimes * Written by William F. Jolitz, 386BSD Project 454Srgrimes */ 464Srgrimes 47556Srgrimes#include "npx.h" 48556Srgrimes 494Srgrimes#include "assym.s" 504Srgrimes#include "machine/psl.h" 514Srgrimes#include "machine/pte.h" 524Srgrimes 534Srgrimes#include "errno.h" 544Srgrimes 554Srgrimes#include "machine/trap.h" 564Srgrimes 574Srgrimes#include "machine/specialreg.h" 584Srgrimes#include "i386/isa/debug.h" 59556Srgrimes#include "machine/cputypes.h" 604Srgrimes 614Srgrimes#define KDSEL 0x10 624Srgrimes#define SEL_RPL_MASK 0x0003 634Srgrimes#define TRAPF_CS_OFF (13 * 4) 644Srgrimes 654Srgrimes/* 664Srgrimes * Note: This version greatly munged to avoid various assembler errors 674Srgrimes * that may be fixed in newer versions of gas. Perhaps newer versions 684Srgrimes * will have more pleasant appearance. 694Srgrimes */ 704Srgrimes 714Srgrimes .set IDXSHIFT,10 724Srgrimes 734Srgrimes#define ALIGN_DATA .align 2 744Srgrimes#define ALIGN_TEXT .align 2,0x90 /* 4-byte boundaries, NOP-filled */ 754Srgrimes#define SUPERALIGN_TEXT .align 4,0x90 /* 16-byte boundaries better for 486 */ 764Srgrimes 77200Sdg#define GEN_ENTRY(name) ALIGN_TEXT; .globl name; name: 78200Sdg#define NON_GPROF_ENTRY(name) GEN_ENTRY(_/**/name) 79134Sdg 80200Sdg#ifdef GPROF 81200Sdg/* 82200Sdg * ALTENTRY() must be before a corresponding ENTRY() so that it can jump 83200Sdg * over the mcounting. 84200Sdg */ 85200Sdg#define ALTENTRY(name) GEN_ENTRY(_/**/name); MCOUNT; jmp 2f 86200Sdg#define ENTRY(name) GEN_ENTRY(_/**/name); MCOUNT; 2: 87200Sdg/* 88200Sdg * The call to mcount supports the usual (bad) conventions. We allocate 89200Sdg * some data and pass a pointer to it although the 386BSD doesn't use 90200Sdg * the data. We set up a frame before calling mcount because that is 91200Sdg * the standard convention although it makes work for both mcount and 92200Sdg * callers. 93200Sdg */ 94200Sdg#define MCOUNT .data; ALIGN_DATA; 1:; .long 0; .text; \ 95570Srgrimes pushl %ebp; movl %esp,%ebp; \ 96200Sdg movl $1b,%eax; call mcount; popl %ebp 97200Sdg#else 98200Sdg/* 99200Sdg * ALTENTRY() has to align because it is before a corresponding ENTRY(). 100200Sdg * ENTRY() has to align to because there may be no ALTENTRY() before it. 101200Sdg * If there is a previous ALTENTRY() then the alignment code is empty. 102200Sdg */ 103200Sdg#define ALTENTRY(name) GEN_ENTRY(_/**/name) 104200Sdg#define ENTRY(name) GEN_ENTRY(_/**/name) 105200Sdg#endif 106200Sdg 1074Srgrimes/* NB: NOP now preserves registers so NOPs can be inserted anywhere */ 1084Srgrimes/* XXX: NOP and FASTER_NOP are misleadingly named */ 109556Srgrimes#ifdef DUMMY_NOPS /* this will break some older machines */ 110556Srgrimes#define FASTER_NOP 111556Srgrimes#define NOP 112556Srgrimes#else 1134Srgrimes#define FASTER_NOP pushl %eax ; inb $0x84,%al ; popl %eax 1144Srgrimes#define NOP pushl %eax ; inb $0x84,%al ; inb $0x84,%al ; popl %eax 1154Srgrimes#endif 1164Srgrimes 1174Srgrimes/* 1184Srgrimes * PTmap is recursive pagemap at top of virtual address space. 1194Srgrimes * Within PTmap, the page directory can be found (third indirection). 1204Srgrimes */ 121592Srgrimes .globl _PTmap,_PTD,_PTDpde,_Sysmap 122592Srgrimes .set _PTmap,PTDPTDI << PDRSHIFT 123592Srgrimes .set _PTD,_PTmap + (PTDPTDI * NBPG) 124608Srgrimes .set _PTDpde,_PTD + (PTDPTDI * 4) /* XXX 4=sizeof pde */ 125592Srgrimes 126608Srgrimes .set _Sysmap,_PTmap + (KPTDI * NBPG) 1274Srgrimes 1284Srgrimes/* 1294Srgrimes * APTmap, APTD is the alternate recursive pagemap. 1304Srgrimes * It's used when modifying another process's page tables. 1314Srgrimes */ 132592Srgrimes .globl _APTmap,_APTD,_APTDpde 133592Srgrimes .set _APTmap,APTDPTDI << PDRSHIFT 134592Srgrimes .set _APTD,_APTmap + (APTDPTDI * NBPG) 135608Srgrimes .set _APTDpde,_PTD + (APTDPTDI * 4) /* XXX 4=sizeof pde */ 1364Srgrimes 1374Srgrimes/* 1384Srgrimes * Access to each processes kernel stack is via a region of 1394Srgrimes * per-process address space (at the beginning), immediatly above 1404Srgrimes * the user process stack. 1414Srgrimes */ 142570Srgrimes .set _kstack,USRSTACK 143134Sdg .globl _kstack 1444Srgrimes .set PPDROFF,0x3F6 145570Srgrimes .set PPTEOFF,0x400-UPAGES /* 0x3FE */ 1464Srgrimes 1474Srgrimes 148556Srgrimes/* 149556Srgrimes * Globals 150556Srgrimes */ 151556Srgrimes .data 152556Srgrimes .globl _esym 153570Srgrimes_esym: .long 0 /* ptr to end of syms */ 154134Sdg 155592Srgrimes .globl _boothowto,_bootdev,_curpcb 156134Sdg 157592Srgrimes .globl _cpu,_cold,_atdevbase 158570Srgrimes_cpu: .long 0 /* are we 386, 386sx, or 486 */ 159570Srgrimes_cold: .long 1 /* cold till we are not */ 160570Srgrimes_atdevbase: .long 0 /* location of start of iomem in virtual */ 161570Srgrimes_atdevphys: .long 0 /* location of device mapping ptes (phys) */ 1624Srgrimes 163592Srgrimes .globl _IdlePTD,_KPTphys 1644Srgrimes_IdlePTD: .long 0 1654Srgrimes_KPTphys: .long 0 1664Srgrimes 167592Srgrimes .globl _cyloffset,_proc0paddr 168134Sdg_cyloffset: .long 0 169134Sdg_proc0paddr: .long 0 170134Sdg 1714Srgrimes .space 512 1724Srgrimestmpstk: 173134Sdg 174134Sdg 175556Srgrimes/* 176556Srgrimes * System Initialization 177556Srgrimes */ 1784Srgrimes .text 179134Sdg 180134Sdg/* 181200Sdg * btext: beginning of text section. 182200Sdg * Also the entry point (jumped to directly from the boot blocks). 183134Sdg */ 184200SdgENTRY(btext) 185570Srgrimes movw $0x1234,0x472 /* warm boot */ 1864Srgrimes jmp 1f 187570Srgrimes .space 0x500 /* skip over warm boot shit */ 1884Srgrimes 1894Srgrimes /* 190556Srgrimes * pass parameters on stack (howto, bootdev, unit, cyloffset, esym) 1914Srgrimes * note: (%esp) is return address of boot 1924Srgrimes * ( if we want to hold onto /boot, it's physical %esp up to _end) 1934Srgrimes */ 1944Srgrimes 1954Srgrimes 1: movl 4(%esp),%eax 196570Srgrimes movl %eax,_boothowto-KERNBASE 1974Srgrimes movl 8(%esp),%eax 198570Srgrimes movl %eax,_bootdev-KERNBASE 1994Srgrimes movl 12(%esp),%eax 200570Srgrimes movl %eax,_cyloffset-KERNBASE 201556Srgrimes movl 16(%esp),%eax 202570Srgrimes addl $KERNBASE,%eax 203570Srgrimes movl %eax,_esym-KERNBASE 2044Srgrimes 205556Srgrimes /* find out our CPU type. */ 206556Srgrimes pushfl 207556Srgrimes popl %eax 208556Srgrimes movl %eax,%ecx 209556Srgrimes xorl $0x40000,%eax 210556Srgrimes pushl %eax 211556Srgrimes popfl 212556Srgrimes pushfl 213556Srgrimes popl %eax 214556Srgrimes xorl %ecx,%eax 215556Srgrimes shrl $18,%eax 216556Srgrimes andl $1,%eax 217556Srgrimes push %ecx 218556Srgrimes popfl 219556Srgrimes 220556Srgrimes cmpl $0,%eax 221556Srgrimes jne 1f 222570Srgrimes movl $CPU_386,_cpu-KERNBASE 223556Srgrimes jmp 2f 224570Srgrimes1: movl $CPU_486,_cpu-KERNBASE 225556Srgrimes2: 226556Srgrimes 2274Srgrimes /* 2284Srgrimes * Finished with old stack; load new %esp now instead of later so 2294Srgrimes * we can trace this code without having to worry about the trace 2304Srgrimes * trap clobbering the memory test or the zeroing of the bss+bootstrap 2314Srgrimes * page tables. 2324Srgrimes * 2334Srgrimes * XXX - wdboot clears the bss after testing that this is safe. 2344Srgrimes * This is too wasteful - memory below 640K is scarce. The boot 2354Srgrimes * program should check: 2364Srgrimes * text+data <= &stack_variable - more_space_for_stack 2374Srgrimes * text+data+bss+pad+space_for_page_tables <= end_of_memory 2384Srgrimes * Oops, the gdt is in the carcass of the boot program so clearing 2394Srgrimes * the rest of memory is still not possible. 2404Srgrimes */ 241570Srgrimes movl $tmpstk-KERNBASE,%esp /* bootstrap stack end location */ 2424Srgrimes 243570Srgrimes/* 244570Srgrimes * Virtual address space of kernel: 245570Srgrimes * 246570Srgrimes * text | data | bss | [syms] | page dir | proc0 kernel stack | usr stk map | Sysmap 247570Srgrimes * 0 1 2 3 4 248570Srgrimes */ 249570Srgrimes 2504Srgrimes/* find end of kernel image */ 251570Srgrimes movl $_end-KERNBASE,%ecx 252570Srgrimes addl $NBPG-1,%ecx /* page align up */ 2534Srgrimes andl $~(NBPG-1),%ecx 254570Srgrimes movl %ecx,%esi /* esi=start of tables */ 2554Srgrimes 2564Srgrimes/* clear bss and memory for bootstrap pagetables. */ 257570Srgrimes movl $_edata-KERNBASE,%edi 2584Srgrimes subl %edi,%ecx 259570Srgrimes addl $(UPAGES+5)*NBPG,%ecx /* size of tables */ 260570Srgrimes 261570Srgrimes xorl %eax,%eax /* pattern */ 2624Srgrimes cld 2634Srgrimes rep 2644Srgrimes stosb 2654Srgrimes 266608Srgrimes/* 267608Srgrimes * If we are loaded at 0x0 check to see if we have space for the 268608Srgrimes * page tables pages after the kernel and before the 640K ISA memory 269608Srgrimes * hole. If we do not have space relocate the page table pages and 270608Srgrimes * the kernel stack to start at 1MB. The value that ends up in esi 271608Srgrimes * is used by the rest of locore to build the tables. Locore adjusts 272608Srgrimes * esi each time it allocates a structure and then passes the final 273608Srgrimes * value to init386(first) as the value first. esi should ALWAYS 274608Srgrimes * be page aligned!! 275608Srgrimes */ 276608Srgrimes movl %esi,%ecx /* Get current first availiable address */ 277608Srgrimes cmpl $0x100000,%ecx /* Lets see if we are already above 1MB */ 278608Srgrimes jge 1f /* yep, don't need to check for room */ 279608Srgrimes addl $(NKPDE + 4) * NBPG,%ecx /* XXX the 4 is for kstack */ 280608Srgrimes /* space for kstack, PTD and PTE's */ 281608Srgrimes cmpl $(640*1024),%ecx 282608Srgrimes /* see if it fits in low memory */ 283608Srgrimes jle 1f /* yep, don't need to relocate it */ 284608Srgrimes movl $0x100000,%esi /* won't fit, so start it at 1MB */ 285608Srgrimes1: 286608Srgrimes 287570Srgrimes/* physical address of Idle Address space */ 288570Srgrimes movl %esi,_IdlePTD-KERNBASE 2894Srgrimes 290592Srgrimes/* 291592Srgrimes * fillkpt 292592Srgrimes * eax = (page frame address | control | status) == pte 293592Srgrimes * ebx = address of page table 294592Srgrimes * ecx = how many pages to map 295592Srgrimes */ 2964Srgrimes#define fillkpt \ 2974Srgrimes1: movl %eax,(%ebx) ; \ 298570Srgrimes addl $NBPG,%eax ; /* increment physical address */ \ 2994Srgrimes addl $4,%ebx ; /* next pte */ \ 3004Srgrimes loop 1b ; 3014Srgrimes 3024Srgrimes/* 3034Srgrimes * Map Kernel 3044Srgrimes * N.B. don't bother with making kernel text RO, as 386 3054Srgrimes * ignores R/W AND U/S bits on kernel access (only v works) ! 3064Srgrimes * 3074Srgrimes * First step - build page tables 3084Srgrimes */ 309570Srgrimes movl %esi,%ecx /* this much memory, */ 310570Srgrimes shrl $PGSHIFT,%ecx /* for this many pte s */ 311570Srgrimes addl $UPAGES+4,%ecx /* including our early context */ 312570Srgrimes cmpl $0xa0,%ecx /* XXX - cover debugger pages */ 313200Sdg jae 1f 314200Sdg movl $0xa0,%ecx 315200Sdg1: 316570Srgrimes movl $PG_V|PG_KW,%eax /* having these bits set, */ 317570Srgrimes lea (4*NBPG)(%esi),%ebx /* physical address of KPT in proc 0, */ 318570Srgrimes movl %ebx,_KPTphys-KERNBASE /* in the kernel page table, */ 3194Srgrimes fillkpt 3204Srgrimes 3214Srgrimes/* map I/O memory map */ 3224Srgrimes 323570Srgrimes movl $0x100-0xa0,%ecx /* for this many pte s, */ 324570Srgrimes movl $(0xa0000|PG_V|PG_UW),%eax /* having these bits set,(perhaps URW?) XXX 06 Aug 92 */ 325570Srgrimes movl %ebx,_atdevphys-KERNBASE /* remember phys addr of ptes */ 3264Srgrimes fillkpt 3274Srgrimes 3284Srgrimes /* map proc 0's kernel stack into user page table page */ 3294Srgrimes 330570Srgrimes movl $UPAGES,%ecx /* for this many pte s, */ 331570Srgrimes lea (1*NBPG)(%esi),%eax /* physical address in proc 0 */ 332570Srgrimes lea (KERNBASE)(%eax),%edx 333592Srgrimes movl %edx,_proc0paddr-KERNBASE 334592Srgrimes /* remember VA for 0th process init */ 335570Srgrimes orl $PG_V|PG_KW,%eax /* having these bits set, */ 336570Srgrimes lea (3*NBPG)(%esi),%ebx /* physical address of stack pt in proc 0 */ 3374Srgrimes addl $(PPTEOFF*4),%ebx 3384Srgrimes fillkpt 3394Srgrimes 3404Srgrimes/* 3414Srgrimes * Construct a page table directory 3424Srgrimes * (of page directory elements - pde's) 3434Srgrimes */ 3444Srgrimes /* install a pde for temporary double map of bottom of VA */ 345570Srgrimes lea (4*NBPG)(%esi),%eax /* physical address of kernel page table */ 346570Srgrimes orl $PG_V|PG_UW,%eax /* pde entry is valid XXX 06 Aug 92 */ 347570Srgrimes movl %eax,(%esi) /* which is where temp maps! */ 3484Srgrimes 3494Srgrimes /* kernel pde's */ 350592Srgrimes movl $(NKPDE),%ecx /* for this many pde s, */ 351592Srgrimes lea (KPTDI*4)(%esi),%ebx /* offset of pde for kernel */ 3524Srgrimes fillkpt 3534Srgrimes 3544Srgrimes /* install a pde recursively mapping page directory as a page table! */ 355570Srgrimes movl %esi,%eax /* phys address of ptd in proc 0 */ 356570Srgrimes orl $PG_V|PG_UW,%eax /* pde entry is valid XXX 06 Aug 92 */ 357592Srgrimes movl %eax,PTDPTDI*4(%esi) /* which is where PTmap maps! */ 3584Srgrimes 3594Srgrimes /* install a pde to map kernel stack for proc 0 */ 360570Srgrimes lea (3*NBPG)(%esi),%eax /* physical address of pt in proc 0 */ 361570Srgrimes orl $PG_V|PG_KW,%eax /* pde entry is valid */ 362570Srgrimes movl %eax,PPDROFF*4(%esi) /* which is where kernel stack maps! */ 3634Srgrimes 3644Srgrimes /* copy and convert stuff from old gdt and idt for debugger */ 3654Srgrimes 366570Srgrimes cmpl $0x0375c339,0x96104 /* XXX - debugger signature */ 3674Srgrimes jne 1f 368570Srgrimes movb $1,_bdb_exists-KERNBASE 3694Srgrimes1: 3704Srgrimes pushal 3714Srgrimes subl $2*6,%esp 3724Srgrimes 3734Srgrimes sgdt (%esp) 374570Srgrimes movl 2(%esp),%esi /* base address of current gdt */ 375570Srgrimes movl $_gdt-KERNBASE,%edi 3764Srgrimes movl %edi,2(%esp) 3774Srgrimes movl $8*18/4,%ecx 378570Srgrimes rep /* copy gdt */ 3794Srgrimes movsl 380570Srgrimes movl $_gdt-KERNBASE,-8+2(%edi) /* adjust gdt self-ptr */ 3814Srgrimes movb $0x92,-8+5(%edi) 3824Srgrimes 3834Srgrimes sidt 6(%esp) 384570Srgrimes movl 6+2(%esp),%esi /* base address of current idt */ 385570Srgrimes movl 8+4(%esi),%eax /* convert dbg descriptor to ... */ 3864Srgrimes movw 8(%esi),%ax 387570Srgrimes movl %eax,bdb_dbg_ljmp+1-KERNBASE /* ... immediate offset ... */ 3884Srgrimes movl 8+2(%esi),%eax 389570Srgrimes movw %ax,bdb_dbg_ljmp+5-KERNBASE /* ... and selector for ljmp */ 390570Srgrimes movl 24+4(%esi),%eax /* same for bpt descriptor */ 3914Srgrimes movw 24(%esi),%ax 392570Srgrimes movl %eax,bdb_bpt_ljmp+1-KERNBASE 3934Srgrimes movl 24+2(%esi),%eax 394570Srgrimes movw %ax,bdb_bpt_ljmp+5-KERNBASE 3954Srgrimes 396570Srgrimes movl $_idt-KERNBASE,%edi 3974Srgrimes movl %edi,6+2(%esp) 3984Srgrimes movl $8*4/4,%ecx 399570Srgrimes rep /* copy idt */ 4004Srgrimes movsl 4014Srgrimes 4024Srgrimes lgdt (%esp) 4034Srgrimes lidt 6(%esp) 4044Srgrimes 4054Srgrimes addl $2*6,%esp 4064Srgrimes popal 4074Srgrimes 408592Srgrimes /* load base of page directory and enable mapping */ 409570Srgrimes movl %esi,%eax /* phys address of ptd in proc 0 */ 410570Srgrimes orl $I386_CR3PAT,%eax 411570Srgrimes movl %eax,%cr3 /* load ptd addr into mmu */ 412570Srgrimes movl %cr0,%eax /* get control word */ 413200Sdg/* 414200Sdg * XXX it is now safe to always (attempt to) set CR0_WP and to set up 415200Sdg * the page tables assuming it works, so USE_486_WRITE_PROTECT will go 416200Sdg * away. The special 386 PTE checking needs to be conditional on 417200Sdg * whatever distingiushes 486-only kernels from 386-486 kernels. 418200Sdg */ 4194Srgrimes#ifdef USE_486_WRITE_PROTECT 420570Srgrimes orl $CR0_PE|CR0_PG|CR0_WP,%eax /* enable paging */ 4214Srgrimes#else 422570Srgrimes orl $CR0_PE|CR0_PG,%eax /* enable paging */ 4234Srgrimes#endif 424570Srgrimes movl %eax,%cr0 /* and let's page NOW! */ 4254Srgrimes 426570Srgrimes pushl $begin /* jump to high mem */ 4274Srgrimes ret 4284Srgrimes 429570Srgrimesbegin: /* now running relocated at KERNBASE where the system is linked to run */ 4304Srgrimes 431592Srgrimes .globl _Crtat /* XXX - locore should not know about */ 432592Srgrimes movl _Crtat,%eax /* variables of device drivers (pccons)! */ 433592Srgrimes subl $(KERNBASE+0xA0000),%eax 434570Srgrimes movl _atdevphys,%edx /* get pte PA */ 435570Srgrimes subl _KPTphys,%edx /* remove base of ptes, now have phys offset */ 436570Srgrimes shll $PGSHIFT-2,%edx /* corresponding to virt offset */ 437570Srgrimes addl $KERNBASE,%edx /* add virtual base */ 438570Srgrimes movl %edx,_atdevbase 4394Srgrimes addl %eax,%edx 4404Srgrimes movl %edx,_Crtat 4414Srgrimes 4424Srgrimes /* set up bootstrap stack */ 443570Srgrimes movl $_kstack+UPAGES*NBPG-4*12,%esp /* bootstrap stack end location */ 444570Srgrimes xorl %eax,%eax /* mark end of frames */ 4454Srgrimes movl %eax,%ebp 446570Srgrimes movl _proc0paddr,%eax 447570Srgrimes movl %esi,PCB_CR3(%eax) 4484Srgrimes 4494Srgrimes /* relocate debugger gdt entries */ 4504Srgrimes 451570Srgrimes movl $_gdt+8*9,%eax /* adjust slots 9-17 */ 4524Srgrimes movl $9,%ecx 4534Srgrimesreloc_gdt: 454570Srgrimes movb $0xfe,7(%eax) /* top byte of base addresses, was 0, */ 455570Srgrimes addl $8,%eax /* now KERNBASE>>24 */ 4564Srgrimes loop reloc_gdt 4574Srgrimes 4584Srgrimes cmpl $0,_bdb_exists 4594Srgrimes je 1f 4604Srgrimes int $3 4614Srgrimes1: 4624Srgrimes 463608Srgrimes /* 464608Srgrimes * Skip over the page tables and the kernel stack 465608Srgrimes * XXX 4 is kstack size 466608Srgrimes */ 467608Srgrimes lea (NKPDE + 4) * NBPG(%esi),%esi 468608Srgrimes 469608Srgrimes pushl %esi /* value of first for init386(first) */ 470570Srgrimes call _init386 /* wire 386 chip for unix operation */ 471200Sdg 4724Srgrimes movl $0,_PTD 473570Srgrimes call _main /* autoconfiguration, mountroot etc */ 4744Srgrimes popl %esi 4754Srgrimes 476134Sdg /* 477570Srgrimes * now we've run main() and determined what cpu-type we are, we can 478570Srgrimes * enable WP mode on i486 cpus and above. 479134Sdg * on return from main(), we are process 1 480134Sdg * set up address space and stack so that we can 'return' to user mode 481134Sdg */ 482134Sdg 483570Srgrimes .globl __ucodesel,__udatasel 4844Srgrimes movl __ucodesel,%eax 4854Srgrimes movl __udatasel,%ecx 486570Srgrimes /* build outer stack frame */ 487570Srgrimes pushl %ecx /* user ss */ 488570Srgrimes pushl $USRSTACK /* user esp */ 489570Srgrimes pushl %eax /* user cs */ 490570Srgrimes pushl $0 /* user ip */ 4914Srgrimes movl %cx,%ds 4924Srgrimes movl %cx,%es 493570Srgrimes movl %ax,%fs /* double map cs to fs */ 494570Srgrimes movl %cx,%gs /* and ds to gs */ 495570Srgrimes lret /* goto user! */ 4964Srgrimes 4974Srgrimes pushl $lretmsg1 /* "should never get here!" */ 4984Srgrimes call _panic 4994Srgrimeslretmsg1: 5004Srgrimes .asciz "lret: toinit\n" 5014Srgrimes 5024Srgrimes 5034Srgrimes .set exec,59 5044Srgrimes .set exit,1 5054Srgrimes 5064Srgrimes#define LCALL(x,y) .byte 0x9a ; .long y; .word x 5074Srgrimes/* 508134Sdg * Icode is copied out to process 1 and executed in user mode: 509134Sdg * execve("/sbin/init", argv, envp); exit(0); 510200Sdg * If the execve fails, process 1 exits and the system panics. 5114Srgrimes */ 512200SdgNON_GPROF_ENTRY(icode) 513570Srgrimes pushl $0 /* envp for execve() */ 514200Sdg 515570Srgrimes# pushl $argv-_icode /* can't do this 'cos gas 1.38 is broken */ 5164Srgrimes movl $argv,%eax 5174Srgrimes subl $_icode,%eax 518570Srgrimes pushl %eax /* argp for execve() */ 5194Srgrimes 520570Srgrimes# pushl $init-_icode 5214Srgrimes movl $init,%eax 5224Srgrimes subl $_icode,%eax 523570Srgrimes pushl %eax /* fname for execve() */ 5244Srgrimes 525570Srgrimes pushl %eax /* dummy return address */ 526200Sdg 5274Srgrimes movl $exec,%eax 5284Srgrimes LCALL(0x7,0x0) 529200Sdg 530570Srgrimes /* exit if something botches up in the above execve() */ 531570Srgrimes pushl %eax /* execve failed, the errno will do for an */ 532570Srgrimes /* exit code because errnos are < 128 */ 533570Srgrimes pushl %eax /* dummy return address */ 5344Srgrimes movl $exit,%eax 5354Srgrimes LCALL(0x7,0x0) 5364Srgrimes 5374Srgrimesinit: 5384Srgrimes .asciz "/sbin/init" 5394Srgrimes ALIGN_DATA 5404Srgrimesargv: 541570Srgrimes .long init+6-_icode /* argv[0] = "init" ("/sbin/init" + 6) */ 542570Srgrimes .long eicode-_icode /* argv[1] follows icode after copyout */ 5434Srgrimes .long 0 5444Srgrimeseicode: 5454Srgrimes 5464Srgrimes .globl _szicode 5474Srgrimes_szicode: 5484Srgrimes .long _szicode-_icode 5494Srgrimes 550200SdgNON_GPROF_ENTRY(sigcode) 551592Srgrimes call SIGF_HANDLER(%esp) 552592Srgrimes lea SIGF_SC(%esp),%eax /* scp (the call may have clobbered the */ 553592Srgrimes /* copy at 8(%esp)) */ 5544Srgrimes pushl %eax 555570Srgrimes pushl %eax /* junk to fake return address */ 556592Srgrimes movl $103,%eax /* XXX sigreturn() */ 557570Srgrimes LCALL(0x7,0) /* enter kernel with args on stack */ 558570Srgrimes hlt /* never gets here */ 5594Srgrimes 5604Srgrimes .globl _szsigcode 5614Srgrimes_szsigcode: 5624Srgrimes .long _szsigcode-_sigcode 5634Srgrimes 564570Srgrimes/* 565570Srgrimes * Support routines for GCC, general C-callable functions 566570Srgrimes */ 5674SrgrimesENTRY(__udivsi3) 5684Srgrimes movl 4(%esp),%eax 5694Srgrimes xorl %edx,%edx 5704Srgrimes divl 8(%esp) 5714Srgrimes ret 5724Srgrimes 5734SrgrimesENTRY(__divsi3) 5744Srgrimes movl 4(%esp),%eax 5754Srgrimes cltd 5764Srgrimes idivl 8(%esp) 5774Srgrimes ret 5784Srgrimes 5794Srgrimes /* 5804Srgrimes * I/O bus instructions via C 5814Srgrimes */ 582570SrgrimesENTRY(inb) /* val = inb(port) */ 5834Srgrimes movl 4(%esp),%edx 584570Srgrimes subl %eax,%eax 585134Sdg NOP 586570Srgrimes inb %dx,%al 587134Sdg ret 588134Sdg 589570SrgrimesENTRY(inw) /* val = inw(port) */ 590134Sdg movl 4(%esp),%edx 591570Srgrimes subl %eax,%eax 592134Sdg NOP 593570Srgrimes inw %dx,%ax 594134Sdg ret 595134Sdg 596570SrgrimesENTRY(insb) /* insb(port, addr, cnt) */ 597570Srgrimes pushl %edi 598134Sdg movw 8(%esp),%dx 599570Srgrimes movl 12(%esp),%edi 600134Sdg movl 16(%esp),%ecx 601134Sdg cld 602134Sdg NOP 603134Sdg rep 604570Srgrimes insb 605134Sdg NOP 606570Srgrimes movl %edi,%eax 607570Srgrimes popl %edi 608134Sdg ret 609134Sdg 610570SrgrimesENTRY(insw) /* insw(port, addr, cnt) */ 611570Srgrimes pushl %edi 612134Sdg movw 8(%esp),%dx 613570Srgrimes movl 12(%esp),%edi 614134Sdg movl 16(%esp),%ecx 615134Sdg cld 616134Sdg NOP 617134Sdg rep 618570Srgrimes insw 619134Sdg NOP 620570Srgrimes movl %edi,%eax 621570Srgrimes popl %edi 622134Sdg ret 623134Sdg 624570SrgrimesENTRY(rtcin) /* rtcin(val) */ 625570Srgrimes movl 4(%esp),%eax 626570Srgrimes outb %al,$0x70 627570Srgrimes subl %eax,%eax 628570Srgrimes inb $0x71,%al 629570Srgrimes ret 630134Sdg 631570SrgrimesENTRY(outb) /* outb(port, val) */ 632134Sdg movl 4(%esp),%edx 6334Srgrimes NOP 634570Srgrimes movl 8(%esp),%eax 635570Srgrimes outb %al,%dx 636570Srgrimes NOP 6374Srgrimes ret 6384Srgrimes 639570SrgrimesENTRY(outw) /* outw(port, val) */ 6404Srgrimes movl 4(%esp),%edx 6414Srgrimes NOP 642570Srgrimes movl 8(%esp),%eax 643570Srgrimes outw %ax,%dx 644570Srgrimes NOP 6454Srgrimes ret 6464Srgrimes 647570SrgrimesENTRY(outsb) /* outsb(port, addr, cnt) */ 648570Srgrimes pushl %esi 649134Sdg movw 8(%esp),%dx 650570Srgrimes movl 12(%esp),%esi 651134Sdg movl 16(%esp),%ecx 652134Sdg cld 653134Sdg NOP 654134Sdg rep 655570Srgrimes outsb 656134Sdg NOP 657570Srgrimes movl %esi,%eax 658570Srgrimes popl %esi 659134Sdg ret 660134Sdg 661570SrgrimesENTRY(outsw) /* outsw(port, addr, cnt) */ 662570Srgrimes pushl %esi 663134Sdg movw 8(%esp),%dx 664570Srgrimes movl 12(%esp),%esi 665134Sdg movl 16(%esp),%ecx 666134Sdg cld 667134Sdg NOP 668134Sdg rep 669570Srgrimes outsw 670134Sdg NOP 671570Srgrimes movl %esi,%eax 672570Srgrimes popl %esi 673134Sdg ret 674134Sdg 6754Srgrimes /* 676134Sdg * bcopy family 6774Srgrimes */ 678570SrgrimesENTRY(bzero) /* void bzero(void *base, u_int cnt) */ 6794Srgrimes pushl %edi 6804Srgrimes movl 8(%esp),%edi 6814Srgrimes movl 12(%esp),%ecx 6824Srgrimes xorl %eax,%eax 683200Sdg shrl $2,%ecx 6844Srgrimes cld 6854Srgrimes rep 6864Srgrimes stosl 6874Srgrimes movl 12(%esp),%ecx 6884Srgrimes andl $3,%ecx 6894Srgrimes rep 6904Srgrimes stosb 6914Srgrimes popl %edi 6924Srgrimes ret 6934Srgrimes 694570SrgrimesENTRY(fillw) /* fillw(pat, base, cnt) */ 6954Srgrimes pushl %edi 6964Srgrimes movl 8(%esp),%eax 6974Srgrimes movl 12(%esp),%edi 6984Srgrimes movl 16(%esp),%ecx 6994Srgrimes cld 7004Srgrimes rep 7014Srgrimes stosw 7024Srgrimes popl %edi 7034Srgrimes ret 7044Srgrimes 7054SrgrimesENTRY(bcopyb) 706200Sdgbcopyb: 7074Srgrimes pushl %esi 7084Srgrimes pushl %edi 7094Srgrimes movl 12(%esp),%esi 7104Srgrimes movl 16(%esp),%edi 7114Srgrimes movl 20(%esp),%ecx 7124Srgrimes cmpl %esi,%edi /* potentially overlapping? */ 7134Srgrimes jnb 1f 7144Srgrimes cld /* nope, copy forwards */ 715200Sdg rep 7164Srgrimes movsb 7174Srgrimes popl %edi 7184Srgrimes popl %esi 7194Srgrimes ret 7204Srgrimes 7214Srgrimes ALIGN_TEXT 7224Srgrimes1: 7234Srgrimes addl %ecx,%edi /* copy backwards. */ 7244Srgrimes addl %ecx,%esi 7254Srgrimes std 7264Srgrimes decl %edi 7274Srgrimes decl %esi 7284Srgrimes rep 7294Srgrimes movsb 7304Srgrimes popl %edi 7314Srgrimes popl %esi 7324Srgrimes cld 7334Srgrimes ret 7344Srgrimes 7354SrgrimesENTRY(bcopyw) 736200Sdgbcopyw: 7374Srgrimes pushl %esi 7384Srgrimes pushl %edi 7394Srgrimes movl 12(%esp),%esi 7404Srgrimes movl 16(%esp),%edi 7414Srgrimes movl 20(%esp),%ecx 7424Srgrimes cmpl %esi,%edi /* potentially overlapping? */ 7434Srgrimes jnb 1f 7444Srgrimes cld /* nope, copy forwards */ 7454Srgrimes shrl $1,%ecx /* copy by 16-bit words */ 7464Srgrimes rep 7474Srgrimes movsw 7484Srgrimes adc %ecx,%ecx /* any bytes left? */ 7494Srgrimes rep 7504Srgrimes movsb 7514Srgrimes popl %edi 7524Srgrimes popl %esi 7534Srgrimes ret 7544Srgrimes 7554Srgrimes ALIGN_TEXT 7564Srgrimes1: 7574Srgrimes addl %ecx,%edi /* copy backwards */ 7584Srgrimes addl %ecx,%esi 7594Srgrimes std 7604Srgrimes andl $1,%ecx /* any fractional bytes? */ 7614Srgrimes decl %edi 7624Srgrimes decl %esi 7634Srgrimes rep 7644Srgrimes movsb 7654Srgrimes movl 20(%esp),%ecx /* copy remainder by 16-bit words */ 7664Srgrimes shrl $1,%ecx 7674Srgrimes decl %esi 7684Srgrimes decl %edi 7694Srgrimes rep 7704Srgrimes movsw 7714Srgrimes popl %edi 7724Srgrimes popl %esi 7734Srgrimes cld 7744Srgrimes ret 7754Srgrimes 7764SrgrimesENTRY(bcopyx) 7774Srgrimes movl 16(%esp),%eax 7784Srgrimes cmpl $2,%eax 779200Sdg je bcopyw /* not _bcopyw, to avoid multiple mcounts */ 7804Srgrimes cmpl $4,%eax 781200Sdg je bcopy 782200Sdg jmp bcopyb 7834Srgrimes 7844Srgrimes /* 785570Srgrimes * (ov)bcopy(src, dst, cnt) 7864Srgrimes * ws@tools.de (Wolfgang Solfrank, TooLs GmbH) +49-228-985800 7874Srgrimes */ 788200SdgALTENTRY(ovbcopy) 7894SrgrimesENTRY(bcopy) 790200Sdgbcopy: 7914Srgrimes pushl %esi 7924Srgrimes pushl %edi 7934Srgrimes movl 12(%esp),%esi 7944Srgrimes movl 16(%esp),%edi 7954Srgrimes movl 20(%esp),%ecx 7964Srgrimes cmpl %esi,%edi /* potentially overlapping? */ 7974Srgrimes jnb 1f 7984Srgrimes cld /* nope, copy forwards */ 7994Srgrimes shrl $2,%ecx /* copy by 32-bit words */ 8004Srgrimes rep 8014Srgrimes movsl 8024Srgrimes movl 20(%esp),%ecx 8034Srgrimes andl $3,%ecx /* any bytes left? */ 8044Srgrimes rep 8054Srgrimes movsb 8064Srgrimes popl %edi 8074Srgrimes popl %esi 8084Srgrimes ret 8094Srgrimes 8104Srgrimes ALIGN_TEXT 8114Srgrimes1: 8124Srgrimes addl %ecx,%edi /* copy backwards */ 8134Srgrimes addl %ecx,%esi 8144Srgrimes std 8154Srgrimes andl $3,%ecx /* any fractional bytes? */ 8164Srgrimes decl %edi 8174Srgrimes decl %esi 8184Srgrimes rep 8194Srgrimes movsb 8204Srgrimes movl 20(%esp),%ecx /* copy remainder by 32-bit words */ 8214Srgrimes shrl $2,%ecx 8224Srgrimes subl $3,%esi 8234Srgrimes subl $3,%edi 8244Srgrimes rep 8254Srgrimes movsl 8264Srgrimes popl %edi 8274Srgrimes popl %esi 8284Srgrimes cld 8294Srgrimes ret 8304Srgrimes 831200SdgALTENTRY(ntohl) 832200SdgENTRY(htonl) 833134Sdg movl 4(%esp),%eax 834134Sdg#ifdef i486 835134Sdg /* XXX */ 836134Sdg /* Since Gas 1.38 does not grok bswap this has been coded as the 837134Sdg * equivalent bytes. This can be changed back to bswap when we 838134Sdg * upgrade to a newer version of Gas */ 839134Sdg /* bswap %eax */ 840200Sdg .byte 0x0f 841134Sdg .byte 0xc8 842134Sdg#else 843134Sdg xchgb %al,%ah 844134Sdg roll $16,%eax 845134Sdg xchgb %al,%ah 846134Sdg#endif 847134Sdg ret 848134Sdg 849200SdgALTENTRY(ntohs) 850200SdgENTRY(htons) 851134Sdg movzwl 4(%esp),%eax 852134Sdg xchgb %al,%ah 853134Sdg ret 854134Sdg 855134Sdg/*****************************************************************************/ 856134Sdg/* copyout and fubyte family */ 857134Sdg/*****************************************************************************/ 858134Sdg/* 859134Sdg * Access user memory from inside the kernel. These routines and possibly 860134Sdg * the math- and DOS emulators should be the only places that do this. 861134Sdg * 862134Sdg * We have to access the memory with user's permissions, so use a segment 863134Sdg * selector with RPL 3. For writes to user space we have to additionally 864134Sdg * check the PTE for write permission, because the 386 does not check 865134Sdg * write permissions when we are executing with EPL 0. The 486 does check 866134Sdg * this if the WP bit is set in CR0, so we can use a simpler version here. 867134Sdg * 868134Sdg * These routines set curpcb->onfault for the time they execute. When a 869134Sdg * protection violation occurs inside the functions, the trap handler 870134Sdg * returns to *curpcb->onfault instead of the function. 871134Sdg */ 872134Sdg 873134Sdg 874570SrgrimesENTRY(copyout) /* copyout(from_kernel, to_user, len) */ 875570Srgrimes movl _curpcb,%eax 876570Srgrimes movl $copyout_fault,PCB_ONFAULT(%eax) 8774Srgrimes pushl %esi 8784Srgrimes pushl %edi 8794Srgrimes pushl %ebx 880570Srgrimes movl 16(%esp),%esi 881570Srgrimes movl 20(%esp),%edi 882570Srgrimes movl 24(%esp),%ebx 883570Srgrimes orl %ebx,%ebx /* anything to do? */ 884134Sdg jz done_copyout 8854Srgrimes 886200Sdg /* 887200Sdg * Check explicitly for non-user addresses. If 486 write protection 888200Sdg * is being used, this check is essential because we are in kernel 889200Sdg * mode so the h/w does not provide any protection against writing 890200Sdg * kernel addresses. 891200Sdg * 892200Sdg * Otherwise, it saves having to load and restore %es to get the 893200Sdg * usual segment-based protection (the destination segment for movs 894200Sdg * is always %es). The other explicit checks for user-writablility 895200Sdg * are not quite sufficient. They fail for the user area because 896200Sdg * we mapped the user area read/write to avoid having an #ifdef in 897200Sdg * vm_machdep.c. They fail for user PTEs and/or PTDs! (107 898200Sdg * addresses including 0xff800000 and 0xfc000000). I'm not sure if 899200Sdg * this can be fixed. Marking the PTEs supervisor mode and the 900200Sdg * PDE's user mode would almost work, but there may be a problem 901200Sdg * with the self-referential PDE. 902200Sdg */ 903570Srgrimes movl %edi,%eax 904570Srgrimes addl %ebx,%eax 905200Sdg jc copyout_fault 906200Sdg#define VM_END_USER_ADDRESS 0xFDBFE000 /* XXX */ 907570Srgrimes cmpl $VM_END_USER_ADDRESS,%eax 908200Sdg ja copyout_fault 9094Srgrimes 910200Sdg#ifndef USE_486_WRITE_PROTECT 911200Sdg /* 912200Sdg * We have to check each PTE for user write permission. 913200Sdg * The checking may cause a page fault, so it is important to set 914200Sdg * up everything for return via copyout_fault before here. 915200Sdg */ 916134Sdg /* compute number of pages */ 917570Srgrimes movl %edi,%ecx 918570Srgrimes andl $NBPG-1,%ecx 919570Srgrimes addl %ebx,%ecx 920134Sdg decl %ecx 921570Srgrimes shrl $IDXSHIFT+2,%ecx 922134Sdg incl %ecx 923134Sdg 924134Sdg /* compute PTE offset for start address */ 925570Srgrimes movl %edi,%edx 926570Srgrimes shrl $IDXSHIFT,%edx 927570Srgrimes andb $0xfc,%dl 928134Sdg 929134Sdg1: /* check PTE for each page */ 930570Srgrimes movb _PTmap(%edx),%al 931570Srgrimes andb $0x07,%al /* Pages must be VALID + USERACC + WRITABLE */ 932570Srgrimes cmpb $0x07,%al 933134Sdg je 2f 934200Sdg 935134Sdg /* simulate a trap */ 936134Sdg pushl %edx 937134Sdg pushl %ecx 938570Srgrimes shll $IDXSHIFT,%edx 939134Sdg pushl %edx 940570Srgrimes call _trapwrite /* trapwrite(addr) */ 9414Srgrimes popl %edx 942134Sdg popl %ecx 943134Sdg popl %edx 9444Srgrimes 945570Srgrimes orl %eax,%eax /* if not ok, return EFAULT */ 946134Sdg jnz copyout_fault 947134Sdg 9484Srgrimes2: 949570Srgrimes addl $4,%edx 950134Sdg decl %ecx 951134Sdg jnz 1b /* check next page */ 952200Sdg#endif /* ndef USE_486_WRITE_PROTECT */ 9534Srgrimes 954570Srgrimes /* bcopy(%esi, %edi, %ebx) */ 9554Srgrimes cld 956570Srgrimes movl %ebx,%ecx 957570Srgrimes shrl $2,%ecx 9584Srgrimes rep 9594Srgrimes movsl 960570Srgrimes movb %bl,%cl 961570Srgrimes andb $3,%cl /* XXX can we trust the rest of %ecx on clones? */ 9624Srgrimes rep 9634Srgrimes movsb 9644Srgrimes 965134Sdgdone_copyout: 9664Srgrimes popl %ebx 9674Srgrimes popl %edi 9684Srgrimes popl %esi 9694Srgrimes xorl %eax,%eax 9704Srgrimes movl _curpcb,%edx 9714Srgrimes movl %eax,PCB_ONFAULT(%edx) 9724Srgrimes ret 9734Srgrimes 974200Sdg ALIGN_TEXT 975134Sdgcopyout_fault: 9764Srgrimes popl %ebx 9774Srgrimes popl %edi 9784Srgrimes popl %esi 979570Srgrimes movl _curpcb,%edx 980570Srgrimes movl $0,PCB_ONFAULT(%edx) 981570Srgrimes movl $EFAULT,%eax 9824Srgrimes ret 9834Srgrimes 984570SrgrimesENTRY(copyin) /* copyin(from_user, to_kernel, len) */ 9854Srgrimes movl _curpcb,%eax 986570Srgrimes movl $copyin_fault,PCB_ONFAULT(%eax) 9874Srgrimes pushl %esi 9884Srgrimes pushl %edi 989570Srgrimes movl 12(%esp),%esi /* caddr_t from */ 990570Srgrimes movl 16(%esp),%edi /* caddr_t to */ 991570Srgrimes movl 20(%esp),%ecx /* size_t len */ 992134Sdg 993134Sdg movb %cl,%al 994570Srgrimes shrl $2,%ecx /* copy longword-wise */ 9954Srgrimes cld 996200Sdg gs 9974Srgrimes rep 9984Srgrimes movsl 999134Sdg movb %al,%cl 1000570Srgrimes andb $3,%cl /* copy remaining bytes */ 1001200Sdg gs 10024Srgrimes rep 10034Srgrimes movsb 1004134Sdg 10054Srgrimes popl %edi 10064Srgrimes popl %esi 1007570Srgrimes xorl %eax,%eax 1008570Srgrimes movl _curpcb,%edx 1009570Srgrimes movl %eax,PCB_ONFAULT(%edx) 10104Srgrimes ret 10114Srgrimes 1012200Sdg ALIGN_TEXT 1013134Sdgcopyin_fault: 10144Srgrimes popl %edi 10154Srgrimes popl %esi 1016570Srgrimes movl _curpcb,%edx 1017570Srgrimes movl $0,PCB_ONFAULT(%edx) 1018570Srgrimes movl $EFAULT,%eax 1019134Sdg ret 1020134Sdg 1021134Sdg /* 1022570Srgrimes * fu{byte,sword,word} : fetch a byte(sword, word) from user memory 1023134Sdg */ 1024200SdgALTENTRY(fuiword) 1025134SdgENTRY(fuword) 1026134Sdg movl _curpcb,%ecx 1027134Sdg movl $fusufault,PCB_ONFAULT(%ecx) 1028134Sdg movl 4(%esp),%edx 1029134Sdg gs 1030134Sdg movl (%edx),%eax 1031134Sdg movl $0,PCB_ONFAULT(%ecx) 1032134Sdg ret 1033200Sdg 1034134SdgENTRY(fusword) 1035134Sdg movl _curpcb,%ecx 1036134Sdg movl $fusufault,PCB_ONFAULT(%ecx) 1037134Sdg movl 4(%esp),%edx 1038134Sdg gs 1039134Sdg movzwl (%edx),%eax 1040134Sdg movl $0,PCB_ONFAULT(%ecx) 1041134Sdg ret 1042200Sdg 1043200SdgALTENTRY(fuibyte) 1044134SdgENTRY(fubyte) 1045134Sdg movl _curpcb,%ecx 1046134Sdg movl $fusufault,PCB_ONFAULT(%ecx) 1047134Sdg movl 4(%esp),%edx 1048134Sdg gs 1049134Sdg movzbl (%edx),%eax 1050134Sdg movl $0,PCB_ONFAULT(%ecx) 1051134Sdg ret 1052200Sdg 1053200Sdg ALIGN_TEXT 1054134Sdgfusufault: 1055134Sdg movl _curpcb,%ecx 10564Srgrimes xorl %eax,%eax 1057134Sdg movl %eax,PCB_ONFAULT(%ecx) 1058134Sdg decl %eax 10594Srgrimes ret 10604Srgrimes 1061134Sdg /* 1062570Srgrimes * su{byte,sword,word}: write a byte(word, longword) to user memory 1063134Sdg */ 1064134Sdg#ifdef USE_486_WRITE_PROTECT 1065134Sdg /* 1066134Sdg * we only have to set the right segment selector. 1067134Sdg */ 1068200SdgALTENTRY(suiword) 1069134SdgENTRY(suword) 1070134Sdg movl _curpcb,%ecx 1071134Sdg movl $fusufault,PCB_ONFAULT(%ecx) 1072134Sdg movl 4(%esp),%edx 1073134Sdg movl 8(%esp),%eax 1074134Sdg gs 1075134Sdg movl %eax,(%edx) 1076200Sdg xorl %eax,%eax 1077200Sdg movl %eax,PCB_ONFAULT(%ecx) 10784Srgrimes ret 1079200Sdg 1080134SdgENTRY(susword) 1081134Sdg movl _curpcb,%ecx 1082134Sdg movl $fusufault,PCB_ONFAULT(%ecx) 1083134Sdg movl 4(%esp),%edx 1084134Sdg movw 8(%esp),%ax 1085134Sdg gs 1086134Sdg movw %ax,(%edx) 1087200Sdg xorl %eax,%eax 1088200Sdg movl %eax,PCB_ONFAULT(%ecx) 1089134Sdg ret 1090200Sdg 1091200SdgALTENTRY(suibyte) 1092134SdgENTRY(subyte) 1093134Sdg movl _curpcb,%ecx 1094134Sdg movl $fusufault,PCB_ONFAULT(%ecx) 1095134Sdg movl 4(%esp),%edx 1096134Sdg movb 8(%esp),%al 1097134Sdg gs 1098134Sdg movb %al,(%edx) 1099200Sdg xorl %eax,%eax 1100200Sdg movl %eax,PCB_ONFAULT(%ecx) 1101134Sdg ret 11024Srgrimes 11034Srgrimes 1104134Sdg#else /* USE_486_WRITE_PROTECT */ 1105134Sdg /* 1106134Sdg * here starts the trouble again: check PTE, twice if word crosses 1107134Sdg * a page boundary. 1108134Sdg */ 1109570Srgrimes /* XXX - page boundary crossing is not handled yet */ 1110134Sdg 1111200SdgALTENTRY(suibyte) 1112134SdgENTRY(subyte) 1113570Srgrimes movl _curpcb,%ecx 1114570Srgrimes movl $fusufault,PCB_ONFAULT(%ecx) 1115570Srgrimes movl 4(%esp),%edx 1116570Srgrimes movl %edx,%eax 1117570Srgrimes shrl $IDXSHIFT,%edx 1118570Srgrimes andb $0xfc,%dl 1119570Srgrimes movb _PTmap(%edx),%dl 1120570Srgrimes andb $0x7,%dl /* must be VALID + USERACC + WRITE */ 1121570Srgrimes cmpb $0x7,%dl 1122134Sdg je 1f 1123134Sdg /* simulate a trap */ 1124134Sdg pushl %eax 1125134Sdg call _trapwrite 1126134Sdg popl %edx 1127570Srgrimes orl %eax,%eax 1128134Sdg jnz fusufault 1129134Sdg1: 1130570Srgrimes movl 4(%esp),%edx 1131570Srgrimes movl 8(%esp),%eax 1132200Sdg gs 1133570Srgrimes movb %al,(%edx) 1134570Srgrimes xorl %eax,%eax 1135570Srgrimes movl _curpcb,%ecx 1136570Srgrimes movl %eax,PCB_ONFAULT(%ecx) 11374Srgrimes ret 11384Srgrimes 1139134SdgENTRY(susword) 1140570Srgrimes movl _curpcb,%ecx 1141570Srgrimes movl $fusufault,PCB_ONFAULT(%ecx) 1142570Srgrimes movl 4(%esp),%edx 1143570Srgrimes movl %edx,%eax 1144570Srgrimes shrl $IDXSHIFT,%edx 1145570Srgrimes andb $0xfc,%dl 1146570Srgrimes movb _PTmap(%edx),%dl 1147570Srgrimes andb $0x7,%dl /* must be VALID + USERACC + WRITE */ 1148570Srgrimes cmpb $0x7,%dl 1149134Sdg je 1f 1150134Sdg /* simulate a trap */ 1151134Sdg pushl %eax 1152134Sdg call _trapwrite 1153134Sdg popl %edx 1154570Srgrimes orl %eax,%eax 1155134Sdg jnz fusufault 1156134Sdg1: 1157570Srgrimes movl 4(%esp),%edx 1158570Srgrimes movl 8(%esp),%eax 1159200Sdg gs 1160570Srgrimes movw %ax,(%edx) 1161570Srgrimes xorl %eax,%eax 1162570Srgrimes movl _curpcb,%ecx 1163570Srgrimes movl %eax,PCB_ONFAULT(%ecx) 1164134Sdg ret 1165134Sdg 1166200SdgALTENTRY(suiword) 1167134SdgENTRY(suword) 1168570Srgrimes movl _curpcb,%ecx 1169570Srgrimes movl $fusufault,PCB_ONFAULT(%ecx) 1170570Srgrimes movl 4(%esp),%edx 1171570Srgrimes movl %edx,%eax 1172570Srgrimes shrl $IDXSHIFT,%edx 1173570Srgrimes andb $0xfc,%dl 1174570Srgrimes movb _PTmap(%edx),%dl 1175570Srgrimes andb $0x7,%dl /* must be VALID + USERACC + WRITE */ 1176570Srgrimes cmpb $0x7,%dl 1177134Sdg je 1f 1178134Sdg /* simulate a trap */ 1179134Sdg pushl %eax 1180134Sdg call _trapwrite 1181134Sdg popl %edx 1182570Srgrimes orl %eax,%eax 1183134Sdg jnz fusufault 1184134Sdg1: 1185570Srgrimes movl 4(%esp),%edx 1186570Srgrimes movl 8(%esp),%eax 1187200Sdg gs 1188570Srgrimes movl %eax,0(%edx) 1189570Srgrimes xorl %eax,%eax 1190570Srgrimes movl _curpcb,%ecx 1191570Srgrimes movl %eax,PCB_ONFAULT(%ecx) 1192134Sdg ret 1193134Sdg 1194134Sdg#endif /* USE_486_WRITE_PROTECT */ 1195200Sdg 1196134Sdg/* 1197134Sdg * copyoutstr(from, to, maxlen, int *lencopied) 1198134Sdg * copy a string from from to to, stop when a 0 character is reached. 1199134Sdg * return ENAMETOOLONG if string is longer than maxlen, and 1200134Sdg * EFAULT on protection violations. If lencopied is non-zero, 1201134Sdg * return the actual length in *lencopied. 1202134Sdg */ 1203134Sdg#ifdef USE_486_WRITE_PROTECT 1204134Sdg 1205134SdgENTRY(copyoutstr) 1206134Sdg pushl %esi 12074Srgrimes pushl %edi 1208570Srgrimes movl _curpcb,%ecx 1209570Srgrimes movl $cpystrflt,PCB_ONFAULT(%ecx) 1210134Sdg 1211570Srgrimes movl 12(%esp),%esi /* %esi = from */ 1212570Srgrimes movl 16(%esp),%edi /* %edi = to */ 1213570Srgrimes movl 20(%esp),%edx /* %edx = maxlen */ 1214134Sdg incl %edx 1215134Sdg 1216134Sdg1: 1217134Sdg decl %edx 1218134Sdg jz 4f 1219200Sdg /* 1220200Sdg * gs override doesn't work for stosb. Use the same explicit check 1221200Sdg * as in copyout(). It's much slower now because it is per-char. 1222200Sdg * XXX - however, it would be faster to rewrite this function to use 1223200Sdg * strlen() and copyout(). 1224200Sdg */ 1225570Srgrimes cmpl $VM_END_USER_ADDRESS,%edi 1226200Sdg jae cpystrflt 1227134Sdg lodsb 1228134Sdg gs 1229134Sdg stosb 1230134Sdg orb %al,%al 1231134Sdg jnz 1b 1232134Sdg /* Success -- 0 byte reached */ 1233134Sdg decl %edx 1234570Srgrimes xorl %eax,%eax 1235134Sdg jmp 6f 1236134Sdg4: 1237134Sdg /* edx is zero -- return ENAMETOOLONG */ 1238570Srgrimes movl $ENAMETOOLONG,%eax 1239134Sdg jmp 6f 1240134Sdg 1241200Sdg#else /* ndef USE_486_WRITE_PROTECT */ 1242134Sdg 1243134SdgENTRY(copyoutstr) 1244134Sdg pushl %esi 1245134Sdg pushl %edi 1246570Srgrimes movl _curpcb,%ecx 1247570Srgrimes movl $cpystrflt,PCB_ONFAULT(%ecx) 1248134Sdg 1249570Srgrimes movl 12(%esp),%esi /* %esi = from */ 1250570Srgrimes movl 16(%esp),%edi /* %edi = to */ 1251570Srgrimes movl 20(%esp),%edx /* %edx = maxlen */ 1252134Sdg1: 1253200Sdg /* 1254200Sdg * It suffices to check that the first byte is in user space, because 1255200Sdg * we look at a page at a time and the end address is on a page 1256200Sdg * boundary. 1257200Sdg */ 1258570Srgrimes cmpl $VM_END_USER_ADDRESS,%edi 1259200Sdg jae cpystrflt 1260570Srgrimes movl %edi,%eax 1261570Srgrimes shrl $IDXSHIFT,%eax 1262570Srgrimes andb $0xfc,%al 1263570Srgrimes movb _PTmap(%eax),%al 1264570Srgrimes andb $7,%al 1265570Srgrimes cmpb $7,%al 1266134Sdg je 2f 1267134Sdg 1268134Sdg /* simulate trap */ 1269134Sdg pushl %edx 1270134Sdg pushl %edi 1271134Sdg call _trapwrite 12724Srgrimes popl %edi 1273134Sdg popl %edx 1274570Srgrimes orl %eax,%eax 1275134Sdg jnz cpystrflt 12764Srgrimes 1277134Sdg2: /* copy up to end of this page */ 1278570Srgrimes movl %edi,%eax 1279570Srgrimes andl $NBPG-1,%eax 1280570Srgrimes movl $NBPG,%ecx 1281570Srgrimes subl %eax,%ecx /* ecx = NBPG - (src % NBPG) */ 1282570Srgrimes cmpl %ecx,%edx 1283134Sdg jge 3f 1284570Srgrimes movl %edx,%ecx /* ecx = min(ecx, edx) */ 1285134Sdg3: 1286570Srgrimes orl %ecx,%ecx 1287134Sdg jz 4f 1288134Sdg decl %ecx 1289134Sdg decl %edx 1290134Sdg lodsb 1291134Sdg stosb 1292570Srgrimes orb %al,%al 1293134Sdg jnz 3b 1294134Sdg 1295134Sdg /* Success -- 0 byte reached */ 1296134Sdg decl %edx 1297570Srgrimes xorl %eax,%eax 1298134Sdg jmp 6f 1299134Sdg 1300134Sdg4: /* next page */ 1301570Srgrimes orl %edx,%edx 1302134Sdg jnz 1b 1303134Sdg /* edx is zero -- return ENAMETOOLONG */ 1304570Srgrimes movl $ENAMETOOLONG,%eax 1305134Sdg jmp 6f 1306200Sdg 1307134Sdg#endif /* USE_486_WRITE_PROTECT */ 1308134Sdg 1309134Sdg/* 1310134Sdg * copyinstr(from, to, maxlen, int *lencopied) 1311134Sdg * copy a string from from to to, stop when a 0 character is reached. 1312134Sdg * return ENAMETOOLONG if string is longer than maxlen, and 1313134Sdg * EFAULT on protection violations. If lencopied is non-zero, 1314134Sdg * return the actual length in *lencopied. 1315134Sdg */ 1316134SdgENTRY(copyinstr) 13174Srgrimes pushl %esi 1318134Sdg pushl %edi 1319570Srgrimes movl _curpcb,%ecx 1320570Srgrimes movl $cpystrflt,PCB_ONFAULT(%ecx) 1321134Sdg 1322570Srgrimes movl 12(%esp),%esi /* %esi = from */ 1323570Srgrimes movl 16(%esp),%edi /* %edi = to */ 1324570Srgrimes movl 20(%esp),%edx /* %edx = maxlen */ 1325134Sdg incl %edx 1326134Sdg 1327134Sdg1: 1328134Sdg decl %edx 1329134Sdg jz 4f 1330134Sdg gs 1331134Sdg lodsb 1332134Sdg stosb 1333134Sdg orb %al,%al 1334134Sdg jnz 1b 1335134Sdg /* Success -- 0 byte reached */ 1336134Sdg decl %edx 1337570Srgrimes xorl %eax,%eax 1338134Sdg jmp 6f 1339134Sdg4: 1340134Sdg /* edx is zero -- return ENAMETOOLONG */ 1341570Srgrimes movl $ENAMETOOLONG,%eax 1342134Sdg jmp 6f 1343134Sdg 1344134Sdgcpystrflt: 1345570Srgrimes movl $EFAULT,%eax 1346134Sdg6: /* set *lencopied and return %eax */ 1347570Srgrimes movl _curpcb,%ecx 1348570Srgrimes movl $0,PCB_ONFAULT(%ecx) 1349570Srgrimes movl 20(%esp),%ecx 1350570Srgrimes subl %edx,%ecx 1351570Srgrimes movl 24(%esp),%edx 1352570Srgrimes orl %edx,%edx 1353134Sdg jz 7f 1354570Srgrimes movl %ecx,(%edx) 1355134Sdg7: 1356134Sdg popl %edi 13574Srgrimes popl %esi 13584Srgrimes ret 13594Srgrimes 1360134Sdg 1361134Sdg/* 1362134Sdg * copystr(from, to, maxlen, int *lencopied) 1363134Sdg */ 1364134SdgENTRY(copystr) 13654Srgrimes pushl %esi 1366134Sdg pushl %edi 1367134Sdg 1368570Srgrimes movl 12(%esp),%esi /* %esi = from */ 1369570Srgrimes movl 16(%esp),%edi /* %edi = to */ 1370570Srgrimes movl 20(%esp),%edx /* %edx = maxlen */ 1371134Sdg incl %edx 1372134Sdg 1373134Sdg1: 1374134Sdg decl %edx 1375134Sdg jz 4f 1376134Sdg lodsb 1377134Sdg stosb 1378134Sdg orb %al,%al 1379134Sdg jnz 1b 1380134Sdg /* Success -- 0 byte reached */ 1381134Sdg decl %edx 1382570Srgrimes xorl %eax,%eax 1383134Sdg jmp 6f 1384134Sdg4: 1385134Sdg /* edx is zero -- return ENAMETOOLONG */ 1386570Srgrimes movl $ENAMETOOLONG,%eax 1387134Sdg 1388134Sdg6: /* set *lencopied and return %eax */ 1389570Srgrimes movl 20(%esp),%ecx 1390570Srgrimes subl %edx,%ecx 1391570Srgrimes movl 24(%esp),%edx 1392570Srgrimes orl %edx,%edx 1393134Sdg jz 7f 1394570Srgrimes movl %ecx,(%edx) 1395134Sdg7: 1396134Sdg popl %edi 13974Srgrimes popl %esi 13984Srgrimes ret 13994Srgrimes 1400570Srgrimes/* 1401570Srgrimes * Handling of special 386 registers and descriptor tables etc 1402570Srgrimes */ 1403570SrgrimesENTRY(lgdt) /* void lgdt(struct region_descriptor *rdp); */ 14044Srgrimes /* reload the descriptor table */ 14054Srgrimes movl 4(%esp),%eax 14064Srgrimes lgdt (%eax) 14074Srgrimes /* flush the prefetch q */ 14084Srgrimes jmp 1f 14094Srgrimes nop 14104Srgrimes1: 14114Srgrimes /* reload "stale" selectors */ 14124Srgrimes movl $KDSEL,%eax 14134Srgrimes movl %ax,%ds 14144Srgrimes movl %ax,%es 14154Srgrimes movl %ax,%ss 14164Srgrimes 14174Srgrimes /* reload code selector by turning return into intersegmental return */ 14184Srgrimes movl (%esp),%eax 14194Srgrimes pushl %eax 1420570Srgrimes# movl $KCSEL,4(%esp) 14214Srgrimes movl $8,4(%esp) 14224Srgrimes lret 14234Srgrimes 14244Srgrimes /* 14254Srgrimes * void lidt(struct region_descriptor *rdp); 14264Srgrimes */ 14274SrgrimesENTRY(lidt) 14284Srgrimes movl 4(%esp),%eax 14294Srgrimes lidt (%eax) 14304Srgrimes ret 14314Srgrimes 14324Srgrimes /* 14334Srgrimes * void lldt(u_short sel) 14344Srgrimes */ 14354SrgrimesENTRY(lldt) 14364Srgrimes lldt 4(%esp) 14374Srgrimes ret 14384Srgrimes 14394Srgrimes /* 14404Srgrimes * void ltr(u_short sel) 14414Srgrimes */ 14424SrgrimesENTRY(ltr) 14434Srgrimes ltr 4(%esp) 14444Srgrimes ret 14454Srgrimes 1446570SrgrimesENTRY(ssdtosd) /* ssdtosd(*ssdp,*sdp) */ 14474Srgrimes pushl %ebx 14484Srgrimes movl 8(%esp),%ecx 14494Srgrimes movl 8(%ecx),%ebx 14504Srgrimes shll $16,%ebx 14514Srgrimes movl (%ecx),%edx 14524Srgrimes roll $16,%edx 14534Srgrimes movb %dh,%bl 14544Srgrimes movb %dl,%bh 14554Srgrimes rorl $8,%ebx 14564Srgrimes movl 4(%ecx),%eax 14574Srgrimes movw %ax,%dx 14584Srgrimes andl $0xf0000,%eax 14594Srgrimes orl %eax,%ebx 14604Srgrimes movl 12(%esp),%ecx 14614Srgrimes movl %edx,(%ecx) 14624Srgrimes movl %ebx,4(%ecx) 14634Srgrimes popl %ebx 14644Srgrimes ret 14654Srgrimes 1466134Sdg 1467570SrgrimesENTRY(tlbflush) /* tlbflush() */ 1468134Sdg movl %cr3,%eax 1469570Srgrimes orl $I386_CR3PAT,%eax 1470134Sdg movl %eax,%cr3 14714Srgrimes ret 1472134Sdg 1473134Sdg 1474570SrgrimesENTRY(load_cr0) /* load_cr0(cr0) */ 1475134Sdg movl 4(%esp),%eax 1476134Sdg movl %eax,%cr0 14774Srgrimes ret 1478134Sdg 1479134Sdg 1480570SrgrimesENTRY(rcr0) /* rcr0() */ 1481134Sdg movl %cr0,%eax 14824Srgrimes ret 14834Srgrimes 1484134Sdg 1485570SrgrimesENTRY(rcr2) /* rcr2() */ 1486134Sdg movl %cr2,%eax 14874Srgrimes ret 14884Srgrimes 14894Srgrimes 1490570SrgrimesENTRY(rcr3) /* rcr3() */ 1491134Sdg movl %cr3,%eax 14924Srgrimes ret 14934Srgrimes 1494134Sdg 1495570SrgrimesENTRY(load_cr3) /* void load_cr3(caddr_t cr3) */ 1496134Sdg movl 4(%esp),%eax 1497570Srgrimes orl $I386_CR3PAT,%eax 1498134Sdg movl %eax,%cr3 14994Srgrimes ret 15004Srgrimes 1501134Sdg 1502134Sdg/*****************************************************************************/ 1503134Sdg/* setjump, longjump */ 1504134Sdg/*****************************************************************************/ 1505134Sdg 15064SrgrimesENTRY(setjmp) 15074Srgrimes movl 4(%esp),%eax 1508570Srgrimes movl %ebx,(%eax) /* save ebx */ 1509570Srgrimes movl %esp,4(%eax) /* save esp */ 1510570Srgrimes movl %ebp,8(%eax) /* save ebp */ 1511570Srgrimes movl %esi,12(%eax) /* save esi */ 1512570Srgrimes movl %edi,16(%eax) /* save edi */ 1513570Srgrimes movl (%esp),%edx /* get rta */ 1514570Srgrimes movl %edx,20(%eax) /* save eip */ 1515570Srgrimes xorl %eax,%eax /* return(0); */ 15164Srgrimes ret 15174Srgrimes 15184SrgrimesENTRY(longjmp) 15194Srgrimes movl 4(%esp),%eax 1520570Srgrimes movl (%eax),%ebx /* restore ebx */ 1521570Srgrimes movl 4(%eax),%esp /* restore esp */ 1522570Srgrimes movl 8(%eax),%ebp /* restore ebp */ 1523570Srgrimes movl 12(%eax),%esi /* restore esi */ 1524570Srgrimes movl 16(%eax),%edi /* restore edi */ 1525570Srgrimes movl 20(%eax),%edx /* get rta */ 1526570Srgrimes movl %edx,(%esp) /* put in return frame */ 1527570Srgrimes xorl %eax,%eax /* return(1); */ 15284Srgrimes incl %eax 15294Srgrimes ret 1530134Sdg 1531134Sdg 1532134Sdg/*****************************************************************************/ 1533134Sdg/* Scheduling */ 1534134Sdg/*****************************************************************************/ 1535134Sdg 15364Srgrimes/* 15374Srgrimes * The following primitives manipulate the run queues. 15384Srgrimes * _whichqs tells which of the 32 queues _qs 15394Srgrimes * have processes in them. Setrq puts processes into queues, Remrq 15404Srgrimes * removes them from queues. The running process is on no queue, 15414Srgrimes * other processes are on a queue related to p->p_pri, divided by 4 15424Srgrimes * actually to shrink the 0-127 range of priorities into the 32 available 15434Srgrimes * queues. 15444Srgrimes */ 15454Srgrimes 15464Srgrimes .globl _whichqs,_qs,_cnt,_panic 15474Srgrimes .comm _noproc,4 15484Srgrimes .comm _runrun,4 15494Srgrimes 15504Srgrimes/* 15514Srgrimes * Setrq(p) 15524Srgrimes * 15534Srgrimes * Call should be made at spl6(), and p->p_stat should be SRUN 15544Srgrimes */ 15554SrgrimesENTRY(setrq) 15564Srgrimes movl 4(%esp),%eax 1557570Srgrimes cmpl $0,P_RLINK(%eax) /* should not be on q already */ 15584Srgrimes je set1 15594Srgrimes pushl $set2 15604Srgrimes call _panic 15614Srgrimesset1: 15624Srgrimes movzbl P_PRI(%eax),%edx 15634Srgrimes shrl $2,%edx 1564570Srgrimes btsl %edx,_whichqs /* set q full bit */ 15654Srgrimes shll $3,%edx 1566570Srgrimes addl $_qs,%edx /* locate q hdr */ 1567570Srgrimes movl %edx,P_LINK(%eax) /* link process on tail of q */ 15684Srgrimes movl P_RLINK(%edx),%ecx 15694Srgrimes movl %ecx,P_RLINK(%eax) 15704Srgrimes movl %eax,P_RLINK(%edx) 15714Srgrimes movl %eax,P_LINK(%ecx) 15724Srgrimes ret 15734Srgrimes 15744Srgrimesset2: .asciz "setrq" 15754Srgrimes 15764Srgrimes/* 15774Srgrimes * Remrq(p) 15784Srgrimes * 15794Srgrimes * Call should be made at spl6(). 15804Srgrimes */ 15814SrgrimesENTRY(remrq) 15824Srgrimes movl 4(%esp),%eax 15834Srgrimes movzbl P_PRI(%eax),%edx 15844Srgrimes shrl $2,%edx 1585570Srgrimes btrl %edx,_whichqs /* clear full bit, panic if clear already */ 15864Srgrimes jb rem1 15874Srgrimes pushl $rem3 15884Srgrimes call _panic 15894Srgrimesrem1: 15904Srgrimes pushl %edx 1591570Srgrimes movl P_LINK(%eax),%ecx /* unlink process */ 15924Srgrimes movl P_RLINK(%eax),%edx 15934Srgrimes movl %edx,P_RLINK(%ecx) 15944Srgrimes movl P_RLINK(%eax),%ecx 15954Srgrimes movl P_LINK(%eax),%edx 15964Srgrimes movl %edx,P_LINK(%ecx) 15974Srgrimes popl %edx 15984Srgrimes movl $_qs,%ecx 15994Srgrimes shll $3,%edx 16004Srgrimes addl %edx,%ecx 1601570Srgrimes cmpl P_LINK(%ecx),%ecx /* q still has something? */ 16024Srgrimes je rem2 1603570Srgrimes shrl $3,%edx /* yes, set bit as still full */ 16044Srgrimes btsl %edx,_whichqs 16054Srgrimesrem2: 1606570Srgrimes movl $0,P_RLINK(%eax) /* zap reverse link to indicate off list */ 16074Srgrimes ret 16084Srgrimes 16094Srgrimesrem3: .asciz "remrq" 16104Srgrimessw0: .asciz "swtch" 16114Srgrimes 16124Srgrimes/* 16134Srgrimes * When no processes are on the runq, Swtch branches to idle 16144Srgrimes * to wait for something to come ready. 16154Srgrimes */ 1616200Sdg ALIGN_TEXT 1617200SdgIdle: 16184Srgrimes sti 16194Srgrimes SHOW_STI 1620200Sdg 1621200Sdg ALIGN_TEXT 1622134Sdgidle_loop: 16234Srgrimes call _spl0 16244Srgrimes cmpl $0,_whichqs 16254Srgrimes jne sw1 1626570Srgrimes hlt /* wait for interrupt */ 1627134Sdg jmp idle_loop 16284Srgrimes 16294Srgrimesbadsw: 16304Srgrimes pushl $sw0 16314Srgrimes call _panic 16324Srgrimes /*NOTREACHED*/ 16334Srgrimes 16344Srgrimes/* 16354Srgrimes * Swtch() 16364Srgrimes */ 1637200Sdg SUPERALIGN_TEXT /* so profiling doesn't lump Idle with swtch().. */ 16384SrgrimesENTRY(swtch) 16394Srgrimes 16404Srgrimes incl _cnt+V_SWTCH 16414Srgrimes 16424Srgrimes /* switch to new process. first, save context as needed */ 16434Srgrimes 16444Srgrimes movl _curproc,%ecx 16454Srgrimes 16464Srgrimes /* if no process to save, don't bother */ 16474Srgrimes testl %ecx,%ecx 16484Srgrimes je sw1 16494Srgrimes 16504Srgrimes movl P_ADDR(%ecx),%ecx 16514Srgrimes 1652570Srgrimes movl (%esp),%eax /* Hardware registers */ 1653570Srgrimes movl %eax,PCB_EIP(%ecx) 1654570Srgrimes movl %ebx,PCB_EBX(%ecx) 1655570Srgrimes movl %esp,PCB_ESP(%ecx) 1656570Srgrimes movl %ebp,PCB_EBP(%ecx) 1657570Srgrimes movl %esi,PCB_ESI(%ecx) 1658570Srgrimes movl %edi,PCB_EDI(%ecx) 16594Srgrimes 1660608Srgrimes#if NNPX > 0 16614Srgrimes /* have we used fp, and need a save? */ 16624Srgrimes mov _curproc,%eax 16634Srgrimes cmp %eax,_npxproc 16644Srgrimes jne 1f 16654Srgrimes pushl %ecx /* h/w bugs make saving complicated */ 16664Srgrimes leal PCB_SAVEFPU(%ecx),%eax 16674Srgrimes pushl %eax 16684Srgrimes call _npxsave /* do it in a big C function */ 16694Srgrimes popl %eax 16704Srgrimes popl %ecx 16714Srgrimes1: 1672608Srgrimes#endif /* NNPX > 0 */ 16734Srgrimes 1674570Srgrimes movl _CMAP2,%eax /* save temporary map PTE */ 1675570Srgrimes movl %eax,PCB_CMAP2(%ecx) /* in our context */ 1676570Srgrimes movl $0,_curproc /* out of process */ 16774Srgrimes 1678570Srgrimes# movw _cpl,%ax 1679570Srgrimes# movw %ax,PCB_IML(%ecx) /* save ipl */ 16804Srgrimes 16814Srgrimes /* save is done, now choose a new process or idle */ 16824Srgrimessw1: 16834Srgrimes cli 16844Srgrimes SHOW_CLI 16854Srgrimes movl _whichqs,%edi 16864Srgrimes2: 1687570Srgrimes /* XXX - bsf is sloow */ 1688570Srgrimes bsfl %edi,%eax /* find a full q */ 1689570Srgrimes je Idle /* if none, idle */ 1690570Srgrimes /* XX update whichqs? */ 16914Srgrimesswfnd: 1692570Srgrimes btrl %eax,%edi /* clear q full status */ 1693570Srgrimes jnb 2b /* if it was clear, look for another */ 1694570Srgrimes movl %eax,%ebx /* save which one we are using */ 16954Srgrimes 16964Srgrimes shll $3,%eax 1697570Srgrimes addl $_qs,%eax /* select q */ 16984Srgrimes movl %eax,%esi 16994Srgrimes 17004Srgrimes#ifdef DIAGNOSTIC 1701570Srgrimes cmpl P_LINK(%eax),%eax /* linked to self? (e.g. not on list) */ 1702570Srgrimes je badsw /* not possible */ 17034Srgrimes#endif 17044Srgrimes 1705570Srgrimes movl P_LINK(%eax),%ecx /* unlink from front of process q */ 17064Srgrimes movl P_LINK(%ecx),%edx 17074Srgrimes movl %edx,P_LINK(%eax) 17084Srgrimes movl P_RLINK(%ecx),%eax 17094Srgrimes movl %eax,P_RLINK(%edx) 17104Srgrimes 1711570Srgrimes cmpl P_LINK(%ecx),%esi /* q empty */ 17124Srgrimes je 3f 1713570Srgrimes btsl %ebx,%edi /* nope, set to indicate full */ 17144Srgrimes3: 1715570Srgrimes movl %edi,_whichqs /* update q status */ 17164Srgrimes 17174Srgrimes movl $0,%eax 17184Srgrimes movl %eax,_want_resched 17194Srgrimes 17204Srgrimes#ifdef DIAGNOSTIC 17214Srgrimes cmpl %eax,P_WCHAN(%ecx) 17224Srgrimes jne badsw 1723570Srgrimes cmpb $SRUN,P_STAT(%ecx) 17244Srgrimes jne badsw 17254Srgrimes#endif 17264Srgrimes 17274Srgrimes movl %eax,P_RLINK(%ecx) /* isolate process to run */ 17284Srgrimes movl P_ADDR(%ecx),%edx 17294Srgrimes movl PCB_CR3(%edx),%ebx 17304Srgrimes 17314Srgrimes /* switch address space */ 17324Srgrimes movl %ebx,%cr3 17334Srgrimes 17344Srgrimes /* restore context */ 1735570Srgrimes movl PCB_EBX(%edx),%ebx 1736570Srgrimes movl PCB_ESP(%edx),%esp 1737570Srgrimes movl PCB_EBP(%edx),%ebp 1738570Srgrimes movl PCB_ESI(%edx),%esi 1739570Srgrimes movl PCB_EDI(%edx),%edi 1740570Srgrimes movl PCB_EIP(%edx),%eax 1741570Srgrimes movl %eax,(%esp) 17424Srgrimes 1743570Srgrimes movl PCB_CMAP2(%edx),%eax /* get temporary map */ 1744570Srgrimes movl %eax,_CMAP2 /* reload temporary map PTE */ 17454Srgrimes 1746570Srgrimes movl %ecx,_curproc /* into next process */ 17474Srgrimes movl %edx,_curpcb 17484Srgrimes 1749570Srgrimes pushl %edx /* save p to return */ 17504Srgrimes/* 17514Srgrimes * XXX - 0.0 forgot to save it - is that why this was commented out in 0.1? 17524Srgrimes * I think restoring the cpl is unnecessary, but we must turn off the cli 17534Srgrimes * now that spl*() don't do it as a side affect. 17544Srgrimes */ 17554Srgrimes pushl PCB_IML(%edx) 17564Srgrimes sti 17574Srgrimes SHOW_STI 17584Srgrimes#if 0 17594Srgrimes call _splx 17604Srgrimes#endif 17614Srgrimes addl $4,%esp 17624Srgrimes/* 17634Srgrimes * XXX - 0.0 gets here via swtch_to_inactive(). I think 0.1 gets here in the 17644Srgrimes * same way. Better return a value. 17654Srgrimes */ 1766570Srgrimes popl %eax /* return(p); */ 17674Srgrimes ret 17684Srgrimes 17694SrgrimesENTRY(mvesp) 17704Srgrimes movl %esp,%eax 17714Srgrimes ret 17724Srgrimes/* 17734Srgrimes * struct proc *swtch_to_inactive(p) ; struct proc *p; 17744Srgrimes * 17754Srgrimes * At exit of a process, move off the address space of the 17764Srgrimes * process and onto a "safe" one. Then, on a temporary stack 17774Srgrimes * return and run code that disposes of the old state. 17784Srgrimes * Since this code requires a parameter from the "old" stack, 17794Srgrimes * pass it back as a return value. 17804Srgrimes */ 17814SrgrimesENTRY(swtch_to_inactive) 1782570Srgrimes popl %edx /* old pc */ 1783570Srgrimes popl %eax /* arg, our return value */ 17844Srgrimes movl _IdlePTD,%ecx 1785570Srgrimes movl %ecx,%cr3 /* good bye address space */ 17864Srgrimes #write buffer? 1787570Srgrimes movl $tmpstk-4,%esp /* temporary stack, compensated for call */ 1788570Srgrimes jmp %edx /* return, execute remainder of cleanup */ 17894Srgrimes 17904Srgrimes/* 17914Srgrimes * savectx(pcb, altreturn) 17924Srgrimes * Update pcb, saving current processor state and arranging 17934Srgrimes * for alternate return ala longjmp in swtch if altreturn is true. 17944Srgrimes */ 17954SrgrimesENTRY(savectx) 1796570Srgrimes movl 4(%esp),%ecx 1797570Srgrimes movw _cpl,%ax 1798570Srgrimes movw %ax,PCB_IML(%ecx) 1799570Srgrimes movl (%esp),%eax 1800570Srgrimes movl %eax,PCB_EIP(%ecx) 1801570Srgrimes movl %ebx,PCB_EBX(%ecx) 1802570Srgrimes movl %esp,PCB_ESP(%ecx) 1803570Srgrimes movl %ebp,PCB_EBP(%ecx) 1804570Srgrimes movl %esi,PCB_ESI(%ecx) 1805570Srgrimes movl %edi,PCB_EDI(%ecx) 18064Srgrimes 1807608Srgrimes#if NNPX > 0 18084Srgrimes /* 18094Srgrimes * If npxproc == NULL, then the npx h/w state is irrelevant and the 18104Srgrimes * state had better already be in the pcb. This is true for forks 18114Srgrimes * but not for dumps (the old book-keeping with FP flags in the pcb 18124Srgrimes * always lost for dumps because the dump pcb has 0 flags). 18134Srgrimes * 18144Srgrimes * If npxproc != NULL, then we have to save the npx h/w state to 18154Srgrimes * npxproc's pcb and copy it to the requested pcb, or save to the 18164Srgrimes * requested pcb and reload. Copying is easier because we would 18174Srgrimes * have to handle h/w bugs for reloading. We used to lose the 18184Srgrimes * parent's npx state for forks by forgetting to reload. 18194Srgrimes */ 18204Srgrimes mov _npxproc,%eax 18214Srgrimes testl %eax,%eax 18224Srgrimes je 1f 18234Srgrimes 18244Srgrimes pushl %ecx 18254Srgrimes movl P_ADDR(%eax),%eax 18264Srgrimes leal PCB_SAVEFPU(%eax),%eax 18274Srgrimes pushl %eax 18284Srgrimes pushl %eax 18294Srgrimes call _npxsave 18304Srgrimes popl %eax 18314Srgrimes popl %eax 18324Srgrimes popl %ecx 18334Srgrimes 18344Srgrimes pushl %ecx 18354Srgrimes pushl $108+8*2 /* XXX h/w state size + padding */ 18364Srgrimes leal PCB_SAVEFPU(%ecx),%ecx 18374Srgrimes pushl %ecx 18384Srgrimes pushl %eax 18394Srgrimes call _bcopy 18404Srgrimes addl $12,%esp 18414Srgrimes popl %ecx 18424Srgrimes1: 1843608Srgrimes#endif /* NNPX > 0 */ 18444Srgrimes 1845570Srgrimes movl _CMAP2,%edx /* save temporary map PTE */ 1846570Srgrimes movl %edx,PCB_CMAP2(%ecx) /* in our context */ 18474Srgrimes 1848570Srgrimes cmpl $0,8(%esp) 18494Srgrimes je 1f 1850570Srgrimes movl %esp,%edx /* relocate current sp relative to pcb */ 1851570Srgrimes subl $_kstack,%edx /* (sp is relative to kstack): */ 1852570Srgrimes addl %edx,%ecx /* pcb += sp - kstack; */ 1853570Srgrimes movl %eax,(%ecx) /* write return pc at (relocated) sp@ */ 1854570Srgrimes /* this mess deals with replicating register state gcc hides */ 18554Srgrimes movl 12(%esp),%eax 18564Srgrimes movl %eax,12(%ecx) 18574Srgrimes movl 16(%esp),%eax 18584Srgrimes movl %eax,16(%ecx) 18594Srgrimes movl 20(%esp),%eax 18604Srgrimes movl %eax,20(%ecx) 18614Srgrimes movl 24(%esp),%eax 18624Srgrimes movl %eax,24(%ecx) 18634Srgrimes1: 1864570Srgrimes xorl %eax,%eax /* return 0 */ 18654Srgrimes ret 18664Srgrimes 18674Srgrimes/* 18684Srgrimes * addupc(int pc, struct uprof *up, int ticks): 18694Srgrimes * update profiling information for the user process. 18704Srgrimes */ 18714SrgrimesENTRY(addupc) 18724Srgrimes pushl %ebp 18734Srgrimes movl %esp,%ebp 18744Srgrimes movl 12(%ebp),%edx /* up */ 18754Srgrimes movl 8(%ebp),%eax /* pc */ 18764Srgrimes 18774Srgrimes subl PR_OFF(%edx),%eax /* pc -= up->pr_off */ 18784Srgrimes jl L1 /* if (pc < 0) return */ 18794Srgrimes 18804Srgrimes shrl $1,%eax /* praddr = pc >> 1 */ 18814Srgrimes imull PR_SCALE(%edx),%eax /* praddr *= up->pr_scale */ 18824Srgrimes shrl $15,%eax /* praddr = praddr << 15 */ 18834Srgrimes andl $-2,%eax /* praddr &= ~1 */ 18844Srgrimes 18854Srgrimes cmpl PR_SIZE(%edx),%eax /* if (praddr > up->pr_size) return */ 18864Srgrimes ja L1 18874Srgrimes 18884Srgrimes/* addl %eax,%eax /* praddr -> word offset */ 18894Srgrimes addl PR_BASE(%edx),%eax /* praddr += up-> pr_base */ 18904Srgrimes movl 16(%ebp),%ecx /* ticks */ 18914Srgrimes 18924Srgrimes movl _curpcb,%edx 18934Srgrimes movl $proffault,PCB_ONFAULT(%edx) 18944Srgrimes addl %ecx,(%eax) /* storage location += ticks */ 18954Srgrimes movl $0,PCB_ONFAULT(%edx) 18964SrgrimesL1: 18974Srgrimes leave 18984Srgrimes ret 18994Srgrimes 19004Srgrimes ALIGN_TEXT 19014Srgrimesproffault: 19024Srgrimes /* if we get a fault, then kill profiling all together */ 19034Srgrimes movl $0,PCB_ONFAULT(%edx) /* squish the fault handler */ 1904200Sdg movl 12(%ebp),%ecx 19054Srgrimes movl $0,PR_SCALE(%ecx) /* up->pr_scale = 0 */ 19064Srgrimes leave 19074Srgrimes ret 19084Srgrimes 1909570Srgrimes/* To be done: */ 1910134SdgENTRY(astoff) 19114Srgrimes ret 19124Srgrimes 19134Srgrimes 1914134Sdg/*****************************************************************************/ 1915134Sdg/* Trap handling */ 1916134Sdg/*****************************************************************************/ 19174Srgrimes/* 19184Srgrimes * Trap and fault vector routines 19194Srgrimes * 19204Srgrimes * XXX - debugger traps are now interrupt gates so at least bdb doesn't lose 19214Srgrimes * control. The sti's give the standard losing behaviour for ddb and kgdb. 1922200Sdg */ 19234Srgrimes#define IDTVEC(name) ALIGN_TEXT; .globl _X/**/name; _X/**/name: 19244Srgrimes#define TRAP(a) pushl $(a) ; jmp alltraps 19254Srgrimes#ifdef KGDB 1926134Sdg# define BPTTRAP(a) sti; pushl $(a) ; jmp bpttraps 19274Srgrimes#else 1928134Sdg# define BPTTRAP(a) sti; TRAP(a) 19294Srgrimes#endif 19304Srgrimes 19314SrgrimesIDTVEC(div) 19324Srgrimes pushl $0; TRAP(T_DIVIDE) 19334SrgrimesIDTVEC(dbg) 19344Srgrimes#ifdef BDBTRAP 19354Srgrimes BDBTRAP(dbg) 19364Srgrimes#endif 19374Srgrimes pushl $0; BPTTRAP(T_TRCTRAP) 19384SrgrimesIDTVEC(nmi) 19394Srgrimes pushl $0; TRAP(T_NMI) 19404SrgrimesIDTVEC(bpt) 19414Srgrimes#ifdef BDBTRAP 19424Srgrimes BDBTRAP(bpt) 19434Srgrimes#endif 19444Srgrimes pushl $0; BPTTRAP(T_BPTFLT) 19454SrgrimesIDTVEC(ofl) 19464Srgrimes pushl $0; TRAP(T_OFLOW) 19474SrgrimesIDTVEC(bnd) 19484Srgrimes pushl $0; TRAP(T_BOUND) 19494SrgrimesIDTVEC(ill) 19504Srgrimes pushl $0; TRAP(T_PRIVINFLT) 19514SrgrimesIDTVEC(dna) 19524Srgrimes pushl $0; TRAP(T_DNA) 19534SrgrimesIDTVEC(dble) 19544Srgrimes TRAP(T_DOUBLEFLT) 19554Srgrimes /*PANIC("Double Fault");*/ 19564SrgrimesIDTVEC(fpusegm) 19574Srgrimes pushl $0; TRAP(T_FPOPFLT) 19584SrgrimesIDTVEC(tss) 19594Srgrimes TRAP(T_TSSFLT) 19604Srgrimes /*PANIC("TSS not valid");*/ 19614SrgrimesIDTVEC(missing) 19624Srgrimes TRAP(T_SEGNPFLT) 19634SrgrimesIDTVEC(stk) 19644Srgrimes TRAP(T_STKFLT) 19654SrgrimesIDTVEC(prot) 19664Srgrimes TRAP(T_PROTFLT) 19674SrgrimesIDTVEC(page) 19684Srgrimes TRAP(T_PAGEFLT) 19694SrgrimesIDTVEC(rsvd) 19704Srgrimes pushl $0; TRAP(T_RESERVED) 19714SrgrimesIDTVEC(fpu) 1972608Srgrimes#if NNPX > 0 19734Srgrimes /* 19744Srgrimes * Handle like an interrupt so that we can call npxintr to clear the 19754Srgrimes * error. It would be better to handle npx interrupts as traps but 19764Srgrimes * this is difficult for nested interrupts. 19774Srgrimes */ 19784Srgrimes pushl $0 /* dummy error code */ 19794Srgrimes pushl $T_ASTFLT 19804Srgrimes pushal 19814Srgrimes nop /* silly, the bug is for popal and it only 19824Srgrimes * bites when the next instruction has a 19834Srgrimes * complicated address mode */ 19844Srgrimes pushl %ds 19854Srgrimes pushl %es /* now the stack frame is a trap frame */ 19864Srgrimes movl $KDSEL,%eax 19874Srgrimes movl %ax,%ds 19884Srgrimes movl %ax,%es 19894Srgrimes pushl _cpl 19904Srgrimes pushl $0 /* dummy unit to finish building intr frame */ 19914Srgrimes incl _cnt+V_TRAP 19924Srgrimes call _npxintr 19934Srgrimes jmp doreti 1994608Srgrimes#else /* NNPX > 0 */ 19954Srgrimes pushl $0; TRAP(T_ARITHTRAP) 1996608Srgrimes#endif /* NNPX > 0 */ 19974Srgrimes /* 17 - 31 reserved for future exp */ 19984SrgrimesIDTVEC(rsvd0) 19994Srgrimes pushl $0; TRAP(17) 20004SrgrimesIDTVEC(rsvd1) 20014Srgrimes pushl $0; TRAP(18) 20024SrgrimesIDTVEC(rsvd2) 20034Srgrimes pushl $0; TRAP(19) 20044SrgrimesIDTVEC(rsvd3) 20054Srgrimes pushl $0; TRAP(20) 20064SrgrimesIDTVEC(rsvd4) 20074Srgrimes pushl $0; TRAP(21) 20084SrgrimesIDTVEC(rsvd5) 20094Srgrimes pushl $0; TRAP(22) 20104SrgrimesIDTVEC(rsvd6) 20114Srgrimes pushl $0; TRAP(23) 20124SrgrimesIDTVEC(rsvd7) 20134Srgrimes pushl $0; TRAP(24) 20144SrgrimesIDTVEC(rsvd8) 20154Srgrimes pushl $0; TRAP(25) 20164SrgrimesIDTVEC(rsvd9) 20174Srgrimes pushl $0; TRAP(26) 20184SrgrimesIDTVEC(rsvd10) 20194Srgrimes pushl $0; TRAP(27) 20204SrgrimesIDTVEC(rsvd11) 20214Srgrimes pushl $0; TRAP(28) 20224SrgrimesIDTVEC(rsvd12) 20234Srgrimes pushl $0; TRAP(29) 20244SrgrimesIDTVEC(rsvd13) 20254Srgrimes pushl $0; TRAP(30) 20264SrgrimesIDTVEC(rsvd14) 20274Srgrimes pushl $0; TRAP(31) 20284Srgrimes 20294Srgrimes SUPERALIGN_TEXT 20304Srgrimesalltraps: 20314Srgrimes pushal 20324Srgrimes nop 20334Srgrimes pushl %ds 20344Srgrimes pushl %es 20354Srgrimes movl $KDSEL,%eax 20364Srgrimes movl %ax,%ds 20374Srgrimes movl %ax,%es 20384Srgrimescalltrap: 20394Srgrimes incl _cnt+V_TRAP 20404Srgrimes call _trap 20414Srgrimes /* 20424Srgrimes * Return through doreti to handle ASTs. Have to change trap frame 20434Srgrimes * to interrupt frame. 20444Srgrimes */ 20454Srgrimes movl $T_ASTFLT,4+4+32(%esp) /* new trap type (err code not used) */ 20464Srgrimes pushl _cpl 20474Srgrimes pushl $0 /* dummy unit */ 20484Srgrimes jmp doreti 20494Srgrimes 20504Srgrimes#ifdef KGDB 20514Srgrimes/* 20524Srgrimes * This code checks for a kgdb trap, then falls through 20534Srgrimes * to the regular trap code. 20544Srgrimes */ 2055134Sdg SUPERALIGN_TEXT 20564Srgrimesbpttraps: 20574Srgrimes pushal 20584Srgrimes nop 20594Srgrimes pushl %es 20604Srgrimes pushl %ds 20614Srgrimes movl $KDSEL,%eax 20624Srgrimes movl %ax,%ds 20634Srgrimes movl %ax,%es 20644Srgrimes testb $SEL_RPL_MASK,TRAPF_CS_OFF(%esp) 2065570Srgrimes /* non-kernel mode? */ 2066570Srgrimes jne calltrap /* yes */ 2067200Sdg call _kgdb_trap_glue 20684Srgrimes jmp calltrap 20694Srgrimes#endif 20704Srgrimes 20714Srgrimes/* 20724Srgrimes * Call gate entry for syscall 20734Srgrimes */ 2074200Sdg SUPERALIGN_TEXT 20754SrgrimesIDTVEC(syscall) 2076570Srgrimes pushfl /* only for stupid carry bit and more stupid wait3 cc kludge */ 2077570Srgrimes /* XXX - also for direction flag (bzero, etc. clear it) */ 2078570Srgrimes pushal /* only need eax,ecx,edx - trap resaves others */ 20794Srgrimes nop 2080570Srgrimes movl $KDSEL,%eax /* switch to kernel segments */ 20814Srgrimes movl %ax,%ds 20824Srgrimes movl %ax,%es 2083570Srgrimes incl _cnt+V_SYSCALL /* kml 3/25/93 */ 20844Srgrimes call _syscall 20854Srgrimes /* 20864Srgrimes * Return through doreti to handle ASTs. Have to change syscall frame 20874Srgrimes * to interrupt frame. 20884Srgrimes * 20894Srgrimes * XXX - we should have set up the frame earlier to avoid the 20904Srgrimes * following popal/pushal (not much can be done to avoid shuffling 20914Srgrimes * the flags). Consistent frames would simplify things all over. 20924Srgrimes */ 20934Srgrimes movl 32+0(%esp),%eax /* old flags, shuffle to above cs:eip */ 20944Srgrimes movl 32+4(%esp),%ebx /* `int' frame should have been ef, eip, cs */ 20954Srgrimes movl 32+8(%esp),%ecx 20964Srgrimes movl %ebx,32+0(%esp) 20974Srgrimes movl %ecx,32+4(%esp) 20984Srgrimes movl %eax,32+8(%esp) 20994Srgrimes popal 21004Srgrimes nop 21014Srgrimes pushl $0 /* dummy error code */ 21024Srgrimes pushl $T_ASTFLT 21034Srgrimes pushal 21044Srgrimes nop 21054Srgrimes movl __udatasel,%eax /* switch back to user segments */ 2106134Sdg pushl %eax /* XXX - better to preserve originals? */ 2107134Sdg pushl %eax 21084Srgrimes pushl _cpl 21094Srgrimes pushl $0 21104Srgrimes jmp doreti 21114Srgrimes 2112570Srgrimes#ifdef SHOW_A_LOT 2113570Srgrimes/* 2114570Srgrimes * 'show_bits' was too big when defined as a macro. The line length for some 2115570Srgrimes * enclosing macro was too big for gas. Perhaps the code would have blown 2116570Srgrimes * the cache anyway. 2117570Srgrimes */ 2118570Srgrimes ALIGN_TEXT 2119570Srgrimesshow_bits: 2120570Srgrimes pushl %eax 2121570Srgrimes SHOW_BIT(0) 2122570Srgrimes SHOW_BIT(1) 2123570Srgrimes SHOW_BIT(2) 2124570Srgrimes SHOW_BIT(3) 2125570Srgrimes SHOW_BIT(4) 2126570Srgrimes SHOW_BIT(5) 2127570Srgrimes SHOW_BIT(6) 2128570Srgrimes SHOW_BIT(7) 2129570Srgrimes SHOW_BIT(8) 2130570Srgrimes SHOW_BIT(9) 2131570Srgrimes SHOW_BIT(10) 2132570Srgrimes SHOW_BIT(11) 2133570Srgrimes SHOW_BIT(12) 2134570Srgrimes SHOW_BIT(13) 2135570Srgrimes SHOW_BIT(14) 2136570Srgrimes SHOW_BIT(15) 2137570Srgrimes popl %eax 2138570Srgrimes ret 21394Srgrimes 2140570Srgrimes .data 2141570Srgrimesbit_colors: 2142570Srgrimes .byte GREEN,RED,0,0 2143570Srgrimes .text 21444Srgrimes 2145570Srgrimes#endif /* SHOW_A_LOT */ 2146570Srgrimes 2147570Srgrimes 2148570Srgrimes/* 2149570Srgrimes * include generated interrupt vectors and ISA intr code 2150570Srgrimes */ 21514Srgrimes#include "i386/isa/vector.s" 21524Srgrimes#include "i386/isa/icu.s" 2153