Skip to content

Commit 770617d

Browse files
committed
tests/ci: add RISC-V SMP sdk suite cases and CI job
- smp_smoke/affinity/ipc_cross/stress/vs_up under tests/sdk_suite - Wire --include-smp / --enable-smp through dev.py and sdk_build
1 parent 4f0177f commit 770617d

19 files changed

Lines changed: 540 additions & 20 deletions

File tree

.github/workflows/ci.yml

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,48 @@ jobs:
233233
path: ci-results/e2e-riscv/
234234
if-no-files-found: warn
235235

236+
# ── RISC-V SMP: full SDK suite + smp_* multi-hart cases ───────────────────
237+
# QEMU multi-hart is RISC-V virt only. UP jobs above stay single-core and
238+
# deliberately omit sdk_suite/smp_*.
239+
integ-tests-riscv-smp:
240+
name: SDK suite (RISC-V SMP)
241+
needs: docker-image
242+
runs-on: ubuntu-latest
243+
timeout-minutes: 120
244+
permissions:
245+
contents: read
246+
packages: read
247+
steps:
248+
- uses: actions/checkout@v4
249+
250+
- name: Log in to GHCR
251+
uses: docker/login-action@v3
252+
with:
253+
registry: ghcr.io
254+
username: ${{ github.actor }}
255+
password: ${{ secrets.GITHUB_TOKEN }}
256+
257+
- name: Pull image
258+
run: |
259+
IMG="${{ needs.docker-image.outputs.image }}:sha-${{ github.sha }}"
260+
docker pull "$IMG"
261+
docker tag "$IMG" ulipe-microkernel:dev
262+
263+
- name: Run SDK suite (UP + SMP)
264+
run: |
265+
python3 tools/dev.py tests e2e \
266+
--board boards/qemu_riscv_virt \
267+
--include-smp \
268+
--json-dir ci-results/e2e-riscv-smp
269+
270+
- name: Upload RISC-V SMP results
271+
if: always()
272+
uses: actions/upload-artifact@v4
273+
with:
274+
name: test-results-riscv-smp
275+
path: ci-results/e2e-riscv-smp/
276+
if-no-files-found: warn
277+
236278
# ── ARM Cortex-M: build (mps2-an500 M7 + mps2-an505 M33) ──────────────────
237279
build-arm:
238280
name: Build kernel (ARM ${{ matrix.board }})
@@ -310,7 +352,12 @@ jobs:
310352
# ── Aggregate markdown report (PASS/FAIL/PARTIAL + coverage matrix) ─────
311353
coverage-report:
312354
name: Test coverage report
313-
needs: [unit-tests, integ-tests-tricore, integ-tests-riscv, integ-tests-arm]
355+
needs:
356+
- unit-tests
357+
- integ-tests-tricore
358+
- integ-tests-riscv
359+
- integ-tests-riscv-smp
360+
- integ-tests-arm
314361
if: always()
315362
runs-on: ubuntu-latest
316363
permissions:

