blob: 38993ac9cb070b3ed98ea32a191e2aa00afe3534 [file] [log] [blame] [edit]
/*
* Copyright 2017, Data61, CSIRO (ABN 41 687 119 230)
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <autoconf.h>
#include <sel4test-driver/gen_config.h>
#include <sel4/sel4.h>
#include <sel4/benchmark_track_types.h>
#include <sel4utils/benchmark_track.h>
#include <vka/object.h>
#include <vka/capops.h>
#include <platsupport/local_time_manager.h>
#include "../timer.h"
#include <utils/util.h>
#if CONFIG_MAX_NUM_NODES > 1 && CONFIG_ARCH_ARM && CONFIG_TRACK_KERNEL_ENTRIES
static int is_timer_interrupt(driver_env_t env, int irq)
{
int i;
for (i = 0; i < env->timer.to.nirqs; i++) {
if (irq == env->timer.to.irqs[i].irq.irq.number) {
return 1;
}
}
return 0;
}
static int override_timer_irqs(driver_env_t env, int targetCore)
{
sel4ps_irq_t irq;
cspacepath_t path;
seL4_Error err;
int i;
for (i = 0; i < env->timer.to.nirqs; i++) {
irq = env->timer.to.irqs[i];
path = irq.handler_path;
/* Clear the current IRQ handler */
err = vka_cnode_delete(&path);
test_assert(err == seL4_NoError);
/* And replace it by the new, core specific handler */
err = seL4_IRQControl_GetTriggerCore(seL4_CapIRQControl, irq.irq.irq.number,
1, path.root, path.capPtr, path.capDepth, 1 << targetCore);
test_assert(err == seL4_NoError);
/* Rebind it with its notification object */
err = seL4_IRQHandler_SetNotification(irq.handler_path.capPtr, irq.badged_ntfn_path.capPtr);
test_assert(err == seL4_NoError);
}
}
static int test_core(driver_env_t env, int core)
{
int i;
seL4_Error err;
override_timer_irqs(env, core);
err = ltimer_set_timeout(&env->timer.ltimer, 1 * NS_IN_MS, TIMEOUT_PERIODIC);
test_assert_fatal(!err);
for (i = 0; i < 10; i++) {
wait_for_timer_interrupt(env);
}
err = ltimer_reset(&env->timer.ltimer);
test_assert_fatal(!err);
return 1;
}
static int test_core_affinity_interrupt(driver_env_t env)
{
cspacepath_t path;
seL4_Error err;
seL4_CPtr logBufferCap;
benchmark_track_kernel_entry_t *logBuffer;
unsigned nbLogEntries, i;
unsigned irqPerNode[CONFIG_MAX_NUM_NODES] = {0};
/* Set up logs */
logBuffer = vspace_new_pages(&env->vspace, seL4_AllRights, 1, seL4_SectionBits);
logBufferCap = vspace_get_cap(&env->vspace, logBuffer);
seL4_BenchmarkSetLogBuffer(logBufferCap);
/* Start logging */
seL4_BenchmarkResetLog();
for (i = 0; i < CONFIG_MAX_NUM_NODES; i++) {
test_core(env, i); /* Generate 10 interrupts routed to core i */
}
/* Stop logging */
nbLogEntries = seL4_BenchmarkFinalizeLog();
/* Iterate through the log to count all timer irqs delivered to each core */
for (i = 0; i < nbLogEntries; i++) {
if (logBuffer[i].entry.path == Entry_Interrupt) {
uint32_t irqVal = logBuffer[i].entry.word;
uint8_t irqCore = logBuffer[i].entry.core;
if (is_timer_interrupt(env, irqVal)) {
irqPerNode[irqCore]++;
}
}
}
/* Assert that exactly 10 timer irqs were delivered to each core */
for (i = 0; i < CONFIG_MAX_NUM_NODES; i++) {
test_assert(irqPerNode[i] == 10);
}
return sel4test_get_result();
}
DEFINE_TEST_BOOTSTRAP(SMPIRQ0001, "Test multicore irqs", test_core_affinity_interrupt, true);
#endif