1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright 2021 Microsoft 4 */ 5 6 #include <linux/hyperv.h> 7 8 #include <drm/drm_print.h> 9 #include <drm/drm_simple_kms_helper.h> 10 11 #include "hyperv_drm.h" 12 13 #define VMBUS_RING_BUFSIZE VMBUS_RING_SIZE(256 * 1024) 14 #define VMBUS_VSP_TIMEOUT (10 * HZ) 15 16 #define SYNTHVID_VERSION(major, minor) ((minor) << 16 | (major)) 17 #define SYNTHVID_VER_GET_MAJOR(ver) (ver & 0x0000ffff) 18 #define SYNTHVID_VER_GET_MINOR(ver) ((ver & 0xffff0000) >> 16) 19 20 /* Support for WIN7 and WIN8 is removed. #define's retained for reference. */ 21 #define SYNTHVID_VERSION_WIN7 SYNTHVID_VERSION(3, 0) 22 #define SYNTHVID_VERSION_WIN8 SYNTHVID_VERSION(3, 2) 23 #define SYNTHVID_VERSION_WIN10 SYNTHVID_VERSION(3, 5) 24 25 #define SYNTHVID_DEPTH_WIN8 32 26 #define SYNTHVID_WIDTH_WIN8 1600 27 #define SYNTHVID_HEIGHT_WIN8 1200 28 #define SYNTHVID_FB_SIZE_WIN8 (8 * 1024 * 1024) 29 30 enum pipe_msg_type { 31 PIPE_MSG_INVALID, 32 PIPE_MSG_DATA, 33 PIPE_MSG_MAX 34 }; 35 36 enum synthvid_msg_type { 37 SYNTHVID_ERROR = 0, 38 SYNTHVID_VERSION_REQUEST = 1, 39 SYNTHVID_VERSION_RESPONSE = 2, 40 SYNTHVID_VRAM_LOCATION = 3, 41 SYNTHVID_VRAM_LOCATION_ACK = 4, 42 SYNTHVID_SITUATION_UPDATE = 5, 43 SYNTHVID_SITUATION_UPDATE_ACK = 6, 44 SYNTHVID_POINTER_POSITION = 7, 45 SYNTHVID_POINTER_SHAPE = 8, 46 SYNTHVID_FEATURE_CHANGE = 9, 47 SYNTHVID_DIRT = 10, 48 SYNTHVID_RESOLUTION_REQUEST = 13, 49 SYNTHVID_RESOLUTION_RESPONSE = 14, 50 51 SYNTHVID_MAX = 15 52 }; 53 54 struct pipe_msg_hdr { 55 u32 type; 56 u32 size; /* size of message after this field */ 57 } __packed; 58 59 struct hvd_screen_info { 60 u16 width; 61 u16 height; 62 } __packed; 63 64 struct synthvid_msg_hdr { 65 u32 type; 66 u32 size; /* size of this header + payload after this field */ 67 } __packed; 68 69 struct synthvid_version_req { 70 u32 version; 71 } __packed; 72 73 struct synthvid_version_resp { 74 u32 version; 75 u8 is_accepted; 76 u8 max_video_outputs; 77 } __packed; 78 79 struct synthvid_vram_location { 80 u64 user_ctx; 81 u8 is_vram_gpa_specified; 82 u64 vram_gpa; 83 } __packed; 84 85 struct synthvid_vram_location_ack { 86 u64 user_ctx; 87 } __packed; 88 89 struct video_output_situation { 90 u8 active; 91 u32 vram_offset; 92 u8 depth_bits; 93 u32 width_pixels; 94 u32 height_pixels; 95 u32 pitch_bytes; 96 } __packed; 97 98 struct synthvid_situation_update { 99 u64 user_ctx; 100 u8 video_output_count; 101 struct video_output_situation video_output[1]; 102 } __packed; 103 104 struct synthvid_situation_update_ack { 105 u64 user_ctx; 106 } __packed; 107 108 struct synthvid_pointer_position { 109 u8 is_visible; 110 u8 video_output; 111 s32 image_x; 112 s32 image_y; 113 } __packed; 114 115 #define SYNTHVID_CURSOR_MAX_X 96 116 #define SYNTHVID_CURSOR_MAX_Y 96 117 #define SYNTHVID_CURSOR_ARGB_PIXEL_SIZE 4 118 #define SYNTHVID_CURSOR_MAX_SIZE (SYNTHVID_CURSOR_MAX_X * \ 119 SYNTHVID_CURSOR_MAX_Y * SYNTHVID_CURSOR_ARGB_PIXEL_SIZE) 120 #define SYNTHVID_CURSOR_COMPLETE (-1) 121 122 struct synthvid_pointer_shape { 123 u8 part_idx; 124 u8 is_argb; 125 u32 width; /* SYNTHVID_CURSOR_MAX_X at most */ 126 u32 height; /* SYNTHVID_CURSOR_MAX_Y at most */ 127 u32 hot_x; /* hotspot relative to upper-left of pointer image */ 128 u32 hot_y; 129 u8 data[4]; 130 } __packed; 131 132 struct synthvid_feature_change { 133 u8 is_dirt_needed; 134 u8 is_ptr_pos_needed; 135 u8 is_ptr_shape_needed; 136 u8 is_situ_needed; 137 } __packed; 138 139 struct rect { 140 s32 x1, y1; /* top left corner */ 141 s32 x2, y2; /* bottom right corner, exclusive */ 142 } __packed; 143 144 struct synthvid_dirt { 145 u8 video_output; 146 u8 dirt_count; 147 struct rect rect[1]; 148 } __packed; 149 150 #define SYNTHVID_EDID_BLOCK_SIZE 128 151 #define SYNTHVID_MAX_RESOLUTION_COUNT 64 152 153 struct synthvid_supported_resolution_req { 154 u8 maximum_resolution_count; 155 } __packed; 156 157 struct synthvid_supported_resolution_resp { 158 u8 edid_block[SYNTHVID_EDID_BLOCK_SIZE]; 159 u8 resolution_count; 160 u8 default_resolution_index; 161 u8 is_standard; 162 struct hvd_screen_info supported_resolution[SYNTHVID_MAX_RESOLUTION_COUNT]; 163 } __packed; 164 165 struct synthvid_msg { 166 struct pipe_msg_hdr pipe_hdr; 167 struct synthvid_msg_hdr vid_hdr; 168 union { 169 struct synthvid_version_req ver_req; 170 struct synthvid_version_resp ver_resp; 171 struct synthvid_vram_location vram; 172 struct synthvid_vram_location_ack vram_ack; 173 struct synthvid_situation_update situ; 174 struct synthvid_situation_update_ack situ_ack; 175 struct synthvid_pointer_position ptr_pos; 176 struct synthvid_pointer_shape ptr_shape; 177 struct synthvid_feature_change feature_chg; 178 struct synthvid_dirt dirt; 179 struct synthvid_supported_resolution_req resolution_req; 180 struct synthvid_supported_resolution_resp resolution_resp; 181 }; 182 } __packed; 183 184 static inline int hv_drm_sendpacket(struct hv_device *hdev, struct synthvid_msg *msg) 185 { 186 static atomic64_t request_id = ATOMIC64_INIT(0); 187 struct hv_drm_device *hv = hv_get_drvdata(hdev); 188 int ret; 189 190 msg->pipe_hdr.type = PIPE_MSG_DATA; 191 msg->pipe_hdr.size = msg->vid_hdr.size; 192 193 ret = vmbus_sendpacket(hdev->channel, msg, 194 msg->vid_hdr.size + sizeof(struct pipe_msg_hdr), 195 atomic64_inc_return(&request_id), 196 VM_PKT_DATA_INBAND, 0); 197 198 if (ret) 199 drm_err_ratelimited(&hv->dev, "Unable to send packet via vmbus; error %d\n", ret); 200 201 return ret; 202 } 203 204 static int hv_drm_negotiate_version(struct hv_device *hdev, u32 ver) 205 { 206 struct hv_drm_device *hv = hv_get_drvdata(hdev); 207 struct synthvid_msg *msg = (struct synthvid_msg *)hv->init_buf; 208 struct drm_device *dev = &hv->dev; 209 unsigned long t; 210 211 memset(msg, 0, sizeof(struct synthvid_msg)); 212 msg->vid_hdr.type = SYNTHVID_VERSION_REQUEST; 213 msg->vid_hdr.size = sizeof(struct synthvid_msg_hdr) + 214 sizeof(struct synthvid_version_req); 215 msg->ver_req.version = ver; 216 hv_drm_sendpacket(hdev, msg); 217 218 t = wait_for_completion_timeout(&hv->wait, VMBUS_VSP_TIMEOUT); 219 if (!t) { 220 drm_err(dev, "Time out on waiting version response\n"); 221 return -ETIMEDOUT; 222 } 223 224 if (!msg->ver_resp.is_accepted) { 225 drm_err(dev, "Version request not accepted\n"); 226 return -ENODEV; 227 } 228 229 drm_info(dev, "Synthvid Version major %d, minor %d\n", 230 SYNTHVID_VER_GET_MAJOR(ver), SYNTHVID_VER_GET_MINOR(ver)); 231 232 return 0; 233 } 234 235 int hv_drm_update_vram_location(struct hv_device *hdev, phys_addr_t vram_pp) 236 { 237 struct hv_drm_device *hv = hv_get_drvdata(hdev); 238 struct synthvid_msg *msg = (struct synthvid_msg *)hv->init_buf; 239 struct drm_device *dev = &hv->dev; 240 unsigned long t; 241 242 memset(msg, 0, sizeof(struct synthvid_msg)); 243 msg->vid_hdr.type = SYNTHVID_VRAM_LOCATION; 244 msg->vid_hdr.size = sizeof(struct synthvid_msg_hdr) + 245 sizeof(struct synthvid_vram_location); 246 msg->vram.user_ctx = vram_pp; 247 msg->vram.vram_gpa = vram_pp; 248 msg->vram.is_vram_gpa_specified = 1; 249 hv_drm_sendpacket(hdev, msg); 250 251 t = wait_for_completion_timeout(&hv->wait, VMBUS_VSP_TIMEOUT); 252 if (!t) { 253 drm_err(dev, "Time out on waiting vram location ack\n"); 254 return -ETIMEDOUT; 255 } 256 if (msg->vram_ack.user_ctx != vram_pp) { 257 drm_err(dev, "Unable to set VRAM location\n"); 258 return -ENODEV; 259 } 260 261 return 0; 262 } 263 264 int hv_drm_update_situation(struct hv_device *hdev, u8 active, u32 bpp, 265 u32 w, u32 h, u32 pitch) 266 { 267 struct synthvid_msg msg; 268 269 memset(&msg, 0, sizeof(struct synthvid_msg)); 270 271 msg.vid_hdr.type = SYNTHVID_SITUATION_UPDATE; 272 msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) + 273 sizeof(struct synthvid_situation_update); 274 msg.situ.user_ctx = 0; 275 msg.situ.video_output_count = 1; 276 msg.situ.video_output[0].active = active; 277 /* vram_offset should always be 0 */ 278 msg.situ.video_output[0].vram_offset = 0; 279 msg.situ.video_output[0].depth_bits = bpp; 280 msg.situ.video_output[0].width_pixels = w; 281 msg.situ.video_output[0].height_pixels = h; 282 msg.situ.video_output[0].pitch_bytes = pitch; 283 284 hv_drm_sendpacket(hdev, &msg); 285 286 return 0; 287 } 288 289 /* 290 * Hyper-V supports a hardware cursor feature. It's not used by Linux VM, 291 * but the Hyper-V host still draws a point as an extra mouse pointer, 292 * which is unwanted, especially when Xorg is running. 293 * 294 * Hide the unwanted pointer, by setting msg.ptr_pos.is_visible = 1 and setting 295 * the msg.ptr_shape.data. Note: setting msg.ptr_pos.is_visible to 0 doesn't 296 * work in tests. 297 * 298 * The hv_drm_hide_hw_ptr() is also called in the handler of the 299 * SYNTHVID_FEATURE_CHANGE event, otherwise the host still draws an extra 300 * unwanted mouse pointer after the VM Connection window is closed and reopened. 301 */ 302 int hv_drm_hide_hw_ptr(struct hv_device *hdev) 303 { 304 struct synthvid_msg msg; 305 306 memset(&msg, 0, sizeof(struct synthvid_msg)); 307 msg.vid_hdr.type = SYNTHVID_POINTER_POSITION; 308 msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) + 309 sizeof(struct synthvid_pointer_position); 310 msg.ptr_pos.is_visible = 1; 311 msg.ptr_pos.video_output = 0; 312 msg.ptr_pos.image_x = 0; 313 msg.ptr_pos.image_y = 0; 314 hv_drm_sendpacket(hdev, &msg); 315 316 memset(&msg, 0, sizeof(struct synthvid_msg)); 317 msg.vid_hdr.type = SYNTHVID_POINTER_SHAPE; 318 msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) + 319 sizeof(struct synthvid_pointer_shape); 320 msg.ptr_shape.part_idx = SYNTHVID_CURSOR_COMPLETE; 321 msg.ptr_shape.is_argb = 1; 322 msg.ptr_shape.width = 1; 323 msg.ptr_shape.height = 1; 324 msg.ptr_shape.hot_x = 0; 325 msg.ptr_shape.hot_y = 0; 326 msg.ptr_shape.data[0] = 0; 327 msg.ptr_shape.data[1] = 1; 328 msg.ptr_shape.data[2] = 1; 329 msg.ptr_shape.data[3] = 1; 330 hv_drm_sendpacket(hdev, &msg); 331 332 return 0; 333 } 334 335 int hv_drm_update_dirt(struct hv_device *hdev, struct drm_rect *rect) 336 { 337 struct hv_drm_device *hv = hv_get_drvdata(hdev); 338 struct synthvid_msg msg; 339 340 if (!hv->dirt_needed) 341 return 0; 342 343 memset(&msg, 0, sizeof(struct synthvid_msg)); 344 345 msg.vid_hdr.type = SYNTHVID_DIRT; 346 msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) + 347 sizeof(struct synthvid_dirt); 348 msg.dirt.video_output = 0; 349 msg.dirt.dirt_count = 1; 350 msg.dirt.rect[0].x1 = rect->x1; 351 msg.dirt.rect[0].y1 = rect->y1; 352 msg.dirt.rect[0].x2 = rect->x2; 353 msg.dirt.rect[0].y2 = rect->y2; 354 355 hv_drm_sendpacket(hdev, &msg); 356 357 return 0; 358 } 359 360 static int hv_drm_get_supported_resolution(struct hv_device *hdev) 361 { 362 struct hv_drm_device *hv = hv_get_drvdata(hdev); 363 struct synthvid_msg *msg = (struct synthvid_msg *)hv->init_buf; 364 struct drm_device *dev = &hv->dev; 365 unsigned long t; 366 u8 index; 367 int i; 368 369 memset(msg, 0, sizeof(struct synthvid_msg)); 370 msg->vid_hdr.type = SYNTHVID_RESOLUTION_REQUEST; 371 msg->vid_hdr.size = sizeof(struct synthvid_msg_hdr) + 372 sizeof(struct synthvid_supported_resolution_req); 373 msg->resolution_req.maximum_resolution_count = 374 SYNTHVID_MAX_RESOLUTION_COUNT; 375 hv_drm_sendpacket(hdev, msg); 376 377 t = wait_for_completion_timeout(&hv->wait, VMBUS_VSP_TIMEOUT); 378 if (!t) { 379 drm_err(dev, "Time out on waiting resolution response\n"); 380 return -ETIMEDOUT; 381 } 382 383 if (msg->resolution_resp.resolution_count == 0 || 384 msg->resolution_resp.resolution_count > 385 SYNTHVID_MAX_RESOLUTION_COUNT) { 386 drm_err(dev, "Invalid resolution count: %d\n", 387 msg->resolution_resp.resolution_count); 388 return -ENODEV; 389 } 390 391 index = msg->resolution_resp.default_resolution_index; 392 if (index >= msg->resolution_resp.resolution_count) { 393 drm_err(dev, "Invalid resolution index: %d\n", index); 394 return -ENODEV; 395 } 396 397 for (i = 0; i < msg->resolution_resp.resolution_count; i++) { 398 hv->screen_width_max = max_t(u32, hv->screen_width_max, 399 msg->resolution_resp.supported_resolution[i].width); 400 hv->screen_height_max = max_t(u32, hv->screen_height_max, 401 msg->resolution_resp.supported_resolution[i].height); 402 } 403 404 hv->preferred_width = 405 msg->resolution_resp.supported_resolution[index].width; 406 hv->preferred_height = 407 msg->resolution_resp.supported_resolution[index].height; 408 409 return 0; 410 } 411 412 static void hv_drm_receive_sub(struct hv_device *hdev, u32 bytes_recvd) 413 { 414 struct hv_drm_device *hv = hv_get_drvdata(hdev); 415 struct synthvid_msg *msg; 416 size_t hdr_size; 417 size_t need; 418 419 if (!hv) 420 return; 421 422 hdr_size = sizeof(struct pipe_msg_hdr) + 423 sizeof(struct synthvid_msg_hdr); 424 if (bytes_recvd < hdr_size) { 425 drm_err_ratelimited(&hv->dev, 426 "synthvid packet too small for header: %u\n", 427 bytes_recvd); 428 return; 429 } 430 431 msg = (struct synthvid_msg *)hv->recv_buf; 432 need = hdr_size; 433 434 switch (msg->vid_hdr.type) { 435 case SYNTHVID_VERSION_RESPONSE: 436 need += sizeof(struct synthvid_version_resp); 437 break; 438 case SYNTHVID_RESOLUTION_RESPONSE: 439 /* 440 * The resolution response is variable length: the host 441 * fills resolution_count entries, not the full 442 * SYNTHVID_MAX_RESOLUTION_COUNT array. Require the fixed 443 * prefix first so resolution_count can be read, then 444 * demand exactly the count-sized array. 445 */ 446 need += offsetof(struct synthvid_supported_resolution_resp, 447 supported_resolution); 448 if (bytes_recvd < need) 449 break; 450 if (msg->resolution_resp.resolution_count > 451 SYNTHVID_MAX_RESOLUTION_COUNT) { 452 drm_err_ratelimited(&hv->dev, 453 "synthvid resolution count too large: %u\n", 454 msg->resolution_resp.resolution_count); 455 return; 456 } 457 need += msg->resolution_resp.resolution_count * 458 sizeof(struct hvd_screen_info); 459 break; 460 case SYNTHVID_VRAM_LOCATION_ACK: 461 need += sizeof(struct synthvid_vram_location_ack); 462 break; 463 case SYNTHVID_FEATURE_CHANGE: 464 /* 465 * Not a completion-driving message: validate its own payload 466 * and consume it here rather than falling through to the 467 * memcpy/complete shared by the wait-event responses. 468 */ 469 if (bytes_recvd < need + 470 sizeof(struct synthvid_feature_change)) { 471 drm_err_ratelimited(&hv->dev, 472 "synthvid feature change packet too small: %u\n", 473 bytes_recvd); 474 return; 475 } 476 hv->dirt_needed = msg->feature_chg.is_dirt_needed; 477 if (hv->dirt_needed) 478 hv_drm_hide_hw_ptr(hv->hdev); 479 return; 480 default: 481 return; 482 } 483 484 /* 485 * Shared completion path for the wait-event responses 486 * (VERSION_RESPONSE, RESOLUTION_RESPONSE, VRAM_LOCATION_ACK): 487 * require the type-specific payload before handing the buffer to 488 * the waiter. 489 */ 490 if (bytes_recvd < need) { 491 drm_err_ratelimited(&hv->dev, 492 "synthvid packet too small for type %u: %u < %zu\n", 493 msg->vid_hdr.type, bytes_recvd, need); 494 return; 495 } 496 memcpy(hv->init_buf, msg, bytes_recvd); 497 complete(&hv->wait); 498 } 499 500 static void hv_drm_receive(void *ctx) 501 { 502 struct hv_device *hdev = ctx; 503 struct hv_drm_device *hv = hv_get_drvdata(hdev); 504 struct synthvid_msg *recv_buf; 505 u32 bytes_recvd; 506 u64 req_id; 507 int ret; 508 509 if (!hv) 510 return; 511 512 recv_buf = (struct synthvid_msg *)hv->recv_buf; 513 514 do { 515 ret = vmbus_recvpacket(hdev->channel, recv_buf, 516 VMBUS_MAX_PACKET_SIZE, 517 &bytes_recvd, &req_id); 518 if (ret) { 519 /* 520 * A nonzero return (e.g. -ENOBUFS for an oversized 521 * packet) is itself a malformed message: bytes_recvd 522 * then reports the required length rather than a copied 523 * payload, so it must not be forwarded to the 524 * sub-handler. Channel recovery is not attempted. 525 */ 526 drm_err_ratelimited(&hv->dev, 527 "vmbus_recvpacket failed: %d (need %u)\n", 528 ret, bytes_recvd); 529 } else if (bytes_recvd > 0 && 530 recv_buf->pipe_hdr.type == PIPE_MSG_DATA) { 531 hv_drm_receive_sub(hdev, bytes_recvd); 532 } 533 } while (bytes_recvd > 0 && ret == 0); 534 } 535 536 int hv_drm_connect_vsp(struct hv_device *hdev) 537 { 538 struct hv_drm_device *hv = hv_get_drvdata(hdev); 539 struct drm_device *dev = &hv->dev; 540 int ret; 541 542 ret = vmbus_open(hdev->channel, VMBUS_RING_BUFSIZE, VMBUS_RING_BUFSIZE, 543 NULL, 0, hv_drm_receive, hdev); 544 if (ret) { 545 drm_err(dev, "Unable to open vmbus channel\n"); 546 return ret; 547 } 548 549 /* 550 * Negotiate the protocol version with host. Since support for hosts 551 * older than WIN10 has been removed from Linux, only negotiate the 552 * WIN10 version. 553 */ 554 ret = hv_drm_negotiate_version(hdev, SYNTHVID_VERSION_WIN10); 555 if (ret) { 556 drm_err(dev, "Synthetic video device version not accepted %d\n", ret); 557 goto error; 558 } 559 560 hv->screen_depth = SYNTHVID_DEPTH_WIN8; 561 562 ret = hv_drm_get_supported_resolution(hdev); 563 if (ret) 564 drm_err(dev, "Failed to get supported resolution from host, use default\n"); 565 566 if (!hv->screen_width_max) { 567 hv->screen_width_max = SYNTHVID_WIDTH_WIN8; 568 hv->screen_height_max = SYNTHVID_HEIGHT_WIN8; 569 hv->preferred_width = SYNTHVID_WIDTH_WIN8; 570 hv->preferred_height = SYNTHVID_HEIGHT_WIN8; 571 } 572 573 hv->mmio_megabytes = hdev->channel->offermsg.offer.mmio_megabytes; 574 575 return 0; 576 577 error: 578 vmbus_close(hdev->channel); 579 return ret; 580 } 581