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