Lines Matching +full:single +full:- +full:channel

1 // SPDX-License-Identifier: GPL-2.0 OR MIT
19 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
100 * @channel: RPC channel
105 static int vmw_open_channel(struct rpc_channel *channel, unsigned int protocol) in vmw_open_channel() argument
116 return -EINVAL; in vmw_open_channel()
118 channel->channel_id = HIGH_WORD(edx); in vmw_open_channel()
119 channel->cookie_high = si; in vmw_open_channel()
120 channel->cookie_low = di; in vmw_open_channel()
130 * @channel: RPC channel
134 static int vmw_close_channel(struct rpc_channel *channel) in vmw_close_channel() argument
139 si = channel->cookie_high; in vmw_close_channel()
140 di = channel->cookie_low; in vmw_close_channel()
144 channel->channel_id << 16, in vmw_close_channel()
149 return -EINVAL; in vmw_close_channel()
155 * vmw_port_hb_out - Send the message payload either through the
156 * high-bandwidth port if available, or through the backdoor otherwise.
157 * @channel: The rpc channel.
158 * @msg: NULL-terminated message.
159 * @hb: Whether the high-bandwidth port is available.
163 static unsigned long vmw_port_hb_out(struct rpc_channel *channel, in vmw_port_hb_out() argument
171 unsigned long bp = channel->cookie_high; in vmw_port_hb_out()
172 u32 channel_id = (channel->channel_id << 16); in vmw_port_hb_out()
175 di = channel->cookie_low; in vmw_port_hb_out()
195 msg_len -= bytes; in vmw_port_hb_out()
197 si = channel->cookie_high; in vmw_port_hb_out()
198 di = channel->cookie_low; in vmw_port_hb_out()
202 channel->channel_id << 16, in vmw_port_hb_out()
211 * vmw_port_hb_in - Receive the message payload either through the
212 * high-bandwidth port if available, or through the backdoor otherwise.
213 * @channel: The rpc channel.
216 * @hb: Whether the high-bandwidth port is available.
220 static unsigned long vmw_port_hb_in(struct rpc_channel *channel, char *reply, in vmw_port_hb_in() argument
227 unsigned long bp = channel->cookie_low; in vmw_port_hb_in()
228 u32 channel_id = (channel->channel_id << 16); in vmw_port_hb_in()
230 si = channel->cookie_high; in vmw_port_hb_in()
248 si = channel->cookie_high; in vmw_port_hb_in()
249 di = channel->cookie_low; in vmw_port_hb_in()
253 channel->channel_id << 16, in vmw_port_hb_in()
261 reply_len -= bytes; in vmw_port_hb_in()
272 * @channel: RPC channel
277 static int vmw_send_msg(struct rpc_channel *channel, const char *msg) in vmw_send_msg() argument
287 si = channel->cookie_high; in vmw_send_msg()
288 di = channel->cookie_low; in vmw_send_msg()
292 channel->channel_id << 16, in vmw_send_msg()
298 return -EINVAL; in vmw_send_msg()
302 ebx = vmw_port_hb_out(channel, msg, in vmw_send_msg()
315 return -EINVAL; in vmw_send_msg()
325 * @channel: channel opened by vmw_open_channel
329 static int vmw_recv_msg(struct rpc_channel *channel, void **msg, in vmw_recv_msg() argument
345 si = channel->cookie_high; in vmw_recv_msg()
346 di = channel->cookie_low; in vmw_recv_msg()
350 channel->channel_id << 16, in vmw_recv_msg()
356 return -EINVAL; in vmw_recv_msg()
367 return -ENOMEM; in vmw_recv_msg()
372 ebx = vmw_port_hb_in(channel, reply, reply_len, in vmw_recv_msg()
382 return -EINVAL; in vmw_recv_msg()
389 si = channel->cookie_high; in vmw_recv_msg()
390 di = channel->cookie_low; in vmw_recv_msg()
394 channel->channel_id << 16, in vmw_recv_msg()
406 return -EINVAL; in vmw_recv_msg()
413 return -EINVAL; in vmw_recv_msg()
427 * a string, and it is up to the caller to post-process.
438 struct rpc_channel channel; in vmw_host_get_guestinfo() local
443 return -ENODEV; in vmw_host_get_guestinfo()
446 return -EINVAL; in vmw_host_get_guestinfo()
448 msg = kasprintf(GFP_KERNEL, "info-get %s", guest_info_param); in vmw_host_get_guestinfo()
452 return -ENOMEM; in vmw_host_get_guestinfo()
455 if (vmw_open_channel(&channel, RPCI_PROTOCOL_NUM)) in vmw_host_get_guestinfo()
458 if (vmw_send_msg(&channel, msg) || in vmw_host_get_guestinfo()
459 vmw_recv_msg(&channel, (void *) &reply, &reply_len)) in vmw_host_get_guestinfo()
462 vmw_close_channel(&channel); in vmw_host_get_guestinfo()
467 reply_len = max(reply_len - 2, (size_t) 0); in vmw_host_get_guestinfo()
482 vmw_close_channel(&channel); in vmw_host_get_guestinfo()
489 return -EINVAL; in vmw_host_get_guestinfo()
504 struct rpc_channel channel; in vmw_host_printf() local
510 return -ENODEV; in vmw_host_printf()
520 return -ENOMEM; in vmw_host_printf()
527 return -ENOMEM; in vmw_host_printf()
530 if (vmw_open_channel(&channel, RPCI_PROTOCOL_NUM)) in vmw_host_printf()
533 if (vmw_send_msg(&channel, msg)) in vmw_host_printf()
536 vmw_close_channel(&channel); in vmw_host_printf()
543 vmw_close_channel(&channel); in vmw_host_printf()
549 return -EINVAL; in vmw_host_printf()
554 * vmw_msg_ioctl: Sends and receveives a message to/from host from/to user-space
556 * Sends a message from user-space to host.
557 * Can also receive a result from host and return that to user-space.
570 struct rpc_channel channel; in vmw_msg_ioctl() local
577 return -ENOMEM; in vmw_msg_ioctl()
580 length = strncpy_from_user(msg, (void __user *)((unsigned long)arg->send), in vmw_msg_ioctl()
585 return -EINVAL; in vmw_msg_ioctl()
589 if (vmw_open_channel(&channel, RPCI_PROTOCOL_NUM)) { in vmw_msg_ioctl()
590 DRM_ERROR("Failed to open channel.\n"); in vmw_msg_ioctl()
594 if (vmw_send_msg(&channel, msg)) { in vmw_msg_ioctl()
599 if (!arg->send_only) { in vmw_msg_ioctl()
603 if (vmw_recv_msg(&channel, (void *) &reply, &reply_len)) { in vmw_msg_ioctl()
608 if (copy_to_user((void __user *)((unsigned long)arg->receive), in vmw_msg_ioctl()
614 arg->receive_len = (__u32)reply_len; in vmw_msg_ioctl()
619 vmw_close_channel(&channel); in vmw_msg_ioctl()
625 vmw_close_channel(&channel); in vmw_msg_ioctl()
629 return -EINVAL; in vmw_msg_ioctl()
665 * hypervisor_ppn_add: Adds a single mksGuestStat instance descriptor to the
682 * hypervisor_ppn_remove: Removes a single mksGuestStat instance descriptor from
700 /* Order of the total number of pages used for kernel-internal mksGuestStat; at least 2 */
706 * mksstat_init_record_time: Initializes an MKSGuestStatCounterTime-based record
709 * @stat_idx: Index of the MKSGuestStatCounterTime-based mksGuestStat record.
732 * mksstat_init_kern_id: Creates a single mksGuestStat instance descriptor and
733 * kernel-internal counters. Adds PFN mapping to the hypervisor.
735 * Create a single mksGuestStat instance descriptor and corresponding structures
736 * for all kernel-internal counters. The corresponding PFNs are mapped with the
750 /* Allocate pages for the kernel-internal instance descriptor */ in mksstat_init_kern_id()
754 return -ENOMEM; in mksstat_init_kern_id()
761 /* Set up all kernel-internal counters and corresponding structures */ in mksstat_init_kern_id()
768 BUG_ON(pstrs_acc - pstrs > PAGE_SIZE); in mksstat_init_kern_id()
770 /* Set up the kernel-internal instance descriptor */ in mksstat_init_kern_id()
771 pdesc->reservedMBZ = 0; in mksstat_init_kern_id()
772 pdesc->statStartVA = (uintptr_t)pstat; in mksstat_init_kern_id()
773 pdesc->strsStartVA = (uintptr_t)pstrs; in mksstat_init_kern_id()
774 pdesc->statLength = sizeof(*pstat) * MKSSTAT_KERN_COUNT; in mksstat_init_kern_id()
775 pdesc->infoLength = sizeof(*pinfo) * MKSSTAT_KERN_COUNT; in mksstat_init_kern_id()
776 pdesc->strsLength = pstrs_acc - pstrs; in mksstat_init_kern_id()
777 snprintf(pdesc->description, ARRAY_SIZE(pdesc->description) - 1, "%s pid=%d", in mksstat_init_kern_id()
778 MKSSTAT_KERNEL_DESCRIPTION, current->pid); in mksstat_init_kern_id()
780 pdesc->statPPNs[0] = page_to_pfn(virt_to_page(pstat)); in mksstat_init_kern_id()
781 reset_ppn_array(pdesc->statPPNs + 1, ARRAY_SIZE(pdesc->statPPNs) - 1); in mksstat_init_kern_id()
783 pdesc->infoPPNs[0] = page_to_pfn(virt_to_page(pinfo)); in mksstat_init_kern_id()
784 reset_ppn_array(pdesc->infoPPNs + 1, ARRAY_SIZE(pdesc->infoPPNs) - 1); in mksstat_init_kern_id()
786 pdesc->strsPPNs[0] = page_to_pfn(virt_to_page(pstrs)); in mksstat_init_kern_id()
787 reset_ppn_array(pdesc->strsPPNs + 1, ARRAY_SIZE(pdesc->strsPPNs) - 1); in mksstat_init_kern_id()
797 * vmw_mksstat_get_kern_slot: Acquires a slot for a single kernel-internal
800 * Find a slot for a single kernel-internal mksGuestStat instance descriptor.
801 * In case no such was already present, allocate a new one and set up a kernel-
806 * Return: Non-negative slot on success, negative error code on error.
814 for (i = 0; i < ARRAY_SIZE(dev_priv->mksstat_kern_pids); ++i) { in vmw_mksstat_get_kern_slot()
815 const size_t slot = (i + base) % ARRAY_SIZE(dev_priv->mksstat_kern_pids); in vmw_mksstat_get_kern_slot()
818 if (pid == (pid_t)atomic_read(&dev_priv->mksstat_kern_pids[slot])) in vmw_mksstat_get_kern_slot()
822 if (!atomic_cmpxchg(&dev_priv->mksstat_kern_pids[slot], 0, MKSSTAT_PID_RESERVED)) { in vmw_mksstat_get_kern_slot()
823 const int ret = mksstat_init_kern_id(&dev_priv->mksstat_kern_pages[slot]); in vmw_mksstat_get_kern_slot()
826 /* Reset top-timer tracking for this slot */ in vmw_mksstat_get_kern_slot()
827 dev_priv->mksstat_kern_top_timer[slot] = MKSSTAT_KERN_COUNT; in vmw_mksstat_get_kern_slot()
829 atomic_set(&dev_priv->mksstat_kern_pids[slot], pid); in vmw_mksstat_get_kern_slot()
833 atomic_set(&dev_priv->mksstat_kern_pids[slot], 0); in vmw_mksstat_get_kern_slot()
838 return -ENOSPC; in vmw_mksstat_get_kern_slot()
844 * vmw_mksstat_cleanup_descriptor: Frees a single userspace-originating
845 * mksGuestStat instance-descriptor page and unpins all related user pages.
848 * the instance-descriptor page itself.
858 for (i = 0; i < ARRAY_SIZE(pdesc->statPPNs) && pdesc->statPPNs[i] != INVALID_PPN64; ++i) in vmw_mksstat_cleanup_descriptor()
859 unpin_user_page(pfn_to_page(pdesc->statPPNs[i])); in vmw_mksstat_cleanup_descriptor()
861 for (i = 0; i < ARRAY_SIZE(pdesc->infoPPNs) && pdesc->infoPPNs[i] != INVALID_PPN64; ++i) in vmw_mksstat_cleanup_descriptor()
862 unpin_user_page(pfn_to_page(pdesc->infoPPNs[i])); in vmw_mksstat_cleanup_descriptor()
864 for (i = 0; i < ARRAY_SIZE(pdesc->strsPPNs) && pdesc->strsPPNs[i] != INVALID_PPN64; ++i) in vmw_mksstat_cleanup_descriptor()
865 unpin_user_page(pfn_to_page(pdesc->strsPPNs[i])); in vmw_mksstat_cleanup_descriptor()
889 /* Discard all userspace-originating instance descriptors and unpin all related pages */ in vmw_mksstat_remove_all()
890 for (i = 0; i < ARRAY_SIZE(dev_priv->mksstat_user_pids); ++i) { in vmw_mksstat_remove_all()
891 const pid_t pid0 = (pid_t)atomic_read(&dev_priv->mksstat_user_pids[i]); in vmw_mksstat_remove_all()
897 const pid_t pid1 = atomic_cmpxchg(&dev_priv->mksstat_user_pids[i], pid0, MKSSTAT_PID_RESERVED); in vmw_mksstat_remove_all()
903 struct page *const page = dev_priv->mksstat_user_pages[i]; in vmw_mksstat_remove_all()
907 dev_priv->mksstat_user_pages[i] = NULL; in vmw_mksstat_remove_all()
908 atomic_set(&dev_priv->mksstat_user_pids[i], 0); in vmw_mksstat_remove_all()
915 ret = -EAGAIN; in vmw_mksstat_remove_all()
919 /* Discard all kernel-internal instance descriptors and free all related pages */ in vmw_mksstat_remove_all()
920 for (i = 0; i < ARRAY_SIZE(dev_priv->mksstat_kern_pids); ++i) { in vmw_mksstat_remove_all()
921 const pid_t pid0 = (pid_t)atomic_read(&dev_priv->mksstat_kern_pids[i]); in vmw_mksstat_remove_all()
927 const pid_t pid1 = atomic_cmpxchg(&dev_priv->mksstat_kern_pids[i], pid0, MKSSTAT_PID_RESERVED); in vmw_mksstat_remove_all()
933 struct page *const page = dev_priv->mksstat_kern_pages[i]; in vmw_mksstat_remove_all()
937 dev_priv->mksstat_kern_pages[i] = NULL; in vmw_mksstat_remove_all()
938 atomic_set(&dev_priv->mksstat_kern_pids[i], 0); in vmw_mksstat_remove_all()
945 ret = -EAGAIN; in vmw_mksstat_remove_all()
973 * vmw_mksstat_add_ioctl: Creates a single userspace-originating mksGuestStat
976 * Create a hypervisor PFN mapping, containing a single mksGuestStat instance
993 const size_t num_pages_stat = PFN_UP(arg->stat_len); in vmw_mksstat_add_ioctl()
994 const size_t num_pages_info = PFN_UP(arg->info_len); in vmw_mksstat_add_ioctl()
995 const size_t num_pages_strs = PFN_UP(arg->strs_len); in vmw_mksstat_add_ioctl()
1006 int ret_err = -ENOMEM; in vmw_mksstat_add_ioctl()
1008 arg->id = -1; in vmw_mksstat_add_ioctl()
1010 if (!arg->stat || !arg->info || !arg->strs) in vmw_mksstat_add_ioctl()
1011 return -EINVAL; in vmw_mksstat_add_ioctl()
1013 if (!arg->stat_len || !arg->info_len || !arg->strs_len) in vmw_mksstat_add_ioctl()
1014 return -EINVAL; in vmw_mksstat_add_ioctl()
1016 if (!arg->description) in vmw_mksstat_add_ioctl()
1017 return -EINVAL; in vmw_mksstat_add_ioctl()
1019 if (num_pages_stat > ARRAY_SIZE(pdesc->statPPNs) || in vmw_mksstat_add_ioctl()
1020 num_pages_info > ARRAY_SIZE(pdesc->infoPPNs) || in vmw_mksstat_add_ioctl()
1021 num_pages_strs > ARRAY_SIZE(pdesc->strsPPNs)) in vmw_mksstat_add_ioctl()
1022 return -EINVAL; in vmw_mksstat_add_ioctl()
1025 for (slot = 0; slot < ARRAY_SIZE(dev_priv->mksstat_user_pids); ++slot) in vmw_mksstat_add_ioctl()
1026 if (!atomic_cmpxchg(&dev_priv->mksstat_user_pids[slot], 0, MKSSTAT_PID_RESERVED)) in vmw_mksstat_add_ioctl()
1029 if (slot == ARRAY_SIZE(dev_priv->mksstat_user_pids)) in vmw_mksstat_add_ioctl()
1030 return -ENOSPC; in vmw_mksstat_add_ioctl()
1032 BUG_ON(dev_priv->mksstat_user_pages[slot]); in vmw_mksstat_add_ioctl()
1034 /* Allocate statically-sized temp arrays for pages -- too big to keep in frame */ in vmw_mksstat_add_ioctl()
1036 ARRAY_SIZE(pdesc->statPPNs) + in vmw_mksstat_add_ioctl()
1037 ARRAY_SIZE(pdesc->infoPPNs) + in vmw_mksstat_add_ioctl()
1038 ARRAY_SIZE(pdesc->strsPPNs), sizeof(*pages_stat), GFP_KERNEL); in vmw_mksstat_add_ioctl()
1043 pages_info = pages_stat + ARRAY_SIZE(pdesc->statPPNs); in vmw_mksstat_add_ioctl()
1044 pages_strs = pages_info + ARRAY_SIZE(pdesc->infoPPNs); in vmw_mksstat_add_ioctl()
1055 pdesc->reservedMBZ = 0; in vmw_mksstat_add_ioctl()
1056 pdesc->statStartVA = arg->stat; in vmw_mksstat_add_ioctl()
1057 pdesc->strsStartVA = arg->strs; in vmw_mksstat_add_ioctl()
1058 pdesc->statLength = arg->stat_len; in vmw_mksstat_add_ioctl()
1059 pdesc->infoLength = arg->info_len; in vmw_mksstat_add_ioctl()
1060 pdesc->strsLength = arg->strs_len; in vmw_mksstat_add_ioctl()
1061 desc_len = strncpy_from_user(pdesc->description, u64_to_user_ptr(arg->description), in vmw_mksstat_add_ioctl()
1062 ARRAY_SIZE(pdesc->description) - 1); in vmw_mksstat_add_ioctl()
1065 ret_err = -EFAULT; in vmw_mksstat_add_ioctl()
1069 reset_ppn_array(pdesc->statPPNs, ARRAY_SIZE(pdesc->statPPNs)); in vmw_mksstat_add_ioctl()
1070 reset_ppn_array(pdesc->infoPPNs, ARRAY_SIZE(pdesc->infoPPNs)); in vmw_mksstat_add_ioctl()
1071 reset_ppn_array(pdesc->strsPPNs, ARRAY_SIZE(pdesc->strsPPNs)); in vmw_mksstat_add_ioctl()
1074 nr_pinned_stat = pin_user_pages_fast(arg->stat, num_pages_stat, FOLL_LONGTERM, pages_stat); in vmw_mksstat_add_ioctl()
1079 pdesc->statPPNs[i] = page_to_pfn(pages_stat[i]); in vmw_mksstat_add_ioctl()
1081 nr_pinned_info = pin_user_pages_fast(arg->info, num_pages_info, FOLL_LONGTERM, pages_info); in vmw_mksstat_add_ioctl()
1086 pdesc->infoPPNs[i] = page_to_pfn(pages_info[i]); in vmw_mksstat_add_ioctl()
1088 nr_pinned_strs = pin_user_pages_fast(arg->strs, num_pages_strs, FOLL_LONGTERM, pages_strs); in vmw_mksstat_add_ioctl()
1093 pdesc->strsPPNs[i] = page_to_pfn(pages_strs[i]); in vmw_mksstat_add_ioctl()
1100 dev_priv->mksstat_user_pages[slot] = page; in vmw_mksstat_add_ioctl()
1101 atomic_set(&dev_priv->mksstat_user_pids[slot], task_pgrp_vnr(current)); in vmw_mksstat_add_ioctl()
1103 arg->id = slot; in vmw_mksstat_add_ioctl()
1105 …DRM_DEV_INFO(dev->dev, "pid=%d arg.description='%.*s' id=%zu\n", current->pid, (int)desc_len, pdes… in vmw_mksstat_add_ioctl()
1123 atomic_set(&dev_priv->mksstat_user_pids[slot], 0); in vmw_mksstat_add_ioctl()
1132 * vmw_mksstat_remove_ioctl: Removes a single userspace-originating mksGuestStat
1135 * Discard a hypervisor PFN mapping, containing a single mksGuestStat instance
1152 const size_t slot = arg->id; in vmw_mksstat_remove_ioctl()
1155 if (slot >= ARRAY_SIZE(dev_priv->mksstat_user_pids)) in vmw_mksstat_remove_ioctl()
1156 return -EINVAL; in vmw_mksstat_remove_ioctl()
1158 DRM_DEV_INFO(dev->dev, "pid=%d arg.id=%zu\n", current->pid, slot); in vmw_mksstat_remove_ioctl()
1161 pid = atomic_cmpxchg(&dev_priv->mksstat_user_pids[slot], pgid, MKSSTAT_PID_RESERVED); in vmw_mksstat_remove_ioctl()
1167 struct page *const page = dev_priv->mksstat_user_pages[slot]; in vmw_mksstat_remove_ioctl()
1171 dev_priv->mksstat_user_pages[slot] = NULL; in vmw_mksstat_remove_ioctl()
1172 atomic_set(&dev_priv->mksstat_user_pids[slot], 0); in vmw_mksstat_remove_ioctl()
1180 return -EAGAIN; in vmw_mksstat_remove_ioctl()