@@ -492,3 +492,15 @@ void free_mcd_txlist(mcd_txlist_st *txlist)
g_free(txlist->tx);
}
+
+MCDRstInfo *marshal_mcd_rst_info(const mcd_rst_info_st *rst_info)
+{
+ MCDRstInfo *marshal = g_malloc0(sizeof(*marshal));
+
+ *marshal = (MCDRstInfo) {
+ .class_vector = rst_info->class_vector,
+ .info_str = g_strdup(rst_info->info_str),
+ };
+
+ return marshal;
+}
@@ -56,6 +56,8 @@ MCDTx *marshal_mcd_tx(const mcd_tx_st *tx);
MCDTxlist *marshal_mcd_txlist(const mcd_txlist_st *txlist);
+MCDRstInfo *marshal_mcd_rst_info(const mcd_rst_info_st *rst_info);
+
mcd_api_version_st unmarshal_mcd_api_version(MCDAPIVersion *api_version);
mcd_core_con_info_st unmarshal_mcd_core_con_info(MCDCoreConInfo *con_info);
@@ -21,6 +21,8 @@
/* Custom memory space type */
static const mcd_mem_type_et MCD_MEM_SPACE_IS_SECURE = 0x00010000;
+#define MCD_RST_CLASS_SYSTEM_RESET 0
+
static const mcd_error_info_st MCD_ERROR_NOT_IMPLEMENTED = {
.return_status = MCD_RET_ACT_HANDLE_ERROR,
.error_code = MCD_ERR_FN_UNIMPLEMENTED,
@@ -2068,24 +2070,110 @@ mcd_return_et mcd_execute_command_f(const mcd_core_st *core,
mcd_return_et mcd_qry_rst_classes_f(const mcd_core_st *core,
uint32_t *rst_class_vector)
{
- g_server_state.last_error = &MCD_ERROR_NOT_IMPLEMENTED;
- return g_server_state.last_error->return_status;
+ 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 || core_state->open_core != core) {
+ g_server_state.last_error = &MCD_ERROR_UNKNOWN_CORE;
+ return g_server_state.last_error->return_status;
+ }
+
+ if (!rst_class_vector) {
+ core_state->last_error = &MCD_ERROR_INVALID_NULL_PARAM;
+ return core_state->last_error->return_status;
+ }
+
+ *rst_class_vector = (1 << MCD_RST_CLASS_SYSTEM_RESET);
+
+ core_state->last_error = &MCD_ERROR_NONE;
+ return core_state->last_error->return_status;
}
mcd_return_et mcd_qry_rst_class_info_f(const mcd_core_st *core,
uint8_t rst_class,
mcd_rst_info_st *rst_info)
{
+ mcdcore_state *core_state;
- g_server_state.last_error = &MCD_ERROR_NOT_IMPLEMENTED;
+ 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 || core_state->open_core != core) {
+ g_server_state.last_error = &MCD_ERROR_UNKNOWN_CORE;
+ return g_server_state.last_error->return_status;
+ }
+
+ if (rst_class != MCD_RST_CLASS_SYSTEM_RESET) {
+ core_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 = "unknown reset class",
+ };
+ core_state->last_error = &core_state->custom_error;
+ return core_state->last_error->return_status;
+ }
+
+ if (!rst_info) {
+ core_state->last_error = &MCD_ERROR_INVALID_NULL_PARAM;
+ return core_state->last_error->return_status;
+ }
+
+ *rst_info = (mcd_rst_info_st) {
+ .class_vector = (1 << MCD_RST_CLASS_SYSTEM_RESET),
+ .info_str = "System Reset",
+ };
+
+ g_server_state.last_error = &MCD_ERROR_NONE;
return g_server_state.last_error->return_status;
}
mcd_return_et mcd_rst_f(const mcd_core_st *core, uint32_t rst_class_vector,
bool rst_and_halt)
{
- g_server_state.last_error = &MCD_ERROR_NOT_IMPLEMENTED;
- return g_server_state.last_error->return_status;
+ 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 || core_state->open_core != core) {
+ g_server_state.last_error = &MCD_ERROR_UNKNOWN_CORE;
+ return g_server_state.last_error->return_status;
+ }
+
+ if (rst_class_vector != (1 << MCD_RST_CLASS_SYSTEM_RESET)) {
+ core_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 = "unknown reset class",
+ };
+ core_state->last_error = &core_state->custom_error;
+ return core_state->last_error->return_status;
+ }
+
+ if (rst_and_halt) {
+ mcd_return_et ret = mcd_stop_f(core, true);
+ if (ret != MCD_RET_ACT_NONE) {
+ return ret;
+ }
+ }
+
+ qemu_system_reset_request(SHUTDOWN_CAUSE_HOST_UI);
+
+ core_state->last_error = &MCD_ERROR_NONE;
+ return core_state->last_error->return_status;
}
mcd_return_et mcd_chl_open_f(const mcd_core_st *core, mcd_chl_st *channel)
@@ -622,6 +622,67 @@ MCDQryStateResult *qmp_mcd_qry_state(uint32_t core_uid, Error **errp)
return result;
}
+MCDQryRstClassesResult *qmp_mcd_qry_rst_classes(uint32_t core_uid, Error **errp)
+{
+ MCDQryRstClassesResult *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_qry_rst_classes_f(core,
+ &result->rst_class_vector);
+ result->has_rst_class_vector = result->return_status == MCD_RET_ACT_NONE;
+
+ g_stub_state.on_error_ask_server = true;
+ return result;
+}
+
+MCDQryRstClassInfoResult *qmp_mcd_qry_rst_class_info(uint32_t core_uid,
+ uint8_t rst_class,
+ Error **errp)
+{
+ MCDQryRstClassInfoResult *result = g_malloc0(sizeof(*result));
+ mcd_rst_info_st rst_info;
+ 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_qry_rst_class_info_f(core, rst_class,
+ &rst_info);
+ if (result->return_status == MCD_RET_ACT_NONE) {
+ result->rst_info = marshal_mcd_rst_info(&rst_info);
+ }
+
+ g_stub_state.on_error_ask_server = true;
+ return result;
+}
+
+MCDRstResult *qmp_mcd_rst(uint32_t core_uid, uint32_t rst_class_vector,
+ bool rst_and_halt, Error **errp)
+{
+ MCDRstResult *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_rst_f(core, rst_class_vector, rst_and_halt);
+
+ g_stub_state.on_error_ask_server = true;
+ return result;
+}
+
MCDQryTrigInfoResult *qmp_mcd_qry_trig_info(uint32_t core_uid, Error **errp)
{
MCDQryTrigInfoResult *result = g_malloc0(sizeof(*result));
@@ -610,6 +610,24 @@
'stop-str' : 'str',
'info-str' : 'str' } }
+
+##
+# @MCDRstInfo:
+#
+# Structure type containing information about a particular reset class.
+#
+# @class-vector: Reset class vector which issues this reset. Exactly one bit
+# may be set.
+# @info-str: Description of the reset class.
+#
+# Since: 9.1
+##
+{ 'struct': 'MCDRstInfo',
+ 'data': {
+ 'class-vector': 'uint32',
+ 'info-str' : 'str' } }
+
+
##
# == Target Initialization API
##
@@ -1881,6 +1899,117 @@
'returns': 'MCDQryStateResult' }
+##
+# == Reset Control API
+##
+
+
+##
+# @MCDQryRstClassesResult:
+#
+# Return value of @mcd-qry-rst-classes.
+#
+# @return-status: Return code.
+# @rst-class-vector: A 32 bit vector that defines the available reset classes.
+#
+# Since: 9.1
+##
+{ 'struct': 'MCDQryRstClassesResult',
+ 'data': {
+ 'return-status': 'uint32',
+ '*rst-class-vector': 'uint32' }}
+
+
+##
+# @mcd-qry-rst-classes:
+#
+# Function querying information about reset classes supported by the target
+# system.
+#
+# @core-uid: Unique identifier of the open core as returned by @mcd-open-core.
+#
+# Returns: @MCDQryRstClassesResult
+#
+# Since: 9.1
+##
+{ 'command': 'mcd-qry-rst-classes',
+ 'data': { 'core-uid': 'uint32' },
+ 'returns': 'MCDQryRstClassesResult' }
+
+
+##
+# @MCDQryRstClassInfoResult:
+#
+# Return value of @mcd-qry-rst-class-info.
+#
+# @return-status: Return code.
+# @rst-info: Detailed information about the reset class.
+#
+# Since: 9.1
+##
+{ 'struct': 'MCDQryRstClassInfoResult',
+ 'data': {
+ 'return-status': 'uint32',
+ '*rst-info': 'MCDRstInfo' }}
+
+
+##
+# @mcd-qry-rst-class-info:
+#
+# Function querying information about a particular reset class supported by the
+# target system.
+#
+# @core-uid: Unique identifier of the open core as returned by @mcd-open-core.
+# @rst-class: Reset class ID which refers to a bit in the 32-bit reset class
+# vector as obtained by @mcd-qry-rst-classes.
+#
+# Returns: @MCDQryRstClassInfoResult
+#
+# Since: 9.1
+##
+{ 'command': 'mcd-qry-rst-class-info',
+ 'data': {
+ 'core-uid' : 'uint32',
+ 'rst-class': 'uint8'},
+ 'returns': 'MCDQryRstClassInfoResult' }
+
+
+##
+# @MCDRstResult:
+#
+# Return value of @mcd-rst.
+#
+# @return-status: Return code.
+#
+# Since: 9.1
+##
+{ 'struct': 'MCDRstResult', 'data': { 'return-status': 'uint32' } }
+
+
+##
+# @mcd-rst:
+#
+# Function triggering one or more reset signals in parallel on the target
+# system.
+#
+# @core-uid: Unique identifier of the open core as returned by
+# @mcd-open-core.
+# @rst-class-vector: Reset vector specifying the resets which shall be issued.
+# @rst-and-halt: Optionally halting the core if the reset changes the core
+# state.
+#
+# Returns: @MCDRstResult
+#
+# Since: 9.1
+##
+{ 'command': 'mcd-rst',
+ 'data': {
+ 'core-uid' : 'uint32',
+ 'rst-class-vector': 'uint32',
+ 'rst-and-halt' : 'bool'},
+ 'returns': 'MCDRstResult' }
+
+
##
# == Target Trigger Setup API
##
Provide a system reset vector and handle it similar to hmp_system_reset We don't use a QMP related shutdown reason because the mcdserver is implemented independent of the used communication protocol. (In fact, another communication protocol implementation for MCD already exists and can be found at https://gitlab.com/lauterbach/mcdrefsrv) Signed-off-by: Mario Fleischmann <mario.fleischmann@lauterbach.com> --- mcd/libmcd_qapi.c | 12 +++++ mcd/libmcd_qapi.h | 2 + mcd/mcdserver.c | 98 ++++++++++++++++++++++++++++++++-- mcd/mcdstub_qapi.c | 61 +++++++++++++++++++++ qapi/mcd.json | 129 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 297 insertions(+), 5 deletions(-)