tests: arm64: add GICv3 ITS test suite
Add a simple ITS driver test allocating 8192 LPIs over 256 DeviceIDS and 32 EventIDs per DeviceID to exercise the ITS for the MSI/MSI-X usecase. The test is set as `build_only: true` and whitelisted to the fvp_base_revc_2xaemv8a board until the shipped Zephyr QEMU has the ITS support. Since `fvp_base_revc_2xaemv8a` needs FIP & BL1 files, test is marked as `skip: true`. Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
This commit is contained in:
parent
0619e96e87
commit
481b5a2424
4 changed files with 204 additions and 0 deletions
12
tests/arch/arm64/arm64_gicv3_its/CMakeLists.txt
Normal file
12
tests/arch/arm64/arm64_gicv3_its/CMakeLists.txt
Normal file
|
@ -0,0 +1,12 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
cmake_minimum_required(VERSION 3.13.1)
|
||||
|
||||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||
project(arm_gicv3_its)
|
||||
|
||||
FILE(GLOB app_sources src/*.c)
|
||||
target_sources(app PRIVATE ${app_sources})
|
||||
target_include_directories(app PRIVATE
|
||||
${ARCH_DIR}/${ARCH}/include
|
||||
)
|
3
tests/arch/arm64/arm64_gicv3_its/prj.conf
Normal file
3
tests/arch/arm64/arm64_gicv3_its/prj.conf
Normal file
|
@ -0,0 +1,3 @@
|
|||
CONFIG_LOG=y
|
||||
CONFIG_ZTEST=y
|
||||
CONFIG_GIC_V3_ITS=y
|
184
tests/arch/arm64/arm64_gicv3_its/src/main.c
Normal file
184
tests/arch/arm64/arm64_gicv3_its/src/main.c
Normal file
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
* Copyright (c) 2021 BayLibre, SAS
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <ztest.h>
|
||||
#include <device.h>
|
||||
#include <drivers/interrupt_controller/gicv3_its.h>
|
||||
|
||||
#define DT_DRV_COMPAT arm_gic_v3_its
|
||||
|
||||
static volatile unsigned int last_lpi_irq_num;
|
||||
|
||||
static void lpi_irq_handle(const void *parameter)
|
||||
{
|
||||
uintptr_t i = (uintptr_t)parameter;
|
||||
|
||||
last_lpi_irq_num = i;
|
||||
}
|
||||
|
||||
/* Generate a DeviceID over the whole 16bits */
|
||||
#define ITS_TEST_DEV(id) ((((id + 256) % 16) << 12) | (((id + 256) % 24) << 8) | (id & 0xff))
|
||||
|
||||
/* Cover up to 8192 LPIs over 256 DevicesIDs and 32 EventIDs per DeviceID */
|
||||
#define ITS_TEST_NUM_DEVS 256
|
||||
#define ITS_TEST_NUM_ITES 32
|
||||
|
||||
/* Do not test all 8192 irqs, iterate with a prime offset to cover most of the possible event_ids */
|
||||
#define ITS_TEST_NEXT 13
|
||||
|
||||
/* Active-wait loops waiting for an interrupt */
|
||||
#define ITS_TEST_LOOPS 10
|
||||
|
||||
unsigned int vectors[ITS_TEST_NUM_DEVS][ITS_TEST_NUM_ITES];
|
||||
|
||||
static void test_gicv3_its_alloc(void)
|
||||
{
|
||||
int devn, event_id;
|
||||
const struct device *dev = DEVICE_DT_INST_GET(0);
|
||||
|
||||
zassert_false(dev == NULL, "");
|
||||
|
||||
for (devn = 0; devn < ITS_TEST_NUM_DEVS; ++devn) {
|
||||
int device_id = ITS_TEST_DEV(devn);
|
||||
|
||||
zassert_true(its_setup_deviceid(dev, device_id, ITS_TEST_NUM_ITES) == 0, "");
|
||||
|
||||
for (event_id = 0; event_id < ITS_TEST_NUM_ITES; ++event_id) {
|
||||
vectors[devn][event_id] = its_alloc_intid(dev);
|
||||
zassert_true(vectors[devn][event_id] >= 8192, "");
|
||||
zassert_true(vectors[devn][event_id] < CONFIG_NUM_IRQS, "");
|
||||
|
||||
zassert_true(its_map_intid(dev, device_id, event_id,
|
||||
vectors[devn][event_id]) == 0, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void test_gicv3_its_connect(void)
|
||||
{
|
||||
int devn, event_id;
|
||||
const struct device *dev = DEVICE_DT_INST_GET(0);
|
||||
unsigned int remain = 0;
|
||||
|
||||
zassert_false(dev == NULL, "");
|
||||
|
||||
for (devn = 0; devn < ITS_TEST_NUM_DEVS; ++devn) {
|
||||
for (event_id = remain; event_id < ITS_TEST_NUM_ITES; event_id += ITS_TEST_NEXT) {
|
||||
unsigned int irqn = vectors[devn][event_id];
|
||||
|
||||
zassert_true(irq_connect_dynamic(irqn, 0, lpi_irq_handle,
|
||||
(void *)(uintptr_t)(irqn), 0) == irqn, "");
|
||||
|
||||
irq_enable(irqn);
|
||||
}
|
||||
remain = event_id - ITS_TEST_NUM_ITES;
|
||||
}
|
||||
}
|
||||
|
||||
static void test_gicv3_its_irq_simple(void)
|
||||
{
|
||||
const struct device *dev = DEVICE_DT_INST_GET(0);
|
||||
unsigned int irqn = vectors[0][0];
|
||||
unsigned int timeout;
|
||||
int device_id = ITS_TEST_DEV(0);
|
||||
int event_id = 0;
|
||||
|
||||
zassert_false(dev == NULL, "");
|
||||
|
||||
last_lpi_irq_num = 0;
|
||||
zassert_true(its_send_int(dev, device_id, event_id) == 0, "");
|
||||
|
||||
timeout = ITS_TEST_LOOPS;
|
||||
while (!last_lpi_irq_num && timeout) {
|
||||
timeout--;
|
||||
}
|
||||
|
||||
zassert_true(last_lpi_irq_num == irqn,
|
||||
"IRQ %d of DeviceID %x EventID %d failed",
|
||||
irqn, device_id, event_id);
|
||||
}
|
||||
|
||||
static void test_gicv3_its_irq_disable(void)
|
||||
{
|
||||
const struct device *dev = DEVICE_DT_INST_GET(0);
|
||||
unsigned int irqn = vectors[0][0];
|
||||
unsigned int timeout;
|
||||
int device_id = ITS_TEST_DEV(0);
|
||||
int event_id = 0;
|
||||
|
||||
zassert_false(dev == NULL, "");
|
||||
|
||||
irq_disable(irqn);
|
||||
|
||||
last_lpi_irq_num = 0;
|
||||
zassert_true(its_send_int(dev, device_id, event_id) == 0, "");
|
||||
|
||||
timeout = ITS_TEST_LOOPS;
|
||||
while (!last_lpi_irq_num && timeout) {
|
||||
timeout--;
|
||||
}
|
||||
|
||||
zassert_true(last_lpi_irq_num == 0,
|
||||
"IRQ %d of DeviceID %x EventID %d disable failed",
|
||||
irqn, device_id, event_id);
|
||||
|
||||
irq_enable(irqn);
|
||||
|
||||
last_lpi_irq_num = 0;
|
||||
zassert_true(its_send_int(dev, device_id, event_id) == 0, "");
|
||||
|
||||
timeout = ITS_TEST_LOOPS;
|
||||
while (!last_lpi_irq_num && timeout) {
|
||||
timeout--;
|
||||
}
|
||||
|
||||
zassert_true(last_lpi_irq_num == irqn,
|
||||
"IRQ %d of DeviceID %x EventID %d re-enable failed",
|
||||
irqn, device_id, event_id);
|
||||
}
|
||||
|
||||
static void test_gicv3_its_irq(void)
|
||||
{
|
||||
int devn, event_id;
|
||||
const struct device *dev = DEVICE_DT_INST_GET(0);
|
||||
unsigned int timeout;
|
||||
unsigned int remain = 0;
|
||||
|
||||
zassert_false(dev == NULL, "");
|
||||
|
||||
for (devn = 0; devn < ITS_TEST_NUM_DEVS; ++devn) {
|
||||
int device_id = ITS_TEST_DEV(devn);
|
||||
|
||||
for (event_id = remain; event_id < ITS_TEST_NUM_ITES; event_id += ITS_TEST_NEXT) {
|
||||
unsigned int irqn = vectors[devn][event_id];
|
||||
|
||||
last_lpi_irq_num = 0;
|
||||
zassert_true(its_send_int(dev, device_id, event_id) == 0, "");
|
||||
|
||||
timeout = ITS_TEST_LOOPS;
|
||||
while (!last_lpi_irq_num && timeout) {
|
||||
timeout--;
|
||||
}
|
||||
|
||||
zassert_true(last_lpi_irq_num == irqn,
|
||||
"IRQ %d of DeviceID %x EventID %d failed",
|
||||
irqn, device_id, event_id);
|
||||
}
|
||||
|
||||
remain = event_id - ITS_TEST_NUM_ITES;
|
||||
}
|
||||
}
|
||||
|
||||
void test_main(void)
|
||||
{
|
||||
ztest_test_suite(its_func,
|
||||
ztest_unit_test(test_gicv3_its_alloc),
|
||||
ztest_unit_test(test_gicv3_its_connect),
|
||||
ztest_unit_test(test_gicv3_its_irq_simple),
|
||||
ztest_unit_test(test_gicv3_its_irq_disable),
|
||||
ztest_unit_test(test_gicv3_its_irq));
|
||||
ztest_run_test_suite(its_func);
|
||||
}
|
5
tests/arch/arm64/arm64_gicv3_its/testcase.yaml
Normal file
5
tests/arch/arm64/arm64_gicv3_its/testcase.yaml
Normal file
|
@ -0,0 +1,5 @@
|
|||
tests:
|
||||
arch.arm64.gicv3_its:
|
||||
build_only: true
|
||||
platform_allow: fvp_base_revc_2xaemv8a
|
||||
skip: true
|
Loading…
Add table
Add a link
Reference in a new issue