| .. | .. |
|---|
| 7 | 7 | */ |
|---|
| 8 | 8 | |
|---|
| 9 | 9 | #include <linux/errno.h> |
|---|
| 10 | +#include <linux/io.h> |
|---|
| 10 | 11 | #include <linux/kernel.h> |
|---|
| 11 | 12 | #include <linux/mm.h> |
|---|
| 12 | 13 | #include <linux/module.h> |
|---|
| .. | .. |
|---|
| 58 | 59 | VBG_LOG(vbg_info, pr_info); |
|---|
| 59 | 60 | VBG_LOG(vbg_warn, pr_warn); |
|---|
| 60 | 61 | VBG_LOG(vbg_err, pr_err); |
|---|
| 62 | +VBG_LOG(vbg_err_ratelimited, pr_err_ratelimited); |
|---|
| 61 | 63 | #if defined(DEBUG) && !defined(CONFIG_DYNAMIC_DEBUG) |
|---|
| 62 | 64 | VBG_LOG(vbg_debug, pr_debug); |
|---|
| 63 | 65 | #endif |
|---|
| 64 | 66 | |
|---|
| 65 | | -void *vbg_req_alloc(size_t len, enum vmmdev_request_type req_type) |
|---|
| 67 | +void *vbg_req_alloc(size_t len, enum vmmdev_request_type req_type, |
|---|
| 68 | + u32 requestor) |
|---|
| 66 | 69 | { |
|---|
| 67 | 70 | struct vmmdev_request_header *req; |
|---|
| 68 | 71 | int order = get_order(PAGE_ALIGN(len)); |
|---|
| .. | .. |
|---|
| 78 | 81 | req->request_type = req_type; |
|---|
| 79 | 82 | req->rc = VERR_GENERAL_FAILURE; |
|---|
| 80 | 83 | req->reserved1 = 0; |
|---|
| 81 | | - req->reserved2 = 0; |
|---|
| 84 | + req->requestor = requestor; |
|---|
| 82 | 85 | |
|---|
| 83 | 86 | return req; |
|---|
| 84 | 87 | } |
|---|
| .. | .. |
|---|
| 119 | 122 | return done; |
|---|
| 120 | 123 | } |
|---|
| 121 | 124 | |
|---|
| 122 | | -int vbg_hgcm_connect(struct vbg_dev *gdev, |
|---|
| 125 | +int vbg_hgcm_connect(struct vbg_dev *gdev, u32 requestor, |
|---|
| 123 | 126 | struct vmmdev_hgcm_service_location *loc, |
|---|
| 124 | 127 | u32 *client_id, int *vbox_status) |
|---|
| 125 | 128 | { |
|---|
| .. | .. |
|---|
| 127 | 130 | int rc; |
|---|
| 128 | 131 | |
|---|
| 129 | 132 | hgcm_connect = vbg_req_alloc(sizeof(*hgcm_connect), |
|---|
| 130 | | - VMMDEVREQ_HGCM_CONNECT); |
|---|
| 133 | + VMMDEVREQ_HGCM_CONNECT, requestor); |
|---|
| 131 | 134 | if (!hgcm_connect) |
|---|
| 132 | 135 | return -ENOMEM; |
|---|
| 133 | 136 | |
|---|
| .. | .. |
|---|
| 153 | 156 | } |
|---|
| 154 | 157 | EXPORT_SYMBOL(vbg_hgcm_connect); |
|---|
| 155 | 158 | |
|---|
| 156 | | -int vbg_hgcm_disconnect(struct vbg_dev *gdev, u32 client_id, int *vbox_status) |
|---|
| 159 | +int vbg_hgcm_disconnect(struct vbg_dev *gdev, u32 requestor, |
|---|
| 160 | + u32 client_id, int *vbox_status) |
|---|
| 157 | 161 | { |
|---|
| 158 | 162 | struct vmmdev_hgcm_disconnect *hgcm_disconnect = NULL; |
|---|
| 159 | 163 | int rc; |
|---|
| 160 | 164 | |
|---|
| 161 | 165 | hgcm_disconnect = vbg_req_alloc(sizeof(*hgcm_disconnect), |
|---|
| 162 | | - VMMDEVREQ_HGCM_DISCONNECT); |
|---|
| 166 | + VMMDEVREQ_HGCM_DISCONNECT, |
|---|
| 167 | + requestor); |
|---|
| 163 | 168 | if (!hgcm_disconnect) |
|---|
| 164 | 169 | return -ENOMEM; |
|---|
| 165 | 170 | |
|---|
| .. | .. |
|---|
| 307 | 312 | switch (type) { |
|---|
| 308 | 313 | default: |
|---|
| 309 | 314 | WARN_ON(1); |
|---|
| 310 | | - /* Fall through */ |
|---|
| 315 | + fallthrough; |
|---|
| 311 | 316 | case VMMDEV_HGCM_PARM_TYPE_LINADDR: |
|---|
| 312 | 317 | case VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL: |
|---|
| 313 | 318 | return VMMDEV_HGCM_F_PARM_DIRECTION_BOTH; |
|---|
| .. | .. |
|---|
| 463 | 468 | * Cancellation fun. |
|---|
| 464 | 469 | */ |
|---|
| 465 | 470 | static int vbg_hgcm_do_call(struct vbg_dev *gdev, struct vmmdev_hgcm_call *call, |
|---|
| 466 | | - u32 timeout_ms, bool *leak_it) |
|---|
| 471 | + u32 timeout_ms, bool interruptible, bool *leak_it) |
|---|
| 467 | 472 | { |
|---|
| 468 | 473 | int rc, cancel_rc, ret; |
|---|
| 469 | 474 | long timeout; |
|---|
| .. | .. |
|---|
| 490 | 495 | else |
|---|
| 491 | 496 | timeout = msecs_to_jiffies(timeout_ms); |
|---|
| 492 | 497 | |
|---|
| 493 | | - timeout = wait_event_interruptible_timeout( |
|---|
| 494 | | - gdev->hgcm_wq, |
|---|
| 495 | | - hgcm_req_done(gdev, &call->header), |
|---|
| 496 | | - timeout); |
|---|
| 498 | + if (interruptible) { |
|---|
| 499 | + timeout = wait_event_interruptible_timeout(gdev->hgcm_wq, |
|---|
| 500 | + hgcm_req_done(gdev, &call->header), |
|---|
| 501 | + timeout); |
|---|
| 502 | + } else { |
|---|
| 503 | + timeout = wait_event_timeout(gdev->hgcm_wq, |
|---|
| 504 | + hgcm_req_done(gdev, &call->header), |
|---|
| 505 | + timeout); |
|---|
| 506 | + } |
|---|
| 497 | 507 | |
|---|
| 498 | 508 | /* timeout > 0 means hgcm_req_done has returned true, so success */ |
|---|
| 499 | 509 | if (timeout > 0) |
|---|
| .. | .. |
|---|
| 594 | 604 | return 0; |
|---|
| 595 | 605 | } |
|---|
| 596 | 606 | |
|---|
| 597 | | -int vbg_hgcm_call(struct vbg_dev *gdev, u32 client_id, u32 function, |
|---|
| 598 | | - u32 timeout_ms, struct vmmdev_hgcm_function_parameter *parms, |
|---|
| 599 | | - u32 parm_count, int *vbox_status) |
|---|
| 607 | +int vbg_hgcm_call(struct vbg_dev *gdev, u32 requestor, u32 client_id, |
|---|
| 608 | + u32 function, u32 timeout_ms, |
|---|
| 609 | + struct vmmdev_hgcm_function_parameter *parms, u32 parm_count, |
|---|
| 610 | + int *vbox_status) |
|---|
| 600 | 611 | { |
|---|
| 601 | 612 | struct vmmdev_hgcm_call *call; |
|---|
| 602 | 613 | void **bounce_bufs = NULL; |
|---|
| .. | .. |
|---|
| 616 | 627 | goto free_bounce_bufs; |
|---|
| 617 | 628 | } |
|---|
| 618 | 629 | |
|---|
| 619 | | - call = vbg_req_alloc(size, VMMDEVREQ_HGCM_CALL); |
|---|
| 630 | + call = vbg_req_alloc(size, VMMDEVREQ_HGCM_CALL, requestor); |
|---|
| 620 | 631 | if (!call) { |
|---|
| 621 | 632 | ret = -ENOMEM; |
|---|
| 622 | 633 | goto free_bounce_bufs; |
|---|
| .. | .. |
|---|
| 625 | 636 | hgcm_call_init_call(call, client_id, function, parms, parm_count, |
|---|
| 626 | 637 | bounce_bufs); |
|---|
| 627 | 638 | |
|---|
| 628 | | - ret = vbg_hgcm_do_call(gdev, call, timeout_ms, &leak_it); |
|---|
| 639 | + ret = vbg_hgcm_do_call(gdev, call, timeout_ms, |
|---|
| 640 | + requestor & VMMDEV_REQUESTOR_USERMODE, &leak_it); |
|---|
| 629 | 641 | if (ret == 0) { |
|---|
| 630 | 642 | *vbox_status = call->header.result; |
|---|
| 631 | 643 | ret = hgcm_call_copy_back_result(call, parms, parm_count, |
|---|
| .. | .. |
|---|
| 648 | 660 | |
|---|
| 649 | 661 | #ifdef CONFIG_COMPAT |
|---|
| 650 | 662 | int vbg_hgcm_call32( |
|---|
| 651 | | - struct vbg_dev *gdev, u32 client_id, u32 function, u32 timeout_ms, |
|---|
| 652 | | - struct vmmdev_hgcm_function_parameter32 *parm32, u32 parm_count, |
|---|
| 653 | | - int *vbox_status) |
|---|
| 663 | + struct vbg_dev *gdev, u32 requestor, u32 client_id, u32 function, |
|---|
| 664 | + u32 timeout_ms, struct vmmdev_hgcm_function_parameter32 *parm32, |
|---|
| 665 | + u32 parm_count, int *vbox_status) |
|---|
| 654 | 666 | { |
|---|
| 655 | 667 | struct vmmdev_hgcm_function_parameter *parm64 = NULL; |
|---|
| 656 | 668 | u32 i, size; |
|---|
| .. | .. |
|---|
| 690 | 702 | goto out_free; |
|---|
| 691 | 703 | } |
|---|
| 692 | 704 | |
|---|
| 693 | | - ret = vbg_hgcm_call(gdev, client_id, function, timeout_ms, |
|---|
| 705 | + ret = vbg_hgcm_call(gdev, requestor, client_id, function, timeout_ms, |
|---|
| 694 | 706 | parm64, parm_count, vbox_status); |
|---|
| 695 | 707 | if (ret < 0) |
|---|
| 696 | 708 | goto out_free; |
|---|