Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/arch/i386/i386/locore.S,v rcsdiff: /ftp/cvs/cvsroot/src/sys/arch/i386/i386/locore.S,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.1.2.3 retrieving revision 1.36.2.1 diff -u -p -r1.1.2.3 -r1.36.2.1 --- src/sys/arch/i386/i386/locore.S 2002/12/11 16:00:50 1.1.2.3 +++ src/sys/arch/i386/i386/locore.S 2006/02/18 15:38:36 1.36.2.1 @@ -1,7 +1,7 @@ -/* $NetBSD: locore.S,v 1.1.2.3 2002/12/11 16:00:50 thorpej Exp $ */ +/* $NetBSD: locore.S,v 1.36.2.1 2006/02/18 15:38:36 yamt Exp $ */ /*- - * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc. + * Copyright (c) 1998, 2000, 2004 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation @@ -51,11 +51,7 @@ * 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 + * 3. 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. * @@ -74,29 +70,28 @@ * @(#)locore.s 7.3 (Berkeley) 5/13/91 */ +#include "opt_compat_netbsd.h" +#include "opt_compat_oldboot.h" #include "opt_cputype.h" #include "opt_ddb.h" #include "opt_ipkdb.h" -#include "opt_vm86.h" -#include "opt_user_ldt.h" -#include "opt_dummy_nops.h" -#include "opt_compat_oldboot.h" -#include "opt_multiprocessor.h" #include "opt_lockdebug.h" +#include "opt_multiprocessor.h" #include "opt_realmem.h" +#include "opt_user_ldt.h" +#include "opt_vm86.h" #include "npx.h" #include "assym.h" #include "apm.h" #include "lapic.h" #include "ioapic.h" +#include "ksyms.h" #include #include #include -#include -#include #include #include #include @@ -106,6 +101,8 @@ #include #endif +#include + /* LINTSTUB: include */ /* LINTSTUB: include */ /* LINTSTUB: include */ @@ -113,12 +110,12 @@ #include #if defined(MULTIPROCESSOR) - + #define SET_CURLWP(lwp,cpu) \ movl CPUVAR(SELF),cpu ; \ movl lwp,CPUVAR(CURLWP) ; \ movl cpu,L_CPU(lwp) - + #else #define SET_CURLWP(lwp,tcpu) movl lwp,CPUVAR(CURLWP) @@ -126,9 +123,8 @@ #endif -#define GET_CURPCB(reg) movl CPUVAR(CURPCB),reg #define SET_CURPCB(reg) movl reg,CPUVAR(CURPCB) - + #define CLEAR_RESCHED(reg) movl reg,CPUVAR(RESCHED) /* XXX temporary kluge; these should not be here */ @@ -155,27 +151,6 @@ #ifdef MULTIPROCESSOR #include #endif - -/* - * PTmap is recursive pagemap at top of virtual address space. - * Within PTmap, the page directory can be found (third indirection). - * - * XXX 4 == sizeof pde - */ - .set _C_LABEL(PTmap),(PDSLOT_PTE << PDSHIFT) - .set _C_LABEL(PTD),(_C_LABEL(PTmap) + PDSLOT_PTE * NBPG) - .set _C_LABEL(PTDpde),(_C_LABEL(PTD) + PDSLOT_PTE * 4) - -/* - * APTmap, APTD is the alternate recursive pagemap. - * It's used when modifying another process's page tables. - * - * XXX 4 == sizeof pde - */ - .set _C_LABEL(APTmap),(PDSLOT_APTE << PDSHIFT) - .set _C_LABEL(APTD),(_C_LABEL(APTmap) + PDSLOT_APTE * NBPG) - .set _C_LABEL(APTDpde),(_C_LABEL(PTD) + PDSLOT_APTE * 4) - /* * Initialization @@ -183,52 +158,49 @@ .data .globl _C_LABEL(cpu) - .globl _C_LABEL(cpu_feature) .globl _C_LABEL(esym),_C_LABEL(boothowto) .globl _C_LABEL(bootinfo),_C_LABEL(atdevbase) #ifdef COMPAT_OLDBOOT .globl _C_LABEL(bootdev) #endif - .globl _C_LABEL(proc0paddr),_C_LABEL(PTDpaddr) + .globl _C_LABEL(proc0paddr),_C_LABEL(PDPpaddr) .globl _C_LABEL(biosbasemem),_C_LABEL(biosextmem) .globl _C_LABEL(gdt) #ifdef I586_CPU .globl _C_LABEL(idt) #endif - .globl _C_LABEL(lapic_tpr) - + .globl _C_LABEL(lapic_tpr) + #if NLAPIC > 0 #ifdef __ELF__ - .align NBPG + .align PAGE_SIZE #else .align 12 #endif .globl _C_LABEL(local_apic), _C_LABEL(lapic_id) _C_LABEL(local_apic): .space LAPIC_ID -_C_LABEL(lapic_id): +_C_LABEL(lapic_id): .long 0x00000000 .space LAPIC_TPRI-(LAPIC_ID+4) -_C_LABEL(lapic_tpr): +_C_LABEL(lapic_tpr): .space LAPIC_PPRI-LAPIC_TPRI -_C_LABEL(lapic_ppr): +_C_LABEL(lapic_ppr): .space LAPIC_ISR-LAPIC_PPRI _C_LABEL(lapic_isr): - .space NBPG-LAPIC_ISR + .space PAGE_SIZE-LAPIC_ISR #else -_C_LABEL(lapic_tpr): +_C_LABEL(lapic_tpr): .long 0 #endif - + _C_LABEL(cpu): .long 0 # are we 386, 386sx, or 486, # or Pentium, or.. -_C_LABEL(cpu_feature): .long 0 # feature flags from 'cpuid' - # instruction _C_LABEL(esym): .long 0 # ptr to end of syms _C_LABEL(atdevbase): .long 0 # location of start of iomem in virtual _C_LABEL(proc0paddr): .long 0 -_C_LABEL(PTDpaddr): .long 0 # paddr of PTD, for libkvm +_C_LABEL(PDPpaddr): .long 0 # paddr of PDP, for libkvm #ifndef REALBASEMEM _C_LABEL(biosbasemem): .long 0 # base memory reported by BIOS #else @@ -239,7 +211,7 @@ _C_LABEL(biosextmem): .long 0 # extended #else _C_LABEL(biosextmem): .long REALEXTMEM #endif - + .space 512 tmpstk: @@ -254,6 +226,40 @@ tmpstk: .globl start start: movw $0x1234,0x472 # warm boot +#if defined(MULTIBOOT) + jmp 1f + + .align 4 + .globl Multiboot_Header +_C_LABEL(Multiboot_Header): +#define MULTIBOOT_HEADER_FLAGS (MULTIBOOT_HEADER_WANT_MEMORY | \ + MULTIBOOT_HEADER_HAS_ADDR) + .long MULTIBOOT_HEADER_MAGIC + .long MULTIBOOT_HEADER_FLAGS + .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) + .long RELOC(Multiboot_Header) + .long RELOC(start) + .long RELOC(_edata) + .long RELOC(_end) + MULTIBOOT_SYMTAB_SPACE + .long RELOC(start) + +1: + /* Check if we are being executed by a Multiboot-compliant boot + * loader. */ + cmpl $MULTIBOOT_INFO_MAGIC,%eax + jne 1f + + /* Indeed, a multiboot-compliat boot loader executed us. We copy + * the received Multiboot information structure into kernel's data + * space to process it later -- after we are relocated. It will + * be safer to run complex C code than doing it at this point. */ + pushl %ebx # Address of Multiboot information + call _C_LABEL(multiboot_pre_reloc) + addl $4,%esp + jmp 3f +#endif + +1: /* * Load parameters from stack * (howto, [bootdev], bootinfo, esym, basemem, extmem). @@ -314,6 +320,7 @@ start: movw $0x1234,0x472 # warm boot movl %eax,RELOC(biosbasemem) 1: +3: /* First, reset the PSL. */ pushl $PSL_MBO popfl @@ -503,17 +510,17 @@ try586: /* Use the `cpuid' instruction. /* * Virtual address space of kernel: * - * text | data | bss | [syms] | page dir | proc0 kstack + * text | data | bss | [syms] | page dir | proc0 kstack * 0 1 2 3 */ -#define PROC0PDIR ((0) * NBPG) -#define PROC0STACK ((1) * NBPG) -#define SYSMAP ((1+UPAGES) * NBPG) -#define TABLESIZE ((1+UPAGES) * NBPG) /* + nkpde * NBPG */ +#define PROC0PDIR ((0) * PAGE_SIZE) +#define PROC0STACK ((1) * PAGE_SIZE) +#define SYSMAP ((1+UPAGES) * PAGE_SIZE) +#define TABLESIZE ((1+UPAGES) * PAGE_SIZE) /* + nkpde * PAGE_SIZE */ /* Find end of kernel image. */ movl $RELOC(end),%edi -#if defined(DDB) && !defined(SYMTAB_SPACE) +#if (NKSYMS || defined(DDB) || defined(LKM)) && !defined(SYMTAB_SPACE) /* Save the symbols (if loaded). */ movl RELOC(esym),%eax testl %eax,%eax @@ -530,17 +537,24 @@ try586: /* Use the `cpuid' instruction. /* * Calculate the size of the kernel page table directory, and - * how many entries it will have. + * how many entries it will have. Adjust nkpde to the actual + * kernel size automatically. Account for the bootstrap tables, + * round up, and add an extra 4MB. */ + leal TABLESIZE+NBPD+PDOFSET(%edi),%eax + shrl $PDSHIFT,%eax movl RELOC(nkpde),%ecx # get nkpde - cmpl $NKPTP_MIN,%ecx # larger than min? + cmpl %ecx,%eax + jb 1f + movl %eax,%ecx +1: cmpl $NKPTP_MIN,%ecx # larger than min? jge 1f movl $NKPTP_MIN,%ecx # set at min jmp 2f 1: cmpl $NKPTP_MAX,%ecx # larger than max? jle 2f movl $NKPTP_MAX,%ecx -2: +2: movl %ecx,RELOC(nkpde) /* Clear memory for bootstrap tables. */ shll $PGSHIFT,%ecx @@ -561,7 +575,7 @@ try586: /* Use the `cpuid' instruction. */ #define fillkpt \ 1: movl %eax,(%ebx) ; \ - addl $NBPG,%eax ; /* increment physical address */ \ + addl $PAGE_SIZE,%eax ; /* increment physical address */ \ addl $4,%ebx ; /* next pte */ \ loop 1b ; @@ -571,7 +585,7 @@ try586: /* Use the `cpuid' instruction. /* Calculate end of text segment, rounded to a page. */ leal (RELOC(etext)+PGOFSET),%edx andl $~PGOFSET,%edx - + /* Skip over the first 1MB. */ movl $_RELOC(KERNTEXTOFF),%eax movl %eax,%ecx @@ -619,8 +633,8 @@ try586: /* Use the `cpuid' instruction. leal (PROC0PDIR+PG_V|PG_KW)(%esi),%eax # pte for ptd movl %eax,(PROC0PDIR+PDSLOT_PTE*4)(%esi) # recursive PD slot - /* Save phys. addr of PTD, for libkvm. */ - movl %esi,RELOC(PTDpaddr) + /* Save phys. addr of PDP, for libkvm. */ + movl %esi,RELOC(PDPpaddr) /* Load base of page directory and enable mapping. */ movl %esi,%eax # phys address of ptd in proc 0 @@ -656,11 +670,19 @@ begin: movl %esi,PCB_CR3(%eax) # pcb->pcb_cr3 xorl %ebp,%ebp # mark end of frames +#if defined(MULTIBOOT) + /* It is now safe to parse the Multiboot information structure + * we saved before from C code. Note that we cannot delay its + * parsing any more because initgdt (called below) needs to make + * use of this information. */ + call _C_LABEL(multiboot_post_reloc) +#endif + subl $NGDT*8, %esp # space for temporary gdt pushl %esp call _C_LABEL(initgdt) addl $4,%esp - + movl _C_LABEL(nkpde),%eax shll $PGSHIFT,%eax addl $TABLESIZE,%eax @@ -707,11 +729,12 @@ NENTRY(proc_trampoline) pushl %ebx call *%esi addl $4,%esp + DO_DEFERRED_SWITCH(%eax) INTRFASTEXIT /* NOTREACHED */ /*****************************************************************************/ - +#ifdef COMPAT_16 /* * Signal trampoline; copied to top of user stack. */ @@ -724,858 +747,14 @@ NENTRY(sigcode) leal 12(%esp),%eax # get pointer to sigcontext movl %eax,4(%esp) # put it in the argument slot # fake return address already there - movl $SYS___sigreturn14,%eax + movl $SYS_compat_16___sigreturn14,%eax int $0x80 # enter kernel with args on stack movl $SYS_exit,%eax int $0x80 # exit if sigreturn fails .globl _C_LABEL(esigcode) _C_LABEL(esigcode): - -/*****************************************************************************/ - -/* - * The following primitives are used to fill and copy regions of memory. - */ - -/* - * XXX No section 9 man page for fillw. - * fillw seems to be very sparsely used (only in pccons it seems.) - * One wonders if it couldn't be done without. - * -- Perry Metzger, May 7, 2001 - */ -/* - * void fillw(short pattern, void *addr, size_t len); - * Write len copies of pattern at addr. - */ -/* LINTSTUB: Func: void fillw(short pattern, void *addr, size_t len) */ -ENTRY(fillw) - pushl %edi - movl 8(%esp),%eax - movl 12(%esp),%edi - movw %ax,%cx - rorl $16,%eax - movw %cx,%ax - cld - movl 16(%esp),%ecx - shrl %ecx # do longwords - rep - stosl - movl 16(%esp),%ecx - andl $1,%ecx # do remainder - rep - stosw - popl %edi - ret - -/* - * int kcopy(const void *from, void *to, size_t len); - * Copy len bytes, abort on fault. - */ -/* LINTSTUB: Func: int kcopy(const void *from, void *to, size_t len) */ -ENTRY(kcopy) - pushl %esi - pushl %edi - GET_CURPCB(%eax) # load curpcb into eax and set on-fault - pushl PCB_ONFAULT(%eax) - movl $_C_LABEL(copy_fault), PCB_ONFAULT(%eax) - - movl 16(%esp),%esi - movl 20(%esp),%edi - movl 24(%esp),%ecx - movl %edi,%eax - subl %esi,%eax - cmpl %ecx,%eax # overlapping? - jb 1f - cld # nope, copy forward - shrl $2,%ecx # copy by 32-bit words - rep - movsl - movl 24(%esp),%ecx - andl $3,%ecx # any bytes left? - rep - movsb - - GET_CURPCB(%edx) # XXX save curpcb? - popl PCB_ONFAULT(%edx) - popl %edi - popl %esi - xorl %eax,%eax - ret - - ALIGN_TEXT -1: addl %ecx,%edi # copy backward - addl %ecx,%esi - std - andl $3,%ecx # any fractional bytes? - decl %edi - decl %esi - rep - movsb - movl 24(%esp),%ecx # copy remainder by 32-bit words - shrl $2,%ecx - subl $3,%esi - subl $3,%edi - rep - movsl - cld - - GET_CURPCB(%edx) - popl PCB_ONFAULT(%edx) - popl %edi - popl %esi - xorl %eax,%eax - ret - -/*****************************************************************************/ - -/* - * The following primitives are used to copy data in and out of the user's - * address space. - */ - -/* - * Default to the lowest-common-denominator. We will improve it - * later. - */ -#if defined(I386_CPU) -#define DEFAULT_COPYOUT _C_LABEL(i386_copyout) -#define DEFAULT_COPYIN _C_LABEL(i386_copyin) -#elif defined(I486_CPU) -#define DEFAULT_COPYOUT _C_LABEL(i486_copyout) -#define DEFAULT_COPYIN _C_LABEL(i386_copyin) -#elif defined(I586_CPU) -#define DEFAULT_COPYOUT _C_LABEL(i486_copyout) /* XXX */ -#define DEFAULT_COPYIN _C_LABEL(i386_copyin) /* XXX */ -#elif defined(I686_CPU) -#define DEFAULT_COPYOUT _C_LABEL(i486_copyout) /* XXX */ -#define DEFAULT_COPYIN _C_LABEL(i386_copyin) /* XXX */ -#endif - - .data - - .globl _C_LABEL(copyout_func) -_C_LABEL(copyout_func): - .long DEFAULT_COPYOUT - - .globl _C_LABEL(copyin_func) -_C_LABEL(copyin_func): - .long DEFAULT_COPYIN - - .text - -/* - * int copyout(const void *from, void *to, size_t len); - * Copy len bytes into the user's address space. - * see copyout(9) - */ -/* LINTSTUB: Func: int copyout(const void *kaddr, void *uaddr, size_t len) */ -ENTRY(copyout) - jmp *_C_LABEL(copyout_func) - -#if defined(I386_CPU) -/* LINTSTUB: Func: int i386_copyout(const void *kaddr, void *uaddr, size_t len) */ -ENTRY(i386_copyout) - pushl %esi - pushl %edi - pushl $0 - - movl 16(%esp),%esi - movl 20(%esp),%edi - movl 24(%esp),%eax - - /* - * We check that the end of the destination buffer is not past the end - * of the user's address space. If it's not, then we only need to - * check that each page is writable. The 486 will do this for us; the - * 386 will not. (We assume that pages in user space that are not - * writable by the user are not writable by the kernel either.) - */ - movl %edi,%edx - addl %eax,%edx - jc _C_LABEL(copy_efault) - cmpl $VM_MAXUSER_ADDRESS,%edx - ja _C_LABEL(copy_efault) - - testl %eax,%eax # anything to do? - jz 3f - - /* - * We have to check each PTE for (write) permission, since the CPU - * doesn't do it for us. - */ - - /* Compute number of pages. */ - movl %edi,%ecx - andl $PGOFSET,%ecx - addl %eax,%ecx - decl %ecx - shrl $PGSHIFT,%ecx - - /* Compute PTE offset for start address. */ - shrl $PGSHIFT,%edi - - GET_CURPCB(%edx) - movl $2f,PCB_ONFAULT(%edx) - -1: /* Check PTE for each page. */ - testb $PG_RW,_C_LABEL(PTmap)(,%edi,4) - jz 2f - -4: incl %edi - decl %ecx - jns 1b - - movl 20(%esp),%edi - movl 24(%esp),%eax - jmp 3f - -2: /* Simulate a trap. */ - pushl %ecx - movl %edi,%eax - shll $PGSHIFT,%eax - pushl %eax - call _C_LABEL(trapwrite) # trapwrite(addr) - addl $4,%esp # pop argument - popl %ecx - testl %eax,%eax # if not ok, return EFAULT - jz 4b - jmp _C_LABEL(copy_efault) - -3: GET_CURPCB(%edx) - movl $_C_LABEL(copy_fault),PCB_ONFAULT(%edx) - - /* bcopy(%esi, %edi, %eax); */ - cld - movl %eax,%ecx - shrl $2,%ecx - rep - movsl - movl %eax,%ecx - andl $3,%ecx - rep - movsb - - popl PCB_ONFAULT(%edx) - popl %edi - popl %esi - xorl %eax,%eax - ret -#endif /* I386_CPU */ - -#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) -/* LINTSTUB: Func: int i486_copyout(const void *kaddr, void *uaddr, size_t len) */ -ENTRY(i486_copyout) - pushl %esi - pushl %edi - pushl $0 - - movl 16(%esp),%esi - movl 20(%esp),%edi - movl 24(%esp),%eax - - /* - * We check that the end of the destination buffer is not past the end - * of the user's address space. - */ - movl %edi,%edx - addl %eax,%edx - jc _C_LABEL(copy_efault) - cmpl $VM_MAXUSER_ADDRESS,%edx - ja _C_LABEL(copy_efault) - - GET_CURPCB(%edx) - movl $_C_LABEL(copy_fault),PCB_ONFAULT(%edx) - - /* bcopy(%esi, %edi, %eax); */ - cld - movl %eax,%ecx - shrl $2,%ecx - rep - movsl - movl %eax,%ecx - andl $3,%ecx - rep - movsb - - popl PCB_ONFAULT(%edx) - popl %edi - popl %esi - xorl %eax,%eax - ret -#endif /* I486_CPU || I586_CPU || I686_CPU */ - -/* - * int copyin(const void *from, void *to, size_t len); - * Copy len bytes from the user's address space. - * see copyin(9) - */ -/* LINTSTUB: Func: int copyin(const void *uaddr, void *kaddr, size_t len) */ -ENTRY(copyin) - jmp *_C_LABEL(copyin_func) - -#if defined(I386_CPU) || defined(I486_CPU) || defined(I586_CPU) || \ - defined(I686_CPU) -/* LINTSTUB: Func: int i386_copyin(const void *uaddr, void *kaddr, size_t len) */ -ENTRY(i386_copyin) - pushl %esi - pushl %edi - GET_CURPCB(%eax) - pushl $0 - movl $_C_LABEL(copy_fault),PCB_ONFAULT(%eax) - - movl 16(%esp),%esi - movl 20(%esp),%edi - movl 24(%esp),%eax - - /* - * We check that the end of the destination buffer is not past the end - * of the user's address space. If it's not, then we only need to - * check that each page is readable, and the CPU will do that for us. - */ - movl %esi,%edx - addl %eax,%edx - jc _C_LABEL(copy_efault) - cmpl $VM_MAXUSER_ADDRESS,%edx - ja _C_LABEL(copy_efault) - - /* bcopy(%esi, %edi, %eax); */ - cld - movl %eax,%ecx - shrl $2,%ecx - rep - movsl - movl %eax,%ecx - andl $3,%ecx - rep - movsb - - GET_CURPCB(%edx) - popl PCB_ONFAULT(%edx) - popl %edi - popl %esi - xorl %eax,%eax - ret -#endif /* I386_CPU || I486_CPU || I586_CPU || I686_CPU */ - -/* LINTSTUB: Ignore */ -NENTRY(copy_efault) - movl $EFAULT,%eax - -/* LINTSTUB: Ignore */ -NENTRY(copy_fault) - GET_CURPCB(%edx) - popl PCB_ONFAULT(%edx) - popl %edi - popl %esi - ret - -/* - * int copyoutstr(const void *from, void *to, size_t maxlen, size_t *lencopied); - * Copy a NUL-terminated string, at most maxlen characters long, into the - * user's address space. Return the number of characters copied (including the - * NUL) in *lencopied. If the string is too long, return ENAMETOOLONG; else - * return 0 or EFAULT. - * see copyoutstr(9) - */ -/* LINTSTUB: Func: int copyoutstr(const void *kaddr, void *uaddr, size_t len, size_t *done) */ -ENTRY(copyoutstr) - pushl %esi - pushl %edi - - movl 12(%esp),%esi # esi = from - movl 16(%esp),%edi # edi = to - movl 20(%esp),%edx # edx = maxlen - -#if defined(I386_CPU) -#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) - cmpl $CPUCLASS_386,_C_LABEL(cpu_class) - jne 5f -#endif /* I486_CPU || I586_CPU || I686_CPU */ - - /* Compute number of bytes in first page. */ - movl %edi,%eax - andl $PGOFSET,%eax - movl $NBPG,%ecx - subl %eax,%ecx # ecx = NBPG - (src % NBPG) - - GET_CURPCB(%eax) - movl $6f,PCB_ONFAULT(%eax) - -1: /* - * Once per page, check that we are still within the bounds of user - * space, and check for a write fault. - */ - cmpl $VM_MAXUSER_ADDRESS,%edi - jae _C_LABEL(copystr_efault) - - /* Compute PTE offset. */ - movl %edi,%eax - shrl $PGSHIFT,%eax # calculate pte address - - testb $PG_RW,_C_LABEL(PTmap)(,%eax,4) - jnz 2f - -6: /* Simulate a trap. */ - pushl %edx - pushl %edi - call _C_LABEL(trapwrite) # trapwrite(addr) - addl $4,%esp # clear argument from stack - popl %edx - testl %eax,%eax - jnz _C_LABEL(copystr_efault) - -2: /* Copy up to end of this page. */ - subl %ecx,%edx # predecrement total count - jnc 3f - addl %edx,%ecx # ecx += (edx - ecx) = edx - xorl %edx,%edx - -3: decl %ecx - js 4f - lodsb - stosb - testb %al,%al - jnz 3b - - /* Success -- 0 byte reached. */ - addl %ecx,%edx # add back residual for this page - xorl %eax,%eax - jmp copystr_return - -4: /* Go to next page, if any. */ - movl $NBPG,%ecx - testl %edx,%edx - jnz 1b - - /* edx is zero -- return ENAMETOOLONG. */ - movl $ENAMETOOLONG,%eax - jmp copystr_return -#endif /* I386_CPU */ - -#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) -5: GET_CURPCB(%eax) - movl $_C_LABEL(copystr_fault),PCB_ONFAULT(%eax) - /* - * Get min(%edx, VM_MAXUSER_ADDRESS-%edi). - */ - movl $VM_MAXUSER_ADDRESS,%eax - subl %edi,%eax - cmpl %edx,%eax - jae 1f - movl %eax,%edx - movl %eax,20(%esp) - -1: incl %edx - cld - -1: decl %edx - jz 2f - lodsb - stosb - testb %al,%al - jnz 1b - - /* Success -- 0 byte reached. */ - decl %edx - xorl %eax,%eax - jmp copystr_return - -2: /* edx is zero -- return EFAULT or ENAMETOOLONG. */ - cmpl $VM_MAXUSER_ADDRESS,%edi - jae _C_LABEL(copystr_efault) - movl $ENAMETOOLONG,%eax - jmp copystr_return -#endif /* I486_CPU || I586_CPU || I686_CPU */ - -/* - * int copyinstr(const void *from, void *to, size_t maxlen, size_t *lencopied); - * Copy a NUL-terminated string, at most maxlen characters long, from the - * user's address space. Return the number of characters copied (including the - * NUL) in *lencopied. If the string is too long, return ENAMETOOLONG; else - * return 0 or EFAULT. - * see copyinstr(9) - */ -/* LINTSTUB: Func: int copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done) */ -ENTRY(copyinstr) - pushl %esi - pushl %edi - GET_CURPCB(%ecx) - movl $_C_LABEL(copystr_fault),PCB_ONFAULT(%ecx) - - movl 12(%esp),%esi # %esi = from - movl 16(%esp),%edi # %edi = to - movl 20(%esp),%edx # %edx = maxlen - - /* - * Get min(%edx, VM_MAXUSER_ADDRESS-%esi). - */ - movl $VM_MAXUSER_ADDRESS,%eax - subl %esi,%eax - cmpl %edx,%eax - jae 1f - movl %eax,%edx - movl %eax,20(%esp) - -1: incl %edx - cld - -1: decl %edx - jz 2f - lodsb - stosb - testb %al,%al - jnz 1b - - /* Success -- 0 byte reached. */ - decl %edx - xorl %eax,%eax - jmp copystr_return - -2: /* edx is zero -- return EFAULT or ENAMETOOLONG. */ - cmpl $VM_MAXUSER_ADDRESS,%esi - jae _C_LABEL(copystr_efault) - movl $ENAMETOOLONG,%eax - jmp copystr_return - -/* LINTSTUB: Ignore */ -NENTRY(copystr_efault) - movl $EFAULT,%eax - -/* LINTSTUB: Ignore */ -NENTRY(copystr_fault) -copystr_return: - /* Set *lencopied and return %eax. */ - GET_CURPCB(%ecx) - movl $0,PCB_ONFAULT(%ecx) - movl 20(%esp),%ecx - subl %edx,%ecx - movl 24(%esp),%edx - testl %edx,%edx - jz 8f - movl %ecx,(%edx) - -8: popl %edi - popl %esi - ret - -/* - * int copystr(const void *from, void *to, size_t maxlen, size_t *lencopied); - * Copy a NUL-terminated string, at most maxlen characters long. Return the - * number of characters copied (including the NUL) in *lencopied. If the - * string is too long, return ENAMETOOLONG; else return 0. - * see copystr(9) - */ -/* LINTSTUB: Func: int copystr(const void *kfaddr, void *kdaddr, size_t len, size_t *done) */ -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 - testb %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 - testl %edx,%edx - jz 7f - movl %ecx,(%edx) - -7: popl %edi - popl %esi - ret - -/* - * long fuword(const void *uaddr); - * Fetch an int from the user's address space. - * see fuword(9) - */ -/* LINTSTUB: Func: long fuword(const void *base) */ -ENTRY(fuword) - movl 4(%esp),%edx - cmpl $VM_MAXUSER_ADDRESS-4,%edx - ja _C_LABEL(fusuaddrfault) - GET_CURPCB(%ecx) - movl $_C_LABEL(fusufault),PCB_ONFAULT(%ecx) - movl (%edx),%eax - movl $0,PCB_ONFAULT(%ecx) - ret - -/* - * int fusword(const void *uaddr); - * Fetch a short from the user's address space. - * see fusword(9) - */ -/* LINTSTUB: Func: int fusword(const void *base) */ -ENTRY(fusword) - movl 4(%esp),%edx - cmpl $VM_MAXUSER_ADDRESS-2,%edx - ja _C_LABEL(fusuaddrfault) - GET_CURPCB(%ecx) - movl $_C_LABEL(fusufault),PCB_ONFAULT(%ecx) - movzwl (%edx),%eax - movl $0,PCB_ONFAULT(%ecx) - ret - -/* - * int fuswintr(const void *uaddr); - * Fetch a short from the user's address space. Can be called during an - * interrupt. - * see fuswintr(9) - */ -/* LINTSTUB: Func: int fuswintr(const void *base) */ -ENTRY(fuswintr) - movl 4(%esp),%edx - cmpl $VM_MAXUSER_ADDRESS-2,%edx - ja _C_LABEL(fusuaddrfault) - movl CPUVAR(CURLWP),%ecx - movl L_ADDR(%ecx),%ecx - movl $_C_LABEL(fusubail),PCB_ONFAULT(%ecx) - movzwl (%edx),%eax - movl $0,PCB_ONFAULT(%ecx) - ret - -/* - * int fubyte(const void *uaddr); - * Fetch a byte from the user's address space. - * see fubyte(9) - */ -/* LINTSTUB: Func: int fubyte(const void *base) */ -ENTRY(fubyte) - movl 4(%esp),%edx - cmpl $VM_MAXUSER_ADDRESS-1,%edx - ja _C_LABEL(fusuaddrfault) - GET_CURPCB(%ecx) - movl $_C_LABEL(fusufault),PCB_ONFAULT(%ecx) - movzbl (%edx),%eax - movl $0,PCB_ONFAULT(%ecx) - ret - -/* - * Handle faults from [fs]u*(). Clean up and return -1. - */ -/* LINTSTUB: Ignore */ -NENTRY(fusufault) - movl $0,PCB_ONFAULT(%ecx) - movl $-1,%eax - ret - -/* - * Handle faults from [fs]u*(). Clean up and return -1. This differs from - * fusufault() in that trap() will recognize it and return immediately rather - * than trying to page fault. - */ -/* LINTSTUB: Ignore */ -NENTRY(fusubail) - movl $0,PCB_ONFAULT(%ecx) - movl $-1,%eax - ret - -/* - * Handle earlier faults from [fs]u*(), due to our of range addresses. - */ -/* LINTSTUB: Ignore */ -NENTRY(fusuaddrfault) - movl $-1,%eax - ret - -/* - * int suword(void *uaddr, long x); - * Store an int in the user's address space. - * see suword(9) - */ -/* LINTSTUB: Func: int suword(void *base, long c) */ -ENTRY(suword) - movl 4(%esp),%edx - cmpl $VM_MAXUSER_ADDRESS-4,%edx - ja _C_LABEL(fusuaddrfault) - -#if defined(I386_CPU) -#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) - cmpl $CPUCLASS_386,_C_LABEL(cpu_class) - jne 2f -#endif /* I486_CPU || I586_CPU || I686_CPU */ - - GET_CURPCB(%eax) - movl $3f,PCB_ONFAULT(%eax) - - movl %edx,%eax - shrl $PGSHIFT,%eax # calculate pte address - testb $PG_RW,_C_LABEL(PTmap)(,%eax,4) - jnz 1f - -3: /* Simulate a trap. */ - pushl %edx - pushl %edx - call _C_LABEL(trapwrite) # trapwrite(addr) - addl $4,%esp # clear parameter from the stack - popl %edx - GET_CURPCB(%ecx) - testl %eax,%eax - jnz _C_LABEL(fusufault) - -1: /* XXX also need to check the following 3 bytes for validity! */ -#endif - -2: GET_CURPCB(%ecx) - movl $_C_LABEL(fusufault),PCB_ONFAULT(%ecx) - - movl 8(%esp),%eax - movl %eax,(%edx) - xorl %eax,%eax - movl %eax,PCB_ONFAULT(%ecx) - ret - -/* - * int susword(void *uaddr, short x); - * Store a short in the user's address space. - * see susword(9) - */ -/* LINTSTUB: Func: int susword(void *base, short c) */ -ENTRY(susword) - movl 4(%esp),%edx - cmpl $VM_MAXUSER_ADDRESS-2,%edx - ja _C_LABEL(fusuaddrfault) - -#if defined(I386_CPU) -#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) - cmpl $CPUCLASS_386,_C_LABEL(cpu_class) - jne 2f -#endif /* I486_CPU || I586_CPU || I686_CPU */ - - GET_CURPCB(%eax) - movl $3f,PCB_ONFAULT(%eax) - - movl %edx,%eax - shrl $PGSHIFT,%eax # calculate pte address - testb $PG_RW,_C_LABEL(PTmap)(,%eax,4) - jnz 1f - -3: /* Simulate a trap. */ - pushl %edx - pushl %edx - call _C_LABEL(trapwrite) # trapwrite(addr) - addl $4,%esp # clear parameter from the stack - popl %edx - GET_CURPCB(%ecx) - testl %eax,%eax - jnz _C_LABEL(fusufault) - -1: /* XXX also need to check the following byte for validity! */ -#endif - -2: GET_CURPCB(%ecx) - movl $_C_LABEL(fusufault),PCB_ONFAULT(%ecx) - - movl 8(%esp),%eax - movw %ax,(%edx) - xorl %eax,%eax - movl %eax,PCB_ONFAULT(%ecx) - ret - -/* - * int suswintr(void *uaddr, short x); - * Store a short in the user's address space. Can be called during an - * interrupt. - * see suswintr(9) - */ -/* LINTSTUB: Func: int suswintr(void *base, short c) */ -ENTRY(suswintr) - movl 4(%esp),%edx - cmpl $VM_MAXUSER_ADDRESS-2,%edx - ja _C_LABEL(fusuaddrfault) - movl CPUVAR(CURLWP),%ecx - movl L_ADDR(%ecx),%ecx - movl $_C_LABEL(fusubail),PCB_ONFAULT(%ecx) - -#if defined(I386_CPU) -#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) - cmpl $CPUCLASS_386,_C_LABEL(cpu_class) - jne 2f -#endif /* I486_CPU || I586_CPU || I686_CPU */ - - movl %edx,%eax - shrl $PGSHIFT,%eax # calculate pte address - testb $PG_RW,_C_LABEL(PTmap)(,%eax,4) - jnz 1f - - /* Simulate a trap. */ - jmp _C_LABEL(fusubail) - -1: /* XXX also need to check the following byte for validity! */ -#endif - -2: movl 8(%esp),%eax - movw %ax,(%edx) - xorl %eax,%eax - movl %eax,PCB_ONFAULT(%ecx) - ret - -/* - * int subyte(void *uaddr, char x); - * Store a byte in the user's address space. - * see subyte(9) - */ -/* LINTSTUB: Func: int subyte(void *base, int c) */ -ENTRY(subyte) - movl 4(%esp),%edx - cmpl $VM_MAXUSER_ADDRESS-1,%edx - ja _C_LABEL(fusuaddrfault) - -#if defined(I386_CPU) -#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) - cmpl $CPUCLASS_386,_C_LABEL(cpu_class) - jne 2f -#endif /* I486_CPU || I586_CPU || I686_CPU */ - - GET_CURPCB(%eax) - movl $3f,PCB_ONFAULT(%eax) - - movl %edx,%eax - shrl $PGSHIFT,%eax # calculate pte address - testb $PG_RW,_C_LABEL(PTmap)(,%eax,4) - jnz 1f - -3: /* Simulate a trap. */ - pushl %edx - pushl %edx - call _C_LABEL(trapwrite) # trapwrite(addr) - addl $4,%esp # clear parameter from the stack - popl %edx - GET_CURPCB(%ecx) - testl %eax,%eax - jnz _C_LABEL(fusufault) - -1: #endif -2: GET_CURPCB(%ecx) - movl $_C_LABEL(fusufault),PCB_ONFAULT(%ecx) - - movb 8(%esp),%al - movb %al,(%edx) - xorl %eax,%eax - movl %eax,PCB_ONFAULT(%ecx) - ret - /*****************************************************************************/ /* @@ -1647,84 +826,9 @@ ENTRY(longjmp) /*****************************************************************************/ -/* - * The following primitives manipulate the run queues. - * _whichqs tells which of the 32 queues _qs - * have processes in them. Setrq puts processes into queues, Remrq - * removes them from queues. The running process is on no queue, - * other processes are on a queue related to p->p_pri, divided by 4 - * actually to shrink the 0-127 range of priorities into the 32 available - * queues. - */ .globl _C_LABEL(sched_whichqs),_C_LABEL(sched_qs) .globl _C_LABEL(uvmexp),_C_LABEL(panic) -/* - * void setrunqueue(struct lwp *p); - * Insert a process on the appropriate queue. Should be called at splclock(). - * See setrunqueue(9) for more details. - */ -/* LINTSTUB: Func: void setrunqueue(struct lwp *p) */ -NENTRY(setrunqueue) - movl 4(%esp),%eax -#ifdef DIAGNOSTIC - cmpl $0,L_BACK(%eax) # should not be on q already - jne 1f - cmpl $0,L_WCHAN(%eax) - jne 1f - cmpb $SRUN,L_STAT(%eax) - jne 1f -#endif /* DIAGNOSTIC */ - movzbl L_PRIORITY(%eax),%edx - shrl $2,%edx - btsl %edx,_C_LABEL(sched_whichqs) # set q full bit - leal _C_LABEL(sched_qs)(,%edx,8),%edx # locate q hdr - movl L_BACK(%edx),%ecx - movl %edx,L_FORW(%eax) # link process on tail of q - movl %eax,L_BACK(%edx) - movl %eax,L_FORW(%ecx) - movl %ecx,L_BACK(%eax) - ret -#ifdef DIAGNOSTIC -1: pushl $2f - call _C_LABEL(panic) - /* NOTREACHED */ -2: .asciz "setrunqueue" -#endif /* DIAGNOSTIC */ - -/* - * void remrunqueue(struct lwp *p); - * Remove a process from its queue. Should be called at splclock(). - * See remrunqueue(9) for more details. - */ -/* LINTSTUB: Func: void remrunqueue(struct lwp *p) */ -NENTRY(remrunqueue) - movl 4(%esp),%ecx - movzbl L_PRIORITY(%ecx),%eax -#ifdef DIAGNOSTIC - shrl $2,%eax - btl %eax,_C_LABEL(sched_whichqs) - jnc 1f -#endif /* DIAGNOSTIC */ - movl L_BACK(%ecx),%edx # unlink process - movl $0,L_BACK(%ecx) # zap reverse link to indicate off list - movl L_FORW(%ecx),%ecx - movl %ecx,L_FORW(%edx) - movl %edx,L_BACK(%ecx) - cmpl %ecx,%edx # q still has something? - jne 2f -#ifndef DIAGNOSTIC - shrl $2,%eax -#endif - btrl %eax,_C_LABEL(sched_whichqs) # no; clear bit -2: ret -#ifdef DIAGNOSTIC -1: pushl $3f - call _C_LABEL(panic) - /* NOTREACHED */ -3: .asciz "remrunqueue" -#endif /* DIAGNOSTIC */ - #ifdef DIAGNOSTIC NENTRY(switch_error) pushl $1f @@ -1738,9 +842,9 @@ NENTRY(switch_error) * Find a runnable process and switch to it. Wait if necessary. If the new * process is the same as the old one, we short-circuit the context save and * restore. - * + * * Note that the stack frame layout is known to "struct switchframe" - * in and to the code in cpu_fork() which initializes + * in and to the code in cpu_fork() which initializes * it for a new lwp. */ ENTRY(cpu_switch) @@ -1751,14 +855,14 @@ ENTRY(cpu_switch) #ifdef DEBUG cmpl $IPL_SCHED,CPUVAR(ILEVEL) jae 1f - pushl 2f + pushl $2f call _C_LABEL(panic) /* NOTREACHED */ -2: .asciz "not splhigh() in cpu_switch!" -1: +2: .asciz "not splsched() in cpu_switch!" +1: #endif /* DEBUG */ - - movl CPUVAR(CURLWP),%esi + + movl 16(%esp),%esi # current /* * Clear curlwp so that we don't accumulate system time while idle. @@ -1775,7 +879,7 @@ ENTRY(cpu_switch) * %eax - queue head, scratch, then zero * %ebx - queue number * %ecx - cached value of whichqs - * %edx - next process in queue + * %edx - next lwp in queue * %esi - old lwp * %edi - new lwp */ @@ -1796,7 +900,7 @@ ENTRY(cpu_switch) */ pushl %esi - call _C_LABEL(pmap_deactivate) # pmap_deactivate(oldproc) + call _C_LABEL(pmap_deactivate2) # pmap_deactivate(oldproc) addl $4,%esp movl L_ADDR(%esi),%esi @@ -1823,12 +927,9 @@ ENTRY(cpu_switch) movl PCB_ESP(%edi),%esp movl PCB_EBP(%edi),%ebp - - /* Switch address space. */ - movl PCB_CR3(%edi),%ecx - movl %ecx,%cr3 - /* Switch TSS. Reset "task busy" flag before loading. */ + movl %cr3,%eax + movl %eax,PCB_CR3(%edi) #ifdef MULTIPROCESSOR movl CPUVAR(GDT),%eax #else @@ -1848,8 +949,8 @@ ENTRY(cpu_switch) xorl %esi,%esi sti -idle_unlock: -#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) +idle_unlock: +#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) call _C_LABEL(sched_unlock_idle) #endif /* Interrupts are okay again. */ @@ -1857,7 +958,7 @@ idle_unlock: call _C_LABEL(Xspllower) # process pending interrupts addl $4,%esp jmp idle_start -idle_zero: +idle_zero: sti call _C_LABEL(uvm_pageidlezero) cli @@ -1871,23 +972,24 @@ idle_loop: sti hlt NENTRY(mpidle) -idle_start: +idle_start: cli cmpl $0,_C_LABEL(sched_whichqs) jz idle_loop -idle_exit: +idle_exit: movl $IPL_HIGH,CPUVAR(ILEVEL) # splhigh -#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) + sti +#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) call _C_LABEL(sched_lock_idle) #endif movl _C_LABEL(sched_whichqs),%ecx bsfl %ecx,%ebx jz idle_unlock -switch_dequeue: - /* +switch_dequeue: + /* * we're running at splhigh(), but it's otherwise okay to take - * interrupts here. + * interrupts here. */ sti leal _C_LABEL(sched_qs)(,%ebx,8),%eax # select q @@ -1927,7 +1029,7 @@ switch_resume: SET_CURLWP(%edi,%ecx) /* Skip context switch if same lwp. */ - movl $1, %eax + xorl %ebx,%ebx cmpl %edi,%esi je switch_return @@ -1945,7 +1047,7 @@ switch_resume: */ pushl %esi - call _C_LABEL(pmap_deactivate) # pmap_deactivate(oldproc) + call _C_LABEL(pmap_deactivate2) # pmap_deactivate(oldproc) addl $4,%esp movl L_ADDR(%esi),%esi @@ -1978,15 +1080,17 @@ switch_exited: jnz switch_restored #endif + /* Switch TSS. Reset "task busy" flag before loading. */ + movl %cr3,%eax + movl %eax,PCB_CR3(%esi) /* XXX should be done by pmap_activate? */ #ifdef MULTIPROCESSOR movl CPUVAR(GDT),%eax -#else +#else /* Load TSS info. */ movl _C_LABEL(gdt),%eax #endif movl L_MD_TSS_SEL(%edi),%edx - /* Switch TSS. Reset "task busy" flag before loading. */ andl $~0x0200,4(%eax,%edx, 1) ltr %dx @@ -2000,16 +1104,16 @@ switch_restored: /* Restore cr0 (including FPU state). */ movl PCB_CR0(%esi),%ecx #ifdef MULTIPROCESSOR - /* - * If our floating point registers are on a different cpu, + /* + * If our floating point registers are on a different CPU, * clear CR0_TS so we'll trap rather than reuse bogus state. */ movl PCB_FPCPU(%esi),%ebx cmpl CPUVAR(SELF),%ebx jz 1f orl $CR0_TS,%ecx -1: -#endif +1: +#endif movl %ecx,%cr0 /* Record new pcb. */ @@ -2020,53 +1124,50 @@ switch_restored: /* * Check for restartable atomic sequences (RAS) - * XXX %edi reloads are not necessary here as %edi is callee-saved! */ movl CPUVAR(CURLWP),%edi movl L_PROC(%edi),%esi - cmpl $0,P_NRAS(%esi) - je 1f - movl L_MD_REGS(%edi),%edx - movl TF_EIP(%edx),%eax - pushl %eax - pushl %esi - call _C_LABEL(ras_lookup) - addl $8,%esp - cmpl $-1,%eax - je 1f - movl CPUVAR(CURLWP),%edi - movl L_MD_REGS(%edi),%edx - movl %eax,TF_EIP(%edx) + cmpl $0,P_RASLIST(%esi) + jne 2f 1: - xor %eax,%eax + movl $1,%ebx switch_return: -#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) +#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) call _C_LABEL(sched_unlock_idle) #endif + cmpl $0,CPUVAR(IPENDING) + jz 3f pushl $IPL_NONE # spl0() call _C_LABEL(Xspllower) # process pending interrupts addl $4,%esp +3: movl $IPL_HIGH,CPUVAR(ILEVEL) # splhigh() - + + movl %ebx,%eax + popl %edi popl %esi popl %ebx ret -#ifdef DIAGNOSTIC -NENTRY(preempt_error) - pushl $1f - call _C_LABEL(panic) - /* NOTREACHED */ -1: .asciz "cpu_preempt" -#endif /* DIAGNOSTIC */ +2: # check RAS list + movl L_MD_REGS(%edi),%ebx + movl TF_EIP(%ebx),%eax + pushl %eax + pushl %esi + call _C_LABEL(ras_lookup) + addl $8,%esp + cmpl $-1,%eax + je 1b + movl %eax,TF_EIP(%ebx) + jmp 1b /* - * void cpu_preempt(struct lwp *current, struct lwp *next) - * Switch to the specified nexxt LWP. + * void cpu_switchto(struct lwp *current, struct lwp *next) + * Switch to the specified next LWP. */ -ENTRY(cpu_preempt) +ENTRY(cpu_switchto) pushl %ebx pushl %esi pushl %edi @@ -2077,11 +1178,11 @@ ENTRY(cpu_preempt) pushl $2f call _C_LABEL(panic) /* NOTREACHED */ -2: .asciz "not splsched() in cpu_preempt!" +2: .asciz "not splsched() in cpu_switchto!" 1: #endif /* DEBUG */ - movl CPUVAR(CURLWP),%esi + movl 16(%esp),%esi # current movl 20(%esp),%edi # next /* @@ -2090,52 +1191,32 @@ ENTRY(cpu_preempt) * the correct queue if it happens to get called from the spllower() * below and changes the priority. (See corresponding comment in * usrret()). + * + * XXX Is this necessary? We know we won't go idle. */ movl $0,CPUVAR(CURLWP) -preempt_dequeue: /* * We're running at splhigh(), but it's otherwise okay to take * interrupts here. */ sti - movzbl L_PRIORITY(%edi),%eax -#ifdef DIAGNOSTIC - shrl $2,%eax - btl %eax,_C_LABEL(sched_whichqs) - jnc _C_LABEL(preempt_error) -#endif /* DIAGNOSTIC */ - movl L_BACK(%edi),%edx # unlink process - movl $0,L_BACK(%edi) # zap reverse link to indicate off list - movl L_FORW(%edi),%ecx - movl %ecx,L_FORW(%edx) - movl %edx,L_BACK(%ecx) - cmpl %ecx,%edx # q still has something? - jne 3f -#ifndef DIAGNOSTIC - shrl $2,%eax -#endif - btrl %eax,_C_LABEL(sched_whichqs) # no; clear bit - -3: /* Jump into the middle of cpu_switch */ xorl %eax,%eax jmp switch_resume /* - * void switch_exit(struct lwp *l); - * Switch to the appropriate idle context (lwp0's if uniprocessor; the cpu's - * if multiprocessor) and deallocate the address space and kernel stack for p. + * void cpu_exit(struct lwp *l) + * Switch to the appropriate idle context (lwp0's if uniprocessor; the CPU's + * if multiprocessor) and deallocate the address space and kernel stack for p. * Then jump into cpu_switch(), as if we were in the idle proc all along. */ #ifndef MULTIPROCESSOR .globl _C_LABEL(lwp0) #endif - .globl _C_LABEL(uvmspace_free),_C_LABEL(kernel_map) - .globl _C_LABEL(uvm_km_free),_C_LABEL(tss_free) -/* LINTSTUB: Func: void switch_exit(struct lwp *l) */ -ENTRY(switch_exit) +/* LINTSTUB: Func: void cpu_exit(struct lwp *l) */ +ENTRY(cpu_exit) movl 4(%esp),%edi # old process #ifndef MULTIPROCESSOR movl $_C_LABEL(lwp0),%ebx @@ -2155,91 +1236,16 @@ ENTRY(switch_exit) movl PCB_ESP(%esi),%esp movl PCB_EBP(%esi),%ebp - /* Load TSS info. */ + /* Switch TSS. Reset "task busy" flag before loading. */ + movl %cr3,%eax + movl %eax,PCB_CR3(%esi) #ifdef MULTIPROCESSOR movl CPUVAR(GDT),%eax -#else - /* Load TSS info. */ - movl _C_LABEL(gdt),%eax -#endif - - /* Switch address space. */ - movl PCB_CR3(%esi),%ecx - movl %ecx,%cr3 - - /* Switch TSS. */ - andl $~0x0200,4-SEL_KPL(%eax,%edx,1) - ltr %dx - - /* We're always in the kernel, so we don't need the LDT. */ - - /* Restore cr0 (including FPU state). */ - movl PCB_CR0(%esi),%ecx - movl %ecx,%cr0 - - /* Record new pcb. */ - SET_CURPCB(%esi) - - /* Interrupts are okay again. */ - sti - - /* - * Schedule the dead process's vmspace and stack to be freed. - */ - pushl %edi /* exit2(l) */ - call _C_LABEL(exit2) - addl $4,%esp - - /* Jump into cpu_switch() with the right state. */ - xorl %esi,%esi - movl %esi,CPUVAR(CURLWP) - jmp idle_start - -/* - * switch_lwp_exit(struct lwp *l); - * Switch to the appropriate idle context (lwp0's if uniprocessor; the cpu's - * if multiprocessor) and deallocate the kernel stack for l. - * Then jump into cpu_switch(), as if we were in the idle proc all along. - */ -#ifndef MULTIPROCESSOR - .globl _C_LABEL(lwp0) -#endif - .globl _C_LABEL(uvmspace_free),_C_LABEL(kernel_map) - .globl _C_LABEL(uvm_km_free),_C_LABEL(tss_free) -/* LINTSTUB: Func: void switch_lwp_exit(struct lwp *l) */ -ENTRY(switch_lwp_exit) - movl 4(%esp),%edi # old process -#ifndef MULTIPROCESSOR - movl $_C_LABEL(lwp0),%ebx - movl L_ADDR(%ebx),%esi - movl L_MD_TSS_SEL(%ebx),%edx #else - movl CPUVAR(IDLE_PCB),%esi - movl CPUVAR(IDLE_TSS_SEL),%edx -#endif - /* In case we fault... */ - movl $0,CPUVAR(CURLWP) - - /* Restore the idle context. */ - cli - - /* Restore stack pointers. */ - movl PCB_ESP(%esi),%esp - movl PCB_EBP(%esi),%ebp - - /* Load TSS info. */ -#ifdef MULTIPROCESSOR - movl CPUVAR(GDT),%eax -#else /* Load TSS info. */ movl _C_LABEL(gdt),%eax #endif - /* Switch address space. */ - movl PCB_CR3(%esi),%ecx - movl %ecx,%cr3 - - /* Switch TSS. */ andl $~0x0200,4-SEL_KPL(%eax,%edx,1) ltr %dx @@ -2256,9 +1262,9 @@ ENTRY(switch_lwp_exit) sti /* - * Schedule the dead process's vmspace and stack to be freed. + * Schedule the dead LWP's stack to be freed. */ - pushl %edi /* lwp_exit2(l) */ + pushl %edi call _C_LABEL(lwp_exit2) addl $4,%esp @@ -2274,7 +1280,7 @@ ENTRY(switch_lwp_exit) /* LINTSTUB: Func: void savectx(struct pcb *pcb) */ ENTRY(savectx) movl 4(%esp),%edx # edx = p->p_addr - + /* Save stack pointers. */ movl %esp,PCB_ESP(%edx) movl %ebp,PCB_EBP(%edx) @@ -2303,6 +1309,12 @@ syscall1: INTRENTRY #ifdef DIAGNOSTIC + cmpl $0, CPUVAR(WANT_PMAPLOAD) + jz 1f + pushl $6f + call _C_LABEL(printf) + addl $4, %esp +1: movl CPUVAR(ILEVEL),%ebx testl %ebx,%ebx jz 1f @@ -2312,13 +1324,16 @@ syscall1: #ifdef DDB int $3 #endif -1: +1: #endif /* DIAGNOSTIC */ movl CPUVAR(CURLWP),%edx movl %esp,L_MD_REGS(%edx) # save pointer to frame movl L_PROC(%edx),%edx + pushl %esp call *P_MD_SYSCALL(%edx) # get pointer to syscall() function -2: /* Check for ASTs on exit to user mode. */ + addl $4,%esp +.Lsyscall_checkast: + /* Check for ASTs on exit to user mode. */ cli CHECK_ASTPENDING(%eax) je 1f @@ -2326,12 +1341,16 @@ syscall1: CLEAR_ASTPENDING(%eax) sti /* Pushed T_ASTFLT into tf_trapno on entry. */ + pushl %esp call _C_LABEL(trap) - jmp 2b + addl $4,%esp + jmp .Lsyscall_checkast /* re-check ASTs */ +1: CHECK_DEFERRED_SWITCH(%eax) + jnz 9f #ifndef DIAGNOSTIC -1: INTRFASTEXIT + INTRFASTEXIT #else /* DIAGNOSTIC */ -1: cmpl $IPL_NONE,CPUVAR(ILEVEL) + cmpl $IPL_NONE,CPUVAR(ILEVEL) jne 3f INTRFASTEXIT 3: sti @@ -2344,8 +1363,12 @@ syscall1: movl $IPL_NONE,CPUVAR(ILEVEL) jmp 2b 4: .asciz "WARNING: SPL NOT LOWERED ON SYSCALL EXIT\n" -5: .asciz "WARNING: SPL NOT ZERO ON SYSCALL ENTRY\n" +5: .asciz "WARNING: SPL NOT ZERO ON SYSCALL ENTRY\n" +6: .asciz "WARNING: WANT PMAPLOAD ON SYSCALL ENTRY\n" #endif /* DIAGNOSTIC */ +9: sti + call _C_LABEL(pmap_load) + jmp .Lsyscall_checkast /* re-check ASTs */ #if NNPX > 0 /*