Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | /* * Copyright (c) 2018 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ #include <ztest.h> #include <interrupt_util.h> #if defined(CONFIG_DYNAMIC_INTERRUPTS) #define ISR_DYN_ARG 0xab249cfd static unsigned int handler_has_run; static uintptr_t handler_test_result; static void dyn_isr(const void *arg) { ARG_UNUSED(arg); handler_test_result = (uintptr_t)arg; handler_has_run = 1; } #if defined(CONFIG_GEN_SW_ISR_TABLE) extern struct _isr_table_entry __sw_isr_table _sw_isr_table[]; extern void z_irq_spurious(const void *unused); /** * @brief Test dynamic ISR installation * * @ingroup kernel_interrupt_tests * * @details This routine locates an unused entry in the software ISR table, * installs a dynamic ISR to the unused entry by calling the dynamic * configured function, and verifies that the ISR is successfully installed * by checking the software ISR table entry. * * @see arch_irq_connect_dynamic() */ void test_isr_dynamic(void) { int i; const void *argval; for (i = 0; i < (CONFIG_NUM_IRQS - CONFIG_GEN_IRQ_START_VECTOR); i++) { if (_sw_isr_table[i].isr == z_irq_spurious) { break; } } zassert_true(_sw_isr_table[i].isr == z_irq_spurious, "could not find slot for dynamic isr"); printk("installing dynamic ISR for IRQ %d\n", CONFIG_GEN_IRQ_START_VECTOR + i); argval = (const void *)&i; arch_irq_connect_dynamic(i + CONFIG_GEN_IRQ_START_VECTOR, 0, dyn_isr, argval, 0); zassert_true(_sw_isr_table[i].isr == dyn_isr && _sw_isr_table[i].arg == argval, "dynamic isr did not install successfully"); } #else /* * For testing arch such as x86, x86_64 and posix which support dynamic * interrupt but without SW ISR table, we test it by applying for a * dynamic interrupt and then trigger it to check if happened correctly. */ #if defined(CONFIG_X86) #define IV_IRQS 32 /* start of vectors available for x86 IRQs */ /* Using APIC TSC deadline timer will conflict with our testcase */ #if defined(CONFIG_APIC_TSC_DEADLINE_TIMER) #define TEST_IRQ_DYN_LINE 17 #else #define TEST_IRQ_DYN_LINE 16 #endif #define TRIGGER_IRQ_DYN_LINE (TEST_IRQ_DYN_LINE + IV_IRQS) #elif defined(CONFIG_ARCH_POSIX) #define TEST_IRQ_DYN_LINE 5 #define TRIGGER_IRQ_DYN_LINE 5 #endif void test_isr_dynamic(void) { int vector_num; /**TESTPOINT: configuration of interrupts dynamically at runtime */ vector_num = arch_irq_connect_dynamic(TEST_IRQ_DYN_LINE, 1, dyn_isr, (void *)ISR_DYN_ARG, 0); #if defined(CONFIG_X86_64) /* The isr table for x86_64 is visiable, so check it up here */ extern void (*x86_irq_funcs[])(const void *); extern const void *x86_irq_args[]; zassert_true(x86_irq_funcs[TEST_IRQ_DYN_LINE] == dyn_isr && x86_irq_args[TEST_IRQ_DYN_LINE] == (void *)ISR_DYN_ARG, "dynamic isr did not install successfully"); #endif TC_PRINT("vector(%d)\n", vector_num); zassert_true(vector_num > 0, "irq connect dynamic failed"); /* * The reason we need to hard code the trigger vector here * is that the x86 only support immediate number for INT * instruction. So trigger an interrupt of x86 under gcov code * coverage report enabled, which means GCC optimization will * be -O0. In this case, an build error happens and shows: * "error: 'asm' operand 0 probably does not match constraints" * and "error: impossible constraint in 'asm'" * * Although we hard code the trigger vecotr it here, we still * do a check if the vector match getting from * arch_irq_connect_dynamic(). */ zassert_equal(vector_num, TRIGGER_IRQ_DYN_LINE, "vector %d mismatch we specified to trigger %d", vector_num, TRIGGER_IRQ_DYN_LINE); zassert_equal(handler_has_run, 0, "handler has run before interrupt trigger"); irq_enable(TEST_IRQ_DYN_LINE); trigger_irq(TRIGGER_IRQ_DYN_LINE); zassert_equal(handler_has_run, 1, "interrupt triggered but handler has not run(%d)", handler_has_run); /**TESTPOINT: pass word-sized parameter to interrupt */ zassert_equal(handler_test_result, ISR_DYN_ARG, "parameter(0x%lx) in handler is not correct", handler_test_result); irq_disable(TRIGGER_IRQ_DYN_LINE); /**TESTPOINT: interrupt cannot be triggered when disable it */ zassert_equal(handler_has_run, 1, "interrupt handler should not be triggered again(%d)", handler_has_run); } #endif /* CONFIG_GEN_SW_ISR_TABLE */ #else /* Skip the dynamic interrupt test for the platforms that do not support it */ void test_isr_dynamic(void) { ztest_test_skip(); } #endif /* CONFIG_DYNAMIC_INTERRUPTS */ |