1*fc30b644Skettenis /* $OpenBSD: intr.h,v 1.34 2024/05/26 13:37:31 kettenis Exp $ */ 2f5df1827Smickey /* $NetBSD: intr.h,v 1.2 2003/05/04 22:01:56 fvdl Exp $ */ 3f5df1827Smickey 4f5df1827Smickey /*- 5f5df1827Smickey * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc. 6f5df1827Smickey * All rights reserved. 7f5df1827Smickey * 8f5df1827Smickey * This code is derived from software contributed to The NetBSD Foundation 9f5df1827Smickey * by Charles M. Hannum, and by Jason R. Thorpe. 10f5df1827Smickey * 11f5df1827Smickey * Redistribution and use in source and binary forms, with or without 12f5df1827Smickey * modification, are permitted provided that the following conditions 13f5df1827Smickey * are met: 14f5df1827Smickey * 1. Redistributions of source code must retain the above copyright 15f5df1827Smickey * notice, this list of conditions and the following disclaimer. 16f5df1827Smickey * 2. Redistributions in binary form must reproduce the above copyright 17f5df1827Smickey * notice, this list of conditions and the following disclaimer in the 18f5df1827Smickey * documentation and/or other materials provided with the distribution. 19f5df1827Smickey * 20f5df1827Smickey * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21f5df1827Smickey * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22f5df1827Smickey * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23f5df1827Smickey * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24f5df1827Smickey * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25f5df1827Smickey * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26f5df1827Smickey * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27f5df1827Smickey * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28f5df1827Smickey * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29f5df1827Smickey * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30f5df1827Smickey * POSSIBILITY OF SUCH DAMAGE. 31f5df1827Smickey */ 32f5df1827Smickey 332fa72412Spirofti #ifndef _MACHINE_INTR_H_ 342fa72412Spirofti #define _MACHINE_INTR_H_ 35f5df1827Smickey 36f5df1827Smickey #include <machine/intrdefs.h> 37f5df1827Smickey 38f5df1827Smickey #ifndef _LOCORE 39f5df1827Smickey #include <machine/cpu.h> 40f5df1827Smickey 416816c79aSderaadt #include <sys/evcount.h> 426816c79aSderaadt 43f5df1827Smickey /* 44f5df1827Smickey * Struct describing an interrupt source for a CPU. struct cpu_info 45f5df1827Smickey * has an array of MAX_INTR_SOURCES of these. The index in the array 46f5df1827Smickey * is equal to the stub number of the stubcode as present in vector.s 47f5df1827Smickey * 48f5df1827Smickey * The primary CPU's array of interrupt sources has its first 16 49f5df1827Smickey * entries reserved for legacy ISA irq handlers. This means that 50f5df1827Smickey * they have a 1:1 mapping for arrayindex:irq_num. This is not 51f5df1827Smickey * true for interrupts that come in through IO APICs, to find 52f5df1827Smickey * their source, go through ci->ci_isources[index].is_pic 53f5df1827Smickey * 54f5df1827Smickey * It's possible to always maintain a 1:1 mapping, but that means 55f5df1827Smickey * limiting the total number of interrupt sources to MAX_INTR_SOURCES 56f5df1827Smickey * (32), instead of 32 per CPU. It also would mean that having multiple 57f5df1827Smickey * IO APICs which deliver interrupts from an equal pin number would 58f5df1827Smickey * overlap if they were to be sent to the same CPU. 59f5df1827Smickey */ 60f5df1827Smickey 61f5df1827Smickey struct intrstub { 62f5df1827Smickey void *ist_entry; 63f5df1827Smickey void *ist_recurse; 64f5df1827Smickey void *ist_resume; 65f5df1827Smickey }; 66f5df1827Smickey 67f5df1827Smickey struct intrsource { 68f5df1827Smickey int is_maxlevel; /* max. IPL for this source */ 69f5df1827Smickey int is_pin; /* IRQ for legacy; pin for IO APIC */ 70f5df1827Smickey struct intrhand *is_handlers; /* handler chain */ 71f5df1827Smickey struct pic *is_pic; /* originating PIC */ 72f5df1827Smickey void *is_recurse; /* entry for spllower */ 73f5df1827Smickey void *is_resume; /* entry for doreti */ 74f5df1827Smickey char is_evname[32]; /* event counter name */ 75f5df1827Smickey int is_flags; /* see below */ 76f5df1827Smickey int is_type; /* level, edge */ 77f5df1827Smickey int is_idtvec; 78f5df1827Smickey int is_minlevel; 79f5df1827Smickey }; 80f5df1827Smickey 81f5df1827Smickey #define IS_LEGACY 0x0001 /* legacy ISA irq source */ 82f5df1827Smickey #define IS_IPI 0x0002 83f5df1827Smickey #define IS_LOG 0x0004 84f5df1827Smickey 85f5df1827Smickey 86f5df1827Smickey /* 87f5df1827Smickey * Interrupt handler chains. *_intr_establish() insert a handler into 88f5df1827Smickey * the list. The handler is called with its (single) argument. 89f5df1827Smickey */ 90f5df1827Smickey 91f5df1827Smickey struct intrhand { 92f5df1827Smickey int (*ih_fun)(void *); 93f5df1827Smickey void *ih_arg; 94f5df1827Smickey int ih_level; 95483e3bc5Skettenis int ih_flags; 96f5df1827Smickey struct intrhand *ih_next; 97f5df1827Smickey int ih_pin; 98f5df1827Smickey int ih_slot; 99f5df1827Smickey struct cpu_info *ih_cpu; 100f5df1827Smickey int ih_irq; 1016816c79aSderaadt struct evcount ih_count; 102f5df1827Smickey }; 103f5df1827Smickey 104f5df1827Smickey #define IMASK(ci,level) (ci)->ci_imask[(level)] 105f5df1827Smickey #define IUNMASK(ci,level) (ci)->ci_iunmask[(level)] 106f5df1827Smickey 107f5df1827Smickey extern void Xspllower(int); 108f5df1827Smickey 1090b57f6e9Sart int splraise(int); 1100b57f6e9Sart int spllower(int); 1110b57f6e9Sart void softintr(int); 112f5df1827Smickey 113f5df1827Smickey /* 114f5df1827Smickey * Convert spl level to local APIC level 115f5df1827Smickey */ 116f5df1827Smickey #define APIC_LEVEL(l) ((l) << 4) 117f5df1827Smickey 118f5df1827Smickey /* 119f5df1827Smickey * compiler barrier: prevent reordering of instructions. 120f5df1827Smickey * This prevents the compiler from reordering code around 121f5df1827Smickey * this "instruction", acting as a sequence point for code generation. 122f5df1827Smickey */ 123f5df1827Smickey 1242df76cc2Sguenther #define __splbarrier() __asm volatile("":::"memory") 125f5df1827Smickey 126f5df1827Smickey /* 127f5df1827Smickey * Hardware interrupt masks 128f5df1827Smickey */ 129f5df1827Smickey #define splbio() splraise(IPL_BIO) 130f5df1827Smickey #define splnet() splraise(IPL_NET) 131f5df1827Smickey #define spltty() splraise(IPL_TTY) 132f5df1827Smickey #define splaudio() splraise(IPL_AUDIO) 133f5df1827Smickey #define splclock() splraise(IPL_CLOCK) 134f5df1827Smickey #define splstatclock() splclock() 135f5df1827Smickey #define splipi() splraise(IPL_IPI) 136f5df1827Smickey 137f5df1827Smickey /* 138f5df1827Smickey * Software interrupt masks 139f5df1827Smickey */ 140f5df1827Smickey #define splsoftclock() splraise(IPL_SOFTCLOCK) 141f5df1827Smickey #define splsoftnet() splraise(IPL_SOFTNET) 142a2cd3cc4Skettenis #define splsofttty() splraise(IPL_SOFTTTY) 143f5df1827Smickey 144f5df1827Smickey /* 145f5df1827Smickey * Miscellaneous 146f5df1827Smickey */ 14793f0663eSbrad #define splvm() splraise(IPL_VM) 148f5df1827Smickey #define splhigh() splraise(IPL_HIGH) 149f5df1827Smickey #define spl0() spllower(IPL_NONE) 150f5df1827Smickey #define splsched() splraise(IPL_SCHED) 151f5df1827Smickey #define splx(x) spllower(x) 152f5df1827Smickey 153f5df1827Smickey /* SPL asserts */ 154f5df1827Smickey #ifdef DIAGNOSTIC 155f5df1827Smickey /* 156f5df1827Smickey * Although this function is implemented in MI code, it must be in this MD 157f5df1827Smickey * header because we don't want this header to include MI includes. 158f5df1827Smickey */ 159f5df1827Smickey void splassert_fail(int, int, const char *); 160f5df1827Smickey extern int splassert_ctl; 161f5df1827Smickey void splassert_check(int, const char *); 162f5df1827Smickey #define splassert(__wantipl) do { \ 163032bee17Sthib if (splassert_ctl > 0) { \ 164f5df1827Smickey splassert_check(__wantipl, __func__); \ 165f5df1827Smickey } \ 166f5df1827Smickey } while (0) 167312f6203Smiod #define splsoftassert(wantipl) splassert(wantipl) 168f5df1827Smickey #else 169f5df1827Smickey #define splassert(wantipl) do { /* nada */ } while (0) 170312f6203Smiod #define splsoftassert(wantipl) do { /* nada */ } while (0) 171f5df1827Smickey #endif 172f5df1827Smickey 173f5df1827Smickey #define IPLSHIFT 4 /* The upper nibble of vectors is the IPL. */ 174f5df1827Smickey #define IPL(level) ((level) >> IPLSHIFT) /* Extract the IPL. */ 175f5df1827Smickey 176b5b9857bSart #include <machine/pic.h> 177b5b9857bSart 178f5df1827Smickey /* 179f5df1827Smickey * Stub declarations. 180f5df1827Smickey */ 181f5df1827Smickey 182f5df1827Smickey extern void Xsoftclock(void); 183f5df1827Smickey extern void Xsoftnet(void); 184a2cd3cc4Skettenis extern void Xsofttty(void); 185f5df1827Smickey 186f5df1827Smickey extern struct intrstub i8259_stubs[]; 187f5df1827Smickey extern struct intrstub ioapic_edge_stubs[]; 188f5df1827Smickey extern struct intrstub ioapic_level_stubs[]; 189f5df1827Smickey 190f5df1827Smickey struct cpu_info; 191f5df1827Smickey 192177417ccSderaadt extern int intr_shared_edge; 193177417ccSderaadt 194f5df1827Smickey extern char idt_allocmap[]; 195f5df1827Smickey 196f5df1827Smickey void intr_default_setup(void); 197f5df1827Smickey int x86_nmi(void); 198f5df1827Smickey void intr_calculatemasks(struct cpu_info *); 199f5df1827Smickey int intr_allocate_slot_cpu(struct cpu_info *, struct pic *, int, int *); 200f5df1827Smickey int intr_allocate_slot(struct pic *, int, int, int, struct cpu_info **, int *, 201f5df1827Smickey int *); 20215db3095Sdlg void *intr_establish(int, struct pic *, int, int, int, 20315db3095Sdlg struct cpu_info *, int (*)(void *), void *, const char *); 204f5df1827Smickey void intr_disestablish(struct intrhand *); 20558643530Sratchov int intr_handler(struct intrframe *, struct intrhand *); 206f5df1827Smickey void cpu_intr_init(struct cpu_info *); 207f5df1827Smickey void intr_printconfig(void); 208edc47eabSkettenis void intr_barrier(void *); 209*fc30b644Skettenis void intr_enable_wakeup(void); 210*fc30b644Skettenis void intr_disable_wakeup(void); 211f5df1827Smickey 212f5df1827Smickey #ifdef MULTIPROCESSOR 213b8fe8d64Ssf void x86_send_ipi(struct cpu_info *, int); 214ae5427f4Sart int x86_fast_ipi(struct cpu_info *, int); 215f5df1827Smickey void x86_broadcast_ipi(int); 216f5df1827Smickey void x86_ipi_handler(void); 2175714d2eaSgwk void x86_setperf_ipi(struct cpu_info *); 218f5df1827Smickey 219f5df1827Smickey extern void (*ipifunc[X86_NIPI])(struct cpu_info *); 220f5df1827Smickey #endif 221f5df1827Smickey 222f5df1827Smickey #endif /* !_LOCORE */ 223f5df1827Smickey 224f5df1827Smickey /* 225f5df1827Smickey * Generic software interrupt support. 226f5df1827Smickey */ 227f5df1827Smickey 228f5df1827Smickey #define X86_SOFTINTR_SOFTCLOCK 0 229f5df1827Smickey #define X86_SOFTINTR_SOFTNET 1 230a2cd3cc4Skettenis #define X86_SOFTINTR_SOFTTTY 2 231f5df1827Smickey #define X86_NSOFTINTR 3 232f5df1827Smickey 233f5df1827Smickey #ifndef _LOCORE 234f5df1827Smickey #include <sys/queue.h> 235f5df1827Smickey 236f5df1827Smickey struct x86_soft_intrhand { 237f5df1827Smickey TAILQ_ENTRY(x86_soft_intrhand) 238f5df1827Smickey sih_q; 239f5df1827Smickey struct x86_soft_intr *sih_intrhead; 240f5df1827Smickey void (*sih_fn)(void *); 241f5df1827Smickey void *sih_arg; 242f5df1827Smickey int sih_pending; 243f5df1827Smickey }; 244f5df1827Smickey 245f5df1827Smickey struct x86_soft_intr { 246f5df1827Smickey TAILQ_HEAD(, x86_soft_intrhand) 247f5df1827Smickey softintr_q; 248f5df1827Smickey int softintr_ssir; 2491f723b73Soga struct mutex softintr_lock; 250f5df1827Smickey }; 251f5df1827Smickey 252f5df1827Smickey void *softintr_establish(int, void (*)(void *), void *); 253f5df1827Smickey void softintr_disestablish(void *); 254f5df1827Smickey void softintr_init(void); 255f5df1827Smickey void softintr_dispatch(int); 256f5df1827Smickey 257f5df1827Smickey #define softintr_schedule(arg) \ 258f5df1827Smickey do { \ 259f5df1827Smickey struct x86_soft_intrhand *__sih = (arg); \ 260f5df1827Smickey struct x86_soft_intr *__si = __sih->sih_intrhead; \ 261f5df1827Smickey \ 2621f723b73Soga mtx_enter(&__si->softintr_lock); \ 263f5df1827Smickey if (__sih->sih_pending == 0) { \ 264f5df1827Smickey TAILQ_INSERT_TAIL(&__si->softintr_q, __sih, sih_q); \ 265f5df1827Smickey __sih->sih_pending = 1; \ 266f5df1827Smickey softintr(__si->softintr_ssir); \ 267f5df1827Smickey } \ 2681f723b73Soga mtx_leave(&__si->softintr_lock); \ 269f5df1827Smickey } while (/*CONSTCOND*/ 0) 270f5df1827Smickey #endif /* _LOCORE */ 271f5df1827Smickey 2722fa72412Spirofti #endif /* !_MACHINE_INTR_H_ */ 273