10967373eSDavid Greenman/*- 20967373eSDavid Greenman * Copyright (c) 1990 The Regents of the University of California. 30967373eSDavid Greenman * All rights reserved. 40967373eSDavid Greenman * 50967373eSDavid Greenman * This code is derived from software contributed to Berkeley by 60967373eSDavid Greenman * William Jolitz. 70967373eSDavid Greenman * 80967373eSDavid Greenman * Redistribution and use in source and binary forms, with or without 90967373eSDavid Greenman * modification, are permitted provided that the following conditions 100967373eSDavid Greenman * are met: 110967373eSDavid Greenman * 1. Redistributions of source code must retain the above copyright 120967373eSDavid Greenman * notice, this list of conditions and the following disclaimer. 130967373eSDavid Greenman * 2. Redistributions in binary form must reproduce the above copyright 140967373eSDavid Greenman * notice, this list of conditions and the following disclaimer in the 150967373eSDavid Greenman * documentation and/or other materials provided with the distribution. 160967373eSDavid Greenman * 3. All advertising materials mentioning features or use of this software 170967373eSDavid Greenman * must display the following acknowledgement: 180967373eSDavid Greenman * This product includes software developed by the University of 190967373eSDavid Greenman * California, Berkeley and its contributors. 200967373eSDavid Greenman * 4. Neither the name of the University nor the names of its contributors 210967373eSDavid Greenman * may be used to endorse or promote products derived from this software 220967373eSDavid Greenman * without specific prior written permission. 230967373eSDavid Greenman * 240967373eSDavid Greenman * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 250967373eSDavid Greenman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 260967373eSDavid Greenman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 270967373eSDavid Greenman * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 280967373eSDavid Greenman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 290967373eSDavid Greenman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 300967373eSDavid Greenman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 310967373eSDavid Greenman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 320967373eSDavid Greenman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 330967373eSDavid Greenman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 340967373eSDavid Greenman * SUCH DAMAGE. 350967373eSDavid Greenman * 360967373eSDavid Greenman * $Id$ 370967373eSDavid Greenman */ 380967373eSDavid Greenman 390967373eSDavid Greenman#include "npx.h" /* for NNPX */ 400967373eSDavid Greenman#include "assym.s" /* for preprocessor defines */ 410967373eSDavid Greenman#include "errno.h" /* for error codes */ 420967373eSDavid Greenman 430967373eSDavid Greenman#include "i386/isa/debug.h" /* for SHOW macros */ 440967373eSDavid Greenman#include "machine/asmacros.h" /* for miscellaneous assembly macros */ 450967373eSDavid Greenman 460967373eSDavid Greenman/*****************************************************************************/ 470967373eSDavid Greenman/* Scheduling */ 480967373eSDavid Greenman/*****************************************************************************/ 490967373eSDavid Greenman 500967373eSDavid Greenman/* 510967373eSDavid Greenman * The following primitives manipulate the run queues. 520967373eSDavid Greenman * _whichqs tells which of the 32 queues _qs 530967373eSDavid Greenman * have processes in them. Setrq puts processes into queues, Remrq 540967373eSDavid Greenman * removes them from queues. The running process is on no queue, 550967373eSDavid Greenman * other processes are on a queue related to p->p_pri, divided by 4 560967373eSDavid Greenman * actually to shrink the 0-127 range of priorities into the 32 available 570967373eSDavid Greenman * queues. 580967373eSDavid Greenman */ 590967373eSDavid Greenman .data 600967373eSDavid Greenman .globl _curpcb, _whichqs 610967373eSDavid Greenman_curpcb: .long 0 /* pointer to curproc's PCB area */ 620967373eSDavid Greenman_whichqs: .long 0 /* which run queues have data */ 630967373eSDavid Greenman 640967373eSDavid Greenman .globl _qs,_cnt,_panic 650967373eSDavid Greenman .comm _noproc,4 660967373eSDavid Greenman .comm _runrun,4 670967373eSDavid Greenman 680967373eSDavid Greenman .globl _want_resched 690967373eSDavid Greenman_want_resched: .long 0 /* we need to re-run the scheduler */ 700967373eSDavid Greenman 710967373eSDavid Greenman .text 720967373eSDavid Greenman/* 730967373eSDavid Greenman * Setrq(p) 740967373eSDavid Greenman * 750967373eSDavid Greenman * Call should be made at spl6(), and p->p_stat should be SRUN 760967373eSDavid Greenman */ 770967373eSDavid GreenmanENTRY(setrq) 780967373eSDavid Greenman movl 4(%esp),%eax 790967373eSDavid Greenman cmpl $0,P_RLINK(%eax) /* should not be on q already */ 800967373eSDavid Greenman je set1 810967373eSDavid Greenman pushl $set2 820967373eSDavid Greenman call _panic 830967373eSDavid Greenmanset1: 840967373eSDavid Greenman movzbl P_PRI(%eax),%edx 850967373eSDavid Greenman shrl $2,%edx 860967373eSDavid Greenman btsl %edx,_whichqs /* set q full bit */ 870967373eSDavid Greenman shll $3,%edx 880967373eSDavid Greenman addl $_qs,%edx /* locate q hdr */ 890967373eSDavid Greenman movl %edx,P_LINK(%eax) /* link process on tail of q */ 900967373eSDavid Greenman movl P_RLINK(%edx),%ecx 910967373eSDavid Greenman movl %ecx,P_RLINK(%eax) 920967373eSDavid Greenman movl %eax,P_RLINK(%edx) 930967373eSDavid Greenman movl %eax,P_LINK(%ecx) 940967373eSDavid Greenman ret 950967373eSDavid Greenman 960967373eSDavid Greenmanset2: .asciz "setrq" 970967373eSDavid Greenman 980967373eSDavid Greenman/* 990967373eSDavid Greenman * Remrq(p) 1000967373eSDavid Greenman * 1010967373eSDavid Greenman * Call should be made at spl6(). 1020967373eSDavid Greenman */ 1030967373eSDavid GreenmanENTRY(remrq) 1040967373eSDavid Greenman movl 4(%esp),%eax 1050967373eSDavid Greenman movzbl P_PRI(%eax),%edx 1060967373eSDavid Greenman shrl $2,%edx 1070967373eSDavid Greenman btrl %edx,_whichqs /* clear full bit, panic if clear already */ 1080967373eSDavid Greenman jb rem1 1090967373eSDavid Greenman pushl $rem3 1100967373eSDavid Greenman call _panic 1110967373eSDavid Greenmanrem1: 1120967373eSDavid Greenman pushl %edx 1130967373eSDavid Greenman movl P_LINK(%eax),%ecx /* unlink process */ 1140967373eSDavid Greenman movl P_RLINK(%eax),%edx 1150967373eSDavid Greenman movl %edx,P_RLINK(%ecx) 1160967373eSDavid Greenman movl P_RLINK(%eax),%ecx 1170967373eSDavid Greenman movl P_LINK(%eax),%edx 1180967373eSDavid Greenman movl %edx,P_LINK(%ecx) 1190967373eSDavid Greenman popl %edx 1200967373eSDavid Greenman movl $_qs,%ecx 1210967373eSDavid Greenman shll $3,%edx 1220967373eSDavid Greenman addl %edx,%ecx 1230967373eSDavid Greenman cmpl P_LINK(%ecx),%ecx /* q still has something? */ 1240967373eSDavid Greenman je rem2 1250967373eSDavid Greenman shrl $3,%edx /* yes, set bit as still full */ 1260967373eSDavid Greenman btsl %edx,_whichqs 1270967373eSDavid Greenmanrem2: 1280967373eSDavid Greenman movl $0,P_RLINK(%eax) /* zap reverse link to indicate off list */ 1290967373eSDavid Greenman ret 1300967373eSDavid Greenman 1310967373eSDavid Greenmanrem3: .asciz "remrq" 1320967373eSDavid Greenmansw0: .asciz "swtch" 1330967373eSDavid Greenman 1340967373eSDavid Greenman/* 1350967373eSDavid Greenman * When no processes are on the runq, Swtch branches to idle 1360967373eSDavid Greenman * to wait for something to come ready. 1370967373eSDavid Greenman */ 1380967373eSDavid Greenman ALIGN_TEXT 1390967373eSDavid GreenmanIdle: 1400967373eSDavid Greenman sti 1410967373eSDavid Greenman SHOW_STI 1420967373eSDavid Greenman 1430967373eSDavid Greenman ALIGN_TEXT 1440967373eSDavid Greenmanidle_loop: 1450967373eSDavid Greenman call _spl0 1460967373eSDavid Greenman cmpl $0,_whichqs 1470967373eSDavid Greenman jne sw1 1480967373eSDavid Greenman hlt /* wait for interrupt */ 1490967373eSDavid Greenman jmp idle_loop 1500967373eSDavid Greenman 1510967373eSDavid Greenmanbadsw: 1520967373eSDavid Greenman pushl $sw0 1530967373eSDavid Greenman call _panic 1540967373eSDavid Greenman /*NOTREACHED*/ 1550967373eSDavid Greenman 1560967373eSDavid Greenman/* 1570967373eSDavid Greenman * Swtch() 1580967373eSDavid Greenman */ 1590967373eSDavid Greenman SUPERALIGN_TEXT /* so profiling doesn't lump Idle with swtch().. */ 1600967373eSDavid GreenmanENTRY(swtch) 1610967373eSDavid Greenman 1620967373eSDavid Greenman incl _cnt+V_SWTCH 1630967373eSDavid Greenman 1640967373eSDavid Greenman /* switch to new process. first, save context as needed */ 1650967373eSDavid Greenman 1660967373eSDavid Greenman movl _curproc,%ecx 1670967373eSDavid Greenman 1680967373eSDavid Greenman /* if no process to save, don't bother */ 1690967373eSDavid Greenman testl %ecx,%ecx 1700967373eSDavid Greenman je sw1 1710967373eSDavid Greenman 1720967373eSDavid Greenman movl P_ADDR(%ecx),%ecx 1730967373eSDavid Greenman 1740967373eSDavid Greenman movl (%esp),%eax /* Hardware registers */ 1750967373eSDavid Greenman movl %eax,PCB_EIP(%ecx) 1760967373eSDavid Greenman movl %ebx,PCB_EBX(%ecx) 1770967373eSDavid Greenman movl %esp,PCB_ESP(%ecx) 1780967373eSDavid Greenman movl %ebp,PCB_EBP(%ecx) 1790967373eSDavid Greenman movl %esi,PCB_ESI(%ecx) 1800967373eSDavid Greenman movl %edi,PCB_EDI(%ecx) 1810967373eSDavid Greenman 1820967373eSDavid Greenman#if NNPX > 0 1830967373eSDavid Greenman /* have we used fp, and need a save? */ 1840967373eSDavid Greenman mov _curproc,%eax 1850967373eSDavid Greenman cmp %eax,_npxproc 1860967373eSDavid Greenman jne 1f 1870967373eSDavid Greenman pushl %ecx /* h/w bugs make saving complicated */ 1880967373eSDavid Greenman leal PCB_SAVEFPU(%ecx),%eax 1890967373eSDavid Greenman pushl %eax 1900967373eSDavid Greenman call _npxsave /* do it in a big C function */ 1910967373eSDavid Greenman popl %eax 1920967373eSDavid Greenman popl %ecx 1930967373eSDavid Greenman1: 1940967373eSDavid Greenman#endif /* NNPX > 0 */ 1950967373eSDavid Greenman 1960967373eSDavid Greenman movl _CMAP2,%eax /* save temporary map PTE */ 1970967373eSDavid Greenman movl %eax,PCB_CMAP2(%ecx) /* in our context */ 1980967373eSDavid Greenman movl $0,_curproc /* out of process */ 1990967373eSDavid Greenman 2000967373eSDavid Greenman# movw _cpl,%ax 2010967373eSDavid Greenman# movw %ax,PCB_IML(%ecx) /* save ipl */ 2020967373eSDavid Greenman 2030967373eSDavid Greenman /* save is done, now choose a new process or idle */ 2040967373eSDavid Greenmansw1: 2050967373eSDavid Greenman cli 2060967373eSDavid Greenman SHOW_CLI 2070967373eSDavid Greenman movl _whichqs,%edi 2080967373eSDavid Greenman2: 2090967373eSDavid Greenman /* XXX - bsf is sloow */ 2100967373eSDavid Greenman bsfl %edi,%eax /* find a full q */ 2110967373eSDavid Greenman je Idle /* if none, idle */ 2120967373eSDavid Greenman /* XX update whichqs? */ 2130967373eSDavid Greenmanswfnd: 2140967373eSDavid Greenman btrl %eax,%edi /* clear q full status */ 2150967373eSDavid Greenman jnb 2b /* if it was clear, look for another */ 2160967373eSDavid Greenman movl %eax,%ebx /* save which one we are using */ 2170967373eSDavid Greenman 2180967373eSDavid Greenman shll $3,%eax 2190967373eSDavid Greenman addl $_qs,%eax /* select q */ 2200967373eSDavid Greenman movl %eax,%esi 2210967373eSDavid Greenman 2220967373eSDavid Greenman#ifdef DIAGNOSTIC 2230967373eSDavid Greenman cmpl P_LINK(%eax),%eax /* linked to self? (e.g. not on list) */ 2240967373eSDavid Greenman je badsw /* not possible */ 2250967373eSDavid Greenman#endif 2260967373eSDavid Greenman 2270967373eSDavid Greenman movl P_LINK(%eax),%ecx /* unlink from front of process q */ 2280967373eSDavid Greenman movl P_LINK(%ecx),%edx 2290967373eSDavid Greenman movl %edx,P_LINK(%eax) 2300967373eSDavid Greenman movl P_RLINK(%ecx),%eax 2310967373eSDavid Greenman movl %eax,P_RLINK(%edx) 2320967373eSDavid Greenman 2330967373eSDavid Greenman cmpl P_LINK(%ecx),%esi /* q empty */ 2340967373eSDavid Greenman je 3f 2350967373eSDavid Greenman btsl %ebx,%edi /* nope, set to indicate full */ 2360967373eSDavid Greenman3: 2370967373eSDavid Greenman movl %edi,_whichqs /* update q status */ 2380967373eSDavid Greenman 2390967373eSDavid Greenman movl $0,%eax 2400967373eSDavid Greenman movl %eax,_want_resched 2410967373eSDavid Greenman 2420967373eSDavid Greenman#ifdef DIAGNOSTIC 2430967373eSDavid Greenman cmpl %eax,P_WCHAN(%ecx) 2440967373eSDavid Greenman jne badsw 2450967373eSDavid Greenman cmpb $SRUN,P_STAT(%ecx) 2460967373eSDavid Greenman jne badsw 2470967373eSDavid Greenman#endif 2480967373eSDavid Greenman 2490967373eSDavid Greenman movl %eax,P_RLINK(%ecx) /* isolate process to run */ 2500967373eSDavid Greenman movl P_ADDR(%ecx),%edx 2510967373eSDavid Greenman movl PCB_CR3(%edx),%ebx 2520967373eSDavid Greenman 2530967373eSDavid Greenman /* switch address space */ 2540967373eSDavid Greenman movl %ebx,%cr3 2550967373eSDavid Greenman 2560967373eSDavid Greenman /* restore context */ 2570967373eSDavid Greenman movl PCB_EBX(%edx),%ebx 2580967373eSDavid Greenman movl PCB_ESP(%edx),%esp 2590967373eSDavid Greenman movl PCB_EBP(%edx),%ebp 2600967373eSDavid Greenman movl PCB_ESI(%edx),%esi 2610967373eSDavid Greenman movl PCB_EDI(%edx),%edi 2620967373eSDavid Greenman movl PCB_EIP(%edx),%eax 2630967373eSDavid Greenman movl %eax,(%esp) 2640967373eSDavid Greenman 2650967373eSDavid Greenman movl PCB_CMAP2(%edx),%eax /* get temporary map */ 2660967373eSDavid Greenman movl %eax,_CMAP2 /* reload temporary map PTE */ 2670967373eSDavid Greenman 2680967373eSDavid Greenman movl %ecx,_curproc /* into next process */ 2690967373eSDavid Greenman movl %edx,_curpcb 2700967373eSDavid Greenman 2710967373eSDavid Greenman pushl %edx /* save p to return */ 2720967373eSDavid Greenman/* 2730967373eSDavid Greenman * XXX - 0.0 forgot to save it - is that why this was commented out in 0.1? 2740967373eSDavid Greenman * I think restoring the cpl is unnecessary, but we must turn off the cli 2750967373eSDavid Greenman * now that spl*() don't do it as a side affect. 2760967373eSDavid Greenman */ 2770967373eSDavid Greenman pushl PCB_IML(%edx) 2780967373eSDavid Greenman sti 2790967373eSDavid Greenman SHOW_STI 2800967373eSDavid Greenman#if 0 2810967373eSDavid Greenman call _splx 2820967373eSDavid Greenman#endif 2830967373eSDavid Greenman addl $4,%esp 2840967373eSDavid Greenman/* 2850967373eSDavid Greenman * XXX - 0.0 gets here via swtch_to_inactive(). I think 0.1 gets here in the 2860967373eSDavid Greenman * same way. Better return a value. 2870967373eSDavid Greenman */ 2880967373eSDavid Greenman popl %eax /* return(p); */ 2890967373eSDavid Greenman ret 2900967373eSDavid Greenman 2910967373eSDavid GreenmanENTRY(mvesp) 2920967373eSDavid Greenman movl %esp,%eax 2930967373eSDavid Greenman ret 2940967373eSDavid Greenman/* 2950967373eSDavid Greenman * struct proc *swtch_to_inactive(p) ; struct proc *p; 2960967373eSDavid Greenman * 2970967373eSDavid Greenman * At exit of a process, move off the address space of the 2980967373eSDavid Greenman * process and onto a "safe" one. Then, on a temporary stack 2990967373eSDavid Greenman * return and run code that disposes of the old state. 3000967373eSDavid Greenman * Since this code requires a parameter from the "old" stack, 3010967373eSDavid Greenman * pass it back as a return value. 3020967373eSDavid Greenman */ 3030967373eSDavid GreenmanENTRY(swtch_to_inactive) 3040967373eSDavid Greenman popl %edx /* old pc */ 3050967373eSDavid Greenman popl %eax /* arg, our return value */ 3060967373eSDavid Greenman movl _IdlePTD,%ecx 3070967373eSDavid Greenman movl %ecx,%cr3 /* good bye address space */ 3080967373eSDavid Greenman #write buffer? 3090967373eSDavid Greenman movl $tmpstk-4,%esp /* temporary stack, compensated for call */ 3100967373eSDavid Greenman jmp %edx /* return, execute remainder of cleanup */ 3110967373eSDavid Greenman 3120967373eSDavid Greenman/* 3130967373eSDavid Greenman * savectx(pcb, altreturn) 3140967373eSDavid Greenman * Update pcb, saving current processor state and arranging 3150967373eSDavid Greenman * for alternate return ala longjmp in swtch if altreturn is true. 3160967373eSDavid Greenman */ 3170967373eSDavid GreenmanENTRY(savectx) 3180967373eSDavid Greenman movl 4(%esp),%ecx 3190967373eSDavid Greenman movw _cpl,%ax 3200967373eSDavid Greenman movw %ax,PCB_IML(%ecx) 3210967373eSDavid Greenman movl (%esp),%eax 3220967373eSDavid Greenman movl %eax,PCB_EIP(%ecx) 3230967373eSDavid Greenman movl %ebx,PCB_EBX(%ecx) 3240967373eSDavid Greenman movl %esp,PCB_ESP(%ecx) 3250967373eSDavid Greenman movl %ebp,PCB_EBP(%ecx) 3260967373eSDavid Greenman movl %esi,PCB_ESI(%ecx) 3270967373eSDavid Greenman movl %edi,PCB_EDI(%ecx) 3280967373eSDavid Greenman 3290967373eSDavid Greenman#if NNPX > 0 3300967373eSDavid Greenman /* 3310967373eSDavid Greenman * If npxproc == NULL, then the npx h/w state is irrelevant and the 3320967373eSDavid Greenman * state had better already be in the pcb. This is true for forks 3330967373eSDavid Greenman * but not for dumps (the old book-keeping with FP flags in the pcb 3340967373eSDavid Greenman * always lost for dumps because the dump pcb has 0 flags). 3350967373eSDavid Greenman * 3360967373eSDavid Greenman * If npxproc != NULL, then we have to save the npx h/w state to 3370967373eSDavid Greenman * npxproc's pcb and copy it to the requested pcb, or save to the 3380967373eSDavid Greenman * requested pcb and reload. Copying is easier because we would 3390967373eSDavid Greenman * have to handle h/w bugs for reloading. We used to lose the 3400967373eSDavid Greenman * parent's npx state for forks by forgetting to reload. 3410967373eSDavid Greenman */ 3420967373eSDavid Greenman mov _npxproc,%eax 3430967373eSDavid Greenman testl %eax,%eax 3440967373eSDavid Greenman je 1f 3450967373eSDavid Greenman 3460967373eSDavid Greenman pushl %ecx 3470967373eSDavid Greenman movl P_ADDR(%eax),%eax 3480967373eSDavid Greenman leal PCB_SAVEFPU(%eax),%eax 3490967373eSDavid Greenman pushl %eax 3500967373eSDavid Greenman pushl %eax 3510967373eSDavid Greenman call _npxsave 3520967373eSDavid Greenman popl %eax 3530967373eSDavid Greenman popl %eax 3540967373eSDavid Greenman popl %ecx 3550967373eSDavid Greenman 3560967373eSDavid Greenman pushl %ecx 3570967373eSDavid Greenman pushl $108+8*2 /* XXX h/w state size + padding */ 3580967373eSDavid Greenman leal PCB_SAVEFPU(%ecx),%ecx 3590967373eSDavid Greenman pushl %ecx 3600967373eSDavid Greenman pushl %eax 3610967373eSDavid Greenman call _bcopy 3620967373eSDavid Greenman addl $12,%esp 3630967373eSDavid Greenman popl %ecx 3640967373eSDavid Greenman1: 3650967373eSDavid Greenman#endif /* NNPX > 0 */ 3660967373eSDavid Greenman 3670967373eSDavid Greenman movl _CMAP2,%edx /* save temporary map PTE */ 3680967373eSDavid Greenman movl %edx,PCB_CMAP2(%ecx) /* in our context */ 3690967373eSDavid Greenman 3700967373eSDavid Greenman cmpl $0,8(%esp) 3710967373eSDavid Greenman je 1f 3720967373eSDavid Greenman movl %esp,%edx /* relocate current sp relative to pcb */ 3730967373eSDavid Greenman subl $_kstack,%edx /* (sp is relative to kstack): */ 3740967373eSDavid Greenman addl %edx,%ecx /* pcb += sp - kstack; */ 3750967373eSDavid Greenman movl %eax,(%ecx) /* write return pc at (relocated) sp@ */ 3760967373eSDavid Greenman 3770967373eSDavid Greenman/* this mess deals with replicating register state gcc hides */ 3780967373eSDavid Greenman movl 12(%esp),%eax 3790967373eSDavid Greenman movl %eax,12(%ecx) 3800967373eSDavid Greenman movl 16(%esp),%eax 3810967373eSDavid Greenman movl %eax,16(%ecx) 3820967373eSDavid Greenman movl 20(%esp),%eax 3830967373eSDavid Greenman movl %eax,20(%ecx) 3840967373eSDavid Greenman movl 24(%esp),%eax 3850967373eSDavid Greenman movl %eax,24(%ecx) 3860967373eSDavid Greenman1: 3870967373eSDavid Greenman xorl %eax,%eax /* return 0 */ 3880967373eSDavid Greenman ret 3890967373eSDavid Greenman 3900967373eSDavid Greenman/* 3910967373eSDavid Greenman * addupc(int pc, struct uprof *up, int ticks): 3920967373eSDavid Greenman * update profiling information for the user process. 3930967373eSDavid Greenman */ 3940967373eSDavid GreenmanENTRY(addupc) 3950967373eSDavid Greenman pushl %ebp 3960967373eSDavid Greenman movl %esp,%ebp 3970967373eSDavid Greenman movl 12(%ebp),%edx /* up */ 3980967373eSDavid Greenman movl 8(%ebp),%eax /* pc */ 3990967373eSDavid Greenman 4000967373eSDavid Greenman subl PR_OFF(%edx),%eax /* pc -= up->pr_off */ 4010967373eSDavid Greenman jl L1 /* if (pc < 0) return */ 4020967373eSDavid Greenman 4030967373eSDavid Greenman shrl $1,%eax /* praddr = pc >> 1 */ 4040967373eSDavid Greenman imull PR_SCALE(%edx),%eax /* praddr *= up->pr_scale */ 4050967373eSDavid Greenman shrl $15,%eax /* praddr = praddr << 15 */ 4060967373eSDavid Greenman andl $-2,%eax /* praddr &= ~1 */ 4070967373eSDavid Greenman 4080967373eSDavid Greenman cmpl PR_SIZE(%edx),%eax /* if (praddr > up->pr_size) return */ 4090967373eSDavid Greenman ja L1 4100967373eSDavid Greenman 4110967373eSDavid Greenman/* addl %eax,%eax /* praddr -> word offset */ 4120967373eSDavid Greenman addl PR_BASE(%edx),%eax /* praddr += up-> pr_base */ 4130967373eSDavid Greenman movl 16(%ebp),%ecx /* ticks */ 4140967373eSDavid Greenman 4150967373eSDavid Greenman movl _curpcb,%edx 4160967373eSDavid Greenman movl $proffault,PCB_ONFAULT(%edx) 4170967373eSDavid Greenman addl %ecx,(%eax) /* storage location += ticks */ 4180967373eSDavid Greenman movl $0,PCB_ONFAULT(%edx) 4190967373eSDavid GreenmanL1: 4200967373eSDavid Greenman leave 4210967373eSDavid Greenman ret 4220967373eSDavid Greenman 4230967373eSDavid Greenman ALIGN_TEXT 4240967373eSDavid Greenmanproffault: 4250967373eSDavid Greenman /* if we get a fault, then kill profiling all together */ 4260967373eSDavid Greenman movl $0,PCB_ONFAULT(%edx) /* squish the fault handler */ 4270967373eSDavid Greenman movl 12(%ebp),%ecx 4280967373eSDavid Greenman movl $0,PR_SCALE(%ecx) /* up->pr_scale = 0 */ 4290967373eSDavid Greenman leave 4300967373eSDavid Greenman ret 4310967373eSDavid Greenman 4320967373eSDavid Greenman/* To be done: */ 4330967373eSDavid GreenmanENTRY(astoff) 4340967373eSDavid Greenman ret 4350967373eSDavid Greenman 436