7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * CDDL HEADER START
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases *
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * The contents of this file are subject to the terms of the
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Common Development and Distribution License (the "License").
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * You may not use this file except in compliance with the License.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases *
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * or http://www.opensolaris.org/os/licensing.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * See the License for the specific language governing permissions
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * and limitations under the License.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases *
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * When distributing Covered Code, include this CDDL HEADER in each
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * If applicable, add the following below this CDDL HEADER, with the
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * fields enclosed by brackets "[]" replaced with your own identifying
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * information: Portions Copyright [yyyy] [name of copyright owner]
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases *
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * CDDL HEADER END
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/cpuvar.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/cpu_event.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/param.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/cmn_err.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/t_lock.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/kmem.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/machlock.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/systm.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/archsystm.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/atomic.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/sdt.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/processor.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/time.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/psm.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/smp_impldefs.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/cram.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/apic.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/pit.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/ddi.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/sunddi.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/ddi_impldefs.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/pci.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/promif.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/x86_archext.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/cpc_impl.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/uadmin.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/panic.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/debug.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/trap.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/machsystm.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/sysmacros.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/rm_platter.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/privregs.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/note.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/pci_intr_lib.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/spl.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/clock.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/dditypes.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/sunddi.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/x_call.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/reboot.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <vm/hat_i86.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/stack.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#include <sys/apix.h>
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic void apix_post_hardint(int);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Insert an vector into the tail of the interrupt pending list
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic __inline__ void
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapix_insert_pending_av(apix_impl_t *apixp, struct autovec *avp, int ipl)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases struct autovec **head = apixp->x_intr_head;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases struct autovec **tail = apixp->x_intr_tail;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases avp->av_ipl_link = NULL;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (tail[ipl] == NULL) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases head[ipl] = tail[ipl] = avp;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases tail[ipl]->av_ipl_link = avp;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases tail[ipl] = avp;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Remove and return an vector from the head of hardware interrupt
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * pending list.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic __inline__ struct autovec *
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapix_remove_pending_av(apix_impl_t *apixp, int ipl)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases struct cpu *cpu = CPU;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases struct autovec **head = apixp->x_intr_head;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases struct autovec **tail = apixp->x_intr_tail;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases struct autovec *avp = head[ipl];
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (avp == NULL)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (NULL);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (avp->av_vector != NULL && avp->av_prilevel < cpu->cpu_base_spl) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * If there is blocked higher level interrupts, return
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * NULL to quit handling of current IPL level.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apixp->x_intr_pending |= (1 << avp->av_prilevel);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (NULL);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases avp->av_flags &= ~AV_PENTRY_PEND;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases avp->av_flags |= AV_PENTRY_ONPROC;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases head[ipl] = avp->av_ipl_link;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases avp->av_ipl_link = NULL;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (head[ipl] == NULL)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases tail[ipl] = NULL;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (avp);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * add_pending_hardint:
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases *
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Add hardware interrupts to the interrupt pending list.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic void
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapix_add_pending_hardint(int vector)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases uint32_t cpuid = psm_get_cpu_id();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_impl_t *apixp = apixs[cpuid];
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_vector_t *vecp = apixp->x_vectbl[vector];
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases struct autovec *p, *prevp = NULL;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int ipl;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * The MSI interrupt not supporting per-vector masking could
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * be triggered on a false vector as a result of rebinding
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * operation cannot programme MSI address & data atomically.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Add ISR of this interrupt to the pending list for such
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * suspicious interrupt.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases APIX_DO_FAKE_INTR(cpuid, vector);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (vecp == NULL)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases for (p = vecp->v_autovect; p != NULL; p = p->av_link) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (p->av_vector == NULL)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases continue; /* skip freed entry */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ipl = p->av_prilevel;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases prevp = p;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* set pending at specified priority level */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apixp->x_intr_pending |= (1 << ipl);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (p->av_flags & AV_PENTRY_PEND)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases continue; /* already in the pending list */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases p->av_flags |= AV_PENTRY_PEND;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* insert into pending list by it original IPL */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_insert_pending_av(apixp, p, ipl);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* last one of the linked list */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (prevp && ((prevp->av_flags & AV_PENTRY_LEVEL) != 0))
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases prevp->av_flags |= (vector & AV_PENTRY_VECTMASK);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Walk pending hardware interrupts at given priority level, invoking
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * each interrupt handler as we go.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesextern uint64_t intr_get_time(void);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic void
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapix_dispatch_pending_autovect(uint_t ipl)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases uint32_t cpuid = psm_get_cpu_id();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_impl_t *apixp = apixs[cpuid];
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases struct autovec *av;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases while ((av = apix_remove_pending_av(apixp, ipl)) != NULL) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases uint_t r;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases uint_t (*intr)() = av->av_vector;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases caddr_t arg1 = av->av_intarg1;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases caddr_t arg2 = av->av_intarg2;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases dev_info_t *dip = av->av_dip;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases uchar_t vector = av->av_flags & AV_PENTRY_VECTMASK;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (intr == NULL)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases continue;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* Don't enable interrupts during x-calls */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (ipl != XC_HI_PIL)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases sti();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases DTRACE_PROBE4(interrupt__start, dev_info_t *, dip,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases void *, intr, caddr_t, arg1, caddr_t, arg2);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases r = (*intr)(arg1, arg2);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases DTRACE_PROBE4(interrupt__complete, dev_info_t *, dip,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases void *, intr, caddr_t, arg1, uint_t, r);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (av->av_ticksp && av->av_prilevel <= LOCK_LEVEL)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases atomic_add_64(av->av_ticksp, intr_get_time());
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cli();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (vector) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if ((av->av_flags & AV_PENTRY_PEND) == 0)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases av->av_flags &= ~AV_PENTRY_VECTMASK;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_post_hardint(vector);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* mark it as idle */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases av->av_flags &= ~AV_PENTRY_ONPROC;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic caddr_t
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapix_do_softint_prolog(struct cpu *cpu, uint_t pil, uint_t oldpil,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases caddr_t stackptr)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases kthread_t *t, *volatile it;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases struct machcpu *mcpu = &cpu->cpu_m;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases hrtime_t now;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases UNREFERENCED_1PARAMETER(oldpil);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT(pil > mcpu->mcpu_pri && pil > cpu->cpu_base_spl);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases atomic_and_32((uint32_t *)&mcpu->mcpu_softinfo.st_pending, ~(1 << pil));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mcpu->mcpu_pri = pil;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases now = tsc_read();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Get set to run interrupt thread.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * There should always be an interrupt thread since we
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * allocate one for each level on the CPU.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases it = cpu->cpu_intr_thread;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT(it != NULL);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu->cpu_intr_thread = it->t_link;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* t_intr_start could be zero due to cpu_intr_swtch_enter. */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases t = cpu->cpu_thread;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if ((t->t_flag & T_INTR_THREAD) && t->t_intr_start != 0) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases hrtime_t intrtime = now - t->t_intr_start;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mcpu->intrstat[pil][0] += intrtime;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu->cpu_intracct[cpu->cpu_mstate] += intrtime;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases t->t_intr_start = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Note that the code in kcpc_overflow_intr -relies- on the
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * ordering of events here - in particular that t->t_lwp of
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * the interrupt thread is set to the pinned thread *before*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * curthread is changed.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases it->t_lwp = t->t_lwp;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases it->t_state = TS_ONPROC;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Push interrupted thread onto list from new thread.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Set the new thread as the current one.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Set interrupted thread's T_SP because if it is the idle thread,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * resume() may use that stack between threads.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT(SA((uintptr_t)stackptr) == (uintptr_t)stackptr);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases t->t_sp = (uintptr_t)stackptr;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases it->t_intr = t;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu->cpu_thread = it;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Set bit for this pil in CPU's interrupt active bitmask.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT((cpu->cpu_intr_actv & (1 << pil)) == 0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu->cpu_intr_actv |= (1 << pil);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Initialize thread priority level from intr_pri
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases it->t_pil = (uchar_t)pil;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases it->t_pri = (pri_t)pil + intr_pri;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases it->t_intr_start = now;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (it->t_stk);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic void
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapix_do_softint_epilog(struct cpu *cpu, uint_t oldpil)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases struct machcpu *mcpu = &cpu->cpu_m;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases kthread_t *t, *it;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases uint_t pil, basespl;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases hrtime_t intrtime;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases hrtime_t now = tsc_read();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases it = cpu->cpu_thread;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases pil = it->t_pil;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu->cpu_stats.sys.intr[pil - 1]++;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT(cpu->cpu_intr_actv & (1 << pil));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu->cpu_intr_actv &= ~(1 << pil);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases intrtime = now - it->t_intr_start;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mcpu->intrstat[pil][0] += intrtime;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu->cpu_intracct[cpu->cpu_mstate] += intrtime;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * If there is still an interrupted thread underneath this one
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * then the interrupt was never blocked and the return is
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * fairly simple. Otherwise it isn't.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if ((t = it->t_intr) == NULL) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Put thread back on the interrupt thread list.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * This was an interrupt thread, so set CPU's base SPL.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases set_base_spl();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* mcpu->mcpu_pri = cpu->cpu_base_spl; */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases it->t_state = TS_FREE;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases it->t_link = cpu->cpu_intr_thread;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu->cpu_intr_thread = it;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (void) splhigh();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases sti();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases swtch();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*NOTREACHED*/
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases panic("dosoftint_epilog: swtch returned");
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases it->t_link = cpu->cpu_intr_thread;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu->cpu_intr_thread = it;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases it->t_state = TS_FREE;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu->cpu_thread = t;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (t->t_flag & T_INTR_THREAD)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases t->t_intr_start = now;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases basespl = cpu->cpu_base_spl;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases pil = MAX(oldpil, basespl);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mcpu->mcpu_pri = pil;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Dispatch a soft interrupt
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic void
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapix_dispatch_softint(uint_t oldpil, uint_t arg2)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases struct cpu *cpu = CPU;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases UNREFERENCED_1PARAMETER(arg2);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases sti();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases av_dispatch_softvect((int)cpu->cpu_thread->t_pil);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cli();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Must run softint_epilog() on the interrupt thread stack, since
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * there may not be a return from it if the interrupt thread blocked.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_do_softint_epilog(cpu, oldpil);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Deliver any softints the current interrupt priority allows.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Called with interrupts disabled.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesint
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapix_do_softint(struct regs *regs)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases struct cpu *cpu = CPU;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int oldipl;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int newipl;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases volatile uint16_t pending;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases caddr_t newsp;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases while ((pending = cpu->cpu_softinfo.st_pending) != 0) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases newipl = bsrw_insn(pending);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases oldipl = cpu->cpu_pri;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (newipl <= oldipl || newipl <= cpu->cpu_base_spl)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (-1);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases newsp = apix_do_softint_prolog(cpu, newipl, oldipl,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (caddr_t)regs);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT(newsp != NULL);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases switch_sp_and_call(newsp, apix_dispatch_softint, oldipl, 0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic int
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapix_hilevel_intr_prolog(struct cpu *cpu, uint_t pil, uint_t oldpil,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases struct regs *rp)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases struct machcpu *mcpu = &cpu->cpu_m;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases hrtime_t intrtime;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases hrtime_t now = tsc_read();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_impl_t *apixp = apixs[cpu->cpu_id];
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases uint_t mask;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT(pil > mcpu->mcpu_pri && pil > cpu->cpu_base_spl);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (pil == CBE_HIGH_PIL) { /* 14 */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu->cpu_profile_pil = oldpil;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (USERMODE(rp->r_cs)) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu->cpu_profile_pc = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu->cpu_profile_upc = rp->r_pc;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu->cpu_cpcprofile_pc = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu->cpu_cpcprofile_upc = rp->r_pc;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } else {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu->cpu_profile_pc = rp->r_pc;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu->cpu_profile_upc = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu->cpu_cpcprofile_pc = rp->r_pc;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu->cpu_cpcprofile_upc = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mcpu->mcpu_pri = pil;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mask = cpu->cpu_intr_actv & CPU_INTR_ACTV_HIGH_LEVEL_MASK;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (mask != 0) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int nestpil;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * We have interrupted another high-level interrupt.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Load starting timestamp, compute interval, update
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * cumulative counter.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases nestpil = bsrw_insn((uint16_t)mask);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases intrtime = now -
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mcpu->pil_high_start[nestpil - (LOCK_LEVEL + 1)];
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mcpu->intrstat[nestpil][0] += intrtime;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu->cpu_intracct[cpu->cpu_mstate] += intrtime;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } else {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases kthread_t *t = cpu->cpu_thread;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * See if we are interrupting a low-level interrupt thread.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * If so, account for its time slice only if its time stamp
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * is non-zero.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if ((t->t_flag & T_INTR_THREAD) != 0 && t->t_intr_start != 0) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases intrtime = now - t->t_intr_start;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mcpu->intrstat[t->t_pil][0] += intrtime;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu->cpu_intracct[cpu->cpu_mstate] += intrtime;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases t->t_intr_start = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* store starting timestamp in CPu structure for this IPL */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mcpu->pil_high_start[pil - (LOCK_LEVEL + 1)] = now;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (pil == 15) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * To support reentrant level 15 interrupts, we maintain a
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * recursion count in the top half of cpu_intr_actv. Only
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * when this count hits zero do we clear the PIL 15 bit from
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * the lower half of cpu_intr_actv.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases uint16_t *refcntp = (uint16_t *)&cpu->cpu_intr_actv + 1;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (*refcntp)++;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu->cpu_intr_actv |= (1 << pil);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* clear pending ipl level bit */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apixp->x_intr_pending &= ~(1 << pil);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (mask);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic int
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapix_hilevel_intr_epilog(struct cpu *cpu, uint_t oldpil)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases struct machcpu *mcpu = &cpu->cpu_m;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases uint_t mask, pil;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases hrtime_t intrtime;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases hrtime_t now = tsc_read();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases pil = mcpu->mcpu_pri;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu->cpu_stats.sys.intr[pil - 1]++;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT(cpu->cpu_intr_actv & (1 << pil));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (pil == 15) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * To support reentrant level 15 interrupts, we maintain a
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * recursion count in the top half of cpu_intr_actv. Only
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * when this count hits zero do we clear the PIL 15 bit from
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * the lower half of cpu_intr_actv.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases uint16_t *refcntp = (uint16_t *)&cpu->cpu_intr_actv + 1;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT(*refcntp > 0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (--(*refcntp) == 0)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu->cpu_intr_actv &= ~(1 << pil);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } else {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu->cpu_intr_actv &= ~(1 << pil);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT(mcpu->pil_high_start[pil - (LOCK_LEVEL + 1)] != 0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases intrtime = now - mcpu->pil_high_start[pil - (LOCK_LEVEL + 1)];
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mcpu->intrstat[pil][0] += intrtime;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu->cpu_intracct[cpu->cpu_mstate] += intrtime;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Check for lower-pil nested high-level interrupt beneath
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * current one. If so, place a starting timestamp in its
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * pil_high_start entry.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mask = cpu->cpu_intr_actv & CPU_INTR_ACTV_HIGH_LEVEL_MASK;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (mask != 0) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int nestpil;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * find PIL of nested interrupt
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases nestpil = bsrw_insn((uint16_t)mask);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT(nestpil < pil);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mcpu->pil_high_start[nestpil - (LOCK_LEVEL + 1)] = now;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * (Another high-level interrupt is active below this one,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * so there is no need to check for an interrupt
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * thread. That will be done by the lowest priority
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * high-level interrupt active.)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } else {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Check to see if there is a low-level interrupt active.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * If so, place a starting timestamp in the thread
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * structure.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases kthread_t *t = cpu->cpu_thread;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (t->t_flag & T_INTR_THREAD)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases t->t_intr_start = now;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mcpu->mcpu_pri = oldpil;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (pil < CBE_HIGH_PIL)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (void) (*setlvlx)(oldpil, 0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (mask);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Dispatch a hilevel interrupt (one above LOCK_LEVEL)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic void
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapix_dispatch_pending_hilevel(uint_t ipl, uint_t arg2)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases UNREFERENCED_1PARAMETER(arg2);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_dispatch_pending_autovect(ipl);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic __inline__ int
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapix_do_pending_hilevel(struct cpu *cpu, struct regs *rp)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases volatile uint16_t pending;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases uint_t newipl, oldipl;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases caddr_t newsp;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases while ((pending = HILEVEL_PENDING(cpu)) != 0) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases newipl = bsrw_insn(pending);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT(newipl > LOCK_LEVEL && newipl > cpu->cpu_base_spl);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases oldipl = cpu->cpu_pri;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (newipl <= oldipl)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (-1);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * High priority interrupts run on this cpu's interrupt stack.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apix_hilevel_intr_prolog(cpu, newipl, oldipl, rp) == 0) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases newsp = cpu->cpu_intr_stack;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases switch_sp_and_call(newsp, apix_dispatch_pending_hilevel,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases newipl, 0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } else { /* already on the interrupt stack */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_dispatch_pending_hilevel(newipl, 0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (void) apix_hilevel_intr_epilog(cpu, oldipl);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Get an interrupt thread and swith to it. It's called from do_interrupt().
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * The IF flag is cleared and thus all maskable interrupts are blocked at
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * the time of calling.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic caddr_t
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapix_intr_thread_prolog(struct cpu *cpu, uint_t pil, caddr_t stackptr)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_impl_t *apixp = apixs[cpu->cpu_id];
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases struct machcpu *mcpu = &cpu->cpu_m;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases hrtime_t now = tsc_read();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases kthread_t *t, *volatile it;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT(pil > mcpu->mcpu_pri && pil > cpu->cpu_base_spl);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apixp->x_intr_pending &= ~(1 << pil);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT((cpu->cpu_intr_actv & (1 << pil)) == 0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu->cpu_intr_actv |= (1 << pil);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mcpu->mcpu_pri = pil;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Get set to run interrupt thread.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * There should always be an interrupt thread since we
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * allocate one for each level on the CPU.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* t_intr_start could be zero due to cpu_intr_swtch_enter. */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases t = cpu->cpu_thread;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if ((t->t_flag & T_INTR_THREAD) && t->t_intr_start != 0) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases hrtime_t intrtime = now - t->t_intr_start;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mcpu->intrstat[pil][0] += intrtime;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu->cpu_intracct[cpu->cpu_mstate] += intrtime;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases t->t_intr_start = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Push interrupted thread onto list from new thread.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Set the new thread as the current one.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Set interrupted thread's T_SP because if it is the idle thread,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * resume() may use that stack between threads.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT(SA((uintptr_t)stackptr) == (uintptr_t)stackptr);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases t->t_sp = (uintptr_t)stackptr; /* mark stack in curthread for resume */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Note that the code in kcpc_overflow_intr -relies- on the
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * ordering of events here - in particular that t->t_lwp of
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * the interrupt thread is set to the pinned thread *before*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * curthread is changed.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases it = cpu->cpu_intr_thread;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu->cpu_intr_thread = it->t_link;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases it->t_intr = t;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases it->t_lwp = t->t_lwp;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * (threads on the interrupt thread free list could have state
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * preset to TS_ONPROC, but it helps in debugging if
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * they're TS_FREE.)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases it->t_state = TS_ONPROC;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu->cpu_thread = it;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Initialize thread priority level from intr_pri
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases it->t_pil = (uchar_t)pil;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases it->t_pri = (pri_t)pil + intr_pri;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases it->t_intr_start = now;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (it->t_stk);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic void
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapix_intr_thread_epilog(struct cpu *cpu, uint_t oldpil)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases struct machcpu *mcpu = &cpu->cpu_m;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases kthread_t *t, *it = cpu->cpu_thread;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases uint_t pil, basespl;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases hrtime_t intrtime;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases hrtime_t now = tsc_read();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases pil = it->t_pil;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu->cpu_stats.sys.intr[pil - 1]++;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT(cpu->cpu_intr_actv & (1 << pil));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu->cpu_intr_actv &= ~(1 << pil);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT(it->t_intr_start != 0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases intrtime = now - it->t_intr_start;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mcpu->intrstat[pil][0] += intrtime;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu->cpu_intracct[cpu->cpu_mstate] += intrtime;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * If there is still an interrupted thread underneath this one
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * then the interrupt was never blocked and the return is
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * fairly simple. Otherwise it isn't.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if ((t = it->t_intr) == NULL) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * The interrupted thread is no longer pinned underneath
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * the interrupt thread. This means the interrupt must
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * have blocked, and the interrupted thread has been
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * unpinned, and has probably been running around the
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * system for a while.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases *
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Since there is no longer a thread under this one, put
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * this interrupt thread back on the CPU's free list and
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * resume the idle thread which will dispatch the next
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * thread to run.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu->cpu_stats.sys.intrblk++;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Put thread back on the interrupt thread list.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * This was an interrupt thread, so set CPU's base SPL.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases set_base_spl();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases basespl = cpu->cpu_base_spl;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mcpu->mcpu_pri = basespl;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (*setlvlx)(basespl, 0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases it->t_state = TS_FREE;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Return interrupt thread to pool
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases it->t_link = cpu->cpu_intr_thread;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu->cpu_intr_thread = it;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (void) splhigh();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases sti();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases swtch();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*NOTREACHED*/
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases panic("dosoftint_epilog: swtch returned");
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Return interrupt thread to the pool
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases it->t_link = cpu->cpu_intr_thread;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu->cpu_intr_thread = it;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases it->t_state = TS_FREE;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu->cpu_thread = t;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (t->t_flag & T_INTR_THREAD)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases t->t_intr_start = now;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases basespl = cpu->cpu_base_spl;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases mcpu->mcpu_pri = MAX(oldpil, basespl);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (*setlvlx)(mcpu->mcpu_pri, 0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic void
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapix_dispatch_pending_hardint(uint_t oldpil, uint_t arg2)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases struct cpu *cpu = CPU;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases UNREFERENCED_1PARAMETER(arg2);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_dispatch_pending_autovect((int)cpu->cpu_thread->t_pil);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Must run intr_thread_epilog() on the interrupt thread stack, since
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * there may not be a return from it if the interrupt thread blocked.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_intr_thread_epilog(cpu, oldpil);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic __inline__ int
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapix_do_pending_hardint(struct cpu *cpu, struct regs *rp)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases volatile uint16_t pending;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases uint_t newipl, oldipl;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases caddr_t newsp;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases while ((pending = LOWLEVEL_PENDING(cpu)) != 0) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases newipl = bsrw_insn(pending);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT(newipl <= LOCK_LEVEL);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases oldipl = cpu->cpu_pri;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (newipl <= oldipl || newipl <= cpu->cpu_base_spl)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (-1);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Run this interrupt in a separate thread.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases newsp = apix_intr_thread_prolog(cpu, newipl, (caddr_t)rp);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT(newsp != NULL);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases switch_sp_and_call(newsp, apix_dispatch_pending_hardint,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases oldipl, 0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases/*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Unmask level triggered interrupts
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic void
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapix_post_hardint(int vector)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_vector_t *vecp = xv_vector(psm_get_cpu_id(), vector);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int irqno = vecp->v_inum;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT(vecp->v_type == APIX_TYPE_FIXED && apic_level_intr[irqno]);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_level_intr_post_dispatch(irqno);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic void
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapix_dispatch_by_vector(uint_t vector)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases struct cpu *cpu = CPU;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_vector_t *vecp = xv_vector(cpu->cpu_id, vector);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases struct autovec *avp;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases uint_t r, (*intr)();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases caddr_t arg1, arg2;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases dev_info_t *dip;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (vecp == NULL ||
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (avp = vecp->v_autovect) == NULL || avp->av_vector == NULL)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases avp->av_flags |= AV_PENTRY_ONPROC;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases intr = avp->av_vector;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases arg1 = avp->av_intarg1;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases arg2 = avp->av_intarg2;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases dip = avp->av_dip;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (avp->av_prilevel != XC_HI_PIL)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases sti();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases DTRACE_PROBE4(interrupt__start, dev_info_t *, dip,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases void *, intr, caddr_t, arg1, caddr_t, arg2);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases r = (*intr)(arg1, arg2);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases DTRACE_PROBE4(interrupt__complete, dev_info_t *, dip,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases void *, intr, caddr_t, arg1, uint_t, r);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cli();
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases avp->av_flags &= ~AV_PENTRY_ONPROC;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic void
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapix_dispatch_hilevel(uint_t vector, uint_t arg2)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases UNREFERENCED_1PARAMETER(arg2);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_dispatch_by_vector(vector);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesstatic void
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapix_dispatch_lowlevel(uint_t vector, uint_t oldipl)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases struct cpu *cpu = CPU;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_dispatch_by_vector(vector);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Must run intr_thread_epilog() on the interrupt thread stack, since
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * there may not be a return from it if the interrupt thread blocked.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_intr_thread_epilog(cpu, oldipl);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
636dfb4b6ac0749387c883053011a3afb4b4893bJerry Jelinek/*
636dfb4b6ac0749387c883053011a3afb4b4893bJerry Jelinek * Interrupt service routine, called with interrupts disabled.
636dfb4b6ac0749387c883053011a3afb4b4893bJerry Jelinek */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesvoid
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayasesapix_do_interrupt(struct regs *rp, trap_trace_rec_t *ttp)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases{
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases struct cpu *cpu = CPU;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int vector = rp->r_trapno, newipl, oldipl = cpu->cpu_pri, ret;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_vector_t *vecp = NULL;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#ifdef TRAPTRACE
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ttp->ttr_marker = TT_INTERRUPT;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ttp->ttr_cpuid = cpu->cpu_id;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ttp->ttr_ipl = 0xff;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ttp->ttr_pri = (uchar_t)oldipl;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ttp->ttr_spl = cpu->cpu_base_spl;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ttp->ttr_vector = 0xff;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#endif /* TRAPTRACE */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu_idle_exit(CPU_IDLE_CB_FLAG_INTR);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ++*(uint16_t *)&cpu->cpu_m.mcpu_istamp;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * If it's a softint go do it now.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (rp->r_trapno == T_SOFTINT) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * It might be the case that when an interrupt is triggered,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * the spl is raised to high by splhigh(). Later when do_splx()
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * is called to restore the spl, both hardware and software
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * interrupt pending flags are check and an SOFTINT is faked
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * accordingly.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (void) apix_do_pending_hilevel(cpu, rp);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (void) apix_do_pending_hardint(cpu, rp);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (void) apix_do_softint(rp);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ASSERT(!interrupts_enabled());
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#ifdef TRAPTRACE
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ttp->ttr_vector = T_SOFTINT;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#endif
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
636dfb4b6ac0749387c883053011a3afb4b4893bJerry Jelinek * Send EOI to local APIC
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases newipl = (*setlvl)(oldipl, (int *)&rp->r_trapno);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#ifdef TRAPTRACE
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ttp->ttr_ipl = (uchar_t)newipl;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#endif /* TRAPTRACE */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Bail if it is a spurious interrupt
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (newipl == -1)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases vector = rp->r_trapno;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases vecp = xv_vector(cpu->cpu_id, vector);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#ifdef TRAPTRACE
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ttp->ttr_vector = (short)vector;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases#endif /* TRAPTRACE */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Direct dispatch for IPI, MSI, MSI-X
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (vecp && vecp->v_type != APIX_TYPE_FIXED &&
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases newipl > MAX(oldipl, cpu->cpu_base_spl)) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases caddr_t newsp;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (newipl > LOCK_LEVEL) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apix_hilevel_intr_prolog(cpu, newipl, oldipl, rp)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases == 0) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases newsp = cpu->cpu_intr_stack;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases switch_sp_and_call(newsp, apix_dispatch_hilevel,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases vector, 0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } else {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_dispatch_hilevel(vector, 0);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (void) apix_hilevel_intr_epilog(cpu, oldipl);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } else {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases newsp = apix_intr_thread_prolog(cpu, newipl,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (caddr_t)rp);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases switch_sp_and_call(newsp, apix_dispatch_lowlevel,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases vector, oldipl);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } else {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /* Add to per-pil pending queue */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases apix_add_pending_hardint(vector);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (newipl <= MAX(oldipl, cpu->cpu_base_spl) ||
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases !apixs[cpu->cpu_id]->x_intr_pending)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (apix_do_pending_hilevel(cpu, rp) < 0)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases do {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ret = apix_do_pending_hardint(cpu, rp);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Deliver any pending soft interrupts.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (void) apix_do_softint(rp);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } while (!ret && LOWLEVEL_PENDING(cpu));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases}