subr_intr.c (9f3a552f9e1a7dbe707f143a8b8e0cdc00a8014e) subr_intr.c (85918beb387f179abc93a6c613801fb9761ff1e2)
1/*-
2 * Copyright (c) 2015-2016 Svatopluk Kraus
3 * Copyright (c) 2015-2016 Michal Meloun
4 * All rights reserved.
5 * Copyright (c) 2015-2016 The FreeBSD Foundation
6 * Copyright (c) 2021 Jessica Clarke <jrtc27@FreeBSD.org>
7 *
8 * Portions of this software were developed by Andrew Turner under

--- 75 unchanged lines hidden (view full) ---

84#include <dev/iommu/iommu_msi.h>
85#endif
86
87#include "pic_if.h"
88#include "msi_if.h"
89
90#define INTRNAME_LEN (2*MAXCOMLEN + 1)
91
1/*-
2 * Copyright (c) 2015-2016 Svatopluk Kraus
3 * Copyright (c) 2015-2016 Michal Meloun
4 * All rights reserved.
5 * Copyright (c) 2015-2016 The FreeBSD Foundation
6 * Copyright (c) 2021 Jessica Clarke <jrtc27@FreeBSD.org>
7 *
8 * Portions of this software were developed by Andrew Turner under

--- 75 unchanged lines hidden (view full) ---

84#include <dev/iommu/iommu_msi.h>
85#endif
86
87#include "pic_if.h"
88#include "msi_if.h"
89
90#define INTRNAME_LEN (2*MAXCOMLEN + 1)
91
92/*
93 * Archs may define multiple roots with INTR_ROOT_NUM to support different kinds
94 * of interrupts (e.g. arm64 FIQs which use a different exception vector than
95 * IRQs).
96 */
97#if !defined(INTR_ROOT_NUM)
98#define INTR_ROOT_NUM 1
99#endif
100
92#ifdef DEBUG
93#define debugf(fmt, args...) do { printf("%s(): ", __func__); \
94 printf(fmt,##args); } while (0)
95#else
96#define debugf(fmt, args...)
97#endif
98
99MALLOC_DECLARE(M_INTRNG);
100MALLOC_DEFINE(M_INTRNG, "intr", "intr interrupt handling");
101
101#ifdef DEBUG
102#define debugf(fmt, args...) do { printf("%s(): ", __func__); \
103 printf(fmt,##args); } while (0)
104#else
105#define debugf(fmt, args...)
106#endif
107
108MALLOC_DECLARE(M_INTRNG);
109MALLOC_DEFINE(M_INTRNG, "intr", "intr interrupt handling");
110
102/* Main interrupt handler called from assembler -> 'hidden' for C code. */
103void intr_irq_handler(struct trapframe *tf);
104
105/* Root interrupt controller stuff. */
111/* Root interrupt controller stuff. */
106device_t intr_irq_root_dev;
107static intr_irq_filter_t *irq_root_filter;
108static void *irq_root_arg;
112struct intr_irq_root {
113 device_t dev;
114 intr_irq_filter_t *filter;
115 void *arg;
116};
109
117
118static struct intr_irq_root intr_irq_roots[INTR_ROOT_NUM];
119
110struct intr_pic_child {
111 SLIST_ENTRY(intr_pic_child) pc_next;
112 struct intr_pic *pc_pic;
113 intr_child_irq_filter_t *pc_filter;
114 void *pc_filter_arg;
115 uintptr_t pc_start;
116 uintptr_t pc_length;
117};

--- 204 unchanged lines hidden (view full) ---

322 bit_nclear(intrcnt_bitmap, idx, idx + 1);
323}
324
325/*
326 * Main interrupt dispatch handler. It's called straight
327 * from the assembler, where CPU interrupt is served.
328 */
329void
120struct intr_pic_child {
121 SLIST_ENTRY(intr_pic_child) pc_next;
122 struct intr_pic *pc_pic;
123 intr_child_irq_filter_t *pc_filter;
124 void *pc_filter_arg;
125 uintptr_t pc_start;
126 uintptr_t pc_length;
127};

--- 204 unchanged lines hidden (view full) ---

332 bit_nclear(intrcnt_bitmap, idx, idx + 1);
333}
334
335/*
336 * Main interrupt dispatch handler. It's called straight
337 * from the assembler, where CPU interrupt is served.
338 */
339void
330intr_irq_handler(struct trapframe *tf)
340intr_irq_handler(struct trapframe *tf, uint32_t rootnum)
331{
332 struct trapframe * oldframe;
333 struct thread * td;
341{
342 struct trapframe * oldframe;
343 struct thread * td;
344 struct intr_irq_root *root;
334
345
335 KASSERT(irq_root_filter != NULL, ("%s: no filter", __func__));
346 KASSERT(rootnum < INTR_ROOT_NUM,
347 ("%s: invalid interrupt root %d", __func__, rootnum));
336
348
349 root = &intr_irq_roots[rootnum];
350 KASSERT(root->filter != NULL, ("%s: no filter", __func__));
351
337 kasan_mark(tf, sizeof(*tf), sizeof(*tf), 0);
338 kmsan_mark(tf, sizeof(*tf), KMSAN_STATE_INITED);
339
340 VM_CNT_INC(v_intr);
341 critical_enter();
342 td = curthread;
343 oldframe = td->td_intr_frame;
344 td->td_intr_frame = tf;
352 kasan_mark(tf, sizeof(*tf), sizeof(*tf), 0);
353 kmsan_mark(tf, sizeof(*tf), KMSAN_STATE_INITED);
354
355 VM_CNT_INC(v_intr);
356 critical_enter();
357 td = curthread;
358 oldframe = td->td_intr_frame;
359 td->td_intr_frame = tf;
345 irq_root_filter(irq_root_arg);
360 (root->filter)(root->arg);
346 td->td_intr_frame = oldframe;
347 critical_exit();
348#ifdef HWPMC_HOOKS
349 if (pmc_hook && TRAPF_USERMODE(tf) &&
350 (PCPU_GET(curthread)->td_pflags & TDP_CALLCHAIN))
351 pmc_hook(PCPU_GET(curthread), PMC_FN_USER_CALLCHAIN, tf);
352#endif
353}

--- 120 unchanged lines hidden (view full) ---

474 * order.
475 */
476 if (irq_next_free >= intr_nirq)
477 irq_next_free = 0;
478
479 return (0);
480}
481
361 td->td_intr_frame = oldframe;
362 critical_exit();
363#ifdef HWPMC_HOOKS
364 if (pmc_hook && TRAPF_USERMODE(tf) &&
365 (PCPU_GET(curthread)->td_pflags & TDP_CALLCHAIN))
366 pmc_hook(PCPU_GET(curthread), PMC_FN_USER_CALLCHAIN, tf);
367#endif
368}

