0ca3609e30
headers in .S directly rather than getting to their macros through genassym.c/assym.s so there are less headers genassym.c has to be kept in sync with. While at it fix some stytle(9) bugs (indentation, prototype format, sort headers, etc) and remove trailing whitespace.
206 lines
6.2 KiB
ArmAsm
206 lines
6.2 KiB
ArmAsm
/*-
|
|
* Copyright (c) 2002 Jake Burkholder.
|
|
* All rights reserved.
|
|
*
|
|
* 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.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
|
*/
|
|
|
|
#include <machine/asm.h>
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
#include <machine/asi.h>
|
|
#include <machine/asmacros.h>
|
|
#include <machine/intr_machdep.h>
|
|
#include <machine/ktr.h>
|
|
#include <machine/pstate.h>
|
|
|
|
#include "assym.s"
|
|
|
|
/*
|
|
* Handle a vectored interrupt.
|
|
*
|
|
* This is either a data bearing mondo vector interrupt, or a cross trap
|
|
* request from another cpu. In either case the hardware supplies an
|
|
* interrupt packet, in the form of 3 data words which are read from internal
|
|
* registers. A data bearing mondo vector packet consists of an interrupt
|
|
* number in the first data word, and zero in 2nd and 3rd. We use the
|
|
* interrupt number to find the function, argument and priority from the
|
|
* intr_vector table, allocate and fill in an intr_request from the per-cpu
|
|
* free list, link it onto the per-cpu active list and finally post a softint
|
|
* at the desired priority. Cross trap requests come in 2 forms, direct
|
|
* and queued. Direct requests are distinguished by the first data word
|
|
* being zero. The 2nd data word carries a function to call and the 3rd
|
|
* an argument to pass. The function is jumped to directly. It executes
|
|
* in nucleus context on interrupt globals and with all interrupts disabled,
|
|
* therefore it must be fast, and the things that it can do are limited.
|
|
* Queued cross trap requests are handled much like mondo vectors, except
|
|
* that the function, argument and priority are contained in the interrupt
|
|
* packet itself. They are distinguished by the upper 4 bits of the data
|
|
* word being non-zero, which specifies the priority of the softint to
|
|
* deliver.
|
|
*
|
|
* Register usage:
|
|
* %g1 - pointer to intr_request
|
|
* %g2 - pointer to intr_vector, temp once required data is loaded
|
|
* %g3 - interrupt number for mondo vectors, unused otherwise
|
|
* %g4 - function, from the interrupt packet for cross traps, or
|
|
* loaded from the interrupt registers for mondo vecors
|
|
* %g5 - argument, as above for %g4
|
|
* %g6 - softint priority
|
|
*/
|
|
ENTRY(intr_vector)
|
|
/*
|
|
* Load the interrupt packet from the hardware.
|
|
*/
|
|
wr %g0, ASI_SDB_INTR_R, %asi
|
|
ldxa [%g0 + AA_SDB_INTR_D0] %asi, %g3
|
|
ldxa [%g0 + AA_SDB_INTR_D1] %asi, %g4
|
|
ldxa [%g0 + AA_SDB_INTR_D2] %asi, %g5
|
|
stxa %g0, [%g0] ASI_INTR_RECEIVE
|
|
membar #Sync
|
|
|
|
/*
|
|
* If the first data word is zero this is a direct cross trap request.
|
|
* The 2nd word points to code to execute and the 3rd is an argument
|
|
* to pass. Jump to it.
|
|
*/
|
|
brnz,a,pt %g3, 1f
|
|
nop
|
|
jmpl %g4, %g0
|
|
nop
|
|
/* NOTREACHED */
|
|
|
|
/*
|
|
* If the high 4 bits of the 1st data word are non-zero, this is a
|
|
* queued cross trap request to be delivered as a softint. The high
|
|
* 4 bits of the 1st data word specify a priority, and the 2nd and
|
|
* 3rd a function and argument.
|
|
*/
|
|
1: srlx %g3, 60, %g6
|
|
brnz,a,pn %g6, 2f
|
|
clr %g3
|
|
|
|
/*
|
|
* Find the function, argument and desired priority from the
|
|
* intr_vector table.
|
|
*/
|
|
SET(intr_vectors, %g4, %g2)
|
|
sllx %g3, IV_SHIFT, %g4
|
|
add %g2, %g4, %g2
|
|
|
|
ldx [%g2 + IV_FUNC], %g4
|
|
ldx [%g2 + IV_ARG], %g5
|
|
lduw [%g2 + IV_PRI], %g6
|
|
|
|
/*
|
|
* Get an intr_request from the free list. There should always be one
|
|
* unless we are getting an interrupt storm from stray interrupts, in
|
|
* which case the we will deference a NULL pointer and panic.
|
|
*/
|
|
2: ldx [PCPU(IRFREE)], %g1
|
|
ldx [%g1 + IR_NEXT], %g2
|
|
stx %g2, [PCPU(IRFREE)]
|
|
|
|
/*
|
|
* Store the vector number, function, argument and priority.
|
|
*/
|
|
stw %g3, [%g1 + IR_VEC]
|
|
stx %g4, [%g1 + IR_FUNC]
|
|
stx %g5, [%g1 + IR_ARG]
|
|
stw %g6, [%g1 + IR_PRI]
|
|
|
|
/*
|
|
* Link it onto the end of the active list.
|
|
*/
|
|
stx %g0, [%g1 + IR_NEXT]
|
|
ldx [PCPU(IRTAIL)], %g4
|
|
stx %g1, [%g4]
|
|
add %g1, IR_NEXT, %g1
|
|
stx %g1, [PCPU(IRTAIL)]
|
|
|
|
/*
|
|
* Trigger a softint at the level indicated by the priority.
|
|
*/
|
|
mov 1, %g1
|
|
sllx %g1, %g6, %g1
|
|
wr %g1, 0, %set_softint
|
|
|
|
/*
|
|
* Done, retry the instruction.
|
|
*/
|
|
retry
|
|
END(intr_vector)
|
|
|
|
ENTRY(intr_fast)
|
|
save %sp, -CCFSZ, %sp
|
|
|
|
/*
|
|
* Disable interrupts while we fiddle with the interrupt request lists
|
|
* as interrupts at levels higher than what got us here aren't blocked.
|
|
*/
|
|
1: wrpr %g0, PSTATE_NORMAL, %pstate
|
|
|
|
ldx [PCPU(IRHEAD)], %l0
|
|
brnz,a,pt %l0, 2f
|
|
nop
|
|
|
|
wrpr %g0, PSTATE_KERNEL, %pstate
|
|
|
|
ret
|
|
restore
|
|
|
|
2: ldx [%l0 + IR_NEXT], %l1
|
|
brnz,pt %l1, 3f
|
|
stx %l1, [PCPU(IRHEAD)]
|
|
PCPU_ADDR(IRHEAD, %l1)
|
|
stx %l1, [PCPU(IRTAIL)]
|
|
|
|
3: ldx [%l0 + IR_FUNC], %o0
|
|
ldx [%l0 + IR_ARG], %o1
|
|
lduw [%l0 + IR_VEC], %o2
|
|
|
|
ldx [PCPU(IRFREE)], %l1
|
|
stx %l1, [%l0 + IR_NEXT]
|
|
stx %l0, [PCPU(IRFREE)]
|
|
|
|
wrpr %g0, PSTATE_KERNEL, %pstate
|
|
|
|
KASSERT(%o0, "intr_fast: ir_func null")
|
|
call %o0
|
|
mov %o1, %o0
|
|
|
|
/* intrcnt[intr_countp[%o2]]++ */
|
|
SET(intrcnt, %l7, %l2) /* %l2 = intrcnt */
|
|
prefetcha [%l2] ASI_N, 1
|
|
SET(intr_countp, %l7, %l3) /* %l3 = intr_countp */
|
|
sllx %o2, 1, %l4 /* %l4 = vec << 1 */
|
|
lduh [%l4 + %l3], %l5 /* %l5 = intr_countp[%o2] */
|
|
sllx %l5, 3, %l6 /* %l6 = intr_countp[%o2] << 3 */
|
|
add %l6, %l2, %l7 /* %l7 = intrcnt[intr_countp[%o2]] */
|
|
ldx [%l7], %l2
|
|
inc %l2
|
|
stx %l2, [%l7]
|
|
|
|
ba,a %xcc, 1b
|
|
nop
|
|
END(intr_fast)
|