0967373e1c
when the machine panics. i386/i386/locore.s: 1) got rid of most .set directives that were being used like #define's, and replaced them with appropriate #define's in the appropriate header files (accessed via genassym). 2) added comments to header inclusions and global definitions, and global variables 3) replaced some hardcoded constants with cpp defines (such as PDESIZE and others) 4) aligned all comments to the same column to make them easier to read 5) moved macro definitions for ENTRY, ALIGN, NOP, etc. to /sys/i386/include/asmacros.h 6) added #ifdef BDE_DEBUGGER around all of Bruce's debugger code 7) added new global '_KERNend' to store last location+1 of kernel 8) cleaned up zeroing of bss so that only bss is zeroed 9) fix zeroing of page tables so that it really does zero them all - not just if they follow the bss. 10) rewrote page table initialization code so that 1) works correctly and 2) write protects the kernel text by default 11) properly initialize the kernel page directory, upages, p0stack PT, and page tables. The previous scheme was more than a bit screwy. 12) change allocation of virtual area of IO hole so that it is fixed at KERNBASE + 0xa0000. The previous scheme put it right after the kernel page tables and then later expected it to be at KERNBASE +0xa0000 13) change multiple bogus settings of user read/write of various areas of kernel VM - including the IO hole; we should never be accessing the IO hole in user mode through the kernel page tables 14) split kernel support routines such as bcopy, bzero, copyin, copyout, etc. into a seperate file 'support.s' 15) split swtch and related routines into a seperate 'swtch.s' 16) split routines related to traps, syscalls, and interrupts into a seperate file 'exception.s' 17) remove some unused global variables from locore that got inserted by Garrett when he pulled them out of some .h files. i386/isa/icu.s: 1) clean up global variable declarations 2) move in declaration of astpending and netisr i386/i386/pmap.c: 1) fix calculation of virtual_avail. It previously was calculated to be right in the middle of the kernel page tables - not a good place to start allocating kernel VM. 2) properly allocate kernel page dir/tables etc out of kernel map - previously only took out 2 pages. i386/i386/machdep.c: 1) modify boot() to print a warning that the system will reboot in PANIC_REBOOT_WAIT_TIME amount of seconds, and let the user abort with a key on the console. The machine will wait for ever if a key is typed before the reboot. The default is 15 seconds, but can be set to 0 to mean don't wait at all, -1 to mean wait forever, or any positive value to wait for that many seconds. 2) print "Rebooting..." just before doing it. kern/subr_prf.c: 1) remove PANICWAIT as it is deprecated by the change to machdep.c i386/i386/trap.c: 1) add table of trap type strings and use it to print a real trap/ panic message rather than just a number. Lot's of work to be done here, but this is the first step. Symbolic traceback is in the TODO. i386/i386/Makefile.i386: 1) add support in to build support.s, exception.s and swtch.s ...and various changes to various header files to make all of the above happen.
386 lines
8.9 KiB
ArmAsm
386 lines
8.9 KiB
ArmAsm
/*-
|
|
* Copyright (c) 1989, 1990 William F. Jolitz.
|
|
* 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.
|
|
*
|
|
* @(#)icu.s 7.2 (Berkeley) 5/21/91
|
|
*
|
|
* $Id: icu.s,v 1.3 1993/09/06 16:12:03 rgrimes Exp $
|
|
*/
|
|
|
|
/*
|
|
* AT/386
|
|
* Vector interrupt control section
|
|
*/
|
|
|
|
/*
|
|
* XXX - this file is now misnamed. All spls are now soft and the only thing
|
|
* related to the hardware icu is that the bit numbering is the same in the
|
|
* soft priority masks as in the hard ones.
|
|
*/
|
|
|
|
#include "sio.h"
|
|
#define HIGHMASK 0xffff
|
|
#define SOFTCLOCKMASK 0x8000
|
|
|
|
.data
|
|
|
|
.globl _cpl
|
|
_cpl: .long 0xffff /* current priority (all off) */
|
|
|
|
.globl _imen
|
|
_imen: .long 0xffff /* interrupt mask enable (all off) */
|
|
|
|
/* .globl _highmask */
|
|
_highmask: .long HIGHMASK
|
|
|
|
.globl _ttymask, _biomask, _netmask
|
|
_ttymask: .long 0
|
|
_biomask: .long 0
|
|
_netmask: .long 0
|
|
|
|
.globl _ipending, _astpending
|
|
_ipending: .long 0
|
|
_astpending: .long 0 /* tells us an AST needs to be taken */
|
|
|
|
.globl _netisr
|
|
_netisr: .long 0 /* set with bits for which queue to service */
|
|
|
|
vec:
|
|
.long vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7
|
|
.long vec8, vec9, vec10, vec11, vec12, vec13, vec14, vec15
|
|
|
|
#define GENSPL(name, mask, event) \
|
|
.globl _spl/**/name ; \
|
|
ALIGN_TEXT ; \
|
|
_spl/**/name: ; \
|
|
COUNT_EVENT(_intrcnt_spl, event) ; \
|
|
movl _cpl,%eax ; \
|
|
movl %eax,%edx ; \
|
|
orl mask,%edx ; \
|
|
movl %edx,_cpl ; \
|
|
SHOW_CPL ; \
|
|
ret
|
|
|
|
#define FASTSPL(mask) \
|
|
movl mask,_cpl ; \
|
|
SHOW_CPL
|
|
|
|
#define FASTSPL_VARMASK(varmask) \
|
|
movl varmask,%eax ; \
|
|
movl %eax,_cpl ; \
|
|
SHOW_CPL
|
|
|
|
.text
|
|
|
|
ALIGN_TEXT
|
|
unpend_v:
|
|
COUNT_EVENT(_intrcnt_spl, 0)
|
|
bsfl %eax,%eax # slow, but not worth optimizing
|
|
btrl %eax,_ipending
|
|
jnc unpend_v_next # some intr cleared the in-memory bit
|
|
SHOW_IPENDING
|
|
movl Vresume(,%eax,4),%eax
|
|
testl %eax,%eax
|
|
je noresume
|
|
jmp %eax
|
|
|
|
ALIGN_TEXT
|
|
/*
|
|
* XXX - must be some fastintr, need to register those too.
|
|
*/
|
|
noresume:
|
|
#if NSIO > 0
|
|
call _softsio1
|
|
#endif
|
|
unpend_v_next:
|
|
movl _cpl,%eax
|
|
movl %eax,%edx
|
|
notl %eax
|
|
andl _ipending,%eax
|
|
je none_to_unpend
|
|
jmp unpend_v
|
|
|
|
/*
|
|
* Handle return from interrupt after device handler finishes
|
|
*/
|
|
ALIGN_TEXT
|
|
doreti:
|
|
COUNT_EVENT(_intrcnt_spl, 1)
|
|
addl $4,%esp # discard unit arg
|
|
popl %eax # get previous priority
|
|
/*
|
|
* Now interrupt frame is a trap frame!
|
|
*
|
|
* XXX - setting up the interrupt frame to be almost a stack frame is mostly
|
|
* a waste of time.
|
|
*/
|
|
movl %eax,_cpl
|
|
SHOW_CPL
|
|
movl %eax,%edx
|
|
notl %eax
|
|
andl _ipending,%eax
|
|
jne unpend_v
|
|
none_to_unpend:
|
|
testl %edx,%edx # returning to zero priority?
|
|
jne 1f # nope, going to non-zero priority
|
|
movl _netisr,%eax
|
|
testl %eax,%eax # check for softint s/traps
|
|
jne 2f # there are some
|
|
jmp test_resched # XXX - schedule jumps better
|
|
COUNT_EVENT(_intrcnt_spl, 2) # XXX
|
|
|
|
ALIGN_TEXT # XXX
|
|
1: # XXX
|
|
COUNT_EVENT(_intrcnt_spl, 3)
|
|
popl %es
|
|
popl %ds
|
|
popal
|
|
addl $8,%esp
|
|
iret
|
|
|
|
#include "../net/netisr.h"
|
|
|
|
#define DONET(s, c, event) ; \
|
|
.globl c ; \
|
|
btrl $s,_netisr ; \
|
|
jnc 1f ; \
|
|
COUNT_EVENT(_intrcnt_spl, event) ; \
|
|
call c ; \
|
|
1:
|
|
|
|
ALIGN_TEXT
|
|
2:
|
|
COUNT_EVENT(_intrcnt_spl, 4)
|
|
/*
|
|
* XXX - might need extra locking while testing reg copy of netisr, but
|
|
* interrupt routines setting it would not cause any new problems (since we
|
|
* don't loop, fresh bits will not be processed until the next doreti or spl0).
|
|
*/
|
|
testl $~((1 << NETISR_SCLK) | (1 << NETISR_AST)),%eax
|
|
je test_ASTs # no net stuff, just temporary AST's
|
|
FASTSPL_VARMASK(_netmask)
|
|
DONET(NETISR_RAW, _rawintr, 5)
|
|
|
|
#ifdef INET
|
|
DONET(NETISR_IP, _ipintr, 6)
|
|
#endif /* INET */
|
|
|
|
#ifdef IMP
|
|
DONET(NETISR_IMP, _impintr, 7)
|
|
#endif /* IMP */
|
|
|
|
#ifdef NS
|
|
DONET(NETISR_NS, _nsintr, 8)
|
|
#endif /* NS */
|
|
|
|
#ifdef ISO
|
|
DONET(NETISR_ISO, _clnlintr, 9)
|
|
#endif /* ISO */
|
|
|
|
FASTSPL($0)
|
|
test_ASTs:
|
|
btrl $NETISR_SCLK,_netisr
|
|
jnc test_resched
|
|
COUNT_EVENT(_intrcnt_spl, 10)
|
|
FASTSPL($SOFTCLOCKMASK)
|
|
/*
|
|
* Back to an interrupt frame for a moment.
|
|
*/
|
|
pushl $0 # previous cpl (probably not used)
|
|
pushl $0x7f # dummy unit number
|
|
call _softclock
|
|
addl $8,%esp # discard dummies
|
|
FASTSPL($0)
|
|
test_resched:
|
|
#ifdef notused1
|
|
btrl $NETISR_AST,_netisr
|
|
jnc 2f
|
|
#endif
|
|
#ifdef notused2
|
|
cmpl $0,_want_resched
|
|
je 2f
|
|
#endif
|
|
cmpl $0,_astpending # XXX - put it back in netisr to
|
|
je 2f # reduce the number of tests
|
|
testb $SEL_RPL_MASK,TRAPF_CS_OFF(%esp)
|
|
# to non-kernel (i.e., user)?
|
|
je 2f # nope, leave
|
|
COUNT_EVENT(_intrcnt_spl, 11)
|
|
movl $0,_astpending
|
|
call _trap
|
|
2:
|
|
COUNT_EVENT(_intrcnt_spl, 12)
|
|
popl %es
|
|
popl %ds
|
|
popal
|
|
addl $8,%esp
|
|
iret
|
|
|
|
/*
|
|
* Interrupt priority mechanism
|
|
* -- soft splXX masks with group mechanism (cpl)
|
|
* -- h/w masks for currently active or unused interrupts (imen)
|
|
* -- ipending = active interrupts currently masked by cpl
|
|
*/
|
|
|
|
GENSPL(bio, _biomask, 13)
|
|
GENSPL(clock, $HIGHMASK, 14) /* splclock == splhigh ex for count */
|
|
GENSPL(high, $HIGHMASK, 15)
|
|
GENSPL(imp, _netmask, 16) /* splimp == splnet except for count */
|
|
GENSPL(net, _netmask, 17)
|
|
GENSPL(softclock, $SOFTCLOCKMASK, 18)
|
|
GENSPL(tty, _ttymask, 19)
|
|
|
|
.globl _splnone
|
|
.globl _spl0
|
|
ALIGN_TEXT
|
|
_splnone:
|
|
_spl0:
|
|
COUNT_EVENT(_intrcnt_spl, 20)
|
|
in_spl0:
|
|
movl _cpl,%eax
|
|
pushl %eax # save old priority
|
|
testl $(1 << NETISR_RAW) | (1 << NETISR_IP),_netisr
|
|
je over_net_stuff_for_spl0
|
|
movl _netmask,%eax # mask off those network devices
|
|
movl %eax,_cpl # set new priority
|
|
SHOW_CPL
|
|
/*
|
|
* XXX - what about other net intrs?
|
|
*/
|
|
DONET(NETISR_RAW, _rawintr, 21)
|
|
|
|
#ifdef INET
|
|
DONET(NETISR_IP, _ipintr, 22)
|
|
#endif /* INET */
|
|
|
|
#ifdef IMP
|
|
DONET(NETISR_IMP, _impintr, 23)
|
|
#endif /* IMP */
|
|
|
|
#ifdef NS
|
|
DONET(NETISR_NS, _nsintr, 24)
|
|
#endif /* NS */
|
|
|
|
#ifdef ISO
|
|
DONET(NETISR_ISO, _clnlintr, 25)
|
|
#endif /* ISO */
|
|
|
|
over_net_stuff_for_spl0:
|
|
movl $0,_cpl # set new priority
|
|
SHOW_CPL
|
|
movl _ipending,%eax
|
|
testl %eax,%eax
|
|
jne unpend_V
|
|
popl %eax # return old priority
|
|
ret
|
|
|
|
.globl _splx
|
|
ALIGN_TEXT
|
|
_splx:
|
|
COUNT_EVENT(_intrcnt_spl, 26)
|
|
movl 4(%esp),%eax # new priority
|
|
testl %eax,%eax
|
|
je in_spl0 # going to "zero level" is special
|
|
COUNT_EVENT(_intrcnt_spl, 27)
|
|
movl _cpl,%edx # save old priority
|
|
movl %eax,_cpl # set new priority
|
|
SHOW_CPL
|
|
notl %eax
|
|
andl _ipending,%eax
|
|
jne unpend_V_result_edx
|
|
movl %edx,%eax # return old priority
|
|
ret
|
|
|
|
ALIGN_TEXT
|
|
unpend_V_result_edx:
|
|
pushl %edx
|
|
unpend_V:
|
|
COUNT_EVENT(_intrcnt_spl, 28)
|
|
bsfl %eax,%eax
|
|
btrl %eax,_ipending
|
|
jnc unpend_V_next
|
|
SHOW_IPENDING
|
|
movl Vresume(,%eax,4),%edx
|
|
testl %edx,%edx
|
|
je noresumeV
|
|
/*
|
|
* We would prefer to call the intr handler directly here but that doesn't
|
|
* work for badly behaved handlers that want the interrupt frame. Also,
|
|
* there's a problem determining the unit number. We should change the
|
|
* interface so that the unit number is not determined at config time.
|
|
*/
|
|
jmp *vec(,%eax,4)
|
|
|
|
ALIGN_TEXT
|
|
/*
|
|
* XXX - must be some fastintr, need to register those too.
|
|
*/
|
|
noresumeV:
|
|
#if NSIO > 0
|
|
call _softsio1
|
|
#endif
|
|
unpend_V_next:
|
|
movl _cpl,%eax
|
|
notl %eax
|
|
andl _ipending,%eax
|
|
jne unpend_V
|
|
popl %eax
|
|
ret
|
|
|
|
#define BUILD_VEC(irq_num) \
|
|
ALIGN_TEXT ; \
|
|
vec/**/irq_num: ; \
|
|
int $ICU_OFFSET + (irq_num) ; \
|
|
popl %eax ; \
|
|
ret
|
|
|
|
BUILD_VEC(0)
|
|
BUILD_VEC(1)
|
|
BUILD_VEC(2)
|
|
BUILD_VEC(3)
|
|
BUILD_VEC(4)
|
|
BUILD_VEC(5)
|
|
BUILD_VEC(6)
|
|
BUILD_VEC(7)
|
|
BUILD_VEC(8)
|
|
BUILD_VEC(9)
|
|
BUILD_VEC(10)
|
|
BUILD_VEC(11)
|
|
BUILD_VEC(12)
|
|
BUILD_VEC(13)
|
|
BUILD_VEC(14)
|
|
BUILD_VEC(15)
|