Loading drivers/soc/qcom/mem-buf.c +23 −7 Original line number Diff line number Diff line Loading @@ -662,10 +662,16 @@ static void mem_buf_alloc_req_work(struct work_struct *work) resp_msg->ret = ret; ret = hh_msgq_send(mem_buf_hh_msgq_hdl, resp_msg, sizeof(*resp_msg), 0); /* * Free the buffer regardless of the return value as the hypervisor * would have consumed the data in the case of a success. */ kfree(resp_msg); if (ret < 0) { pr_err("%s: failed to send memory allocation response rc: %d\n", __func__, ret); kfree(resp_msg); mutex_lock(&mem_buf_xfer_mem_list_lock); list_del(&xfer_mem->entry); mutex_unlock(&mem_buf_xfer_mem_list_lock); Loading Loading @@ -868,10 +874,15 @@ static int mem_buf_request_mem(struct mem_buf_desc *membuf) } ret = mem_buf_msg_send(alloc_req_msg, msg_size); if (ret < 0) { /* * Free the buffer regardless of the return value as the hypervisor * would have consumed the data in the case of a success. */ kfree(alloc_req_msg); if (ret < 0) goto out; } ret = mem_buf_txn_wait(&txn); if (ret < 0) Loading @@ -897,11 +908,16 @@ static void mem_buf_relinquish_mem(struct mem_buf_desc *membuf) msg->hdl = membuf->memparcel_hdl; ret = hh_msgq_send(mem_buf_hh_msgq_hdl, msg, sizeof(*msg), 0); if (ret < 0) { /* * Free the buffer regardless of the return value as the hypervisor * would have consumed the data in the case of a success. */ kfree(msg); if (ret < 0) pr_err("%s failed to send memory relinquish message rc: %d\n", __func__, ret); kfree(msg); } } static int mem_buf_map_mem_s2(struct mem_buf_desc *membuf) Loading drivers/virt/haven/hh_msgq.c +44 −17 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ #include <linux/module.h> #include <linux/spinlock.h> #include <linux/interrupt.h> #include <linux/ratelimit.h> #include <linux/haven/hcall.h> #include <linux/haven/hh_msgq.h> Loading Loading @@ -40,6 +41,7 @@ struct hh_msgq_cap_table { wait_queue_head_t rx_wq; }; static bool hh_msgq_initialized; static struct hh_msgq_cap_table hh_msgq_cap_table[HH_MSGQ_LABEL_MAX]; static irqreturn_t hh_msgq_rx_isr(int irq, void *dev) Loading Loading @@ -118,6 +120,9 @@ static int __hh_msgq_recv(struct hh_msgq_cap_table *cap_table_entry, * if the message queue is not yet ready to communicate, and -EPERM if the * caller doesn't have permissions to receive the data. 0 is the data is * successfully received. * * Note: this function may sleep and should not be called from interrupt * context */ int hh_msgq_recv(void *msgq_client_desc, void **buff, size_t *size, unsigned long flags) Loading @@ -139,15 +144,25 @@ int hh_msgq_recv(void *msgq_client_desc, goto err; } if (cap_table_entry->rx_cap_id == HH_CAPID_INVAL) { pr_err("%s: Recv info for label %d not yet initialized\n", if ((cap_table_entry->rx_cap_id == HH_CAPID_INVAL) && (flags & HH_MSGQ_NONBLOCK)) { pr_err_ratelimited( "%s: Recv info for label %d not yet initialized\n", __func__, client_desc->label); ret = -EAGAIN; goto err; } spin_unlock(&cap_table_entry->cap_entry_lock); if (wait_event_interruptible(cap_table_entry->rx_wq, cap_table_entry->rx_cap_id != HH_CAPID_INVAL)) return -ERESTARTSYS; spin_lock(&cap_table_entry->cap_entry_lock); if (!cap_table_entry->rx_irq) { pr_err("%s: Rx IRQ for label %d not yet setup\n", pr_err_ratelimited("%s: Rx IRQ for label %d not yet setup\n", __func__, client_desc->label); ret = -EAGAIN; goto err; Loading Loading @@ -224,15 +239,12 @@ static int __hh_msgq_send(struct hh_msgq_cap_table *cap_table_entry, /** * hh_msgq_send: Send a message to the client on a different VM * @client_desc: The client descriptor that was obtained via hh_msgq_register() * @buff: Pointer to the buffer that needs to be sent. The buffer should be * dynamically allocated via kmalloc/kzalloc. * @buff: Pointer to the buffer that needs to be sent * @size: The size of the buffer * @flags: Optional flags to pass to send the data. For the list of flags, * see linux/haven/hh_msgq.h * * The function would free the buffer upon success, and returns 0. The caller * should not be referencing the buffer anymore. * On the other hand, it returns -EINVAL if the caller passes invalid arguments, * The function returns -EINVAL if the caller passes invalid arguments, * -EAGAIN if the message queue is not yet ready to communicate, and -EPERM if * the caller doesn't have permissions to send the data. * Loading Loading @@ -260,15 +272,25 @@ int hh_msgq_send(void *msgq_client_desc, goto err; } if (cap_table_entry->tx_cap_id == HH_CAPID_INVAL) { pr_err("%s: Send info for label %d not yet initialized\n", if ((cap_table_entry->tx_cap_id == HH_CAPID_INVAL) && (flags & HH_MSGQ_NONBLOCK)) { pr_err_ratelimited( "%s: Send info for label %d not yet initialized\n", __func__, client_desc->label); ret = -EAGAIN; goto err; } spin_unlock(&cap_table_entry->cap_entry_lock); if (wait_event_interruptible(cap_table_entry->tx_wq, cap_table_entry->tx_cap_id != HH_CAPID_INVAL)) return -ERESTARTSYS; spin_lock(&cap_table_entry->cap_entry_lock); if (!cap_table_entry->tx_irq) { pr_err("%s: Tx IRQ for label %d not yet setup\n", pr_err_ratelimited("%s: Tx IRQ for label %d not yet setup\n", __func__, client_desc->label); ret = -EAGAIN; goto err; Loading @@ -287,12 +309,6 @@ int hh_msgq_send(void *msgq_client_desc, ret = __hh_msgq_send(cap_table_entry, buff, size, flags); } while (ret == -EAGAIN); /* If the send is success, hypervisor should not be holding any * references to 'buff', and hence, can be released. */ if (!ret) kfree(buff); return ret; err: spin_unlock(&cap_table_entry->cap_entry_lock); Loading @@ -316,6 +332,9 @@ void *hh_msgq_register(enum hh_msgq_label label) struct hh_msgq_cap_table *cap_table_entry; struct hh_msgq_desc *client_desc; if (!hh_msgq_initialized) return ERR_PTR(-EPROBE_DEFER); if (label < 0 || label >= HH_MSGQ_LABEL_MAX) return ERR_PTR(-EINVAL); Loading Loading @@ -393,6 +412,9 @@ int hh_msgq_populate_cap_info(enum hh_msgq_label label, u64 cap_id, struct hh_msgq_cap_table *cap_table_entry; int ret; if (!hh_msgq_initialized) return -EPROBE_DEFER; if (label < 0 || label >= HH_MSGQ_LABEL_MAX) { pr_err("%s: Invalid label passed\n", __func__); return -EINVAL; Loading @@ -415,6 +437,8 @@ int hh_msgq_populate_cap_info(enum hh_msgq_label label, u64 cap_id, cap_table_entry->tx_irq = irq; cap_table_entry->tx_cap_id = cap_id; wake_up_interruptible(&cap_table_entry->tx_wq); } else if (direction == HH_MSGQ_DIRECTION_RX) { ret = request_irq(irq, hh_msgq_rx_isr, 0, cap_table_entry->rx_irq_name, cap_table_entry); Loading @@ -423,6 +447,8 @@ int hh_msgq_populate_cap_info(enum hh_msgq_label label, u64 cap_id, cap_table_entry->rx_cap_id = cap_id; cap_table_entry->rx_irq = irq; wake_up_interruptible(&cap_table_entry->rx_wq); } else { pr_err("%s: Invalid direction passed\n", __func__); ret = -EINVAL; Loading Loading @@ -493,6 +519,7 @@ static int __init hh_msgq_init(void) } } hh_msgq_initialized = true; return 0; err: Loading drivers/virt/haven/hh_rm_core.c +10 −3 Original line number Diff line number Diff line Loading @@ -518,11 +518,18 @@ static int hh_rm_send_request(u32 message_id, ret = hh_msgq_send(hh_rm_msgq_desc, send_buff, sizeof(*hdr) + payload_size, tx_flags); if (ret) { /* * In the case of a success, the hypervisor would have consumed * the buffer. While in the case of a failure, we are going to * quit anyways. Hence, free the buffer regardless of the * return value. */ kfree(send_buff); if (ret) return ret; } } return 0; } Loading Loading
drivers/soc/qcom/mem-buf.c +23 −7 Original line number Diff line number Diff line Loading @@ -662,10 +662,16 @@ static void mem_buf_alloc_req_work(struct work_struct *work) resp_msg->ret = ret; ret = hh_msgq_send(mem_buf_hh_msgq_hdl, resp_msg, sizeof(*resp_msg), 0); /* * Free the buffer regardless of the return value as the hypervisor * would have consumed the data in the case of a success. */ kfree(resp_msg); if (ret < 0) { pr_err("%s: failed to send memory allocation response rc: %d\n", __func__, ret); kfree(resp_msg); mutex_lock(&mem_buf_xfer_mem_list_lock); list_del(&xfer_mem->entry); mutex_unlock(&mem_buf_xfer_mem_list_lock); Loading Loading @@ -868,10 +874,15 @@ static int mem_buf_request_mem(struct mem_buf_desc *membuf) } ret = mem_buf_msg_send(alloc_req_msg, msg_size); if (ret < 0) { /* * Free the buffer regardless of the return value as the hypervisor * would have consumed the data in the case of a success. */ kfree(alloc_req_msg); if (ret < 0) goto out; } ret = mem_buf_txn_wait(&txn); if (ret < 0) Loading @@ -897,11 +908,16 @@ static void mem_buf_relinquish_mem(struct mem_buf_desc *membuf) msg->hdl = membuf->memparcel_hdl; ret = hh_msgq_send(mem_buf_hh_msgq_hdl, msg, sizeof(*msg), 0); if (ret < 0) { /* * Free the buffer regardless of the return value as the hypervisor * would have consumed the data in the case of a success. */ kfree(msg); if (ret < 0) pr_err("%s failed to send memory relinquish message rc: %d\n", __func__, ret); kfree(msg); } } static int mem_buf_map_mem_s2(struct mem_buf_desc *membuf) Loading
drivers/virt/haven/hh_msgq.c +44 −17 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ #include <linux/module.h> #include <linux/spinlock.h> #include <linux/interrupt.h> #include <linux/ratelimit.h> #include <linux/haven/hcall.h> #include <linux/haven/hh_msgq.h> Loading Loading @@ -40,6 +41,7 @@ struct hh_msgq_cap_table { wait_queue_head_t rx_wq; }; static bool hh_msgq_initialized; static struct hh_msgq_cap_table hh_msgq_cap_table[HH_MSGQ_LABEL_MAX]; static irqreturn_t hh_msgq_rx_isr(int irq, void *dev) Loading Loading @@ -118,6 +120,9 @@ static int __hh_msgq_recv(struct hh_msgq_cap_table *cap_table_entry, * if the message queue is not yet ready to communicate, and -EPERM if the * caller doesn't have permissions to receive the data. 0 is the data is * successfully received. * * Note: this function may sleep and should not be called from interrupt * context */ int hh_msgq_recv(void *msgq_client_desc, void **buff, size_t *size, unsigned long flags) Loading @@ -139,15 +144,25 @@ int hh_msgq_recv(void *msgq_client_desc, goto err; } if (cap_table_entry->rx_cap_id == HH_CAPID_INVAL) { pr_err("%s: Recv info for label %d not yet initialized\n", if ((cap_table_entry->rx_cap_id == HH_CAPID_INVAL) && (flags & HH_MSGQ_NONBLOCK)) { pr_err_ratelimited( "%s: Recv info for label %d not yet initialized\n", __func__, client_desc->label); ret = -EAGAIN; goto err; } spin_unlock(&cap_table_entry->cap_entry_lock); if (wait_event_interruptible(cap_table_entry->rx_wq, cap_table_entry->rx_cap_id != HH_CAPID_INVAL)) return -ERESTARTSYS; spin_lock(&cap_table_entry->cap_entry_lock); if (!cap_table_entry->rx_irq) { pr_err("%s: Rx IRQ for label %d not yet setup\n", pr_err_ratelimited("%s: Rx IRQ for label %d not yet setup\n", __func__, client_desc->label); ret = -EAGAIN; goto err; Loading Loading @@ -224,15 +239,12 @@ static int __hh_msgq_send(struct hh_msgq_cap_table *cap_table_entry, /** * hh_msgq_send: Send a message to the client on a different VM * @client_desc: The client descriptor that was obtained via hh_msgq_register() * @buff: Pointer to the buffer that needs to be sent. The buffer should be * dynamically allocated via kmalloc/kzalloc. * @buff: Pointer to the buffer that needs to be sent * @size: The size of the buffer * @flags: Optional flags to pass to send the data. For the list of flags, * see linux/haven/hh_msgq.h * * The function would free the buffer upon success, and returns 0. The caller * should not be referencing the buffer anymore. * On the other hand, it returns -EINVAL if the caller passes invalid arguments, * The function returns -EINVAL if the caller passes invalid arguments, * -EAGAIN if the message queue is not yet ready to communicate, and -EPERM if * the caller doesn't have permissions to send the data. * Loading Loading @@ -260,15 +272,25 @@ int hh_msgq_send(void *msgq_client_desc, goto err; } if (cap_table_entry->tx_cap_id == HH_CAPID_INVAL) { pr_err("%s: Send info for label %d not yet initialized\n", if ((cap_table_entry->tx_cap_id == HH_CAPID_INVAL) && (flags & HH_MSGQ_NONBLOCK)) { pr_err_ratelimited( "%s: Send info for label %d not yet initialized\n", __func__, client_desc->label); ret = -EAGAIN; goto err; } spin_unlock(&cap_table_entry->cap_entry_lock); if (wait_event_interruptible(cap_table_entry->tx_wq, cap_table_entry->tx_cap_id != HH_CAPID_INVAL)) return -ERESTARTSYS; spin_lock(&cap_table_entry->cap_entry_lock); if (!cap_table_entry->tx_irq) { pr_err("%s: Tx IRQ for label %d not yet setup\n", pr_err_ratelimited("%s: Tx IRQ for label %d not yet setup\n", __func__, client_desc->label); ret = -EAGAIN; goto err; Loading @@ -287,12 +309,6 @@ int hh_msgq_send(void *msgq_client_desc, ret = __hh_msgq_send(cap_table_entry, buff, size, flags); } while (ret == -EAGAIN); /* If the send is success, hypervisor should not be holding any * references to 'buff', and hence, can be released. */ if (!ret) kfree(buff); return ret; err: spin_unlock(&cap_table_entry->cap_entry_lock); Loading @@ -316,6 +332,9 @@ void *hh_msgq_register(enum hh_msgq_label label) struct hh_msgq_cap_table *cap_table_entry; struct hh_msgq_desc *client_desc; if (!hh_msgq_initialized) return ERR_PTR(-EPROBE_DEFER); if (label < 0 || label >= HH_MSGQ_LABEL_MAX) return ERR_PTR(-EINVAL); Loading Loading @@ -393,6 +412,9 @@ int hh_msgq_populate_cap_info(enum hh_msgq_label label, u64 cap_id, struct hh_msgq_cap_table *cap_table_entry; int ret; if (!hh_msgq_initialized) return -EPROBE_DEFER; if (label < 0 || label >= HH_MSGQ_LABEL_MAX) { pr_err("%s: Invalid label passed\n", __func__); return -EINVAL; Loading @@ -415,6 +437,8 @@ int hh_msgq_populate_cap_info(enum hh_msgq_label label, u64 cap_id, cap_table_entry->tx_irq = irq; cap_table_entry->tx_cap_id = cap_id; wake_up_interruptible(&cap_table_entry->tx_wq); } else if (direction == HH_MSGQ_DIRECTION_RX) { ret = request_irq(irq, hh_msgq_rx_isr, 0, cap_table_entry->rx_irq_name, cap_table_entry); Loading @@ -423,6 +447,8 @@ int hh_msgq_populate_cap_info(enum hh_msgq_label label, u64 cap_id, cap_table_entry->rx_cap_id = cap_id; cap_table_entry->rx_irq = irq; wake_up_interruptible(&cap_table_entry->rx_wq); } else { pr_err("%s: Invalid direction passed\n", __func__); ret = -EINVAL; Loading Loading @@ -493,6 +519,7 @@ static int __init hh_msgq_init(void) } } hh_msgq_initialized = true; return 0; err: Loading
drivers/virt/haven/hh_rm_core.c +10 −3 Original line number Diff line number Diff line Loading @@ -518,11 +518,18 @@ static int hh_rm_send_request(u32 message_id, ret = hh_msgq_send(hh_rm_msgq_desc, send_buff, sizeof(*hdr) + payload_size, tx_flags); if (ret) { /* * In the case of a success, the hypervisor would have consumed * the buffer. While in the case of a failure, we are going to * quit anyways. Hence, free the buffer regardless of the * return value. */ kfree(send_buff); if (ret) return ret; } } return 0; } Loading