Index: head/sys/amd64/amd64/genassym.c =================================================================== --- head/sys/amd64/amd64/genassym.c (revision 2688) +++ head/sys/amd64/amd64/genassym.c (revision 2689) @@ -1,193 +1,191 @@ /*- * Copyright (c) 1982, 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * William Jolitz. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: @(#)genassym.c 5.11 (Berkeley) 5/10/91 - * $Id: genassym.c,v 1.9 1994/09/01 05:12:16 davidg Exp $ + * $Id: genassym.c,v 1.10 1994/09/02 05:58:50 davidg Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include #include main() { struct proc *p = (struct proc *)0; struct vmmeter *vm = (struct vmmeter *)0; struct user *up = (struct user *)0; struct rusage *rup = (struct rusage *)0; struct uprof *uprof = (struct uprof *)0; struct vmspace *vms = (struct vmspace *)0; vm_map_t map = (vm_map_t)0; pmap_t pmap = (pmap_t)0; struct pcb *pcb = (struct pcb *)0; struct trapframe *tf = (struct trapframe *)0; struct sigframe *sigf = (struct sigframe *)0; register unsigned i; - printf("#define\tI386_CR3PAT %d\n", I386_CR3PAT); printf("#define\tUDOT_SZ %d\n", sizeof(struct user)); printf("#define\tP_FORW %d\n", &p->p_forw); printf("#define\tP_BACK %d\n", &p->p_back); printf("#define\tP_VMSPACE %d\n", &p->p_vmspace); printf("#define\tVM_PMAP %d\n", &vms->vm_pmap); printf("#define\tP_ADDR %d\n", &p->p_addr); printf("#define\tP_PRI %d\n", &p->p_priority); printf("#define\tP_RTPRIO %d\n", &p->p_rtprio); printf("#define\tP_STAT %d\n", &p->p_stat); printf("#define\tP_WCHAN %d\n", &p->p_wchan); printf("#define\tP_FLAG %d\n", &p->p_flag); printf("#define\tP_PID %d\n", &p->p_pid); printf("#define\tSSLEEP %d\n", SSLEEP); printf("#define\tSRUN %d\n", SRUN); printf("#define\tV_SWTCH %d\n", &vm->v_swtch); printf("#define\tV_TRAP %d\n", &vm->v_trap); printf("#define\tV_SYSCALL %d\n", &vm->v_syscall); printf("#define\tV_INTR %d\n", &vm->v_intr); printf("#define\tV_SOFT %d\n", &vm->v_soft); /* printf("#define\tV_PDMA %d\n", &vm->v_pdma); */ printf("#define\tV_FAULTS %d\n", &vm->v_faults); /* printf("#define\tV_PGREC %d\n", &vm->v_pgrec); */ /* printf("#define\tV_FASTPGREC %d\n", &vm->v_fastpgrec); */ printf("#define\tUPAGES %d\n", UPAGES); - printf("#define\tHIGHPAGES %d\n", HIGHPAGES); printf("#define\tCLSIZE %d\n", CLSIZE); printf("#define\tNBPG %d\n", NBPG); printf("#define\tNPTEPG %d\n", NPTEPG); printf("#define\tPDESIZE %d\n", PDESIZE); printf("#define\tPTESIZE %d\n", PTESIZE); printf("#define\tNKPDE %d\n", NKPDE); printf("#define\tNKPT %d\n", NKPT); printf("#define\tKPTDI 0x%x\n", KPTDI); printf("#define\tKSTKPTDI 0x%x\n", KSTKPTDI); printf("#define\tKSTKPTEOFF 0x%x\n", KSTKPTEOFF); printf("#define\tPTDPTDI 0x%x\n", PTDPTDI); printf("#define\tAPTDPTDI 0x%x\n", APTDPTDI); printf("#define\tPGSHIFT %d\n", PGSHIFT); printf("#define\tPDRSHIFT %d\n", PDRSHIFT); printf("#define\tSYSPTSIZE %d\n", SYSPTSIZE); printf("#define\tUSRPTSIZE %d\n", USRPTSIZE); printf("#define\tUSRIOSIZE %d\n", USRIOSIZE); #ifdef SYSVSHM printf("#define\tSHMMAXPGS %d\n", SHMMAXPGS); #endif printf("#define\tUSRSTACK 0x%x\n", USRSTACK); printf("#define\tVM_MAXUSER_ADDRESS 0x%x\n", VM_MAXUSER_ADDRESS); printf("#define\tKERNBASE 0x%x\n", KERNBASE); printf("#define\tMSGBUFPTECNT %d\n", btoc(sizeof (struct msgbuf))); printf("#define\tNMBCLUSTERS %d\n", NMBCLUSTERS); printf("#define\tMCLBYTES %d\n", MCLBYTES); printf("#define\tPCB_LINK %d\n", &pcb->pcb_tss.tss_link); printf("#define\tPCB_ESP0 %d\n", &pcb->pcb_tss.tss_esp0); printf("#define\tPCB_SS0 %d\n", &pcb->pcb_tss.tss_ss0); printf("#define\tPCB_ESP1 %d\n", &pcb->pcb_tss.tss_esp1); printf("#define\tPCB_SS1 %d\n", &pcb->pcb_tss.tss_ss1); printf("#define\tPCB_ESP2 %d\n", &pcb->pcb_tss.tss_esp2); printf("#define\tPCB_SS2 %d\n", &pcb->pcb_tss.tss_ss2); printf("#define\tPCB_CR3 %d\n", &pcb->pcb_tss.tss_cr3); printf("#define\tPCB_EIP %d\n", &pcb->pcb_tss.tss_eip); printf("#define\tPCB_EFLAGS %d\n", &pcb->pcb_tss.tss_eflags); printf("#define\tPCB_EAX %d\n", &pcb->pcb_tss.tss_eax); printf("#define\tPCB_ECX %d\n", &pcb->pcb_tss.tss_ecx); printf("#define\tPCB_EDX %d\n", &pcb->pcb_tss.tss_edx); printf("#define\tPCB_EBX %d\n", &pcb->pcb_tss.tss_ebx); printf("#define\tPCB_ESP %d\n", &pcb->pcb_tss.tss_esp); printf("#define\tPCB_EBP %d\n", &pcb->pcb_tss.tss_ebp); printf("#define\tPCB_ESI %d\n", &pcb->pcb_tss.tss_esi); printf("#define\tPCB_EDI %d\n", &pcb->pcb_tss.tss_edi); printf("#define\tPCB_ES %d\n", &pcb->pcb_tss.tss_es); printf("#define\tPCB_CS %d\n", &pcb->pcb_tss.tss_cs); printf("#define\tPCB_SS %d\n", &pcb->pcb_tss.tss_ss); printf("#define\tPCB_DS %d\n", &pcb->pcb_tss.tss_ds); printf("#define\tPCB_FS %d\n", &pcb->pcb_tss.tss_fs); printf("#define\tPCB_GS %d\n", &pcb->pcb_tss.tss_gs); printf("#define\tPCB_LDT %d\n", &pcb->pcb_tss.tss_ldt); printf("#define\tPCB_USERLDT %d\n", &pcb->pcb_ldt); printf("#define\tPCB_IOOPT %d\n", &pcb->pcb_tss.tss_ioopt); printf("#define\tU_PROF %d\n", &up->u_stats.p_prof); printf("#define\tU_PROFSCALE %d\n", &up->u_stats.p_prof.pr_scale); printf("#define\tPR_BASE %d\n", &uprof->pr_base); printf("#define\tPR_SIZE %d\n", &uprof->pr_size); printf("#define\tPR_OFF %d\n", &uprof->pr_off); printf("#define\tPR_SCALE %d\n", &uprof->pr_scale); printf("#define\tRU_MINFLT %d\n", &rup->ru_minflt); printf("#define\tPCB_FLAGS %d\n", &pcb->pcb_flags); printf("#define\tPCB_SAVEFPU %d\n", &pcb->pcb_savefpu); printf("#define\tFP_USESEMC %d\n", FP_USESEMC); printf("#define\tPCB_SAVEEMC %d\n", &pcb->pcb_saveemc); printf("#define\tPCB_CMAP2 %d\n", &pcb->pcb_cmap2); printf("#define\tPCB_IML %d\n", &pcb->pcb_iml); printf("#define\tPCB_ONFAULT %d\n", &pcb->pcb_onfault); printf("#define\tTF_ES %d\n", &tf->tf_es); printf("#define\tTF_DS %d\n", &tf->tf_ds); printf("#define\tTF_EDI %d\n", &tf->tf_edi); printf("#define\tTF_ESI %d\n", &tf->tf_esi); printf("#define\tTF_EBP %d\n", &tf->tf_ebp); printf("#define\tTF_ISP %d\n", &tf->tf_isp); printf("#define\tTF_EBX %d\n", &tf->tf_ebx); printf("#define\tTF_EDX %d\n", &tf->tf_edx); printf("#define\tTF_ECX %d\n", &tf->tf_ecx); printf("#define\tTF_EAX %d\n", &tf->tf_eax); printf("#define\tTF_TRAPNO %d\n", &tf->tf_trapno); printf("#define\tTF_ERR %d\n", &tf->tf_err); printf("#define\tTF_EIP %d\n", &tf->tf_eip); printf("#define\tTF_CS %d\n", &tf->tf_cs); printf("#define\tTF_EFLAGS %d\n", &tf->tf_eflags); printf("#define\tTF_ESP %d\n", &tf->tf_esp); printf("#define\tTF_SS %d\n", &tf->tf_ss); printf("#define\tSIGF_SIGNUM %d\n", &sigf->sf_signum); printf("#define\tSIGF_CODE %d\n", &sigf->sf_code); printf("#define\tSIGF_SCP %d\n", &sigf->sf_scp); printf("#define\tSIGF_HANDLER %d\n", &sigf->sf_handler); printf("#define\tSIGF_SC %d\n", &sigf->sf_sc); printf("#define\tB_READ %d\n", B_READ); printf("#define\tENOENT %d\n", ENOENT); printf("#define\tEFAULT %d\n", EFAULT); printf("#define\tENAMETOOLONG %d\n", ENAMETOOLONG); exit(0); } Index: head/sys/amd64/amd64/locore.S =================================================================== --- head/sys/amd64/amd64/locore.S (revision 2688) +++ head/sys/amd64/amd64/locore.S (revision 2689) @@ -1,591 +1,590 @@ /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * William Jolitz. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: @(#)locore.s 7.3 (Berkeley) 5/13/91 - * $Id: locore.s,v 1.25 1994/09/05 05:20:29 davidg Exp $ + * $Id: locore.s,v 1.26 1994/09/05 14:09:41 bde Exp $ */ /* * locore.s: FreeBSD machine support for the Intel 386 * originally from: locore.s, by William F. Jolitz * * Substantially rewritten by David Greenman, Rod Grimes, * Bruce Evans, Wolfgang Solfrank, and many others. */ #include "npx.h" /* for NNPX */ #include "assym.s" /* system definitions */ #include /* processor status longword defs */ #include /* page table entry definitions */ #include /* error return codes */ #include /* x86 special registers */ #include /* x86 cpu type definitions */ #include /* system call numbers */ #include /* miscellaneous asm macros */ /* * XXX * * Note: This version greatly munged to avoid various assembler errors * that may be fixed in newer versions of gas. Perhaps newer versions * will have more pleasant appearance. */ /* * PTmap is recursive pagemap at top of virtual address space. * Within PTmap, the page directory can be found (third indirection). */ .globl _PTmap,_PTD,_PTDpde,_Sysmap .set _PTmap,PTDPTDI << PDRSHIFT .set _PTD,_PTmap + (PTDPTDI * NBPG) .set _PTDpde,_PTD + (PTDPTDI * PDESIZE) /* Sysmap is the base address of the kernel page tables */ .set _Sysmap,_PTmap + (KPTDI * NBPG) /* * APTmap, APTD is the alternate recursive pagemap. * It's used when modifying another process's page tables. */ .globl _APTmap,_APTD,_APTDpde .set _APTmap,APTDPTDI << PDRSHIFT .set _APTD,_APTmap + (APTDPTDI * NBPG) .set _APTDpde,_PTD + (APTDPTDI * PDESIZE) /* * Access to each processes kernel stack is via a region of * per-process address space (at the beginning), immediatly above * the user process stack. */ .set _kstack,USRSTACK .globl _kstack /* * Globals */ .data .globl _esym _esym: .long 0 /* ptr to end of syms */ .globl _boothowto,_bootdev,_curpcb .globl _cpu,_cold,_atdevbase,_cpu_vendor,_cpu_id _cpu: .long 0 /* are we 386, 386sx, or 486 */ _cpu_id: .long 0 /* stepping ID */ _cpu_vendor: .space 20 /* CPU origin code */ _cold: .long 1 /* cold till we are not */ _atdevbase: .long 0 /* location of start of iomem in virtual */ _atdevphys: .long 0 /* location of device mapping ptes (phys) */ .globl _KERNend _KERNend: .long 0 /* phys addr end of kernel (just after bss) */ .globl _IdlePTD,_KPTphys _IdlePTD: .long 0 /* phys addr of kernel PTD */ _KPTphys: .long 0 /* phys addr of kernel page tables */ .globl _cyloffset _cyloffset: .long 0 /* cylinder offset from boot blocks */ .globl _proc0paddr _proc0paddr: .long 0 /* address of proc 0 address space */ #ifdef BDE_DEBUGGER .globl _bdb_exists /* flag to indicate BDE debugger is available */ _bdb_exists: .long 0 #endif .globl tmpstk .space 0x1000 tmpstk: /* * System Initialization */ .text /* * btext: beginning of text section. * Also the entry point (jumped to directly from the boot blocks). */ NON_GPROF_ENTRY(btext) movw $0x1234,0x472 /* warm boot */ jmp 1f .org 0x500 /* space for BIOS variables */ 1: /* Don't trust what the BIOS gives for eflags. */ pushl $PSL_MBO popfl /* * pass parameters on stack (howto, bootdev, unit, cyloffset, esym) * note: (%esp) is return address of boot * ( if we want to hold onto /boot, it's physical %esp up to _end) */ movl 4(%esp),%eax movl %eax,_boothowto-KERNBASE movl 8(%esp),%eax movl %eax,_bootdev-KERNBASE movl 12(%esp),%eax movl %eax,_cyloffset-KERNBASE movl 16(%esp),%eax addl $KERNBASE,%eax movl %eax,_esym-KERNBASE #ifdef DISKLESS /* Copy diskless structure */ movl _nfs_diskless_size-KERNBASE,%ecx movl 20(%esp),%esi movl $(_nfs_diskless-KERNBASE),%edi cld rep movsb #endif /* Find out our CPU type. */ /* Try to toggle alignment check flag; does not exist on 386. */ pushfl popl %eax movl %eax,%ecx orl $PSL_AC,%eax pushl %eax popfl pushfl popl %eax xorl %ecx,%eax andl $PSL_AC,%eax pushl %ecx popfl testl %eax,%eax jnz 1f movl $CPU_386,_cpu-KERNBASE jmp 2f 1: /* Try to toggle identification flag; does not exist on early 486s. */ pushfl popl %eax movl %eax,%ecx xorl $PSL_ID,%eax pushl %eax popfl pushfl popl %eax xorl %ecx,%eax andl $PSL_ID,%eax pushl %ecx popfl testl %eax,%eax jnz 1f movl $CPU_486,_cpu-KERNBASE /* check for Cyrix 486DLC -- based on check routine */ /* documented in "Cx486SLC/e SMM Programmer's Guide" */ xorw %dx,%dx cmpw %dx,%dx # set flags to known state pushfw popw %cx # store flags in ecx movw $0xffff,%ax movw $0x0004,%bx divw %bx pushfw popw %ax andw $0x08d5,%ax # mask off important bits andw $0x08d5,%cx cmpw %ax,%cx jnz 2f # if flags changed, Intel chip movl $CPU_486DLC,_cpu-KERNBASE # set CPU value for Cyrix movl $0x69727943,_cpu_vendor-KERNBASE # store vendor string movw $0x0078,_cpu_vendor-KERNBASE+4 invd # Start with guaranteed clean cache /* Disable caching of the ISA hole only. */ movb $CCR0,%al # Configuration Register index (CCR0) outb %al,$0x22 inb $0x23,%al orb $CCR0_NC1,%al outb %al,$0x23 invd jmp 2f 1: /* Use the `cpuid' instruction. */ xorl %eax,%eax .byte 0x0f,0xa2 # cpuid 0 movl %ebx,_cpu_vendor-KERNBASE # store vendor string movl %edx,_cpu_vendor+4-KERNBASE movl %ecx,_cpu_vendor+8-KERNBASE movb $0,_cpu_vendor+12-KERNBASE movl $1,%eax .byte 0x0f,0xa2 # cpuid 1 movl %eax,_cpu_id-KERNBASE # store cpu_id rorl $8,%eax # extract family type andl $15,%eax cmpl $5,%eax jae 1f /* less than Pentium; must be 486 */ movl $CPU_486,_cpu-KERNBASE jmp 2f 1: movl $CPU_586,_cpu-KERNBASE 2: /* * Finished with old stack; load new %esp now instead of later so * we can trace this code without having to worry about the trace * trap clobbering the memory test or the zeroing of the bss+bootstrap * page tables. * * XXX - wdboot clears the bss after testing that this is safe. * This is too wasteful - memory below 640K is scarce. The boot * program should check: * text+data <= &stack_variable - more_space_for_stack * text+data+bss+pad+space_for_page_tables <= end_of_memory * Oops, the gdt is in the carcass of the boot program so clearing * the rest of memory is still not possible. */ movl $tmpstk-KERNBASE,%esp /* bootstrap stack end location */ /* * Virtual address space of kernel: * * text | data | bss | [syms] | page dir | proc0 kernel stack | usr stk map | Sysmap * pages: 1 UPAGES (2) 1 NKPT (7) */ /* find end of kernel image */ movl $_end-KERNBASE,%ecx addl $NBPG-1,%ecx /* page align up */ andl $~(NBPG-1),%ecx movl %ecx,%esi /* esi = start of free memory */ movl %ecx,_KERNend-KERNBASE /* save end of kernel */ /* clear bss */ movl $_edata-KERNBASE,%edi subl %edi,%ecx /* get amount to clear */ xorl %eax,%eax /* specify zero fill */ cld rep stosb /* * The value in esi is both the end of the kernel bss and a pointer to * the kernel page directory, and is used by the rest of locore to build * the tables. * esi + 1(page dir) + 2(UPAGES) + 1(p0stack) + NKPT(number of kernel * page table pages) is then passed on the stack to init386(first) as * the value first. esi should ALWAYS be page aligned!! */ movl %esi,%ecx /* Get current first availiable address */ /* clear pagetables, page directory, stack, etc... */ movl %esi,%edi /* base (page directory) */ movl $((1+UPAGES+1+NKPT)*NBPG),%ecx /* amount to clear */ xorl %eax,%eax /* specify zero fill */ cld rep stosb /* physical address of Idle proc/kernel page directory */ movl %esi,_IdlePTD-KERNBASE /* * fillkpt * eax = (page frame address | control | status) == pte * ebx = address of page table * ecx = how many pages to map */ #define fillkpt \ 1: movl %eax,(%ebx) ; \ addl $NBPG,%eax ; /* increment physical address */ \ addl $4,%ebx ; /* next pte */ \ loop 1b ; /* * Map Kernel * * First step - build page tables */ #if defined (KGDB) || defined (BDE_DEBUGGER) movl _KERNend-KERNBASE,%ecx /* this much memory, */ shrl $PGSHIFT,%ecx /* for this many PTEs */ #ifdef BDE_DEBUGGER cmpl $0xa0,%ecx /* XXX - cover debugger pages */ jae 1f movl $0xa0,%ecx 1: #endif /* BDE_DEBUGGER */ movl $PG_V|PG_KW,%eax /* kernel R/W, valid */ lea ((1+UPAGES+1)*NBPG)(%esi),%ebx /* phys addr of kernel PT base */ movl %ebx,_KPTphys-KERNBASE /* save in global */ fillkpt #else /* !KGDB && !BDE_DEBUGGER */ /* write protect kernel text (doesn't do a thing for 386's - only 486's) */ movl $_etext-KERNBASE,%ecx /* get size of text */ shrl $PGSHIFT,%ecx /* for this many PTEs */ movl $PG_V|PG_KR,%eax /* specify read only */ lea ((1+UPAGES+1)*NBPG)(%esi),%ebx /* phys addr of kernel PT base */ movl %ebx,_KPTphys-KERNBASE /* save in global */ fillkpt /* data and bss are r/w */ andl $PG_FRAME,%eax /* strip to just addr of bss */ movl _KERNend-KERNBASE,%ecx /* calculate size */ subl %eax,%ecx shrl $PGSHIFT,%ecx orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ fillkpt #endif /* KGDB || BDE_DEBUGGER */ /* now initialize the page dir, upages, p0stack PT, and page tables */ movl $(1+UPAGES+1+NKPT),%ecx /* number of PTEs */ movl %esi,%eax /* phys address of PTD */ andl $PG_FRAME,%eax /* convert to PFN, should be a NOP */ orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ movl %esi,%ebx /* calculate pte offset to ptd */ shrl $PGSHIFT-2,%ebx addl %esi,%ebx /* address of page directory */ addl $((1+UPAGES+1)*NBPG),%ebx /* offset to kernel page tables */ fillkpt /* map I/O memory map */ movl _KPTphys-KERNBASE,%ebx /* base of kernel page tables */ lea (0xa0 * PTESIZE)(%ebx),%ebx /* hardwire ISA hole at KERNBASE + 0xa0000 */ movl $0x100-0xa0,%ecx /* for this many pte s, */ movl $(0xa0000|PG_V|PG_KW|PG_N),%eax /* valid, kernel read/write, non-cacheable */ movl %ebx,_atdevphys-KERNBASE /* save phys addr of ptes */ fillkpt /* map proc 0's kernel stack into user page table page */ movl $UPAGES,%ecx /* for this many pte s, */ lea (1*NBPG)(%esi),%eax /* physical address in proc 0 */ lea (KERNBASE)(%eax),%edx /* change into virtual addr */ movl %edx,_proc0paddr-KERNBASE /* save VA for proc 0 init */ orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ lea ((1+UPAGES)*NBPG)(%esi),%ebx /* addr of stack page table in proc 0 */ addl $(KSTKPTEOFF * PTESIZE),%ebx /* offset to kernel stack PTE */ fillkpt /* * Initialize kernel page table directory */ /* install a pde for temporary double map of bottom of VA */ movl _KPTphys-KERNBASE,%eax orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ movl %eax,(%esi) /* which is where temp maps! */ /* initialize kernel pde's */ movl $(NKPT),%ecx /* for this many PDEs */ lea (KPTDI*PDESIZE)(%esi),%ebx /* offset of pde for kernel */ fillkpt /* install a pde recursively mapping page directory as a page table! */ movl %esi,%eax /* phys address of ptd in proc 0 */ orl $PG_V|PG_KW,%eax /* pde entry is valid */ movl %eax,PTDPTDI*PDESIZE(%esi) /* which is where PTmap maps! */ /* install a pde to map kernel stack for proc 0 */ lea ((1+UPAGES)*NBPG)(%esi),%eax /* physical address of pt in proc 0 */ orl $PG_V|PG_KW,%eax /* pde entry is valid */ movl %eax,KSTKPTDI*PDESIZE(%esi) /* which is where kernel stack maps! */ #ifdef BDE_DEBUGGER /* copy and convert stuff from old gdt and idt for debugger */ cmpl $0x0375c339,0x96104 /* XXX - debugger signature */ jne 1f movb $1,_bdb_exists-KERNBASE 1: pushal subl $2*6,%esp sgdt (%esp) movl 2(%esp),%esi /* base address of current gdt */ movl $_gdt-KERNBASE,%edi movl %edi,2(%esp) movl $8*18/4,%ecx cld rep /* copy gdt */ movsl movl $_gdt-KERNBASE,-8+2(%edi) /* adjust gdt self-ptr */ movb $0x92,-8+5(%edi) sidt 6(%esp) movl 6+2(%esp),%esi /* base address of current idt */ movl 8+4(%esi),%eax /* convert dbg descriptor to ... */ movw 8(%esi),%ax movl %eax,bdb_dbg_ljmp+1-KERNBASE /* ... immediate offset ... */ movl 8+2(%esi),%eax movw %ax,bdb_dbg_ljmp+5-KERNBASE /* ... and selector for ljmp */ movl 24+4(%esi),%eax /* same for bpt descriptor */ movw 24(%esi),%ax movl %eax,bdb_bpt_ljmp+1-KERNBASE movl 24+2(%esi),%eax movw %ax,bdb_bpt_ljmp+5-KERNBASE movl $_idt-KERNBASE,%edi movl %edi,6+2(%esp) movl $8*4/4,%ecx cld rep /* copy idt */ movsl lgdt (%esp) lidt 6(%esp) addl $2*6,%esp popal #endif /* BDE_DEBUGGER */ /* load base of page directory and enable mapping */ movl %esi,%eax /* phys address of ptd in proc 0 */ - orl $I386_CR3PAT,%eax movl %eax,%cr3 /* load ptd addr into mmu */ movl %cr0,%eax /* get control word */ orl $CR0_PE|CR0_PG,%eax /* enable paging */ movl %eax,%cr0 /* and let's page NOW! */ pushl $begin /* jump to high mem */ ret begin: /* now running relocated at KERNBASE where the system is linked to run */ .globl _Crtat /* XXX - locore should not know about */ movl _Crtat,%eax /* variables of device drivers (pccons)! */ subl $(KERNBASE+0xA0000),%eax movl _atdevphys,%edx /* get pte PA */ subl _KPTphys,%edx /* remove base of ptes, now have phys offset */ shll $PGSHIFT-2,%edx /* corresponding to virt offset */ addl $KERNBASE,%edx /* add virtual base */ movl %edx,_atdevbase addl %eax,%edx movl %edx,_Crtat /* set up bootstrap stack - 48 bytes */ movl $_kstack+UPAGES*NBPG-4*12,%esp /* bootstrap stack end location */ xorl %eax,%eax /* mark end of frames */ movl %eax,%ebp movl _proc0paddr,%eax movl %esi,PCB_CR3(%eax) #ifdef BDE_DEBUGGER /* relocate debugger gdt entries */ movl $_gdt+8*9,%eax /* adjust slots 9-17 */ movl $9,%ecx reloc_gdt: movb $KERNBASE>>24,7(%eax) /* top byte of base addresses, was 0, */ addl $8,%eax /* now KERNBASE>>24 */ loop reloc_gdt cmpl $0,_bdb_exists je 1f int $3 1: #endif /* BDE_DEBUGGER */ /* * Skip over the page tables and the kernel stack */ lea ((1+UPAGES+1+NKPT)*NBPG)(%esi),%esi pushl %esi /* value of first for init386(first) */ call _init386 /* wire 386 chip for unix operation */ popl %esi .globl __ucodesel,__udatasel pushl $0 /* unused */ pushl __udatasel /* ss */ pushl $0 /* esp - filled in by execve() */ pushl $PSL_USERSET /* eflags (ring 0, int enab) */ pushl __ucodesel /* cs */ pushl $0 /* eip - filled in by execve() */ subl $(12*4),%esp /* space for rest of registers */ pushl %esp /* call main with frame pointer */ call _main /* autoconfiguration, mountroot etc */ addl $(13*4),%esp /* back to a frame we can return with */ /* * now we've run main() and determined what cpu-type we are, we can * enable WP mode on i486 cpus and above. */ #if defined(I486_CPU) || defined(I586_CPU) cmpl $CPUCLASS_386,_cpu_class je 1f movl %cr0,%eax /* get control word */ orl $CR0_WP,%eax /* enable write protect for all modes */ movl %eax,%cr0 /* and do it */ #endif /* * on return from main(), we are process 1 * set up address space and stack so that we can 'return' to user mode */ 1: movl __ucodesel,%eax movl __udatasel,%ecx movl %cx,%ds movl %cx,%es movl %ax,%fs /* double map cs to fs */ movl %cx,%gs /* and ds to gs */ iret /* goto user! */ #define LCALL(x,y) .byte 0x9a ; .long y ; .word x NON_GPROF_ENTRY(sigcode) call SIGF_HANDLER(%esp) lea SIGF_SC(%esp),%eax /* scp (the call may have clobbered the */ /* copy at 8(%esp)) */ pushl %eax pushl %eax /* junk to fake return address */ movl $103,%eax /* XXX sigreturn() */ LCALL(0x7,0) /* enter kernel with args on stack */ hlt /* never gets here */ .globl _szsigcode _szsigcode: .long _szsigcode-_sigcode Index: head/sys/amd64/amd64/locore.s =================================================================== --- head/sys/amd64/amd64/locore.s (revision 2688) +++ head/sys/amd64/amd64/locore.s (revision 2689) @@ -1,591 +1,590 @@ /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * William Jolitz. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: @(#)locore.s 7.3 (Berkeley) 5/13/91 - * $Id: locore.s,v 1.25 1994/09/05 05:20:29 davidg Exp $ + * $Id: locore.s,v 1.26 1994/09/05 14:09:41 bde Exp $ */ /* * locore.s: FreeBSD machine support for the Intel 386 * originally from: locore.s, by William F. Jolitz * * Substantially rewritten by David Greenman, Rod Grimes, * Bruce Evans, Wolfgang Solfrank, and many others. */ #include "npx.h" /* for NNPX */ #include "assym.s" /* system definitions */ #include /* processor status longword defs */ #include /* page table entry definitions */ #include /* error return codes */ #include /* x86 special registers */ #include /* x86 cpu type definitions */ #include /* system call numbers */ #include /* miscellaneous asm macros */ /* * XXX * * Note: This version greatly munged to avoid various assembler errors * that may be fixed in newer versions of gas. Perhaps newer versions * will have more pleasant appearance. */ /* * PTmap is recursive pagemap at top of virtual address space. * Within PTmap, the page directory can be found (third indirection). */ .globl _PTmap,_PTD,_PTDpde,_Sysmap .set _PTmap,PTDPTDI << PDRSHIFT .set _PTD,_PTmap + (PTDPTDI * NBPG) .set _PTDpde,_PTD + (PTDPTDI * PDESIZE) /* Sysmap is the base address of the kernel page tables */ .set _Sysmap,_PTmap + (KPTDI * NBPG) /* * APTmap, APTD is the alternate recursive pagemap. * It's used when modifying another process's page tables. */ .globl _APTmap,_APTD,_APTDpde .set _APTmap,APTDPTDI << PDRSHIFT .set _APTD,_APTmap + (APTDPTDI * NBPG) .set _APTDpde,_PTD + (APTDPTDI * PDESIZE) /* * Access to each processes kernel stack is via a region of * per-process address space (at the beginning), immediatly above * the user process stack. */ .set _kstack,USRSTACK .globl _kstack /* * Globals */ .data .globl _esym _esym: .long 0 /* ptr to end of syms */ .globl _boothowto,_bootdev,_curpcb .globl _cpu,_cold,_atdevbase,_cpu_vendor,_cpu_id _cpu: .long 0 /* are we 386, 386sx, or 486 */ _cpu_id: .long 0 /* stepping ID */ _cpu_vendor: .space 20 /* CPU origin code */ _cold: .long 1 /* cold till we are not */ _atdevbase: .long 0 /* location of start of iomem in virtual */ _atdevphys: .long 0 /* location of device mapping ptes (phys) */ .globl _KERNend _KERNend: .long 0 /* phys addr end of kernel (just after bss) */ .globl _IdlePTD,_KPTphys _IdlePTD: .long 0 /* phys addr of kernel PTD */ _KPTphys: .long 0 /* phys addr of kernel page tables */ .globl _cyloffset _cyloffset: .long 0 /* cylinder offset from boot blocks */ .globl _proc0paddr _proc0paddr: .long 0 /* address of proc 0 address space */ #ifdef BDE_DEBUGGER .globl _bdb_exists /* flag to indicate BDE debugger is available */ _bdb_exists: .long 0 #endif .globl tmpstk .space 0x1000 tmpstk: /* * System Initialization */ .text /* * btext: beginning of text section. * Also the entry point (jumped to directly from the boot blocks). */ NON_GPROF_ENTRY(btext) movw $0x1234,0x472 /* warm boot */ jmp 1f .org 0x500 /* space for BIOS variables */ 1: /* Don't trust what the BIOS gives for eflags. */ pushl $PSL_MBO popfl /* * pass parameters on stack (howto, bootdev, unit, cyloffset, esym) * note: (%esp) is return address of boot * ( if we want to hold onto /boot, it's physical %esp up to _end) */ movl 4(%esp),%eax movl %eax,_boothowto-KERNBASE movl 8(%esp),%eax movl %eax,_bootdev-KERNBASE movl 12(%esp),%eax movl %eax,_cyloffset-KERNBASE movl 16(%esp),%eax addl $KERNBASE,%eax movl %eax,_esym-KERNBASE #ifdef DISKLESS /* Copy diskless structure */ movl _nfs_diskless_size-KERNBASE,%ecx movl 20(%esp),%esi movl $(_nfs_diskless-KERNBASE),%edi cld rep movsb #endif /* Find out our CPU type. */ /* Try to toggle alignment check flag; does not exist on 386. */ pushfl popl %eax movl %eax,%ecx orl $PSL_AC,%eax pushl %eax popfl pushfl popl %eax xorl %ecx,%eax andl $PSL_AC,%eax pushl %ecx popfl testl %eax,%eax jnz 1f movl $CPU_386,_cpu-KERNBASE jmp 2f 1: /* Try to toggle identification flag; does not exist on early 486s. */ pushfl popl %eax movl %eax,%ecx xorl $PSL_ID,%eax pushl %eax popfl pushfl popl %eax xorl %ecx,%eax andl $PSL_ID,%eax pushl %ecx popfl testl %eax,%eax jnz 1f movl $CPU_486,_cpu-KERNBASE /* check for Cyrix 486DLC -- based on check routine */ /* documented in "Cx486SLC/e SMM Programmer's Guide" */ xorw %dx,%dx cmpw %dx,%dx # set flags to known state pushfw popw %cx # store flags in ecx movw $0xffff,%ax movw $0x0004,%bx divw %bx pushfw popw %ax andw $0x08d5,%ax # mask off important bits andw $0x08d5,%cx cmpw %ax,%cx jnz 2f # if flags changed, Intel chip movl $CPU_486DLC,_cpu-KERNBASE # set CPU value for Cyrix movl $0x69727943,_cpu_vendor-KERNBASE # store vendor string movw $0x0078,_cpu_vendor-KERNBASE+4 invd # Start with guaranteed clean cache /* Disable caching of the ISA hole only. */ movb $CCR0,%al # Configuration Register index (CCR0) outb %al,$0x22 inb $0x23,%al orb $CCR0_NC1,%al outb %al,$0x23 invd jmp 2f 1: /* Use the `cpuid' instruction. */ xorl %eax,%eax .byte 0x0f,0xa2 # cpuid 0 movl %ebx,_cpu_vendor-KERNBASE # store vendor string movl %edx,_cpu_vendor+4-KERNBASE movl %ecx,_cpu_vendor+8-KERNBASE movb $0,_cpu_vendor+12-KERNBASE movl $1,%eax .byte 0x0f,0xa2 # cpuid 1 movl %eax,_cpu_id-KERNBASE # store cpu_id rorl $8,%eax # extract family type andl $15,%eax cmpl $5,%eax jae 1f /* less than Pentium; must be 486 */ movl $CPU_486,_cpu-KERNBASE jmp 2f 1: movl $CPU_586,_cpu-KERNBASE 2: /* * Finished with old stack; load new %esp now instead of later so * we can trace this code without having to worry about the trace * trap clobbering the memory test or the zeroing of the bss+bootstrap * page tables. * * XXX - wdboot clears the bss after testing that this is safe. * This is too wasteful - memory below 640K is scarce. The boot * program should check: * text+data <= &stack_variable - more_space_for_stack * text+data+bss+pad+space_for_page_tables <= end_of_memory * Oops, the gdt is in the carcass of the boot program so clearing * the rest of memory is still not possible. */ movl $tmpstk-KERNBASE,%esp /* bootstrap stack end location */ /* * Virtual address space of kernel: * * text | data | bss | [syms] | page dir | proc0 kernel stack | usr stk map | Sysmap * pages: 1 UPAGES (2) 1 NKPT (7) */ /* find end of kernel image */ movl $_end-KERNBASE,%ecx addl $NBPG-1,%ecx /* page align up */ andl $~(NBPG-1),%ecx movl %ecx,%esi /* esi = start of free memory */ movl %ecx,_KERNend-KERNBASE /* save end of kernel */ /* clear bss */ movl $_edata-KERNBASE,%edi subl %edi,%ecx /* get amount to clear */ xorl %eax,%eax /* specify zero fill */ cld rep stosb /* * The value in esi is both the end of the kernel bss and a pointer to * the kernel page directory, and is used by the rest of locore to build * the tables. * esi + 1(page dir) + 2(UPAGES) + 1(p0stack) + NKPT(number of kernel * page table pages) is then passed on the stack to init386(first) as * the value first. esi should ALWAYS be page aligned!! */ movl %esi,%ecx /* Get current first availiable address */ /* clear pagetables, page directory, stack, etc... */ movl %esi,%edi /* base (page directory) */ movl $((1+UPAGES+1+NKPT)*NBPG),%ecx /* amount to clear */ xorl %eax,%eax /* specify zero fill */ cld rep stosb /* physical address of Idle proc/kernel page directory */ movl %esi,_IdlePTD-KERNBASE /* * fillkpt * eax = (page frame address | control | status) == pte * ebx = address of page table * ecx = how many pages to map */ #define fillkpt \ 1: movl %eax,(%ebx) ; \ addl $NBPG,%eax ; /* increment physical address */ \ addl $4,%ebx ; /* next pte */ \ loop 1b ; /* * Map Kernel * * First step - build page tables */ #if defined (KGDB) || defined (BDE_DEBUGGER) movl _KERNend-KERNBASE,%ecx /* this much memory, */ shrl $PGSHIFT,%ecx /* for this many PTEs */ #ifdef BDE_DEBUGGER cmpl $0xa0,%ecx /* XXX - cover debugger pages */ jae 1f movl $0xa0,%ecx 1: #endif /* BDE_DEBUGGER */ movl $PG_V|PG_KW,%eax /* kernel R/W, valid */ lea ((1+UPAGES+1)*NBPG)(%esi),%ebx /* phys addr of kernel PT base */ movl %ebx,_KPTphys-KERNBASE /* save in global */ fillkpt #else /* !KGDB && !BDE_DEBUGGER */ /* write protect kernel text (doesn't do a thing for 386's - only 486's) */ movl $_etext-KERNBASE,%ecx /* get size of text */ shrl $PGSHIFT,%ecx /* for this many PTEs */ movl $PG_V|PG_KR,%eax /* specify read only */ lea ((1+UPAGES+1)*NBPG)(%esi),%ebx /* phys addr of kernel PT base */ movl %ebx,_KPTphys-KERNBASE /* save in global */ fillkpt /* data and bss are r/w */ andl $PG_FRAME,%eax /* strip to just addr of bss */ movl _KERNend-KERNBASE,%ecx /* calculate size */ subl %eax,%ecx shrl $PGSHIFT,%ecx orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ fillkpt #endif /* KGDB || BDE_DEBUGGER */ /* now initialize the page dir, upages, p0stack PT, and page tables */ movl $(1+UPAGES+1+NKPT),%ecx /* number of PTEs */ movl %esi,%eax /* phys address of PTD */ andl $PG_FRAME,%eax /* convert to PFN, should be a NOP */ orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ movl %esi,%ebx /* calculate pte offset to ptd */ shrl $PGSHIFT-2,%ebx addl %esi,%ebx /* address of page directory */ addl $((1+UPAGES+1)*NBPG),%ebx /* offset to kernel page tables */ fillkpt /* map I/O memory map */ movl _KPTphys-KERNBASE,%ebx /* base of kernel page tables */ lea (0xa0 * PTESIZE)(%ebx),%ebx /* hardwire ISA hole at KERNBASE + 0xa0000 */ movl $0x100-0xa0,%ecx /* for this many pte s, */ movl $(0xa0000|PG_V|PG_KW|PG_N),%eax /* valid, kernel read/write, non-cacheable */ movl %ebx,_atdevphys-KERNBASE /* save phys addr of ptes */ fillkpt /* map proc 0's kernel stack into user page table page */ movl $UPAGES,%ecx /* for this many pte s, */ lea (1*NBPG)(%esi),%eax /* physical address in proc 0 */ lea (KERNBASE)(%eax),%edx /* change into virtual addr */ movl %edx,_proc0paddr-KERNBASE /* save VA for proc 0 init */ orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ lea ((1+UPAGES)*NBPG)(%esi),%ebx /* addr of stack page table in proc 0 */ addl $(KSTKPTEOFF * PTESIZE),%ebx /* offset to kernel stack PTE */ fillkpt /* * Initialize kernel page table directory */ /* install a pde for temporary double map of bottom of VA */ movl _KPTphys-KERNBASE,%eax orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ movl %eax,(%esi) /* which is where temp maps! */ /* initialize kernel pde's */ movl $(NKPT),%ecx /* for this many PDEs */ lea (KPTDI*PDESIZE)(%esi),%ebx /* offset of pde for kernel */ fillkpt /* install a pde recursively mapping page directory as a page table! */ movl %esi,%eax /* phys address of ptd in proc 0 */ orl $PG_V|PG_KW,%eax /* pde entry is valid */ movl %eax,PTDPTDI*PDESIZE(%esi) /* which is where PTmap maps! */ /* install a pde to map kernel stack for proc 0 */ lea ((1+UPAGES)*NBPG)(%esi),%eax /* physical address of pt in proc 0 */ orl $PG_V|PG_KW,%eax /* pde entry is valid */ movl %eax,KSTKPTDI*PDESIZE(%esi) /* which is where kernel stack maps! */ #ifdef BDE_DEBUGGER /* copy and convert stuff from old gdt and idt for debugger */ cmpl $0x0375c339,0x96104 /* XXX - debugger signature */ jne 1f movb $1,_bdb_exists-KERNBASE 1: pushal subl $2*6,%esp sgdt (%esp) movl 2(%esp),%esi /* base address of current gdt */ movl $_gdt-KERNBASE,%edi movl %edi,2(%esp) movl $8*18/4,%ecx cld rep /* copy gdt */ movsl movl $_gdt-KERNBASE,-8+2(%edi) /* adjust gdt self-ptr */ movb $0x92,-8+5(%edi) sidt 6(%esp) movl 6+2(%esp),%esi /* base address of current idt */ movl 8+4(%esi),%eax /* convert dbg descriptor to ... */ movw 8(%esi),%ax movl %eax,bdb_dbg_ljmp+1-KERNBASE /* ... immediate offset ... */ movl 8+2(%esi),%eax movw %ax,bdb_dbg_ljmp+5-KERNBASE /* ... and selector for ljmp */ movl 24+4(%esi),%eax /* same for bpt descriptor */ movw 24(%esi),%ax movl %eax,bdb_bpt_ljmp+1-KERNBASE movl 24+2(%esi),%eax movw %ax,bdb_bpt_ljmp+5-KERNBASE movl $_idt-KERNBASE,%edi movl %edi,6+2(%esp) movl $8*4/4,%ecx cld rep /* copy idt */ movsl lgdt (%esp) lidt 6(%esp) addl $2*6,%esp popal #endif /* BDE_DEBUGGER */ /* load base of page directory and enable mapping */ movl %esi,%eax /* phys address of ptd in proc 0 */ - orl $I386_CR3PAT,%eax movl %eax,%cr3 /* load ptd addr into mmu */ movl %cr0,%eax /* get control word */ orl $CR0_PE|CR0_PG,%eax /* enable paging */ movl %eax,%cr0 /* and let's page NOW! */ pushl $begin /* jump to high mem */ ret begin: /* now running relocated at KERNBASE where the system is linked to run */ .globl _Crtat /* XXX - locore should not know about */ movl _Crtat,%eax /* variables of device drivers (pccons)! */ subl $(KERNBASE+0xA0000),%eax movl _atdevphys,%edx /* get pte PA */ subl _KPTphys,%edx /* remove base of ptes, now have phys offset */ shll $PGSHIFT-2,%edx /* corresponding to virt offset */ addl $KERNBASE,%edx /* add virtual base */ movl %edx,_atdevbase addl %eax,%edx movl %edx,_Crtat /* set up bootstrap stack - 48 bytes */ movl $_kstack+UPAGES*NBPG-4*12,%esp /* bootstrap stack end location */ xorl %eax,%eax /* mark end of frames */ movl %eax,%ebp movl _proc0paddr,%eax movl %esi,PCB_CR3(%eax) #ifdef BDE_DEBUGGER /* relocate debugger gdt entries */ movl $_gdt+8*9,%eax /* adjust slots 9-17 */ movl $9,%ecx reloc_gdt: movb $KERNBASE>>24,7(%eax) /* top byte of base addresses, was 0, */ addl $8,%eax /* now KERNBASE>>24 */ loop reloc_gdt cmpl $0,_bdb_exists je 1f int $3 1: #endif /* BDE_DEBUGGER */ /* * Skip over the page tables and the kernel stack */ lea ((1+UPAGES+1+NKPT)*NBPG)(%esi),%esi pushl %esi /* value of first for init386(first) */ call _init386 /* wire 386 chip for unix operation */ popl %esi .globl __ucodesel,__udatasel pushl $0 /* unused */ pushl __udatasel /* ss */ pushl $0 /* esp - filled in by execve() */ pushl $PSL_USERSET /* eflags (ring 0, int enab) */ pushl __ucodesel /* cs */ pushl $0 /* eip - filled in by execve() */ subl $(12*4),%esp /* space for rest of registers */ pushl %esp /* call main with frame pointer */ call _main /* autoconfiguration, mountroot etc */ addl $(13*4),%esp /* back to a frame we can return with */ /* * now we've run main() and determined what cpu-type we are, we can * enable WP mode on i486 cpus and above. */ #if defined(I486_CPU) || defined(I586_CPU) cmpl $CPUCLASS_386,_cpu_class je 1f movl %cr0,%eax /* get control word */ orl $CR0_WP,%eax /* enable write protect for all modes */ movl %eax,%cr0 /* and do it */ #endif /* * on return from main(), we are process 1 * set up address space and stack so that we can 'return' to user mode */ 1: movl __ucodesel,%eax movl __udatasel,%ecx movl %cx,%ds movl %cx,%es movl %ax,%fs /* double map cs to fs */ movl %cx,%gs /* and ds to gs */ iret /* goto user! */ #define LCALL(x,y) .byte 0x9a ; .long y ; .word x NON_GPROF_ENTRY(sigcode) call SIGF_HANDLER(%esp) lea SIGF_SC(%esp),%eax /* scp (the call may have clobbered the */ /* copy at 8(%esp)) */ pushl %eax pushl %eax /* junk to fake return address */ movl $103,%eax /* XXX sigreturn() */ LCALL(0x7,0) /* enter kernel with args on stack */ hlt /* never gets here */ .globl _szsigcode _szsigcode: .long _szsigcode-_sigcode Index: head/sys/amd64/amd64/support.S =================================================================== --- head/sys/amd64/amd64/support.S (revision 2688) +++ head/sys/amd64/amd64/support.S (revision 2689) @@ -1,1224 +1,1223 @@ /*- * Copyright (c) 1993 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: support.s,v 1.15 1994/08/09 11:21:44 davidg Exp $ + * $Id: support.s,v 1.16 1994/09/04 10:24:22 davidg Exp $ */ #include "assym.s" /* system definitions */ #include "errno.h" /* error return codes */ #include "machine/asmacros.h" /* miscellaneous asm macros */ #include "machine/cputypes.h" /* types of CPUs */ #define KDSEL 0x10 /* kernel data selector */ #define IDXSHIFT 10 /* * Support routines for GCC, general C-callable functions */ ENTRY(__udivsi3) movl 4(%esp),%eax xorl %edx,%edx divl 8(%esp) ret ENTRY(__divsi3) movl 4(%esp),%eax cltd idivl 8(%esp) ret /* * I/O bus instructions via C */ ENTRY(inb) /* val = inb(port) */ movl 4(%esp),%edx subl %eax,%eax inb %dx,%al NOP ret ENTRY(inw) /* val = inw(port) */ movl 4(%esp),%edx subl %eax,%eax inw %dx,%ax NOP ret ENTRY(insb) /* insb(port, addr, cnt) */ pushl %edi movl 8(%esp),%edx movl 12(%esp),%edi movl 16(%esp),%ecx cld rep insb NOP movl %edi,%eax popl %edi ret ENTRY(insw) /* insw(port, addr, cnt) */ pushl %edi movl 8(%esp),%edx movl 12(%esp),%edi movl 16(%esp),%ecx cld rep insw NOP movl %edi,%eax popl %edi ret ENTRY(insl) /* insl(port, addr, cnt) */ pushl %edi movl 8(%esp),%edx movl 12(%esp),%edi movl 16(%esp),%ecx cld rep insl NOP movl %edi,%eax popl %edi ret ENTRY(rtcin) /* rtcin(val) */ movl 4(%esp),%eax outb %al,$0x70 NOP xorl %eax,%eax inb $0x71,%al NOP ret ENTRY(outb) /* outb(port, val) */ movl 4(%esp),%edx movl 8(%esp),%eax outb %al,%dx NOP ret ENTRY(outw) /* outw(port, val) */ movl 4(%esp),%edx movl 8(%esp),%eax outw %ax,%dx NOP ret ENTRY(outsb) /* outsb(port, addr, cnt) */ pushl %esi movl 8(%esp),%edx movl 12(%esp),%esi movl 16(%esp),%ecx cld rep outsb NOP movl %esi,%eax popl %esi ret ENTRY(outsw) /* outsw(port, addr, cnt) */ pushl %esi movl 8(%esp),%edx movl 12(%esp),%esi movl 16(%esp),%ecx cld rep outsw NOP movl %esi,%eax popl %esi ret ENTRY(outsl) /* outsl(port, addr, cnt) */ pushl %esi movl 8(%esp),%edx movl 12(%esp),%esi movl 16(%esp),%ecx cld rep outsl NOP movl %esi,%eax popl %esi ret /* * bcopy family */ /* * void bzero(void *base, u_int cnt) * Special code for I486 because stosl uses lots * of clocks. Makes little or no difference on DX2 type * machines, but stosl is about 1/2 as fast as * memory moves on a standard DX !!!!! */ ALTENTRY(blkclr) ENTRY(bzero) #if defined(I486_CPU) cmpl $CPUCLASS_486,_cpu_class jz 1f #endif pushl %edi movl 8(%esp),%edi movl 12(%esp),%ecx xorl %eax,%eax shrl $2,%ecx cld rep stosl movl 12(%esp),%ecx andl $3,%ecx rep stosb popl %edi ret #if defined(I486_CPU) SUPERALIGN_TEXT 1: movl 4(%esp),%edx movl 8(%esp),%ecx xorl %eax,%eax / / do 64 byte chunks first / / XXX this is probably over-unrolled at least for DX2's / 2: cmpl $64,%ecx jb 3f movl %eax,(%edx) movl %eax,4(%edx) movl %eax,8(%edx) movl %eax,12(%edx) movl %eax,16(%edx) movl %eax,20(%edx) movl %eax,24(%edx) movl %eax,28(%edx) movl %eax,32(%edx) movl %eax,36(%edx) movl %eax,40(%edx) movl %eax,44(%edx) movl %eax,48(%edx) movl %eax,52(%edx) movl %eax,56(%edx) movl %eax,60(%edx) addl $64,%edx subl $64,%ecx jnz 2b ret / / do 16 byte chunks / SUPERALIGN_TEXT 3: cmpl $16,%ecx jb 4f movl %eax,(%edx) movl %eax,4(%edx) movl %eax,8(%edx) movl %eax,12(%edx) addl $16,%edx subl $16,%ecx jnz 3b ret / / do 4 byte chunks / SUPERALIGN_TEXT 4: cmpl $4,%ecx jb 5f movl %eax,(%edx) addl $4,%edx subl $4,%ecx jnz 4b ret / / do 1 byte chunks / a jump table seems to be faster than a loop or more range reductions / / XXX need a const section for non-text / SUPERALIGN_TEXT jtab: .long do0 .long do1 .long do2 .long do3 SUPERALIGN_TEXT 5: jmp jtab(,%ecx,4) SUPERALIGN_TEXT do3: movw %ax,(%edx) movb %al,2(%edx) ret SUPERALIGN_TEXT do2: movw %ax,(%edx) ret SUPERALIGN_TEXT do1: movb %al,(%edx) SUPERALIGN_TEXT do0: ret #endif /* I486_CPU */ /* fillw(pat, base, cnt) */ ENTRY(fillw) pushl %edi movl 8(%esp),%eax movl 12(%esp),%edi movl 16(%esp),%ecx cld rep stosw popl %edi ret /* filli(pat, base, cnt) */ ENTRY(filli) pushl %edi movl 8(%esp),%eax movl 12(%esp),%edi movl 16(%esp),%ecx cld rep stosl popl %edi ret ENTRY(bcopyb) bcopyb: pushl %esi pushl %edi movl 12(%esp),%esi movl 16(%esp),%edi movl 20(%esp),%ecx cmpl %esi,%edi /* potentially overlapping? */ jnb 1f cld /* nope, copy forwards */ rep movsb popl %edi popl %esi ret ALIGN_TEXT 1: addl %ecx,%edi /* copy backwards. */ addl %ecx,%esi std decl %edi decl %esi rep movsb popl %edi popl %esi cld ret ENTRY(bcopyw) bcopyw: pushl %esi pushl %edi movl 12(%esp),%esi movl 16(%esp),%edi movl 20(%esp),%ecx cmpl %esi,%edi /* potentially overlapping? */ jnb 1f shrl $1,%ecx /* copy by 16-bit words */ cld /* nope, copy forwards */ rep movsw adc %ecx,%ecx /* any bytes left? */ rep movsb popl %edi popl %esi ret ALIGN_TEXT 1: addl %ecx,%edi /* copy backwards */ addl %ecx,%esi andl $1,%ecx /* any fractional bytes? */ decl %edi decl %esi std rep movsb movl 20(%esp),%ecx /* copy remainder by 16-bit words */ shrl $1,%ecx decl %esi decl %edi rep movsw popl %edi popl %esi cld ret ENTRY(bcopyx) movl 16(%esp),%eax cmpl $2,%eax je bcopyw /* not _bcopyw, to avoid multiple mcounts */ cmpl $4,%eax je bcopy /* XXX the shared ret's break mexitcount */ jmp bcopyb /* * (ov)bcopy(src, dst, cnt) * ws@tools.de (Wolfgang Solfrank, TooLs GmbH) +49-228-985800 */ ALTENTRY(ovbcopy) ENTRY(bcopy) bcopy: pushl %esi pushl %edi movl 12(%esp),%esi movl 16(%esp),%edi movl 20(%esp),%ecx cmpl %esi,%edi /* potentially overlapping? */ jnb 1f shrl $2,%ecx /* copy by 32-bit words */ cld /* nope, copy forwards */ rep movsl movl 20(%esp),%ecx andl $3,%ecx /* any bytes left? */ rep movsb popl %edi popl %esi ret ALIGN_TEXT 1: addl %ecx,%edi /* copy backwards */ addl %ecx,%esi andl $3,%ecx /* any fractional bytes? */ decl %edi decl %esi std rep movsb movl 20(%esp),%ecx /* copy remainder by 32-bit words */ shrl $2,%ecx subl $3,%esi subl $3,%edi rep movsl popl %edi popl %esi cld ret /*****************************************************************************/ /* copyout and fubyte family */ /*****************************************************************************/ /* * Access user memory from inside the kernel. These routines and possibly * the math- and DOS emulators should be the only places that do this. * * We have to access the memory with user's permissions, so use a segment * selector with RPL 3. For writes to user space we have to additionally * check the PTE for write permission, because the 386 does not check * write permissions when we are executing with EPL 0. The 486 does check * this if the WP bit is set in CR0, so we can use a simpler version here. * * These routines set curpcb->onfault for the time they execute. When a * protection violation occurs inside the functions, the trap handler * returns to *curpcb->onfault instead of the function. */ ENTRY(copyout) /* copyout(from_kernel, to_user, len) */ movl _curpcb,%eax movl $copyout_fault,PCB_ONFAULT(%eax) pushl %esi pushl %edi pushl %ebx movl 16(%esp),%esi movl 20(%esp),%edi movl 24(%esp),%ebx orl %ebx,%ebx /* anything to do? */ jz done_copyout /* * Check explicitly for non-user addresses. If 486 write protection * is being used, this check is essential because we are in kernel * mode so the h/w does not provide any protection against writing * kernel addresses. * * Otherwise, it saves having to load and restore %es to get the * usual segment-based protection (the destination segment for movs * is always %es). The other explicit checks for user-writablility * are not quite sufficient. They fail for the user area because * we mapped the user area read/write to avoid having an #ifdef in * vm_machdep.c. They fail for user PTEs and/or PTDs! (107 * addresses including 0xff800000 and 0xfc000000). I'm not sure if * this can be fixed. Marking the PTEs supervisor mode and the * PDE's user mode would almost work, but there may be a problem * with the self-referential PDE. */ movl %edi,%eax addl %ebx,%eax jc copyout_fault /* * XXX STOP USING VM_MAXUSER_ADDRESS. * It is an end address, not a max, so every time it is used correctly it * looks like there is an off by one error, and of course it caused an off * by one error in several places. */ cmpl $VM_MAXUSER_ADDRESS,%eax ja copyout_fault #if defined(I386_CPU) #if defined(I486_CPU) || defined(I586_CPU) cmpl $CPUCLASS_386,_cpu_class jne 3f #endif /* * We have to check each PTE for user write permission. * The checking may cause a page fault, so it is important to set * up everything for return via copyout_fault before here. */ /* compute number of pages */ movl %edi,%ecx andl $NBPG-1,%ecx addl %ebx,%ecx decl %ecx shrl $IDXSHIFT+2,%ecx incl %ecx /* compute PTE offset for start address */ movl %edi,%edx shrl $IDXSHIFT,%edx andb $0xfc,%dl 1: /* check PTE for each page */ movb _PTmap(%edx),%al andb $0x07,%al /* Pages must be VALID + USERACC + WRITABLE */ cmpb $0x07,%al je 2f /* simulate a trap */ pushl %edx pushl %ecx shll $IDXSHIFT,%edx pushl %edx call _trapwrite /* trapwrite(addr) */ popl %edx popl %ecx popl %edx orl %eax,%eax /* if not ok, return EFAULT */ jnz copyout_fault 2: addl $4,%edx decl %ecx jnz 1b /* check next page */ #endif /* I386_CPU */ /* bcopy(%esi, %edi, %ebx) */ 3: movl %ebx,%ecx shrl $2,%ecx cld rep movsl movb %bl,%cl andb $3,%cl rep movsb done_copyout: popl %ebx popl %edi popl %esi xorl %eax,%eax movl _curpcb,%edx movl %eax,PCB_ONFAULT(%edx) ret ALIGN_TEXT copyout_fault: popl %ebx popl %edi popl %esi movl _curpcb,%edx movl $0,PCB_ONFAULT(%edx) movl $EFAULT,%eax ret /* copyin(from_user, to_kernel, len) */ ENTRY(copyin) movl _curpcb,%eax movl $copyin_fault,PCB_ONFAULT(%eax) pushl %esi pushl %edi movl 12(%esp),%esi /* caddr_t from */ movl 16(%esp),%edi /* caddr_t to */ movl 20(%esp),%ecx /* size_t len */ /* * make sure address is valid */ movl %esi,%edx addl %ecx,%edx jc copyin_fault cmpl $VM_MAXUSER_ADDRESS,%edx ja copyin_fault movb %cl,%al shrl $2,%ecx /* copy longword-wise */ cld rep movsl movb %al,%cl andb $3,%cl /* copy remaining bytes */ rep movsb popl %edi popl %esi xorl %eax,%eax movl _curpcb,%edx movl %eax,PCB_ONFAULT(%edx) ret ALIGN_TEXT copyin_fault: popl %edi popl %esi movl _curpcb,%edx movl $0,PCB_ONFAULT(%edx) movl $EFAULT,%eax ret /* * fu{byte,sword,word} : fetch a byte (sword, word) from user memory */ ALTENTRY(fuiword) ENTRY(fuword) movl _curpcb,%ecx movl $fusufault,PCB_ONFAULT(%ecx) movl 4(%esp),%edx /* from */ cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address is valid */ ja fusufault movl (%edx),%eax movl $0,PCB_ONFAULT(%ecx) ret /* * These two routines are called from the profiling code, potentially * at interrupt time. If they fail, that's okay, good things will * happen later. Fail all the time for now - until the trap code is * able to deal with this. */ ALTENTRY(suswintr) ENTRY(fuswintr) movl $-1,%eax ret ENTRY(fusword) movl _curpcb,%ecx movl $fusufault,PCB_ONFAULT(%ecx) movl 4(%esp),%edx cmpl $VM_MAXUSER_ADDRESS-2,%edx ja fusufault movzwl (%edx),%eax movl $0,PCB_ONFAULT(%ecx) ret ALTENTRY(fuibyte) ENTRY(fubyte) movl _curpcb,%ecx movl $fusufault,PCB_ONFAULT(%ecx) movl 4(%esp),%edx cmpl $VM_MAXUSER_ADDRESS-1,%edx ja fusufault movzbl (%edx),%eax movl $0,PCB_ONFAULT(%ecx) ret ALIGN_TEXT fusufault: movl _curpcb,%ecx xorl %eax,%eax movl %eax,PCB_ONFAULT(%ecx) decl %eax ret /* * su{byte,sword,word}: write a byte (word, longword) to user memory */ ALTENTRY(suiword) ENTRY(suword) movl _curpcb,%ecx movl $fusufault,PCB_ONFAULT(%ecx) movl 4(%esp),%edx #if defined(I386_CPU) #if defined(I486_CPU) || defined(I586_CPU) cmpl $CPUCLASS_386,_cpu_class jne 2f /* we only have to set the right segment selector */ #endif /* I486_CPU || I586_CPU */ /* XXX - page boundary crossing is still not handled */ movl %edx,%eax shrl $IDXSHIFT,%edx andb $0xfc,%dl movb _PTmap(%edx),%dl andb $0x7,%dl /* must be VALID + USERACC + WRITE */ cmpb $0x7,%dl je 1f /* simulate a trap */ pushl %eax call _trapwrite popl %edx /* remove junk parameter from stack */ movl _curpcb,%ecx /* restore trashed register */ orl %eax,%eax jnz fusufault 1: movl 4(%esp),%edx #endif 2: cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address validity */ ja fusufault movl 8(%esp),%eax movl %eax,(%edx) xorl %eax,%eax movl %eax,PCB_ONFAULT(%ecx) ret ENTRY(susword) movl _curpcb,%ecx movl $fusufault,PCB_ONFAULT(%ecx) movl 4(%esp),%edx #if defined(I386_CPU) #if defined(I486_CPU) || defined(I586_CPU) cmpl $CPUCLASS_386,_cpu_class jne 2f #endif /* I486_CPU || I586_CPU */ /* XXX - page boundary crossing is still not handled */ movl %edx,%eax shrl $IDXSHIFT,%edx andb $0xfc,%dl movb _PTmap(%edx),%dl andb $0x7,%dl /* must be VALID + USERACC + WRITE */ cmpb $0x7,%dl je 1f /* simulate a trap */ pushl %eax call _trapwrite popl %edx /* remove junk parameter from stack */ movl _curpcb,%ecx /* restore trashed register */ orl %eax,%eax jnz fusufault 1: movl 4(%esp),%edx #endif 2: cmpl $VM_MAXUSER_ADDRESS-2,%edx /* verify address validity */ ja fusufault movw 8(%esp),%ax movw %ax,(%edx) xorl %eax,%eax movl %eax,PCB_ONFAULT(%ecx) ret ALTENTRY(suibyte) ENTRY(subyte) movl _curpcb,%ecx movl $fusufault,PCB_ONFAULT(%ecx) movl 4(%esp),%edx #if defined(I386_CPU) #if defined(I486_CPU) || defined(I586_CPU) cmpl $CPUCLASS_386,_cpu_class jne 2f #endif /* I486_CPU || I586_CPU */ movl %edx,%eax shrl $IDXSHIFT,%edx andb $0xfc,%dl movb _PTmap(%edx),%dl andb $0x7,%dl /* must be VALID + USERACC + WRITE */ cmpb $0x7,%dl je 1f /* simulate a trap */ pushl %eax call _trapwrite popl %edx /* remove junk parameter from stack */ movl _curpcb,%ecx /* restore trashed register */ orl %eax,%eax jnz fusufault 1: movl 4(%esp),%edx #endif 2: cmpl $VM_MAXUSER_ADDRESS-1,%edx /* verify address validity */ ja fusufault movb 8(%esp),%al movb %al,(%edx) xorl %eax,%eax movl %eax,PCB_ONFAULT(%ecx) ret /* * copyoutstr(from, to, maxlen, int *lencopied) * copy a string from from to to, stop when a 0 character is reached. * return ENAMETOOLONG if string is longer than maxlen, and * EFAULT on protection violations. If lencopied is non-zero, * return the actual length in *lencopied. */ ENTRY(copyoutstr) pushl %esi pushl %edi movl _curpcb,%ecx movl $cpystrflt,PCB_ONFAULT(%ecx) /* XXX rename copyoutstr_fault */ movl 12(%esp),%esi /* %esi = from */ movl 16(%esp),%edi /* %edi = to */ movl 20(%esp),%edx /* %edx = maxlen */ cld #if defined(I386_CPU) #if defined(I486_CPU) || defined(I586_CPU) cmpl $CPUCLASS_386,_cpu_class jne 5f #endif /* I486_CPU || I586_CPU */ 1: /* * It suffices to check that the first byte is in user space, because * we look at a page at a time and the end address is on a page * boundary. */ cmpl $VM_MAXUSER_ADDRESS-1,%edi ja cpystrflt movl %edi,%eax shrl $IDXSHIFT,%eax andb $0xfc,%al movb _PTmap(%eax),%al andb $7,%al cmpb $7,%al je 2f /* simulate trap */ pushl %edx pushl %edi call _trapwrite cld popl %edi popl %edx orl %eax,%eax jnz cpystrflt 2: /* copy up to end of this page */ movl %edi,%eax andl $NBPG-1,%eax movl $NBPG,%ecx subl %eax,%ecx /* ecx = NBPG - (src % NBPG) */ cmpl %ecx,%edx jae 3f movl %edx,%ecx /* ecx = min(ecx, edx) */ 3: orl %ecx,%ecx jz 4f decl %ecx decl %edx lodsb stosb orb %al,%al jnz 3b /* Success -- 0 byte reached */ decl %edx xorl %eax,%eax jmp 6f 4: /* next page */ orl %edx,%edx jnz 1b /* edx is zero -- return ENAMETOOLONG */ movl $ENAMETOOLONG,%eax jmp cpystrflt_x #endif /* I386_CPU */ #if defined(I486_CPU) || defined(I586_CPU) 5: incl %edx 1: decl %edx jz 2f /* * XXX - would be faster to rewrite this function to use * strlen() and copyout(). */ cmpl $VM_MAXUSER_ADDRESS-1,%edi ja cpystrflt lodsb stosb orb %al,%al jnz 1b /* Success -- 0 byte reached */ decl %edx xorl %eax,%eax jmp cpystrflt_x 2: /* edx is zero -- return ENAMETOOLONG */ movl $ENAMETOOLONG,%eax jmp cpystrflt_x #endif /* I486_CPU || I586_CPU */ /* * copyinstr(from, to, maxlen, int *lencopied) * copy a string from from to to, stop when a 0 character is reached. * return ENAMETOOLONG if string is longer than maxlen, and * EFAULT on protection violations. If lencopied is non-zero, * return the actual length in *lencopied. */ ENTRY(copyinstr) pushl %esi pushl %edi movl _curpcb,%ecx movl $cpystrflt,PCB_ONFAULT(%ecx) movl 12(%esp),%esi /* %esi = from */ movl 16(%esp),%edi /* %edi = to */ movl 20(%esp),%edx /* %edx = maxlen */ movl $VM_MAXUSER_ADDRESS,%eax /* make sure 'from' is within bounds */ subl %esi,%eax jbe cpystrflt /* restrict maxlen to <= VM_MAXUSER_ADDRESS-from */ cmpl %edx,%eax jae 1f movl %eax,%edx movl %eax,20(%esp) 1: incl %edx cld 2: decl %edx jz 3f lodsb stosb orb %al,%al jnz 2b /* Success -- 0 byte reached */ decl %edx xorl %eax,%eax jmp cpystrflt_x 3: /* edx is zero - return ENAMETOOLONG or EFAULT */ cmpl $VM_MAXUSER_ADDRESS,%esi jae cpystrflt 4: movl $ENAMETOOLONG,%eax jmp cpystrflt_x cpystrflt: movl $EFAULT,%eax cpystrflt_x: /* set *lencopied and return %eax */ movl _curpcb,%ecx movl $0,PCB_ONFAULT(%ecx) movl 20(%esp),%ecx subl %edx,%ecx movl 24(%esp),%edx testl %edx,%edx jz 1f movl %ecx,(%edx) 1: popl %edi popl %esi ret /* * copystr(from, to, maxlen, int *lencopied) */ ENTRY(copystr) pushl %esi pushl %edi movl 12(%esp),%esi /* %esi = from */ movl 16(%esp),%edi /* %edi = to */ movl 20(%esp),%edx /* %edx = maxlen */ incl %edx cld 1: decl %edx jz 4f lodsb stosb orb %al,%al jnz 1b /* Success -- 0 byte reached */ decl %edx xorl %eax,%eax jmp 6f 4: /* edx is zero -- return ENAMETOOLONG */ movl $ENAMETOOLONG,%eax 6: /* set *lencopied and return %eax */ movl 20(%esp),%ecx subl %edx,%ecx movl 24(%esp),%edx orl %edx,%edx jz 7f movl %ecx,(%edx) 7: popl %edi popl %esi ret /* * Miscellaneous kernel support functions */ ENTRY(ffs) bsfl 4(%esp),%eax jz 1f incl %eax ret 1: xorl %eax,%eax ret ENTRY(bcmp) pushl %edi pushl %esi movl 12(%esp),%edi movl 16(%esp),%esi movl 20(%esp),%edx xorl %eax,%eax movl %edx,%ecx shrl $2,%ecx cld /* compare forwards */ repe cmpsl jne 1f movl %edx,%ecx andl $3,%ecx repe cmpsb je 2f 1: incl %eax 2: popl %esi popl %edi ret /* * Handling of special 386 registers and descriptor tables etc */ /* void lgdt(struct region_descriptor *rdp); */ ENTRY(lgdt) /* reload the descriptor table */ movl 4(%esp),%eax lgdt (%eax) /* flush the prefetch q */ jmp 1f nop 1: /* reload "stale" selectors */ movl $KDSEL,%eax movl %ax,%ds movl %ax,%es movl %ax,%ss /* reload code selector by turning return into intersegmental return */ movl (%esp),%eax pushl %eax # movl $KCSEL,4(%esp) movl $8,4(%esp) lret /* * void lidt(struct region_descriptor *rdp); */ ENTRY(lidt) movl 4(%esp),%eax lidt (%eax) ret /* * void lldt(u_short sel) */ ENTRY(lldt) lldt 4(%esp) ret /* * void ltr(u_short sel) */ ENTRY(ltr) ltr 4(%esp) ret /* ssdtosd(*ssdp,*sdp) */ ENTRY(ssdtosd) pushl %ebx movl 8(%esp),%ecx movl 8(%ecx),%ebx shll $16,%ebx movl (%ecx),%edx roll $16,%edx movb %dh,%bl movb %dl,%bh rorl $8,%ebx movl 4(%ecx),%eax movw %ax,%dx andl $0xf0000,%eax orl %eax,%ebx movl 12(%esp),%ecx movl %edx,(%ecx) movl %ebx,4(%ecx) popl %ebx ret /* load_cr0(cr0) */ ENTRY(load_cr0) movl 4(%esp),%eax movl %eax,%cr0 ret /* rcr0() */ ENTRY(rcr0) movl %cr0,%eax ret /* rcr3() */ ENTRY(rcr3) movl %cr3,%eax ret /* void load_cr3(caddr_t cr3) */ ENTRY(load_cr3) movl 4(%esp),%eax - orl $I386_CR3PAT,%eax movl %eax,%cr3 ret /*****************************************************************************/ /* setjump, longjump */ /*****************************************************************************/ ENTRY(setjmp) movl 4(%esp),%eax movl %ebx,(%eax) /* save ebx */ movl %esp,4(%eax) /* save esp */ movl %ebp,8(%eax) /* save ebp */ movl %esi,12(%eax) /* save esi */ movl %edi,16(%eax) /* save edi */ movl (%esp),%edx /* get rta */ movl %edx,20(%eax) /* save eip */ xorl %eax,%eax /* return(0); */ ret ENTRY(longjmp) movl 4(%esp),%eax movl (%eax),%ebx /* restore ebx */ movl 4(%eax),%esp /* restore esp */ movl 8(%eax),%ebp /* restore ebp */ movl 12(%eax),%esi /* restore esi */ movl 16(%eax),%edi /* restore edi */ movl 20(%eax),%edx /* get rta */ movl %edx,(%esp) /* put in return frame */ xorl %eax,%eax /* return(1); */ incl %eax ret Index: head/sys/amd64/amd64/support.s =================================================================== --- head/sys/amd64/amd64/support.s (revision 2688) +++ head/sys/amd64/amd64/support.s (revision 2689) @@ -1,1224 +1,1223 @@ /*- * Copyright (c) 1993 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: support.s,v 1.15 1994/08/09 11:21:44 davidg Exp $ + * $Id: support.s,v 1.16 1994/09/04 10:24:22 davidg Exp $ */ #include "assym.s" /* system definitions */ #include "errno.h" /* error return codes */ #include "machine/asmacros.h" /* miscellaneous asm macros */ #include "machine/cputypes.h" /* types of CPUs */ #define KDSEL 0x10 /* kernel data selector */ #define IDXSHIFT 10 /* * Support routines for GCC, general C-callable functions */ ENTRY(__udivsi3) movl 4(%esp),%eax xorl %edx,%edx divl 8(%esp) ret ENTRY(__divsi3) movl 4(%esp),%eax cltd idivl 8(%esp) ret /* * I/O bus instructions via C */ ENTRY(inb) /* val = inb(port) */ movl 4(%esp),%edx subl %eax,%eax inb %dx,%al NOP ret ENTRY(inw) /* val = inw(port) */ movl 4(%esp),%edx subl %eax,%eax inw %dx,%ax NOP ret ENTRY(insb) /* insb(port, addr, cnt) */ pushl %edi movl 8(%esp),%edx movl 12(%esp),%edi movl 16(%esp),%ecx cld rep insb NOP movl %edi,%eax popl %edi ret ENTRY(insw) /* insw(port, addr, cnt) */ pushl %edi movl 8(%esp),%edx movl 12(%esp),%edi movl 16(%esp),%ecx cld rep insw NOP movl %edi,%eax popl %edi ret ENTRY(insl) /* insl(port, addr, cnt) */ pushl %edi movl 8(%esp),%edx movl 12(%esp),%edi movl 16(%esp),%ecx cld rep insl NOP movl %edi,%eax popl %edi ret ENTRY(rtcin) /* rtcin(val) */ movl 4(%esp),%eax outb %al,$0x70 NOP xorl %eax,%eax inb $0x71,%al NOP ret ENTRY(outb) /* outb(port, val) */ movl 4(%esp),%edx movl 8(%esp),%eax outb %al,%dx NOP ret ENTRY(outw) /* outw(port, val) */ movl 4(%esp),%edx movl 8(%esp),%eax outw %ax,%dx NOP ret ENTRY(outsb) /* outsb(port, addr, cnt) */ pushl %esi movl 8(%esp),%edx movl 12(%esp),%esi movl 16(%esp),%ecx cld rep outsb NOP movl %esi,%eax popl %esi ret ENTRY(outsw) /* outsw(port, addr, cnt) */ pushl %esi movl 8(%esp),%edx movl 12(%esp),%esi movl 16(%esp),%ecx cld rep outsw NOP movl %esi,%eax popl %esi ret ENTRY(outsl) /* outsl(port, addr, cnt) */ pushl %esi movl 8(%esp),%edx movl 12(%esp),%esi movl 16(%esp),%ecx cld rep outsl NOP movl %esi,%eax popl %esi ret /* * bcopy family */ /* * void bzero(void *base, u_int cnt) * Special code for I486 because stosl uses lots * of clocks. Makes little or no difference on DX2 type * machines, but stosl is about 1/2 as fast as * memory moves on a standard DX !!!!! */ ALTENTRY(blkclr) ENTRY(bzero) #if defined(I486_CPU) cmpl $CPUCLASS_486,_cpu_class jz 1f #endif pushl %edi movl 8(%esp),%edi movl 12(%esp),%ecx xorl %eax,%eax shrl $2,%ecx cld rep stosl movl 12(%esp),%ecx andl $3,%ecx rep stosb popl %edi ret #if defined(I486_CPU) SUPERALIGN_TEXT 1: movl 4(%esp),%edx movl 8(%esp),%ecx xorl %eax,%eax / / do 64 byte chunks first / / XXX this is probably over-unrolled at least for DX2's / 2: cmpl $64,%ecx jb 3f movl %eax,(%edx) movl %eax,4(%edx) movl %eax,8(%edx) movl %eax,12(%edx) movl %eax,16(%edx) movl %eax,20(%edx) movl %eax,24(%edx) movl %eax,28(%edx) movl %eax,32(%edx) movl %eax,36(%edx) movl %eax,40(%edx) movl %eax,44(%edx) movl %eax,48(%edx) movl %eax,52(%edx) movl %eax,56(%edx) movl %eax,60(%edx) addl $64,%edx subl $64,%ecx jnz 2b ret / / do 16 byte chunks / SUPERALIGN_TEXT 3: cmpl $16,%ecx jb 4f movl %eax,(%edx) movl %eax,4(%edx) movl %eax,8(%edx) movl %eax,12(%edx) addl $16,%edx subl $16,%ecx jnz 3b ret / / do 4 byte chunks / SUPERALIGN_TEXT 4: cmpl $4,%ecx jb 5f movl %eax,(%edx) addl $4,%edx subl $4,%ecx jnz 4b ret / / do 1 byte chunks / a jump table seems to be faster than a loop or more range reductions / / XXX need a const section for non-text / SUPERALIGN_TEXT jtab: .long do0 .long do1 .long do2 .long do3 SUPERALIGN_TEXT 5: jmp jtab(,%ecx,4) SUPERALIGN_TEXT do3: movw %ax,(%edx) movb %al,2(%edx) ret SUPERALIGN_TEXT do2: movw %ax,(%edx) ret SUPERALIGN_TEXT do1: movb %al,(%edx) SUPERALIGN_TEXT do0: ret #endif /* I486_CPU */ /* fillw(pat, base, cnt) */ ENTRY(fillw) pushl %edi movl 8(%esp),%eax movl 12(%esp),%edi movl 16(%esp),%ecx cld rep stosw popl %edi ret /* filli(pat, base, cnt) */ ENTRY(filli) pushl %edi movl 8(%esp),%eax movl 12(%esp),%edi movl 16(%esp),%ecx cld rep stosl popl %edi ret ENTRY(bcopyb) bcopyb: pushl %esi pushl %edi movl 12(%esp),%esi movl 16(%esp),%edi movl 20(%esp),%ecx cmpl %esi,%edi /* potentially overlapping? */ jnb 1f cld /* nope, copy forwards */ rep movsb popl %edi popl %esi ret ALIGN_TEXT 1: addl %ecx,%edi /* copy backwards. */ addl %ecx,%esi std decl %edi decl %esi rep movsb popl %edi popl %esi cld ret ENTRY(bcopyw) bcopyw: pushl %esi pushl %edi movl 12(%esp),%esi movl 16(%esp),%edi movl 20(%esp),%ecx cmpl %esi,%edi /* potentially overlapping? */ jnb 1f shrl $1,%ecx /* copy by 16-bit words */ cld /* nope, copy forwards */ rep movsw adc %ecx,%ecx /* any bytes left? */ rep movsb popl %edi popl %esi ret ALIGN_TEXT 1: addl %ecx,%edi /* copy backwards */ addl %ecx,%esi andl $1,%ecx /* any fractional bytes? */ decl %edi decl %esi std rep movsb movl 20(%esp),%ecx /* copy remainder by 16-bit words */ shrl $1,%ecx decl %esi decl %edi rep movsw popl %edi popl %esi cld ret ENTRY(bcopyx) movl 16(%esp),%eax cmpl $2,%eax je bcopyw /* not _bcopyw, to avoid multiple mcounts */ cmpl $4,%eax je bcopy /* XXX the shared ret's break mexitcount */ jmp bcopyb /* * (ov)bcopy(src, dst, cnt) * ws@tools.de (Wolfgang Solfrank, TooLs GmbH) +49-228-985800 */ ALTENTRY(ovbcopy) ENTRY(bcopy) bcopy: pushl %esi pushl %edi movl 12(%esp),%esi movl 16(%esp),%edi movl 20(%esp),%ecx cmpl %esi,%edi /* potentially overlapping? */ jnb 1f shrl $2,%ecx /* copy by 32-bit words */ cld /* nope, copy forwards */ rep movsl movl 20(%esp),%ecx andl $3,%ecx /* any bytes left? */ rep movsb popl %edi popl %esi ret ALIGN_TEXT 1: addl %ecx,%edi /* copy backwards */ addl %ecx,%esi andl $3,%ecx /* any fractional bytes? */ decl %edi decl %esi std rep movsb movl 20(%esp),%ecx /* copy remainder by 32-bit words */ shrl $2,%ecx subl $3,%esi subl $3,%edi rep movsl popl %edi popl %esi cld ret /*****************************************************************************/ /* copyout and fubyte family */ /*****************************************************************************/ /* * Access user memory from inside the kernel. These routines and possibly * the math- and DOS emulators should be the only places that do this. * * We have to access the memory with user's permissions, so use a segment * selector with RPL 3. For writes to user space we have to additionally * check the PTE for write permission, because the 386 does not check * write permissions when we are executing with EPL 0. The 486 does check * this if the WP bit is set in CR0, so we can use a simpler version here. * * These routines set curpcb->onfault for the time they execute. When a * protection violation occurs inside the functions, the trap handler * returns to *curpcb->onfault instead of the function. */ ENTRY(copyout) /* copyout(from_kernel, to_user, len) */ movl _curpcb,%eax movl $copyout_fault,PCB_ONFAULT(%eax) pushl %esi pushl %edi pushl %ebx movl 16(%esp),%esi movl 20(%esp),%edi movl 24(%esp),%ebx orl %ebx,%ebx /* anything to do? */ jz done_copyout /* * Check explicitly for non-user addresses. If 486 write protection * is being used, this check is essential because we are in kernel * mode so the h/w does not provide any protection against writing * kernel addresses. * * Otherwise, it saves having to load and restore %es to get the * usual segment-based protection (the destination segment for movs * is always %es). The other explicit checks for user-writablility * are not quite sufficient. They fail for the user area because * we mapped the user area read/write to avoid having an #ifdef in * vm_machdep.c. They fail for user PTEs and/or PTDs! (107 * addresses including 0xff800000 and 0xfc000000). I'm not sure if * this can be fixed. Marking the PTEs supervisor mode and the * PDE's user mode would almost work, but there may be a problem * with the self-referential PDE. */ movl %edi,%eax addl %ebx,%eax jc copyout_fault /* * XXX STOP USING VM_MAXUSER_ADDRESS. * It is an end address, not a max, so every time it is used correctly it * looks like there is an off by one error, and of course it caused an off * by one error in several places. */ cmpl $VM_MAXUSER_ADDRESS,%eax ja copyout_fault #if defined(I386_CPU) #if defined(I486_CPU) || defined(I586_CPU) cmpl $CPUCLASS_386,_cpu_class jne 3f #endif /* * We have to check each PTE for user write permission. * The checking may cause a page fault, so it is important to set * up everything for return via copyout_fault before here. */ /* compute number of pages */ movl %edi,%ecx andl $NBPG-1,%ecx addl %ebx,%ecx decl %ecx shrl $IDXSHIFT+2,%ecx incl %ecx /* compute PTE offset for start address */ movl %edi,%edx shrl $IDXSHIFT,%edx andb $0xfc,%dl 1: /* check PTE for each page */ movb _PTmap(%edx),%al andb $0x07,%al /* Pages must be VALID + USERACC + WRITABLE */ cmpb $0x07,%al je 2f /* simulate a trap */ pushl %edx pushl %ecx shll $IDXSHIFT,%edx pushl %edx call _trapwrite /* trapwrite(addr) */ popl %edx popl %ecx popl %edx orl %eax,%eax /* if not ok, return EFAULT */ jnz copyout_fault 2: addl $4,%edx decl %ecx jnz 1b /* check next page */ #endif /* I386_CPU */ /* bcopy(%esi, %edi, %ebx) */ 3: movl %ebx,%ecx shrl $2,%ecx cld rep movsl movb %bl,%cl andb $3,%cl rep movsb done_copyout: popl %ebx popl %edi popl %esi xorl %eax,%eax movl _curpcb,%edx movl %eax,PCB_ONFAULT(%edx) ret ALIGN_TEXT copyout_fault: popl %ebx popl %edi popl %esi movl _curpcb,%edx movl $0,PCB_ONFAULT(%edx) movl $EFAULT,%eax ret /* copyin(from_user, to_kernel, len) */ ENTRY(copyin) movl _curpcb,%eax movl $copyin_fault,PCB_ONFAULT(%eax) pushl %esi pushl %edi movl 12(%esp),%esi /* caddr_t from */ movl 16(%esp),%edi /* caddr_t to */ movl 20(%esp),%ecx /* size_t len */ /* * make sure address is valid */ movl %esi,%edx addl %ecx,%edx jc copyin_fault cmpl $VM_MAXUSER_ADDRESS,%edx ja copyin_fault movb %cl,%al shrl $2,%ecx /* copy longword-wise */ cld rep movsl movb %al,%cl andb $3,%cl /* copy remaining bytes */ rep movsb popl %edi popl %esi xorl %eax,%eax movl _curpcb,%edx movl %eax,PCB_ONFAULT(%edx) ret ALIGN_TEXT copyin_fault: popl %edi popl %esi movl _curpcb,%edx movl $0,PCB_ONFAULT(%edx) movl $EFAULT,%eax ret /* * fu{byte,sword,word} : fetch a byte (sword, word) from user memory */ ALTENTRY(fuiword) ENTRY(fuword) movl _curpcb,%ecx movl $fusufault,PCB_ONFAULT(%ecx) movl 4(%esp),%edx /* from */ cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address is valid */ ja fusufault movl (%edx),%eax movl $0,PCB_ONFAULT(%ecx) ret /* * These two routines are called from the profiling code, potentially * at interrupt time. If they fail, that's okay, good things will * happen later. Fail all the time for now - until the trap code is * able to deal with this. */ ALTENTRY(suswintr) ENTRY(fuswintr) movl $-1,%eax ret ENTRY(fusword) movl _curpcb,%ecx movl $fusufault,PCB_ONFAULT(%ecx) movl 4(%esp),%edx cmpl $VM_MAXUSER_ADDRESS-2,%edx ja fusufault movzwl (%edx),%eax movl $0,PCB_ONFAULT(%ecx) ret ALTENTRY(fuibyte) ENTRY(fubyte) movl _curpcb,%ecx movl $fusufault,PCB_ONFAULT(%ecx) movl 4(%esp),%edx cmpl $VM_MAXUSER_ADDRESS-1,%edx ja fusufault movzbl (%edx),%eax movl $0,PCB_ONFAULT(%ecx) ret ALIGN_TEXT fusufault: movl _curpcb,%ecx xorl %eax,%eax movl %eax,PCB_ONFAULT(%ecx) decl %eax ret /* * su{byte,sword,word}: write a byte (word, longword) to user memory */ ALTENTRY(suiword) ENTRY(suword) movl _curpcb,%ecx movl $fusufault,PCB_ONFAULT(%ecx) movl 4(%esp),%edx #if defined(I386_CPU) #if defined(I486_CPU) || defined(I586_CPU) cmpl $CPUCLASS_386,_cpu_class jne 2f /* we only have to set the right segment selector */ #endif /* I486_CPU || I586_CPU */ /* XXX - page boundary crossing is still not handled */ movl %edx,%eax shrl $IDXSHIFT,%edx andb $0xfc,%dl movb _PTmap(%edx),%dl andb $0x7,%dl /* must be VALID + USERACC + WRITE */ cmpb $0x7,%dl je 1f /* simulate a trap */ pushl %eax call _trapwrite popl %edx /* remove junk parameter from stack */ movl _curpcb,%ecx /* restore trashed register */ orl %eax,%eax jnz fusufault 1: movl 4(%esp),%edx #endif 2: cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address validity */ ja fusufault movl 8(%esp),%eax movl %eax,(%edx) xorl %eax,%eax movl %eax,PCB_ONFAULT(%ecx) ret ENTRY(susword) movl _curpcb,%ecx movl $fusufault,PCB_ONFAULT(%ecx) movl 4(%esp),%edx #if defined(I386_CPU) #if defined(I486_CPU) || defined(I586_CPU) cmpl $CPUCLASS_386,_cpu_class jne 2f #endif /* I486_CPU || I586_CPU */ /* XXX - page boundary crossing is still not handled */ movl %edx,%eax shrl $IDXSHIFT,%edx andb $0xfc,%dl movb _PTmap(%edx),%dl andb $0x7,%dl /* must be VALID + USERACC + WRITE */ cmpb $0x7,%dl je 1f /* simulate a trap */ pushl %eax call _trapwrite popl %edx /* remove junk parameter from stack */ movl _curpcb,%ecx /* restore trashed register */ orl %eax,%eax jnz fusufault 1: movl 4(%esp),%edx #endif 2: cmpl $VM_MAXUSER_ADDRESS-2,%edx /* verify address validity */ ja fusufault movw 8(%esp),%ax movw %ax,(%edx) xorl %eax,%eax movl %eax,PCB_ONFAULT(%ecx) ret ALTENTRY(suibyte) ENTRY(subyte) movl _curpcb,%ecx movl $fusufault,PCB_ONFAULT(%ecx) movl 4(%esp),%edx #if defined(I386_CPU) #if defined(I486_CPU) || defined(I586_CPU) cmpl $CPUCLASS_386,_cpu_class jne 2f #endif /* I486_CPU || I586_CPU */ movl %edx,%eax shrl $IDXSHIFT,%edx andb $0xfc,%dl movb _PTmap(%edx),%dl andb $0x7,%dl /* must be VALID + USERACC + WRITE */ cmpb $0x7,%dl je 1f /* simulate a trap */ pushl %eax call _trapwrite popl %edx /* remove junk parameter from stack */ movl _curpcb,%ecx /* restore trashed register */ orl %eax,%eax jnz fusufault 1: movl 4(%esp),%edx #endif 2: cmpl $VM_MAXUSER_ADDRESS-1,%edx /* verify address validity */ ja fusufault movb 8(%esp),%al movb %al,(%edx) xorl %eax,%eax movl %eax,PCB_ONFAULT(%ecx) ret /* * copyoutstr(from, to, maxlen, int *lencopied) * copy a string from from to to, stop when a 0 character is reached. * return ENAMETOOLONG if string is longer than maxlen, and * EFAULT on protection violations. If lencopied is non-zero, * return the actual length in *lencopied. */ ENTRY(copyoutstr) pushl %esi pushl %edi movl _curpcb,%ecx movl $cpystrflt,PCB_ONFAULT(%ecx) /* XXX rename copyoutstr_fault */ movl 12(%esp),%esi /* %esi = from */ movl 16(%esp),%edi /* %edi = to */ movl 20(%esp),%edx /* %edx = maxlen */ cld #if defined(I386_CPU) #if defined(I486_CPU) || defined(I586_CPU) cmpl $CPUCLASS_386,_cpu_class jne 5f #endif /* I486_CPU || I586_CPU */ 1: /* * It suffices to check that the first byte is in user space, because * we look at a page at a time and the end address is on a page * boundary. */ cmpl $VM_MAXUSER_ADDRESS-1,%edi ja cpystrflt movl %edi,%eax shrl $IDXSHIFT,%eax andb $0xfc,%al movb _PTmap(%eax),%al andb $7,%al cmpb $7,%al je 2f /* simulate trap */ pushl %edx pushl %edi call _trapwrite cld popl %edi popl %edx orl %eax,%eax jnz cpystrflt 2: /* copy up to end of this page */ movl %edi,%eax andl $NBPG-1,%eax movl $NBPG,%ecx subl %eax,%ecx /* ecx = NBPG - (src % NBPG) */ cmpl %ecx,%edx jae 3f movl %edx,%ecx /* ecx = min(ecx, edx) */ 3: orl %ecx,%ecx jz 4f decl %ecx decl %edx lodsb stosb orb %al,%al jnz 3b /* Success -- 0 byte reached */ decl %edx xorl %eax,%eax jmp 6f 4: /* next page */ orl %edx,%edx jnz 1b /* edx is zero -- return ENAMETOOLONG */ movl $ENAMETOOLONG,%eax jmp cpystrflt_x #endif /* I386_CPU */ #if defined(I486_CPU) || defined(I586_CPU) 5: incl %edx 1: decl %edx jz 2f /* * XXX - would be faster to rewrite this function to use * strlen() and copyout(). */ cmpl $VM_MAXUSER_ADDRESS-1,%edi ja cpystrflt lodsb stosb orb %al,%al jnz 1b /* Success -- 0 byte reached */ decl %edx xorl %eax,%eax jmp cpystrflt_x 2: /* edx is zero -- return ENAMETOOLONG */ movl $ENAMETOOLONG,%eax jmp cpystrflt_x #endif /* I486_CPU || I586_CPU */ /* * copyinstr(from, to, maxlen, int *lencopied) * copy a string from from to to, stop when a 0 character is reached. * return ENAMETOOLONG if string is longer than maxlen, and * EFAULT on protection violations. If lencopied is non-zero, * return the actual length in *lencopied. */ ENTRY(copyinstr) pushl %esi pushl %edi movl _curpcb,%ecx movl $cpystrflt,PCB_ONFAULT(%ecx) movl 12(%esp),%esi /* %esi = from */ movl 16(%esp),%edi /* %edi = to */ movl 20(%esp),%edx /* %edx = maxlen */ movl $VM_MAXUSER_ADDRESS,%eax /* make sure 'from' is within bounds */ subl %esi,%eax jbe cpystrflt /* restrict maxlen to <= VM_MAXUSER_ADDRESS-from */ cmpl %edx,%eax jae 1f movl %eax,%edx movl %eax,20(%esp) 1: incl %edx cld 2: decl %edx jz 3f lodsb stosb orb %al,%al jnz 2b /* Success -- 0 byte reached */ decl %edx xorl %eax,%eax jmp cpystrflt_x 3: /* edx is zero - return ENAMETOOLONG or EFAULT */ cmpl $VM_MAXUSER_ADDRESS,%esi jae cpystrflt 4: movl $ENAMETOOLONG,%eax jmp cpystrflt_x cpystrflt: movl $EFAULT,%eax cpystrflt_x: /* set *lencopied and return %eax */ movl _curpcb,%ecx movl $0,PCB_ONFAULT(%ecx) movl 20(%esp),%ecx subl %edx,%ecx movl 24(%esp),%edx testl %edx,%edx jz 1f movl %ecx,(%edx) 1: popl %edi popl %esi ret /* * copystr(from, to, maxlen, int *lencopied) */ ENTRY(copystr) pushl %esi pushl %edi movl 12(%esp),%esi /* %esi = from */ movl 16(%esp),%edi /* %edi = to */ movl 20(%esp),%edx /* %edx = maxlen */ incl %edx cld 1: decl %edx jz 4f lodsb stosb orb %al,%al jnz 1b /* Success -- 0 byte reached */ decl %edx xorl %eax,%eax jmp 6f 4: /* edx is zero -- return ENAMETOOLONG */ movl $ENAMETOOLONG,%eax 6: /* set *lencopied and return %eax */ movl 20(%esp),%ecx subl %edx,%ecx movl 24(%esp),%edx orl %edx,%edx jz 7f movl %ecx,(%edx) 7: popl %edi popl %esi ret /* * Miscellaneous kernel support functions */ ENTRY(ffs) bsfl 4(%esp),%eax jz 1f incl %eax ret 1: xorl %eax,%eax ret ENTRY(bcmp) pushl %edi pushl %esi movl 12(%esp),%edi movl 16(%esp),%esi movl 20(%esp),%edx xorl %eax,%eax movl %edx,%ecx shrl $2,%ecx cld /* compare forwards */ repe cmpsl jne 1f movl %edx,%ecx andl $3,%ecx repe cmpsb je 2f 1: incl %eax 2: popl %esi popl %edi ret /* * Handling of special 386 registers and descriptor tables etc */ /* void lgdt(struct region_descriptor *rdp); */ ENTRY(lgdt) /* reload the descriptor table */ movl 4(%esp),%eax lgdt (%eax) /* flush the prefetch q */ jmp 1f nop 1: /* reload "stale" selectors */ movl $KDSEL,%eax movl %ax,%ds movl %ax,%es movl %ax,%ss /* reload code selector by turning return into intersegmental return */ movl (%esp),%eax pushl %eax # movl $KCSEL,4(%esp) movl $8,4(%esp) lret /* * void lidt(struct region_descriptor *rdp); */ ENTRY(lidt) movl 4(%esp),%eax lidt (%eax) ret /* * void lldt(u_short sel) */ ENTRY(lldt) lldt 4(%esp) ret /* * void ltr(u_short sel) */ ENTRY(ltr) ltr 4(%esp) ret /* ssdtosd(*ssdp,*sdp) */ ENTRY(ssdtosd) pushl %ebx movl 8(%esp),%ecx movl 8(%ecx),%ebx shll $16,%ebx movl (%ecx),%edx roll $16,%edx movb %dh,%bl movb %dl,%bh rorl $8,%ebx movl 4(%ecx),%eax movw %ax,%dx andl $0xf0000,%eax orl %eax,%ebx movl 12(%esp),%ecx movl %edx,(%ecx) movl %ebx,4(%ecx) popl %ebx ret /* load_cr0(cr0) */ ENTRY(load_cr0) movl 4(%esp),%eax movl %eax,%cr0 ret /* rcr0() */ ENTRY(rcr0) movl %cr0,%eax ret /* rcr3() */ ENTRY(rcr3) movl %cr3,%eax ret /* void load_cr3(caddr_t cr3) */ ENTRY(load_cr3) movl 4(%esp),%eax - orl $I386_CR3PAT,%eax movl %eax,%cr3 ret /*****************************************************************************/ /* setjump, longjump */ /*****************************************************************************/ ENTRY(setjmp) movl 4(%esp),%eax movl %ebx,(%eax) /* save ebx */ movl %esp,4(%eax) /* save esp */ movl %ebp,8(%eax) /* save ebp */ movl %esi,12(%eax) /* save esi */ movl %edi,16(%eax) /* save edi */ movl (%esp),%edx /* get rta */ movl %edx,20(%eax) /* save eip */ xorl %eax,%eax /* return(0); */ ret ENTRY(longjmp) movl 4(%esp),%eax movl (%eax),%ebx /* restore ebx */ movl 4(%eax),%esp /* restore esp */ movl 8(%eax),%ebp /* restore ebp */ movl 12(%eax),%esi /* restore esi */ movl 16(%eax),%edi /* restore edi */ movl 20(%eax),%edx /* get rta */ movl %edx,(%esp) /* put in return frame */ xorl %eax,%eax /* return(1); */ incl %eax ret Index: head/sys/amd64/include/vmparam.h =================================================================== --- head/sys/amd64/include/vmparam.h (revision 2688) +++ head/sys/amd64/include/vmparam.h (revision 2689) @@ -1,238 +1,134 @@ /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * Copyright (c) 1994 John S. Dyson * All rights reserved. * * This code is derived from software contributed to Berkeley by * William Jolitz. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: @(#)vmparam.h 5.9 (Berkeley) 5/12/91 - * $Id: vmparam.h,v 1.13 1994/05/25 08:57:22 rgrimes Exp $ + * $Id: vmparam.h,v 1.14 1994/09/01 03:16:40 davidg Exp $ */ #ifndef _MACHINE_VMPARAM_H_ #define _MACHINE_VMPARAM_H_ 1 /* * Machine dependent constants for 386. */ /* - * Virtual address space arrangement. On 386, both user and kernel - * share the address space, not unlike the vax. - * USRTEXT is the start of the user text/data space, while USRSTACK - * is the top (end) of the user stack. Immediately above the user stack - * resides the user structure, which is UPAGES long and contains the - * kernel stack. - * - * Immediately after the user structure is the page table map, and then - * kernal address space. - */ -#define USRTEXT 0UL -/* #define USRSTACK 0xFDBFE000UL */ -#define BTOPUSRSTACK (0xFDC00-(UPAGES)) /* btop(USRSTACK) */ -#define LOWPAGES 0UL -#define HIGHPAGES UPAGES - -/* * Virtual memory related constants, all in bytes */ #define MAXTSIZ (16UL*1024*1024) /* max text size */ #ifndef DFLDSIZ #define DFLDSIZ (64UL*1024*1024) /* initial data size limit */ #endif #ifndef MAXDSIZ #define MAXDSIZ (128UL*1024*1024) /* max data size */ #endif #ifndef DFLSSIZ #define DFLSSIZ (8UL*1024*1024) /* initial stack size limit */ #endif #ifndef MAXSSIZ #define MAXSSIZ (64UL*1024*1024) /* max stack size */ #endif #ifndef SGROWSIZ #define SGROWSIZ (128UL*1024) /* amount to grow stack */ #endif +#define USRTEXT (1*NBPG) /* base of user text XXX bogus */ + /* * Default sizes of swap allocation chunks (see dmap.h). * The actual values may be changed in vminit() based on MAXDSIZ. * With MAXDSIZ of 16Mb and NDMAP of 38, dmmax will be 1024. */ #define DMMIN 32 /* smallest swap allocation */ #define DMMAX 4096 /* largest potential swap allocation */ #define DMTEXT 1024 /* swap allocation for text */ /* * Sizes of the system and user portions of the system page table. */ #define SYSPTSIZE (2*NPTEPG) #define USRPTSIZE (2*NPTEPG) /* * Size of the Shared Memory Pages page table. */ #ifndef SHMMAXPGS #define SHMMAXPGS 512 /* XXX until we have more kmap space */ #endif /* * Size of User Raw I/O map */ #define USRIOSIZE 1024 /* - * The size of the clock loop. - */ -#define LOOPPAGES (maxfree - firstfree) - -/* * The time for a process to be blocked before being very swappable. * This is a number of seconds which the system takes as being a non-trivial * amount of real time. You probably shouldn't change this; * it is used in subtle ways (fractions and multiples of it are, that is, like * half of a ``long time'', almost a long time, etc.) * It is related to human patience and other factors which don't really * change over time. */ #define MAXSLP 20 /* - * A swapped in process is given a small amount of core without being bothered - * by the page replacement algorithm. Basically this says that if you are - * swapped in you deserve some resources. We protect the last SAFERSS - * pages against paging and will just swap you out rather than paging you. - * Note that each process has at least UPAGES+CLSIZE pages which are not - * paged anyways (this is currently 8+2=10 pages or 5k bytes), so this - * number just means a swapped in process is given around 25k bytes. - * Just for fun: current memory prices are 4600$ a megabyte on VAX (4/22/81), - * so we loan each swapped in process memory worth 100$, or just admit - * that we don't consider it worthwhile and swap it out to disk which costs - * $30/mb or about $0.75. - * { wfj 6/16/89: Retail AT memory expansion $800/megabyte, loan of $17 - * on disk costing $7/mb or $0.18 (in memory still 100:1 in cost!) } - */ -#define SAFERSS 8 /* nominal ``small'' resident set size - protected against replacement */ - -/* - * DISKRPM is used to estimate the number of paging i/o operations - * which one can expect from a single disk controller. - */ -#define DISKRPM 60 - -/* - * Klustering constants. Klustering is the gathering - * of pages together for pagein/pageout, while clustering - * is the treatment of hardware page size as though it were - * larger than it really is. - * - * KLMAX gives maximum cluster size in CLSIZE page (cluster-page) - * units. Note that KLMAX*CLSIZE must be <= DMMIN in dmap.h. - */ - -#define KLMAX (4/CLSIZE) -#define KLSEQL (2/CLSIZE) /* in klust if vadvise(VA_SEQL) */ -#define KLIN (4/CLSIZE) /* default data/stack in klust */ -#define KLTXT (4/CLSIZE) /* default text in klust */ -#define KLOUT (4/CLSIZE) - -/* - * KLSDIST is the advance or retard of the fifo reclaim for sequential - * processes data space. - */ -#define KLSDIST 3 /* klusters advance/retard for seq. fifo */ - -/* - * There are two clock hands, initially separated by HANDSPREAD bytes - * (but at most all of user memory). The amount of time to reclaim - * a page once the pageout process examines it increases with this - * distance and decreases as the scan rate rises. - */ -#define HANDSPREAD (2 * 1024 * 1024) - -/* - * The number of times per second to recompute the desired paging rate - * and poke the pagedaemon. - */ -#define RATETOSCHEDPAGING 4 - -/* - * Believed threshold (in megabytes) for which interleaved - * swapping area is desirable. - */ -#define LOTSOFMEM 2 - -#define mapin(pte, v, pfnum, prot) \ - {(*(int *)(pte) = ((pfnum)<p_addr) - -/* - * Flush MMU TLB - */ - -#ifndef I386_CR3PAT -#define I386_CR3PAT 0x0 -#endif #endif /* _MACHINE_VMPARAM_H_ */ Index: head/sys/i386/i386/genassym.c =================================================================== --- head/sys/i386/i386/genassym.c (revision 2688) +++ head/sys/i386/i386/genassym.c (revision 2689) @@ -1,193 +1,191 @@ /*- * Copyright (c) 1982, 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * William Jolitz. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: @(#)genassym.c 5.11 (Berkeley) 5/10/91 - * $Id: genassym.c,v 1.9 1994/09/01 05:12:16 davidg Exp $ + * $Id: genassym.c,v 1.10 1994/09/02 05:58:50 davidg Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include #include main() { struct proc *p = (struct proc *)0; struct vmmeter *vm = (struct vmmeter *)0; struct user *up = (struct user *)0; struct rusage *rup = (struct rusage *)0; struct uprof *uprof = (struct uprof *)0; struct vmspace *vms = (struct vmspace *)0; vm_map_t map = (vm_map_t)0; pmap_t pmap = (pmap_t)0; struct pcb *pcb = (struct pcb *)0; struct trapframe *tf = (struct trapframe *)0; struct sigframe *sigf = (struct sigframe *)0; register unsigned i; - printf("#define\tI386_CR3PAT %d\n", I386_CR3PAT); printf("#define\tUDOT_SZ %d\n", sizeof(struct user)); printf("#define\tP_FORW %d\n", &p->p_forw); printf("#define\tP_BACK %d\n", &p->p_back); printf("#define\tP_VMSPACE %d\n", &p->p_vmspace); printf("#define\tVM_PMAP %d\n", &vms->vm_pmap); printf("#define\tP_ADDR %d\n", &p->p_addr); printf("#define\tP_PRI %d\n", &p->p_priority); printf("#define\tP_RTPRIO %d\n", &p->p_rtprio); printf("#define\tP_STAT %d\n", &p->p_stat); printf("#define\tP_WCHAN %d\n", &p->p_wchan); printf("#define\tP_FLAG %d\n", &p->p_flag); printf("#define\tP_PID %d\n", &p->p_pid); printf("#define\tSSLEEP %d\n", SSLEEP); printf("#define\tSRUN %d\n", SRUN); printf("#define\tV_SWTCH %d\n", &vm->v_swtch); printf("#define\tV_TRAP %d\n", &vm->v_trap); printf("#define\tV_SYSCALL %d\n", &vm->v_syscall); printf("#define\tV_INTR %d\n", &vm->v_intr); printf("#define\tV_SOFT %d\n", &vm->v_soft); /* printf("#define\tV_PDMA %d\n", &vm->v_pdma); */ printf("#define\tV_FAULTS %d\n", &vm->v_faults); /* printf("#define\tV_PGREC %d\n", &vm->v_pgrec); */ /* printf("#define\tV_FASTPGREC %d\n", &vm->v_fastpgrec); */ printf("#define\tUPAGES %d\n", UPAGES); - printf("#define\tHIGHPAGES %d\n", HIGHPAGES); printf("#define\tCLSIZE %d\n", CLSIZE); printf("#define\tNBPG %d\n", NBPG); printf("#define\tNPTEPG %d\n", NPTEPG); printf("#define\tPDESIZE %d\n", PDESIZE); printf("#define\tPTESIZE %d\n", PTESIZE); printf("#define\tNKPDE %d\n", NKPDE); printf("#define\tNKPT %d\n", NKPT); printf("#define\tKPTDI 0x%x\n", KPTDI); printf("#define\tKSTKPTDI 0x%x\n", KSTKPTDI); printf("#define\tKSTKPTEOFF 0x%x\n", KSTKPTEOFF); printf("#define\tPTDPTDI 0x%x\n", PTDPTDI); printf("#define\tAPTDPTDI 0x%x\n", APTDPTDI); printf("#define\tPGSHIFT %d\n", PGSHIFT); printf("#define\tPDRSHIFT %d\n", PDRSHIFT); printf("#define\tSYSPTSIZE %d\n", SYSPTSIZE); printf("#define\tUSRPTSIZE %d\n", USRPTSIZE); printf("#define\tUSRIOSIZE %d\n", USRIOSIZE); #ifdef SYSVSHM printf("#define\tSHMMAXPGS %d\n", SHMMAXPGS); #endif printf("#define\tUSRSTACK 0x%x\n", USRSTACK); printf("#define\tVM_MAXUSER_ADDRESS 0x%x\n", VM_MAXUSER_ADDRESS); printf("#define\tKERNBASE 0x%x\n", KERNBASE); printf("#define\tMSGBUFPTECNT %d\n", btoc(sizeof (struct msgbuf))); printf("#define\tNMBCLUSTERS %d\n", NMBCLUSTERS); printf("#define\tMCLBYTES %d\n", MCLBYTES); printf("#define\tPCB_LINK %d\n", &pcb->pcb_tss.tss_link); printf("#define\tPCB_ESP0 %d\n", &pcb->pcb_tss.tss_esp0); printf("#define\tPCB_SS0 %d\n", &pcb->pcb_tss.tss_ss0); printf("#define\tPCB_ESP1 %d\n", &pcb->pcb_tss.tss_esp1); printf("#define\tPCB_SS1 %d\n", &pcb->pcb_tss.tss_ss1); printf("#define\tPCB_ESP2 %d\n", &pcb->pcb_tss.tss_esp2); printf("#define\tPCB_SS2 %d\n", &pcb->pcb_tss.tss_ss2); printf("#define\tPCB_CR3 %d\n", &pcb->pcb_tss.tss_cr3); printf("#define\tPCB_EIP %d\n", &pcb->pcb_tss.tss_eip); printf("#define\tPCB_EFLAGS %d\n", &pcb->pcb_tss.tss_eflags); printf("#define\tPCB_EAX %d\n", &pcb->pcb_tss.tss_eax); printf("#define\tPCB_ECX %d\n", &pcb->pcb_tss.tss_ecx); printf("#define\tPCB_EDX %d\n", &pcb->pcb_tss.tss_edx); printf("#define\tPCB_EBX %d\n", &pcb->pcb_tss.tss_ebx); printf("#define\tPCB_ESP %d\n", &pcb->pcb_tss.tss_esp); printf("#define\tPCB_EBP %d\n", &pcb->pcb_tss.tss_ebp); printf("#define\tPCB_ESI %d\n", &pcb->pcb_tss.tss_esi); printf("#define\tPCB_EDI %d\n", &pcb->pcb_tss.tss_edi); printf("#define\tPCB_ES %d\n", &pcb->pcb_tss.tss_es); printf("#define\tPCB_CS %d\n", &pcb->pcb_tss.tss_cs); printf("#define\tPCB_SS %d\n", &pcb->pcb_tss.tss_ss); printf("#define\tPCB_DS %d\n", &pcb->pcb_tss.tss_ds); printf("#define\tPCB_FS %d\n", &pcb->pcb_tss.tss_fs); printf("#define\tPCB_GS %d\n", &pcb->pcb_tss.tss_gs); printf("#define\tPCB_LDT %d\n", &pcb->pcb_tss.tss_ldt); printf("#define\tPCB_USERLDT %d\n", &pcb->pcb_ldt); printf("#define\tPCB_IOOPT %d\n", &pcb->pcb_tss.tss_ioopt); printf("#define\tU_PROF %d\n", &up->u_stats.p_prof); printf("#define\tU_PROFSCALE %d\n", &up->u_stats.p_prof.pr_scale); printf("#define\tPR_BASE %d\n", &uprof->pr_base); printf("#define\tPR_SIZE %d\n", &uprof->pr_size); printf("#define\tPR_OFF %d\n", &uprof->pr_off); printf("#define\tPR_SCALE %d\n", &uprof->pr_scale); printf("#define\tRU_MINFLT %d\n", &rup->ru_minflt); printf("#define\tPCB_FLAGS %d\n", &pcb->pcb_flags); printf("#define\tPCB_SAVEFPU %d\n", &pcb->pcb_savefpu); printf("#define\tFP_USESEMC %d\n", FP_USESEMC); printf("#define\tPCB_SAVEEMC %d\n", &pcb->pcb_saveemc); printf("#define\tPCB_CMAP2 %d\n", &pcb->pcb_cmap2); printf("#define\tPCB_IML %d\n", &pcb->pcb_iml); printf("#define\tPCB_ONFAULT %d\n", &pcb->pcb_onfault); printf("#define\tTF_ES %d\n", &tf->tf_es); printf("#define\tTF_DS %d\n", &tf->tf_ds); printf("#define\tTF_EDI %d\n", &tf->tf_edi); printf("#define\tTF_ESI %d\n", &tf->tf_esi); printf("#define\tTF_EBP %d\n", &tf->tf_ebp); printf("#define\tTF_ISP %d\n", &tf->tf_isp); printf("#define\tTF_EBX %d\n", &tf->tf_ebx); printf("#define\tTF_EDX %d\n", &tf->tf_edx); printf("#define\tTF_ECX %d\n", &tf->tf_ecx); printf("#define\tTF_EAX %d\n", &tf->tf_eax); printf("#define\tTF_TRAPNO %d\n", &tf->tf_trapno); printf("#define\tTF_ERR %d\n", &tf->tf_err); printf("#define\tTF_EIP %d\n", &tf->tf_eip); printf("#define\tTF_CS %d\n", &tf->tf_cs); printf("#define\tTF_EFLAGS %d\n", &tf->tf_eflags); printf("#define\tTF_ESP %d\n", &tf->tf_esp); printf("#define\tTF_SS %d\n", &tf->tf_ss); printf("#define\tSIGF_SIGNUM %d\n", &sigf->sf_signum); printf("#define\tSIGF_CODE %d\n", &sigf->sf_code); printf("#define\tSIGF_SCP %d\n", &sigf->sf_scp); printf("#define\tSIGF_HANDLER %d\n", &sigf->sf_handler); printf("#define\tSIGF_SC %d\n", &sigf->sf_sc); printf("#define\tB_READ %d\n", B_READ); printf("#define\tENOENT %d\n", ENOENT); printf("#define\tEFAULT %d\n", EFAULT); printf("#define\tENAMETOOLONG %d\n", ENAMETOOLONG); exit(0); } Index: head/sys/i386/i386/locore.s =================================================================== --- head/sys/i386/i386/locore.s (revision 2688) +++ head/sys/i386/i386/locore.s (revision 2689) @@ -1,591 +1,590 @@ /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * William Jolitz. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: @(#)locore.s 7.3 (Berkeley) 5/13/91 - * $Id: locore.s,v 1.25 1994/09/05 05:20:29 davidg Exp $ + * $Id: locore.s,v 1.26 1994/09/05 14:09:41 bde Exp $ */ /* * locore.s: FreeBSD machine support for the Intel 386 * originally from: locore.s, by William F. Jolitz * * Substantially rewritten by David Greenman, Rod Grimes, * Bruce Evans, Wolfgang Solfrank, and many others. */ #include "npx.h" /* for NNPX */ #include "assym.s" /* system definitions */ #include /* processor status longword defs */ #include /* page table entry definitions */ #include /* error return codes */ #include /* x86 special registers */ #include /* x86 cpu type definitions */ #include /* system call numbers */ #include /* miscellaneous asm macros */ /* * XXX * * Note: This version greatly munged to avoid various assembler errors * that may be fixed in newer versions of gas. Perhaps newer versions * will have more pleasant appearance. */ /* * PTmap is recursive pagemap at top of virtual address space. * Within PTmap, the page directory can be found (third indirection). */ .globl _PTmap,_PTD,_PTDpde,_Sysmap .set _PTmap,PTDPTDI << PDRSHIFT .set _PTD,_PTmap + (PTDPTDI * NBPG) .set _PTDpde,_PTD + (PTDPTDI * PDESIZE) /* Sysmap is the base address of the kernel page tables */ .set _Sysmap,_PTmap + (KPTDI * NBPG) /* * APTmap, APTD is the alternate recursive pagemap. * It's used when modifying another process's page tables. */ .globl _APTmap,_APTD,_APTDpde .set _APTmap,APTDPTDI << PDRSHIFT .set _APTD,_APTmap + (APTDPTDI * NBPG) .set _APTDpde,_PTD + (APTDPTDI * PDESIZE) /* * Access to each processes kernel stack is via a region of * per-process address space (at the beginning), immediatly above * the user process stack. */ .set _kstack,USRSTACK .globl _kstack /* * Globals */ .data .globl _esym _esym: .long 0 /* ptr to end of syms */ .globl _boothowto,_bootdev,_curpcb .globl _cpu,_cold,_atdevbase,_cpu_vendor,_cpu_id _cpu: .long 0 /* are we 386, 386sx, or 486 */ _cpu_id: .long 0 /* stepping ID */ _cpu_vendor: .space 20 /* CPU origin code */ _cold: .long 1 /* cold till we are not */ _atdevbase: .long 0 /* location of start of iomem in virtual */ _atdevphys: .long 0 /* location of device mapping ptes (phys) */ .globl _KERNend _KERNend: .long 0 /* phys addr end of kernel (just after bss) */ .globl _IdlePTD,_KPTphys _IdlePTD: .long 0 /* phys addr of kernel PTD */ _KPTphys: .long 0 /* phys addr of kernel page tables */ .globl _cyloffset _cyloffset: .long 0 /* cylinder offset from boot blocks */ .globl _proc0paddr _proc0paddr: .long 0 /* address of proc 0 address space */ #ifdef BDE_DEBUGGER .globl _bdb_exists /* flag to indicate BDE debugger is available */ _bdb_exists: .long 0 #endif .globl tmpstk .space 0x1000 tmpstk: /* * System Initialization */ .text /* * btext: beginning of text section. * Also the entry point (jumped to directly from the boot blocks). */ NON_GPROF_ENTRY(btext) movw $0x1234,0x472 /* warm boot */ jmp 1f .org 0x500 /* space for BIOS variables */ 1: /* Don't trust what the BIOS gives for eflags. */ pushl $PSL_MBO popfl /* * pass parameters on stack (howto, bootdev, unit, cyloffset, esym) * note: (%esp) is return address of boot * ( if we want to hold onto /boot, it's physical %esp up to _end) */ movl 4(%esp),%eax movl %eax,_boothowto-KERNBASE movl 8(%esp),%eax movl %eax,_bootdev-KERNBASE movl 12(%esp),%eax movl %eax,_cyloffset-KERNBASE movl 16(%esp),%eax addl $KERNBASE,%eax movl %eax,_esym-KERNBASE #ifdef DISKLESS /* Copy diskless structure */ movl _nfs_diskless_size-KERNBASE,%ecx movl 20(%esp),%esi movl $(_nfs_diskless-KERNBASE),%edi cld rep movsb #endif /* Find out our CPU type. */ /* Try to toggle alignment check flag; does not exist on 386. */ pushfl popl %eax movl %eax,%ecx orl $PSL_AC,%eax pushl %eax popfl pushfl popl %eax xorl %ecx,%eax andl $PSL_AC,%eax pushl %ecx popfl testl %eax,%eax jnz 1f movl $CPU_386,_cpu-KERNBASE jmp 2f 1: /* Try to toggle identification flag; does not exist on early 486s. */ pushfl popl %eax movl %eax,%ecx xorl $PSL_ID,%eax pushl %eax popfl pushfl popl %eax xorl %ecx,%eax andl $PSL_ID,%eax pushl %ecx popfl testl %eax,%eax jnz 1f movl $CPU_486,_cpu-KERNBASE /* check for Cyrix 486DLC -- based on check routine */ /* documented in "Cx486SLC/e SMM Programmer's Guide" */ xorw %dx,%dx cmpw %dx,%dx # set flags to known state pushfw popw %cx # store flags in ecx movw $0xffff,%ax movw $0x0004,%bx divw %bx pushfw popw %ax andw $0x08d5,%ax # mask off important bits andw $0x08d5,%cx cmpw %ax,%cx jnz 2f # if flags changed, Intel chip movl $CPU_486DLC,_cpu-KERNBASE # set CPU value for Cyrix movl $0x69727943,_cpu_vendor-KERNBASE # store vendor string movw $0x0078,_cpu_vendor-KERNBASE+4 invd # Start with guaranteed clean cache /* Disable caching of the ISA hole only. */ movb $CCR0,%al # Configuration Register index (CCR0) outb %al,$0x22 inb $0x23,%al orb $CCR0_NC1,%al outb %al,$0x23 invd jmp 2f 1: /* Use the `cpuid' instruction. */ xorl %eax,%eax .byte 0x0f,0xa2 # cpuid 0 movl %ebx,_cpu_vendor-KERNBASE # store vendor string movl %edx,_cpu_vendor+4-KERNBASE movl %ecx,_cpu_vendor+8-KERNBASE movb $0,_cpu_vendor+12-KERNBASE movl $1,%eax .byte 0x0f,0xa2 # cpuid 1 movl %eax,_cpu_id-KERNBASE # store cpu_id rorl $8,%eax # extract family type andl $15,%eax cmpl $5,%eax jae 1f /* less than Pentium; must be 486 */ movl $CPU_486,_cpu-KERNBASE jmp 2f 1: movl $CPU_586,_cpu-KERNBASE 2: /* * Finished with old stack; load new %esp now instead of later so * we can trace this code without having to worry about the trace * trap clobbering the memory test or the zeroing of the bss+bootstrap * page tables. * * XXX - wdboot clears the bss after testing that this is safe. * This is too wasteful - memory below 640K is scarce. The boot * program should check: * text+data <= &stack_variable - more_space_for_stack * text+data+bss+pad+space_for_page_tables <= end_of_memory * Oops, the gdt is in the carcass of the boot program so clearing * the rest of memory is still not possible. */ movl $tmpstk-KERNBASE,%esp /* bootstrap stack end location */ /* * Virtual address space of kernel: * * text | data | bss | [syms] | page dir | proc0 kernel stack | usr stk map | Sysmap * pages: 1 UPAGES (2) 1 NKPT (7) */ /* find end of kernel image */ movl $_end-KERNBASE,%ecx addl $NBPG-1,%ecx /* page align up */ andl $~(NBPG-1),%ecx movl %ecx,%esi /* esi = start of free memory */ movl %ecx,_KERNend-KERNBASE /* save end of kernel */ /* clear bss */ movl $_edata-KERNBASE,%edi subl %edi,%ecx /* get amount to clear */ xorl %eax,%eax /* specify zero fill */ cld rep stosb /* * The value in esi is both the end of the kernel bss and a pointer to * the kernel page directory, and is used by the rest of locore to build * the tables. * esi + 1(page dir) + 2(UPAGES) + 1(p0stack) + NKPT(number of kernel * page table pages) is then passed on the stack to init386(first) as * the value first. esi should ALWAYS be page aligned!! */ movl %esi,%ecx /* Get current first availiable address */ /* clear pagetables, page directory, stack, etc... */ movl %esi,%edi /* base (page directory) */ movl $((1+UPAGES+1+NKPT)*NBPG),%ecx /* amount to clear */ xorl %eax,%eax /* specify zero fill */ cld rep stosb /* physical address of Idle proc/kernel page directory */ movl %esi,_IdlePTD-KERNBASE /* * fillkpt * eax = (page frame address | control | status) == pte * ebx = address of page table * ecx = how many pages to map */ #define fillkpt \ 1: movl %eax,(%ebx) ; \ addl $NBPG,%eax ; /* increment physical address */ \ addl $4,%ebx ; /* next pte */ \ loop 1b ; /* * Map Kernel * * First step - build page tables */ #if defined (KGDB) || defined (BDE_DEBUGGER) movl _KERNend-KERNBASE,%ecx /* this much memory, */ shrl $PGSHIFT,%ecx /* for this many PTEs */ #ifdef BDE_DEBUGGER cmpl $0xa0,%ecx /* XXX - cover debugger pages */ jae 1f movl $0xa0,%ecx 1: #endif /* BDE_DEBUGGER */ movl $PG_V|PG_KW,%eax /* kernel R/W, valid */ lea ((1+UPAGES+1)*NBPG)(%esi),%ebx /* phys addr of kernel PT base */ movl %ebx,_KPTphys-KERNBASE /* save in global */ fillkpt #else /* !KGDB && !BDE_DEBUGGER */ /* write protect kernel text (doesn't do a thing for 386's - only 486's) */ movl $_etext-KERNBASE,%ecx /* get size of text */ shrl $PGSHIFT,%ecx /* for this many PTEs */ movl $PG_V|PG_KR,%eax /* specify read only */ lea ((1+UPAGES+1)*NBPG)(%esi),%ebx /* phys addr of kernel PT base */ movl %ebx,_KPTphys-KERNBASE /* save in global */ fillkpt /* data and bss are r/w */ andl $PG_FRAME,%eax /* strip to just addr of bss */ movl _KERNend-KERNBASE,%ecx /* calculate size */ subl %eax,%ecx shrl $PGSHIFT,%ecx orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ fillkpt #endif /* KGDB || BDE_DEBUGGER */ /* now initialize the page dir, upages, p0stack PT, and page tables */ movl $(1+UPAGES+1+NKPT),%ecx /* number of PTEs */ movl %esi,%eax /* phys address of PTD */ andl $PG_FRAME,%eax /* convert to PFN, should be a NOP */ orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ movl %esi,%ebx /* calculate pte offset to ptd */ shrl $PGSHIFT-2,%ebx addl %esi,%ebx /* address of page directory */ addl $((1+UPAGES+1)*NBPG),%ebx /* offset to kernel page tables */ fillkpt /* map I/O memory map */ movl _KPTphys-KERNBASE,%ebx /* base of kernel page tables */ lea (0xa0 * PTESIZE)(%ebx),%ebx /* hardwire ISA hole at KERNBASE + 0xa0000 */ movl $0x100-0xa0,%ecx /* for this many pte s, */ movl $(0xa0000|PG_V|PG_KW|PG_N),%eax /* valid, kernel read/write, non-cacheable */ movl %ebx,_atdevphys-KERNBASE /* save phys addr of ptes */ fillkpt /* map proc 0's kernel stack into user page table page */ movl $UPAGES,%ecx /* for this many pte s, */ lea (1*NBPG)(%esi),%eax /* physical address in proc 0 */ lea (KERNBASE)(%eax),%edx /* change into virtual addr */ movl %edx,_proc0paddr-KERNBASE /* save VA for proc 0 init */ orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ lea ((1+UPAGES)*NBPG)(%esi),%ebx /* addr of stack page table in proc 0 */ addl $(KSTKPTEOFF * PTESIZE),%ebx /* offset to kernel stack PTE */ fillkpt /* * Initialize kernel page table directory */ /* install a pde for temporary double map of bottom of VA */ movl _KPTphys-KERNBASE,%eax orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ movl %eax,(%esi) /* which is where temp maps! */ /* initialize kernel pde's */ movl $(NKPT),%ecx /* for this many PDEs */ lea (KPTDI*PDESIZE)(%esi),%ebx /* offset of pde for kernel */ fillkpt /* install a pde recursively mapping page directory as a page table! */ movl %esi,%eax /* phys address of ptd in proc 0 */ orl $PG_V|PG_KW,%eax /* pde entry is valid */ movl %eax,PTDPTDI*PDESIZE(%esi) /* which is where PTmap maps! */ /* install a pde to map kernel stack for proc 0 */ lea ((1+UPAGES)*NBPG)(%esi),%eax /* physical address of pt in proc 0 */ orl $PG_V|PG_KW,%eax /* pde entry is valid */ movl %eax,KSTKPTDI*PDESIZE(%esi) /* which is where kernel stack maps! */ #ifdef BDE_DEBUGGER /* copy and convert stuff from old gdt and idt for debugger */ cmpl $0x0375c339,0x96104 /* XXX - debugger signature */ jne 1f movb $1,_bdb_exists-KERNBASE 1: pushal subl $2*6,%esp sgdt (%esp) movl 2(%esp),%esi /* base address of current gdt */ movl $_gdt-KERNBASE,%edi movl %edi,2(%esp) movl $8*18/4,%ecx cld rep /* copy gdt */ movsl movl $_gdt-KERNBASE,-8+2(%edi) /* adjust gdt self-ptr */ movb $0x92,-8+5(%edi) sidt 6(%esp) movl 6+2(%esp),%esi /* base address of current idt */ movl 8+4(%esi),%eax /* convert dbg descriptor to ... */ movw 8(%esi),%ax movl %eax,bdb_dbg_ljmp+1-KERNBASE /* ... immediate offset ... */ movl 8+2(%esi),%eax movw %ax,bdb_dbg_ljmp+5-KERNBASE /* ... and selector for ljmp */ movl 24+4(%esi),%eax /* same for bpt descriptor */ movw 24(%esi),%ax movl %eax,bdb_bpt_ljmp+1-KERNBASE movl 24+2(%esi),%eax movw %ax,bdb_bpt_ljmp+5-KERNBASE movl $_idt-KERNBASE,%edi movl %edi,6+2(%esp) movl $8*4/4,%ecx cld rep /* copy idt */ movsl lgdt (%esp) lidt 6(%esp) addl $2*6,%esp popal #endif /* BDE_DEBUGGER */ /* load base of page directory and enable mapping */ movl %esi,%eax /* phys address of ptd in proc 0 */ - orl $I386_CR3PAT,%eax movl %eax,%cr3 /* load ptd addr into mmu */ movl %cr0,%eax /* get control word */ orl $CR0_PE|CR0_PG,%eax /* enable paging */ movl %eax,%cr0 /* and let's page NOW! */ pushl $begin /* jump to high mem */ ret begin: /* now running relocated at KERNBASE where the system is linked to run */ .globl _Crtat /* XXX - locore should not know about */ movl _Crtat,%eax /* variables of device drivers (pccons)! */ subl $(KERNBASE+0xA0000),%eax movl _atdevphys,%edx /* get pte PA */ subl _KPTphys,%edx /* remove base of ptes, now have phys offset */ shll $PGSHIFT-2,%edx /* corresponding to virt offset */ addl $KERNBASE,%edx /* add virtual base */ movl %edx,_atdevbase addl %eax,%edx movl %edx,_Crtat /* set up bootstrap stack - 48 bytes */ movl $_kstack+UPAGES*NBPG-4*12,%esp /* bootstrap stack end location */ xorl %eax,%eax /* mark end of frames */ movl %eax,%ebp movl _proc0paddr,%eax movl %esi,PCB_CR3(%eax) #ifdef BDE_DEBUGGER /* relocate debugger gdt entries */ movl $_gdt+8*9,%eax /* adjust slots 9-17 */ movl $9,%ecx reloc_gdt: movb $KERNBASE>>24,7(%eax) /* top byte of base addresses, was 0, */ addl $8,%eax /* now KERNBASE>>24 */ loop reloc_gdt cmpl $0,_bdb_exists je 1f int $3 1: #endif /* BDE_DEBUGGER */ /* * Skip over the page tables and the kernel stack */ lea ((1+UPAGES+1+NKPT)*NBPG)(%esi),%esi pushl %esi /* value of first for init386(first) */ call _init386 /* wire 386 chip for unix operation */ popl %esi .globl __ucodesel,__udatasel pushl $0 /* unused */ pushl __udatasel /* ss */ pushl $0 /* esp - filled in by execve() */ pushl $PSL_USERSET /* eflags (ring 0, int enab) */ pushl __ucodesel /* cs */ pushl $0 /* eip - filled in by execve() */ subl $(12*4),%esp /* space for rest of registers */ pushl %esp /* call main with frame pointer */ call _main /* autoconfiguration, mountroot etc */ addl $(13*4),%esp /* back to a frame we can return with */ /* * now we've run main() and determined what cpu-type we are, we can * enable WP mode on i486 cpus and above. */ #if defined(I486_CPU) || defined(I586_CPU) cmpl $CPUCLASS_386,_cpu_class je 1f movl %cr0,%eax /* get control word */ orl $CR0_WP,%eax /* enable write protect for all modes */ movl %eax,%cr0 /* and do it */ #endif /* * on return from main(), we are process 1 * set up address space and stack so that we can 'return' to user mode */ 1: movl __ucodesel,%eax movl __udatasel,%ecx movl %cx,%ds movl %cx,%es movl %ax,%fs /* double map cs to fs */ movl %cx,%gs /* and ds to gs */ iret /* goto user! */ #define LCALL(x,y) .byte 0x9a ; .long y ; .word x NON_GPROF_ENTRY(sigcode) call SIGF_HANDLER(%esp) lea SIGF_SC(%esp),%eax /* scp (the call may have clobbered the */ /* copy at 8(%esp)) */ pushl %eax pushl %eax /* junk to fake return address */ movl $103,%eax /* XXX sigreturn() */ LCALL(0x7,0) /* enter kernel with args on stack */ hlt /* never gets here */ .globl _szsigcode _szsigcode: .long _szsigcode-_sigcode Index: head/sys/i386/i386/support.s =================================================================== --- head/sys/i386/i386/support.s (revision 2688) +++ head/sys/i386/i386/support.s (revision 2689) @@ -1,1224 +1,1223 @@ /*- * Copyright (c) 1993 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: support.s,v 1.15 1994/08/09 11:21:44 davidg Exp $ + * $Id: support.s,v 1.16 1994/09/04 10:24:22 davidg Exp $ */ #include "assym.s" /* system definitions */ #include "errno.h" /* error return codes */ #include "machine/asmacros.h" /* miscellaneous asm macros */ #include "machine/cputypes.h" /* types of CPUs */ #define KDSEL 0x10 /* kernel data selector */ #define IDXSHIFT 10 /* * Support routines for GCC, general C-callable functions */ ENTRY(__udivsi3) movl 4(%esp),%eax xorl %edx,%edx divl 8(%esp) ret ENTRY(__divsi3) movl 4(%esp),%eax cltd idivl 8(%esp) ret /* * I/O bus instructions via C */ ENTRY(inb) /* val = inb(port) */ movl 4(%esp),%edx subl %eax,%eax inb %dx,%al NOP ret ENTRY(inw) /* val = inw(port) */ movl 4(%esp),%edx subl %eax,%eax inw %dx,%ax NOP ret ENTRY(insb) /* insb(port, addr, cnt) */ pushl %edi movl 8(%esp),%edx movl 12(%esp),%edi movl 16(%esp),%ecx cld rep insb NOP movl %edi,%eax popl %edi ret ENTRY(insw) /* insw(port, addr, cnt) */ pushl %edi movl 8(%esp),%edx movl 12(%esp),%edi movl 16(%esp),%ecx cld rep insw NOP movl %edi,%eax popl %edi ret ENTRY(insl) /* insl(port, addr, cnt) */ pushl %edi movl 8(%esp),%edx movl 12(%esp),%edi movl 16(%esp),%ecx cld rep insl NOP movl %edi,%eax popl %edi ret ENTRY(rtcin) /* rtcin(val) */ movl 4(%esp),%eax outb %al,$0x70 NOP xorl %eax,%eax inb $0x71,%al NOP ret ENTRY(outb) /* outb(port, val) */ movl 4(%esp),%edx movl 8(%esp),%eax outb %al,%dx NOP ret ENTRY(outw) /* outw(port, val) */ movl 4(%esp),%edx movl 8(%esp),%eax outw %ax,%dx NOP ret ENTRY(outsb) /* outsb(port, addr, cnt) */ pushl %esi movl 8(%esp),%edx movl 12(%esp),%esi movl 16(%esp),%ecx cld rep outsb NOP movl %esi,%eax popl %esi ret ENTRY(outsw) /* outsw(port, addr, cnt) */ pushl %esi movl 8(%esp),%edx movl 12(%esp),%esi movl 16(%esp),%ecx cld rep outsw NOP movl %esi,%eax popl %esi ret ENTRY(outsl) /* outsl(port, addr, cnt) */ pushl %esi movl 8(%esp),%edx movl 12(%esp),%esi movl 16(%esp),%ecx cld rep outsl NOP movl %esi,%eax popl %esi ret /* * bcopy family */ /* * void bzero(void *base, u_int cnt) * Special code for I486 because stosl uses lots * of clocks. Makes little or no difference on DX2 type * machines, but stosl is about 1/2 as fast as * memory moves on a standard DX !!!!! */ ALTENTRY(blkclr) ENTRY(bzero) #if defined(I486_CPU) cmpl $CPUCLASS_486,_cpu_class jz 1f #endif pushl %edi movl 8(%esp),%edi movl 12(%esp),%ecx xorl %eax,%eax shrl $2,%ecx cld rep stosl movl 12(%esp),%ecx andl $3,%ecx rep stosb popl %edi ret #if defined(I486_CPU) SUPERALIGN_TEXT 1: movl 4(%esp),%edx movl 8(%esp),%ecx xorl %eax,%eax / / do 64 byte chunks first / / XXX this is probably over-unrolled at least for DX2's / 2: cmpl $64,%ecx jb 3f movl %eax,(%edx) movl %eax,4(%edx) movl %eax,8(%edx) movl %eax,12(%edx) movl %eax,16(%edx) movl %eax,20(%edx) movl %eax,24(%edx) movl %eax,28(%edx) movl %eax,32(%edx) movl %eax,36(%edx) movl %eax,40(%edx) movl %eax,44(%edx) movl %eax,48(%edx) movl %eax,52(%edx) movl %eax,56(%edx) movl %eax,60(%edx) addl $64,%edx subl $64,%ecx jnz 2b ret / / do 16 byte chunks / SUPERALIGN_TEXT 3: cmpl $16,%ecx jb 4f movl %eax,(%edx) movl %eax,4(%edx) movl %eax,8(%edx) movl %eax,12(%edx) addl $16,%edx subl $16,%ecx jnz 3b ret / / do 4 byte chunks / SUPERALIGN_TEXT 4: cmpl $4,%ecx jb 5f movl %eax,(%edx) addl $4,%edx subl $4,%ecx jnz 4b ret / / do 1 byte chunks / a jump table seems to be faster than a loop or more range reductions / / XXX need a const section for non-text / SUPERALIGN_TEXT jtab: .long do0 .long do1 .long do2 .long do3 SUPERALIGN_TEXT 5: jmp jtab(,%ecx,4) SUPERALIGN_TEXT do3: movw %ax,(%edx) movb %al,2(%edx) ret SUPERALIGN_TEXT do2: movw %ax,(%edx) ret SUPERALIGN_TEXT do1: movb %al,(%edx) SUPERALIGN_TEXT do0: ret #endif /* I486_CPU */ /* fillw(pat, base, cnt) */ ENTRY(fillw) pushl %edi movl 8(%esp),%eax movl 12(%esp),%edi movl 16(%esp),%ecx cld rep stosw popl %edi ret /* filli(pat, base, cnt) */ ENTRY(filli) pushl %edi movl 8(%esp),%eax movl 12(%esp),%edi movl 16(%esp),%ecx cld rep stosl popl %edi ret ENTRY(bcopyb) bcopyb: pushl %esi pushl %edi movl 12(%esp),%esi movl 16(%esp),%edi movl 20(%esp),%ecx cmpl %esi,%edi /* potentially overlapping? */ jnb 1f cld /* nope, copy forwards */ rep movsb popl %edi popl %esi ret ALIGN_TEXT 1: addl %ecx,%edi /* copy backwards. */ addl %ecx,%esi std decl %edi decl %esi rep movsb popl %edi popl %esi cld ret ENTRY(bcopyw) bcopyw: pushl %esi pushl %edi movl 12(%esp),%esi movl 16(%esp),%edi movl 20(%esp),%ecx cmpl %esi,%edi /* potentially overlapping? */ jnb 1f shrl $1,%ecx /* copy by 16-bit words */ cld /* nope, copy forwards */ rep movsw adc %ecx,%ecx /* any bytes left? */ rep movsb popl %edi popl %esi ret ALIGN_TEXT 1: addl %ecx,%edi /* copy backwards */ addl %ecx,%esi andl $1,%ecx /* any fractional bytes? */ decl %edi decl %esi std rep movsb movl 20(%esp),%ecx /* copy remainder by 16-bit words */ shrl $1,%ecx decl %esi decl %edi rep movsw popl %edi popl %esi cld ret ENTRY(bcopyx) movl 16(%esp),%eax cmpl $2,%eax je bcopyw /* not _bcopyw, to avoid multiple mcounts */ cmpl $4,%eax je bcopy /* XXX the shared ret's break mexitcount */ jmp bcopyb /* * (ov)bcopy(src, dst, cnt) * ws@tools.de (Wolfgang Solfrank, TooLs GmbH) +49-228-985800 */ ALTENTRY(ovbcopy) ENTRY(bcopy) bcopy: pushl %esi pushl %edi movl 12(%esp),%esi movl 16(%esp),%edi movl 20(%esp),%ecx cmpl %esi,%edi /* potentially overlapping? */ jnb 1f shrl $2,%ecx /* copy by 32-bit words */ cld /* nope, copy forwards */ rep movsl movl 20(%esp),%ecx andl $3,%ecx /* any bytes left? */ rep movsb popl %edi popl %esi ret ALIGN_TEXT 1: addl %ecx,%edi /* copy backwards */ addl %ecx,%esi andl $3,%ecx /* any fractional bytes? */ decl %edi decl %esi std rep movsb movl 20(%esp),%ecx /* copy remainder by 32-bit words */ shrl $2,%ecx subl $3,%esi subl $3,%edi rep movsl popl %edi popl %esi cld ret /*****************************************************************************/ /* copyout and fubyte family */ /*****************************************************************************/ /* * Access user memory from inside the kernel. These routines and possibly * the math- and DOS emulators should be the only places that do this. * * We have to access the memory with user's permissions, so use a segment * selector with RPL 3. For writes to user space we have to additionally * check the PTE for write permission, because the 386 does not check * write permissions when we are executing with EPL 0. The 486 does check * this if the WP bit is set in CR0, so we can use a simpler version here. * * These routines set curpcb->onfault for the time they execute. When a * protection violation occurs inside the functions, the trap handler * returns to *curpcb->onfault instead of the function. */ ENTRY(copyout) /* copyout(from_kernel, to_user, len) */ movl _curpcb,%eax movl $copyout_fault,PCB_ONFAULT(%eax) pushl %esi pushl %edi pushl %ebx movl 16(%esp),%esi movl 20(%esp),%edi movl 24(%esp),%ebx orl %ebx,%ebx /* anything to do? */ jz done_copyout /* * Check explicitly for non-user addresses. If 486 write protection * is being used, this check is essential because we are in kernel * mode so the h/w does not provide any protection against writing * kernel addresses. * * Otherwise, it saves having to load and restore %es to get the * usual segment-based protection (the destination segment for movs * is always %es). The other explicit checks for user-writablility * are not quite sufficient. They fail for the user area because * we mapped the user area read/write to avoid having an #ifdef in * vm_machdep.c. They fail for user PTEs and/or PTDs! (107 * addresses including 0xff800000 and 0xfc000000). I'm not sure if * this can be fixed. Marking the PTEs supervisor mode and the * PDE's user mode would almost work, but there may be a problem * with the self-referential PDE. */ movl %edi,%eax addl %ebx,%eax jc copyout_fault /* * XXX STOP USING VM_MAXUSER_ADDRESS. * It is an end address, not a max, so every time it is used correctly it * looks like there is an off by one error, and of course it caused an off * by one error in several places. */ cmpl $VM_MAXUSER_ADDRESS,%eax ja copyout_fault #if defined(I386_CPU) #if defined(I486_CPU) || defined(I586_CPU) cmpl $CPUCLASS_386,_cpu_class jne 3f #endif /* * We have to check each PTE for user write permission. * The checking may cause a page fault, so it is important to set * up everything for return via copyout_fault before here. */ /* compute number of pages */ movl %edi,%ecx andl $NBPG-1,%ecx addl %ebx,%ecx decl %ecx shrl $IDXSHIFT+2,%ecx incl %ecx /* compute PTE offset for start address */ movl %edi,%edx shrl $IDXSHIFT,%edx andb $0xfc,%dl 1: /* check PTE for each page */ movb _PTmap(%edx),%al andb $0x07,%al /* Pages must be VALID + USERACC + WRITABLE */ cmpb $0x07,%al je 2f /* simulate a trap */ pushl %edx pushl %ecx shll $IDXSHIFT,%edx pushl %edx call _trapwrite /* trapwrite(addr) */ popl %edx popl %ecx popl %edx orl %eax,%eax /* if not ok, return EFAULT */ jnz copyout_fault 2: addl $4,%edx decl %ecx jnz 1b /* check next page */ #endif /* I386_CPU */ /* bcopy(%esi, %edi, %ebx) */ 3: movl %ebx,%ecx shrl $2,%ecx cld rep movsl movb %bl,%cl andb $3,%cl rep movsb done_copyout: popl %ebx popl %edi popl %esi xorl %eax,%eax movl _curpcb,%edx movl %eax,PCB_ONFAULT(%edx) ret ALIGN_TEXT copyout_fault: popl %ebx popl %edi popl %esi movl _curpcb,%edx movl $0,PCB_ONFAULT(%edx) movl $EFAULT,%eax ret /* copyin(from_user, to_kernel, len) */ ENTRY(copyin) movl _curpcb,%eax movl $copyin_fault,PCB_ONFAULT(%eax) pushl %esi pushl %edi movl 12(%esp),%esi /* caddr_t from */ movl 16(%esp),%edi /* caddr_t to */ movl 20(%esp),%ecx /* size_t len */ /* * make sure address is valid */ movl %esi,%edx addl %ecx,%edx jc copyin_fault cmpl $VM_MAXUSER_ADDRESS,%edx ja copyin_fault movb %cl,%al shrl $2,%ecx /* copy longword-wise */ cld rep movsl movb %al,%cl andb $3,%cl /* copy remaining bytes */ rep movsb popl %edi popl %esi xorl %eax,%eax movl _curpcb,%edx movl %eax,PCB_ONFAULT(%edx) ret ALIGN_TEXT copyin_fault: popl %edi popl %esi movl _curpcb,%edx movl $0,PCB_ONFAULT(%edx) movl $EFAULT,%eax ret /* * fu{byte,sword,word} : fetch a byte (sword, word) from user memory */ ALTENTRY(fuiword) ENTRY(fuword) movl _curpcb,%ecx movl $fusufault,PCB_ONFAULT(%ecx) movl 4(%esp),%edx /* from */ cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address is valid */ ja fusufault movl (%edx),%eax movl $0,PCB_ONFAULT(%ecx) ret /* * These two routines are called from the profiling code, potentially * at interrupt time. If they fail, that's okay, good things will * happen later. Fail all the time for now - until the trap code is * able to deal with this. */ ALTENTRY(suswintr) ENTRY(fuswintr) movl $-1,%eax ret ENTRY(fusword) movl _curpcb,%ecx movl $fusufault,PCB_ONFAULT(%ecx) movl 4(%esp),%edx cmpl $VM_MAXUSER_ADDRESS-2,%edx ja fusufault movzwl (%edx),%eax movl $0,PCB_ONFAULT(%ecx) ret ALTENTRY(fuibyte) ENTRY(fubyte) movl _curpcb,%ecx movl $fusufault,PCB_ONFAULT(%ecx) movl 4(%esp),%edx cmpl $VM_MAXUSER_ADDRESS-1,%edx ja fusufault movzbl (%edx),%eax movl $0,PCB_ONFAULT(%ecx) ret ALIGN_TEXT fusufault: movl _curpcb,%ecx xorl %eax,%eax movl %eax,PCB_ONFAULT(%ecx) decl %eax ret /* * su{byte,sword,word}: write a byte (word, longword) to user memory */ ALTENTRY(suiword) ENTRY(suword) movl _curpcb,%ecx movl $fusufault,PCB_ONFAULT(%ecx) movl 4(%esp),%edx #if defined(I386_CPU) #if defined(I486_CPU) || defined(I586_CPU) cmpl $CPUCLASS_386,_cpu_class jne 2f /* we only have to set the right segment selector */ #endif /* I486_CPU || I586_CPU */ /* XXX - page boundary crossing is still not handled */ movl %edx,%eax shrl $IDXSHIFT,%edx andb $0xfc,%dl movb _PTmap(%edx),%dl andb $0x7,%dl /* must be VALID + USERACC + WRITE */ cmpb $0x7,%dl je 1f /* simulate a trap */ pushl %eax call _trapwrite popl %edx /* remove junk parameter from stack */ movl _curpcb,%ecx /* restore trashed register */ orl %eax,%eax jnz fusufault 1: movl 4(%esp),%edx #endif 2: cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address validity */ ja fusufault movl 8(%esp),%eax movl %eax,(%edx) xorl %eax,%eax movl %eax,PCB_ONFAULT(%ecx) ret ENTRY(susword) movl _curpcb,%ecx movl $fusufault,PCB_ONFAULT(%ecx) movl 4(%esp),%edx #if defined(I386_CPU) #if defined(I486_CPU) || defined(I586_CPU) cmpl $CPUCLASS_386,_cpu_class jne 2f #endif /* I486_CPU || I586_CPU */ /* XXX - page boundary crossing is still not handled */ movl %edx,%eax shrl $IDXSHIFT,%edx andb $0xfc,%dl movb _PTmap(%edx),%dl andb $0x7,%dl /* must be VALID + USERACC + WRITE */ cmpb $0x7,%dl je 1f /* simulate a trap */ pushl %eax call _trapwrite popl %edx /* remove junk parameter from stack */ movl _curpcb,%ecx /* restore trashed register */ orl %eax,%eax jnz fusufault 1: movl 4(%esp),%edx #endif 2: cmpl $VM_MAXUSER_ADDRESS-2,%edx /* verify address validity */ ja fusufault movw 8(%esp),%ax movw %ax,(%edx) xorl %eax,%eax movl %eax,PCB_ONFAULT(%ecx) ret ALTENTRY(suibyte) ENTRY(subyte) movl _curpcb,%ecx movl $fusufault,PCB_ONFAULT(%ecx) movl 4(%esp),%edx #if defined(I386_CPU) #if defined(I486_CPU) || defined(I586_CPU) cmpl $CPUCLASS_386,_cpu_class jne 2f #endif /* I486_CPU || I586_CPU */ movl %edx,%eax shrl $IDXSHIFT,%edx andb $0xfc,%dl movb _PTmap(%edx),%dl andb $0x7,%dl /* must be VALID + USERACC + WRITE */ cmpb $0x7,%dl je 1f /* simulate a trap */ pushl %eax call _trapwrite popl %edx /* remove junk parameter from stack */ movl _curpcb,%ecx /* restore trashed register */ orl %eax,%eax jnz fusufault 1: movl 4(%esp),%edx #endif 2: cmpl $VM_MAXUSER_ADDRESS-1,%edx /* verify address validity */ ja fusufault movb 8(%esp),%al movb %al,(%edx) xorl %eax,%eax movl %eax,PCB_ONFAULT(%ecx) ret /* * copyoutstr(from, to, maxlen, int *lencopied) * copy a string from from to to, stop when a 0 character is reached. * return ENAMETOOLONG if string is longer than maxlen, and * EFAULT on protection violations. If lencopied is non-zero, * return the actual length in *lencopied. */ ENTRY(copyoutstr) pushl %esi pushl %edi movl _curpcb,%ecx movl $cpystrflt,PCB_ONFAULT(%ecx) /* XXX rename copyoutstr_fault */ movl 12(%esp),%esi /* %esi = from */ movl 16(%esp),%edi /* %edi = to */ movl 20(%esp),%edx /* %edx = maxlen */ cld #if defined(I386_CPU) #if defined(I486_CPU) || defined(I586_CPU) cmpl $CPUCLASS_386,_cpu_class jne 5f #endif /* I486_CPU || I586_CPU */ 1: /* * It suffices to check that the first byte is in user space, because * we look at a page at a time and the end address is on a page * boundary. */ cmpl $VM_MAXUSER_ADDRESS-1,%edi ja cpystrflt movl %edi,%eax shrl $IDXSHIFT,%eax andb $0xfc,%al movb _PTmap(%eax),%al andb $7,%al cmpb $7,%al je 2f /* simulate trap */ pushl %edx pushl %edi call _trapwrite cld popl %edi popl %edx orl %eax,%eax jnz cpystrflt 2: /* copy up to end of this page */ movl %edi,%eax andl $NBPG-1,%eax movl $NBPG,%ecx subl %eax,%ecx /* ecx = NBPG - (src % NBPG) */ cmpl %ecx,%edx jae 3f movl %edx,%ecx /* ecx = min(ecx, edx) */ 3: orl %ecx,%ecx jz 4f decl %ecx decl %edx lodsb stosb orb %al,%al jnz 3b /* Success -- 0 byte reached */ decl %edx xorl %eax,%eax jmp 6f 4: /* next page */ orl %edx,%edx jnz 1b /* edx is zero -- return ENAMETOOLONG */ movl $ENAMETOOLONG,%eax jmp cpystrflt_x #endif /* I386_CPU */ #if defined(I486_CPU) || defined(I586_CPU) 5: incl %edx 1: decl %edx jz 2f /* * XXX - would be faster to rewrite this function to use * strlen() and copyout(). */ cmpl $VM_MAXUSER_ADDRESS-1,%edi ja cpystrflt lodsb stosb orb %al,%al jnz 1b /* Success -- 0 byte reached */ decl %edx xorl %eax,%eax jmp cpystrflt_x 2: /* edx is zero -- return ENAMETOOLONG */ movl $ENAMETOOLONG,%eax jmp cpystrflt_x #endif /* I486_CPU || I586_CPU */ /* * copyinstr(from, to, maxlen, int *lencopied) * copy a string from from to to, stop when a 0 character is reached. * return ENAMETOOLONG if string is longer than maxlen, and * EFAULT on protection violations. If lencopied is non-zero, * return the actual length in *lencopied. */ ENTRY(copyinstr) pushl %esi pushl %edi movl _curpcb,%ecx movl $cpystrflt,PCB_ONFAULT(%ecx) movl 12(%esp),%esi /* %esi = from */ movl 16(%esp),%edi /* %edi = to */ movl 20(%esp),%edx /* %edx = maxlen */ movl $VM_MAXUSER_ADDRESS,%eax /* make sure 'from' is within bounds */ subl %esi,%eax jbe cpystrflt /* restrict maxlen to <= VM_MAXUSER_ADDRESS-from */ cmpl %edx,%eax jae 1f movl %eax,%edx movl %eax,20(%esp) 1: incl %edx cld 2: decl %edx jz 3f lodsb stosb orb %al,%al jnz 2b /* Success -- 0 byte reached */ decl %edx xorl %eax,%eax jmp cpystrflt_x 3: /* edx is zero - return ENAMETOOLONG or EFAULT */ cmpl $VM_MAXUSER_ADDRESS,%esi jae cpystrflt 4: movl $ENAMETOOLONG,%eax jmp cpystrflt_x cpystrflt: movl $EFAULT,%eax cpystrflt_x: /* set *lencopied and return %eax */ movl _curpcb,%ecx movl $0,PCB_ONFAULT(%ecx) movl 20(%esp),%ecx subl %edx,%ecx movl 24(%esp),%edx testl %edx,%edx jz 1f movl %ecx,(%edx) 1: popl %edi popl %esi ret /* * copystr(from, to, maxlen, int *lencopied) */ ENTRY(copystr) pushl %esi pushl %edi movl 12(%esp),%esi /* %esi = from */ movl 16(%esp),%edi /* %edi = to */ movl 20(%esp),%edx /* %edx = maxlen */ incl %edx cld 1: decl %edx jz 4f lodsb stosb orb %al,%al jnz 1b /* Success -- 0 byte reached */ decl %edx xorl %eax,%eax jmp 6f 4: /* edx is zero -- return ENAMETOOLONG */ movl $ENAMETOOLONG,%eax 6: /* set *lencopied and return %eax */ movl 20(%esp),%ecx subl %edx,%ecx movl 24(%esp),%edx orl %edx,%edx jz 7f movl %ecx,(%edx) 7: popl %edi popl %esi ret /* * Miscellaneous kernel support functions */ ENTRY(ffs) bsfl 4(%esp),%eax jz 1f incl %eax ret 1: xorl %eax,%eax ret ENTRY(bcmp) pushl %edi pushl %esi movl 12(%esp),%edi movl 16(%esp),%esi movl 20(%esp),%edx xorl %eax,%eax movl %edx,%ecx shrl $2,%ecx cld /* compare forwards */ repe cmpsl jne 1f movl %edx,%ecx andl $3,%ecx repe cmpsb je 2f 1: incl %eax 2: popl %esi popl %edi ret /* * Handling of special 386 registers and descriptor tables etc */ /* void lgdt(struct region_descriptor *rdp); */ ENTRY(lgdt) /* reload the descriptor table */ movl 4(%esp),%eax lgdt (%eax) /* flush the prefetch q */ jmp 1f nop 1: /* reload "stale" selectors */ movl $KDSEL,%eax movl %ax,%ds movl %ax,%es movl %ax,%ss /* reload code selector by turning return into intersegmental return */ movl (%esp),%eax pushl %eax # movl $KCSEL,4(%esp) movl $8,4(%esp) lret /* * void lidt(struct region_descriptor *rdp); */ ENTRY(lidt) movl 4(%esp),%eax lidt (%eax) ret /* * void lldt(u_short sel) */ ENTRY(lldt) lldt 4(%esp) ret /* * void ltr(u_short sel) */ ENTRY(ltr) ltr 4(%esp) ret /* ssdtosd(*ssdp,*sdp) */ ENTRY(ssdtosd) pushl %ebx movl 8(%esp),%ecx movl 8(%ecx),%ebx shll $16,%ebx movl (%ecx),%edx roll $16,%edx movb %dh,%bl movb %dl,%bh rorl $8,%ebx movl 4(%ecx),%eax movw %ax,%dx andl $0xf0000,%eax orl %eax,%ebx movl 12(%esp),%ecx movl %edx,(%ecx) movl %ebx,4(%ecx) popl %ebx ret /* load_cr0(cr0) */ ENTRY(load_cr0) movl 4(%esp),%eax movl %eax,%cr0 ret /* rcr0() */ ENTRY(rcr0) movl %cr0,%eax ret /* rcr3() */ ENTRY(rcr3) movl %cr3,%eax ret /* void load_cr3(caddr_t cr3) */ ENTRY(load_cr3) movl 4(%esp),%eax - orl $I386_CR3PAT,%eax movl %eax,%cr3 ret /*****************************************************************************/ /* setjump, longjump */ /*****************************************************************************/ ENTRY(setjmp) movl 4(%esp),%eax movl %ebx,(%eax) /* save ebx */ movl %esp,4(%eax) /* save esp */ movl %ebp,8(%eax) /* save ebp */ movl %esi,12(%eax) /* save esi */ movl %edi,16(%eax) /* save edi */ movl (%esp),%edx /* get rta */ movl %edx,20(%eax) /* save eip */ xorl %eax,%eax /* return(0); */ ret ENTRY(longjmp) movl 4(%esp),%eax movl (%eax),%ebx /* restore ebx */ movl 4(%eax),%esp /* restore esp */ movl 8(%eax),%ebp /* restore ebp */ movl 12(%eax),%esi /* restore esi */ movl 16(%eax),%edi /* restore edi */ movl 20(%eax),%edx /* get rta */ movl %edx,(%esp) /* put in return frame */ xorl %eax,%eax /* return(1); */ incl %eax ret Index: head/sys/i386/include/vmparam.h =================================================================== --- head/sys/i386/include/vmparam.h (revision 2688) +++ head/sys/i386/include/vmparam.h (revision 2689) @@ -1,238 +1,134 @@ /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * Copyright (c) 1994 John S. Dyson * All rights reserved. * * This code is derived from software contributed to Berkeley by * William Jolitz. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: @(#)vmparam.h 5.9 (Berkeley) 5/12/91 - * $Id: vmparam.h,v 1.13 1994/05/25 08:57:22 rgrimes Exp $ + * $Id: vmparam.h,v 1.14 1994/09/01 03:16:40 davidg Exp $ */ #ifndef _MACHINE_VMPARAM_H_ #define _MACHINE_VMPARAM_H_ 1 /* * Machine dependent constants for 386. */ /* - * Virtual address space arrangement. On 386, both user and kernel - * share the address space, not unlike the vax. - * USRTEXT is the start of the user text/data space, while USRSTACK - * is the top (end) of the user stack. Immediately above the user stack - * resides the user structure, which is UPAGES long and contains the - * kernel stack. - * - * Immediately after the user structure is the page table map, and then - * kernal address space. - */ -#define USRTEXT 0UL -/* #define USRSTACK 0xFDBFE000UL */ -#define BTOPUSRSTACK (0xFDC00-(UPAGES)) /* btop(USRSTACK) */ -#define LOWPAGES 0UL -#define HIGHPAGES UPAGES - -/* * Virtual memory related constants, all in bytes */ #define MAXTSIZ (16UL*1024*1024) /* max text size */ #ifndef DFLDSIZ #define DFLDSIZ (64UL*1024*1024) /* initial data size limit */ #endif #ifndef MAXDSIZ #define MAXDSIZ (128UL*1024*1024) /* max data size */ #endif #ifndef DFLSSIZ #define DFLSSIZ (8UL*1024*1024) /* initial stack size limit */ #endif #ifndef MAXSSIZ #define MAXSSIZ (64UL*1024*1024) /* max stack size */ #endif #ifndef SGROWSIZ #define SGROWSIZ (128UL*1024) /* amount to grow stack */ #endif +#define USRTEXT (1*NBPG) /* base of user text XXX bogus */ + /* * Default sizes of swap allocation chunks (see dmap.h). * The actual values may be changed in vminit() based on MAXDSIZ. * With MAXDSIZ of 16Mb and NDMAP of 38, dmmax will be 1024. */ #define DMMIN 32 /* smallest swap allocation */ #define DMMAX 4096 /* largest potential swap allocation */ #define DMTEXT 1024 /* swap allocation for text */ /* * Sizes of the system and user portions of the system page table. */ #define SYSPTSIZE (2*NPTEPG) #define USRPTSIZE (2*NPTEPG) /* * Size of the Shared Memory Pages page table. */ #ifndef SHMMAXPGS #define SHMMAXPGS 512 /* XXX until we have more kmap space */ #endif /* * Size of User Raw I/O map */ #define USRIOSIZE 1024 /* - * The size of the clock loop. - */ -#define LOOPPAGES (maxfree - firstfree) - -/* * The time for a process to be blocked before being very swappable. * This is a number of seconds which the system takes as being a non-trivial * amount of real time. You probably shouldn't change this; * it is used in subtle ways (fractions and multiples of it are, that is, like * half of a ``long time'', almost a long time, etc.) * It is related to human patience and other factors which don't really * change over time. */ #define MAXSLP 20 /* - * A swapped in process is given a small amount of core without being bothered - * by the page replacement algorithm. Basically this says that if you are - * swapped in you deserve some resources. We protect the last SAFERSS - * pages against paging and will just swap you out rather than paging you. - * Note that each process has at least UPAGES+CLSIZE pages which are not - * paged anyways (this is currently 8+2=10 pages or 5k bytes), so this - * number just means a swapped in process is given around 25k bytes. - * Just for fun: current memory prices are 4600$ a megabyte on VAX (4/22/81), - * so we loan each swapped in process memory worth 100$, or just admit - * that we don't consider it worthwhile and swap it out to disk which costs - * $30/mb or about $0.75. - * { wfj 6/16/89: Retail AT memory expansion $800/megabyte, loan of $17 - * on disk costing $7/mb or $0.18 (in memory still 100:1 in cost!) } - */ -#define SAFERSS 8 /* nominal ``small'' resident set size - protected against replacement */ - -/* - * DISKRPM is used to estimate the number of paging i/o operations - * which one can expect from a single disk controller. - */ -#define DISKRPM 60 - -/* - * Klustering constants. Klustering is the gathering - * of pages together for pagein/pageout, while clustering - * is the treatment of hardware page size as though it were - * larger than it really is. - * - * KLMAX gives maximum cluster size in CLSIZE page (cluster-page) - * units. Note that KLMAX*CLSIZE must be <= DMMIN in dmap.h. - */ - -#define KLMAX (4/CLSIZE) -#define KLSEQL (2/CLSIZE) /* in klust if vadvise(VA_SEQL) */ -#define KLIN (4/CLSIZE) /* default data/stack in klust */ -#define KLTXT (4/CLSIZE) /* default text in klust */ -#define KLOUT (4/CLSIZE) - -/* - * KLSDIST is the advance or retard of the fifo reclaim for sequential - * processes data space. - */ -#define KLSDIST 3 /* klusters advance/retard for seq. fifo */ - -/* - * There are two clock hands, initially separated by HANDSPREAD bytes - * (but at most all of user memory). The amount of time to reclaim - * a page once the pageout process examines it increases with this - * distance and decreases as the scan rate rises. - */ -#define HANDSPREAD (2 * 1024 * 1024) - -/* - * The number of times per second to recompute the desired paging rate - * and poke the pagedaemon. - */ -#define RATETOSCHEDPAGING 4 - -/* - * Believed threshold (in megabytes) for which interleaved - * swapping area is desirable. - */ -#define LOTSOFMEM 2 - -#define mapin(pte, v, pfnum, prot) \ - {(*(int *)(pte) = ((pfnum)<p_addr) - -/* - * Flush MMU TLB - */ - -#ifndef I386_CR3PAT -#define I386_CR3PAT 0x0 -#endif #endif /* _MACHINE_VMPARAM_H_ */ Index: head/sys/ufs/mfs/mfs_vnops.c =================================================================== --- head/sys/ufs/mfs/mfs_vnops.c (revision 2688) +++ head/sys/ufs/mfs/mfs_vnops.c (revision 2689) @@ -1,435 +1,355 @@ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)mfs_vnops.c 8.3 (Berkeley) 9/21/93 - * $Id$ + * $Id: mfs_vnops.c,v 1.3 1994/08/02 07:54:44 davidg Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if !defined(hp300) && !defined(i386) && !defined(mips) && !defined(sparc) && !defined(luna68k) static int mfsmap_want; /* 1 => need kernel I/O resources */ struct map mfsmap[MFS_MAPSIZE]; extern char mfsiobuf[]; #endif /* * mfs vnode operations. */ int (**mfs_vnodeop_p)(); struct vnodeopv_entry_desc mfs_vnodeop_entries[] = { { &vop_default_desc, vn_default_error }, { &vop_lookup_desc, mfs_lookup }, /* lookup */ { &vop_create_desc, mfs_create }, /* create */ { &vop_mknod_desc, mfs_mknod }, /* mknod */ { &vop_open_desc, mfs_open }, /* open */ { &vop_close_desc, mfs_close }, /* close */ { &vop_access_desc, mfs_access }, /* access */ { &vop_getattr_desc, mfs_getattr }, /* getattr */ { &vop_setattr_desc, mfs_setattr }, /* setattr */ { &vop_read_desc, mfs_read }, /* read */ { &vop_write_desc, mfs_write }, /* write */ { &vop_ioctl_desc, mfs_ioctl }, /* ioctl */ { &vop_select_desc, mfs_select }, /* select */ { &vop_mmap_desc, mfs_mmap }, /* mmap */ { &vop_fsync_desc, spec_fsync }, /* fsync */ { &vop_seek_desc, mfs_seek }, /* seek */ { &vop_remove_desc, mfs_remove }, /* remove */ { &vop_link_desc, mfs_link }, /* link */ { &vop_rename_desc, mfs_rename }, /* rename */ { &vop_mkdir_desc, mfs_mkdir }, /* mkdir */ { &vop_rmdir_desc, mfs_rmdir }, /* rmdir */ { &vop_symlink_desc, mfs_symlink }, /* symlink */ { &vop_readdir_desc, mfs_readdir }, /* readdir */ { &vop_readlink_desc, mfs_readlink }, /* readlink */ { &vop_abortop_desc, mfs_abortop }, /* abortop */ { &vop_inactive_desc, mfs_inactive }, /* inactive */ { &vop_reclaim_desc, mfs_reclaim }, /* reclaim */ { &vop_lock_desc, mfs_lock }, /* lock */ { &vop_unlock_desc, mfs_unlock }, /* unlock */ { &vop_bmap_desc, mfs_bmap }, /* bmap */ { &vop_strategy_desc, mfs_strategy }, /* strategy */ { &vop_print_desc, mfs_print }, /* print */ { &vop_islocked_desc, mfs_islocked }, /* islocked */ { &vop_pathconf_desc, mfs_pathconf }, /* pathconf */ { &vop_advlock_desc, mfs_advlock }, /* advlock */ { &vop_blkatoff_desc, mfs_blkatoff }, /* blkatoff */ { &vop_valloc_desc, mfs_valloc }, /* valloc */ { &vop_vfree_desc, mfs_vfree }, /* vfree */ { &vop_truncate_desc, mfs_truncate }, /* truncate */ { &vop_update_desc, mfs_update }, /* update */ { &vop_bwrite_desc, mfs_bwrite }, /* bwrite */ { (struct vnodeop_desc*)NULL, (int(*)())NULL } }; struct vnodeopv_desc mfs_vnodeop_opv_desc = { &mfs_vnodeop_p, mfs_vnodeop_entries }; /* * Vnode Operations. * * Open called to allow memory filesystem to initialize and * validate before actual IO. Record our process identifier * so we can tell when we are doing I/O to ourself. */ /* ARGSUSED */ int mfs_open(ap) struct vop_open_args /* { struct vnode *a_vp; int a_mode; struct ucred *a_cred; struct proc *a_p; } */ *ap; { if (ap->a_vp->v_type != VBLK) { panic("mfs_ioctl not VBLK"); /* NOTREACHED */ } return (0); } /* * Ioctl operation. */ /* ARGSUSED */ int mfs_ioctl(ap) struct vop_ioctl_args /* { struct vnode *a_vp; int a_command; caddr_t a_data; int a_fflag; struct ucred *a_cred; struct proc *a_p; } */ *ap; { return (ENOTTY); } /* * Pass I/O requests to the memory filesystem process. */ int mfs_strategy(ap) struct vop_strategy_args /* { struct buf *a_bp; } */ *ap; { register struct buf *bp = ap->a_bp; register struct mfsnode *mfsp; struct vnode *vp; struct proc *p = curproc; /* XXX */ if (!vfinddev(bp->b_dev, VBLK, &vp) || vp->v_usecount == 0) panic("mfs_strategy: bad dev"); mfsp = VTOMFS(vp); /* check for mini-root access */ if (mfsp->mfs_pid == 0) { caddr_t base; base = mfsp->mfs_baseoff + (bp->b_blkno << DEV_BSHIFT); if (bp->b_flags & B_READ) bcopy(base, bp->b_data, bp->b_bcount); else bcopy(bp->b_data, base, bp->b_bcount); biodone(bp); } else if (mfsp->mfs_pid == p->p_pid) { mfs_doio(bp, mfsp->mfs_baseoff); } else { bp->b_actf = mfsp->mfs_buflist; mfsp->mfs_buflist = bp; wakeup((caddr_t)vp); } return (0); } -#if defined(vax) || defined(tahoe) /* * Memory file system I/O. * - * Essentially play ubasetup() and disk interrupt service routine by - * doing the copies to or from the memfs process. If doing physio - * (i.e. pagein), we must map the I/O through the kernel virtual - * address space. - */ -void -mfs_doio(bp, base) - register struct buf *bp; - caddr_t base; -{ - register struct pte *pte, *ppte; - register caddr_t vaddr; - int off, npf, npf2, reg; - caddr_t kernaddr, offset; - - /* - * For phys I/O, map the b_data into kernel virtual space using - * the Mfsiomap pte's. - */ - if ((bp->b_flags & B_PHYS) == 0) { - kernaddr = bp->b_data; - } else { - if (bp->b_flags & (B_PAGET | B_UAREA | B_DIRTY)) - panic("swap on memfs?"); - off = (int)bp->b_data & PGOFSET; - npf = btoc(bp->b_bcount + off); - /* - * Get some mapping page table entries - */ - while ((reg = rmalloc(mfsmap, (long)npf)) == 0) { - mfsmap_want++; - sleep((caddr_t)&mfsmap_want, PZERO-1); - } - reg--; - pte = vtopte(bp->b_proc, btop(bp->b_data)); - /* - * Do vmaccess() but with the Mfsiomap page table. - */ - ppte = &Mfsiomap[reg]; - vaddr = &mfsiobuf[reg * NBPG]; - kernaddr = vaddr + off; - for (npf2 = npf; npf2; npf2--) { - mapin(ppte, (u_int)vaddr, pte->pg_pfnum, - (int)(PG_V|PG_KW)); -#if defined(tahoe) - if ((bp->b_flags & B_READ) == 0) - mtpr(P1DC, vaddr); -#endif - ppte++; - pte++; - vaddr += NBPG; - } - } - offset = base + (bp->b_blkno << DEV_BSHIFT); - if (bp->b_flags & B_READ) - bp->b_error = copyin(offset, kernaddr, bp->b_bcount); - else - bp->b_error = copyout(kernaddr, offset, bp->b_bcount); - if (bp->b_error) - bp->b_flags |= B_ERROR; - /* - * Release pte's used by physical I/O. - */ - if (bp->b_flags & B_PHYS) { - rmfree(mfsmap, (long)npf, (long)++reg); - if (mfsmap_want) { - mfsmap_want = 0; - wakeup((caddr_t)&mfsmap_want); - } - } - biodone(bp); -} -#endif /* vax || tahoe */ - -#if defined(hp300) || defined(i386) || defined(mips) || defined(sparc) || defined(luna68k) -/* - * Memory file system I/O. - * * Trivial on the HP since buffer has already been mapping into KVA space. */ void mfs_doio(bp, base) register struct buf *bp; caddr_t base; { base += (bp->b_blkno << DEV_BSHIFT); if (bp->b_flags & B_READ) bp->b_error = copyin(base, bp->b_data, bp->b_bcount); else bp->b_error = copyout(bp->b_data, base, bp->b_bcount); if (bp->b_error) bp->b_flags |= B_ERROR; biodone(bp); } -#endif /* * This is a noop, simply returning what one has been given. */ int mfs_bmap(ap) struct vop_bmap_args /* { struct vnode *a_vp; daddr_t a_bn; struct vnode **a_vpp; daddr_t *a_bnp; int *a_runp; } */ *ap; { if (ap->a_vpp != NULL) *ap->a_vpp = ap->a_vp; if (ap->a_bnp != NULL) *ap->a_bnp = ap->a_bn; return (0); } /* * Memory filesystem close routine */ /* ARGSUSED */ int mfs_close(ap) struct vop_close_args /* { struct vnode *a_vp; int a_fflag; struct ucred *a_cred; struct proc *a_p; } */ *ap; { register struct vnode *vp = ap->a_vp; register struct mfsnode *mfsp = VTOMFS(vp); register struct buf *bp; int error; /* * Finish any pending I/O requests. */ while (bp = mfsp->mfs_buflist) { mfsp->mfs_buflist = bp->b_actf; mfs_doio(bp, mfsp->mfs_baseoff); wakeup((caddr_t)bp); } /* * On last close of a memory filesystem * we must invalidate any in core blocks, so that * we can, free up its vnode. */ if (error = vinvalbuf(vp, 1, ap->a_cred, ap->a_p, 0, 0)) return (error); /* * There should be no way to have any more uses of this * vnode, so if we find any other uses, it is a panic. */ if (vp->v_usecount > 1) printf("mfs_close: ref count %d > 1\n", vp->v_usecount); if (vp->v_usecount > 1 || mfsp->mfs_buflist) panic("mfs_close"); /* * Send a request to the filesystem server to exit. */ mfsp->mfs_buflist = (struct buf *)(-1); wakeup((caddr_t)vp); return (0); } /* * Memory filesystem inactive routine */ /* ARGSUSED */ int mfs_inactive(ap) struct vop_inactive_args /* { struct vnode *a_vp; } */ *ap; { register struct mfsnode *mfsp = VTOMFS(ap->a_vp); if (mfsp->mfs_buflist && mfsp->mfs_buflist != (struct buf *)(-1)) panic("mfs_inactive: not inactive (mfs_buflist %x)", mfsp->mfs_buflist); return (0); } /* * Reclaim a memory filesystem devvp so that it can be reused. */ int mfs_reclaim(ap) struct vop_reclaim_args /* { struct vnode *a_vp; } */ *ap; { FREE(ap->a_vp->v_data, M_MFSNODE); ap->a_vp->v_data = NULL; return (0); } /* * Print out the contents of an mfsnode. */ int mfs_print(ap) struct vop_print_args /* { struct vnode *a_vp; } */ *ap; { register struct mfsnode *mfsp = VTOMFS(ap->a_vp); printf("tag VT_MFS, pid %d, base %d, size %d\n", mfsp->mfs_pid, mfsp->mfs_baseoff, mfsp->mfs_size); return (0); } /* * Block device bad operation */ int mfs_badop() { panic("mfs_badop called\n"); /* NOTREACHED */ } /* * Memory based filesystem initialization. */ int mfs_init() { #if !defined(hp300) && !defined(i386) && !defined(mips) && !defined(sparc) && !defined(luna68k) rminit(mfsmap, (long)MFS_MAPREG, (long)1, "mfs mapreg", MFS_MAPSIZE); #endif return (0); } Index: head/sys/vm/vm_meter.c =================================================================== --- head/sys/vm/vm_meter.c (revision 2688) +++ head/sys/vm/vm_meter.c (revision 2689) @@ -1,226 +1,225 @@ /* * Copyright (c) 1982, 1986, 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)vm_meter.c 8.4 (Berkeley) 1/4/94 - * $Id$ + * $Id: vm_meter.c,v 1.3 1994/08/02 07:55:27 davidg Exp $ */ #include #include #include #include #include #include struct loadavg averunnable; /* load average, of runnable procs */ int maxslp = MAXSLP; -int saferss = SAFERSS; void vmmeter() { if (time.tv_sec % 5 == 0) loadav(&averunnable); if (proc0.p_slptime > maxslp/2) wakeup((caddr_t)&proc0); } /* * Constants for averages over 1, 5, and 15 minutes * when sampling at 5 second intervals. */ fixpt_t cexp[3] = { 0.9200444146293232 * FSCALE, /* exp(-1/12) */ 0.9834714538216174 * FSCALE, /* exp(-1/60) */ 0.9944598480048967 * FSCALE, /* exp(-1/180) */ }; /* * Compute a tenex style load average of a quantity on * 1, 5 and 15 minute intervals. */ void loadav(avg) register struct loadavg *avg; { register int i, nrun; register struct proc *p; for (nrun = 0, p = (struct proc *)allproc; p != NULL; p = p->p_next) { switch (p->p_stat) { case SSLEEP: if (p->p_priority > PZERO || p->p_slptime != 0) continue; /* fall through */ case SRUN: case SIDL: nrun++; } } for (i = 0; i < 3; i++) avg->ldavg[i] = (cexp[i] * avg->ldavg[i] + nrun * FSCALE * (FSCALE - cexp[i])) >> FSHIFT; } /* * Attributes associated with virtual memory. */ int vm_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) int *name; u_int namelen; void *oldp; size_t *oldlenp; void *newp; size_t newlen; struct proc *p; { struct vmtotal vmtotals; /* all sysctl names at this level are terminal */ if (namelen != 1) return (ENOTDIR); /* overloaded */ switch (name[0]) { case VM_LOADAVG: averunnable.fscale = FSCALE; return (sysctl_rdstruct(oldp, oldlenp, newp, &averunnable, sizeof(averunnable))); case VM_METER: vmtotal(&vmtotals); return (sysctl_rdstruct(oldp, oldlenp, newp, &vmtotals, sizeof(vmtotals))); default: return (EOPNOTSUPP); } /* NOTREACHED */ } /* * Calculate the current state of the system. * Done on demand from getkerninfo(). */ void vmtotal(totalp) register struct vmtotal *totalp; { register struct proc *p; register vm_map_entry_t entry; register vm_object_t object; register vm_map_t map; int paging; bzero(totalp, sizeof *totalp); /* * Mark all objects as inactive. */ simple_lock(&vm_object_list_lock); for (object = vm_object_list.tqh_first; object != NULL; object = object->object_list.tqe_next) object->flags &= ~OBJ_ACTIVE; simple_unlock(&vm_object_list_lock); /* * Calculate process statistics. */ for (p = (struct proc *)allproc; p != NULL; p = p->p_next) { if (p->p_flag & P_SYSTEM) continue; switch (p->p_stat) { case 0: continue; case SSLEEP: case SSTOP: if (p->p_flag & P_INMEM) { if (p->p_priority <= PZERO) totalp->t_dw++; else if (p->p_slptime < maxslp) totalp->t_sl++; } else if (p->p_slptime < maxslp) totalp->t_sw++; if (p->p_slptime >= maxslp) continue; break; case SRUN: case SIDL: if (p->p_flag & P_INMEM) totalp->t_rq++; else totalp->t_sw++; if (p->p_stat == SIDL) continue; break; } /* * Note active objects. */ paging = 0; for (map = &p->p_vmspace->vm_map, entry = map->header.next; entry != &map->header; entry = entry->next) { if (entry->is_a_map || entry->is_sub_map || entry->object.vm_object == NULL) continue; entry->object.vm_object->flags |= OBJ_ACTIVE; paging |= entry->object.vm_object->paging_in_progress; } if (paging) totalp->t_pw++; } /* * Calculate object memory usage statistics. */ simple_lock(&vm_object_list_lock); for (object = vm_object_list.tqh_first; object != NULL; object = object->object_list.tqe_next) { totalp->t_vm += num_pages(object->size); totalp->t_rm += object->resident_page_count; if (object->flags & OBJ_ACTIVE) { totalp->t_avm += num_pages(object->size); totalp->t_arm += object->resident_page_count; } if (object->ref_count > 1) { /* shared object */ totalp->t_vmshr += num_pages(object->size); totalp->t_rmshr += object->resident_page_count; if (object->flags & OBJ_ACTIVE) { totalp->t_avmshr += num_pages(object->size); totalp->t_armshr += object->resident_page_count; } } } totalp->t_free = cnt.v_free_count; }