Exercise the server-reference RPMI policy alongside the shared protocol tests. Cover explicit and default RPMI-off realization, RPMI-on service discovery, FDT layouts, and migration behavior for both property states.
The FDT checks verify mailbox phandles, service IDs, sibling placement, and preservation of the legacy syscon nodes when RPMI is disabled. The RPMI-off migration check is a policy smoke test that verifies command acceptance only; it does not restore a destination VM. Use per-machine queue sizes in the shared protocol harness so the enlarged virt queues and existing server queues both retain correct acknowledgement offsets and ring wraparound. Signed-off-by: Subrahmanya Lingappa <[email protected]> --- tests/qtest/riscv-rpmi-test.c | 434 ++++++++++++++++++++++++++-------- 1 file changed, 336 insertions(+), 98 deletions(-) diff --git a/tests/qtest/riscv-rpmi-test.c b/tests/qtest/riscv-rpmi-test.c index 318c66b426..9cece1e939 100644 --- a/tests/qtest/riscv-rpmi-test.c +++ b/tests/qtest/riscv-rpmi-test.c @@ -16,13 +16,16 @@ #define RPMI_SHMEM_BASE 0x10200000ULL #define RPMI_DOORBELL_BASE 0x10230000ULL +#define RVSERVER_RPMI_SHMEM_BASE 0x110000ULL +#define RVSERVER_RPMI_DOORBELL_BASE 0x140000ULL #define RPMI_SLOT_SIZE 64 -#define RPMI_QUEUE_SIZE 0x7800 -#define RPMI_QUEUE_DATA_SLOTS (RPMI_QUEUE_SIZE / RPMI_SLOT_SIZE - 2) +#define RPMI_VIRT_QUEUE_SIZE 0x7800 +#define RPMI_RVSERVER_QUEUE_SIZE 0x400 +#define RPMI_QUEUE_DATA_SLOTS (rpmi_queue_size / RPMI_SLOT_SIZE - 2) -#define RPMI_A2P_HEAD RPMI_SHMEM_BASE -#define RPMI_A2P_TAIL (RPMI_SHMEM_BASE + RPMI_SLOT_SIZE) -#define RPMI_A2P_SLOT0 (RPMI_SHMEM_BASE + 2 * RPMI_SLOT_SIZE) +#define RPMI_A2P_HEAD rpmi_shmem_base +#define RPMI_A2P_TAIL (rpmi_shmem_base + RPMI_SLOT_SIZE) +#define RPMI_A2P_SLOT0 (rpmi_shmem_base + 2 * RPMI_SLOT_SIZE) #define RPMI_SRVGRP_BASE 0x0001 #define RPMI_SRVGRP_SYSTEM_RESET 0x0003 @@ -61,53 +64,65 @@ #define RPMI_HSM_TEST_START_ADDR 0x80000000ULL #define RPMI_HSM_TEST_RESUME_ADDR 0x80001000ULL -#define RPMI_P2A_ACK_BASE (RPMI_SHMEM_BASE + RPMI_QUEUE_SIZE) +#define RPMI_P2A_ACK_BASE (rpmi_shmem_base + rpmi_queue_size) #define RPMI_P2A_ACK_HEAD RPMI_P2A_ACK_BASE #define RPMI_P2A_ACK_TAIL (RPMI_P2A_ACK_BASE + RPMI_SLOT_SIZE) -static uint64_t rpmi_response_base; - -static uint64_t rpmi_queue_slot(uint64_t queue_base, uint32_t index) -{ - return queue_base + (index + 2) * RPMI_SLOT_SIZE; -} - -static void rpmi_send_request(QTestState *qts, uint16_t service_group, - uint8_t service_id, uint8_t request_type, - const uint32_t *data, size_t data_words) -{ - uint32_t tail = qtest_readl(qts, RPMI_A2P_TAIL); - uint64_t slot = rpmi_queue_slot(RPMI_SHMEM_BASE, tail); - size_t i; - - qtest_writew(qts, slot, service_group); - qtest_writeb(qts, slot + 2, service_id); - qtest_writeb(qts, slot + 3, request_type); - qtest_writew(qts, slot + 4, data_words * sizeof(*data)); - qtest_writew(qts, slot + 6, RPMI_TOKEN); - - for (i = 0; i < data_words; i++) { - qtest_writel(qts, slot + 8 + i * sizeof(*data), data[i]); - } - - g_test_message( - "RPMI_A2P_REQ shmem=0x%016" PRIx64 " doorbell=0x%016" PRIx64 - " group=0x%04x service=0x%02x type=0x%02x data_len=%zu" - " token=0x%04x a2p_tail=%u slot=0x%016" PRIx64, - (uint64_t)RPMI_SHMEM_BASE, (uint64_t)RPMI_DOORBELL_BASE, - service_group, service_id, request_type, data_words * sizeof(*data), - RPMI_TOKEN, tail, slot); - - qtest_writel(qts, RPMI_A2P_TAIL, (tail + 1) % RPMI_QUEUE_DATA_SLOTS); - qtest_writel(qts, RPMI_DOORBELL_BASE, 1); -} - -static uint32_t rpmi_response_word(QTestState *qts, unsigned int word) -{ - return qtest_readl(qts, rpmi_response_base + 8 + word * sizeof(uint32_t)); -} - -static void test_rpmi_virt_fdt_service_nodes(void) +typedef struct RiscvRpmiQTestMachine { + const char *machine_opts; + uint64_t shmem_base; + uint64_t doorbell_base; + uint32_t queue_size; + const char *platform_info; + const char *reset_node; + const char *poweroff_node; +} RiscvRpmiQTestMachine; + +static const RiscvRpmiQTestMachine virt_rpmi_machine = { + .machine_opts = "virt,rpmi=on", + .shmem_base = RPMI_SHMEM_BASE, + .doorbell_base = RPMI_DOORBELL_BASE, + .queue_size = RPMI_VIRT_QUEUE_SIZE, + .platform_info = "QEMU RISC-V virt RPMI", + .reset_node = "/reboot", + .poweroff_node = "/poweroff", +}; + +static const RiscvRpmiQTestMachine rvserver_ref_rpmi_machine = { + .machine_opts = "riscv-server-ref,rpmi=on", + .shmem_base = RVSERVER_RPMI_SHMEM_BASE, + .doorbell_base = RVSERVER_RPMI_DOORBELL_BASE, + .queue_size = RPMI_RVSERVER_QUEUE_SIZE, + .platform_info = "QEMU RISC-V server-ref RPMI", + .reset_node = "/reboot", + .poweroff_node = "/poweroff", +}; + +static const RiscvRpmiQTestMachine rvserver_ref_legacy_machine = { + .machine_opts = "riscv-server-ref,rpmi=off", + .shmem_base = RVSERVER_RPMI_SHMEM_BASE, + .doorbell_base = RVSERVER_RPMI_DOORBELL_BASE, + .queue_size = RPMI_RVSERVER_QUEUE_SIZE, + .platform_info = "QEMU RISC-V server-ref RPMI", + .reset_node = "/reboot", + .poweroff_node = "/poweroff", +}; + +static const RiscvRpmiQTestMachine rvserver_ref_default_machine = { + .machine_opts = "riscv-server-ref", + .shmem_base = RVSERVER_RPMI_SHMEM_BASE, + .doorbell_base = RVSERVER_RPMI_DOORBELL_BASE, + .queue_size = RPMI_RVSERVER_QUEUE_SIZE, + .platform_info = "QEMU RISC-V server-ref RPMI", + .reset_node = "/reboot", + .poweroff_node = "/poweroff", +}; + +static QTestState *rpmi_qtest_init(const RiscvRpmiQTestMachine *machine, + const char *extra_args); + +static void rpmi_test_fdt_service_nodes( + const RiscvRpmiQTestMachine *machine) { static const struct { const char *name; @@ -118,6 +133,7 @@ static void test_rpmi_virt_fdt_service_nodes(void) { "suspend", RPMI_SRVGRP_SYSTEM_SUSPEND }, }; g_autofree char *dtb_path = NULL; + g_autofree char *mailbox_path = NULL; g_autofree char *dtb = NULL; gsize dtb_size; const fdt32_t *prop; @@ -128,7 +144,7 @@ static void test_rpmi_virt_fdt_service_nodes(void) dtb_path = g_strdup_printf("%s/riscv-rpmi-fdt-%u.dtb", g_get_tmp_dir(), (unsigned)getpid()); - qts = qtest_init("-machine virt,rpmi=on -display none -S"); + qts = rpmi_qtest_init(machine, " -display none -S"); qtest_qmp_assert_success(qts, "{ 'execute': 'dumpdtb', 'arguments': " "{ 'filename': %s } }", dtb_path); @@ -137,15 +153,17 @@ static void test_rpmi_virt_fdt_service_nodes(void) g_assert_true(g_file_get_contents(dtb_path, &dtb, &dtb_size, NULL)); g_assert_cmpint(fdt_check_header(dtb), ==, 0); - mailbox_offset = fdt_path_offset(dtb, "/soc/mailbox@10200000"); + mailbox_path = g_strdup_printf("/soc/mailbox@%" PRIx64, + machine->shmem_base); + mailbox_offset = fdt_path_offset(dtb, mailbox_path); g_assert_cmpint(mailbox_offset, >=, 0); prop = fdt_getprop(dtb, mailbox_offset, "reg", &phandle_len); g_assert_nonnull(prop); g_assert_cmpint(phandle_len, >=, 8 * sizeof(*prop)); for (unsigned int queue = 0; queue < 2; queue++) { g_assert_cmphex(fdt32_to_cpu(prop[4 * queue + 1]), ==, - RPMI_SHMEM_BASE + queue * RPMI_QUEUE_SIZE); - g_assert_cmphex(fdt32_to_cpu(prop[4 * queue + 3]), ==, RPMI_QUEUE_SIZE); + machine->shmem_base + queue * machine->queue_size); + g_assert_cmphex(fdt32_to_cpu(prop[4 * queue + 3]), ==, machine->queue_size); } prop = fdt_getprop(dtb, mailbox_offset, "phandle", &phandle_len); g_assert_nonnull(prop); @@ -170,9 +188,111 @@ static void test_rpmi_virt_fdt_service_nodes(void) services[i].service_group); } + g_assert_cmpint(fdt_path_offset(dtb, machine->reset_node), ==, + -FDT_ERR_NOTFOUND); + g_assert_cmpint(fdt_path_offset(dtb, machine->poweroff_node), ==, + -FDT_ERR_NOTFOUND); + g_assert_cmpint(g_remove(dtb_path), ==, 0); } +static void test_rpmi_virt_fdt_service_nodes(void) +{ + rpmi_test_fdt_service_nodes(&virt_rpmi_machine); +} + +static void test_rpmi_rvserver_ref_fdt_service_nodes(void) +{ + rpmi_test_fdt_service_nodes(&rvserver_ref_rpmi_machine); +} + +static void rpmi_test_fdt_legacy_nodes( + const RiscvRpmiQTestMachine *machine) +{ + g_autofree char *dtb_path = NULL; + g_autofree char *dtb = NULL; + gsize dtb_size; + QTestState *qts; + + dtb_path = g_strdup_printf("%s/riscv-rpmi-fdt-legacy-%u.dtb", + g_get_tmp_dir(), (unsigned)getpid()); + qts = rpmi_qtest_init(machine, " -display none -S"); + qtest_qmp_assert_success(qts, + "{ 'execute': 'dumpdtb', 'arguments': " + "{ 'filename': %s } }", dtb_path); + qtest_quit(qts); + + g_assert_true(g_file_get_contents(dtb_path, &dtb, &dtb_size, NULL)); + g_assert_cmpint(fdt_check_header(dtb), ==, 0); + g_assert_cmpint(fdt_path_offset(dtb, machine->reset_node), >=, 0); + g_assert_cmpint(fdt_path_offset(dtb, machine->poweroff_node), >=, 0); + g_assert_cmpint(fdt_path_offset(dtb, "/soc/mailbox@110000"), ==, + -FDT_ERR_NOTFOUND); + g_assert_cmpint(fdt_path_offset(dtb, "/soc/sysreset"), ==, + -FDT_ERR_NOTFOUND); + g_assert_cmpint(g_remove(dtb_path), ==, 0); +} + +static void test_rpmi_rvserver_ref_fdt_legacy_nodes(void) +{ + rpmi_test_fdt_legacy_nodes(&rvserver_ref_legacy_machine); +} + +static uint64_t rpmi_shmem_base = RPMI_SHMEM_BASE; +static uint64_t rpmi_doorbell_base = RPMI_DOORBELL_BASE; +static uint32_t rpmi_queue_size = RPMI_VIRT_QUEUE_SIZE; +static uint64_t rpmi_response_base; + +static QTestState *rpmi_qtest_init(const RiscvRpmiQTestMachine *machine, + const char *extra_args) +{ + rpmi_shmem_base = machine->shmem_base; + rpmi_doorbell_base = machine->doorbell_base; + rpmi_queue_size = machine->queue_size; + + return qtest_initf("-machine %s%s", machine->machine_opts, extra_args); +} + +static uint64_t rpmi_queue_slot(uint64_t queue_base, uint32_t index) +{ + return queue_base + (index + 2) * RPMI_SLOT_SIZE; +} + +static void rpmi_send_request(QTestState *qts, uint16_t service_group, + uint8_t service_id, uint8_t request_type, + const uint32_t *data, size_t data_words) +{ + uint32_t tail = qtest_readl(qts, RPMI_A2P_TAIL); + uint64_t slot = rpmi_queue_slot(rpmi_shmem_base, tail); + size_t i; + + qtest_writew(qts, slot, service_group); + qtest_writeb(qts, slot + 2, service_id); + qtest_writeb(qts, slot + 3, request_type); + qtest_writew(qts, slot + 4, data_words * sizeof(*data)); + qtest_writew(qts, slot + 6, RPMI_TOKEN); + + for (i = 0; i < data_words; i++) { + qtest_writel(qts, slot + 8 + i * sizeof(*data), data[i]); + } + + g_test_message( + "RPMI_A2P_REQ shmem=0x%016" PRIx64 " doorbell=0x%016" PRIx64 + " group=0x%04x service=0x%02x type=0x%02x data_len=%zu" + " token=0x%04x a2p_tail=%u slot=0x%016" PRIx64, + (uint64_t)rpmi_shmem_base, (uint64_t)rpmi_doorbell_base, + service_group, service_id, request_type, data_words * sizeof(*data), + RPMI_TOKEN, tail, slot); + + qtest_writel(qts, RPMI_A2P_TAIL, (tail + 1) % RPMI_QUEUE_DATA_SLOTS); + qtest_writel(qts, rpmi_doorbell_base, 1); +} + +static uint32_t rpmi_response_word(QTestState *qts, unsigned int word) +{ + return qtest_readl(qts, rpmi_response_base + 8 + word * sizeof(uint32_t)); +} + static void rpmi_expect_ack(QTestState *qts, uint16_t service_group, uint8_t service_id, uint16_t data_len) { @@ -194,7 +314,7 @@ static void rpmi_expect_ack(QTestState *qts, uint16_t service_group, " group=0x%04x service=0x%02x type=0x%02x data_len=%u" " token=0x%04x p2a_head=%u slot=0x%016" PRIx64 " status=0x%08x", - (uint64_t)RPMI_SHMEM_BASE, service_group, service_id, + (uint64_t)rpmi_shmem_base, service_group, service_id, RPMI_MSG_ACKNOWLEDGEMENT, data_len, RPMI_TOKEN, head, rpmi_response_base, data_len >= sizeof(uint32_t) ? rpmi_response_word(qts, 0) : 0); @@ -255,30 +375,41 @@ static void test_rpmi_machine_rejects_too_many_harts(void) "max CPUs supported by machine 'virt' is 512"); } -static void test_rpmi_base_platform_info(void) +static void rpmi_check_platform_info(QTestState *qts, const char *expected) { - static const char expected[] = "QEMU RISC-V virt RPMI"; - QTestState *qts; + size_t expected_len = strlen(expected) + 1; size_t i; - qts = qtest_init("-machine virt,rpmi=on"); rpmi_send_request(qts, RPMI_SRVGRP_BASE, RPMI_BASE_SRV_GET_PLATFORM_INFO, RPMI_MSG_NORMAL_REQUEST, NULL, 0); rpmi_expect_ack(qts, RPMI_SRVGRP_BASE, RPMI_BASE_SRV_GET_PLATFORM_INFO, - 2 * sizeof(uint32_t) + sizeof(expected)); + 2 * sizeof(uint32_t) + expected_len); g_assert_cmphex(rpmi_response_word(qts, 0), ==, 0); - g_assert_cmphex(rpmi_response_word(qts, 1), ==, sizeof(expected)); - for (i = 0; i < sizeof(expected); i++) { + g_assert_cmphex(rpmi_response_word(qts, 1), ==, expected_len); + for (i = 0; i < expected_len; i++) { g_assert_cmphex(qtest_readb(qts, rpmi_response_base + 16 + i), ==, expected[i]); } +} + +static void rpmi_test_platform_info(const RiscvRpmiQTestMachine *machine) +{ + QTestState *qts; + + qts = rpmi_qtest_init(machine, ""); + rpmi_check_platform_info(qts, machine->platform_info); qtest_quit(qts); } +static void test_rpmi_base_platform_info(void) +{ + rpmi_test_platform_info(&virt_rpmi_machine); +} + static void rpmi_probe_group(QTestState *qts, uint32_t service_group, bool present) { @@ -297,11 +428,8 @@ static void rpmi_probe_group(QTestState *qts, uint32_t service_group, } } -static void test_rpmi_base_probe_service_groups(void) +static void rpmi_check_service_groups(QTestState *qts) { - QTestState *qts; - - qts = qtest_init("-machine virt,rpmi=on,aia=aplic-imsic"); rpmi_probe_group(qts, RPMI_SRVGRP_BASE, true); qtest_system_reset(qts); rpmi_probe_group(qts, RPMI_SRVGRP_SYSTEM_RESET, true); @@ -309,10 +437,88 @@ static void test_rpmi_base_probe_service_groups(void) rpmi_probe_group(qts, RPMI_SRVGRP_HSM, true); qtest_system_reset(qts); rpmi_probe_group(qts, RPMI_SRVGRP_SYSTEM_SUSPEND, true); +} + +static void rpmi_test_service_groups(const RiscvRpmiQTestMachine *machine, + const char *extra_args) +{ + QTestState *qts; + + qts = rpmi_qtest_init(machine, extra_args); + rpmi_check_service_groups(qts); + + qtest_quit(qts); +} + +static void test_rpmi_base_probe_service_groups(void) +{ + rpmi_test_service_groups(&virt_rpmi_machine, ",aia=aplic-imsic"); +} + +static void test_rpmi_rvserver_ref_machine_realize_off(void) +{ + QTestState *qts; + + qts = rpmi_qtest_init(&rvserver_ref_legacy_machine, ""); + qtest_quit(qts); +} + +static void test_rpmi_rvserver_ref_machine_realize_default(void) +{ + QTestState *qts; + + qts = rpmi_qtest_init(&rvserver_ref_default_machine, ""); + qtest_quit(qts); +} + +static void test_rpmi_rvserver_ref_fdt_default_nodes(void) +{ + rpmi_test_fdt_legacy_nodes(&rvserver_ref_default_machine); +} + +static void test_rpmi_rvserver_ref_platform_info(void) +{ + rpmi_test_platform_info(&rvserver_ref_rpmi_machine); +} + +static void test_rpmi_rvserver_ref_probe_service_groups(void) +{ + rpmi_test_service_groups(&rvserver_ref_rpmi_machine, ""); +} + +static void rpmi_check_hsm_hart_list(QTestState *qts, uint32_t hart_count) +{ + uint32_t start_index = 0; + + rpmi_send_request(qts, RPMI_SRVGRP_HSM, RPMI_HSM_SRV_GET_HART_LIST, + RPMI_MSG_NORMAL_REQUEST, &start_index, 1); + + rpmi_expect_ack(qts, RPMI_SRVGRP_HSM, RPMI_HSM_SRV_GET_HART_LIST, + (3 + hart_count) * sizeof(uint32_t)); + g_assert_cmphex(rpmi_response_word(qts, 0), ==, 0); + g_assert_cmphex(rpmi_response_word(qts, 1), ==, 0); + g_assert_cmphex(rpmi_response_word(qts, 2), ==, hart_count); + for (uint32_t i = 0; i < hart_count; i++) { + g_assert_cmphex(rpmi_response_word(qts, i + 3), ==, i); + } +} + +static void rpmi_test_hsm_hart_list(const RiscvRpmiQTestMachine *machine, + const char *extra_args) +{ + QTestState *qts; + + qts = rpmi_qtest_init(machine, extra_args); + rpmi_check_hsm_hart_list(qts, 4); qtest_quit(qts); } +static void test_rpmi_rvserver_ref_hsm_hart_list(void) +{ + rpmi_test_hsm_hart_list(&rvserver_ref_rpmi_machine, " -smp 4"); +} + static void test_rpmi_sysreset_attrs(void) { static const struct { @@ -325,7 +531,7 @@ static void test_rpmi_sysreset_attrs(void) }; QTestState *qts; - qts = qtest_init("-machine virt,rpmi=on"); + qts = rpmi_qtest_init(&virt_rpmi_machine, ""); for (size_t i = 0; i < ARRAY_SIZE(cases); i++) { if (i) { qtest_system_reset(qts); @@ -348,7 +554,7 @@ static void test_rpmi_sysreset_shutdown(void) { QTestState *qts; - qts = qtest_init("-machine virt,rpmi=on"); + qts = rpmi_qtest_init(&virt_rpmi_machine, ""); rpmi_send_sysreset(qts, RPMI_SYSRST_TYPE_SHUTDOWN, RPMI_MSG_POSTED_REQUEST); qtest_qmp_eventwait(qts, "SHUTDOWN"); @@ -359,7 +565,7 @@ static void test_rpmi_sysreset_cold_reboot(void) { QTestState *qts; - qts = qtest_init("-machine virt,rpmi=on -no-reboot"); + qts = rpmi_qtest_init(&virt_rpmi_machine, " -no-reboot"); rpmi_send_sysreset(qts, RPMI_SYSRST_TYPE_COLD_REBOOT, RPMI_MSG_POSTED_REQUEST); qtest_qmp_eventwait(qts, "SHUTDOWN"); @@ -370,7 +576,7 @@ static void test_rpmi_sysreset_invalid_type(void) { QTestState *qts; - qts = qtest_init("-machine virt,rpmi=on"); + qts = rpmi_qtest_init(&virt_rpmi_machine, ""); rpmi_send_sysreset(qts, RPMI_SYSRST_TYPE_INVALID, RPMI_MSG_NORMAL_REQUEST); @@ -387,7 +593,7 @@ static void test_rpmi_repeated_reset_after_traffic(void) QTestState *qts; uint32_t reset_type = RPMI_SYSRST_TYPE_SHUTDOWN; - qts = qtest_init("-machine virt,rpmi=on,aia=aplic-imsic"); + qts = rpmi_qtest_init(&virt_rpmi_machine, ",aia=aplic-imsic"); for (uint32_t i = 0; i < 5; i++) { rpmi_send_request(qts, RPMI_SRVGRP_SYSTEM_RESET, RPMI_SYSRST_SRV_GET_ATTRIBUTES, @@ -406,7 +612,7 @@ static void test_rpmi_reset_clears_transport(void) { QTestState *qts; - qts = qtest_init("-machine virt,rpmi=on"); + qts = rpmi_qtest_init(&virt_rpmi_machine, ""); rpmi_send_sysreset(qts, RPMI_SYSRST_TYPE_INVALID, RPMI_MSG_NORMAL_REQUEST); rpmi_expect_ack(qts, RPMI_SRVGRP_SYSTEM_RESET, @@ -425,7 +631,7 @@ static void test_rpmi_doorbell_invalid_access(void) { QTestState *qts; - qts = qtest_init("-machine virt,rpmi=on"); + qts = rpmi_qtest_init(&virt_rpmi_machine, ""); qtest_writeb(qts, RPMI_DOORBELL_BASE, 1); qtest_writel(qts, RPMI_DOORBELL_BASE + 4, 1); g_assert_cmphex(qtest_readl(qts, RPMI_DOORBELL_BASE), ==, 0); @@ -437,7 +643,7 @@ static void test_rpmi_queue_bounds(void) { QTestState *qts; - qts = qtest_init("-machine virt,rpmi=on"); + qts = rpmi_qtest_init(&virt_rpmi_machine, ""); qtest_writel(qts, RPMI_A2P_TAIL, RPMI_QUEUE_DATA_SLOTS); qtest_writel(qts, RPMI_DOORBELL_BASE, 1); g_assert_cmphex(qtest_readl(qts, RPMI_A2P_HEAD), ==, 0); @@ -463,7 +669,7 @@ static void test_rpmi_migration_blocked(void) QDict *error; const char *desc; - qts = qtest_init("-machine virt,rpmi=on -S"); + qts = rpmi_qtest_init(&virt_rpmi_machine, " -S"); error = qtest_qmp_assert_failure_ref(qts, "{ 'execute': 'migrate'," " 'arguments': { 'uri': 'exec:cat > /dev/null' } }"); @@ -477,41 +683,50 @@ static void test_rpmi_migration_blocked(void) qtest_quit(qts); } -static void rpmi_expect_hsm_hart_list(QTestState *qts) +static void test_rpmi_rvserver_ref_migration_blocked(void) { - uint32_t start_index = 0; + QTestState *qts; + QDict *error; + const char *desc; - rpmi_send_request(qts, RPMI_SRVGRP_HSM, RPMI_HSM_SRV_GET_HART_LIST, - RPMI_MSG_NORMAL_REQUEST, &start_index, 1); + qts = rpmi_qtest_init(&rvserver_ref_rpmi_machine, " -S"); + error = qtest_qmp_assert_failure_ref(qts, + "{ 'execute': 'migrate'," + " 'arguments': { 'uri': 'exec:cat > /dev/null' } }"); + desc = qdict_get_try_str(error, "desc"); - rpmi_expect_ack(qts, RPMI_SRVGRP_HSM, RPMI_HSM_SRV_GET_HART_LIST, - 7 * sizeof(uint32_t)); - g_assert_cmphex(rpmi_response_word(qts, 0), ==, 0); - g_assert_cmphex(rpmi_response_word(qts, 1), ==, 0); - g_assert_cmphex(rpmi_response_word(qts, 2), ==, 4); - g_assert_cmphex(rpmi_response_word(qts, 3), ==, 0); - g_assert_cmphex(rpmi_response_word(qts, 4), ==, 1); - g_assert_cmphex(rpmi_response_word(qts, 5), ==, 2); - g_assert_cmphex(rpmi_response_word(qts, 6), ==, 3); + g_assert_nonnull(desc); + g_assert_nonnull(strstr(desc, "non-migratable device")); + g_assert_nonnull(strstr(desc, "riscv-rpmi")); + + qobject_unref(error); + qtest_quit(qts); } -static void test_rpmi_hsm_hart_list(void) +static void test_rpmi_rvserver_ref_migration_command_accepted(void) { QTestState *qts; - qts = qtest_init("-machine virt,rpmi=on -smp 4"); - rpmi_expect_hsm_hart_list(qts); - + qts = rpmi_qtest_init(&rvserver_ref_legacy_machine, " -S"); + /* This is a policy smoke test; no migration destination is restored. */ + qtest_qmp_assert_success(qts, + "{ 'execute': 'migrate'," + " 'arguments': { 'uri': 'exec:cat > /dev/null' } }"); qtest_quit(qts); } +static void test_rpmi_hsm_hart_list(void) +{ + rpmi_test_hsm_hart_list(&virt_rpmi_machine, " -smp 4"); +} + static void test_rpmi_hsm_multi_socket_hart_list(void) { QTestState *qts; - qts = qtest_init("-machine virt,rpmi=on " - "-smp 4,sockets=2,cores=2,threads=1"); - rpmi_expect_hsm_hart_list(qts); + qts = rpmi_qtest_init(&virt_rpmi_machine, + " -smp 4,sockets=2,cores=2,threads=1"); + rpmi_check_hsm_hart_list(qts, 4); qtest_quit(qts); } @@ -521,7 +736,7 @@ static void test_rpmi_hsm_hart_status(void) QTestState *qts; uint32_t hart_id = 3; - qts = qtest_init("-machine virt,rpmi=on -smp 4"); + qts = rpmi_qtest_init(&virt_rpmi_machine, " -smp 4"); rpmi_send_request(qts, RPMI_SRVGRP_HSM, RPMI_HSM_SRV_GET_HART_STATUS, RPMI_MSG_NORMAL_REQUEST, &hart_id, 1); @@ -555,7 +770,7 @@ static void test_rpmi_hsm_hart_control(void) uint32_t start_index = 0; uint32_t suspend_type = 0; - qts = qtest_init("-machine virt,rpmi=on -smp 2"); + qts = rpmi_qtest_init(&virt_rpmi_machine, " -smp 2"); rpmi_send_request(qts, RPMI_SRVGRP_HSM, RPMI_HSM_SRV_GET_SUSPEND_TYPES, RPMI_MSG_NORMAL_REQUEST, &start_index, 1); rpmi_expect_ack(qts, RPMI_SRVGRP_HSM, RPMI_HSM_SRV_GET_SUSPEND_TYPES, @@ -601,7 +816,7 @@ static void test_rpmi_hsm_hart_control(void) qtest_quit(qts); - qts = qtest_init("-machine virt,rpmi=on -smp 2"); + qts = rpmi_qtest_init(&virt_rpmi_machine, " -smp 2"); rpmi_send_request(qts, RPMI_SRVGRP_HSM, RPMI_HSM_SRV_HART_SUSPEND, RPMI_MSG_NORMAL_REQUEST, suspend_request, ARRAY_SIZE(suspend_request)); @@ -632,7 +847,7 @@ static void test_rpmi_syssusp_attrs_and_suspend(void) uint32_t suspend_type = 0; uint32_t suspend_request[] = { 0, 0, 0x80000000, 0 }; - qts = qtest_init("-machine virt,rpmi=on -smp 1"); + qts = rpmi_qtest_init(&virt_rpmi_machine, " -smp 1"); rpmi_send_request(qts, RPMI_SRVGRP_SYSTEM_SUSPEND, RPMI_SYSSUSP_SRV_GET_ATTRIBUTES, RPMI_MSG_NORMAL_REQUEST, &suspend_type, 1); @@ -755,5 +970,28 @@ int main(int argc, char **argv) test_rpmi_syssusp_attrs_and_suspend); } + if (qtest_has_machine("riscv-server-ref")) { + qtest_add_func("/riscv/rpmi/rvserver-ref/machine/realize-off", + test_rpmi_rvserver_ref_machine_realize_off); + qtest_add_func("/riscv/rpmi/rvserver-ref/machine/realize-default", + test_rpmi_rvserver_ref_machine_realize_default); + qtest_add_func("/riscv/rpmi/rvserver-ref/fdt/service-nodes", + test_rpmi_rvserver_ref_fdt_service_nodes); + qtest_add_func("/riscv/rpmi/rvserver-ref/fdt/legacy-nodes", + test_rpmi_rvserver_ref_fdt_legacy_nodes); + qtest_add_func("/riscv/rpmi/rvserver-ref/fdt/default-nodes", + test_rpmi_rvserver_ref_fdt_default_nodes); + qtest_add_func("/riscv/rpmi/rvserver-ref/rpmi/platform-info", + test_rpmi_rvserver_ref_platform_info); + qtest_add_func("/riscv/rpmi/rvserver-ref/base/probe-service-groups", + test_rpmi_rvserver_ref_probe_service_groups); + qtest_add_func("/riscv/rpmi/rvserver-ref/hsm/hart-list", + test_rpmi_rvserver_ref_hsm_hart_list); + qtest_add_func("/riscv/rpmi/rvserver-ref/migration/blocked", + test_rpmi_rvserver_ref_migration_blocked); + qtest_add_func("/riscv/rpmi/rvserver-ref/migration/command-accepted", + test_rpmi_rvserver_ref_migration_command_accepted); + } + return g_test_run(); }
