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:
parent
e93ccd9973
commit
937c9c215f
5 changed files with 115 additions and 3 deletions
|
@ -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:
|
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
|
while running in handler mode (i.e. in an ISR). Only for ARM
|
||||||
Cortex-M targets.
|
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:
|
Building and Running Project:
|
||||||
|
@ -62,6 +68,13 @@ Sample Output:
|
||||||
|
|
||||||
PASS - test_arm_interrupt
|
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
|
Test suite arm_interrupt succeeded
|
||||||
===================================================================
|
===================================================================
|
||||||
PROJECT EXECUTION SUCCESSFUL
|
PROJECT EXECUTION SUCCESSFUL
|
||||||
|
|
|
@ -1,2 +1,4 @@
|
||||||
CONFIG_ZTEST=y
|
CONFIG_ZTEST=y
|
||||||
CONFIG_DYNAMIC_INTERRUPTS=y
|
CONFIG_DYNAMIC_INTERRUPTS=y
|
||||||
|
CONFIG_TEST_USERSPACE=y
|
||||||
|
CONFIG_APPLICATION_DEFINED_SYSCALL=y
|
||||||
|
|
|
@ -114,6 +114,86 @@ void test_arm_interrupt(void)
|
||||||
zassert_true(post_flag == j, "Test flag not set by ISR\n");
|
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 */
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -7,10 +7,12 @@
|
||||||
#include <ztest.h>
|
#include <ztest.h>
|
||||||
|
|
||||||
extern void test_arm_interrupt(void);
|
extern void test_arm_interrupt(void);
|
||||||
|
extern void test_arm_user_interrupt(void);
|
||||||
|
|
||||||
void test_main(void)
|
void test_main(void)
|
||||||
{
|
{
|
||||||
ztest_test_suite(arm_interrupt,
|
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);
|
ztest_run_test_suite(arm_interrupt);
|
||||||
}
|
}
|
||||||
|
|
15
tests/arch/arm/arm_interrupt/src/test_syscalls.h
Normal file
15
tests/arch/arm/arm_interrupt/src/test_syscalls.h
Normal 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_ */
|
Loading…
Add table
Add a link
Reference in a new issue