In MCD, core-specific operations require an open connection to the core. This commit implements the necessary operations to open and close the connection to cores.
Signed-off-by: Mario Fleischmann <mario.fleischm...@lauterbach.com> --- mcd/mcdserver.c | 176 ++++++++++++++++++++++++++++--- mcd/mcdstub_qapi.c | 116 ++++++++++++++++++++- qapi/mcd.json | 132 +++++++++++++++++++++++- tests/qtest/libmcd-test.c | 52 +++++++++- tests/qtest/libmcd-test.h | 9 +- tests/qtest/mcd-test.c | 212 +++++++++++++++++++++++++++----------- 6 files changed, 613 insertions(+), 84 deletions(-) diff --git a/mcd/mcdserver.c b/mcd/mcdserver.c index 9cc7ec0362..83ffa4f097 100644 --- a/mcd/mcdserver.c +++ b/mcd/mcdserver.c @@ -34,6 +34,13 @@ static const mcd_error_info_st MCD_ERROR_SERVER_NOT_OPEN = { .error_str = "server is not open", }; +static const mcd_error_info_st MCD_ERROR_UNKNOWN_CORE = { + .return_status = MCD_RET_ACT_HANDLE_ERROR, + .error_code = MCD_ERR_PARAM, + .error_events = MCD_ERR_EVT_NONE, + .error_str = "specified core is unknown to server", +}; + static const mcd_error_info_st MCD_ERROR_NONE = { .return_status = MCD_RET_ACT_NONE, .error_code = MCD_ERR_NONE, @@ -44,6 +51,24 @@ static const mcd_error_info_st MCD_ERROR_NONE = { /* reserves memory for custom errors */ static mcd_error_info_st custom_mcd_error; +/** + * struct mcdcore_state - State of a core. + * + * @last_error: Error info of most recent executed function. + * @info: Core connection information. + * @open_core: Open core instance as allocated in mcd_open_core_f(). + * + * MCD is mainly being used on the core level: + * After the initial query functions, a core connection is opened in + * mcd_open_core_f(). The allocated mcd_core_st instance is then the basis + * of subsequent operations. + */ +typedef struct mcdcore_state { + const mcd_error_info_st *last_error; + mcd_core_con_info_st info; + mcd_core_st *open_core; +} mcdcore_state; + /** * struct mcdserver_state - State of the MCD server * @@ -66,6 +91,24 @@ static mcdserver_state g_server_state = { .cores = NULL, }; +static mcdcore_state *find_core(const mcd_core_con_info_st *core_con_info) +{ + uint32_t core_id; + mcdcore_state *core; + + if (!core_con_info || !g_server_state.cores) { + return NULL; + } + + core_id = core_con_info->core_id; + if (core_id > g_server_state.cores->len) { + return NULL; + } + + core = &g_array_index(g_server_state.cores, mcdcore_state, core_id); + return core; +} + mcd_return_et mcd_initialize_f(const mcd_api_version_st *version_req, mcd_impl_version_info_st *impl_info) { @@ -200,16 +243,19 @@ mcd_return_et mcd_open_server_f(const char *system_key, } /* update the internal core information data base */ - g_server_state.cores = g_array_new(false, true, - sizeof(mcd_core_con_info_st)); + g_server_state.cores = g_array_new(false, true, sizeof(mcdcore_state)); CPU_FOREACH(cpu) { ObjectClass *oc = object_get_class(OBJECT(cpu)); const char *cpu_model = object_class_get_name(oc); - mcd_core_con_info_st info = { - .core_id = g_server_state.cores->len, + mcdcore_state c = { + .info = (mcd_core_con_info_st) { + .core_id = g_server_state.cores->len, + }, + .last_error = &MCD_ERROR_NONE, + .open_core = NULL, }; - pstrcpy(info.core, MCD_UNIQUE_NAME_LEN, cpu_model); - g_array_append_val(g_server_state.cores, info); + pstrcpy(c.info.core, MCD_UNIQUE_NAME_LEN, cpu_model); + g_array_append_val(g_server_state.cores, c); } g_server_state.last_error = &MCD_ERROR_NONE; @@ -240,6 +286,14 @@ mcd_return_et mcd_close_server_f(const mcd_server_st *server) return g_server_state.last_error->return_status; } + for (int i = 0; i < g_server_state.cores->len; i++) { + mcdcore_state *c = &g_array_index(g_server_state.cores, + mcdcore_state, i); + if (c->open_core) { + mcd_close_core_f(c->open_core); + } + } + g_array_free(g_server_state.cores, true); g_free(g_server_state.open_server); g_server_state.open_server = NULL; @@ -396,12 +450,11 @@ mcd_return_et mcd_qry_cores_f(const mcd_core_con_info_st *connection_info, i < *num_cores && start_index + i < g_server_state.cores->len; i++) { - mcd_core_con_info_st *info = &g_array_index(g_server_state.cores, - mcd_core_con_info_st, - start_index + i); + mcdcore_state *c = &g_array_index(g_server_state.cores, mcdcore_state, + start_index + i); core_con_info[i] = *connection_info; - core_con_info[i].core_id = info->core_id; - pstrcpy(core_con_info[i].core, MCD_UNIQUE_NAME_LEN, info->core); + core_con_info[i].core_id = c->info.core_id; + pstrcpy(core_con_info[i].core, MCD_UNIQUE_NAME_LEN, c->info.core); } *num_cores = i; @@ -421,21 +474,116 @@ mcd_return_et mcd_qry_core_modes_f(const mcd_core_st *core, mcd_return_et mcd_open_core_f(const mcd_core_con_info_st *core_con_info, mcd_core_st **core) { - g_server_state.last_error = &MCD_ERROR_NOT_IMPLEMENTED; + uint32_t core_id; + mcdcore_state *core_state; + mcd_core_con_info_st *info; + + if (!g_server_state.open_server) { + g_server_state.last_error = &MCD_ERROR_SERVER_NOT_OPEN; + return g_server_state.last_error->return_status; + } + + if (!core_con_info || !core) { + g_server_state.last_error = &MCD_ERROR_INVALID_NULL_PARAM; + return g_server_state.last_error->return_status; + } + + core_id = core_con_info->core_id; + if (core_id > g_server_state.cores->len) { + custom_mcd_error = (mcd_error_info_st) { + .return_status = MCD_RET_ACT_HANDLE_ERROR, + .error_code = MCD_ERR_PARAM, + .error_events = MCD_ERR_EVT_NONE, + .error_str = "specified core index exceeds the number of cores", + }; + g_server_state.last_error = &custom_mcd_error; + return g_server_state.last_error->return_status; + } + + core_state = &g_array_index(g_server_state.cores, mcdcore_state, core_id); + if (core_state->open_core) { + custom_mcd_error = (mcd_error_info_st) { + .return_status = MCD_RET_ACT_HANDLE_ERROR, + .error_code = MCD_ERR_CONNECTION, + .error_events = MCD_ERR_EVT_NONE, + .error_str = "core already open", + }; + g_server_state.last_error = &custom_mcd_error; + return g_server_state.last_error->return_status; + } + + *core = g_malloc(sizeof(mcd_core_st)); + info = g_malloc(sizeof(mcd_core_con_info_st)); + *info = *core_con_info; + (*core)->core_con_info = info; + (*core)->instance = NULL; + core_state->open_core = *core; + core_state->last_error = &MCD_ERROR_NONE; + + g_server_state.last_error = &MCD_ERROR_NONE; return g_server_state.last_error->return_status; } mcd_return_et mcd_close_core_f(const mcd_core_st *core) { - g_server_state.last_error = &MCD_ERROR_NOT_IMPLEMENTED; + mcdcore_state *core_state; + + if (!core) { + g_server_state.last_error = &MCD_ERROR_INVALID_NULL_PARAM; + return g_server_state.last_error->return_status; + } + + core_state = find_core(core->core_con_info); + if (!core_state) { + g_server_state.last_error = &MCD_ERROR_UNKNOWN_CORE; + return g_server_state.last_error->return_status; + } + + if (core_state->open_core != core) { + custom_mcd_error = (mcd_error_info_st) { + .return_status = MCD_RET_ACT_HANDLE_ERROR, + .error_code = MCD_ERR_CONNECTION, + .error_events = MCD_ERR_EVT_NONE, + .error_str = "core not open", + }; + g_server_state.last_error = &custom_mcd_error; + return g_server_state.last_error->return_status; + } + + g_free((void *)core->core_con_info); + g_free((void *)core); + core_state->open_core = NULL; + + g_server_state.last_error = &MCD_ERROR_NONE; return g_server_state.last_error->return_status; } void mcd_qry_error_info_f(const mcd_core_st *core, mcd_error_info_st *error_info) { - if (error_info) { + mcdcore_state *core_state; + + if (!error_info) { + return; + } + + if (!core) { *error_info = *g_server_state.last_error; + return; + } + + core_state = find_core(core->core_con_info); + if (!core_state) { + *error_info = MCD_ERROR_UNKNOWN_CORE; + } else if (core_state->open_core != core) { + *error_info = (mcd_error_info_st) { + .return_status = MCD_RET_ACT_HANDLE_ERROR, + .error_code = MCD_ERR_CONNECTION, + .error_events = MCD_ERR_EVT_NONE, + .error_str = "core not open", + }; + } else { + *error_info = *core_state->last_error; } } diff --git a/mcd/mcdstub_qapi.c b/mcd/mcdstub_qapi.c index f4573bc77c..51292d239d 100644 --- a/mcd/mcdstub_qapi.c +++ b/mcd/mcdstub_qapi.c @@ -18,18 +18,27 @@ /** * struct mcdstub_state - State of the MCD server stub * - * @open_server: Open server instance as allocated in mcd_open_server_f(). - * @open_server_uid: Unique identifier of the open server. + * @open_server: Open server instance as allocated in + * mcd_open_server_f(). + * @open_server_uid: Unique identifier of the open server. + * @open_cores: Array of open cores. + * @custom_error: Last error which occurred in the server stub. + * @on_error_ask_server: Call mcd_qry_error_info_f() when asked for most recent + * error. */ typedef struct mcdstub_state { mcd_server_st *open_server; uint32_t open_server_uid; + GPtrArray *open_cores; + mcd_error_info_st custom_error; + bool on_error_ask_server; } mcdstub_state; static mcdstub_state g_stub_state = { .open_server = NULL, .open_server_uid = 0, + .on_error_ask_server = true, }; static uint32_t store_open_server(mcd_server_st *server) @@ -48,6 +57,50 @@ static mcd_server_st *retrieve_open_server(uint32_t server_uid) } } +static uint32_t store_open_core(mcd_core_st *core) +{ + /* core_uid 0 is reserved */ + uint32_t core_uid = core->core_con_info->core_id + 1; + mcd_core_st **core_p; + + if (!g_stub_state.open_cores) { + g_stub_state.open_cores = g_ptr_array_new(); + } + + if (core_uid > g_stub_state.open_cores->len) { + g_ptr_array_set_size(g_stub_state.open_cores, core_uid); + } + + core_p = (mcd_core_st **) &g_ptr_array_index(g_stub_state.open_cores, + core_uid - 1); + *core_p = core; + return core_uid; +} + +static mcd_return_et retrieve_open_core(uint32_t core_uid, mcd_core_st **core) +{ + if (core_uid > 0 && + (!g_stub_state.open_cores || core_uid > g_stub_state.open_cores->len)) { + g_stub_state.custom_error = (mcd_error_info_st) { + .return_status = MCD_RET_ACT_HANDLE_ERROR, + .error_code = MCD_ERR_PARAM, + .error_events = MCD_ERR_EVT_NONE, + .error_str = "stub: core UID not found", + }; + return g_stub_state.custom_error.return_status; + } + + g_assert(core); + + if (!core_uid) { + *core = NULL; + } else { + *core = g_ptr_array_index(g_stub_state.open_cores, core_uid - 1); + } + + return MCD_RET_ACT_NONE; +} + MCDInitializeResult *qmp_mcd_initialize(MCDAPIVersion *version_req, Error **errp) { @@ -63,6 +116,7 @@ MCDInitializeResult *qmp_mcd_initialize(MCDAPIVersion *version_req, result->impl_info = marshal_mcd_impl_version_info(&impl_info); } + g_stub_state.on_error_ask_server = true; return result; } @@ -105,6 +159,7 @@ MCDQryServersResult *qmp_mcd_qry_servers(const char *host, bool running, g_free(server_info); } + g_stub_state.on_error_ask_server = true; return result; } @@ -125,6 +180,7 @@ MCDOpenServerResult *qmp_mcd_open_server(const char *system_key, result->config_string = g_strdup(server->config_string); } + g_stub_state.on_error_ask_server = true; return result; } @@ -169,6 +225,7 @@ MCDQrySystemsResult *qmp_mcd_qry_systems(uint32_t start_index, g_free(system_con_info); } + g_stub_state.on_error_ask_server = true; return result; } @@ -209,6 +266,7 @@ MCDQryDevicesResult *qmp_mcd_qry_devices(MCDCoreConInfo *system_con_info, g_free(device_con_info); } + g_stub_state.on_error_ask_server = true; return result; } @@ -249,14 +307,64 @@ MCDQryCoresResult *qmp_mcd_qry_cores(MCDCoreConInfo *connection_info, g_free(core_con_info); } + g_stub_state.on_error_ask_server = true; return result; } -MCDErrorInfo *qmp_mcd_qry_error_info(Error **errp) +MCDOpenCoreResult *qmp_mcd_open_core(MCDCoreConInfo *core_con_info, + Error **errp) +{ + MCDOpenCoreResult *result = g_malloc0(sizeof(*result)); + mcd_core_st *core; + mcd_core_con_info_st core_con_info_unmarshalled = + unmarshal_mcd_core_con_info(core_con_info); + + result->return_status = mcd_open_core_f(&core_con_info_unmarshalled, + &core); + + if (result->return_status == MCD_RET_ACT_NONE) { + result->has_core_uid = true; + result->core_uid = store_open_core(core); + result->core_con_info = marshal_mcd_core_con_info(core->core_con_info); + } + + g_stub_state.on_error_ask_server = true; + return result; +} + +MCDCloseCoreResult *qmp_mcd_close_core(uint32_t core_uid, Error **errp) +{ + MCDCloseCoreResult *result = g_malloc0(sizeof(*result)); + mcd_core_st *core = NULL; + + result->return_status = retrieve_open_core(core_uid, &core); + if (result->return_status != MCD_RET_ACT_NONE) { + g_stub_state.on_error_ask_server = false; + return result; + } + + result->return_status = mcd_close_core_f(core); + + g_stub_state.on_error_ask_server = true; + return result; +} + +MCDErrorInfo *qmp_mcd_qry_error_info(uint32_t core_uid, Error **errp) { MCDErrorInfo *result; + mcd_core_st *core = NULL; mcd_error_info_st error_info; - mcd_qry_error_info_f(NULL, &error_info); + + if (retrieve_open_core(core_uid, &core) != MCD_RET_ACT_NONE) { + g_stub_state.on_error_ask_server = false; + } + + if (g_stub_state.on_error_ask_server) { + mcd_qry_error_info_f(core, &error_info); + } else { + error_info = g_stub_state.custom_error; + } + result = marshal_mcd_error_info(&error_info); return result; } diff --git a/qapi/mcd.json b/qapi/mcd.json index 2d581b9d89..7219056464 100644 --- a/qapi/mcd.json +++ b/qapi/mcd.json @@ -713,6 +713,133 @@ # == Core Connection API ## +## +# @MCDOpenCoreResult: +# +# Return value of @mcd-open-core. +# +# @return-status: Return code. +# @core-uid: Unique identifier of the core instance. +# @core-con-info: Core connection information of the core instance. +# +# Since: 9.1 +## +{ 'struct': 'MCDOpenCoreResult', + 'data': { + 'return-status' : 'uint32', + '*core-uid' : 'uint32', + '*core-con-info': 'MCDCoreConInfo' }} + + +## +# @mcd-open-core: +# +# Function opening a core connection. +# +# @core-con-info: Unambiguous core information (e.g. from @mcd-qry-cores). +# +# Returns: @MCDOpenCoreResult +# +# Since: 9.1 +# +# .. qmp-example:: +# +# -> { "execute": "mcd-open-core", +# "arguments": { +# "core-con-info": { +# "core-id": 0, +# "device": "virt-10.0", +# "device-id": 0, +# "device-key": "", +# "system": "", +# "core": "cortex-a53-arm-cpu", +# "host": "", +# "system-key": "qemu-system-aarch64", +# "system-instance": "", +# "acc-hw": "", +# "core-type": 0, +# "device-type": 0, +# "server-key": "", +# "server-port": 0 } } } +# <- { +# "return": { +# "core-con-info": { +# "core-id": 0, +# "device": "virt-10.0", +# "device-id": 0, +# "device-key": "", +# "system": "", +# "core": "cortex-a53-arm-cpu", +# "host": "", +# "system-key": "qemu-system-aarch64", +# "system-instance": "", +# "acc-hw": "", +# "core-type": 0, +# "device-type": 0, +# "server-key": "", +# "server-port": 0 +# }, +# "return-status": 0, +# "core-uid": 1 +# } +# } +## +{ 'command': 'mcd-open-core', + 'data': { 'core-con-info': 'MCDCoreConInfo' }, + 'returns': 'MCDOpenCoreResult' } + + +## +# @MCDCloseCoreResult: +# +# Return value of @mcd-close-core. +# +# @return-status: Return code. +# +# Since: 9.1 +## +{ 'struct': 'MCDCloseCoreResult', 'data': { 'return-status': 'uint32' } } + + +## +# @mcd-close-core: +# +# Function closing a core connection. +# +# @core-uid: Unique identifier of the open core as returned by @mcd-open-core. +# +# Returns: @MCDCloseCoreResult +# +# Since: 9.1 +# +# .. qmp-example:: +# +# -> { "execute": "mcd-close-core", "arguments": { "core-uid": 1 } } +# <- { +# "return": { +# "return-status": 0 +# } +# } +# -> { "execute": "mcd-close-core", "arguments": { "core-uid": 1 } } +# <- { +# "return": { +# "return-status": 3 +# } +# } +# -> { "execute": "mcd-qry-error-info", "arguments": { "core-uid": 1 } } +# <- { +# "return": { +# "error-str": "core not open", +# "error-code": 512, +# "error-events": 0, +# "return-status": 3 +# } +# } +## +{ 'command': 'mcd-close-core', + 'data': { 'core-uid': 'uint32' }, + 'returns': 'MCDCloseCoreResult' } + ## # @mcd-qry-error-info: @@ -720,6 +847,8 @@ # Function allowing the access to detailed error and/or event information after # an API call. # +# @core-uid: Unique identifier of the open core as returned by @mcd-open-core. +# # Returns: @MCDErrorInfo # # Since: 9.1 @@ -736,7 +865,7 @@ # "return-status": 3 # } # } -# -> { "execute": "mcd-qry-error-info" } +# -> { "execute": "mcd-qry-error-info", "arguments": { "core-uid": 0 }} # <- { # "return": { # "error-str": "incompatible versions", @@ -747,4 +876,5 @@ # } ## { 'command': 'mcd-qry-error-info', + 'data': { 'core-uid': 'uint32' }, 'returns': 'MCDErrorInfo' } diff --git a/tests/qtest/libmcd-test.c b/tests/qtest/libmcd-test.c index 0874a0eb4c..c976eb1bed 100644 --- a/tests/qtest/libmcd-test.c +++ b/tests/qtest/libmcd-test.c @@ -72,21 +72,27 @@ MCDInitializeResult *qtest_mcd_initialize(QTestState *qts, return unmarshal; } -MCDErrorInfo *qtest_mcd_qry_error_info(QTestState *qts) +MCDErrorInfo *qtest_mcd_qry_error_info(QTestState *qts, + q_obj_mcd_qry_error_info_arg *args) { Visitor *v; - QDict *resp; + QObject *marshal; + QDict *arg, *resp; QObject *ret; bool ok; MCDErrorInfo *unmarshal; - resp = qtest_qmp(qts, "{'execute': 'mcd-qry-error-info'}"); + MARSHAL_ARGS(q_obj_mcd_qry_error_info_arg); + + resp = qtest_qmp(qts, "{'execute': 'mcd-qry-error-info'," + "'arguments': %p}", arg); UNMARSHAL_RESULT(MCDErrorInfo); return unmarshal; } + void qtest_mcd_exit(QTestState *qts) { QDict *resp = qtest_qmp(qts, "{'execute': 'mcd-exit' }"); @@ -212,3 +218,43 @@ MCDQryCoresResult *qtest_mcd_qry_cores(QTestState *qts, return unmarshal; } + +MCDOpenCoreResult *qtest_mcd_open_core(QTestState *qts, + q_obj_mcd_open_core_arg *args) +{ + Visitor *v; + QObject *marshal; + QDict *arg, *resp; + QObject *ret; + bool ok; + MCDOpenCoreResult *unmarshal; + + MARSHAL_ARGS(q_obj_mcd_open_core_arg); + + resp = qtest_qmp(qts, "{'execute': 'mcd-open-core'," + "'arguments': %p}", arg); + + UNMARSHAL_RESULT(MCDOpenCoreResult); + + return unmarshal; +} + +MCDCloseCoreResult *qtest_mcd_close_core(QTestState *qts, + q_obj_mcd_close_core_arg *args) +{ + Visitor *v; + QObject *marshal; + QDict *arg, *resp; + QObject *ret; + bool ok; + MCDCloseCoreResult *unmarshal; + + MARSHAL_ARGS(q_obj_mcd_close_core_arg); + + resp = qtest_qmp(qts, "{'execute': 'mcd-close-core'," + "'arguments': %p}", arg); + + UNMARSHAL_RESULT(MCDCloseCoreResult); + + return unmarshal; +} diff --git a/tests/qtest/libmcd-test.h b/tests/qtest/libmcd-test.h index baeaf57419..323458785e 100644 --- a/tests/qtest/libmcd-test.h +++ b/tests/qtest/libmcd-test.h @@ -18,7 +18,8 @@ MCDInitializeResult *qtest_mcd_initialize(QTestState *qts, q_obj_mcd_initialize_arg *args); -MCDErrorInfo *qtest_mcd_qry_error_info(QTestState *qts); +MCDErrorInfo *qtest_mcd_qry_error_info(QTestState *qts, + q_obj_mcd_qry_error_info_arg *args); void qtest_mcd_exit(QTestState *qts); @@ -40,4 +41,10 @@ MCDQryDevicesResult *qtest_mcd_qry_devices(QTestState *qts, MCDQryCoresResult *qtest_mcd_qry_cores(QTestState *qts, q_obj_mcd_qry_cores_arg *args); +MCDOpenCoreResult *qtest_mcd_open_core(QTestState *qts, + q_obj_mcd_open_core_arg *args); + +MCDCloseCoreResult *qtest_mcd_close_core(QTestState *qts, + q_obj_mcd_close_core_arg *args); + #endif /* LIBMCD_TEST_H */ diff --git a/tests/qtest/mcd-test.c b/tests/qtest/mcd-test.c index 2e61867c8d..8a7e04c5cf 100644 --- a/tests/qtest/mcd-test.c +++ b/tests/qtest/mcd-test.c @@ -22,6 +22,71 @@ static bool verbose; +static MCDQryCoresResult *open_server_query_cores(QTestState *qts) +{ + char empty_string[] = ""; + + q_obj_mcd_open_server_arg open_server_args = { + .system_key = empty_string, + .config_string = empty_string, + }; + + q_obj_mcd_qry_systems_arg qry_systems_args = { + .start_index = 0, + .num_systems = 1, + }; + + q_obj_mcd_qry_devices_arg qry_devices_args = { + .start_index = 0, + .num_devices = 1, + }; + + /* first for num_cores only */ + q_obj_mcd_qry_cores_arg qry_cores_args = { + .start_index = 0, + .num_cores = 0, + }; + + MCDOpenServerResult *open_server_result; + MCDQrySystemsResult *qry_systems_result; + MCDQryDevicesResult *qry_devices_result; + MCDQryCoresResult *qry_cores_result; + + open_server_result = qtest_mcd_open_server(qts, &open_server_args); + g_assert(open_server_result->return_status == MCD_RET_ACT_NONE); + g_assert(open_server_result->has_server_uid); + qapi_free_MCDOpenServerResult(open_server_result); + + qry_systems_result = qtest_mcd_qry_systems(qts, &qry_systems_args); + g_assert(qry_systems_result->return_status == MCD_RET_ACT_NONE); + g_assert(qry_systems_result->has_system_con_info); + + qry_devices_args.system_con_info = + qry_systems_result->system_con_info->value; + + qry_devices_result = qtest_mcd_qry_devices(qts, &qry_devices_args); + g_assert(qry_devices_result->return_status == MCD_RET_ACT_NONE); + g_assert(qry_devices_result->has_device_con_info); + qapi_free_MCDQrySystemsResult(qry_systems_result); + + qry_cores_args.connection_info = + qry_devices_result->device_con_info->value; + + qry_cores_result = qtest_mcd_qry_cores(qts, &qry_cores_args); + g_assert(qry_cores_result->return_status == MCD_RET_ACT_NONE); + g_assert(qry_cores_result->has_num_cores); + g_assert(qry_cores_result->num_cores > 0); + qry_cores_args.num_cores = qry_cores_result->num_cores; + qapi_free_MCDQryCoresResult(qry_cores_result); + qry_cores_result = qtest_mcd_qry_cores(qts, &qry_cores_args); + g_assert(qry_cores_result->return_status == MCD_RET_ACT_NONE); + g_assert(qry_cores_result->has_num_cores); + g_assert(qry_cores_result->num_cores > 0); + qapi_free_MCDQryDevicesResult(qry_devices_result); + + return qry_cores_result; +} + static void test_initialize(void) { QTestState *qts = qtest_init(QEMU_EXTRA_ARGS); @@ -37,6 +102,8 @@ static void test_initialize(void) .version_req = marshal_mcd_api_version(&version_req), }; + q_obj_mcd_qry_error_info_arg qry_error_info_args = { .core_uid = 0 }; + MCDInitializeResult *result = qtest_mcd_initialize(qts, &qapi_args); g_assert(result->return_status == MCD_RET_ACT_NONE); @@ -67,7 +134,7 @@ static void test_initialize(void) result = qtest_mcd_initialize(qts, &qapi_args); g_assert(result->return_status != MCD_RET_ACT_NONE); - error_info = qtest_mcd_qry_error_info(qts); + error_info = qtest_mcd_qry_error_info(qts, &qry_error_info_args); g_assert(error_info->error_code == MCD_ERR_GENERAL); if (verbose) { @@ -150,7 +217,9 @@ static void test_open_server(void) g_assert(open_server_result->return_status != MCD_RET_ACT_NONE); if (verbose) { - MCDErrorInfo *error_info = qtest_mcd_qry_error_info(qts); + q_obj_mcd_qry_error_info_arg qry_error_info_args = { .core_uid = 0 }; + MCDErrorInfo *error_info = qtest_mcd_qry_error_info(qts, + &qry_error_info_args); fprintf(stderr, "[INFO]\tServer cannot be opened twice: %s\n", error_info->error_str); qapi_free_MCDErrorInfo(error_info); @@ -166,7 +235,9 @@ static void test_open_server(void) g_assert(close_server_result->return_status != MCD_RET_ACT_NONE); if (verbose) { - MCDErrorInfo *error_info = qtest_mcd_qry_error_info(qts); + q_obj_mcd_qry_error_info_arg qry_error_info_args = { .core_uid = 0 }; + MCDErrorInfo *error_info = qtest_mcd_qry_error_info(qts, + &qry_error_info_args); fprintf(stderr, "[INFO]\tServer cannot be closed twice: %s\n", error_info->error_str); qapi_free_MCDErrorInfo(error_info); @@ -179,64 +250,7 @@ static void test_open_server(void) static void test_qry_cores(void) { QTestState *qts = qtest_init(QEMU_EXTRA_ARGS); - - char empty_string[] = ""; - - q_obj_mcd_open_server_arg open_server_args = { - .system_key = empty_string, - .config_string = empty_string, - }; - - q_obj_mcd_qry_systems_arg qry_systems_args = { - .start_index = 0, - .num_systems = 1, - }; - - q_obj_mcd_qry_devices_arg qry_devices_args = { - .start_index = 0, - .num_devices = 1, - }; - - q_obj_mcd_qry_cores_arg qry_cores_args = { - .start_index = 0, - /* first, only query the number of cores */ - .num_cores = 0, - }; - - MCDOpenServerResult *open_server_result; - MCDQrySystemsResult *qry_systems_result; - MCDQryDevicesResult *qry_devices_result; - MCDQryCoresResult *qry_cores_result; - - open_server_result = qtest_mcd_open_server(qts, &open_server_args); - g_assert(open_server_result->return_status == MCD_RET_ACT_NONE); - g_assert(open_server_result->has_server_uid); - qapi_free_MCDOpenServerResult(open_server_result); - - qry_systems_result = qtest_mcd_qry_systems(qts, &qry_systems_args); - g_assert(qry_systems_result->return_status == MCD_RET_ACT_NONE); - g_assert(qry_systems_result->has_system_con_info); - - qry_devices_args.system_con_info = - qry_systems_result->system_con_info->value; - - qry_devices_result = qtest_mcd_qry_devices(qts, &qry_devices_args); - g_assert(qry_devices_result->return_status == MCD_RET_ACT_NONE); - g_assert(qry_devices_result->has_device_con_info); - qapi_free_MCDQrySystemsResult(qry_systems_result); - - qry_cores_args.connection_info = - qry_devices_result->device_con_info->value; - - qry_cores_result = qtest_mcd_qry_cores(qts, &qry_cores_args); - g_assert(qry_cores_result->return_status == MCD_RET_ACT_NONE); - g_assert(qry_cores_result->has_num_cores); - g_assert(qry_cores_result->num_cores > 0); - qry_cores_args.num_cores = qry_cores_result->num_cores; - qapi_free_MCDQryCoresResult(qry_cores_result); - qry_cores_result = qtest_mcd_qry_cores(qts, &qry_cores_args); - qapi_free_MCDQryDevicesResult(qry_devices_result); - + MCDQryCoresResult *qry_cores_result = open_server_query_cores(qts); if (verbose) { MCDCoreConInfoList *core_head = qry_cores_result->core_con_info; for (uint32_t c = 0; c < qry_cores_result->num_cores; c++) { @@ -258,6 +272,81 @@ static void test_qry_cores(void) qtest_quit(qts); } +static void test_open_core(void) +{ + QTestState *qts = qtest_init(QEMU_EXTRA_ARGS); + MCDQryCoresResult *cores_query = open_server_query_cores(qts); + + MCDCoreConInfoList *core_head = cores_query->core_con_info; + for (uint32_t c = 0; c < cores_query->num_cores; c++) { + q_obj_mcd_close_core_arg close_core_args; + MCDCloseCoreResult *close_core_result; + + MCDCoreConInfo *core_con_info = core_head->value; + q_obj_mcd_open_core_arg open_core_args = { + .core_con_info = core_con_info, + }; + + q_obj_mcd_qry_error_info_arg error_info_args = { + .core_uid = 0, + }; + MCDErrorInfo *last_server_error; + + MCDOpenCoreResult *open_core_result = + qtest_mcd_open_core(qts, &open_core_args); + g_assert(open_core_result->return_status == MCD_RET_ACT_NONE); + g_assert(open_core_result->has_core_uid); + + if (verbose) { + fprintf(stderr, "[INFO]\tCore #%d open with UID %d\n", + core_con_info->core_id, + open_core_result->core_uid); + } + + close_core_args.core_uid = open_core_result->core_uid; + + /* Verify that core cannot be opened twice */ + qapi_free_MCDOpenCoreResult(open_core_result); + open_core_result = qtest_mcd_open_core(qts, &open_core_args); + g_assert(open_core_result->return_status != MCD_RET_ACT_NONE); + + last_server_error = qtest_mcd_qry_error_info(qts, &error_info_args); + if (verbose) { + fprintf(stderr, "[INFO]\tCore cannot be opened twice: %s\n", + last_server_error->error_str); + } + qapi_free_MCDErrorInfo(last_server_error); + + close_core_result = qtest_mcd_close_core(qts, &close_core_args); + g_assert(close_core_result->return_status == MCD_RET_ACT_NONE); + + if (verbose) { + fprintf(stderr, "[INFO]\tCore with UID %d closed\n", + close_core_args.core_uid); + } + + /* Check that core cannot be closed twice */ + qapi_free_MCDCloseCoreResult(close_core_result); + close_core_result = qtest_mcd_close_core(qts, &close_core_args); + g_assert(close_core_result->return_status != MCD_RET_ACT_NONE); + + last_server_error = qtest_mcd_qry_error_info(qts, &error_info_args); + if (verbose) { + fprintf(stderr, "[INFO]\tCore cannot be closed twice: %s\n", + last_server_error->error_str); + } + qapi_free_MCDErrorInfo(last_server_error); + + qapi_free_MCDCloseCoreResult(close_core_result); + qapi_free_MCDOpenCoreResult(open_core_result); + core_head = core_head->next; + } + + qapi_free_MCDQryCoresResult(cores_query); + qtest_mcd_exit(qts); + qtest_quit(qts); +} + int main(int argc, char *argv[]) { char *v_env = getenv("V"); @@ -268,5 +357,6 @@ int main(int argc, char *argv[]) qtest_add_func("mcd/qry-servers", test_qry_servers); qtest_add_func("mcd/open-server", test_open_server); qtest_add_func("mcd/qry-cores", test_qry_cores); + qtest_add_func("mcd/open-core", test_open_core); return g_test_run(); } -- 2.34.1