Inter-revision diff: patch 2

Comparing rfc (message) to v4 (message)

--- vrfc
+++ v4
@@ -1,88 +1,62 @@
 From: Tianyu Lan <Tianyu.Lan@microsoft.com>
 
-Add new hvcall guest address host visibility support. Mark vmbus
-ring buffer visible to host when create gpadl buffer and mark back
-to not visible when tear down gpadl buffer.
-
-Signed-off-by: Sunil Muthuswamy <sunilmut@microsoft.com>
-Co-Developed-by: Sunil Muthuswamy <sunilmut@microsoft.com>
+Add new hvcall guest address host visibility support to mark
+memory visible to host. Call it inside set_memory_decrypted
+/encrypted().
+
 Signed-off-by: Tianyu Lan <Tianyu.Lan@microsoft.com>
 ---
- arch/x86/include/asm/hyperv-tlfs.h | 13 ++++++++
- arch/x86/include/asm/mshyperv.h    |  4 +--
- arch/x86/kernel/cpu/mshyperv.c     | 46 ++++++++++++++++++++++++++
- drivers/hv/channel.c               | 53 ++++++++++++++++++++++++++++--
- drivers/net/hyperv/hyperv_net.h    |  1 +
- drivers/net/hyperv/netvsc.c        |  9 +++--
- drivers/uio/uio_hv_generic.c       |  6 ++--
- include/asm-generic/hyperv-tlfs.h  |  1 +
- include/linux/hyperv.h             |  3 +-
- 9 files changed, 126 insertions(+), 10 deletions(-)
-
-diff --git a/arch/x86/include/asm/hyperv-tlfs.h b/arch/x86/include/asm/hyperv-tlfs.h
-index fb1893a4c32b..d22b1c3f425a 100644
---- a/arch/x86/include/asm/hyperv-tlfs.h
-+++ b/arch/x86/include/asm/hyperv-tlfs.h
-@@ -573,4 +573,17 @@ enum hv_interrupt_type {
- 
- #include <asm-generic/hyperv-tlfs.h>
- 
-+/* All input parameters should be in single page. */
-+#define HV_MAX_MODIFY_GPA_REP_COUNT		\
-+	((PAGE_SIZE - 2 * sizeof(u64)) / (sizeof(u64)))
-+
-+/* HvCallModifySparseGpaPageHostVisibility hypercall */
-+struct hv_input_modify_sparse_gpa_page_host_visibility {
-+	u64 partition_id;
-+	u32 host_visibility:2;
-+	u32 reserved0:30;
-+	u32 reserved1;
-+	u64 gpa_page_list[HV_MAX_MODIFY_GPA_REP_COUNT];
-+} __packed;
-+
- #endif
-diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
-index ccf60a809a17..1e8275d35c1f 100644
---- a/arch/x86/include/asm/mshyperv.h
-+++ b/arch/x86/include/asm/mshyperv.h
-@@ -262,13 +262,13 @@ static inline void hv_set_msi_entry_from_desc(union hv_msi_entry *msi_entry,
- 	msi_entry->address.as_uint32 = msi_desc->msg.address_lo;
- 	msi_entry->data.as_uint32 = msi_desc->msg.data;
- }
--
- struct irq_domain *hv_create_pci_msi_domain(void);
- 
- int hv_map_ioapic_interrupt(int ioapic_id, bool level, int vcpu, int vector,
- 		struct hv_interrupt_entry *entry);
- int hv_unmap_ioapic_interrupt(int ioapic_id, struct hv_interrupt_entry *entry);
--
-+int hv_set_mem_host_visibility(void *kbuffer, u32 size, u32 visibility);
-+int hv_mark_gpa_visibility(u16 count, const u64 pfn[], u32 visibility);
- #else /* CONFIG_HYPERV */
- static inline void hyperv_init(void) {}
- static inline void hyperv_setup_mmu_ops(void) {}
-diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
-index e88bc296afca..347c32eac8fd 100644
---- a/arch/x86/kernel/cpu/mshyperv.c
-+++ b/arch/x86/kernel/cpu/mshyperv.c
-@@ -37,6 +37,8 @@
- bool hv_root_partition;
- EXPORT_SYMBOL_GPL(hv_root_partition);
- 
-+#define HV_PARTITION_ID_SELF ((u64)-1)
-+
- struct ms_hyperv_info ms_hyperv;
- EXPORT_SYMBOL_GPL(ms_hyperv);
- 
-@@ -477,3 +479,47 @@ const __initconst struct hypervisor_x86 x86_hyper_ms_hyperv = {
- 	.init.msi_ext_dest_id	= ms_hyperv_msi_ext_dest_id,
- 	.init.init_platform	= ms_hyperv_init_platform,
- };
-+
+ arch/x86/hyperv/Makefile           |   2 +-
+ arch/x86/hyperv/ivm.c              | 112 +++++++++++++++++++++++++++++
+ arch/x86/include/asm/hyperv-tlfs.h |  18 +++++
+ arch/x86/include/asm/mshyperv.h    |   3 +-
+ arch/x86/mm/pat/set_memory.c       |   6 +-
+ include/asm-generic/hyperv-tlfs.h  |   1 +
+ 6 files changed, 139 insertions(+), 3 deletions(-)
+ create mode 100644 arch/x86/hyperv/ivm.c
+
+diff --git a/arch/x86/hyperv/Makefile b/arch/x86/hyperv/Makefile
+index 48e2c51464e8..5d2de10809ae 100644
+--- a/arch/x86/hyperv/Makefile
++++ b/arch/x86/hyperv/Makefile
+@@ -1,5 +1,5 @@
+ # SPDX-License-Identifier: GPL-2.0-only
+-obj-y			:= hv_init.o mmu.o nested.o irqdomain.o
++obj-y			:= hv_init.o mmu.o nested.o irqdomain.o ivm.o
+ obj-$(CONFIG_X86_64)	+= hv_apic.o hv_proc.o
+ 
+ ifdef CONFIG_X86_64
+diff --git a/arch/x86/hyperv/ivm.c b/arch/x86/hyperv/ivm.c
+new file mode 100644
+index 000000000000..24a58795abd8
+--- /dev/null
++++ b/arch/x86/hyperv/ivm.c
+@@ -0,0 +1,112 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Hyper-V Isolation VM interface with paravisor and hypervisor
++ *
++ * Author:
++ *  Tianyu Lan <Tianyu.Lan@microsoft.com>
++ */
++
++#include <linux/hyperv.h>
++#include <linux/types.h>
++#include <linux/bitfield.h>
++#include <linux/slab.h>
++#include <asm/io.h>
++#include <asm/mshyperv.h>
++
++/*
++ * hv_mark_gpa_visibility - Set pages visible to host via hvcall.
++ *
++ * In Isolation VM, all guest memory is encripted from host and guest
++ * needs to set memory visible to host via hvcall before sharing memory
++ * with host.
++ */
 +int hv_mark_gpa_visibility(u16 count, const u64 pfn[], u32 visibility)
 +{
-+	struct hv_input_modify_sparse_gpa_page_host_visibility **input_pcpu;
-+	struct hv_input_modify_sparse_gpa_page_host_visibility *input;
++	struct hv_gpa_range_for_visibility **input_pcpu, *input;
 +	u16 pages_processed;
 +	u64 hv_status;
 +	unsigned long flags;
@@ -98,12 +72,12 @@
 +	}
 +
 +	local_irq_save(flags);
-+	input_pcpu = (struct hv_input_modify_sparse_gpa_page_host_visibility **)
++	input_pcpu = (struct hv_gpa_range_for_visibility **)
 +			this_cpu_ptr(hyperv_pcpu_input_arg);
 +	input = *input_pcpu;
 +	if (unlikely(!input)) {
 +		local_irq_restore(flags);
-+		return -1;
++		return -EINVAL;
 +	}
 +
 +	input->partition_id = HV_PARTITION_ID_SELF;
@@ -119,31 +93,29 @@
 +	if (!(hv_status & HV_HYPERCALL_RESULT_MASK))
 +		return 0;
 +
-+	return -EFAULT;
++	return hv_status & HV_HYPERCALL_RESULT_MASK;
 +}
 +EXPORT_SYMBOL(hv_mark_gpa_visibility);
-diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
-index daa21cc72beb..204e6f3598a5 100644
---- a/drivers/hv/channel.c
-+++ b/drivers/hv/channel.c
-@@ -237,6 +237,38 @@ int vmbus_send_modifychannel(u32 child_relid, u32 target_vp)
- }
- EXPORT_SYMBOL_GPL(vmbus_send_modifychannel);
- 
++
 +/*
-+ * hv_set_mem_host_visibility - Set host visibility for specified memory.
++ * hv_set_mem_host_visibility - Set specified memory visible to host.
++ *
++ * In Isolation VM, all guest memory is encrypted from host and guest
++ * needs to set memory visible to host via hvcall before sharing memory
++ * with host. This function works as wrap of hv_mark_gpa_visibility()
++ * with memory base and size.
 + */
-+int hv_set_mem_host_visibility(void *kbuffer, u32 size, u32 visibility)
++static int hv_set_mem_host_visibility(void *kbuffer, size_t size, u32 visibility)
 +{
-+	int i, pfn;
 +	int pagecount = size >> HV_HYP_PAGE_SHIFT;
 +	u64 *pfn_array;
 +	int ret = 0;
-+
-+	if (!hv_isolation_type_snp())
++	int i, pfn;
++
++	if (!hv_is_isolation_supported() || !ms_hyperv.ghcb_base)
 +		return 0;
 +
-+	pfn_array = vzalloc(HV_HYP_PAGE_SIZE);
++	pfn_array = kzalloc(HV_HYP_PAGE_SIZE, GFP_KERNEL);
 +	if (!pfn_array)
 +		return -ENOMEM;
 +
@@ -154,143 +126,98 @@
 +		if (pfn == HV_MAX_MODIFY_GPA_REP_COUNT || i == pagecount - 1) {
 +			ret |= hv_mark_gpa_visibility(pfn, pfn_array, visibility);
 +			pfn = 0;
++
++			if (ret)
++				goto err_free_pfn_array;
 +		}
 +	}
 +
