root/sys/arch/x86/x86/x86_softintr.c
/*      $NetBSD: x86_softintr.c,v 1.4 2022/09/07 00:40:19 knakahara Exp $       */

/*
 * Copyright (c) 2007, 2008, 2009, 2019 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Andrew Doran, and by Jason R. Thorpe.
 *
 * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
 */

/*
 * Copyright 2002 (c) Wasabi Systems, Inc.
 * All rights reserved.
 *
 * Written by Frank van der Linden for Wasabi Systems, Inc.
 *
 * 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 for the NetBSD Project by
 *      Wasabi Systems, Inc.
 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
 *    or promote products derived from this software without specific prior
 *    written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
 * 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.
 */

/*-
 * Copyright (c) 1991 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. 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.
 *
 *      @(#)isa.c       7.2 (Berkeley) 5/13/91
 */

/*-
 * Copyright (c) 1993, 1994 Charles Hannum.
 *
 * 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.
 *
 *      @(#)isa.c       7.2 (Berkeley) 5/13/91
 */

#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: x86_softintr.c,v 1.4 2022/09/07 00:40:19 knakahara Exp $");

#include <sys/kmem.h>
#include <sys/proc.h>
#include <sys/intr.h>

struct pic softintr_pic = {
        .pic_name = "softintr_fakepic",
        .pic_type = PIC_SOFT,
        .pic_vecbase = 0,
        .pic_apicid = 0,
        .pic_lock = __SIMPLELOCK_UNLOCKED,
};

/*
 * Recalculate the interrupt masks from scratch.
 * During early boot, anything goes and we are always called on the BP.
 * When the system is up and running:
 *
 * => called with ci == curcpu()
 * => cpu_lock held by the initiator
 * => interrupts disabled on-chip (PSL_I)
 *
 * Do not call printf(), kmem_free() or other "heavyweight" routines
 * from here.  This routine must be quick and must not block.
 */
void
x86_intr_calculatemasks(struct cpu_info *ci)
{
        uint64_t unusedirqs, intrlevel[MAX_INTR_SOURCES];
        int irq, level;
        struct intrhand *q;

        /* First, figure out which levels each IRQ uses. */
        unusedirqs = UINT64_MAX;
        for (irq = 0; irq < MAX_INTR_SOURCES; irq++) {
                int levels = 0;

                if (ci->ci_isources[irq] == NULL) {
                        intrlevel[irq] = 0;
                        continue;
                }
                for (q = ci->ci_isources[irq]->is_handlers; q; q = q->ih_next)
                        levels |= 1 << q->ih_level;
                intrlevel[irq] = levels;
                if (levels)
                        unusedirqs &= ~(1ULL << irq);
        }

        /* Then figure out which IRQs use each level. */
        for (level = 0; level < NIPL; level++) {
                uint64_t irqs = 0;
                for (irq = 0; irq < MAX_INTR_SOURCES; irq++)
                        if (intrlevel[irq] & (1ULL << level))
                                irqs |= 1ULL << irq;
                ci->ci_imask[level] = irqs | unusedirqs;
        }

        for (level = 0; level<(NIPL-1); level++)
                ci->ci_imask[level+1] |= ci->ci_imask[level];

        for (irq = 0; irq < MAX_INTR_SOURCES; irq++) {
                int maxlevel = IPL_NONE;
                int minlevel = IPL_HIGH;

                if (ci->ci_isources[irq] == NULL)
                        continue;
                for (q = ci->ci_isources[irq]->is_handlers; q;
                     q = q->ih_next) {
                        if (q->ih_level < minlevel)
                                minlevel = q->ih_level;
                        if (q->ih_level > maxlevel)
                                maxlevel = q->ih_level;
                }
                ci->ci_isources[irq]->is_maxlevel = maxlevel;
                ci->ci_isources[irq]->is_minlevel = minlevel;
        }

        for (level = 0; level < NIPL; level++)
                ci->ci_iunmask[level] = ~ci->ci_imask[level];
}



#if defined(__HAVE_PREEMPTION)
struct intrhand fake_preempt_intrhand;

void
x86_init_preempt(struct cpu_info *ci)
{
        struct intrsource *isp;

        isp = kmem_zalloc(sizeof(*isp), KM_SLEEP);
        isp->is_recurse = Xrecurse_preempt;
        isp->is_resume = Xresume_preempt;
        fake_preempt_intrhand.ih_pic = &softintr_pic;
        fake_preempt_intrhand.ih_level = IPL_PREEMPT;
        isp->is_handlers = &fake_preempt_intrhand;
        isp->is_pic = &softintr_pic;
        ci->ci_isources[SIR_PREEMPT] = isp;
}
#endif

#if defined(__HAVE_FAST_SOFTINTS)
struct intrhand fake_softclock_intrhand;
struct intrhand fake_softnet_intrhand;
struct intrhand fake_softserial_intrhand;
struct intrhand fake_softbio_intrhand;

void
softint_init_md(lwp_t *l, u_int level, uintptr_t *machdep)
{
        struct intrsource *isp;
        struct cpu_info *ci;
        u_int sir;

        ci = l->l_cpu;

        isp = kmem_zalloc(sizeof(*isp), KM_SLEEP);
        isp->is_recurse = Xsoftintr;
        isp->is_resume = Xsoftintr;
        isp->is_pic = &softintr_pic;

        switch (level) {
        case SOFTINT_BIO:
                sir = SIR_BIO;
                fake_softbio_intrhand.ih_pic = &softintr_pic;
                fake_softbio_intrhand.ih_level = IPL_SOFTBIO;
                isp->is_handlers = &fake_softbio_intrhand;
                break;
        case SOFTINT_NET:
                sir = SIR_NET;
                fake_softnet_intrhand.ih_pic = &softintr_pic;
                fake_softnet_intrhand.ih_level = IPL_SOFTNET;
                isp->is_handlers = &fake_softnet_intrhand;
                break;
        case SOFTINT_SERIAL:
                sir = SIR_SERIAL;
                fake_softserial_intrhand.ih_pic = &softintr_pic;
                fake_softserial_intrhand.ih_level = IPL_SOFTSERIAL;
                isp->is_handlers = &fake_softserial_intrhand;
                break;
        case SOFTINT_CLOCK:
                sir = SIR_CLOCK;
                fake_softclock_intrhand.ih_pic = &softintr_pic;
                fake_softclock_intrhand.ih_level = IPL_SOFTCLOCK;
                isp->is_handlers = &fake_softclock_intrhand;
                break;
        default:
                panic("softint_init_md");
        }

        KASSERT(ci->ci_isources[sir] == NULL);

        *machdep = (1 << sir);
        ci->ci_isources[sir] = isp;
        ci->ci_isources[sir]->is_lwp = l;

        x86_intr_calculatemasks(ci);
}
#endif /* __HAVE_FAST_SOFTINTS */