Make nOS-V kernel overflow test configurable

This commit is contained in:
Rodrigo Arias 2024-07-31 11:53:01 +02:00 committed by Rodrigo Arias Mallo
parent e9788e22ad
commit acf18c1bb4
3 changed files with 75 additions and 23 deletions

View File

@ -44,7 +44,6 @@ nosv_test(parallel-tasks.c SORT)
nosv_test(inline.c SORT)
nosv_test(mutex.c SORT LEVEL 3)
nosv_test(barrier.c SORT LEVEL 3)
nosv_test(overflow-kernel-ring.c SORT LEVEL 3)
# Test multiple instrumentation levels
nosv_test(several-tasks.c SORT NAME several-tasks-level-0 LEVEL 0)
@ -63,3 +62,13 @@ nosv_test(several-tasks.c SORT NAME several-tasks-breakdown-level-2 LEVEL 2 BREA
# From level 3 up the breakdown can be enabled
nosv_test(several-tasks.c SORT NAME several-tasks-breakdown-level-3 LEVEL 3 BREAKDOWN)
nosv_test(several-tasks.c SORT NAME several-tasks-breakdown-level-4 LEVEL 4 BREAKDOWN)
include(CheckPerfParanoid)
if (PERF_PARANOID_KERNEL)
message(STATUS "Enabling perf paranoid tests for nOS-V")
nosv_test(overflow-kernel-ring.c DRIVER "overflow-kernel-ring.driver.sh")
elseif(ENABLE_ALL_TESTS)
message(FATAL_ERROR "Cannot enable perf paranoid tests for nOS-V")
else()
message(STATUS "Disabling perf paranoid tests for nOS-V")
endif()

View File

@ -5,47 +5,44 @@
#include <nosv/affinity.h>
#include <stdatomic.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include "common.h"
#include "compat.h"
int done = 0;
/* https://gitlab.bsc.es/nos-v/nos-v/-/blob/master/src/include/instr.h?ref_type=heads#L542 */
#define NOSV_INSTR_KBUFLEN (4UL * 1024UL * 1024UL) // 4 MB
unsigned long ncs = 0;
unsigned long nflush = 0;
static void
task_run(nosv_task_t task)
{
UNUSED(task);
/* Cause enough context switches for the kernel ring to be full,
* which wouldn't fail if nosv_waitfor() flushes the kernel
* events. */
unsigned long fill = 3 * NOSV_INSTR_KBUFLEN / 4;
unsigned long n = fill / 16;
struct timespec one_ns = { .tv_sec = 0, .tv_nsec = 1 };
for (unsigned long run = 0; run < 3; run++) {
info("starting run %lu", run);
for (unsigned long i = 0; i < n; i++)
nanosleep(&one_ns, NULL);
info("starting waitfor");
if (nosv_waitfor(1, NULL) != 0)
die("nosv_waitfor failed");
info("end run %lu", run);
for (unsigned long i = 1; i <= ncs; i++) {
nanosleep(&one_ns, NULL);
/* Make a total of 16 waitfor calls to flush the ring buffer */
if (i % nflush == 0) {
info("flusing at %lu", i);
if (nosv_waitfor(1, NULL) != 0)
die("nosv_waitfor failed");
}
}
done = 1;
}
int main(void)
int main(int argc, char *argv[])
{
if (argc != 3)
die("usage: %s <num-cs> <num-flush>\n", argv[0]);
ncs = (unsigned long) atol(argv[1]);
nflush = (unsigned long) atol(argv[2]);
if (nosv_init())
die("nosv_init failed");

View File

@ -0,0 +1,46 @@
target=$OVNI_TEST_BIN
# We will set our own
unset NOSV_CONFIG
unset NOSV_CONFIG_OVERRIDE
export NOSV_APPID=1
# Small kernel ring size to make execution fast
ringsize=$((64*1024))
# Each CS event pair occupies 16 bytes.
cspair=32
# How many CS event pairs fit in the ring buffer?
navail=$(($ringsize / $cspair))
# For the test, write 8 times the ring buffer
ncs=$((8 * $navail))
# Flush the kernel after writing 1/4 of the ring buffer.
nflush=$(($ringsize / $cspair / 4))
cat > nosv.toml << EOF
instrumentation.version = "ovni"
ovni.level = 3
ovni.kernel_ringsize = ${ringsize}
EOF
$target $ncs $nflush 2>&1 | tee err.log
# Ensure no nOS-V warnings at runtime
if grep -c "cannot enable kernel events" err.log; then
echo "cannot enable kernel events in all threads" >&2
exit 1
fi
# We need to sort the trace as it has unsorted regions
ovnisort ovni
# Ensure we have at least the number of context switches we caused, and ensure
# the number of "in" and "out" events match.
ovnitop ovni | awk '{n[$1] = $2} END { if (n["KCO"] != n["KCI"] || n["KCO"] < '$ncs') exit 1 }'
# Run the emulator
ovniemu -l ovni