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.25 retrieving revision 1.31.6.2 diff -u -p -r1.25 -r1.31.6.2 --- src/sys/arch/i386/i386/locore.S 2004/03/26 19:05:33 1.25 +++ src/sys/arch/i386/i386/locore.S 2005/03/19 08:33:02 1.31.6.2 @@ -1,7 +1,7 @@ -/* $NetBSD: locore.S,v 1.25 2004/03/26 19:05:33 drochner Exp $ */ +/* $NetBSD: locore.S,v 1.31.6.2 2005/03/19 08:33:02 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 @@ -110,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) @@ -123,7 +123,7 @@ #endif -#define GET_CURPCB(reg) movl CPUVAR(CURPCB),reg +#define GET_CURPCB(reg) movl CPUVAR(CURPCB),reg #define SET_CURPCB(reg) movl reg,CPUVAR(CURPCB) #define CLEAR_RESCHED(reg) movl reg,CPUVAR(RESCHED) @@ -152,27 +152,9 @@ #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 * PAGE_SIZE) - .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 * PAGE_SIZE) - .set _C_LABEL(APTDpde),(_C_LABEL(PTD) + PDSLOT_APTE * 4) +/* This shouldn't conflict with a macro of the same name defined in pmap.h */ +#define PTE_BASE (PDSLOT_PTE << PDSHIFT) /* * Initialization @@ -185,14 +167,14 @@ #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 PAGE_SIZE @@ -202,27 +184,27 @@ .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 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(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 @@ -233,7 +215,7 @@ _C_LABEL(biosextmem): .long 0 # extended #else _C_LABEL(biosextmem): .long REALEXTMEM #endif - + .space 512 tmpstk: @@ -497,7 +479,7 @@ 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) * PAGE_SIZE) @@ -524,17 +506,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 @@ -565,7 +554,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 @@ -613,8 +602,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 @@ -654,7 +643,7 @@ begin: pushl %esp call _C_LABEL(initgdt) addl $4,%esp - + movl _C_LABEL(nkpde),%eax shll $PGSHIFT,%eax addl $TABLESIZE,%eax @@ -875,7 +864,7 @@ ENTRY(i386_copyout) pushl %esi pushl %edi pushl $0 - + movl 16(%esp),%esi movl 20(%esp),%edi movl 24(%esp),%eax @@ -915,9 +904,9 @@ ENTRY(i386_copyout) movl $2f,PCB_ONFAULT(%edx) 1: /* Check PTE for each page. */ - testb $PG_RW,_C_LABEL(PTmap)(,%edi,4) + testb $PG_RW,PTE_BASE(,%edi,4) jz 2f - + 4: incl %edi decl %ecx jns 1b @@ -925,7 +914,7 @@ ENTRY(i386_copyout) movl 20(%esp),%edi movl 24(%esp),%eax jmp 3f - + 2: /* Simulate a trap. */ pushl %ecx movl %edi,%eax @@ -965,7 +954,7 @@ ENTRY(i486_copyout) pushl %esi pushl %edi pushl $0 - + movl 16(%esp),%esi movl 20(%esp),%edi movl 24(%esp),%eax @@ -1020,7 +1009,7 @@ ENTRY(i386_copyin) 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 @@ -1125,7 +1114,7 @@ ENTRY(copyoutstr) movl %edi,%eax shrl $PGSHIFT,%eax # calculate pte address - testb $PG_RW,_C_LABEL(PTmap)(,%eax,4) + testb $PG_RW,PTE_BASE(,%eax,4) jnz 2f 6: /* Simulate a trap. */ @@ -1173,6 +1162,7 @@ ENTRY(copyoutstr) */ movl $VM_MAXUSER_ADDRESS,%eax subl %edi,%eax + jc _C_LABEL(copystr_efault) cmpl %edx,%eax jae 1f movl %eax,%edx @@ -1212,7 +1202,7 @@ ENTRY(copyoutstr) ENTRY(copyinstr) pushl %esi pushl %edi - + DO_DEFERRED_SWITCH(%eax) GET_CURPCB(%ecx) @@ -1227,6 +1217,7 @@ ENTRY(copyinstr) */ movl $VM_MAXUSER_ADDRESS,%eax subl %esi,%eax + jc _C_LABEL(copystr_efault) cmpl %edx,%eax jae 1f movl %eax,%edx @@ -1335,7 +1326,7 @@ ENTRY(fuword) movl (%edx),%eax movl $0,PCB_ONFAULT(%ecx) ret - + /* * int fusword(const void *uaddr); * Fetch a short from the user's address space. @@ -1352,7 +1343,7 @@ ENTRY(fusword) 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 @@ -1372,7 +1363,7 @@ ENTRY(fuswintr) movzwl (%edx),%eax movl $0,PCB_ONFAULT(%ecx) ret - + /* * int fubyte(const void *uaddr); * Fetch a byte from the user's address space. @@ -1441,7 +1432,7 @@ ENTRY(suword) movl %edx,%eax shrl $PGSHIFT,%eax # calculate pte address - testb $PG_RW,_C_LABEL(PTmap)(,%eax,4) + testb $PG_RW,PTE_BASE(,%eax,4) jnz 1f 3: /* Simulate a trap. */ @@ -1465,7 +1456,7 @@ ENTRY(suword) xorl %eax,%eax movl %eax,PCB_ONFAULT(%ecx) ret - + /* * int susword(void *uaddr, short x); * Store a short in the user's address space. @@ -1489,7 +1480,7 @@ ENTRY(susword) movl %edx,%eax shrl $PGSHIFT,%eax # calculate pte address - testb $PG_RW,_C_LABEL(PTmap)(,%eax,4) + testb $PG_RW,PTE_BASE(,%eax,4) jnz 1f 3: /* Simulate a trap. */ @@ -1539,7 +1530,7 @@ ENTRY(suswintr) movl %edx,%eax shrl $PGSHIFT,%eax # calculate pte address - testb $PG_RW,_C_LABEL(PTmap)(,%eax,4) + testb $PG_RW,PTE_BASE(,%eax,4) jnz 1f /* Simulate a trap. */ @@ -1572,12 +1563,12 @@ ENTRY(subyte) jne 2f #endif /* I486_CPU || I586_CPU || I686_CPU */ - GET_CURPCB(%eax) + 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) + testb $PG_RW,PTE_BASE(,%eax,4) jnz 1f 3: /* Simulate a trap. */ @@ -1689,9 +1680,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) @@ -1706,9 +1697,9 @@ ENTRY(cpu_switch) call _C_LABEL(panic) /* NOTREACHED */ 2: .asciz "not splsched() in cpu_switch!" -1: +1: #endif /* DEBUG */ - + movl 16(%esp),%esi # current /* @@ -1775,6 +1766,8 @@ ENTRY(cpu_switch) movl PCB_EBP(%edi),%ebp /* Switch TSS. Reset "task busy" flag before loading. */ + movl %cr3,%eax + movl %eax,PCB_CR3(%edi) #ifdef MULTIPROCESSOR movl CPUVAR(GDT),%eax #else @@ -1794,8 +1787,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. */ @@ -1803,7 +1796,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 @@ -1817,24 +1810,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 sti -#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) +#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 @@ -1925,15 +1918,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 @@ -1947,7 +1942,7 @@ switch_restored: /* Restore cr0 (including FPU state). */ movl PCB_CR0(%esi),%ecx #ifdef MULTIPROCESSOR - /* + /* * If our floating point registers are on a different CPU, * clear CR0_TS so we'll trap rather than reuse bogus state. */ @@ -1955,8 +1950,8 @@ switch_restored: cmpl CPUVAR(SELF),%ebx jz 1f orl $CR0_TS,%ecx -1: -#endif +1: +#endif movl %ecx,%cr0 /* Record new pcb. */ @@ -1976,16 +1971,19 @@ switch_restored: 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 @@ -2048,15 +2046,13 @@ ENTRY(cpu_switchto) /* * 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. + * 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 cpu_exit(struct lwp *l) */ ENTRY(cpu_exit) movl 4(%esp),%edi # old process @@ -2078,15 +2074,16 @@ ENTRY(cpu_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 +#else /* Load TSS info. */ movl _C_LABEL(gdt),%eax #endif - /* Switch TSS. */ andl $~0x0200,4-SEL_KPL(%eax,%edx,1) ltr %dx @@ -2121,7 +2118,7 @@ ENTRY(cpu_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) @@ -2165,7 +2162,7 @@ syscall1: #ifdef DDB int $3 #endif -1: +1: #endif /* DIAGNOSTIC */ movl CPUVAR(CURLWP),%edx movl %esp,L_MD_REGS(%edx) # save pointer to frame @@ -2173,7 +2170,7 @@ syscall1: pushl %esp call *P_MD_SYSCALL(%edx) # get pointer to syscall() function addl $4,%esp -syscall_checkast: +.Lsyscall_checkast: /* Check for ASTs on exit to user mode. */ cli CHECK_ASTPENDING(%eax) @@ -2185,7 +2182,7 @@ syscall_checkast: pushl %esp call _C_LABEL(trap) addl $4,%esp - jmp syscall_checkast /* re-check ASTs */ + jmp .Lsyscall_checkast /* re-check ASTs */ 1: CHECK_DEFERRED_SWITCH(%eax) jnz 9f #ifndef DIAGNOSTIC @@ -2204,12 +2201,12 @@ syscall_checkast: 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" -6: .asciz "WARNING: WANT PMAPLOAD 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 syscall_checkast /* re-check ASTs */ + jmp .Lsyscall_checkast /* re-check ASTs */ #if NNPX > 0 /*