From cef0d6677ff1044dda48527f9226bc139a54167b Mon Sep 17 00:00:00 2001 From: Subrahmanya Lingappa Date: Fri, 15 May 2026 11:22:35 +0530 Subject: [PATCH 01/10] test: make RPMI harness report failures Propagate per-test mismatches into scenario return status so make check fails when a comparison fails. Also copy request flags into the RPMI message header, verify ACK header identity for normal requests, and reject unexpected ACKs for posted requests. This makes the existing tests validate protocol behavior instead of only printing failures. Signed-off-by: Subrahmanya Lingappa --- test/test_common.c | 100 +++++++++++++++++++++++++++++++++++++++------ test/test_common.h | 6 +++ 2 files changed, 93 insertions(+), 13 deletions(-) diff --git a/test/test_common.c b/test/test_common.c index f39edf1..6549a09 100644 --- a/test/test_common.c +++ b/test/test_common.c @@ -78,8 +78,61 @@ static void test_wait(struct rpmi_test_scenario *scene, struct rpmi_test *test, } } +static int test_check_no_ack(struct rpmi_test_scenario *scene, + struct rpmi_test *test, + struct rpmi_message *resp_msg) +{ + int rc; + + rpmi_env_memset(resp_msg, 0, sizeof(*resp_msg)); + rc = rpmi_transport_dequeue(scene->xport, RPMI_QUEUE_P2A_ACK, resp_msg); + if (rc == RPMI_ERR_IO) + return 0; + + if (rc == RPMI_SUCCESS) + printf("%s: unexpected acknowledgment for posted request\n", test->name); + else + printf("%s: failed to check acknowledgment queue (error %d)\n", + test->name, rc); + + return 1; +} + +static int test_verify_header(struct rpmi_test *test, struct rpmi_message *msg, + rpmi_uint16_t token) +{ + int failed = 0; + + if (msg->header.flags != RPMI_MSG_ACKNOWLEDGEMENT) { + printf("%s: response flags mismatch: expected: %d, got: %d\n", + test->name, RPMI_MSG_ACKNOWLEDGEMENT, msg->header.flags); + failed = 1; + } + + if (msg->header.servicegroup_id != test->attrs.servicegroup_id) { + printf("%s: response servicegroup mismatch: expected: %d, got: %d\n", + test->name, test->attrs.servicegroup_id, msg->header.servicegroup_id); + failed = 1; + } + + if (msg->header.service_id != test->attrs.service_id) { + printf("%s: response service mismatch: expected: %d, got: %d\n", + test->name, test->attrs.service_id, msg->header.service_id); + failed = 1; + } + + if (msg->header.token != token) { + printf("%s: response token mismatch: expected: %d, got: %d\n", + test->name, token, msg->header.token); + failed = 1; + } + + return failed; +} + static void test_verify(struct rpmi_test *test, struct rpmi_message *msg, - void *exp_data, rpmi_uint16_t exp_data_len) + void *exp_data, rpmi_uint16_t exp_data_len, + int *nfail) { int failed = 0; @@ -107,33 +160,36 @@ static void test_verify(struct rpmi_test *test, struct rpmi_message *msg, } printf("TEST: %-50s \t : %s!\n", test->name, failed ? "Failed" : "Succeeded"); + if (failed) + (*nfail)++; } -static void execute_scenario(struct rpmi_test_scenario *scene) +static int execute_scenario(struct rpmi_test_scenario *scene) { struct rpmi_message *req_msg, *resp_msg; rpmi_uint16_t exp_data_len; struct rpmi_test *test; void *exp_data; - int i, rc; + rpmi_uint16_t token; + int i, rc, failed, nfail = 0; req_msg = rpmi_env_zalloc(scene->slot_size); if (!req_msg) { printf("Failed to allocate request message\n"); - return; + return 1; } exp_data = rpmi_env_zalloc(RPMI_MSG_DATA_SIZE(scene->slot_size)); if (!exp_data) { printf("Failed to allocate expected message\n"); rpmi_env_free(req_msg); - return; + return 1; } resp_msg = rpmi_env_zalloc(scene->slot_size); if (!resp_msg) { printf("Failed to allocate response message\n"); rpmi_env_free(exp_data); rpmi_env_free(req_msg); - return; + return 1; } printf("\nExecuting %s test scenario :\n", scene->name); @@ -148,13 +204,16 @@ static void execute_scenario(struct rpmi_test_scenario *scene) rc = 0; if (rc) { printf("Failed to initialize test %s (error %d)\n", test->name, rc); + nfail++; continue; } /* Initialize request message header */ req_msg->header.servicegroup_id = test->attrs.servicegroup_id; req_msg->header.service_id = test->attrs.service_id; + req_msg->header.flags = test->attrs.flags; req_msg->header.datalen = 0; + token = scene->token_sequence; req_msg->header.token = scene->token_sequence; scene->token_sequence++; @@ -178,6 +237,7 @@ static void execute_scenario(struct rpmi_test_scenario *scene) rc = test_run(scene, test, req_msg); if (rc) { printf("Failed to run test %s (error %d)\n", test->name, rc); + nfail++; goto skip; } @@ -186,14 +246,25 @@ static void execute_scenario(struct rpmi_test_scenario *scene) else scenario_process(scene); + failed = 0; + if ((test->attrs.flags & RPMI_MSG_FLAGS_TYPE) == RPMI_MSG_POSTED_REQUEST) + failed = test_check_no_ack(scene, test, resp_msg); + /* Wait for test to finish */ if (test->wait) test->wait(scene, test, resp_msg); - else + else if (!failed) test_wait(scene, test, resp_msg); + if (!failed && (test->attrs.flags & RPMI_MSG_FLAGS_TYPE) == RPMI_MSG_NORMAL_REQUEST) + failed = test_verify_header(test, resp_msg, token); + /* Verify and report */ - test_verify(test, resp_msg, exp_data, exp_data_len); + test_verify(test, resp_msg, exp_data, exp_data_len, &failed); + if (test->verify) + failed += test->verify(scene, test, resp_msg); + if (failed) + nfail++; skip: /* Cleanup if needed */ @@ -204,6 +275,8 @@ static void execute_scenario(struct rpmi_test_scenario *scene) rpmi_env_free(resp_msg); rpmi_env_free(exp_data); rpmi_env_free(req_msg); + + return nfail; } rpmi_uint16_t test_init_request_data_from_attrs(struct rpmi_test_scenario *scene, @@ -313,13 +386,14 @@ int test_scenario_execute(struct rpmi_test_scenario *scene) return rc; } - execute_scenario(scene); + rc = execute_scenario(scene); + if (rc) + printf("%d test(s) failed in scenario %s\n", rc, scene->name); - rc = scene->cleanup(scene); - if (rc) { + if (scene->cleanup(scene)) { printf("Failed to cleanup test scenario %s\n", scene->name); - return rc; + return RPMI_ERR_FAILED; } - return 0; + return rc ? RPMI_ERR_FAILED : 0; } diff --git a/test/test_common.h b/test/test_common.h index 29cd5a1..5d8ab20 100644 --- a/test/test_common.h +++ b/test/test_common.h @@ -11,6 +11,10 @@ #include #include +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#endif + /* * Qemu shared memory offsets. * its better to decode these data from DTS file, hardcoding for now. @@ -51,6 +55,8 @@ struct rpmi_test { struct rpmi_message *msg); void (*wait)(struct rpmi_test_scenario *scene, struct rpmi_test *test, struct rpmi_message *msg); + int (*verify)(struct rpmi_test_scenario *scene, struct rpmi_test *test, + struct rpmi_message *msg); void (*cleanup)(struct rpmi_test_scenario *scene, struct rpmi_test *test); }; From a120cfafefbf4fe8a14afe9554c1bab1d730c6d8 Mon Sep 17 00:00:00 2001 From: Subrahmanya Lingappa Date: Fri, 15 May 2026 11:22:35 +0530 Subject: [PATCH 02/10] test: expand BASE service group coverage Add BASE probe coverage for unregistered, experimental, and vendor service group IDs, plus an invalid BASE service ID case. This complements the existing positive BASE service tests and relies on the shared harness ACK header checks to verify token, service group, and service ID mirroring for normal requests. Signed-off-by: Subrahmanya Lingappa --- test/test_srvgrp_base.c | 76 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/test/test_srvgrp_base.c b/test/test_srvgrp_base.c index f669526..ca5a9f3 100644 --- a/test/test_srvgrp_base.c +++ b/test/test_srvgrp_base.c @@ -50,6 +50,27 @@ static rpmi_uint32_t probe_expdata_default[] = { RPMI_BASE_VERSION(1, 0), }; +static rpmi_uint32_t probe_sysreset_reqdata_default[] = { + RPMI_SRVGRP_SYSTEM_RESET, +}; + +static rpmi_uint32_t probe_unsupported_expdata_default[] = { + RPMI_SUCCESS, + 0, +}; + +static rpmi_uint32_t probe_experimental_reqdata_default[] = { + RPMI_SRVGRP_EXPERIMENTAL_START, +}; + +static rpmi_uint32_t probe_vendor_reqdata_default[] = { + RPMI_SRVGRP_VENDOR_START, +}; + +static rpmi_uint32_t invalid_service_expdata_default[] = { + RPMI_ERR_NOTSUPP, +}; + static rpmi_uint32_t attribs_expdata_default[] = { RPMI_SUCCESS, RPMI_BASE_FLAGS_F0_PRIVILEGE, @@ -70,7 +91,7 @@ static struct rpmi_test_scenario scenario_base_default = { .init = test_scenario_default_init, .cleanup = test_scenario_default_cleanup, - .num_tests = 7, + .num_tests = 11, .tests = { { .name = "RPMI_BASE_SRV_ENABLE_NOTIFICATION", @@ -141,6 +162,59 @@ static struct rpmi_test_scenario scenario_base_default = { .init_request_data = test_init_request_data_from_attrs, .init_expected_data = test_init_expected_data_from_attrs, }, + { + .name = "RPMI_BASE_SRV_PROBE_SERVICE_GROUP unsupported", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_BASE, + .service_id = RPMI_BASE_SRV_PROBE_SERVICE_GROUP, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = probe_sysreset_reqdata_default, + .request_data_len = sizeof(probe_sysreset_reqdata_default), + .expected_data = probe_unsupported_expdata_default, + .expected_data_len = sizeof(probe_unsupported_expdata_default), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "RPMI_BASE_SRV_PROBE_SERVICE_GROUP experimental", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_BASE, + .service_id = RPMI_BASE_SRV_PROBE_SERVICE_GROUP, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = probe_experimental_reqdata_default, + .request_data_len = sizeof(probe_experimental_reqdata_default), + .expected_data = probe_unsupported_expdata_default, + .expected_data_len = sizeof(probe_unsupported_expdata_default), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "RPMI_BASE_SRV_PROBE_SERVICE_GROUP vendor", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_BASE, + .service_id = RPMI_BASE_SRV_PROBE_SERVICE_GROUP, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = probe_vendor_reqdata_default, + .request_data_len = sizeof(probe_vendor_reqdata_default), + .expected_data = probe_unsupported_expdata_default, + .expected_data_len = sizeof(probe_unsupported_expdata_default), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "RPMI_BASE invalid service", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_BASE, + .service_id = RPMI_BASE_SRV_ID_MAX, + .flags = RPMI_MSG_NORMAL_REQUEST, + .expected_data = invalid_service_expdata_default, + .expected_data_len = sizeof(invalid_service_expdata_default), + }, + .init_expected_data = test_init_expected_data_from_attrs, + }, { .name = "RPMI_BASE_SRV_GET_ATTRIBUTES", .attrs = { From 489a78f7fa8b63c3e2b0ace7f6b25ea96419a650 Mon Sep 17 00:00:00 2001 From: Subrahmanya Lingappa Date: Fri, 15 May 2026 11:22:35 +0530 Subject: [PATCH 03/10] test: verify SYSTEM_RESET callback behavior Track reset callback invocation count and reset type so posted SYSTEM_RESET requests are validated beyond response payload checks. Cover both configured reset types, shutdown and cold reboot, and add an unsupported reset-type posted request to verify the platform callback is not invoked. The shared harness also verifies that posted requests do not generate acknowledgements. Signed-off-by: Subrahmanya Lingappa --- test/test_srvgrp_sysreset.c | 90 ++++++++++++++++++++++++++++++++++++- 1 file changed, 89 insertions(+), 1 deletion(-) diff --git a/test/test_srvgrp_sysreset.c b/test/test_srvgrp_sysreset.c index b870397..9b6cd5d 100644 --- a/test/test_srvgrp_sysreset.c +++ b/test/test_srvgrp_sysreset.c @@ -66,8 +66,24 @@ static rpmi_uint32_t reset_reqdata_supp[] = { RPMI_SYSRST_TYPE_COLD_REBOOT, }; +static rpmi_uint32_t reset_reqdata_shutdown[] = { + RPMI_SYSRST_TYPE_SHUTDOWN, +}; + +static rpmi_uint32_t reset_reqdata_unsupported[] = { + RPMI_SYSRST_TYPE_WARM_REBOOT, +}; + +static rpmi_uint32_t reset_type_cold = RPMI_SYSRST_TYPE_COLD_REBOOT; +static rpmi_uint32_t reset_type_shutdown = RPMI_SYSRST_TYPE_SHUTDOWN; + +static rpmi_uint32_t test_reset_call_count; +static rpmi_uint32_t test_reset_last_type = RPMI_SYSRST_TYPE_MAX; + static void rpmi_do_system_reset(void *priv, rpmi_uint32_t reset_type) { + test_reset_call_count++; + test_reset_last_type = reset_type; if (reset_type == RPMI_SYSRST_TYPE_WARM_REBOOT) { printf("platform callback: warm reset\n"); } else if (reset_type == RPMI_SYSRST_TYPE_COLD_REBOOT) { @@ -85,6 +101,48 @@ struct rpmi_sysreset_platform_ops rpmi_reset_ops = { .do_system_reset = rpmi_do_system_reset }; +static int test_reset_callback_init(struct rpmi_test_scenario *scene, + struct rpmi_test *test) +{ + test_reset_call_count = 0; + test_reset_last_type = RPMI_SYSRST_TYPE_MAX; + return 0; +} + +static int test_reset_callback_verify(struct rpmi_test_scenario *scene, + struct rpmi_test *test, + struct rpmi_message *msg) +{ + rpmi_uint32_t expected_type = *(rpmi_uint32_t *)test->priv; + + if (test_reset_call_count != 1) { + printf("%s: expected one reset callback, got %d\n", + test->name, test_reset_call_count); + return 1; + } + + if (test_reset_last_type != expected_type) { + printf("%s: expected reset type %d, got %d\n", + test->name, expected_type, test_reset_last_type); + return 1; + } + + return 0; +} + +static int test_no_reset_callback_verify(struct rpmi_test_scenario *scene, + struct rpmi_test *test, + struct rpmi_message *msg) +{ + if (test_reset_call_count) { + printf("%s: unexpected reset callback count %d, last type %d\n", + test->name, test_reset_call_count, test_reset_last_type); + return 1; + } + + return 0; +} + static int test_sysreset_scenario_init(struct rpmi_test_scenario *scene) { int ret; @@ -112,7 +170,7 @@ static struct rpmi_test_scenario scenario_sysreset_default = { .init = test_sysreset_scenario_init, .cleanup = test_scenario_default_cleanup, - .num_tests = 5, + .num_tests = 7, .tests = { { .name = "ENABLE NOTIFICATION TEST (notifications not supported)", @@ -180,6 +238,36 @@ static struct rpmi_test_scenario scenario_sysreset_default = { .request_data_len = sizeof(reset_reqdata_supp), }, .init_request_data = test_init_request_data_from_attrs, + .init = test_reset_callback_init, + .verify = test_reset_callback_verify, + .priv = &reset_type_cold, + }, + { + .name = "SYSTEM RESET (shutdown reset type)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_SYSTEM_RESET, + .service_id = RPMI_SYSRST_SRV_SYSTEM_RESET, + .flags = RPMI_MSG_POSTED_REQUEST, + .request_data = reset_reqdata_shutdown, + .request_data_len = sizeof(reset_reqdata_shutdown), + }, + .init_request_data = test_init_request_data_from_attrs, + .init = test_reset_callback_init, + .verify = test_reset_callback_verify, + .priv = &reset_type_shutdown, + }, + { + .name = "SYSTEM RESET (unsupported reset type)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_SYSTEM_RESET, + .service_id = RPMI_SYSRST_SRV_SYSTEM_RESET, + .flags = RPMI_MSG_POSTED_REQUEST, + .request_data = reset_reqdata_unsupported, + .request_data_len = sizeof(reset_reqdata_unsupported), + }, + .init_request_data = test_init_request_data_from_attrs, + .init = test_reset_callback_init, + .verify = test_no_reset_callback_verify, }, }, }; From 5fb469d1997d95f0545c65555bd8c8eaeda04f0a Mon Sep 17 00:00:00 2001 From: Subrahmanya Lingappa Date: Fri, 15 May 2026 11:22:35 +0530 Subject: [PATCH 04/10] test: expand HSM suspend service coverage Add coverage for HSM_GET_SUSPEND_TYPES with no configured suspend types, HSM_GET_SUSPEND_INFO for an invalid type, and HSM_HART_SUSPEND with a full invalid-type request. These cases cover previously untested HSM service IDs and distinguish a malformed short suspend request from a valid-length request with an invalid suspend type. Signed-off-by: Subrahmanya Lingappa --- test/test_srvgrp_hsm.c | 84 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) diff --git a/test/test_srvgrp_hsm.c b/test/test_srvgrp_hsm.c index 94712f3..629fcc4 100644 --- a/test/test_srvgrp_hsm.c +++ b/test/test_srvgrp_hsm.c @@ -96,6 +96,33 @@ static rpmi_uint32_t get_hart_state_invalid_hartid_expdata[] = { TEST_HART_STATE_IGNORED_VALUE }; +/* Get Suspend Types - Request Data */ +static rpmi_uint32_t get_suspend_types_reqdata[] = { + 0, +}; + +/* Get Suspend Types - Response Data */ +static rpmi_uint32_t get_suspend_types_expdata[] = { + RPMI_SUCCESS, + 0, + 0, +}; + +/* Get Suspend Info invalid type - Request Data */ +static rpmi_uint32_t get_suspend_info_invalid_reqdata[] = { + 0, +}; + +/* Get Suspend Info invalid type - Response Data */ +static rpmi_uint32_t get_suspend_info_invalid_expdata[] = { + RPMI_ERR_INVALID_PARAM, + 0, + 0, + 0, + 0, + 0, +}; + /* Hart Start (valid hartid) - Request Data */ static rpmi_uint32_t hart_start_valid_hartid_reqdata[] = { TEST_HART_ID_VALID, @@ -150,6 +177,19 @@ static rpmi_uint32_t hart_suspend_notsupp_expdata[] = { RPMI_ERR_NOTSUPP, }; +/* Hart Suspend invalid type - Request Data */ +static rpmi_uint32_t hart_suspend_invalid_type_reqdata[] = { + TEST_HART_ID_VALID, + 0, + 0, + 0, +}; + +/* Hart Suspend invalid type - Response Data */ +static rpmi_uint32_t hart_suspend_invalid_type_expdata[] = { + RPMI_ERR_INVALID_PARAM, +}; + /** * Platform Callbacks for Hart State Management */ @@ -253,7 +293,7 @@ static struct rpmi_test_scenario scenario_hsm_default = { .init = test_hsm_scenario_init, .cleanup = test_scenario_default_cleanup, - .num_tests = 10, + .num_tests = 13, .tests = { { .name = "ENABLE NOTIFICATION TEST (notifications not supported)", @@ -325,6 +365,34 @@ static struct rpmi_test_scenario scenario_hsm_default = { .init_request_data = test_init_request_data_from_attrs, .init_expected_data = test_init_expected_data_from_attrs, }, + { + .name = "GET SUSPEND TYPES (none configured)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_HSM, + .service_id = RPMI_HSM_SRV_GET_SUSPEND_TYPES, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = get_suspend_types_reqdata, + .request_data_len = sizeof(get_suspend_types_reqdata), + .expected_data = get_suspend_types_expdata, + .expected_data_len = sizeof(get_suspend_types_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET SUSPEND INFO (invalid type)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_HSM, + .service_id = RPMI_HSM_SRV_GET_SUSPEND_INFO, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = get_suspend_info_invalid_reqdata, + .request_data_len = sizeof(get_suspend_info_invalid_reqdata), + .expected_data = get_suspend_info_invalid_expdata, + .expected_data_len = sizeof(get_suspend_info_invalid_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, { .name = "HART START (valid hart id, hart already started)", .attrs = { @@ -381,6 +449,20 @@ static struct rpmi_test_scenario scenario_hsm_default = { .init_request_data = test_init_request_data_from_attrs, .init_expected_data = test_init_expected_data_from_attrs, }, + { + .name = "HART Suspend (invalid type)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_HSM, + .service_id = RPMI_HSM_SRV_HART_SUSPEND, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = hart_suspend_invalid_type_reqdata, + .request_data_len = sizeof(hart_suspend_invalid_type_reqdata), + .expected_data = hart_suspend_invalid_type_expdata, + .expected_data_len = sizeof(hart_suspend_invalid_type_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, { .name = "HART Suspend (not supported)", .attrs = { From 88d6f3449a6a2900b3e5526e86afc21d0e7916e9 Mon Sep 17 00:00:00 2001 From: Subrahmanya Lingappa Date: Fri, 15 May 2026 11:23:10 +0530 Subject: [PATCH 05/10] test: add SYSTEM_MSI service group coverage Add a dedicated SYSTEM_MSI test scenario and register it in the test object list. The scenario covers notification unsupported behavior, group attributes, MSI attributes, MSI state set/get, MSI target set/get, invalid MSI indexes, and invalid target address handling. Signed-off-by: Subrahmanya Lingappa --- test/objects.mk | 5 + test/test_srvgrp_sysmsi.c | 294 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 299 insertions(+) create mode 100644 test/test_srvgrp_sysmsi.c diff --git a/test/objects.mk b/test/objects.mk index 0d0b29d..03f01cf 100644 --- a/test/objects.mk +++ b/test/objects.mk @@ -18,3 +18,8 @@ test-elfs-y += test_srvgrp_hsm test_srvgrp_hsm-objs-y += test/test_log.o test_srvgrp_hsm-objs-y += test/test_common.o + +test-elfs-y += test_srvgrp_sysmsi + +test_srvgrp_sysmsi-objs-y += test/test_log.o +test_srvgrp_sysmsi-objs-y += test/test_common.o diff --git a/test/test_srvgrp_sysmsi.c b/test/test_srvgrp_sysmsi.c new file mode 100644 index 0000000..32b4b6d --- /dev/null +++ b/test/test_srvgrp_sysmsi.c @@ -0,0 +1,294 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2024 Ventana Micro Systems Inc. + */ + +#include +#include +#include "test_common.h" +#include "test_log.h" + +#define TEST_SYSMSI_COUNT 2 +#define TEST_SYSMSI_VALID_INDEX 0 +#define TEST_SYSMSI_INVALID_INDEX TEST_SYSMSI_COUNT +#define TEST_SYSMSI_ADDR_LOW 0x12345000 +#define TEST_SYSMSI_ADDR_HIGH 0x0 +#define TEST_SYSMSI_DATA 0x55aa55aa +#define TEST_SYSMSI_BAD_ADDR_LOW 0xdead0000 +#define TEST_EVENT_ID 0x0 +#define TEST_REQUEST_STATE_ENABLE 0x1 + +static rpmi_uint32_t enable_notif_reqdata[] = { + TEST_EVENT_ID, + TEST_REQUEST_STATE_ENABLE, +}; + +static rpmi_uint32_t enable_notif_expdata[] = { + RPMI_ERR_NOTSUPP, +}; + +static rpmi_uint32_t get_attrs_expdata[] = { + RPMI_SUCCESS, + TEST_SYSMSI_COUNT, + 0, + 0, +}; + +static rpmi_uint32_t get_msi_attrs_reqdata[] = { + TEST_SYSMSI_VALID_INDEX, +}; + +static rpmi_uint32_t get_msi_attrs_expdata[] = { + RPMI_SUCCESS, + RPMI_SYSMSI_MSI_ATTRIBUTES_FLAG0_PREF_PRIV, + 0, + 0, + 0, + 0, + 0, +}; + +static rpmi_uint32_t invalid_msi_reqdata[] = { + TEST_SYSMSI_INVALID_INDEX, +}; + +static rpmi_uint32_t invalid_param_expdata[] = { + RPMI_ERR_INVALID_PARAM, +}; + +static rpmi_uint32_t set_msi_state_reqdata[] = { + TEST_SYSMSI_VALID_INDEX, + RPMI_SYSMSI_MSI_STATE_ENABLE, +}; + +static rpmi_uint32_t success_expdata[] = { + RPMI_SUCCESS, +}; + +static rpmi_uint32_t get_msi_state_reqdata[] = { + TEST_SYSMSI_VALID_INDEX, +}; + +static rpmi_uint32_t get_msi_state_expdata[] = { + RPMI_SUCCESS, + RPMI_SYSMSI_MSI_STATE_ENABLE, +}; + +static rpmi_uint32_t set_msi_target_reqdata[] = { + TEST_SYSMSI_VALID_INDEX, + TEST_SYSMSI_ADDR_LOW, + TEST_SYSMSI_ADDR_HIGH, + TEST_SYSMSI_DATA, +}; + +static rpmi_uint32_t get_msi_target_expdata[] = { + RPMI_SUCCESS, + TEST_SYSMSI_ADDR_LOW, + TEST_SYSMSI_ADDR_HIGH, + TEST_SYSMSI_DATA, +}; + +static rpmi_uint32_t set_msi_bad_target_reqdata[] = { + TEST_SYSMSI_VALID_INDEX, + TEST_SYSMSI_BAD_ADDR_LOW, + 0, + TEST_SYSMSI_DATA, +}; + +static rpmi_uint32_t invalid_addr_expdata[] = { + RPMI_ERR_INVALID_ADDR, +}; + +static rpmi_bool_t test_validate_msi_addr(void *priv, rpmi_uint64_t msi_addr) +{ + return msi_addr == TEST_SYSMSI_ADDR_LOW; +} + +static rpmi_bool_t test_mmode_preferred(void *priv, rpmi_uint32_t msi_index) +{ + return msi_index == TEST_SYSMSI_VALID_INDEX; +} + +static struct rpmi_sysmsi_platform_ops test_sysmsi_ops = { + .validate_msi_addr = test_validate_msi_addr, + .mmode_preferred = test_mmode_preferred, +}; + +static int test_sysmsi_scenario_init(struct rpmi_test_scenario *scene) +{ + struct rpmi_service_group *grp; + int ret; + + ret = test_scenario_default_init(scene); + if (ret) + return RPMI_ERR_FAILED; + + grp = rpmi_service_group_sysmsi_create(TEST_SYSMSI_COUNT, + TEST_SYSMSI_VALID_INDEX, + &test_sysmsi_ops, NULL); + if (!grp) { + printf("failed to create rpmi sysmsi service group"); + return RPMI_ERR_FAILED; + } + + rpmi_context_add_group(scene->cntx, grp); + return 0; +} + +static struct rpmi_test_scenario scenario_sysmsi_default = { + .name = "System MSI Service Group", + .shm_size = RPMI_SHM_SZ, + .slot_size = RPMI_SLOT_SIZE, + .max_num_groups = RPMI_SRVGRP_ID_MAX_COUNT, + .priv = NULL, + + .init = test_sysmsi_scenario_init, + .cleanup = test_scenario_default_cleanup, + + .num_tests = 10, + .tests = { + { + .name = "ENABLE NOTIFICATION TEST (notifications not supported)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_SYSTEM_MSI, + .service_id = RPMI_SYSMSI_SRV_ENABLE_NOTIFICATION, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = enable_notif_reqdata, + .request_data_len = sizeof(enable_notif_reqdata), + .expected_data = enable_notif_expdata, + .expected_data_len = sizeof(enable_notif_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET ATTRIBUTES", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_SYSTEM_MSI, + .service_id = RPMI_SYSMSI_SRV_GET_ATTRIBUTES, + .flags = RPMI_MSG_NORMAL_REQUEST, + .expected_data = get_attrs_expdata, + .expected_data_len = sizeof(get_attrs_expdata), + }, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET MSI ATTRIBUTES", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_SYSTEM_MSI, + .service_id = RPMI_SYSMSI_SRV_GET_MSI_ATTRIBUTES, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = get_msi_attrs_reqdata, + .request_data_len = sizeof(get_msi_attrs_reqdata), + .expected_data = get_msi_attrs_expdata, + .expected_data_len = sizeof(get_msi_attrs_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET MSI ATTRIBUTES (invalid index)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_SYSTEM_MSI, + .service_id = RPMI_SYSMSI_SRV_GET_MSI_ATTRIBUTES, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = invalid_msi_reqdata, + .request_data_len = sizeof(invalid_msi_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "SET MSI STATE (enable)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_SYSTEM_MSI, + .service_id = RPMI_SYSMSI_SRV_SET_MSI_STATE, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = set_msi_state_reqdata, + .request_data_len = sizeof(set_msi_state_reqdata), + .expected_data = success_expdata, + .expected_data_len = sizeof(success_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET MSI STATE (enabled)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_SYSTEM_MSI, + .service_id = RPMI_SYSMSI_SRV_GET_MSI_STATE, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = get_msi_state_reqdata, + .request_data_len = sizeof(get_msi_state_reqdata), + .expected_data = get_msi_state_expdata, + .expected_data_len = sizeof(get_msi_state_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET MSI STATE (invalid index)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_SYSTEM_MSI, + .service_id = RPMI_SYSMSI_SRV_GET_MSI_STATE, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = invalid_msi_reqdata, + .request_data_len = sizeof(invalid_msi_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "SET MSI TARGET", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_SYSTEM_MSI, + .service_id = RPMI_SYSMSI_SRV_SET_MSI_TARGET, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = set_msi_target_reqdata, + .request_data_len = sizeof(set_msi_target_reqdata), + .expected_data = success_expdata, + .expected_data_len = sizeof(success_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET MSI TARGET", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_SYSTEM_MSI, + .service_id = RPMI_SYSMSI_SRV_GET_MSI_TARGET, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = get_msi_state_reqdata, + .request_data_len = sizeof(get_msi_state_reqdata), + .expected_data = get_msi_target_expdata, + .expected_data_len = sizeof(get_msi_target_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "SET MSI TARGET (invalid address)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_SYSTEM_MSI, + .service_id = RPMI_SYSMSI_SRV_SET_MSI_TARGET, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = set_msi_bad_target_reqdata, + .request_data_len = sizeof(set_msi_bad_target_reqdata), + .expected_data = invalid_addr_expdata, + .expected_data_len = sizeof(invalid_addr_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + }, +}; + +int main(int argc, char *argv[]) +{ + printf("Test System MSI Service Group\n"); + return test_scenario_execute(&scenario_sysmsi_default); +} From c7341d19b822eae649cae36eace1b8935b9d1318 Mon Sep 17 00:00:00 2001 From: Subrahmanya Lingappa Date: Fri, 15 May 2026 11:23:22 +0530 Subject: [PATCH 06/10] test: add SYSTEM_SUSPEND service group coverage Add a dedicated SYSTEM_SUSPEND test scenario and register it in the test object list. The scenario covers notification unsupported behavior, attributes for supported and unsupported suspend types, valid suspend callback flow, and invalid suspend type handling using a single-hart HSM fixture. Signed-off-by: Subrahmanya Lingappa --- test/objects.mk | 5 + test/test_srvgrp_syssusp.c | 299 +++++++++++++++++++++++++++++++++++++ 2 files changed, 304 insertions(+) create mode 100644 test/test_srvgrp_syssusp.c diff --git a/test/objects.mk b/test/objects.mk index 03f01cf..0ac7c29 100644 --- a/test/objects.mk +++ b/test/objects.mk @@ -23,3 +23,8 @@ test-elfs-y += test_srvgrp_sysmsi test_srvgrp_sysmsi-objs-y += test/test_log.o test_srvgrp_sysmsi-objs-y += test/test_common.o + +test-elfs-y += test_srvgrp_syssusp + +test_srvgrp_syssusp-objs-y += test/test_log.o +test_srvgrp_syssusp-objs-y += test/test_common.o diff --git a/test/test_srvgrp_syssusp.c b/test/test_srvgrp_syssusp.c new file mode 100644 index 0000000..0ee3553 --- /dev/null +++ b/test/test_srvgrp_syssusp.c @@ -0,0 +1,299 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2024 Ventana Micro Systems Inc. + */ + +#include +#include +#include "test_common.h" +#include "test_log.h" + +#define TEST_HART_ID 0 +#define TEST_EVENT_ID 0x0 +#define TEST_REQUEST_STATE_ENABLE 0x1 +#define TEST_RESUME_ADDR_LOW 0x80000000 +#define TEST_RESUME_ADDR_HIGH 0x0 + +static rpmi_uint32_t test_hartid_array[] = { + TEST_HART_ID, +}; + +static struct rpmi_system_suspend_type test_syssusp_types[] = { + { + .type = RPMI_SYSSUSP_TYPE_SUSPEND_TO_RAM, + .attr = RPMI_SYSSUSP_ATTRS_FLAGS_RESUMEADDR, + }, +}; + +static rpmi_uint32_t enable_notif_reqdata[] = { + TEST_EVENT_ID, + TEST_REQUEST_STATE_ENABLE, +}; + +static rpmi_uint32_t enable_notif_expdata[] = { + RPMI_ERR_NOTSUPP, +}; + +static rpmi_uint32_t get_attrs_supp_reqdata[] = { + RPMI_SYSSUSP_TYPE_SUSPEND_TO_RAM, +}; + +static rpmi_uint32_t get_attrs_supp_expdata[] = { + RPMI_SUCCESS, + RPMI_SYSSUSP_ATTRS_FLAGS_SUSPENDTYPE | RPMI_SYSSUSP_ATTRS_FLAGS_RESUMEADDR, +}; + +static rpmi_uint32_t get_attrs_notsupp_reqdata[] = { + RPMI_SYSSUSP_TYPE_MAX, +}; + +static rpmi_uint32_t get_attrs_notsupp_expdata[] = { + RPMI_SUCCESS, + 0, +}; + +static rpmi_uint32_t suspend_reqdata[] = { + TEST_HART_ID, + RPMI_SYSSUSP_TYPE_SUSPEND_TO_RAM, + TEST_RESUME_ADDR_LOW, + TEST_RESUME_ADDR_HIGH, +}; + +static rpmi_uint32_t suspend_invalid_type_reqdata[] = { + TEST_HART_ID, + RPMI_SYSSUSP_TYPE_MAX, + TEST_RESUME_ADDR_LOW, + TEST_RESUME_ADDR_HIGH, +}; + +static rpmi_uint32_t success_expdata[] = { + RPMI_SUCCESS, +}; + +static rpmi_uint32_t invalid_param_expdata[] = { + RPMI_ERR_INVALID_PARAM, +}; + +static rpmi_uint32_t prepare_count; +static rpmi_uint32_t finalize_count; +static rpmi_uint32_t resume_count; +static rpmi_uint32_t last_hart_index; +static rpmi_uint32_t last_suspend_type; +static rpmi_uint64_t last_resume_addr; + +static enum rpmi_hart_hw_state test_hart_get_hw_state(void *priv, + rpmi_uint32_t hart_index) +{ + return RPMI_HART_HW_STATE_STARTED; +} + +static struct rpmi_hsm_platform_ops test_hsm_ops = { + .hart_get_hw_state = test_hart_get_hw_state, +}; + +static enum rpmi_error +test_system_suspend_prepare(void *priv, rpmi_uint32_t hart_index, + const struct rpmi_system_suspend_type *syssusp_type, + rpmi_uint64_t resume_addr) +{ + prepare_count++; + last_hart_index = hart_index; + last_suspend_type = syssusp_type->type; + last_resume_addr = resume_addr; + return RPMI_SUCCESS; +} + +static rpmi_bool_t test_system_suspend_ready(void *priv, rpmi_uint32_t hart_index) +{ + return true; +} + +static void test_system_suspend_finalize(void *priv, rpmi_uint32_t hart_index, + const struct rpmi_system_suspend_type *syssusp_type, + rpmi_uint64_t resume_addr) +{ + finalize_count++; + last_hart_index = hart_index; + last_suspend_type = syssusp_type->type; + last_resume_addr = resume_addr; +} + +static rpmi_bool_t test_system_suspend_can_resume(void *priv, rpmi_uint32_t hart_index) +{ + return true; +} + +static enum rpmi_error +test_system_suspend_resume(void *priv, rpmi_uint32_t hart_index, + const struct rpmi_system_suspend_type *syssusp_type, + rpmi_uint64_t resume_addr) +{ + resume_count++; + return RPMI_SUCCESS; +} + +static struct rpmi_syssusp_platform_ops test_syssusp_ops = { + .system_suspend_prepare = test_system_suspend_prepare, + .system_suspend_ready = test_system_suspend_ready, + .system_suspend_finalize = test_system_suspend_finalize, + .system_suspend_can_resume = test_system_suspend_can_resume, + .system_suspend_resume = test_system_suspend_resume, +}; + +static int test_suspend_callback_init(struct rpmi_test_scenario *scene, + struct rpmi_test *test) +{ + prepare_count = 0; + finalize_count = 0; + resume_count = 0; + last_hart_index = -1U; + last_suspend_type = RPMI_SYSSUSP_TYPE_MAX; + last_resume_addr = 0; + return 0; +} + +static int test_suspend_callback_verify(struct rpmi_test_scenario *scene, + struct rpmi_test *test, + struct rpmi_message *msg) +{ + rpmi_uint64_t expected_resume_addr = TEST_RESUME_ADDR_LOW; + + if (prepare_count != 1 || finalize_count != 1) { + printf("%s: expected prepare/finalize once, got %d/%d\n", + test->name, prepare_count, finalize_count); + return 1; + } + + if (last_hart_index != 0 || last_suspend_type != RPMI_SYSSUSP_TYPE_SUSPEND_TO_RAM || + last_resume_addr != expected_resume_addr) { + printf("%s: unexpected callback args hart=%d type=%d resume=0x%lx\n", + test->name, last_hart_index, last_suspend_type, + (unsigned long)last_resume_addr); + return 1; + } + + return 0; +} + +static int test_syssusp_scenario_init(struct rpmi_test_scenario *scene) +{ + struct rpmi_service_group *grp; + struct rpmi_hsm *hsm; + int ret; + + ret = test_scenario_default_init(scene); + if (ret) + return RPMI_ERR_FAILED; + + hsm = rpmi_hsm_create(ARRAY_SIZE(test_hartid_array), + test_hartid_array, 0, NULL, &test_hsm_ops, NULL); + if (!hsm) { + printf("failed to create rpmi hsm"); + return RPMI_ERR_FAILED; + } + + grp = rpmi_service_group_syssusp_create(hsm, + ARRAY_SIZE(test_syssusp_types), + test_syssusp_types, + &test_syssusp_ops, NULL); + if (!grp) { + printf("failed to create rpmi syssusp service group"); + return RPMI_ERR_FAILED; + } + + rpmi_context_add_group(scene->cntx, grp); + return 0; +} + +static struct rpmi_test_scenario scenario_syssusp_default = { + .name = "System Suspend Service Group", + .shm_size = RPMI_SHM_SZ, + .slot_size = RPMI_SLOT_SIZE, + .max_num_groups = RPMI_SRVGRP_ID_MAX_COUNT, + .priv = NULL, + + .init = test_syssusp_scenario_init, + .cleanup = test_scenario_default_cleanup, + + .num_tests = 5, + .tests = { + { + .name = "ENABLE NOTIFICATION TEST (notifications not supported)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_SYSTEM_SUSPEND, + .service_id = RPMI_SYSSUSP_SRV_ENABLE_NOTIFICATION, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = enable_notif_reqdata, + .request_data_len = sizeof(enable_notif_reqdata), + .expected_data = enable_notif_expdata, + .expected_data_len = sizeof(enable_notif_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET ATTRIBUTES TEST (for supported suspend type)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_SYSTEM_SUSPEND, + .service_id = RPMI_SYSSUSP_SRV_GET_ATTRIBUTES, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = get_attrs_supp_reqdata, + .request_data_len = sizeof(get_attrs_supp_reqdata), + .expected_data = get_attrs_supp_expdata, + .expected_data_len = sizeof(get_attrs_supp_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET ATTRIBUTES TEST (for unsupported suspend type)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_SYSTEM_SUSPEND, + .service_id = RPMI_SYSSUSP_SRV_GET_ATTRIBUTES, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = get_attrs_notsupp_reqdata, + .request_data_len = sizeof(get_attrs_notsupp_reqdata), + .expected_data = get_attrs_notsupp_expdata, + .expected_data_len = sizeof(get_attrs_notsupp_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "SYSTEM SUSPEND (valid suspend type)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_SYSTEM_SUSPEND, + .service_id = RPMI_SYSSUSP_SRV_SYSTEM_SUSPEND, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = suspend_reqdata, + .request_data_len = sizeof(suspend_reqdata), + .expected_data = success_expdata, + .expected_data_len = sizeof(success_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + .init = test_suspend_callback_init, + .verify = test_suspend_callback_verify, + }, + { + .name = "SYSTEM SUSPEND (invalid suspend type)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_SYSTEM_SUSPEND, + .service_id = RPMI_SYSSUSP_SRV_SYSTEM_SUSPEND, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = suspend_invalid_type_reqdata, + .request_data_len = sizeof(suspend_invalid_type_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + }, +}; + +int main(int argc, char *argv[]) +{ + printf("Test System Suspend Service Group\n"); + return test_scenario_execute(&scenario_syssusp_default); +} From a1f6e7929466e1fd039cc39218dffe00f8ec4ec1 Mon Sep 17 00:00:00 2001 From: Subrahmanya Lingappa Date: Fri, 15 May 2026 11:32:08 +0530 Subject: [PATCH 07/10] test: add CPPC service group coverage Add a dedicated CPPC test scenario and register it in the test object list. The scenario covers notification unsupported behavior, register probe/read/write paths, fast-channel region and offset discovery, hart-list discovery, invalid register IDs, unsupported registers, invalid harts, and denied writes to read-only registers. Signed-off-by: Subrahmanya Lingappa --- test/objects.mk | 5 + test/test_srvgrp_cppc.c | 428 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 433 insertions(+) create mode 100644 test/test_srvgrp_cppc.c diff --git a/test/objects.mk b/test/objects.mk index 0ac7c29..2b4f44c 100644 --- a/test/objects.mk +++ b/test/objects.mk @@ -28,3 +28,8 @@ test-elfs-y += test_srvgrp_syssusp test_srvgrp_syssusp-objs-y += test/test_log.o test_srvgrp_syssusp-objs-y += test/test_common.o + +test-elfs-y += test_srvgrp_cppc + +test_srvgrp_cppc-objs-y += test/test_log.o +test_srvgrp_cppc-objs-y += test/test_common.o diff --git a/test/test_srvgrp_cppc.c b/test/test_srvgrp_cppc.c new file mode 100644 index 0000000..42511a9 --- /dev/null +++ b/test/test_srvgrp_cppc.c @@ -0,0 +1,428 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2024 Ventana Micro Systems Inc. + */ + +#include +#include +#include "librpmi_internal.h" +#include "test_common.h" +#include "test_log.h" + +#define TEST_HART_ID 0 +#define TEST_HART_ID_INVALID 1 +#define TEST_EVENT_ID 0x0 +#define TEST_REQUEST_STATE_ENABLE 0x1 +#define TEST_CPPC_HIGHEST_PERF 0x64 +#define TEST_CPPC_NOMINAL_PERF 0x50 +#define TEST_CPPC_COUNTER_LO 0x55667788 +#define TEST_CPPC_COUNTER_HI 0x11223344 +#define TEST_CPPC_FASTCHAN_SIZE 64 +#define TEST_CPPC_FASTCHAN_REQ_OFFSET 0 +#define TEST_CPPC_FASTCHAN_FB_OFFSET RPMI_CPPC_FASTCHAN_SIZE + +static rpmi_uint8_t test_fastchan_mem[TEST_CPPC_FASTCHAN_SIZE] + __aligned(RPMI_CPPC_FASTCHAN_SIZE); + +static rpmi_uint32_t test_hartid_array[] = { + TEST_HART_ID, +}; + +static struct rpmi_cppc_regs test_cppc_regs = { + .highest_perf = TEST_CPPC_HIGHEST_PERF, + .nominal_perf = TEST_CPPC_NOMINAL_PERF, + .lowest_nonlinear_perf = 0x30, + .lowest_perf = 0x10, + .reference_perf = TEST_CPPC_NOMINAL_PERF, + .lowest_freq = 1000000000U, + .nominal_freq = 2000000000U, + .transition_latency = 10, +}; + +static rpmi_uint32_t enable_notif_reqdata[] = { + TEST_EVENT_ID, + TEST_REQUEST_STATE_ENABLE, +}; + +static rpmi_uint32_t enable_notif_expdata[] = { + RPMI_ERR_NOTSUPP, +}; + +static rpmi_uint32_t probe_highest_reqdata[] = { + TEST_HART_ID, + RPMI_CPPC_HIGHEST_PERF, +}; + +static rpmi_uint32_t probe_32bit_expdata[] = { + RPMI_SUCCESS, + 32, +}; + +static rpmi_uint32_t probe_not_supp_reqdata[] = { + TEST_HART_ID, + RPMI_CPPC_MIN_PERF, +}; + +static rpmi_uint32_t probe_not_supp_expdata[] = { + RPMI_ERR_NOTSUPP, + 0, +}; + +static rpmi_uint32_t probe_invalid_reg_reqdata[] = { + TEST_HART_ID, + RPMI_CPPC_NON_ACPI_REG_MAX_IDX, +}; + +static rpmi_uint32_t invalid_param_expdata[] = { + RPMI_ERR_INVALID_PARAM, +}; + +static rpmi_uint32_t read_highest_reqdata[] = { + TEST_HART_ID, + RPMI_CPPC_HIGHEST_PERF, +}; + +static rpmi_uint32_t read_highest_expdata[] = { + RPMI_SUCCESS, + TEST_CPPC_HIGHEST_PERF, + 0, +}; + +static rpmi_uint32_t read_counter_reqdata[] = { + TEST_HART_ID, + RPMI_CPPC_REFERENCE_PERF_COUNTER, +}; + +static rpmi_uint32_t read_counter_expdata[] = { + RPMI_SUCCESS, + TEST_CPPC_COUNTER_LO, + TEST_CPPC_COUNTER_HI, +}; + +static rpmi_uint32_t read_invalid_hart_reqdata[] = { + TEST_HART_ID_INVALID, + RPMI_CPPC_HIGHEST_PERF, +}; + +static rpmi_uint32_t write_readonly_reqdata[] = { + TEST_HART_ID, + RPMI_CPPC_HIGHEST_PERF, + 1, + 0, +}; + +static rpmi_uint32_t denied_expdata[] = { + RPMI_ERR_DENIED, +}; + +static rpmi_uint32_t get_fastchan_offset_reqdata[] = { + TEST_HART_ID, +}; + +static rpmi_uint32_t get_fastchan_offset_expdata[] = { + RPMI_SUCCESS, + TEST_CPPC_FASTCHAN_REQ_OFFSET, + 0, + TEST_CPPC_FASTCHAN_FB_OFFSET, + 0, +}; + +static rpmi_uint32_t get_hart_list_reqdata[] = { + 0, +}; + +static rpmi_uint32_t get_hart_list_expdata[] = { + RPMI_SUCCESS, + 0, + 1, + TEST_HART_ID, +}; + +static enum rpmi_hart_hw_state test_hart_get_hw_state(void *priv, + rpmi_uint32_t hart_index) +{ + return RPMI_HART_HW_STATE_STARTED; +} + +static struct rpmi_hsm_platform_ops test_hsm_ops = { + .hart_get_hw_state = test_hart_get_hw_state, +}; + +static enum rpmi_error test_cppc_get_reg(void *priv, rpmi_uint32_t reg_id, + rpmi_uint32_t hart_index, + rpmi_uint64_t *val) +{ + if (reg_id == RPMI_CPPC_REFERENCE_PERF_COUNTER) { + *val = ((rpmi_uint64_t)TEST_CPPC_COUNTER_HI << 32) | + TEST_CPPC_COUNTER_LO; + return RPMI_SUCCESS; + } + + *val = 0; + return RPMI_ERR_NOTSUPP; +} + +static enum rpmi_error test_cppc_set_reg(void *priv, rpmi_uint32_t reg_id, + rpmi_uint32_t hart_index, + rpmi_uint64_t val) +{ + return RPMI_SUCCESS; +} + +static enum rpmi_error test_cppc_update_perf(void *priv, + rpmi_uint32_t hart_index, + rpmi_uint32_t desired_perf) +{ + return RPMI_SUCCESS; +} + +static enum rpmi_error test_cppc_get_current_freq(void *priv, + rpmi_uint32_t hart_index, + rpmi_uint64_t *current_freq_hz) +{ + *current_freq_hz = 2000000000ULL; + return RPMI_SUCCESS; +} + +static struct rpmi_cppc_platform_ops test_cppc_ops = { + .cppc_get_reg = test_cppc_get_reg, + .cppc_set_reg = test_cppc_set_reg, + .cppc_update_perf = test_cppc_update_perf, + .cppc_get_current_freq = test_cppc_get_current_freq, +}; + +static rpmi_uint16_t init_fastchan_region_expected(struct rpmi_test_scenario *scene, + struct rpmi_test *test, + void *data, + rpmi_uint16_t max_data_len) +{ + rpmi_uint32_t *exp = data; + rpmi_uint64_t base = (rpmi_uint64_t)(rpmi_uintptr_t)test_fastchan_mem; + + exp[0] = RPMI_SUCCESS; + exp[1] = 0; + exp[2] = (rpmi_uint32_t)base; + exp[3] = (rpmi_uint32_t)(base >> 32); + exp[4] = TEST_CPPC_FASTCHAN_SIZE; + exp[5] = 0; + exp[6] = 0; + exp[7] = 0; + exp[8] = 0; + exp[9] = 0; + exp[10] = 0; + exp[11] = 0; + + return 12 * sizeof(*exp); +} + +static int test_cppc_scenario_init(struct rpmi_test_scenario *scene) +{ + struct rpmi_service_group *grp; + struct rpmi_shmem *fastchan_shmem; + struct rpmi_hsm *hsm; + int ret; + + ret = test_scenario_default_init(scene); + if (ret) + return RPMI_ERR_FAILED; + + hsm = rpmi_hsm_create(ARRAY_SIZE(test_hartid_array), + test_hartid_array, 0, NULL, &test_hsm_ops, NULL); + if (!hsm) { + printf("failed to create rpmi hsm"); + return RPMI_ERR_FAILED; + } + + fastchan_shmem = rpmi_shmem_create("test_cppc_fastchan", + (rpmi_uint64_t)(rpmi_uintptr_t)test_fastchan_mem, + sizeof(test_fastchan_mem), + &rpmi_shmem_simple_ops, NULL); + if (!fastchan_shmem) { + printf("failed to create cppc fastchannel shmem"); + return RPMI_ERR_FAILED; + } + + grp = rpmi_service_group_cppc_create(hsm, &test_cppc_regs, + RPMI_CPPC_PASSIVE_MODE, + fastchan_shmem, + TEST_CPPC_FASTCHAN_REQ_OFFSET, + TEST_CPPC_FASTCHAN_FB_OFFSET, + &test_cppc_ops, NULL); + if (!grp) { + printf("failed to create rpmi cppc service group"); + return RPMI_ERR_FAILED; + } + + rpmi_context_add_group(scene->cntx, grp); + return 0; +} + +static struct rpmi_test_scenario scenario_cppc_default = { + .name = "CPPC Service Group", + .shm_size = RPMI_SHM_SZ, + .slot_size = RPMI_SLOT_SIZE, + .max_num_groups = RPMI_SRVGRP_ID_MAX_COUNT, + .priv = NULL, + + .init = test_cppc_scenario_init, + .cleanup = test_scenario_default_cleanup, + + .num_tests = 11, + .tests = { + { + .name = "ENABLE NOTIFICATION TEST (notifications not supported)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CPPC, + .service_id = RPMI_CPPC_SRV_ENABLE_NOTIFICATION, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = enable_notif_reqdata, + .request_data_len = sizeof(enable_notif_reqdata), + .expected_data = enable_notif_expdata, + .expected_data_len = sizeof(enable_notif_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "PROBE REG (implemented 32-bit reg)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CPPC, + .service_id = RPMI_CPPC_SRV_PROBE_REG, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = probe_highest_reqdata, + .request_data_len = sizeof(probe_highest_reqdata), + .expected_data = probe_32bit_expdata, + .expected_data_len = sizeof(probe_32bit_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "PROBE REG (not supported reg)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CPPC, + .service_id = RPMI_CPPC_SRV_PROBE_REG, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = probe_not_supp_reqdata, + .request_data_len = sizeof(probe_not_supp_reqdata), + .expected_data = probe_not_supp_expdata, + .expected_data_len = sizeof(probe_not_supp_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "PROBE REG (invalid reg)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CPPC, + .service_id = RPMI_CPPC_SRV_PROBE_REG, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = probe_invalid_reg_reqdata, + .request_data_len = sizeof(probe_invalid_reg_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "READ REG (static 32-bit reg)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CPPC, + .service_id = RPMI_CPPC_SRV_READ_REG, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = read_highest_reqdata, + .request_data_len = sizeof(read_highest_reqdata), + .expected_data = read_highest_expdata, + .expected_data_len = sizeof(read_highest_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "READ REG (platform 64-bit counter)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CPPC, + .service_id = RPMI_CPPC_SRV_READ_REG, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = read_counter_reqdata, + .request_data_len = sizeof(read_counter_reqdata), + .expected_data = read_counter_expdata, + .expected_data_len = sizeof(read_counter_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "READ REG (invalid hart)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CPPC, + .service_id = RPMI_CPPC_SRV_READ_REG, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = read_invalid_hart_reqdata, + .request_data_len = sizeof(read_invalid_hart_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "WRITE REG (read-only reg denied)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CPPC, + .service_id = RPMI_CPPC_SRV_WRITE_REG, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = write_readonly_reqdata, + .request_data_len = sizeof(write_readonly_reqdata), + .expected_data = denied_expdata, + .expected_data_len = sizeof(denied_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET FAST CHANNEL REGION", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CPPC, + .service_id = RPMI_CPPC_SRV_GET_FAST_CHANNEL_REGION, + .flags = RPMI_MSG_NORMAL_REQUEST, + }, + .init_expected_data = init_fastchan_region_expected, + }, + { + .name = "GET FAST CHANNEL OFFSET", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CPPC, + .service_id = RPMI_CPPC_SRV_GET_FAST_CHANNEL_OFFSET, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = get_fastchan_offset_reqdata, + .request_data_len = sizeof(get_fastchan_offset_reqdata), + .expected_data = get_fastchan_offset_expdata, + .expected_data_len = sizeof(get_fastchan_offset_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET HART LIST", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CPPC, + .service_id = RPMI_CPPC_SRV_GET_HART_LIST, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = get_hart_list_reqdata, + .request_data_len = sizeof(get_hart_list_reqdata), + .expected_data = get_hart_list_expdata, + .expected_data_len = sizeof(get_hart_list_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + }, +}; + +int main(int argc, char *argv[]) +{ + printf("Test CPPC Service Group\n"); + return test_scenario_execute(&scenario_cppc_default); +} From 6fd42c53bf9f9ea9678d59d0eb572c66eb6edb45 Mon Sep 17 00:00:00 2001 From: Subrahmanya Lingappa Date: Fri, 15 May 2026 11:35:53 +0530 Subject: [PATCH 08/10] test: add Voltage service group coverage Add a dedicated Voltage test scenario and register it in the test object list. The scenario covers notification unsupported behavior, domain count reporting, attributes, discrete and linear supported-level queries, config set/get, voltage level set/get, invalid domains, short requests, bad config values, and unsupported voltage levels. Signed-off-by: Subrahmanya Lingappa --- test/objects.mk | 5 + test/test_srvgrp_voltage.c | 562 +++++++++++++++++++++++++++++++++++++ 2 files changed, 567 insertions(+) create mode 100644 test/test_srvgrp_voltage.c diff --git a/test/objects.mk b/test/objects.mk index 2b4f44c..81e4423 100644 --- a/test/objects.mk +++ b/test/objects.mk @@ -33,3 +33,8 @@ test-elfs-y += test_srvgrp_cppc test_srvgrp_cppc-objs-y += test/test_log.o test_srvgrp_cppc-objs-y += test/test_common.o + +test-elfs-y += test_srvgrp_voltage + +test_srvgrp_voltage-objs-y += test/test_log.o +test_srvgrp_voltage-objs-y += test/test_common.o diff --git a/test/test_srvgrp_voltage.c b/test/test_srvgrp_voltage.c new file mode 100644 index 0000000..a2f6d1c --- /dev/null +++ b/test/test_srvgrp_voltage.c @@ -0,0 +1,562 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2024 Ventana Micro Systems Inc. + */ + +#include +#include +#include "test_common.h" +#include "test_log.h" + +#define TEST_VOLT_COUNT 2 +#define TEST_VOLT_CPU 0 +#define TEST_VOLT_MEM 1 +#define TEST_VOLT_INVALID TEST_VOLT_COUNT +#define TEST_EVENT_ID 0x0 +#define TEST_REQUEST_STATE_ENABLE 0x1 +#define TEST_VOLT_CPU_LATENCY 10 +#define TEST_VOLT_MEM_LATENCY 20 +#define TEST_VOLT_CPU_INITIAL 800000 +#define TEST_VOLT_CPU_TARGET 1000000 +#define TEST_VOLT_CPU_UNSUPP 1100000 +#define TEST_VOLT_BAD_CONFIG RPMI_VOLT_CONFIG_MAX + +struct test_volt_attrs_expdata { + rpmi_uint32_t status; + rpmi_uint32_t capability; + rpmi_uint32_t num_levels; + rpmi_uint32_t trans_latency; + char name[16]; +}; + +static rpmi_int32_t test_cpu_levels[] = { + 800000, + 900000, + 1000000, +}; + +static rpmi_int32_t test_mem_levels[] = { + 1800000, + 1900000, +}; + +static struct rpmi_voltage_discrete_range test_cpu_range = { + .uvolt = (rpmi_uint32_t *)test_cpu_levels, +}; + +static struct rpmi_voltage_linear_range test_mem_range = { + .uvolt_min = 1800000, + .uvolt_max = 1900000, + .uvolt_step = 100000, +}; + +static struct rpmi_voltage_data test_voltage_data[TEST_VOLT_COUNT] = { + [TEST_VOLT_CPU] = { + .name = "vdd_cpu", + .voltage_type = RPMI_VOLT_TYPE_DISCRETE, + .control = RPMI_VOLT_CAPABILITY_ENABLED_DISABLED, + .config = RPMI_VOLT_CONFIG_DISABLED, + .num_levels = ARRAY_SIZE(test_cpu_levels), + .trans_latency = TEST_VOLT_CPU_LATENCY, + .discrete_range = &test_cpu_range, + .discrete_levels = test_cpu_levels, + .level_uv = TEST_VOLT_CPU_INITIAL, + }, + [TEST_VOLT_MEM] = { + .name = "vdd_mem", + .voltage_type = RPMI_VOLT_TYPE_LINEAR, + .control = RPMI_VOLT_CAPABILITY_ALWAYS_ON, + .config = RPMI_VOLT_CONFIG_NOT_SUPPORTED, + .num_levels = ARRAY_SIZE(test_mem_levels), + .trans_latency = TEST_VOLT_MEM_LATENCY, + .linear_range = &test_mem_range, + .linear_levels = test_mem_levels, + .level_uv = 1800000, + }, +}; + +static rpmi_uint32_t test_current_config[TEST_VOLT_COUNT] = { + RPMI_VOLT_CONFIG_DISABLED, + RPMI_VOLT_CONFIG_NOT_SUPPORTED, +}; + +static rpmi_int32_t test_current_level[TEST_VOLT_COUNT] = { + TEST_VOLT_CPU_INITIAL, + 1800000, +}; + +static rpmi_uint32_t enable_notif_reqdata[] = { + TEST_EVENT_ID, + TEST_REQUEST_STATE_ENABLE, +}; + +static rpmi_uint32_t notsupp_expdata[] = { + RPMI_ERR_NOTSUPP, +}; + +static rpmi_uint32_t get_num_domains_expdata[] = { + RPMI_SUCCESS, + TEST_VOLT_COUNT, +}; + +static rpmi_uint32_t volt_cpu_reqdata[] = { + TEST_VOLT_CPU, +}; + +static rpmi_uint32_t volt_invalid_reqdata[] = { + TEST_VOLT_INVALID, +}; + +static struct test_volt_attrs_expdata get_attrs_cpu_expdata = { + .status = RPMI_SUCCESS, + .capability = RPMI_VOLT_TYPE_DISCRETE | RPMI_VOLT_CAPABILITY_ENABLED_DISABLED, + .num_levels = ARRAY_SIZE(test_cpu_levels), + .trans_latency = TEST_VOLT_CPU_LATENCY, + .name = "vdd_cpu", +}; + +static rpmi_uint32_t invalid_param_expdata[] = { + RPMI_ERR_INVALID_PARAM, +}; + +static rpmi_uint32_t get_cpu_levels_reqdata[] = { + TEST_VOLT_CPU, + 1, +}; + +static rpmi_uint32_t get_cpu_levels_expdata[] = { + RPMI_SUCCESS, + 0, + 0, + 2, + 900000, + 1000000, +}; + +static rpmi_uint32_t get_mem_levels_reqdata[] = { + TEST_VOLT_MEM, + 0, +}; + +static rpmi_uint32_t get_mem_levels_expdata[] = { + RPMI_SUCCESS, + 0, + 0, + 2, + 1800000, + 1900000, +}; + +static rpmi_uint32_t get_invalid_levels_reqdata[] = { + TEST_VOLT_INVALID, + 0, +}; + +static rpmi_uint32_t set_config_enable_reqdata[] = { + TEST_VOLT_CPU, + RPMI_VOLT_CONFIG_ENABLED, +}; + +static rpmi_uint32_t success_expdata[] = { + RPMI_SUCCESS, +}; + +static rpmi_uint32_t get_config_enabled_expdata[] = { + RPMI_SUCCESS, + RPMI_VOLT_CONFIG_ENABLED, +}; + +static rpmi_uint32_t set_config_bad_reqdata[] = { + TEST_VOLT_CPU, + TEST_VOLT_BAD_CONFIG, +}; + +static rpmi_uint32_t set_level_cpu_reqdata[] = { + TEST_VOLT_CPU, + TEST_VOLT_CPU_TARGET, +}; + +static rpmi_uint32_t get_level_cpu_expdata[] = { + RPMI_SUCCESS, + TEST_VOLT_CPU_TARGET, +}; + +static rpmi_uint32_t set_level_unsupported_reqdata[] = { + TEST_VOLT_CPU, + TEST_VOLT_CPU_UNSUPP, +}; + +static enum rpmi_error test_voltage_set_config(void *priv, + rpmi_uint32_t volt_id, + rpmi_uint32_t config) +{ + if (volt_id >= TEST_VOLT_COUNT) + return RPMI_ERR_INVALID_PARAM; + + if (config >= RPMI_VOLT_CONFIG_MAX) + return RPMI_ERR_INVALID_PARAM; + + test_current_config[volt_id] = config; + return RPMI_SUCCESS; +} + +static enum rpmi_error test_voltage_get_config(void *priv, + rpmi_uint32_t volt_id, + rpmi_uint32_t *config) +{ + if (volt_id >= TEST_VOLT_COUNT || !config) + return RPMI_ERR_INVALID_PARAM; + + *config = test_current_config[volt_id]; + return RPMI_SUCCESS; +} + +static rpmi_bool_t test_voltage_level_supported(rpmi_uint32_t volt_id, + rpmi_int32_t level) +{ + rpmi_int32_t *levels; + rpmi_uint32_t i, count; + + if (volt_id >= TEST_VOLT_COUNT) + return false; + + if (volt_id == TEST_VOLT_CPU) { + levels = test_cpu_levels; + count = ARRAY_SIZE(test_cpu_levels); + } else { + levels = test_mem_levels; + count = ARRAY_SIZE(test_mem_levels); + } + + for (i = 0; i < count; i++) { + if (levels[i] == level) + return true; + } + + return false; +} + +static enum rpmi_error test_voltage_set_level(void *priv, + rpmi_uint32_t volt_id, + rpmi_int32_t *volt_level) +{ + if (volt_id >= TEST_VOLT_COUNT || !volt_level) + return RPMI_ERR_INVALID_PARAM; + + if (!test_voltage_level_supported(volt_id, *volt_level)) + return RPMI_ERR_INVALID_PARAM; + + test_current_level[volt_id] = *volt_level; + return RPMI_SUCCESS; +} + +static enum rpmi_error test_voltage_get_level(void *priv, + rpmi_uint32_t volt_id, + rpmi_int32_t *volt_level) +{ + if (volt_id >= TEST_VOLT_COUNT || !volt_level) + return RPMI_ERR_INVALID_PARAM; + + *volt_level = test_current_level[volt_id]; + return RPMI_SUCCESS; +} + +static enum rpmi_error test_voltage_get_supp_levels(void *priv, + rpmi_uint32_t volt_id, + rpmi_uint32_t max, + rpmi_uint32_t volt_index, + rpmi_uint32_t *returned_levels, + rpmi_int32_t *level_array) +{ + rpmi_int32_t *src; + rpmi_uint32_t count, returned, i; + + if (volt_id >= TEST_VOLT_COUNT || !returned_levels || !level_array) + return RPMI_ERR_INVALID_PARAM; + + if (volt_id == TEST_VOLT_CPU) { + src = test_cpu_levels; + count = ARRAY_SIZE(test_cpu_levels); + } else { + src = test_mem_levels; + count = ARRAY_SIZE(test_mem_levels); + } + + if (volt_index >= count) + return RPMI_ERR_INVALID_PARAM; + + returned = count - volt_index; + if (returned > max) + returned = max; + + for (i = 0; i < returned; i++) + level_array[i] = src[volt_index + i]; + + *returned_levels = returned; + return RPMI_SUCCESS; +} + +static struct rpmi_voltage_platform_ops test_voltage_ops = { + .set_config = test_voltage_set_config, + .get_config = test_voltage_get_config, + .set_level = test_voltage_set_level, + .get_level = test_voltage_get_level, + .get_supp_levels = test_voltage_get_supp_levels, +}; + +static int test_voltage_state_init(struct rpmi_test_scenario *scene, + struct rpmi_test *test) +{ + test_current_config[TEST_VOLT_CPU] = RPMI_VOLT_CONFIG_DISABLED; + test_current_config[TEST_VOLT_MEM] = RPMI_VOLT_CONFIG_NOT_SUPPORTED; + test_current_level[TEST_VOLT_CPU] = TEST_VOLT_CPU_INITIAL; + test_current_level[TEST_VOLT_MEM] = test_mem_levels[0]; + return 0; +} + +static int test_voltage_scenario_init(struct rpmi_test_scenario *scene) +{ + struct rpmi_service_group *grp; + int ret; + + ret = test_scenario_default_init(scene); + if (ret) + return RPMI_ERR_FAILED; + + grp = rpmi_service_group_voltage_create(TEST_VOLT_COUNT, + test_voltage_data, + &test_voltage_ops, NULL); + if (!grp) { + printf("failed to create rpmi voltage service group"); + return RPMI_ERR_FAILED; + } + + rpmi_context_add_group(scene->cntx, grp); + return 0; +} + +static struct rpmi_test_scenario scenario_voltage_default = { + .name = "Voltage Service Group", + .shm_size = RPMI_SHM_SZ, + .slot_size = RPMI_SLOT_SIZE, + .max_num_groups = RPMI_SRVGRP_ID_MAX_COUNT, + .priv = NULL, + + .init = test_voltage_scenario_init, + .cleanup = test_scenario_default_cleanup, + + .num_tests = 15, + .tests = { + { + .name = "ENABLE NOTIFICATION TEST (notifications not supported)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_VOLTAGE, + .service_id = RPMI_VOLT_SRV_ENABLE_NOTIFICATION, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = enable_notif_reqdata, + .request_data_len = sizeof(enable_notif_reqdata), + .expected_data = notsupp_expdata, + .expected_data_len = sizeof(notsupp_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET NUM DOMAINS", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_VOLTAGE, + .service_id = RPMI_VOLT_SRV_GET_NUM_DOMAINS, + .flags = RPMI_MSG_NORMAL_REQUEST, + .expected_data = get_num_domains_expdata, + .expected_data_len = sizeof(get_num_domains_expdata), + }, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET ATTRIBUTES", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_VOLTAGE, + .service_id = RPMI_VOLT_SRV_GET_ATTRIBUTES, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = volt_cpu_reqdata, + .request_data_len = sizeof(volt_cpu_reqdata), + .expected_data = &get_attrs_cpu_expdata, + .expected_data_len = sizeof(get_attrs_cpu_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET ATTRIBUTES (invalid domain)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_VOLTAGE, + .service_id = RPMI_VOLT_SRV_GET_ATTRIBUTES, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = volt_invalid_reqdata, + .request_data_len = sizeof(volt_invalid_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET SUPPORTED LEVELS (discrete)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_VOLTAGE, + .service_id = RPMI_VOLT_SRV_GET_SUPPORTED_LEVELS, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = get_cpu_levels_reqdata, + .request_data_len = sizeof(get_cpu_levels_reqdata), + .expected_data = get_cpu_levels_expdata, + .expected_data_len = sizeof(get_cpu_levels_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET SUPPORTED LEVELS (linear)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_VOLTAGE, + .service_id = RPMI_VOLT_SRV_GET_SUPPORTED_LEVELS, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = get_mem_levels_reqdata, + .request_data_len = sizeof(get_mem_levels_reqdata), + .expected_data = get_mem_levels_expdata, + .expected_data_len = sizeof(get_mem_levels_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET SUPPORTED LEVELS (invalid domain)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_VOLTAGE, + .service_id = RPMI_VOLT_SRV_GET_SUPPORTED_LEVELS, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = get_invalid_levels_reqdata, + .request_data_len = sizeof(get_invalid_levels_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "SET CONFIG (enable)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_VOLTAGE, + .service_id = RPMI_VOLT_SRV_SET_CONFIG, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = set_config_enable_reqdata, + .request_data_len = sizeof(set_config_enable_reqdata), + .expected_data = success_expdata, + .expected_data_len = sizeof(success_expdata), + }, + .init = test_voltage_state_init, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET CONFIG (enabled)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_VOLTAGE, + .service_id = RPMI_VOLT_SRV_GET_CONFIG, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = volt_cpu_reqdata, + .request_data_len = sizeof(volt_cpu_reqdata), + .expected_data = get_config_enabled_expdata, + .expected_data_len = sizeof(get_config_enabled_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET CONFIG (short request)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_VOLTAGE, + .service_id = RPMI_VOLT_SRV_GET_CONFIG, + .flags = RPMI_MSG_NORMAL_REQUEST, + .expected_data = notsupp_expdata, + .expected_data_len = sizeof(notsupp_expdata), + }, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "SET CONFIG (invalid config)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_VOLTAGE, + .service_id = RPMI_VOLT_SRV_SET_CONFIG, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = set_config_bad_reqdata, + .request_data_len = sizeof(set_config_bad_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "SET VOLT LEVEL", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_VOLTAGE, + .service_id = RPMI_VOLT_SRV_SET_VOLT_LEVEL, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = set_level_cpu_reqdata, + .request_data_len = sizeof(set_level_cpu_reqdata), + .expected_data = success_expdata, + .expected_data_len = sizeof(success_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET VOLT LEVEL", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_VOLTAGE, + .service_id = RPMI_VOLT_SRV_GET_VOLT_LEVEL, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = volt_cpu_reqdata, + .request_data_len = sizeof(volt_cpu_reqdata), + .expected_data = get_level_cpu_expdata, + .expected_data_len = sizeof(get_level_cpu_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "SET VOLT LEVEL (unsupported level)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_VOLTAGE, + .service_id = RPMI_VOLT_SRV_SET_VOLT_LEVEL, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = set_level_unsupported_reqdata, + .request_data_len = sizeof(set_level_unsupported_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET VOLT LEVEL (invalid domain)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_VOLTAGE, + .service_id = RPMI_VOLT_SRV_GET_VOLT_LEVEL, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = volt_invalid_reqdata, + .request_data_len = sizeof(volt_invalid_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + }, +}; + +int main(int argc, char *argv[]) +{ + printf("Test Voltage Service Group\n"); + return test_scenario_execute(&scenario_voltage_default); +} From adf858232b02e443162b300298c364bca0ad176d Mon Sep 17 00:00:00 2001 From: Subrahmanya Lingappa Date: Fri, 15 May 2026 11:37:46 +0530 Subject: [PATCH 09/10] test: add Clock service group coverage Add a dedicated Clock test scenario and register it in the test object list. The scenario covers notification unsupported behavior, clock count reporting, attributes, discrete and linear supported-rate queries, config set/get, 64-bit rate set/get, invalid clock IDs, bad rate indexes, short requests, invalid rate-match flags, zero rates, and unsupported rates. Signed-off-by: Subrahmanya Lingappa --- test/objects.mk | 5 + test/test_srvgrp_clock.c | 573 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 578 insertions(+) create mode 100644 test/test_srvgrp_clock.c diff --git a/test/objects.mk b/test/objects.mk index 81e4423..f92dccf 100644 --- a/test/objects.mk +++ b/test/objects.mk @@ -38,3 +38,8 @@ test-elfs-y += test_srvgrp_voltage test_srvgrp_voltage-objs-y += test/test_log.o test_srvgrp_voltage-objs-y += test/test_common.o + +test-elfs-y += test_srvgrp_clock + +test_srvgrp_clock-objs-y += test/test_log.o +test_srvgrp_clock-objs-y += test/test_common.o diff --git a/test/test_srvgrp_clock.c b/test/test_srvgrp_clock.c new file mode 100644 index 0000000..855e6dd --- /dev/null +++ b/test/test_srvgrp_clock.c @@ -0,0 +1,573 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2024 Ventana Micro Systems Inc. + */ + +#include +#include +#include "test_common.h" +#include "test_log.h" + +#define TEST_CLK_COUNT 2 +#define TEST_CLK_CPU 0 +#define TEST_CLK_BUS 1 +#define TEST_CLK_INVALID TEST_CLK_COUNT +#define TEST_EVENT_ID 0x0 +#define TEST_REQUEST_STATE_ENABLE 0x1 +#define TEST_CLK_CPU_LATENCY 5 +#define TEST_CLK_BUS_LATENCY 7 +#define TEST_CLK_CPU_INITIAL_RATE 100000000ULL +#define TEST_CLK_CPU_TARGET_RATE 200000000ULL +#define TEST_CLK_CPU_UNSUPP_RATE 123456789ULL +#define TEST_CLK_BUS_MIN_RATE 500000000ULL +#define TEST_CLK_BUS_MAX_RATE 1000000000ULL +#define TEST_CLK_BUS_STEP_RATE 100000000ULL + +#define RATE_LO(_rate) ((rpmi_uint32_t)((rpmi_uint64_t)(_rate))) +#define RATE_HI(_rate) ((rpmi_uint32_t)(((rpmi_uint64_t)(_rate)) >> 32)) + +struct test_clk_attrs_expdata { + rpmi_uint32_t status; + rpmi_uint32_t flags; + rpmi_uint32_t rate_count; + rpmi_uint32_t transition_latency; + char name[16]; +}; + +static const rpmi_uint64_t test_cpu_rates[] = { + TEST_CLK_CPU_INITIAL_RATE, + TEST_CLK_CPU_TARGET_RATE, + 400000000ULL, +}; + +static const rpmi_uint64_t test_bus_rates[] = { + TEST_CLK_BUS_MIN_RATE, + TEST_CLK_BUS_MAX_RATE, + TEST_CLK_BUS_STEP_RATE, +}; + +static struct rpmi_clock_data test_clock_data[TEST_CLK_COUNT] = { + [TEST_CLK_CPU] = { + .parent_id = -1U, + .transition_latency_ms = TEST_CLK_CPU_LATENCY, + .rate_count = ARRAY_SIZE(test_cpu_rates), + .clock_type = RPMI_CLK_TYPE_DISCRETE, + .name = "clk_cpu", + .clock_rate_array = test_cpu_rates, + }, + [TEST_CLK_BUS] = { + .parent_id = -1U, + .transition_latency_ms = TEST_CLK_BUS_LATENCY, + .rate_count = ARRAY_SIZE(test_bus_rates), + .clock_type = RPMI_CLK_TYPE_LINEAR, + .name = "clk_bus", + .clock_rate_array = test_bus_rates, + }, +}; + +static enum rpmi_clock_state test_clock_state[TEST_CLK_COUNT] = { + RPMI_CLK_STATE_DISABLED, + RPMI_CLK_STATE_ENABLED, +}; + +static rpmi_uint64_t test_clock_rate[TEST_CLK_COUNT] = { + TEST_CLK_CPU_INITIAL_RATE, + TEST_CLK_BUS_MIN_RATE, +}; + +static rpmi_uint32_t enable_notif_reqdata[] = { + TEST_EVENT_ID, + TEST_REQUEST_STATE_ENABLE, +}; + +static rpmi_uint32_t notsupp_expdata[] = { + RPMI_ERR_NOTSUPP, +}; + +static rpmi_uint32_t get_num_clocks_expdata[] = { + RPMI_SUCCESS, + TEST_CLK_COUNT, +}; + +static rpmi_uint32_t clk_cpu_reqdata[] = { + TEST_CLK_CPU, +}; + +static rpmi_uint32_t clk_invalid_reqdata[] = { + TEST_CLK_INVALID, +}; + +static struct test_clk_attrs_expdata get_attrs_cpu_expdata = { + .status = RPMI_SUCCESS, + .flags = 0, + .rate_count = ARRAY_SIZE(test_cpu_rates), + .transition_latency = TEST_CLK_CPU_LATENCY, + .name = "clk_cpu", +}; + +static rpmi_uint32_t invalid_param_expdata[] = { + RPMI_ERR_INVALID_PARAM, +}; + +static rpmi_uint32_t get_cpu_rates_reqdata[] = { + TEST_CLK_CPU, + 1, +}; + +static rpmi_uint32_t get_cpu_rates_expdata[] = { + RPMI_SUCCESS, + 0, + 0, + 2, + RATE_LO(TEST_CLK_CPU_TARGET_RATE), + RATE_HI(TEST_CLK_CPU_TARGET_RATE), + RATE_LO(400000000ULL), + RATE_HI(400000000ULL), +}; + +static rpmi_uint32_t get_bus_rates_reqdata[] = { + TEST_CLK_BUS, + 0, +}; + +static rpmi_uint32_t get_bus_rates_expdata[] = { + RPMI_SUCCESS, + 0, + 0, + 3, + RATE_LO(TEST_CLK_BUS_MIN_RATE), + RATE_HI(TEST_CLK_BUS_MIN_RATE), + RATE_LO(TEST_CLK_BUS_MAX_RATE), + RATE_HI(TEST_CLK_BUS_MAX_RATE), + RATE_LO(TEST_CLK_BUS_STEP_RATE), + RATE_HI(TEST_CLK_BUS_STEP_RATE), +}; + +static rpmi_uint32_t get_cpu_rates_bad_index_reqdata[] = { + TEST_CLK_CPU, + 4, +}; + +static rpmi_uint32_t set_config_enable_reqdata[] = { + TEST_CLK_CPU, + 1, +}; + +static rpmi_uint32_t success_expdata[] = { + RPMI_SUCCESS, +}; + +static rpmi_uint32_t get_config_enabled_expdata[] = { + RPMI_SUCCESS, + 1, +}; + +static rpmi_uint32_t set_rate_cpu_reqdata[] = { + TEST_CLK_CPU, + RPMI_CLK_RATE_MATCH_ROUND_UP, + RATE_LO(TEST_CLK_CPU_TARGET_RATE), + RATE_HI(TEST_CLK_CPU_TARGET_RATE), +}; + +static rpmi_uint32_t get_rate_cpu_expdata[] = { + RPMI_SUCCESS, + RATE_LO(TEST_CLK_CPU_TARGET_RATE), + RATE_HI(TEST_CLK_CPU_TARGET_RATE), +}; + +static rpmi_uint32_t set_rate_bad_match_reqdata[] = { + TEST_CLK_CPU, + RPMI_CLK_RATE_MATCH_MAX, + RATE_LO(TEST_CLK_CPU_TARGET_RATE), + RATE_HI(TEST_CLK_CPU_TARGET_RATE), +}; + +static rpmi_uint32_t set_rate_zero_reqdata[] = { + TEST_CLK_CPU, + RPMI_CLK_RATE_MATCH_PLATFORM, + 0, + 0, +}; + +static rpmi_uint32_t set_rate_unsupported_reqdata[] = { + TEST_CLK_CPU, + RPMI_CLK_RATE_MATCH_PLATFORM, + RATE_LO(TEST_CLK_CPU_UNSUPP_RATE), + RATE_HI(TEST_CLK_CPU_UNSUPP_RATE), +}; + +static rpmi_bool_t test_clock_rate_supported(rpmi_uint32_t clock_id, + rpmi_uint64_t rate) +{ + const rpmi_uint64_t *rates; + rpmi_uint32_t count, i; + + if (clock_id >= TEST_CLK_COUNT) + return false; + + if (clock_id == TEST_CLK_CPU) { + rates = test_cpu_rates; + count = ARRAY_SIZE(test_cpu_rates); + } else { + rates = test_bus_rates; + count = ARRAY_SIZE(test_bus_rates); + } + + for (i = 0; i < count; i++) { + if (rates[i] == rate) + return true; + } + + return false; +} + +static enum rpmi_error test_clock_set_state(void *priv, + rpmi_uint32_t clock_id, + enum rpmi_clock_state state) +{ + if (clock_id >= TEST_CLK_COUNT || state >= RPMI_CLK_STATE_MAX) + return RPMI_ERR_INVALID_PARAM; + + test_clock_state[clock_id] = state; + return RPMI_SUCCESS; +} + +static enum rpmi_error test_clock_get_state_and_rate(void *priv, + rpmi_uint32_t clock_id, + enum rpmi_clock_state *state, + rpmi_uint64_t *rate) +{ + if (clock_id >= TEST_CLK_COUNT) + return RPMI_ERR_INVALID_PARAM; + + if (state) + *state = test_clock_state[clock_id]; + if (rate) + *rate = test_clock_rate[clock_id]; + + return RPMI_SUCCESS; +} + +static rpmi_bool_t test_clock_rate_change_match(void *priv, + rpmi_uint32_t clock_id, + rpmi_uint64_t rate) +{ + if (clock_id >= TEST_CLK_COUNT) + return false; + + return test_clock_rate[clock_id] != rate; +} + +static enum rpmi_error test_clock_set_rate(void *priv, + rpmi_uint32_t clock_id, + enum rpmi_clock_rate_match match, + rpmi_uint64_t rate, + rpmi_uint64_t *new_rate) +{ + if (clock_id >= TEST_CLK_COUNT || !new_rate) + return RPMI_ERR_INVALID_PARAM; + + if (!test_clock_rate_supported(clock_id, rate)) + return RPMI_ERR_INVALID_PARAM; + + test_clock_rate[clock_id] = rate; + *new_rate = rate; + return RPMI_SUCCESS; +} + +static enum rpmi_error test_clock_set_rate_recalc(void *priv, + rpmi_uint32_t clock_id, + rpmi_uint64_t parent_rate, + rpmi_uint64_t *new_rate) +{ + if (clock_id >= TEST_CLK_COUNT || !new_rate) + return RPMI_ERR_INVALID_PARAM; + + test_clock_rate[clock_id] = parent_rate; + *new_rate = parent_rate; + return RPMI_SUCCESS; +} + +static struct rpmi_clock_platform_ops test_clock_ops = { + .set_state = test_clock_set_state, + .get_state_and_rate = test_clock_get_state_and_rate, + .rate_change_match = test_clock_rate_change_match, + .set_rate = test_clock_set_rate, + .set_rate_recalc = test_clock_set_rate_recalc, +}; + +static int test_clock_state_init(struct rpmi_test_scenario *scene, + struct rpmi_test *test) +{ + test_clock_state[TEST_CLK_CPU] = RPMI_CLK_STATE_DISABLED; + test_clock_state[TEST_CLK_BUS] = RPMI_CLK_STATE_ENABLED; + test_clock_rate[TEST_CLK_CPU] = TEST_CLK_CPU_INITIAL_RATE; + test_clock_rate[TEST_CLK_BUS] = TEST_CLK_BUS_MIN_RATE; + return 0; +} + +static int test_clock_scenario_init(struct rpmi_test_scenario *scene) +{ + struct rpmi_service_group *grp; + int ret; + + ret = test_scenario_default_init(scene); + if (ret) + return RPMI_ERR_FAILED; + + test_clock_state[TEST_CLK_CPU] = RPMI_CLK_STATE_DISABLED; + test_clock_state[TEST_CLK_BUS] = RPMI_CLK_STATE_ENABLED; + test_clock_rate[TEST_CLK_CPU] = TEST_CLK_CPU_INITIAL_RATE; + test_clock_rate[TEST_CLK_BUS] = TEST_CLK_BUS_MIN_RATE; + + grp = rpmi_service_group_clock_create(TEST_CLK_COUNT, + test_clock_data, + &test_clock_ops, NULL); + if (!grp) { + printf("failed to create rpmi clock service group"); + return RPMI_ERR_FAILED; + } + + rpmi_context_add_group(scene->cntx, grp); + return 0; +} + +static struct rpmi_test_scenario scenario_clock_default = { + .name = "Clock Service Group", + .shm_size = RPMI_SHM_SZ, + .slot_size = RPMI_SLOT_SIZE, + .max_num_groups = RPMI_SRVGRP_ID_MAX_COUNT, + .priv = NULL, + + .init = test_clock_scenario_init, + .cleanup = test_scenario_default_cleanup, + + .num_tests = 16, + .tests = { + { + .name = "ENABLE NOTIFICATION TEST (notifications not supported)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CLOCK, + .service_id = RPMI_CLK_SRV_ENABLE_NOTIFICATION, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = enable_notif_reqdata, + .request_data_len = sizeof(enable_notif_reqdata), + .expected_data = notsupp_expdata, + .expected_data_len = sizeof(notsupp_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET NUM CLOCKS", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CLOCK, + .service_id = RPMI_CLK_SRV_GET_NUM_CLOCKS, + .flags = RPMI_MSG_NORMAL_REQUEST, + .expected_data = get_num_clocks_expdata, + .expected_data_len = sizeof(get_num_clocks_expdata), + }, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET ATTRIBUTES", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CLOCK, + .service_id = RPMI_CLK_SRV_GET_ATTRIBUTES, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = clk_cpu_reqdata, + .request_data_len = sizeof(clk_cpu_reqdata), + .expected_data = &get_attrs_cpu_expdata, + .expected_data_len = sizeof(get_attrs_cpu_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET ATTRIBUTES (invalid clock)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CLOCK, + .service_id = RPMI_CLK_SRV_GET_ATTRIBUTES, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = clk_invalid_reqdata, + .request_data_len = sizeof(clk_invalid_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET SUPPORTED RATES (discrete)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CLOCK, + .service_id = RPMI_CLK_SRV_GET_SUPPORTED_RATES, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = get_cpu_rates_reqdata, + .request_data_len = sizeof(get_cpu_rates_reqdata), + .expected_data = get_cpu_rates_expdata, + .expected_data_len = sizeof(get_cpu_rates_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET SUPPORTED RATES (linear)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CLOCK, + .service_id = RPMI_CLK_SRV_GET_SUPPORTED_RATES, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = get_bus_rates_reqdata, + .request_data_len = sizeof(get_bus_rates_reqdata), + .expected_data = get_bus_rates_expdata, + .expected_data_len = sizeof(get_bus_rates_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET SUPPORTED RATES (bad index)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CLOCK, + .service_id = RPMI_CLK_SRV_GET_SUPPORTED_RATES, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = get_cpu_rates_bad_index_reqdata, + .request_data_len = sizeof(get_cpu_rates_bad_index_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "SET CONFIG (enable)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CLOCK, + .service_id = RPMI_CLK_SRV_SET_CONFIG, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = set_config_enable_reqdata, + .request_data_len = sizeof(set_config_enable_reqdata), + .expected_data = success_expdata, + .expected_data_len = sizeof(success_expdata), + }, + .init = test_clock_state_init, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET CONFIG (enabled)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CLOCK, + .service_id = RPMI_CLK_SRV_GET_CONFIG, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = clk_cpu_reqdata, + .request_data_len = sizeof(clk_cpu_reqdata), + .expected_data = get_config_enabled_expdata, + .expected_data_len = sizeof(get_config_enabled_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET CONFIG (short request)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CLOCK, + .service_id = RPMI_CLK_SRV_GET_CONFIG, + .flags = RPMI_MSG_NORMAL_REQUEST, + .expected_data = notsupp_expdata, + .expected_data_len = sizeof(notsupp_expdata), + }, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "SET RATE", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CLOCK, + .service_id = RPMI_CLK_SRV_SET_RATE, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = set_rate_cpu_reqdata, + .request_data_len = sizeof(set_rate_cpu_reqdata), + .expected_data = success_expdata, + .expected_data_len = sizeof(success_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET RATE", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CLOCK, + .service_id = RPMI_CLK_SRV_GET_RATE, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = clk_cpu_reqdata, + .request_data_len = sizeof(clk_cpu_reqdata), + .expected_data = get_rate_cpu_expdata, + .expected_data_len = sizeof(get_rate_cpu_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "SET RATE (bad match)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CLOCK, + .service_id = RPMI_CLK_SRV_SET_RATE, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = set_rate_bad_match_reqdata, + .request_data_len = sizeof(set_rate_bad_match_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "SET RATE (zero rate)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CLOCK, + .service_id = RPMI_CLK_SRV_SET_RATE, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = set_rate_zero_reqdata, + .request_data_len = sizeof(set_rate_zero_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "SET RATE (unsupported rate)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CLOCK, + .service_id = RPMI_CLK_SRV_SET_RATE, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = set_rate_unsupported_reqdata, + .request_data_len = sizeof(set_rate_unsupported_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET RATE (invalid clock)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_CLOCK, + .service_id = RPMI_CLK_SRV_GET_RATE, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = clk_invalid_reqdata, + .request_data_len = sizeof(clk_invalid_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + }, +}; + +int main(int argc, char *argv[]) +{ + printf("Test Clock Service Group\n"); + return test_scenario_execute(&scenario_clock_default); +} From 241bbd783bfc9ccdc55abd0670957ad5f43383c2 Mon Sep 17 00:00:00 2001 From: Subrahmanya Lingappa Date: Fri, 15 May 2026 11:38:46 +0530 Subject: [PATCH 10/10] test: add Device Power service group coverage Add a dedicated Device Power test scenario and register it in the test object list. The scenario covers notification unsupported behavior, domain count reporting, attributes, state set/get mutation through platform callbacks, invalid domain IDs, short requests, and unsupported power-state rejection. Signed-off-by: Subrahmanya Lingappa --- test/objects.mk | 5 + test/test_srvgrp_device_power.c | 297 ++++++++++++++++++++++++++++++++ 2 files changed, 302 insertions(+) create mode 100644 test/test_srvgrp_device_power.c diff --git a/test/objects.mk b/test/objects.mk index f92dccf..f8edf61 100644 --- a/test/objects.mk +++ b/test/objects.mk @@ -43,3 +43,8 @@ test-elfs-y += test_srvgrp_clock test_srvgrp_clock-objs-y += test/test_log.o test_srvgrp_clock-objs-y += test/test_common.o + +test-elfs-y += test_srvgrp_device_power + +test_srvgrp_device_power-objs-y += test/test_log.o +test_srvgrp_device_power-objs-y += test/test_common.o diff --git a/test/test_srvgrp_device_power.c b/test/test_srvgrp_device_power.c new file mode 100644 index 0000000..5e3f627 --- /dev/null +++ b/test/test_srvgrp_device_power.c @@ -0,0 +1,297 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2024 Ventana Micro Systems Inc. + */ + +#include +#include +#include "test_common.h" +#include "test_log.h" + +#define TEST_DPWR_COUNT 2 +#define TEST_DPWR_GPU 0 +#define TEST_DPWR_NPU 1 +#define TEST_DPWR_INVALID TEST_DPWR_COUNT +#define TEST_DPWR_GPU_LATENCY 15 +#define TEST_DPWR_BAD_STATE 1 +#define TEST_EVENT_ID 0x0 +#define TEST_REQUEST_STATE_ENABLE 0x1 + +struct test_dpwr_attrs_expdata { + rpmi_uint32_t status; + rpmi_uint32_t flags; + rpmi_uint32_t trans_latency; + char name[16]; +}; + +static struct rpmi_dpwr_data test_dpwr_data[TEST_DPWR_COUNT] = { + [TEST_DPWR_GPU] = { + .trans_latency = TEST_DPWR_GPU_LATENCY, + .name = "gpu_pd", + }, + [TEST_DPWR_NPU] = { + .trans_latency = 25, + .name = "npu_pd", + }, +}; + +static rpmi_uint32_t test_dpwr_state[TEST_DPWR_COUNT] = { + RPMI_DPWR_STATE_ON, + RPMI_DPWR_STATE_OFF, +}; + +static rpmi_uint32_t enable_notif_reqdata[] = { + TEST_EVENT_ID, + TEST_REQUEST_STATE_ENABLE, +}; + +static rpmi_uint32_t notsupp_expdata[] = { + RPMI_ERR_NOTSUPP, +}; + +static rpmi_uint32_t get_num_domains_expdata[] = { + RPMI_SUCCESS, + TEST_DPWR_COUNT, +}; + +static rpmi_uint32_t dpwr_gpu_reqdata[] = { + TEST_DPWR_GPU, +}; + +static rpmi_uint32_t dpwr_invalid_reqdata[] = { + TEST_DPWR_INVALID, +}; + +static struct test_dpwr_attrs_expdata get_attrs_gpu_expdata = { + .status = RPMI_SUCCESS, + .flags = 0, + .trans_latency = TEST_DPWR_GPU_LATENCY, + .name = "gpu_pd", +}; + +static rpmi_uint32_t invalid_param_expdata[] = { + RPMI_ERR_INVALID_PARAM, +}; + +static rpmi_uint32_t set_state_off_reqdata[] = { + TEST_DPWR_GPU, + RPMI_DPWR_STATE_OFF, +}; + +static rpmi_uint32_t success_expdata[] = { + RPMI_SUCCESS, +}; + +static rpmi_uint32_t get_state_off_expdata[] = { + RPMI_SUCCESS, + RPMI_DPWR_STATE_OFF, +}; + +static rpmi_uint32_t set_state_bad_reqdata[] = { + TEST_DPWR_GPU, + TEST_DPWR_BAD_STATE, +}; + +static enum rpmi_error test_dpwr_get_state(void *priv, + rpmi_uint32_t dpwr_id, + rpmi_uint32_t *state) +{ + if (dpwr_id >= TEST_DPWR_COUNT || !state) + return RPMI_ERR_INVALID_PARAM; + + *state = test_dpwr_state[dpwr_id]; + return RPMI_SUCCESS; +} + +static enum rpmi_error test_dpwr_set_state(void *priv, + rpmi_uint32_t dpwr_id, + rpmi_uint32_t state) +{ + if (dpwr_id >= TEST_DPWR_COUNT) + return RPMI_ERR_INVALID_PARAM; + + if (state != RPMI_DPWR_STATE_ON && state != RPMI_DPWR_STATE_OFF) + return RPMI_ERR_INVALID_PARAM; + + test_dpwr_state[dpwr_id] = state; + return RPMI_SUCCESS; +} + +static struct rpmi_dpwr_platform_ops test_dpwr_ops = { + .get_state = test_dpwr_get_state, + .set_state = test_dpwr_set_state, +}; + +static int test_dpwr_state_init(struct rpmi_test_scenario *scene, + struct rpmi_test *test) +{ + test_dpwr_state[TEST_DPWR_GPU] = RPMI_DPWR_STATE_ON; + test_dpwr_state[TEST_DPWR_NPU] = RPMI_DPWR_STATE_OFF; + return 0; +} + +static int test_dpwr_scenario_init(struct rpmi_test_scenario *scene) +{ + struct rpmi_service_group *grp; + int ret; + + ret = test_scenario_default_init(scene); + if (ret) + return RPMI_ERR_FAILED; + + test_dpwr_state[TEST_DPWR_GPU] = RPMI_DPWR_STATE_ON; + test_dpwr_state[TEST_DPWR_NPU] = RPMI_DPWR_STATE_OFF; + + grp = rpmi_service_group_dpwr_create(TEST_DPWR_COUNT, + test_dpwr_data, + &test_dpwr_ops, NULL); + if (!grp) { + printf("failed to create rpmi dpwr service group"); + return RPMI_ERR_FAILED; + } + + rpmi_context_add_group(scene->cntx, grp); + return 0; +} + +static struct rpmi_test_scenario scenario_dpwr_default = { + .name = "Device Power Service Group", + .shm_size = RPMI_SHM_SZ, + .slot_size = RPMI_SLOT_SIZE, + .max_num_groups = RPMI_SRVGRP_ID_MAX_COUNT, + .priv = NULL, + + .init = test_dpwr_scenario_init, + .cleanup = test_scenario_default_cleanup, + + .num_tests = 9, + .tests = { + { + .name = "ENABLE NOTIFICATION TEST (notifications not supported)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_DEVICE_POWER, + .service_id = RPMI_DPWR_SRV_ENABLE_NOTIFICATION, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = enable_notif_reqdata, + .request_data_len = sizeof(enable_notif_reqdata), + .expected_data = notsupp_expdata, + .expected_data_len = sizeof(notsupp_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET NUM DOMAINS", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_DEVICE_POWER, + .service_id = RPMI_DPWR_SRV_GET_NUM_DOMAINS, + .flags = RPMI_MSG_NORMAL_REQUEST, + .expected_data = get_num_domains_expdata, + .expected_data_len = sizeof(get_num_domains_expdata), + }, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET ATTRIBUTES", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_DEVICE_POWER, + .service_id = RPMI_DPWR_SRV_GET_ATTRIBUTES, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = dpwr_gpu_reqdata, + .request_data_len = sizeof(dpwr_gpu_reqdata), + .expected_data = &get_attrs_gpu_expdata, + .expected_data_len = sizeof(get_attrs_gpu_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET ATTRIBUTES (invalid domain)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_DEVICE_POWER, + .service_id = RPMI_DPWR_SRV_GET_ATTRIBUTES, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = dpwr_invalid_reqdata, + .request_data_len = sizeof(dpwr_invalid_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "SET STATE (off)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_DEVICE_POWER, + .service_id = RPMI_DPWR_SRV_SET_DPWR_STATE, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = set_state_off_reqdata, + .request_data_len = sizeof(set_state_off_reqdata), + .expected_data = success_expdata, + .expected_data_len = sizeof(success_expdata), + }, + .init = test_dpwr_state_init, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET STATE (off)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_DEVICE_POWER, + .service_id = RPMI_DPWR_SRV_GET_DPWR_STATE, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = dpwr_gpu_reqdata, + .request_data_len = sizeof(dpwr_gpu_reqdata), + .expected_data = get_state_off_expdata, + .expected_data_len = sizeof(get_state_off_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "SET STATE (unsupported state)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_DEVICE_POWER, + .service_id = RPMI_DPWR_SRV_SET_DPWR_STATE, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = set_state_bad_reqdata, + .request_data_len = sizeof(set_state_bad_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET STATE (invalid domain)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_DEVICE_POWER, + .service_id = RPMI_DPWR_SRV_GET_DPWR_STATE, + .flags = RPMI_MSG_NORMAL_REQUEST, + .request_data = dpwr_invalid_reqdata, + .request_data_len = sizeof(dpwr_invalid_reqdata), + .expected_data = invalid_param_expdata, + .expected_data_len = sizeof(invalid_param_expdata), + }, + .init_request_data = test_init_request_data_from_attrs, + .init_expected_data = test_init_expected_data_from_attrs, + }, + { + .name = "GET STATE (short request)", + .attrs = { + .servicegroup_id = RPMI_SRVGRP_DEVICE_POWER, + .service_id = RPMI_DPWR_SRV_GET_DPWR_STATE, + .flags = RPMI_MSG_NORMAL_REQUEST, + .expected_data = notsupp_expdata, + .expected_data_len = sizeof(notsupp_expdata), + }, + .init_expected_data = test_init_expected_data_from_attrs, + }, + }, +}; + +int main(int argc, char *argv[]) +{ + printf("Test Device Power Service Group\n"); + return test_scenario_execute(&scenario_dpwr_default); +}