From: Tianyu Lan <Tianyu.Lan@xxxxxxxxxxxxx> Mark vmbus ring buffer visible with set_memory_decrypted() when establish gpadl handle. Signed-off-by: Tianyu Lan <Tianyu.Lan@xxxxxxxxxxxxx> --- drivers/hv/channel.c | 44 ++++++++++++++++++++++++++++++++++++++++-- include/linux/hyperv.h | 11 +++++++++++ 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index f3761c73b074..4c4717c26240 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -17,6 +17,7 @@ #include <linux/hyperv.h> #include <linux/uio.h> #include <linux/interrupt.h> +#include <linux/set_memory.h> #include <asm/page.h> #include <asm/mshyperv.h> @@ -465,7 +466,14 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel, struct list_head *curr; u32 next_gpadl_handle; unsigned long flags; - int ret = 0; + int ret = 0, index; + + index = atomic_inc_return(&channel->gpadl_index) - 1; + + if (index > VMBUS_GPADL_RANGE_COUNT - 1) { + pr_err("Gpadl handle position(%d) has been occupied.\n", index); + return -ENOSPC; + } next_gpadl_handle = (atomic_inc_return(&vmbus_connection.next_gpadl_handle) - 1); @@ -474,6 +482,13 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel, if (ret) return ret; + ret = set_memory_decrypted((unsigned long)kbuffer, + HVPFN_UP(size)); + if (ret) { + pr_warn("Failed to set host visibility.\n"); + return ret; + } + init_completion(&msginfo->waitevent); msginfo->waiting_channel = channel; @@ -539,6 +554,10 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel, /* At this point, we received the gpadl created msg */ *gpadl_handle = gpadlmsg->gpadl; + channel->gpadl_array[index].size = size; + channel->gpadl_array[index].buffer = kbuffer; + channel->gpadl_array[index].gpadlhandle = *gpadl_handle; + cleanup: spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); list_del(&msginfo->msglistentry); @@ -549,6 +568,13 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel, } kfree(msginfo); + + if (ret) { + set_memory_encrypted((unsigned long)kbuffer, + HVPFN_UP(size)); + atomic_dec(&channel->gpadl_index); + } + return ret; } @@ -676,6 +702,7 @@ static int __vmbus_open(struct vmbus_channel *newchannel, /* Establish the gpadl for the ring buffer */ newchannel->ringbuffer_gpadlhandle = 0; + atomic_set(&newchannel->gpadl_index, 0); err = __vmbus_establish_gpadl(newchannel, HV_GPADL_RING, page_address(newchannel->ringbuffer_page), @@ -811,7 +838,7 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle) struct vmbus_channel_gpadl_teardown *msg; struct vmbus_channel_msginfo *info; unsigned long flags; - int ret; + int ret, i; info = kzalloc(sizeof(*info) + sizeof(struct vmbus_channel_gpadl_teardown), GFP_KERNEL); @@ -859,6 +886,19 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle) spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); kfree(info); + + /* Find gpadl buffer virtual address and size. */ + for (i = 0; i < VMBUS_GPADL_RANGE_COUNT; i++) + if (channel->gpadl_array[i].gpadlhandle == gpadl_handle) + break; + + if (set_memory_encrypted((unsigned long)channel->gpadl_array[i].buffer, + HVPFN_UP(channel->gpadl_array[i].size))) + pr_warn("Fail to set mem host visibility.\n"); + + channel->gpadl_array[i].gpadlhandle = 0; + atomic_dec(&channel->gpadl_index); + return ret; } EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl); diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index ddc8713ce57b..90b542597143 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -803,6 +803,14 @@ struct vmbus_device { #define VMBUS_DEFAULT_MAX_PKT_SIZE 4096 +struct vmbus_gpadl { + u32 gpadlhandle; + u32 size; + void *buffer; +}; + +#define VMBUS_GPADL_RANGE_COUNT 3 + struct vmbus_channel { struct list_head listentry; @@ -823,6 +831,9 @@ struct vmbus_channel { struct completion rescind_event; u32 ringbuffer_gpadlhandle; + /* GPADL_RING and Send/Receive GPADL_BUFFER. */ + struct vmbus_gpadl gpadl_array[VMBUS_GPADL_RANGE_COUNT]; + atomic_t gpadl_index; /* Allocated memory for ring buffer */ struct page *ringbuffer_page; -- 2.25.1