Skip to content

Commit 37cae58

Browse files
Liu Shuojren1
authored andcommitted
virtio-heci: Add HBM handler for backend service
HECI Bus Message is important for HECI clients communication. They use HBM for connect, disconnect, get property and so on. In backend service, we need do some emulation for HBM as we are running on top of native MEI driver. Signed-off-by: Liu Shuo <shuo.a.liu@intel.com> Reviewed-by: Li Hao <hao.l.li@intel.com> Reviewed-by: Wang Yu <yu1.wang@intel.com> Reviewed-by: Zhao, Yakui <yakui.zhao@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
1 parent 12b9299 commit 37cae58

File tree

1 file changed

+234
-2
lines changed

1 file changed

+234
-2
lines changed

devicemodel/hw/pci/virtio/virtio_heci.c

Lines changed: 234 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -521,9 +521,232 @@ static void
521521
virtio_heci_hbm_response(struct virtio_heci *vheci,
522522
struct heci_msg_hdr *hdr, void *data, int len)
523523
{
524-
/* TODO: heci hbm response */
524+
struct virtio_heci_client *client;
525+
526+
client = virtio_heci_get_hbm_client(vheci);
527+
if (!client) {
528+
DPRINTF(("vheci: HBM client has been released, ignore.\r\n"));
529+
return;
530+
}
531+
pthread_mutex_lock(&vheci->rx_mutex);
532+
memcpy(client->recv_buf + client->recv_offset, hdr,
533+
sizeof(struct heci_msg_hdr));
534+
client->recv_offset += sizeof(struct heci_msg_hdr);
535+
memcpy(client->recv_buf + client->recv_offset, data, len);
536+
client->recv_offset += len;
537+
vheci->rx_need_sched = true;
538+
539+
pthread_mutex_unlock(&vheci->rx_mutex);
540+
virtio_heci_client_put(vheci, client);
525541
}
526542