--- 120 unchanged lines hidden (view full) ---

489 * order.
490 */
491 if (irq_next_free >= intr_nirq)
492 irq_next_free = 0;
493
494 return (0);
495}
496
497device_t
498intr_irq_root_device(uint32_t rootnum)
499{
500 KASSERT(rootnum < INTR_ROOT_NUM,
501 ("%s: invalid interrupt root %d", __func__, rootnum));
502 return (intr_irq_roots[rootnum].dev);
503}
504
482/*
483 * Initialize interrupt source and register it into global interrupt table.
484 */
485int
486intr_isrc_register(struct intr_irqsrc *isrc, device_t dev, u_int flags,
487 const char *fmt, ...)
488{
489 int error;

--- 382 unchanged lines hidden (view full) ---

872 * In FDT case, according to ePAPR approved version 1.1 from 08 April 2011,
873 * page 30:
874 * "The root of the interrupt tree is determined when traversal
875 * of the interrupt tree reaches an interrupt controller node without
876 * an interrupts property and thus no explicit interrupt parent."
877 */
878int
879intr_pic_claim_root(device_t dev, intptr_t xref, intr_irq_filter_t *filter,
505/*
506 * Initialize interrupt source and register it into global interrupt table.
507 */
508int
509intr_isrc_register(struct intr_irqsrc *isrc, device_t dev, u_int flags,
510 const char *fmt, ...)
511{
512 int error;

--- 382 unchanged lines hidden (view full) ---

895 * In FDT case, according to ePAPR approved version 1.1 from 08 April 2011,
896 * page 30:
897 * "The root of the interrupt tree is determined when traversal
898 * of the interrupt tree reaches an interrupt controller node without
899 * an interrupts property and thus no explicit interrupt parent."
900 */
901int
902intr_pic_claim_root(device_t dev, intptr_t xref, intr_irq_filter_t *filter,
880 void *arg)
903 void *arg, uint32_t rootnum)
881{
882 struct intr_pic *pic;
904{
905 struct intr_pic *pic;
906 struct intr_irq_root *root;
883
884 pic = pic_lookup(dev, xref, FLAG_PIC);
885 if (pic == NULL) {
886 device_printf(dev, "not registered\n");
887 return (EINVAL);
888 }
889
890 KASSERT((pic->pic_flags & FLAG_TYPE_MASK) == FLAG_PIC,

--- 5 unchanged lines hidden (view full) ---

896 return (EINVAL);
897 }
898
899 /*
900 * Only one interrupt controllers could be on the root for now.
901 * Note that we further suppose that there is not threaded interrupt
902 * routine (handler) on the root. See intr_irq_handler().
903 */
907
908 pic = pic_lookup(dev, xref, FLAG_PIC);
909 if (pic == NULL) {
910 device_printf(dev, "not registered\n");
911 return (EINVAL);
912 }
913
914 KASSERT((pic->pic_flags & FLAG_TYPE_MASK) == FLAG_PIC,

--- 5 unchanged lines hidden (view full) ---

920 return (EINVAL);
921 }
922
923 /*
924 * Only one interrupt controllers could be on the root for now.
925 * Note that we further suppose that there is not threaded interrupt
926 * routine (handler) on the root. See intr_irq_handler().
927 */
904 if (intr_irq_root_dev != NULL) {
928 KASSERT(rootnum < INTR_ROOT_NUM,
929 ("%s: invalid interrupt root %d", __func__, rootnum));
930 root = &intr_irq_roots[rootnum];
931 if (root->dev != NULL) {
905 device_printf(dev, "another root already set\n");
906 return (EBUSY);
907 }
908
932 device_printf(dev, "another root already set\n");
933 return (EBUSY);
934 }
935
909 intr_irq_root_dev = dev;
910 irq_root_filter = filter;
911 irq_root_arg = arg;
936 root->dev = dev;
937 root->filter = filter;
938 root->arg = arg;
912
913 debugf("irq root set to %s\n", device_get_nameunit(dev));
914 return (0);
915}
916
917/*
918 * Add a handler to manage a sub range of a parents interrupts.
919 */

--- 627 unchanged lines hidden (view full) ---

1547
1548#ifdef SMP
1549/*
1550 * Init interrupt controller on another CPU.
1551 */
1552void
1553intr_pic_init_secondary(void)
1554{
939
940 debugf("irq root set to %s\n", device_get_nameunit(dev));
941 return (0);
942}
943
944/*
945 * Add a handler to manage a sub range of a parents interrupts.
946 */

--- 627 unchanged lines hidden (view full) ---

1574
1575#ifdef SMP
1576/*
1577 * Init interrupt controller on another CPU.
1578 */
1579void
1580intr_pic_init_secondary(void)
1581{
1582 device_t dev;
1583 uint32_t rootnum;
1555
1556 /*
1584
1585 /*
1557 * QQQ: Only root PIC is aware of other CPUs ???
1586 * QQQ: Only root PICs are aware of other CPUs ???
1558 */
1587 */
1559 KASSERT(intr_irq_root_dev != NULL, ("%s: no root attached", __func__));
1560
1561 //mtx_lock(&isrc_table_lock);
1588 //mtx_lock(&isrc_table_lock);
1562 PIC_INIT_SECONDARY(intr_irq_root_dev);
1589 for (rootnum = 0; rootnum < INTR_ROOT_NUM; rootnum++) {
1590 dev = intr_irq_roots[rootnum].dev;
1591 if (dev != NULL) {
1592 PIC_INIT_SECONDARY(dev, rootnum);
1593 }
1594 }
1563 //mtx_unlock(&isrc_table_lock);
1564}
1565#endif
1566
1567#ifdef DDB
1568DB_SHOW_COMMAND_FLAGS(irqs, db_show_irqs, DB_CMD_MEMSAFE)
1569{
1570 u_int i, irqsum;

--- 358 unchanged lines hidden ---
1595 //mtx_unlock(&isrc_table_lock);
1596}
1597#endif
1598
1599#ifdef DDB
1600DB_SHOW_COMMAND_FLAGS(irqs, db_show_irqs, DB_CMD_MEMSAFE)
1601{
1602 u_int i, irqsum;

--- 358 unchanged lines hidden ---