tests: arch: arm: interrupt: add test-case for user mode IRQ locking

We add a simple test to cover the case of invoking
IRQ lock()/unlock() from ARM Cortex-M user mode.

Signed-off-by: Ioannis Glaropoulos <Ioannis.Glaropoulos@nordicsemi.no>
This commit is contained in:
Ioannis Glaropoulos 2020-01-14 16:07:04 +01:00 committed by Maureen Helm
commit 937c9c215f
5 changed files with 115 additions and 3 deletions

View file

@ -1,11 +1,17 @@
Title: Test to verify code fault handling in ISR execution context (ARM Only)
Title: Test to verify code fault handling in ISR execution context
and the behavior of irq_lock() and irq_unlock() when invoked
from User Mode. (ARM Only)
Description:
This test verifies that we can handle system fault conditions
The first test verifies that we can handle system fault conditions
while running in handler mode (i.e. in an ISR). Only for ARM
Cortex-M targets.
The second test verifies that threads in user mode, despite being able to call
the irq_lock() and irq_unlock() functions without triggering a CPU fault,
they won't be able to read or modify the current IRQ locking status.
---------------------------------------------------------------------------
Building and Running Project:
@ -62,6 +68,13 @@ Sample Output:
PASS - test_arm_interrupt
===================================================================
starting test - test_arm_user_interrupt
PASS - test_arm_user_interrupt
===================================================================
Test suite arm_interrupt succeeded
===================================================================
PROJECT EXECUTION SUCCESSFUL
Test suite arm_interrupt succeeded
===================================================================
PROJECT EXECUTION SUCCESSFUL

View file

@ -1,2 +1,4 @@
CONFIG_ZTEST=y
CONFIG_DYNAMIC_INTERRUPTS=y
CONFIG_TEST_USERSPACE=y
CONFIG_APPLICATION_DEFINED_SYSCALL=y

View file

@ -114,6 +114,86 @@ void test_arm_interrupt(void)
zassert_true(post_flag == j, "Test flag not set by ISR\n");
}
}
#if defined(CONFIG_USERSPACE)
#include <syscall_handler.h>
#include "test_syscalls.h"
void z_impl_test_arm_user_interrupt_syscall(void)
{
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
/* Confirm IRQs are not locked */
zassert_false(__get_PRIMASK(), "PRIMASK is set\n");
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
static bool first_call = 1;
if (first_call == 1) {
/* First time the syscall is invoked */
first_call = 0;
/* Lock IRQs in supervisor mode */
int key = irq_lock();
/* Verify that IRQs were not already locked */
zassert_false(key, "IRQs locked in system call\n");
}
/* Confirm IRQs are still locked */
zassert_true(__get_BASEPRI(), "BASEPRI not set\n");
#endif
}
static inline void z_vrfy_test_arm_user_interrupt_syscall(void)
{
z_impl_test_arm_user_interrupt_syscall();
}
#include <syscalls/test_arm_user_interrupt_syscall_mrsh.c>
void test_arm_user_interrupt(void)
{
/* Test thread executing in user mode */
zassert_true(arch_is_user_context(),
"Test thread not running in user mode\n");
/* Attempt to lock IRQs in user mode */
irq_lock();
/* Attempt to lock again should return non-zero value of previous
* locking attempt, if that were to be successful.
*/
int lock = irq_lock();
zassert_false(lock, "IRQs shown locked in user mode\n");
/* Generate a system call to manage the IRQ locking */
test_arm_user_interrupt_syscall();
/* Attempt to unlock IRQs in user mode */
irq_unlock(0);
#if defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
/* The first system call has left the IRQs locked.
* Generate a second system call to inspect the IRQ locking.
*
* In Cortex-M Baseline system calls cannot be invoked
* with interrupts locked, so we skip this part of the
* test.
*/
test_arm_user_interrupt_syscall();
/* Verify that thread is not able to infer that IRQs are locked. */
zassert_false(irq_lock(), "IRQs are shown to be locked\n");
#endif
}
#else
void test_arm_user_interrupt(void)
{
TC_PRINT("Skipped\n");
}
#endif /* CONFIG_USERSPACE */
/**
* @}
*/

View file

@ -7,10 +7,12 @@
#include <ztest.h>
extern void test_arm_interrupt(void);
extern void test_arm_user_interrupt(void);
void test_main(void)
{
ztest_test_suite(arm_interrupt,
ztest_unit_test(test_arm_interrupt));
ztest_unit_test(test_arm_interrupt),
ztest_user_unit_test(test_arm_user_interrupt));
ztest_run_test_suite(arm_interrupt);
}

View file

@ -0,0 +1,15 @@
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _TEST_SYSCALLS_H_
#define _TEST_SYSCALLS_H_
#include <zephyr.h>
__syscall void test_arm_user_interrupt_syscall(void);
#include <syscalls/test_syscalls.h>
#endif /* _TEST_SYSCALLS_H_ */