1*6f987b59SSivaprasad Tummala /* SPDX-License-Identifier: BSD-3-Clause 2*6f987b59SSivaprasad Tummala * Copyright(c) 2010-2014 Intel Corporation 3*6f987b59SSivaprasad Tummala */ 4*6f987b59SSivaprasad Tummala 5*6f987b59SSivaprasad Tummala #include <glob.h> 6*6f987b59SSivaprasad Tummala #include <stdio.h> 7*6f987b59SSivaprasad Tummala #include <unistd.h> 8*6f987b59SSivaprasad Tummala #include <limits.h> 9*6f987b59SSivaprasad Tummala #include <fcntl.h> 10*6f987b59SSivaprasad Tummala #include <string.h> 11*6f987b59SSivaprasad Tummala #include <errno.h> 12*6f987b59SSivaprasad Tummala #include <poll.h> 13*6f987b59SSivaprasad Tummala 14*6f987b59SSivaprasad Tummala 15*6f987b59SSivaprasad Tummala #include <rte_log.h> 16*6f987b59SSivaprasad Tummala #include <rte_power_guest_channel.h> 17*6f987b59SSivaprasad Tummala 18*6f987b59SSivaprasad Tummala #include "guest_channel.h" 19*6f987b59SSivaprasad Tummala 20*6f987b59SSivaprasad Tummala RTE_LOG_REGISTER_SUFFIX(guest_channel_logtype, guest_channel, INFO); 21*6f987b59SSivaprasad Tummala #define RTE_LOGTYPE_GUEST_CHANNEL guest_channel_logtype 22*6f987b59SSivaprasad Tummala #define GUEST_CHANNEL_LOG(level, ...) \ 23*6f987b59SSivaprasad Tummala RTE_LOG_LINE(level, GUEST_CHANNEL, "" __VA_ARGS__) 24*6f987b59SSivaprasad Tummala 25*6f987b59SSivaprasad Tummala /* Timeout for incoming message in milliseconds. */ 26*6f987b59SSivaprasad Tummala #define TIMEOUT 10 27*6f987b59SSivaprasad Tummala 28*6f987b59SSivaprasad Tummala static int global_fds[RTE_MAX_LCORE] = { [0 ... RTE_MAX_LCORE-1] = -1 }; 29*6f987b59SSivaprasad Tummala 30*6f987b59SSivaprasad Tummala int 31*6f987b59SSivaprasad Tummala guest_channel_host_check_exists(const char *path) 32*6f987b59SSivaprasad Tummala { 33*6f987b59SSivaprasad Tummala char glob_path[PATH_MAX]; 34*6f987b59SSivaprasad Tummala glob_t g; 35*6f987b59SSivaprasad Tummala int ret; 36*6f987b59SSivaprasad Tummala 37*6f987b59SSivaprasad Tummala /* we cannot know in advance which cores have VM channels, so glob */ 38*6f987b59SSivaprasad Tummala snprintf(glob_path, PATH_MAX, "%s.*", path); 39*6f987b59SSivaprasad Tummala 40*6f987b59SSivaprasad Tummala ret = glob(glob_path, GLOB_NOSORT, NULL, &g); 41*6f987b59SSivaprasad Tummala if (ret != 0) { 42*6f987b59SSivaprasad Tummala /* couldn't read anything */ 43*6f987b59SSivaprasad Tummala ret = 0; 44*6f987b59SSivaprasad Tummala goto out; 45*6f987b59SSivaprasad Tummala } 46*6f987b59SSivaprasad Tummala 47*6f987b59SSivaprasad Tummala /* do we have at least one match? */ 48*6f987b59SSivaprasad Tummala ret = g.gl_pathc > 0; 49*6f987b59SSivaprasad Tummala 50*6f987b59SSivaprasad Tummala out: 51*6f987b59SSivaprasad Tummala globfree(&g); 52*6f987b59SSivaprasad Tummala return ret; 53*6f987b59SSivaprasad Tummala } 54*6f987b59SSivaprasad Tummala 55*6f987b59SSivaprasad Tummala int 56*6f987b59SSivaprasad Tummala guest_channel_host_connect(const char *path, unsigned int lcore_id) 57*6f987b59SSivaprasad Tummala { 58*6f987b59SSivaprasad Tummala int flags, ret; 59*6f987b59SSivaprasad Tummala struct rte_power_channel_packet pkt; 60*6f987b59SSivaprasad Tummala char fd_path[PATH_MAX]; 61*6f987b59SSivaprasad Tummala int fd = -1; 62*6f987b59SSivaprasad Tummala 63*6f987b59SSivaprasad Tummala if (lcore_id >= RTE_MAX_LCORE) { 64*6f987b59SSivaprasad Tummala GUEST_CHANNEL_LOG(ERR, "Channel(%u) is out of range 0...%d", 65*6f987b59SSivaprasad Tummala lcore_id, RTE_MAX_LCORE-1); 66*6f987b59SSivaprasad Tummala return -1; 67*6f987b59SSivaprasad Tummala } 68*6f987b59SSivaprasad Tummala /* check if path is already open */ 69*6f987b59SSivaprasad Tummala if (global_fds[lcore_id] != -1) { 70*6f987b59SSivaprasad Tummala GUEST_CHANNEL_LOG(ERR, "Channel(%u) is already open with fd %d", 71*6f987b59SSivaprasad Tummala lcore_id, global_fds[lcore_id]); 72*6f987b59SSivaprasad Tummala return -1; 73*6f987b59SSivaprasad Tummala } 74*6f987b59SSivaprasad Tummala 75*6f987b59SSivaprasad Tummala snprintf(fd_path, PATH_MAX, "%s.%u", path, lcore_id); 76*6f987b59SSivaprasad Tummala GUEST_CHANNEL_LOG(INFO, "Opening channel '%s' for lcore %u", 77*6f987b59SSivaprasad Tummala fd_path, lcore_id); 78*6f987b59SSivaprasad Tummala fd = open(fd_path, O_RDWR); 79*6f987b59SSivaprasad Tummala if (fd < 0) { 80*6f987b59SSivaprasad Tummala GUEST_CHANNEL_LOG(ERR, "Unable to connect to '%s' with error " 81*6f987b59SSivaprasad Tummala "%s", fd_path, strerror(errno)); 82*6f987b59SSivaprasad Tummala return -1; 83*6f987b59SSivaprasad Tummala } 84*6f987b59SSivaprasad Tummala 85*6f987b59SSivaprasad Tummala flags = fcntl(fd, F_GETFL, 0); 86*6f987b59SSivaprasad Tummala if (flags < 0) { 87*6f987b59SSivaprasad Tummala GUEST_CHANNEL_LOG(ERR, "Failed on fcntl get flags for file %s", 88*6f987b59SSivaprasad Tummala fd_path); 89*6f987b59SSivaprasad Tummala goto error; 90*6f987b59SSivaprasad Tummala } 91*6f987b59SSivaprasad Tummala 92*6f987b59SSivaprasad Tummala flags |= O_NONBLOCK; 93*6f987b59SSivaprasad Tummala if (fcntl(fd, F_SETFL, flags) < 0) { 94*6f987b59SSivaprasad Tummala GUEST_CHANNEL_LOG(ERR, "Failed on setting non-blocking mode for " 95*6f987b59SSivaprasad Tummala "file %s", fd_path); 96*6f987b59SSivaprasad Tummala goto error; 97*6f987b59SSivaprasad Tummala } 98*6f987b59SSivaprasad Tummala /* QEMU needs a delay after connection */ 99*6f987b59SSivaprasad Tummala sleep(1); 100*6f987b59SSivaprasad Tummala 101*6f987b59SSivaprasad Tummala /* Send a test packet, this command is ignored by the host, but a successful 102*6f987b59SSivaprasad Tummala * send indicates that the host endpoint is monitoring. 103*6f987b59SSivaprasad Tummala */ 104*6f987b59SSivaprasad Tummala pkt.command = RTE_POWER_CPU_POWER_CONNECT; 105*6f987b59SSivaprasad Tummala global_fds[lcore_id] = fd; 106*6f987b59SSivaprasad Tummala ret = guest_channel_send_msg(&pkt, lcore_id); 107*6f987b59SSivaprasad Tummala if (ret != 0) { 108*6f987b59SSivaprasad Tummala GUEST_CHANNEL_LOG(ERR, 109*6f987b59SSivaprasad Tummala "Error on channel '%s' communications test: %s", 110*6f987b59SSivaprasad Tummala fd_path, ret > 0 ? strerror(ret) : 111*6f987b59SSivaprasad Tummala "channel not connected"); 112*6f987b59SSivaprasad Tummala goto error; 113*6f987b59SSivaprasad Tummala } 114*6f987b59SSivaprasad Tummala GUEST_CHANNEL_LOG(INFO, "Channel '%s' is now connected", fd_path); 115*6f987b59SSivaprasad Tummala return 0; 116*6f987b59SSivaprasad Tummala error: 117*6f987b59SSivaprasad Tummala close(fd); 118*6f987b59SSivaprasad Tummala global_fds[lcore_id] = -1; 119*6f987b59SSivaprasad Tummala return -1; 120*6f987b59SSivaprasad Tummala } 121*6f987b59SSivaprasad Tummala 122*6f987b59SSivaprasad Tummala int 123*6f987b59SSivaprasad Tummala guest_channel_send_msg(struct rte_power_channel_packet *pkt, 124*6f987b59SSivaprasad Tummala unsigned int lcore_id) 125*6f987b59SSivaprasad Tummala { 126*6f987b59SSivaprasad Tummala int ret, buffer_len = sizeof(*pkt); 127*6f987b59SSivaprasad Tummala void *buffer = pkt; 128*6f987b59SSivaprasad Tummala 129*6f987b59SSivaprasad Tummala if (lcore_id >= RTE_MAX_LCORE) { 130*6f987b59SSivaprasad Tummala GUEST_CHANNEL_LOG(ERR, "Channel(%u) is out of range 0...%d", 131*6f987b59SSivaprasad Tummala lcore_id, RTE_MAX_LCORE-1); 132*6f987b59SSivaprasad Tummala return -1; 133*6f987b59SSivaprasad Tummala } 134*6f987b59SSivaprasad Tummala 135*6f987b59SSivaprasad Tummala if (global_fds[lcore_id] < 0) { 136*6f987b59SSivaprasad Tummala GUEST_CHANNEL_LOG(ERR, "Channel is not connected"); 137*6f987b59SSivaprasad Tummala return -1; 138*6f987b59SSivaprasad Tummala } 139*6f987b59SSivaprasad Tummala while (buffer_len > 0) { 140*6f987b59SSivaprasad Tummala ret = write(global_fds[lcore_id], buffer, buffer_len); 141*6f987b59SSivaprasad Tummala if (ret == buffer_len) 142*6f987b59SSivaprasad Tummala return 0; 143*6f987b59SSivaprasad Tummala if (ret == -1) { 144*6f987b59SSivaprasad Tummala if (errno == EINTR) 145*6f987b59SSivaprasad Tummala continue; 146*6f987b59SSivaprasad Tummala return errno; 147*6f987b59SSivaprasad Tummala } 148*6f987b59SSivaprasad Tummala buffer = (char *)buffer + ret; 149*6f987b59SSivaprasad Tummala buffer_len -= ret; 150*6f987b59SSivaprasad Tummala } 151*6f987b59SSivaprasad Tummala return 0; 152*6f987b59SSivaprasad Tummala } 153*6f987b59SSivaprasad Tummala 154*6f987b59SSivaprasad Tummala int rte_power_guest_channel_send_msg(struct rte_power_channel_packet *pkt, 155*6f987b59SSivaprasad Tummala unsigned int lcore_id) 156*6f987b59SSivaprasad Tummala { 157*6f987b59SSivaprasad Tummala return guest_channel_send_msg(pkt, lcore_id); 158*6f987b59SSivaprasad Tummala } 159*6f987b59SSivaprasad Tummala 160*6f987b59SSivaprasad Tummala int power_guest_channel_read_msg(void *pkt, 161*6f987b59SSivaprasad Tummala size_t pkt_len, 162*6f987b59SSivaprasad Tummala unsigned int lcore_id) 163*6f987b59SSivaprasad Tummala { 164*6f987b59SSivaprasad Tummala int ret; 165*6f987b59SSivaprasad Tummala struct pollfd fds; 166*6f987b59SSivaprasad Tummala 167*6f987b59SSivaprasad Tummala if (pkt_len == 0 || pkt == NULL) 168*6f987b59SSivaprasad Tummala return -1; 169*6f987b59SSivaprasad Tummala 170*6f987b59SSivaprasad Tummala if (lcore_id >= RTE_MAX_LCORE) { 171*6f987b59SSivaprasad Tummala GUEST_CHANNEL_LOG(ERR, "Channel(%u) is out of range 0...%d", 172*6f987b59SSivaprasad Tummala lcore_id, RTE_MAX_LCORE-1); 173*6f987b59SSivaprasad Tummala return -1; 174*6f987b59SSivaprasad Tummala } 175*6f987b59SSivaprasad Tummala 176*6f987b59SSivaprasad Tummala if (global_fds[lcore_id] < 0) { 177*6f987b59SSivaprasad Tummala GUEST_CHANNEL_LOG(ERR, "Channel is not connected"); 178*6f987b59SSivaprasad Tummala return -1; 179*6f987b59SSivaprasad Tummala } 180*6f987b59SSivaprasad Tummala 181*6f987b59SSivaprasad Tummala fds.fd = global_fds[lcore_id]; 182*6f987b59SSivaprasad Tummala fds.events = POLLIN; 183*6f987b59SSivaprasad Tummala 184*6f987b59SSivaprasad Tummala ret = poll(&fds, 1, TIMEOUT); 185*6f987b59SSivaprasad Tummala if (ret == 0) { 186*6f987b59SSivaprasad Tummala GUEST_CHANNEL_LOG(DEBUG, "Timeout occurred during poll function."); 187*6f987b59SSivaprasad Tummala return -1; 188*6f987b59SSivaprasad Tummala } else if (ret < 0) { 189*6f987b59SSivaprasad Tummala GUEST_CHANNEL_LOG(ERR, "Error occurred during poll function: %s", 190*6f987b59SSivaprasad Tummala strerror(errno)); 191*6f987b59SSivaprasad Tummala return -1; 192*6f987b59SSivaprasad Tummala } 193*6f987b59SSivaprasad Tummala 194*6f987b59SSivaprasad Tummala while (pkt_len > 0) { 195*6f987b59SSivaprasad Tummala ret = read(global_fds[lcore_id], 196*6f987b59SSivaprasad Tummala pkt, pkt_len); 197*6f987b59SSivaprasad Tummala 198*6f987b59SSivaprasad Tummala if (ret < 0) { 199*6f987b59SSivaprasad Tummala if (errno == EINTR) 200*6f987b59SSivaprasad Tummala continue; 201*6f987b59SSivaprasad Tummala return -1; 202*6f987b59SSivaprasad Tummala } 203*6f987b59SSivaprasad Tummala 204*6f987b59SSivaprasad Tummala if (ret == 0) { 205*6f987b59SSivaprasad Tummala GUEST_CHANNEL_LOG(ERR, "Expected more data, but connection has been closed."); 206*6f987b59SSivaprasad Tummala return -1; 207*6f987b59SSivaprasad Tummala } 208*6f987b59SSivaprasad Tummala pkt = (char *)pkt + ret; 209*6f987b59SSivaprasad Tummala pkt_len -= ret; 210*6f987b59SSivaprasad Tummala } 211*6f987b59SSivaprasad Tummala 212*6f987b59SSivaprasad Tummala return 0; 213*6f987b59SSivaprasad Tummala } 214*6f987b59SSivaprasad Tummala 215*6f987b59SSivaprasad Tummala int rte_power_guest_channel_receive_msg(void *pkt, 216*6f987b59SSivaprasad Tummala size_t pkt_len, 217*6f987b59SSivaprasad Tummala unsigned int lcore_id) 218*6f987b59SSivaprasad Tummala { 219*6f987b59SSivaprasad Tummala return power_guest_channel_read_msg(pkt, pkt_len, lcore_id); 220*6f987b59SSivaprasad Tummala } 221*6f987b59SSivaprasad Tummala 222*6f987b59SSivaprasad Tummala void 223*6f987b59SSivaprasad Tummala guest_channel_host_disconnect(unsigned int lcore_id) 224*6f987b59SSivaprasad Tummala { 225*6f987b59SSivaprasad Tummala if (lcore_id >= RTE_MAX_LCORE) { 226*6f987b59SSivaprasad Tummala GUEST_CHANNEL_LOG(ERR, "Channel(%u) is out of range 0...%d", 227*6f987b59SSivaprasad Tummala lcore_id, RTE_MAX_LCORE-1); 228*6f987b59SSivaprasad Tummala return; 229*6f987b59SSivaprasad Tummala } 230*6f987b59SSivaprasad Tummala if (global_fds[lcore_id] < 0) 231*6f987b59SSivaprasad Tummala return; 232*6f987b59SSivaprasad Tummala close(global_fds[lcore_id]); 233*6f987b59SSivaprasad Tummala global_fds[lcore_id] = -1; 234*6f987b59SSivaprasad Tummala } 235