1 // SPDX-License-Identifier: GPL-2.0 OR MIT 2 /* 3 * Copyright 2016 VMware, Inc., Palo Alto, CA., USA 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sub license, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial portions 15 * of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 20 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 * 25 */ 26 27 #include <linux/frame.h> 28 #include <linux/kernel.h> 29 #include <linux/module.h> 30 #include <linux/slab.h> 31 32 #include <asm/hypervisor.h> 33 34 #include "vmwgfx_drv.h" 35 #include "vmwgfx_msg.h" 36 37 #define MESSAGE_STATUS_SUCCESS 0x0001 38 #define MESSAGE_STATUS_DORECV 0x0002 39 #define MESSAGE_STATUS_CPT 0x0010 40 #define MESSAGE_STATUS_HB 0x0080 41 42 #define RPCI_PROTOCOL_NUM 0x49435052 43 #define GUESTMSG_FLAG_COOKIE 0x80000000 44 45 #define RETRIES 3 46 47 #define VMW_HYPERVISOR_MAGIC 0x564D5868 48 49 #define VMW_PORT_CMD_MSG 30 50 #define VMW_PORT_CMD_HB_MSG 0 51 #define VMW_PORT_CMD_OPEN_CHANNEL (MSG_TYPE_OPEN << 16 | VMW_PORT_CMD_MSG) 52 #define VMW_PORT_CMD_CLOSE_CHANNEL (MSG_TYPE_CLOSE << 16 | VMW_PORT_CMD_MSG) 53 #define VMW_PORT_CMD_SENDSIZE (MSG_TYPE_SENDSIZE << 16 | VMW_PORT_CMD_MSG) 54 #define VMW_PORT_CMD_RECVSIZE (MSG_TYPE_RECVSIZE << 16 | VMW_PORT_CMD_MSG) 55 #define VMW_PORT_CMD_RECVSTATUS (MSG_TYPE_RECVSTATUS << 16 | VMW_PORT_CMD_MSG) 56 57 #define HIGH_WORD(X) ((X & 0xFFFF0000) >> 16) 58 59 static u32 vmw_msg_enabled = 1; 60 61 enum rpc_msg_type { 62 MSG_TYPE_OPEN, 63 MSG_TYPE_SENDSIZE, 64 MSG_TYPE_SENDPAYLOAD, 65 MSG_TYPE_RECVSIZE, 66 MSG_TYPE_RECVPAYLOAD, 67 MSG_TYPE_RECVSTATUS, 68 MSG_TYPE_CLOSE, 69 }; 70 71 struct rpc_channel { 72 u16 channel_id; 73 u32 cookie_high; 74 u32 cookie_low; 75 }; 76 77 78 79 /** 80 * vmw_open_channel 81 * 82 * @channel: RPC channel 83 * @protocol: 84 * 85 * Returns: 0 on success 86 */ 87 static int vmw_open_channel(struct rpc_channel *channel, unsigned int protocol) 88 { 89 unsigned long eax, ebx, ecx, edx, si = 0, di = 0; 90 91 VMW_PORT(VMW_PORT_CMD_OPEN_CHANNEL, 92 (protocol | GUESTMSG_FLAG_COOKIE), si, di, 93 0, 94 VMW_HYPERVISOR_MAGIC, 95 eax, ebx, ecx, edx, si, di); 96 97 if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0) 98 return -EINVAL; 99 100 channel->channel_id = HIGH_WORD(edx); 101 channel->cookie_high = si; 102 channel->cookie_low = di; 103 104 return 0; 105 } 106 107 108 109 /** 110 * vmw_close_channel 111 * 112 * @channel: RPC channel 113 * 114 * Returns: 0 on success 115 */ 116 static int vmw_close_channel(struct rpc_channel *channel) 117 { 118 unsigned long eax, ebx, ecx, edx, si, di; 119 120 /* Set up additional parameters */ 121 si = channel->cookie_high; 122 di = channel->cookie_low; 123 124 VMW_PORT(VMW_PORT_CMD_CLOSE_CHANNEL, 125 0, si, di, 126 channel->channel_id << 16, 127 VMW_HYPERVISOR_MAGIC, 128 eax, ebx, ecx, edx, si, di); 129 130 if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0) 131 return -EINVAL; 132 133 return 0; 134 } 135 136 /** 137 * vmw_port_hb_out - Send the message payload either through the 138 * high-bandwidth port if available, or through the backdoor otherwise. 139 * @channel: The rpc channel. 140 * @msg: NULL-terminated message. 141 * @hb: Whether the high-bandwidth port is available. 142 * 143 * Return: The port status. 144 */ 145 static unsigned long vmw_port_hb_out(struct rpc_channel *channel, 146 const char *msg, bool hb) 147 { 148 unsigned long si, di, eax, ebx, ecx, edx; 149 unsigned long msg_len = strlen(msg); 150 151 if (hb) { 152 unsigned long bp = channel->cookie_high; 153 154 si = (uintptr_t) msg; 155 di = channel->cookie_low; 156 157 VMW_PORT_HB_OUT( 158 (MESSAGE_STATUS_SUCCESS << 16) | VMW_PORT_CMD_HB_MSG, 159 msg_len, si, di, 160 VMWARE_HYPERVISOR_HB | (channel->channel_id << 16) | 161 VMWARE_HYPERVISOR_OUT, 162 VMW_HYPERVISOR_MAGIC, bp, 163 eax, ebx, ecx, edx, si, di); 164 165 return ebx; 166 } 167 168 /* HB port not available. Send the message 4 bytes at a time. */ 169 ecx = MESSAGE_STATUS_SUCCESS << 16; 170 while (msg_len && (HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS)) { 171 unsigned int bytes = min_t(size_t, msg_len, 4); 172 unsigned long word = 0; 173 174 memcpy(&word, msg, bytes); 175 msg_len -= bytes; 176 msg += bytes; 177 si = channel->cookie_high; 178 di = channel->cookie_low; 179 180 VMW_PORT(VMW_PORT_CMD_MSG | (MSG_TYPE_SENDPAYLOAD << 16), 181 word, si, di, 182 channel->channel_id << 16, 183 VMW_HYPERVISOR_MAGIC, 184 eax, ebx, ecx, edx, si, di); 185 } 186 187 return ecx; 188 } 189 190 /** 191 * vmw_port_hb_in - Receive the message payload either through the 192 * high-bandwidth port if available, or through the backdoor otherwise. 193 * @channel: The rpc channel. 194 * @reply: Pointer to buffer holding reply. 195 * @reply_len: Length of the reply. 196 * @hb: Whether the high-bandwidth port is available. 197 * 198 * Return: The port status. 199 */ 200 static unsigned long vmw_port_hb_in(struct rpc_channel *channel, char *reply, 201 unsigned long reply_len, bool hb) 202 { 203 unsigned long si, di, eax, ebx, ecx, edx; 204 205 if (hb) { 206 unsigned long bp = channel->cookie_low; 207 208 si = channel->cookie_high; 209 di = (uintptr_t) reply; 210 211 VMW_PORT_HB_IN( 212 (MESSAGE_STATUS_SUCCESS << 16) | VMW_PORT_CMD_HB_MSG, 213 reply_len, si, di, 214 VMWARE_HYPERVISOR_HB | (channel->channel_id << 16), 215 VMW_HYPERVISOR_MAGIC, bp, 216 eax, ebx, ecx, edx, si, di); 217 218 return ebx; 219 } 220 221 /* HB port not available. Retrieve the message 4 bytes at a time. */ 222 ecx = MESSAGE_STATUS_SUCCESS << 16; 223 while (reply_len) { 224 unsigned int bytes = min_t(unsigned long, reply_len, 4); 225 226 si = channel->cookie_high; 227 di = channel->cookie_low; 228 229 VMW_PORT(VMW_PORT_CMD_MSG | (MSG_TYPE_RECVPAYLOAD << 16), 230 MESSAGE_STATUS_SUCCESS, si, di, 231 channel->channel_id << 16, 232 VMW_HYPERVISOR_MAGIC, 233 eax, ebx, ecx, edx, si, di); 234 235 if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0) 236 break; 237 238 memcpy(reply, &ebx, bytes); 239 reply_len -= bytes; 240 reply += bytes; 241 } 242 243 return ecx; 244 } 245 246 247 /** 248 * vmw_send_msg: Sends a message to the host 249 * 250 * @channel: RPC channel 251 * @logmsg: NULL terminated string 252 * 253 * Returns: 0 on success 254 */ 255 static int vmw_send_msg(struct rpc_channel *channel, const char *msg) 256 { 257 unsigned long eax, ebx, ecx, edx, si, di; 258 size_t msg_len = strlen(msg); 259 int retries = 0; 260 261 while (retries < RETRIES) { 262 retries++; 263 264 /* Set up additional parameters */ 265 si = channel->cookie_high; 266 di = channel->cookie_low; 267 268 VMW_PORT(VMW_PORT_CMD_SENDSIZE, 269 msg_len, si, di, 270 channel->channel_id << 16, 271 VMW_HYPERVISOR_MAGIC, 272 eax, ebx, ecx, edx, si, di); 273 274 if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0) { 275 /* Expected success. Give up. */ 276 return -EINVAL; 277 } 278 279 /* Send msg */ 280 ebx = vmw_port_hb_out(channel, msg, 281 !!(HIGH_WORD(ecx) & MESSAGE_STATUS_HB)); 282 283 if ((HIGH_WORD(ebx) & MESSAGE_STATUS_SUCCESS) != 0) { 284 return 0; 285 } else if ((HIGH_WORD(ebx) & MESSAGE_STATUS_CPT) != 0) { 286 /* A checkpoint occurred. Retry. */ 287 continue; 288 } else { 289 break; 290 } 291 } 292 293 return -EINVAL; 294 } 295 STACK_FRAME_NON_STANDARD(vmw_send_msg); 296 297 298 /** 299 * vmw_recv_msg: Receives a message from the host 300 * 301 * Note: It is the caller's responsibility to call kfree() on msg. 302 * 303 * @channel: channel opened by vmw_open_channel 304 * @msg: [OUT] message received from the host 305 * @msg_len: message length 306 */ 307 static int vmw_recv_msg(struct rpc_channel *channel, void **msg, 308 size_t *msg_len) 309 { 310 unsigned long eax, ebx, ecx, edx, si, di; 311 char *reply; 312 size_t reply_len; 313 int retries = 0; 314 315 316 *msg_len = 0; 317 *msg = NULL; 318 319 while (retries < RETRIES) { 320 retries++; 321 322 /* Set up additional parameters */ 323 si = channel->cookie_high; 324 di = channel->cookie_low; 325 326 VMW_PORT(VMW_PORT_CMD_RECVSIZE, 327 0, si, di, 328 channel->channel_id << 16, 329 VMW_HYPERVISOR_MAGIC, 330 eax, ebx, ecx, edx, si, di); 331 332 if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0) { 333 DRM_ERROR("Failed to get reply size for host message.\n"); 334 return -EINVAL; 335 } 336 337 /* No reply available. This is okay. */ 338 if ((HIGH_WORD(ecx) & MESSAGE_STATUS_DORECV) == 0) 339 return 0; 340 341 reply_len = ebx; 342 reply = kzalloc(reply_len + 1, GFP_KERNEL); 343 if (!reply) { 344 DRM_ERROR("Cannot allocate memory for host message reply.\n"); 345 return -ENOMEM; 346 } 347 348 349 /* Receive buffer */ 350 ebx = vmw_port_hb_in(channel, reply, reply_len, 351 !!(HIGH_WORD(ecx) & MESSAGE_STATUS_HB)); 352 if ((HIGH_WORD(ebx) & MESSAGE_STATUS_SUCCESS) == 0) { 353 kfree(reply); 354 reply = NULL; 355 if ((HIGH_WORD(ebx) & MESSAGE_STATUS_CPT) != 0) { 356 /* A checkpoint occurred. Retry. */ 357 continue; 358 } 359 360 return -EINVAL; 361 } 362 363 reply[reply_len] = '\0'; 364 365 366 /* Ack buffer */ 367 si = channel->cookie_high; 368 di = channel->cookie_low; 369 370 VMW_PORT(VMW_PORT_CMD_RECVSTATUS, 371 MESSAGE_STATUS_SUCCESS, si, di, 372 channel->channel_id << 16, 373 VMW_HYPERVISOR_MAGIC, 374 eax, ebx, ecx, edx, si, di); 375 376 if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0) { 377 kfree(reply); 378 reply = NULL; 379 if ((HIGH_WORD(ecx) & MESSAGE_STATUS_CPT) != 0) { 380 /* A checkpoint occurred. Retry. */ 381 continue; 382 } 383 384 return -EINVAL; 385 } 386 387 break; 388 } 389 390 if (!reply) 391 return -EINVAL; 392 393 *msg_len = reply_len; 394 *msg = reply; 395 396 return 0; 397 } 398 STACK_FRAME_NON_STANDARD(vmw_recv_msg); 399 400 401 /** 402 * vmw_host_get_guestinfo: Gets a GuestInfo parameter 403 * 404 * Gets the value of a GuestInfo.* parameter. The value returned will be in 405 * a string, and it is up to the caller to post-process. 406 * 407 * @guest_info_param: Parameter to get, e.g. GuestInfo.svga.gl3 408 * @buffer: if NULL, *reply_len will contain reply size. 409 * @length: size of the reply_buf. Set to size of reply upon return 410 * 411 * Returns: 0 on success 412 */ 413 int vmw_host_get_guestinfo(const char *guest_info_param, 414 char *buffer, size_t *length) 415 { 416 struct rpc_channel channel; 417 char *msg, *reply = NULL; 418 size_t reply_len = 0; 419 420 if (!vmw_msg_enabled) 421 return -ENODEV; 422 423 if (!guest_info_param || !length) 424 return -EINVAL; 425 426 msg = kasprintf(GFP_KERNEL, "info-get %s", guest_info_param); 427 if (!msg) { 428 DRM_ERROR("Cannot allocate memory to get guest info \"%s\".", 429 guest_info_param); 430 return -ENOMEM; 431 } 432 433 if (vmw_open_channel(&channel, RPCI_PROTOCOL_NUM)) 434 goto out_open; 435 436 if (vmw_send_msg(&channel, msg) || 437 vmw_recv_msg(&channel, (void *) &reply, &reply_len)) 438 goto out_msg; 439 440 vmw_close_channel(&channel); 441 if (buffer && reply && reply_len > 0) { 442 /* Remove reply code, which are the first 2 characters of 443 * the reply 444 */ 445 reply_len = max(reply_len - 2, (size_t) 0); 446 reply_len = min(reply_len, *length); 447 448 if (reply_len > 0) 449 memcpy(buffer, reply + 2, reply_len); 450 } 451 452 *length = reply_len; 453 454 kfree(reply); 455 kfree(msg); 456 457 return 0; 458 459 out_msg: 460 vmw_close_channel(&channel); 461 kfree(reply); 462 out_open: 463 *length = 0; 464 kfree(msg); 465 DRM_ERROR("Failed to get guest info \"%s\".", guest_info_param); 466 467 return -EINVAL; 468 } 469 470 471 472 /** 473 * vmw_host_log: Sends a log message to the host 474 * 475 * @log: NULL terminated string 476 * 477 * Returns: 0 on success 478 */ 479 int vmw_host_log(const char *log) 480 { 481 struct rpc_channel channel; 482 char *msg; 483 int ret = 0; 484 485 486 if (!vmw_msg_enabled) 487 return -ENODEV; 488 489 if (!log) 490 return ret; 491 492 msg = kasprintf(GFP_KERNEL, "log %s", log); 493 if (!msg) { 494 DRM_ERROR("Cannot allocate memory for host log message.\n"); 495 return -ENOMEM; 496 } 497 498 if (vmw_open_channel(&channel, RPCI_PROTOCOL_NUM)) 499 goto out_open; 500 501 if (vmw_send_msg(&channel, msg)) 502 goto out_msg; 503 504 vmw_close_channel(&channel); 505 kfree(msg); 506 507 return 0; 508 509 out_msg: 510 vmw_close_channel(&channel); 511 out_open: 512 kfree(msg); 513 DRM_ERROR("Failed to send host log message.\n"); 514 515 return -EINVAL; 516 } 517