kmv/tdx: Introduce CONNECTING/CONNECTED/DISCONNECTED vTPM client state

These states are used to manage the STREAM socket communication,
make sure the QIOChannelSocket is freed properly and return
DEVICE_ERROR to user for disconnected case.

Signed-off-by: Yao Yuan <yuan.yao@intel.com>
This commit is contained in:
Yao Yuan
2023-04-19 14:11:55 +08:00
committed by Nikolay Borisov
parent a038e1f049
commit a43b17b361
2 changed files with 35 additions and 7 deletions

View File

@@ -343,6 +343,13 @@ static void tdx_vtpm_vmcall_service_handle_command(TdxVtpmClient *vtpm_client,
return;
}
if (vtpm_client->state != TDX_VTPM_CLIENT_STATE_CONNECTED) {
tdx_vmcall_service_set_response_state(vsi,
TDG_VP_VMCALL_SERVICE_DEVICE_ERROR);
tdx_vmcall_service_complete_request(vsi);
return;
}
switch (cmd_head->command) {
case TDX_VTPM_SEND_MESSAGE:
tdx_vtpm_handle_send_message(vtpm_client, vsi);
@@ -418,6 +425,19 @@ static void tdx_vtpm_client_handle_trans_protocol(TdxVtpmClient *client,
}
}
static void tdx_vtpm_client_disconnected(TdxVtpmClient *client)
{
if (client->state == TDX_VTPM_CLIENT_STATE_DISCONNECTED) {
return;
}
if (client->parent.ioc) {
object_unref(client->parent.ioc);
}
client->state = TDX_VTPM_CLIENT_STATE_DISCONNECTED;
}
static void tdx_vtpm_client_handle_recv_data(TdxVtpmClient *client)
{
QIOChannelSocket *ioc = client->parent.ioc;
@@ -431,6 +451,7 @@ static void tdx_vtpm_client_handle_recv_data(TdxVtpmClient *client)
NULL);
if (read_size <= 0) {
error_report("Read trans protocol failed: %d", read_size);
tdx_vtpm_client_disconnected(client);
return;
}
@@ -444,10 +465,6 @@ static void tdx_vtpm_socket_client_recv(void *opaque)
{
TdxVtpmClient *client = opaque;
printf("%s: Close connection\n", __func__);
object_unref(OBJECT(client->parent.ioc));
return;
qemu_mutex_lock(&client->lock);
tdx_vtpm_client_handle_recv_data(client);
@@ -475,7 +492,7 @@ static void tdx_vtpm_client_connected(QIOTask *task, gpointer opaque)
ret = qio_task_propagate_error(task, NULL);
if (ret) {
warn_report("Failed to connect vTPM Server");
object_unref(client->parent.ioc);
tdx_vtpm_client_disconnected(client);
return;
}
@@ -487,9 +504,11 @@ static void tdx_vtpm_client_connected(QIOTask *task, gpointer opaque)
NULL, client);
ret = tdx_vtpm_client_send_sync(client);
if (ret) {
if (!ret) {
client->state = TDX_VTPM_CLIENT_STATE_CONNECTED;
} else {
warn_report("Failed to send SYNC message to vTPM Server, connection closed");
object_unref(client->parent.ioc);
tdx_vtpm_client_disconnected(client);
}
}
@@ -508,6 +527,7 @@ static QIOChannelSocket *tdx_vtpm_client_setup_communication(TdxVtpmClient *clie
if (!ioc)
goto free_addr;
client->state = TDX_VTPM_CLIENT_STATE_CONNECTING;
client->parent.ioc = ioc;
/* qio_channel_socket_connect_async refs ioc */
qio_channel_socket_connect_async(ioc, addr, tdx_vtpm_client_connected,

View File

@@ -61,6 +61,13 @@ typedef struct TdxVtpmServer {
int tdx_vtpm_init_server(TdxVtpm *base, TdxVmcallService *vms,
TdxGuest *tdx, TdxVmcallServiceType *type);
enum TdxVtpmClientState {
TDX_VTPM_CLIENT_STATE_INIT,
TDX_VTPM_CLIENT_STATE_CONNECTING,
TDX_VTPM_CLIENT_STATE_DISCONNECTED,
TDX_VTPM_CLIENT_STATE_CONNECTED,
};
struct TdxVtpmClientDataEntry;
struct TdxVtpmClientPendingRequest;
typedef struct TdxVtpmClient {
@@ -75,6 +82,7 @@ typedef struct TdxVtpmClient {
QLIST_HEAD(, TdxVtpmClientPendingRequest) request_list;
SocketRecvBuffer recv_buf;
enum TdxVtpmClientState state;
} TdxVtpmClient;
int tdx_vtpm_init_client(TdxVtpm *base, TdxVmcallService *vms,