tests/sdk_suite/_common/sdk_test_util.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ static inline ulmk_tid_t sdk_spawn_priv(const char *name, void (*entry)(void *),
5757
void *arg, uint8_t prio, size_t stack,
5858
size_t heap, ulmk_privilege_t priv)
5959
{
60-
ulmk_thread_attr_t a;
60+
ulmk_thread_attr_t a = {0};
6161

6262
a.name = name;
6363
a.entry = entry;
@@ -66,6 +66,7 @@ static inline ulmk_tid_t sdk_spawn_priv(const char *name, void (*entry)(void *),
6666
a.stack_size = stack;
6767
a.privilege = priv;
6868
a.heap_size = heap;
69+
a.cpu = 0u;
6970
return ulmk_thread_create(&a);
7071
}
7172

tests/sdk_suite/abi_smoke/root_thread.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ static void idle_target(void *arg)
138138
static ulmk_tid_t spawn(const char *name, void (*entry)(void *), void *arg,
139139
uint8_t prio, size_t heap)
140140
{
141-
ulmk_thread_attr_t a;
141+
ulmk_thread_attr_t a = {0};
142142

143143
a.name = name;
144144
a.entry = entry;

tests/sdk_suite/cap_neg/root_thread.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ static void idle_victim(void *arg)
5858

5959
static void user_probe(void *arg)
6060
{
61-
ulmk_thread_attr_t a;
61+
ulmk_thread_attr_t a = {0};
6262
ulmk_notif_t n;
6363
void *p;
6464
ulmk_tid_t tid;
@@ -90,7 +90,7 @@ static void user_probe(void *arg)
9090

9191
static void driver_probe(void *arg)
9292
{
93-
ulmk_thread_attr_t a;
93+
ulmk_thread_attr_t a = {0};
9494
ulmk_notif_t n;
9595
void *p;
9696
ulmk_tid_t tid;

tests/sdk_suite/sdk_case.mk

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,19 @@ MACHINE := virt
3434
QEMU_EXTRA := -bios none -m 16M
3535
BOARD := boards/qemu_riscv_virt
3636
ARCH_FLAGS := -march=rv32imac_zicsr_zifencei -mabi=ilp32
37+
# Optional: CASE Makefile sets SMP=1 for multi-hart SDK + QEMU -smp 2
38+
SMP ?= 0
39+
ifeq ($(SMP),1)
40+
ifneq ($(ARCH),riscv)
41+
$(error SMP sdk_suite cases require ARCH=riscv)
42+
endif
43+
QEMU_EXTRA += -smp 2
44+
SDK_SMP_FLAG := --enable-smp
45+
TAG_SUFFIX := _smp
46+
else
47+
SDK_SMP_FLAG :=
48+
TAG_SUFFIX :=
49+
endif
3750
else ifeq ($(ARCH),arm)
3851
ARM_BOARD ?= qemu_mps2_an500
3952
CC := arm-none-eabi-gcc
@@ -52,7 +65,10 @@ $(error unsupported ARCH '$(ARCH)' — use tricore, riscv or arm)
5265
endif
5366

5467
BOARD_NAME := $(notdir $(BOARD))
55-
TAG := $(ARCH)_$(BOARD_NAME)_gcc
68+
# Non-riscv boards: TAG_SUFFIX / SDK_SMP_FLAG empty
69+
TAG_SUFFIX ?=
70+
SDK_SMP_FLAG ?=
71+
TAG := $(ARCH)_$(BOARD_NAME)_gcc$(TAG_SUFFIX)
5672
TOOLCHAIN := $(WS)/cmake/toolchain-$(ARCH)-gcc.cmake
5773

5874
# Shared cache (preferred) or per-case _out/
@@ -105,7 +121,8 @@ sdk:
105121
--arch $(ARCH) \
106122
--board-name $(BOARD_NAME) \
107123
--build-dir $(BUILD) \
108-
--out-dir $(SDK); \
124+
--out-dir $(SDK) \
125+
$(SDK_SMP_FLAG); \
109126
fi
110127

111128
all: sdk $(TARGET)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CASE_NAME := smp_affinity
2+
CASE_SRCS := root_thread.c
3+
SENTINELS := "smp_affinity: PASS"
4+
FAIL_SENTINEL := "smp_affinity: FAIL"
5+
QEMU_TIMEOUT := 60
6+
SMP := 1
7+
8+
include ../sdk_case.mk
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/* SPDX-License-Identifier: MIT */
2+
#include <stdint.h>
3+
#include <ulmk/microkernel.h>
4+
#include <board_services.h>
5+
#include <board_console.h>
6+
7+
static volatile uint32_t g_samples[32];
8+
static volatile uint32_t g_n;
9+
static volatile uint32_t g_pin1_started;
10+
static ulmk_notif_t g_done;
11+
12+
static void pin1(void *arg)
13+
{
14+
uint32_t i;
15+
16+
(void)arg;
17+
g_pin1_started = 1u;
18+
for (i = 0u; i < 32u; i++) {
19+
g_samples[i] = ulmk_cpu_id();
20+
ulmk_thread_yield();
21+
}
22+
g_n = 32u;
23+
ulmk_notif_signal(g_done, 0x1u);
24+
ulmk_thread_exit();
25+
}
26+
27+
void ulmk_root_thread(const ulmk_boot_info_t *info)
28+
{
29+
ulmk_thread_attr_t attr = {0};
30+
uint32_t bits = 0;
31+
uint32_t i;
32+
ulmk_tid_t tid;
33+
34+
(void)info;
35+
board_services_init(info);
36+
board_console_puts("smp_affinity: begin\n");
37+
38+
if (ulmk_cpu_id() != 0u) {
39+
board_console_puts("smp_affinity: FAIL root cpu\n");
40+
for (;;)
41+
;
42+
}
43+
44+
g_done = ulmk_notif_create();
45+
board_console_puts("smp_affinity: notif\n");
46+
47+
attr.name = "pin1";
48+
attr.entry = pin1;
49+
attr.priority = 1u;
50+
attr.stack_size = 2048u;
51+
attr.privilege = ULMK_PRIV_DRIVER;
52+
attr.cpu = 1u;
53+
tid = ulmk_thread_create(&attr);
54+
if (tid == ULMK_TID_INVALID) {
55+
board_console_puts("smp_affinity: FAIL spawn\n");
56+
for (;;)
57+
;
58+
}
59+
board_console_puts("smp_affinity: spawned\n");
60+
61+
for (i = 0u; i < 100000u && g_pin1_started == 0u; i++)
62+
ulmk_thread_yield();
63+
64+
if (g_pin1_started == 0u) {
65+
board_console_puts("smp_affinity: FAIL pin1 never ran\n");
66+
for (;;)
67+
;
68+
}
69+
board_console_puts("smp_affinity: pin1 ok\n");
70+
71+
ulmk_notif_wait(g_done, 0x1u, &bits);
72+
73+
if (g_n != 32u) {
74+
board_console_puts("smp_affinity: FAIL short samples\n");
75+
for (;;)
76+
;
77+
}
78+
79+
for (i = 0u; i < g_n; i++) {
80+
if (g_samples[i] != 1u) {
81+
board_console_puts("smp_affinity: FAIL migrated\n");
82+
for (;;)
83+
;
84+
}
85+
}
86+
board_console_puts("smp_affinity: PASS\n");
87+
ulmk_thread_exit();
88+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CASE_NAME := smp_ipc_cross
2+
CASE_SRCS := root_thread.c
3+
SENTINELS := "smp_ipc_cross: PASS"
4+
FAIL_SENTINEL := "smp_ipc_cross: FAIL"
5+
QEMU_TIMEOUT := 60
6+
SMP := 1
7+
8+
include ../sdk_case.mk
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/* SPDX-License-Identifier: MIT */
2+
/*
3+
* Cross-CPU wake path used by IPC reply (remote enqueue + IPI + notif).
4+
* Full ep_call/reply rendezvous under ISR preemption needs per-hart IRQ
5+
* stacks — tracked separately from the SMP overnight MVP.
6+
*/
7+
#include <stdint.h>
8+
#include <ulmk/microkernel.h>
9+
#include <board_services.h>
10+
#include <board_console.h>
11+
12+
static volatile uint32_t g_seen;
13+
static ulmk_notif_t g_done;
14+
15+
static void worker_cpu1(void *arg)
16+
{
17+
(void)arg;
18+
g_seen = ulmk_cpu_id();
19+
ulmk_notif_signal(g_done, 0x1u);
20+
ulmk_thread_exit();
21+
}
22+
23+
void ulmk_root_thread(const ulmk_boot_info_t *info)
24+
{
25+
ulmk_thread_attr_t attr = {0};
26+
uint32_t bits = 0;
27+
uint32_t i;
28+
29+
(void)info;
30+
board_services_init(info);
31+
board_console_puts("smp_ipc_cross: begin\n");
32+
33+
g_done = ulmk_notif_create();
34+
attr.name = "w1";
35+
attr.entry = worker_cpu1;
36+
attr.priority = 1u;
37+
attr.stack_size = 2048u;
38+
attr.privilege = ULMK_PRIV_DRIVER;
39+
attr.cpu = 1u;
40+
if (ulmk_thread_create(&attr) == ULMK_TID_INVALID) {
41+
board_console_puts("smp_ipc_cross: FAIL spawn\n");
42+
for (;;)
43+
;
44+
}
45+
46+
for (i = 0u; i < 100000u && g_seen == 0u; i++)
47+
ulmk_thread_yield();
48+
49+
ulmk_notif_wait(g_done, 0x1u, &bits);
50+
if (g_seen != 1u) {
51+
board_console_puts("smp_ipc_cross: FAIL\n");
52+
for (;;)
53+
;
54+
}
55+
board_console_puts("smp_ipc_cross: PASS\n");
56+
ulmk_thread_exit();
57+
}

tests/sdk_suite/smp_smoke/Makefile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CASE_NAME := smp_smoke
2+
CASE_SRCS := root_thread.c
3+
SENTINELS := "smp_smoke: PASS"
4+
FAIL_SENTINEL := "smp_smoke: FAIL"
5+
QEMU_TIMEOUT := 60
6+
SMP := 1
7+
8+
include ../sdk_case.mk

0 commit comments

Comments
 (0)