From 669ab243f94ac84c923f7cac04270eb846f22e67 Mon Sep 17 00:00:00 2001 From: Etienne Carriere Date: Wed, 25 Jan 2023 10:05:23 +0100 Subject: [PATCH] pta: test: invoke: add interrupt during interrupt test Test when OP-TEE raises an interrupt notification from the interrupt context of the normal world. This test is based on the fact Linux OS is masking interrupts that have no consumers but where caught. Mask operation is called from Linux optee irqchip driver, from the interrupt context, after interrupts events have been retrieved. Raising an interrupt notification from that context helps testing if the notification was well received by normal OS or if the interrupt event are still pending, needing another async notif to be retrieved. Signed-off-by: Etienne Carriere --- core/pta/tests/misc.c | 81 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/core/pta/tests/misc.c b/core/pta/tests/misc.c index 23a92702f5c..d1cc1a7e351 100644 --- a/core/pta/tests/misc.c +++ b/core/pta/tests/misc.c @@ -227,6 +227,87 @@ static TEE_Result test1_it_notif_do(void) return res; } +/* + * Test1: test interrupt event during REE interrupt context + */ + +static void test2_notif_set_mask(struct notif_it *notif_it, bool do_mask) +{ + if (!do_mask) + return; + + if (notif_it->id == idx2id(0)) + notif_it_raise_event(test_it_notif + 1); + else if (notif_it->id == idx2id(1)) + notif_it_raise_event(test_it_notif + 2); + else if (notif_it->id == idx2id(2)) + notif_it_raise_event(test_it_notif + 3); +} +DECLARE_KEEP_PAGER(test2_notif_set_mask); + +const struct notif_it_ops test2_notif_ops = { + .set_mask = test2_notif_set_mask, +}; + +static TEE_Result test2_it_notif_do(void) +{ + TEE_Result res = TEE_SUCCESS; + size_t n = 0; + + static_assert(TEST_IT_NOTIF_CNT >= 4); + + for (n = 0; n <= 3; n++) { + res = register_test_it_notif(n, &test2_notif_ops); + if (res) + goto out; + } + + IMSG("It-notif: test interrupt during interrupt "); + + for (n = 0; n <= 3; n++) + notif_it_set_mask(idx2id(n), 0); + + /* + * This test simulates cases where an interrupt is notified and + * under processing in REE, in an interrupt context, while another + * OP-TEE event raises a notification. The goal is to check the 2nd + * notification is well signaled to REE and not pending. + * + * Raise test interrupt #0. In return, REE will mask it because + * it has no consumer in Linux kernel. During mask operation, + * test interrupt #0 raises #1, #1 raises #2, #2 raises #3. + * So raising #n makes #n to #3 be raised and masked back by REE. + * + * Check that all interrupts are consumed, with 2, 3 or 4 linked + * interrupts. + */ + notif_it_raise_event(test_it_notif + 0); + mdelay(10); + + for (n = 0; n <= 3; n++) + if (test_it_is_pending(n)) + break; + + if (n < 4) { + EMSG("Test ITs notif are still pending"); + res = TEE_ERROR_GENERIC; + goto out; + } + + for (n = 0; n <= 3; n++) + notif_it_set_mask(idx2id(n), 1); + +out: + unregister_test_all_notif(); + + if (res) + EMSG("Test it-notif failed: %#"PRIx32, res); + else + IMSG("It-notif: test successful"); + + return res; +} + static TEE_Result test_it_notif_do(void) { TEE_Result res = TEE_ERROR_GENERIC;