543+
static void
544+
virtio_heci_hbm_handler(struct virtio_heci *vheci, void *data)
545+
{
546+
struct heci_hbm_cmd *hbm_cmd = (struct heci_hbm_cmd *)data;
547+
struct heci_msg_hdr *phdr, hdr = {0};
548+
struct virtio_heci_client *client = NULL;
549+
struct mei_request_client_params params_req = {0};
550+
int ret = 0, status = 0;
551+
552+
struct heci_hbm_host_ver_res ver_res = {{0} };
553+
struct heci_hbm_host_enum_req *enum_req;
554+
struct heci_hbm_host_enum_res enum_res = {{0} };
555+
struct heci_hbm_host_client_prop_req *client_prop_req;
556+
struct heci_hbm_host_client_prop_res client_prop_res = {{0} };
557+
struct heci_hbm_client_connect_req *connect_req;
558+
struct heci_hbm_client_connect_res connect_res = {{0} };
559+
struct heci_hbm_client_disconnect_res disconnect_res = {{0} };
560+
struct heci_hbm_flow_ctl flow_ctl_req = {{0} };
561+
struct heci_hbm_flow_ctl *pflow_ctl_req;
562+
563+
DPRINTF(("vheci: HBM cmd[%d] is handling\n\r", hbm_cmd->cmd));
564+
phdr = &hdr;
565+
switch (hbm_cmd->cmd) {
566+
case HECI_HBM_HOST_VERSION:
567+
ver_res = *(struct heci_hbm_host_ver_res *)data;
568+
ver_res.hbm_cmd.is_response = 1;
569+
/* always support host request version */
570+
ver_res.host_ver_support = 1;
571+
populate_heci_hdr(vheci->hbm_client, phdr,
572+
sizeof(struct heci_hbm_host_ver_res), 1);
573+
DPRINTF(("vheci: HBM cmd[%d] response: hdr[%08x]\n\r",
574+
hbm_cmd->cmd, *(unsigned int *)phdr));
575+
print_hex((unsigned char *)&ver_res, sizeof(ver_res));
576+
virtio_heci_hbm_response(vheci, phdr,
577+
&ver_res, sizeof(ver_res));
578+
break;
579+
case HECI_HBM_HOST_STOP:
580+
/* TODO:
581+
* disconnect all clients
582+
*/
583+
DPRINTF(("vheci: %s HBM cmd[%d] not support for now\n\r",
584+
__func__, hbm_cmd->cmd));
585+
break;
586+
case HECI_HBM_ME_STOP:
587+
/* TODO:
588+
* reset all device
589+
*/
590+
DPRINTF(("vheci: %s HBM cmd[%d] not support for now\n\r",
591+
__func__, hbm_cmd->cmd));
592+
break;
593+
case HECI_HBM_HOST_ENUM:
594+
enum_req = (struct heci_hbm_host_enum_req *)data;
595+
enum_res.hbm_cmd = enum_req->hbm_cmd;
596+
enum_res.hbm_cmd.is_response = 1;
597+
/* copy valid_addresses for hbm enum request */
598+
memcpy(enum_res.valid_addresses, &vheci->me_clients_map,
599+
sizeof(enum_res.valid_addresses));
600+
populate_heci_hdr(vheci->hbm_client, phdr,
601+
sizeof(struct heci_hbm_host_enum_res), 1);
602+
DPRINTF(("vheci: HBM cmd[%d] response: hdr[%08x]\n\r",
603+
hbm_cmd->cmd, *(unsigned int *)phdr));
604+
print_hex((unsigned char *)&enum_res, sizeof(enum_res));
605+
virtio_heci_hbm_response(vheci, phdr,
606+
&enum_res, sizeof(enum_res));
607+
break;
608+
case HECI_HBM_HOST_CLIENT_PROP:
609+
client_prop_req = (struct heci_hbm_host_client_prop_req *)data;
610+
client_prop_res.hbm_cmd = client_prop_req->hbm_cmd;
611+
client_prop_res.hbm_cmd.is_response = 1;
612+
613+
client_prop_res.status = HECI_HBM_SUCCESS;
614+
/* get the client's props */
615+
client_prop_res.address = params_req.client_id =
616+
client_prop_req->address;
617+
ret = ioctl(vheci->hbm_client->client_fd,
618+
IOCTL_MEI_REQUEST_CLIENT_PROP, &params_req);
619+
if (ret < 0) {
620+
/* not client found */
621+
client_prop_res.status = HECI_HBM_CLIENT_NOT_FOUND;
622+
}
623+
memcpy(&client_prop_res.props, params_req.data,
624+
sizeof(struct heci_client_properties));
625+
populate_heci_hdr(vheci->hbm_client, phdr,
626+
sizeof(struct heci_hbm_host_client_prop_res), 1);
627+
DPRINTF(("vheci: HBM cmd[%d] response: hdr[%08x]\n\r",
628+
hbm_cmd->cmd, *(unsigned int *)phdr));
629+
print_hex((unsigned char *)&client_prop_res,
630+
sizeof(client_prop_res));
631+
virtio_heci_hbm_response(vheci, phdr,
632+
&client_prop_res, sizeof(client_prop_res));
633+
break;
634+
case HECI_HBM_CLIENT_CONNECT:
635+
/*
636+
* need handle some driver probed clients.
637+
* There are some single connection clients with kernel
638+
* driver probed, like DAL's VM clients, we need emulate
639+
* the response to guest and setup the link between
640+
* virtio_heci_client and front-end client
641+
*/
642+
connect_req = (struct heci_hbm_client_connect_req *)data;
643+
connect_res =
644+
*(struct heci_hbm_client_connect_res *)connect_req;
645+
connect_res.hbm_cmd.is_response = 1;
646+
client = virtio_heci_find_client(vheci, connect_req->host_addr);
647+
if (!client) {
648+
/* no client mapping in mediator, need create */
649+
client = virtio_heci_create_client(vheci,
650+
connect_req->me_addr,
651+
connect_req->host_addr, &status);
652+
if (!client) {
653+
/* create client failed
654+
* TODO: need change the status according to
655+
* the status of virtio_heci_create_client.
656+
*/
657+
connect_res.status = status;
658+
} else
659+
virtio_heci_client_get(client);
660+
} else {
661+
/* already exist, return @HECI_HBM_ALREADY_EXISTS */
662+
connect_res.status = HECI_HBM_ALREADY_EXISTS;
663+
}
664+
populate_heci_hdr(vheci->hbm_client, phdr,
665+
sizeof(struct heci_hbm_client_connect_res), 1);
666+
DPRINTF(("vheci: HBM cmd[%d] response: hdr[%08x]\n\r",
667+
hbm_cmd->cmd, *(unsigned int *)phdr));
668+
print_hex((unsigned char *)&connect_res, sizeof(connect_res));
669+
virtio_heci_hbm_response(vheci, phdr,
670+
&connect_res, sizeof(connect_res));
671+
672+
/* create client failed, not need to send flow control */
673+
if (!client) {
674+
DPRINTF(("vheci: create client failed.\r\n"));
675+
break;
676+
}
677+
678+
/* Give guest a flow control credit to let it send msssage */
679+
flow_ctl_req.hbm_cmd.cmd = HECI_HBM_FLOW_CONTROL;
680+
flow_ctl_req.me_addr = client->client_id;
681+
/*
682+
* single recv buffer client,
683+
*/
684+
if (client->props.single_recv_buf)
685+
flow_ctl_req.host_addr = 0;
686+
else
687+
flow_ctl_req.host_addr = client->client_addr;
688+
689+
virtio_heci_client_put(vheci, client);
690+
populate_heci_hdr(vheci->hbm_client, phdr,
691+
sizeof(struct heci_hbm_flow_ctl), 1);
692+
DPRINTF(("vheci: HBM flow control: hdr[%08x]\n\r",
693+
*(unsigned int *)phdr));
694+
print_hex((unsigned char *)&flow_ctl_req, sizeof(flow_ctl_req));
695+
virtio_heci_hbm_response(vheci, phdr,
696+
&flow_ctl_req, sizeof(flow_ctl_req));
697+
break;
698+
case HECI_HBM_CLIENT_DISCONNECT:
699+
disconnect_res = *(struct heci_hbm_client_disconnect_res *)data;
700+
if (!hbm_cmd->is_response) {
701+
disconnect_res.hbm_cmd.is_response = 1;
702+
disconnect_res.status = 0;
703+
populate_heci_hdr(vheci->hbm_client, phdr,
704+
sizeof(struct heci_hbm_client_disconnect_res),
705+
1);
706+
virtio_heci_hbm_response(vheci, phdr,
707+
&disconnect_res, sizeof(disconnect_res));
708+
}
709+
client = virtio_heci_find_client(vheci,
710+
disconnect_res.host_addr);
711+
if (client) {
712+
virtio_heci_client_put(vheci, client);
713+
/* put once more as find_client will get ref */
714+
virtio_heci_client_put(vheci, client);
715+
} else
716+
DPRINTF(("vheci: client has been disconnected!!\r\n"));
717+
break;
718+
case HECI_HBM_FLOW_CONTROL:
719+
/*
720+
* FE client is ready, we can send message
721+
*/
722+
pflow_ctl_req = (struct heci_hbm_flow_ctl *)data;
723+
client = virtio_heci_find_client(vheci,
724+
pflow_ctl_req->host_addr);
725+
if (client) {
726+
client->recv_creds++;
727+
virtio_heci_client_put(vheci, client);
728+
pthread_mutex_lock(&vheci->rx_mutex);
729+
vheci->rx_need_sched = true;
730+
pthread_mutex_unlock(&vheci->rx_mutex);
731+
} else
732+
DPRINTF(("vheci: client has been released.\r\n"));
733+
break;
734+
case HECI_HBM_CLIENT_CONNECTION_RESET:
735+
/* TODO:
736+
* disconnect all clients
737+
*/
738+
DPRINTF(("vheci: %s HBM cmd[%d] not support for now\n\r",
739+
__func__, hbm_cmd->cmd));
740+
break;
741+
default:
742+
DPRINTF(("vheci: %s HBM cmd[%d] not support for now\n\r",
743+
__func__, hbm_cmd->cmd));
744+
break;
745+
}
746+
DPRINTF(("vheci: HBM cmd[%d] is done!\n\r", hbm_cmd->cmd));
747+
}
748+
749+
527750
static void
528751
virtio_heci_proc_tx(struct virtio_heci *vheci, struct virtio_vq_info *vq)
529752
{
@@ -550,8 +773,17 @@ virtio_heci_proc_tx(struct virtio_heci *vheci, struct virtio_vq_info *vq)
550773

551774
if (hdr_is_hbm(heci_hdr)) {
552775
/*
553-
* TODO: hbm client handler
776+
* hbm client handler
777+
* all hbm will be complete in one msg package,
778+
* so handle here directly
554779
*/
780+
hbm_client = virtio_heci_get_hbm_client(vheci);
781+
if (!hbm_client) {
782+
DPRINTF(("vheci: TX: HBM client get fail!!\r\n"));
783+
goto failed;
784+
}
785+
virtio_heci_hbm_handler(vheci, (void *)iov[1].iov_base);
786+
virtio_heci_client_put(vheci, hbm_client);
555787
} else if (hdr_is_fixed(heci_hdr)) {
556788
/*
557789
* TODO: fixed address client handler

0 commit comments

Comments
 (0)