diff options
author | Steve Passe <fsmp@FreeBSD.org> | 1997-08-24 00:05:37 +0000 |
---|---|---|
committer | Steve Passe <fsmp@FreeBSD.org> | 1997-08-24 00:05:37 +0000 |
commit | 886e789627610009bb880256851ac358e0be8a79 (patch) | |
tree | 208e418cfc0371d581622ab7c5d3d2201f0b4529 /sys/i386/isa/apic_ipl.s | |
parent | a89989b26f18285a92fb372157c8af79987599cb (diff) | |
download | src-886e789627610009bb880256851ac358e0be8a79.tar.gz src-886e789627610009bb880256851ac358e0be8a79.zip |
The last of the encapsolation of cpl/spl/ipending things into a critical
region protected by the simplelock 'cpl_lock'.
Notes:
- this code is currently controlled on a section by section basis with
defines in machine/param.h. All sections are currently enabled.
- this code is not as clean as I would like, but that can wait till later.
- the "giant lock" still surrounds most instances of this "cpl region".
I still have to do the code that arbitrates setting cpl between the
top and bottom halves of the kernel.
- the possibility of deadlock exists, I am committing the code at this
point so as to exercise it and detect any such cases B4 the "giant lock"
is removed.
Notes
Notes:
svn path=/head/; revision=28641
Diffstat (limited to 'sys/i386/isa/apic_ipl.s')
-rw-r--r-- | sys/i386/isa/apic_ipl.s | 113 |
1 files changed, 87 insertions, 26 deletions
diff --git a/sys/i386/isa/apic_ipl.s b/sys/i386/isa/apic_ipl.s index a36c4decc7f2..ec9b94fb2f8d 100644 --- a/sys/i386/isa/apic_ipl.s +++ b/sys/i386/isa/apic_ipl.s @@ -22,13 +22,29 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: apic_ipl.s,v 1.23 1997/08/21 04:52:30 smp Exp smp $ + * $Id: apic_ipl.s,v 1.28 1997/08/23 05:15:12 smp Exp smp $ */ +#if defined(SMP) && defined(REAL_AICPL) + +#define AICPL_LOCK SCPL_LOCK +#define AICPL_UNLOCK SCPL_UNLOCK + +#else /* SMP */ + +#define AICPL_LOCK +#define AICPL_UNLOCK + +#endif /* SMP */ + .data ALIGN_DATA +/* current INTerrupt level */ + .globl _cil +_cil: .long 0 + /* this allows us to change the 8254 APIC pin# assignment */ .globl _Xintr8254 _Xintr8254: @@ -46,31 +62,6 @@ _vec: .long vec8, vec9, vec10, vec11, vec12, vec13, vec14, vec15 .long vec16, vec17, vec18, vec19, vec20, vec21, vec22, vec23 -/* various simple locks */ - .align 2 /* MUST be 32bit aligned */ - -#if 0 -/* critical region around IO APIC */ - .globl _imen_lock -_imen_lock: - .long 0 - -/* critical region around spl & cpl */ - .globl _cpl_lock -_cpl_lock: - .long 0 - -/* critical region around FAST_INTR() routines */ - .globl _fast_intr_lock -_fast_intr_lock: - .long 0 - -/* critical region around INTR() routines */ - .globl _intr_lock -_intr_lock: - .long 0 -#endif - /* * Note: * This is the UP equivilant of _imen. @@ -83,10 +74,12 @@ _intr_lock: * MAYBE_UNMASK_IRQ * imen_dump() */ + .align 2 /* MUST be 32bit aligned */ .globl _apic_imen _apic_imen: .long HWI_MASK + /* * */ @@ -94,6 +87,74 @@ _apic_imen: SUPERALIGN_TEXT /* + * 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 + */ + +ENTRY(splz) + /* + * The caller has restored cpl and checked that (ipending & ~cpl) + * is nonzero. We have to repeat the check since if there is an + * interrupt while we're looking, _doreti processing for the + * interrupt will handle all the unmasked pending interrupts + * because we restored early. We're repeating the calculation + * of (ipending & ~cpl) anyway so that the caller doesn't have + * to pass it, so this only costs one "jne". "bsfl %ecx,%ecx" + * is undefined when %ecx is 0 so we can't rely on the secondary + * btrl tests. + */ + AICPL_LOCK + movl _cpl,%eax +splz_next: + /* + * We don't need any locking here. (ipending & ~cpl) cannot grow + * while we're looking at it - any interrupt will shrink it to 0. + */ + movl %eax,%ecx + notl %ecx /* set bit = unmasked level */ + andl _ipending,%ecx /* set bit = unmasked pending INT */ + jne splz_unpend + AICPL_UNLOCK + ret + + ALIGN_TEXT +splz_unpend: + bsfl %ecx,%ecx + lock + btrl %ecx, _ipending + jnc splz_next + movl ihandlers(,%ecx,4),%edx + testl %edx,%edx + je splz_next /* "can't happen" */ + cmpl $NHWI,%ecx + jae splz_swi + AICPL_UNLOCK + /* + * 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(,%ecx,4) + + ALIGN_TEXT +splz_swi: + cmpl $SWI_AST,%ecx + je splz_next /* "can't happen" */ + pushl %eax + orl imasks(,%ecx,4),%eax + movl %eax,_cpl + AICPL_UNLOCK + call %edx + AICPL_LOCK + popl %eax + movl %eax,_cpl + jmp splz_next + +/* * Fake clock interrupt(s) so that they appear to come from our caller instead * of from here, so that system profiling works. * XXX do this more generally (for all vectors; look up the C entry point). |