.. | .. |
---|
24 | 24 | * |
---|
25 | 25 | */ |
---|
26 | 26 | |
---|
27 | | - |
---|
28 | | -#include <linux/slab.h> |
---|
29 | | -#include <linux/module.h> |
---|
| 27 | +#include <linux/objtool.h> |
---|
30 | 28 | #include <linux/kernel.h> |
---|
31 | | -#include <linux/frame.h> |
---|
| 29 | +#include <linux/module.h> |
---|
| 30 | +#include <linux/slab.h> |
---|
| 31 | +#include <linux/mem_encrypt.h> |
---|
| 32 | + |
---|
32 | 33 | #include <asm/hypervisor.h> |
---|
33 | | -#include <drm/drmP.h> |
---|
| 34 | + |
---|
34 | 35 | #include "vmwgfx_drv.h" |
---|
35 | 36 | #include "vmwgfx_msg.h" |
---|
36 | | - |
---|
37 | 37 | |
---|
38 | 38 | #define MESSAGE_STATUS_SUCCESS 0x0001 |
---|
39 | 39 | #define MESSAGE_STATUS_DORECV 0x0002 |
---|
.. | .. |
---|
46 | 46 | #define RETRIES 3 |
---|
47 | 47 | |
---|
48 | 48 | #define VMW_HYPERVISOR_MAGIC 0x564D5868 |
---|
49 | | -#define VMW_HYPERVISOR_PORT 0x5658 |
---|
50 | | -#define VMW_HYPERVISOR_HB_PORT 0x5659 |
---|
51 | 49 | |
---|
52 | 50 | #define VMW_PORT_CMD_MSG 30 |
---|
53 | 51 | #define VMW_PORT_CMD_HB_MSG 0 |
---|
.. | .. |
---|
58 | 56 | #define VMW_PORT_CMD_RECVSTATUS (MSG_TYPE_RECVSTATUS << 16 | VMW_PORT_CMD_MSG) |
---|
59 | 57 | |
---|
60 | 58 | #define HIGH_WORD(X) ((X & 0xFFFF0000) >> 16) |
---|
| 59 | + |
---|
| 60 | +#define MAX_USER_MSG_LENGTH PAGE_SIZE |
---|
61 | 61 | |
---|
62 | 62 | static u32 vmw_msg_enabled = 1; |
---|
63 | 63 | |
---|
.. | .. |
---|
93 | 93 | |
---|
94 | 94 | VMW_PORT(VMW_PORT_CMD_OPEN_CHANNEL, |
---|
95 | 95 | (protocol | GUESTMSG_FLAG_COOKIE), si, di, |
---|
96 | | - VMW_HYPERVISOR_PORT, |
---|
| 96 | + 0, |
---|
97 | 97 | VMW_HYPERVISOR_MAGIC, |
---|
98 | 98 | eax, ebx, ecx, edx, si, di); |
---|
99 | 99 | |
---|
.. | .. |
---|
126 | 126 | |
---|
127 | 127 | VMW_PORT(VMW_PORT_CMD_CLOSE_CHANNEL, |
---|
128 | 128 | 0, si, di, |
---|
129 | | - (VMW_HYPERVISOR_PORT | (channel->channel_id << 16)), |
---|
| 129 | + channel->channel_id << 16, |
---|
130 | 130 | VMW_HYPERVISOR_MAGIC, |
---|
131 | 131 | eax, ebx, ecx, edx, si, di); |
---|
132 | 132 | |
---|
.. | .. |
---|
151 | 151 | unsigned long si, di, eax, ebx, ecx, edx; |
---|
152 | 152 | unsigned long msg_len = strlen(msg); |
---|
153 | 153 | |
---|
154 | | - if (hb) { |
---|
| 154 | + /* HB port can't access encrypted memory. */ |
---|
| 155 | + if (hb && !mem_encrypt_active()) { |
---|
155 | 156 | unsigned long bp = channel->cookie_high; |
---|
156 | 157 | |
---|
157 | 158 | si = (uintptr_t) msg; |
---|
.. | .. |
---|
160 | 161 | VMW_PORT_HB_OUT( |
---|
161 | 162 | (MESSAGE_STATUS_SUCCESS << 16) | VMW_PORT_CMD_HB_MSG, |
---|
162 | 163 | msg_len, si, di, |
---|
163 | | - VMW_HYPERVISOR_HB_PORT | (channel->channel_id << 16), |
---|
| 164 | + VMWARE_HYPERVISOR_HB | (channel->channel_id << 16) | |
---|
| 165 | + VMWARE_HYPERVISOR_OUT, |
---|
164 | 166 | VMW_HYPERVISOR_MAGIC, bp, |
---|
165 | 167 | eax, ebx, ecx, edx, si, di); |
---|
166 | 168 | |
---|
.. | .. |
---|
181 | 183 | |
---|
182 | 184 | VMW_PORT(VMW_PORT_CMD_MSG | (MSG_TYPE_SENDPAYLOAD << 16), |
---|
183 | 185 | word, si, di, |
---|
184 | | - VMW_HYPERVISOR_PORT | (channel->channel_id << 16), |
---|
| 186 | + channel->channel_id << 16, |
---|
185 | 187 | VMW_HYPERVISOR_MAGIC, |
---|
186 | 188 | eax, ebx, ecx, edx, si, di); |
---|
187 | 189 | } |
---|
.. | .. |
---|
204 | 206 | { |
---|
205 | 207 | unsigned long si, di, eax, ebx, ecx, edx; |
---|
206 | 208 | |
---|
207 | | - if (hb) { |
---|
| 209 | + /* HB port can't access encrypted memory */ |
---|
| 210 | + if (hb && !mem_encrypt_active()) { |
---|
208 | 211 | unsigned long bp = channel->cookie_low; |
---|
209 | 212 | |
---|
210 | 213 | si = channel->cookie_high; |
---|
.. | .. |
---|
213 | 216 | VMW_PORT_HB_IN( |
---|
214 | 217 | (MESSAGE_STATUS_SUCCESS << 16) | VMW_PORT_CMD_HB_MSG, |
---|
215 | 218 | reply_len, si, di, |
---|
216 | | - VMW_HYPERVISOR_HB_PORT | (channel->channel_id << 16), |
---|
| 219 | + VMWARE_HYPERVISOR_HB | (channel->channel_id << 16), |
---|
217 | 220 | VMW_HYPERVISOR_MAGIC, bp, |
---|
218 | 221 | eax, ebx, ecx, edx, si, di); |
---|
219 | 222 | |
---|
.. | .. |
---|
230 | 233 | |
---|
231 | 234 | VMW_PORT(VMW_PORT_CMD_MSG | (MSG_TYPE_RECVPAYLOAD << 16), |
---|
232 | 235 | MESSAGE_STATUS_SUCCESS, si, di, |
---|
233 | | - VMW_HYPERVISOR_PORT | (channel->channel_id << 16), |
---|
| 236 | + channel->channel_id << 16, |
---|
234 | 237 | VMW_HYPERVISOR_MAGIC, |
---|
235 | 238 | eax, ebx, ecx, edx, si, di); |
---|
236 | 239 | |
---|
.. | .. |
---|
269 | 272 | |
---|
270 | 273 | VMW_PORT(VMW_PORT_CMD_SENDSIZE, |
---|
271 | 274 | msg_len, si, di, |
---|
272 | | - VMW_HYPERVISOR_PORT | (channel->channel_id << 16), |
---|
| 275 | + channel->channel_id << 16, |
---|
273 | 276 | VMW_HYPERVISOR_MAGIC, |
---|
274 | 277 | eax, ebx, ecx, edx, si, di); |
---|
275 | 278 | |
---|
.. | .. |
---|
327 | 330 | |
---|
328 | 331 | VMW_PORT(VMW_PORT_CMD_RECVSIZE, |
---|
329 | 332 | 0, si, di, |
---|
330 | | - (VMW_HYPERVISOR_PORT | (channel->channel_id << 16)), |
---|
| 333 | + channel->channel_id << 16, |
---|
331 | 334 | VMW_HYPERVISOR_MAGIC, |
---|
332 | 335 | eax, ebx, ecx, edx, si, di); |
---|
333 | 336 | |
---|
.. | .. |
---|
371 | 374 | |
---|
372 | 375 | VMW_PORT(VMW_PORT_CMD_RECVSTATUS, |
---|
373 | 376 | MESSAGE_STATUS_SUCCESS, si, di, |
---|
374 | | - (VMW_HYPERVISOR_PORT | (channel->channel_id << 16)), |
---|
| 377 | + channel->channel_id << 16, |
---|
375 | 378 | VMW_HYPERVISOR_MAGIC, |
---|
376 | 379 | eax, ebx, ecx, edx, si, di); |
---|
377 | 380 | |
---|
.. | .. |
---|
516 | 519 | |
---|
517 | 520 | return -EINVAL; |
---|
518 | 521 | } |
---|
| 522 | + |
---|
| 523 | + |
---|
| 524 | +/** |
---|
| 525 | + * vmw_msg_ioctl: Sends and receveives a message to/from host from/to user-space |
---|
| 526 | + * |
---|
| 527 | + * Sends a message from user-space to host. |
---|
| 528 | + * Can also receive a result from host and return that to user-space. |
---|
| 529 | + * |
---|
| 530 | + * @dev: Identifies the drm device. |
---|
| 531 | + * @data: Pointer to the ioctl argument. |
---|
| 532 | + * @file_priv: Identifies the caller. |
---|
| 533 | + * Return: Zero on success, negative error code on error. |
---|
| 534 | + */ |
---|
| 535 | + |
---|
| 536 | +int vmw_msg_ioctl(struct drm_device *dev, void *data, |
---|
| 537 | + struct drm_file *file_priv) |
---|
| 538 | +{ |
---|
| 539 | + struct drm_vmw_msg_arg *arg = |
---|
| 540 | + (struct drm_vmw_msg_arg *) data; |
---|
| 541 | + struct rpc_channel channel; |
---|
| 542 | + char *msg; |
---|
| 543 | + int length; |
---|
| 544 | + |
---|
| 545 | + msg = kmalloc(MAX_USER_MSG_LENGTH, GFP_KERNEL); |
---|
| 546 | + if (!msg) { |
---|
| 547 | + DRM_ERROR("Cannot allocate memory for log message.\n"); |
---|
| 548 | + return -ENOMEM; |
---|
| 549 | + } |
---|
| 550 | + |
---|
| 551 | + length = strncpy_from_user(msg, (void __user *)((unsigned long)arg->send), |
---|
| 552 | + MAX_USER_MSG_LENGTH); |
---|
| 553 | + if (length < 0 || length >= MAX_USER_MSG_LENGTH) { |
---|
| 554 | + DRM_ERROR("Userspace message access failure.\n"); |
---|
| 555 | + kfree(msg); |
---|
| 556 | + return -EINVAL; |
---|
| 557 | + } |
---|
| 558 | + |
---|
| 559 | + |
---|
| 560 | + if (vmw_open_channel(&channel, RPCI_PROTOCOL_NUM)) { |
---|
| 561 | + DRM_ERROR("Failed to open channel.\n"); |
---|
| 562 | + goto out_open; |
---|
| 563 | + } |
---|
| 564 | + |
---|
| 565 | + if (vmw_send_msg(&channel, msg)) { |
---|
| 566 | + DRM_ERROR("Failed to send message to host.\n"); |
---|
| 567 | + goto out_msg; |
---|
| 568 | + } |
---|
| 569 | + |
---|
| 570 | + if (!arg->send_only) { |
---|
| 571 | + char *reply = NULL; |
---|
| 572 | + size_t reply_len = 0; |
---|
| 573 | + |
---|
| 574 | + if (vmw_recv_msg(&channel, (void *) &reply, &reply_len)) { |
---|
| 575 | + DRM_ERROR("Failed to receive message from host.\n"); |
---|
| 576 | + goto out_msg; |
---|
| 577 | + } |
---|
| 578 | + if (reply && reply_len > 0) { |
---|
| 579 | + if (copy_to_user((void __user *)((unsigned long)arg->receive), |
---|
| 580 | + reply, reply_len)) { |
---|
| 581 | + DRM_ERROR("Failed to copy message to userspace.\n"); |
---|
| 582 | + kfree(reply); |
---|
| 583 | + goto out_msg; |
---|
| 584 | + } |
---|
| 585 | + arg->receive_len = (__u32)reply_len; |
---|
| 586 | + } |
---|
| 587 | + kfree(reply); |
---|
| 588 | + } |
---|
| 589 | + |
---|
| 590 | + vmw_close_channel(&channel); |
---|
| 591 | + kfree(msg); |
---|
| 592 | + |
---|
| 593 | + return 0; |
---|
| 594 | + |
---|
| 595 | +out_msg: |
---|
| 596 | + vmw_close_channel(&channel); |
---|
| 597 | +out_open: |
---|
| 598 | + kfree(msg); |
---|
| 599 | + |
---|
| 600 | + return -EINVAL; |
---|
| 601 | +} |
---|