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 --- |