-+	vfree(pfn_array);
++ err_free_pfn_array:
++	kfree(pfn_array);
 +	return ret;
 +}
-+EXPORT_SYMBOL_GPL(hv_set_mem_host_visibility);
++
++int hv_set_mem_enc(unsigned long addr, int numpages, bool enc)
++{
++	return hv_set_mem_host_visibility((void *)addr,
++			numpages * HV_HYP_PAGE_SIZE,
++			enc ? VMBUS_PAGE_NOT_VISIBLE
++			: VMBUS_PAGE_VISIBLE_READ_WRITE);
++}
+diff --git a/arch/x86/include/asm/hyperv-tlfs.h b/arch/x86/include/asm/hyperv-tlfs.h
+index 606f5cc579b2..68826fbf92ca 100644
+--- a/arch/x86/include/asm/hyperv-tlfs.h
++++ b/arch/x86/include/asm/hyperv-tlfs.h
+@@ -262,6 +262,11 @@ enum hv_isolation_type {
+ #define HV_X64_MSR_TIME_REF_COUNT	HV_REGISTER_TIME_REF_COUNT
+ #define HV_X64_MSR_REFERENCE_TSC	HV_REGISTER_REFERENCE_TSC
+ 
++/* Hyper-V GPA map flags */
++#define	VMBUS_PAGE_NOT_VISIBLE		0
++#define	VMBUS_PAGE_VISIBLE_READ_ONLY	1
++#define	VMBUS_PAGE_VISIBLE_READ_WRITE	3
 +
  /*
-  * create_gpadl_header - Creates a gpadl for the specified buffer
+  * Declare the MSR used to setup pages used to communicate with the hypervisor.
   */
-@@ -410,6 +442,12 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel,
- 	if (ret)
- 		return ret;
- 
-+	ret = hv_set_mem_host_visibility(kbuffer, size, visibility);
-+	if (ret) {
-+		pr_warn("Failed to set host visibility.\n");
-+		return ret;
-+	}
-+
- 	init_completion(&msginfo->waitevent);
- 	msginfo->waiting_channel = channel;
- 
-@@ -693,7 +731,9 @@ static int __vmbus_open(struct vmbus_channel *newchannel,
- error_free_info:
- 	kfree(open_info);
- error_free_gpadl:
--	vmbus_teardown_gpadl(newchannel, newchannel->ringbuffer_gpadlhandle);
-+	vmbus_teardown_gpadl(newchannel, newchannel->ringbuffer_gpadlhandle,
-+			     page_address(newchannel->ringbuffer_page),
-+			     newchannel->ringbuffer_pagecount << PAGE_SHIFT);
- 	newchannel->ringbuffer_gpadlhandle = 0;
- error_clean_ring:
- 	hv_ringbuffer_cleanup(&newchannel->outbound);
-@@ -740,7 +780,8 @@ EXPORT_SYMBOL_GPL(vmbus_open);
- /*
-  * vmbus_teardown_gpadl -Teardown the specified GPADL handle
-  */
--int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)
-+int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle,
-+			 void *kbuffer, u32 size)
- {
- 	struct vmbus_channel_gpadl_teardown *msg;
- 	struct vmbus_channel_msginfo *info;
-@@ -793,6 +834,10 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)
- 	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
- 
- 	kfree(info);
-+
-+	if (hv_set_mem_host_visibility(kbuffer, size, VMBUS_PAGE_NOT_VISIBLE))
-+		pr_warn("Fail to set mem host visibility.\n");
-+
- 	return ret;
- }
- EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl);
-@@ -869,7 +914,9 @@ static int vmbus_close_internal(struct vmbus_channel *channel)
- 	/* Tear down the gpadl for the channel's ring buffer */
- 	else if (channel->ringbuffer_gpadlhandle) {
- 		ret = vmbus_teardown_gpadl(channel,
--					   channel->ringbuffer_gpadlhandle);
-+					   channel->ringbuffer_gpadlhandle,
-+					   page_address(channel->ringbuffer_page),
-+					   channel->ringbuffer_pagecount << PAGE_SHIFT);
- 		if (ret) {
- 			pr_err("Close failed: teardown gpadl return %d\n", ret);
- 			/*
-diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
-index 2a87cfa27ac0..b3a43c4ec8ab 100644
---- a/drivers/net/hyperv/hyperv_net.h
-+++ b/drivers/net/hyperv/hyperv_net.h
-@@ -1034,6 +1034,7 @@ struct netvsc_device {
- 
- 	/* Send buffer allocated by us */
- 	void *send_buf;
-+	u32 send_buf_size;
- 	u32 send_buf_gpadl_handle;
- 	u32 send_section_cnt;
- 	u32 send_section_size;
-diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
-index bb72c7578330..08d73401bb28 100644
---- a/drivers/net/hyperv/netvsc.c
-+++ b/drivers/net/hyperv/netvsc.c
-@@ -245,7 +245,9 @@ static void netvsc_teardown_recv_gpadl(struct hv_device *device,
- 
- 	if (net_device->recv_buf_gpadl_handle) {
- 		ret = vmbus_teardown_gpadl(device->channel,
--					   net_device->recv_buf_gpadl_handle);
-+					   net_device->recv_buf_gpadl_handle,
-+					   net_device->recv_buf,
-+					   net_device->recv_buf_size);
- 
- 		/* If we failed here, we might as well return and have a leak
- 		 * rather than continue and a bugchk
-@@ -267,7 +269,9 @@ static void netvsc_teardown_send_gpadl(struct hv_device *device,
- 
- 	if (net_device->send_buf_gpadl_handle) {
- 		ret = vmbus_teardown_gpadl(device->channel,
--					   net_device->send_buf_gpadl_handle);
-+					   net_device->send_buf_gpadl_handle,
-+					   net_device->send_buf,
-+					   net_device->send_buf_size);
- 
- 		/* If we failed here, we might as well return and have a leak
- 		 * rather than continue and a bugchk
-@@ -419,6 +423,7 @@ static int netvsc_init_buf(struct hv_device *device,
- 		ret = -ENOMEM;
- 		goto cleanup;
- 	}
-+	net_device->send_buf_size = buf_size;
- 
- 	/* Establish the gpadl handle for this buffer on this
- 	 * channel.  Note: This call uses the vmbus connection rather
-diff --git a/drivers/uio/uio_hv_generic.c b/drivers/uio/uio_hv_generic.c
-index 813a7bee5139..c8d4704fc90c 100644
---- a/drivers/uio/uio_hv_generic.c
-+++ b/drivers/uio/uio_hv_generic.c
-@@ -181,13 +181,15 @@ static void
- hv_uio_cleanup(struct hv_device *dev, struct hv_uio_private_data *pdata)
- {
- 	if (pdata->send_gpadl) {
--		vmbus_teardown_gpadl(dev->channel, pdata->send_gpadl);
-+		vmbus_teardown_gpadl(dev->channel, pdata->send_gpadl,
-+				     pdata->send_buf, SEND_BUFFER_SIZE);
- 		pdata->send_gpadl = 0;
- 		vfree(pdata->send_buf);
- 	}
- 
- 	if (pdata->recv_gpadl) {
--		vmbus_teardown_gpadl(dev->channel, pdata->recv_gpadl);
-+		vmbus_teardown_gpadl(dev->channel, pdata->recv_gpadl,
-+				     pdata->recv_buf, RECV_BUFFER_SIZE);
- 		pdata->recv_gpadl = 0;
- 		vfree(pdata->recv_buf);
- 	}
+@@ -561,4 +566,17 @@ enum hv_interrupt_type {
+ 
+ #include <asm-generic/hyperv-tlfs.h>
+ 
++/* All input parameters should be in single page. */
++#define HV_MAX_MODIFY_GPA_REP_COUNT		\
++	((PAGE_SIZE / sizeof(u64)) - 2)
++
++/* HvCallModifySparseGpaPageHostVisibility hypercall */
++struct hv_gpa_range_for_visibility {
++	u64 partition_id;
++	u32 host_visibility:2;
++	u32 reserved0:30;
++	u32 reserved1;
++	u64 gpa_page_list[HV_MAX_MODIFY_GPA_REP_COUNT];
++} __packed;
++
+ #endif
+diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
+index aeacca7c4da8..2172493dc881 100644
+--- a/arch/x86/include/asm/mshyperv.h
++++ b/arch/x86/include/asm/mshyperv.h
+@@ -194,7 +194,8 @@ struct irq_domain *hv_create_pci_msi_domain(void);
+ int hv_map_ioapic_interrupt(int ioapic_id, bool level, int vcpu, int vector,
+ 		struct hv_interrupt_entry *entry);
+ int hv_unmap_ioapic_interrupt(int ioapic_id, struct hv_interrupt_entry *entry);
+-
++int hv_mark_gpa_visibility(u16 count, const u64 pfn[], u32 visibility);
++int hv_set_mem_enc(unsigned long addr, int numpages, bool enc);
+ #else /* CONFIG_HYPERV */
+ static inline void hyperv_init(void) {}
+ static inline void hyperv_setup_mmu_ops(void) {}
+diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
+index 156cd235659f..6cc83c57383d 100644
+--- a/arch/x86/mm/pat/set_memory.c
++++ b/arch/x86/mm/pat/set_memory.c
+@@ -29,6 +29,8 @@
+ #include <asm/proto.h>
+ #include <asm/memtype.h>
+ #include <asm/set_memory.h>
++#include <asm/hyperv-tlfs.h>
++#include <asm/mshyperv.h>
+ 
+ #include "../mm_internal.h"
+ 
+@@ -1986,7 +1988,9 @@ static int __set_memory_enc_dec(unsigned long addr, int numpages, bool enc)
+ 	int ret;
+ 
+ 	/* Nothing to do if memory encryption is not active */
+-	if (!mem_encrypt_active())
++	if (hv_is_isolation_supported())
++		return hv_set_mem_enc(addr, numpages, enc);
++	else if (!mem_encrypt_active())
+ 		return 0;
+ 
+ 	/* Should not be working on unaligned addresses */
 diff --git a/include/asm-generic/hyperv-tlfs.h b/include/asm-generic/hyperv-tlfs.h
-index 83448e837ded..ad19f4199f90 100644
+index 515c3fb06ab3..8a0219255545 100644
 --- a/include/asm-generic/hyperv-tlfs.h
 +++ b/include/asm-generic/hyperv-tlfs.h
 @@ -158,6 +158,7 @@ struct ms_hyperv_tsc_page {
@@ -299,22 +226,8 @@
  #define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_LIST 0x00b0
 +#define HVCALL_MODIFY_SPARSE_GPA_PAGE_HOST_VISIBILITY 0x00db
  
- #define HV_FLUSH_ALL_PROCESSORS			BIT(0)
- #define HV_FLUSH_ALL_VIRTUAL_ADDRESS_SPACES	BIT(1)
-diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
-index 016fdca20d6e..41cbaa2db567 100644
---- a/include/linux/hyperv.h
-+++ b/include/linux/hyperv.h
-@@ -1183,7 +1183,8 @@ extern int vmbus_establish_gpadl(struct vmbus_channel *channel,
- 				      u32 visibility);
- 
- extern int vmbus_teardown_gpadl(struct vmbus_channel *channel,
--				     u32 gpadl_handle);
-+				u32 gpadl_handle,
-+				void *kbuffer, u32 size);
- 
- void vmbus_reset_channel_cb(struct vmbus_channel *channel);
- 
+ /* Extended hypercalls */
+ #define HV_EXT_CALL_QUERY_CAPABILITIES		0x8001
 -- 
 2.25.1
 
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help