From 6430f0823ff575aa4bc89fe5ade79da1a773ae7a Mon Sep 17 00:00:00 2001 From: Dave Patel Date: Thu, 27 Aug 2026 11:07:27 +0100 Subject: [PATCH] Adding Vector Context xtest Signed-off-by: Dave Patel --- host/xtest/regression_1000.c | 31 ++++++++++++ ta/os_test/include/os_test.h | 3 ++ ta/os_test/include/ta_os_test.h | 2 + ta/os_test/os_test.c | 82 +++++++++++++++++++++++++++++++ ta/os_test/riscv_vector_context.S | 43 ++++++++++++++++ ta/os_test/sub.mk | 4 ++ ta/os_test/ta_entry.c | 3 ++ 7 files changed, 168 insertions(+) create mode 100644 ta/os_test/riscv_vector_context.S diff --git a/host/xtest/regression_1000.c b/host/xtest/regression_1000.c index 82300fd0b..5a4833a1b 100644 --- a/host/xtest/regression_1000.c +++ b/host/xtest/regression_1000.c @@ -3408,3 +3408,34 @@ static void xtest_tee_test_1041(ADBG_Case_t *c) Do_ADBG_Log("Expected \"%s\" to be a character device", fname); } ADBG_CASE_DEFINE(regression, 1041, xtest_tee_test_1041, "Test fTPM sanity"); + + +static void xtest_tee_test_1046(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + TEEC_Result res = TEEC_ERROR_GENERIC; + uint32_t origin = 0; + + res = xtest_teec_open_session(&session, &os_test_ta_uuid, NULL, &origin); + ADBG_EXPECT_TEEC_SUCCESS(c, res); + if (res != TEEC_SUCCESS) + return; + + res = TEEC_InvokeCommand(&session, + TA_OS_TEST_CMD_RISCV_VECTOR_CONTEXT, + &op, &origin); + + if (res == TEEC_ERROR_NOT_SUPPORTED) { + Do_ADBG_Log("RISC-V Vector extension is not enabled"); + goto out; + } + + ADBG_EXPECT_TEEC_SUCCESS(c, res); + +out: + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 1046, xtest_tee_test_1046, + "RISC-V Vector context switching"); + diff --git a/ta/os_test/include/os_test.h b/ta/os_test/include/os_test.h index 62c237852..a9eba05a9 100644 --- a/ta/os_test/include/os_test.h +++ b/ta/os_test/include/os_test.h @@ -47,4 +47,7 @@ TEE_Result ta_entry_memtag_invalid_tag(void); TEE_Result ta_entry_memtag_double_free(void); TEE_Result ta_entry_memtag_buffer_overrun(void); +TEE_Result ta_entry_riscv_vector_context(uint32_t param_types, + TEE_Param params[4]); + #endif /*OS_TEST_H */ diff --git a/ta/os_test/include/ta_os_test.h b/ta/os_test/include/ta_os_test.h index 93785e2d9..0209cd125 100644 --- a/ta/os_test/include/ta_os_test.h +++ b/ta/os_test/include/ta_os_test.h @@ -47,5 +47,7 @@ #define TA_OS_TEST_CMD_MEMTAG_DOUBLE_FREE 35 #define TA_OS_TEST_CMD_MEMTAG_BUFFER_OVERRUN 36 #define TA_OS_TEST_CMD_TA2TA_MEMREF_SIZE0 37 +#define TA_OS_TEST_CMD_RISCV_FP_CONTEXT 38 +#define TA_OS_TEST_CMD_RISCV_VECTOR_CONTEXT 39 #endif /*TA_OS_TEST_H */ diff --git a/ta/os_test/os_test.c b/ta/os_test/os_test.c index 6833e0c3e..ce8b6cd50 100644 --- a/ta/os_test/os_test.c +++ b/ta/os_test/os_test.c @@ -1601,3 +1601,85 @@ TEE_Result ta_entry_memtag_buffer_overrun(void) TEE_Free(p); return TEE_ERROR_GENERIC; } + + +#define RISCV_VECTOR_REG_COUNT 32 +#define RISCV_VECTOR_MAX_VLENB 256 + +/* Forward declarations for assembly */ +void ta_vector_write_pattern(unsigned long pattern); +unsigned long ta_vector_verify_pattern(unsigned long pattern); + +void riscv_vector_test_load(const uint8_t *src, unsigned long *state); +void riscv_vector_test_store(uint8_t *dst, unsigned long *state); +unsigned long riscv_vector_test_vlenb(void); + +static void fill_vector_pattern(uint8_t *buf, size_t vlenb, + unsigned int round) +{ + size_t reg = 0; + size_t byte = 0; + + for (reg = 0; reg < RISCV_VECTOR_REG_COUNT; reg++) { + for (byte = 0; byte < vlenb; byte++) { + buf[reg * vlenb + byte] = + (uint8_t)(0x5aU ^ (reg * 17U) ^ + (byte * 3U) ^ round); + } + } +} + + + +TEE_Result ta_entry_riscv_vector_context(uint32_t param_types, + TEE_Param params[4]) +{ + unsigned long pattern = 0xA5A5A5A55A5A5A5AUL; + unsigned long failed; + TEE_Time time = { }; + + IMSG("TA: Initialising Vector registers with test pattern..."); + + /* Write to the vector registers. + * Note: In a production-ready OP-TEE OS, the secure kernel must catch + * the U-mode Vector Trap, update status registers, and enable vector extensions + * transparently for the calling TA thread. */ + IMSG("Dave TA: Before Context Switch\n"); + ta_vector_write_pattern(pattern); + + /* Force a context switch to Normal World. + * TEE_Wait yields the current secure thread back to the rich OS (REE) + * scheduler for 50 milliseconds, ensuring a hard swap of the register sets. */ + IMSG("Dave TA: GetSystemTime force a context switch..."); + //TEE_Wait(50); + TEE_GetSystemTime(&time); + IMSG("Dave TA: First Resumed. Verifying Vector register integrity..."); + + IMSG("Dave TA: After First Context Switch\n"); + + /* Read back and verify */ + failed = ta_vector_verify_pattern(pattern); + if (failed) { + EMSG("TA: FAILURE! Vector context corrupted after GetSystemTime context switch."); + return TEE_ERROR_SECURITY; + } + + + IMSG("Dave TA: Sleeping for 50ms to force a context switch..."); + //TEE_Wait(50); + TEE_GetSystemTime(&time); + IMSG("Dave TA: Second Resumed. Verifying Vector register integrity..."); + IMSG("Dave TA: After Second Context Switch\n"); + + failed = ta_vector_verify_pattern(pattern); + + if (failed) { + EMSG("TA: FAILURE! Vector context corrupted after wait 50 ms context switch."); + return TEE_ERROR_SECURITY; + } + + IMSG("Dave TA: SUCCESS! Vector context switch verified perfectly."); + return TEE_SUCCESS; +} + + diff --git a/ta/os_test/riscv_vector_context.S b/ta/os_test/riscv_vector_context.S new file mode 100644 index 000000000..dfa8de876 --- /dev/null +++ b/ta/os_test/riscv_vector_context.S @@ -0,0 +1,43 @@ +.global ta_vector_write_pattern +.global ta_vector_verify_pattern + +/* + * void ta_vector_write_pattern(unsigned long pattern); + */ +ta_vector_write_pattern: + /* Configure vector unit: 64-bit element width, LMUL=1 */ + vsetvli t0, x0, e64, m1, ta, ma + + /* Broadcast scalar value in a0 (pattern) to vector registers v0-v3 */ + vmv.v.x v0, a0 + vmv.v.x v1, a0 + vmv.v.x v2, a0 + vmv.v.x v3, a0 + ret + +/* + * unsigned long ta_vector_verify_pattern(unsigned long pattern); + * Returns 0 on success, 1 on failure. + */ +ta_vector_verify_pattern: + vsetvli t0, x0, e64, m1, ta, ma + + /* Pull the first element of each vector back to scalar registers */ + vmv.x.s t1, v0 + vmv.x.s t2, v1 + vmv.x.s t3, v2 + vmv.x.s t4, v3 + + /* Check elements against the original pattern in a0 */ + bne t1, a0, .L_fail + bne t2, a0, .L_fail + bne t3, a0, .L_fail + bne t4, a0, .L_fail + + li a0, 0 + ret + +.L_fail: + li a0, 1 + ret + diff --git a/ta/os_test/sub.mk b/ta/os_test/sub.mk index 0b080c04d..0230fd150 100644 --- a/ta/os_test/sub.mk +++ b/ta/os_test/sub.mk @@ -28,3 +28,7 @@ srcs-$(CFG_TA_PAUTH) += ta_arm_pauth.c cflags-$(CFG_TA_PAUTH) += -march=armv8.3-a endif srcs-y += attestation.c +srcs-y += riscv_vector_context.S + +cflags-os_test.c-y += -march=rv64imafdcv_zicsr_zifencei +aflags-riscv_vector_context.S-y += -march=rv64imafdcv_zicsr_zifencei diff --git a/ta/os_test/ta_entry.c b/ta/os_test/ta_entry.c index 56f3ef0ae..03a804201 100644 --- a/ta/os_test/ta_entry.c +++ b/ta/os_test/ta_entry.c @@ -181,6 +181,9 @@ TEE_Result TA_InvokeCommandEntryPoint(void *pSessionContext, case TA_OS_TEST_CMD_ATTESTATION: return ta_entry_attestation(nParamTypes, pParams); + case TA_OS_TEST_CMD_RISCV_VECTOR_CONTEXT: + return ta_entry_riscv_vector_context(nParamTypes, pParams); + default: return TEE_ERROR_BAD_PARAMETERS; }