Inter-revision diff: patch 4

Comparing v5 (message) to v3 (message)

--- v5
+++ v3
@@ -1,389 +1,546 @@
 From: Tianyu Lan <Tianyu.Lan@microsoft.com>
 
-Mark vmbus ring buffer visible with set_memory_decrypted() when
-establish gpadl handle.
+Hyper-V provides GHCB protocol to write Synthetic Interrupt
+Controller MSR registers and these registers are emulated by
+Hypervisor rather than paravisor in VMPL0.
+
+Hyper-V requests to write SINTx MSR registers twice(once via
+GHCB and once via wrmsr instruction emulated by paravisor including
+the proxy bit 21). Guest OS ID MSR also needs to be set via GHCB.
 
 Signed-off-by: Tianyu Lan <Tianyu.Lan@microsoft.com>
 ---
-Change sincv v4
-	* Change gpadl handle in netvsc and uio driver from u32 to
-	  struct vmbus_gpadl.
-	* Change vmbus_establish_gpadl()'s gpadl_handle parameter
-	  to vmbus_gpadl data structure.
+ arch/x86/hyperv/hv_init.c       |  26 +------
+ arch/x86/hyperv/ivm.c           | 125 ++++++++++++++++++++++++++++++++
+ arch/x86/include/asm/mshyperv.h |  78 +++++++++++++++++++-
+ arch/x86/kernel/cpu/mshyperv.c  |   3 +
+ drivers/hv/hv.c                 | 114 +++++++++++++++++++----------
+ include/asm-generic/mshyperv.h  |   4 +-
+ 6 files changed, 287 insertions(+), 63 deletions(-)
 
-Change since v3:
-	* Change vmbus_teardown_gpadl() parameter and put gpadl handle,
-	  buffer and buffer size in the struct vmbus_gpadl.
----
- drivers/hv/channel.c            | 54 ++++++++++++++++++++++++---------
- drivers/net/hyperv/hyperv_net.h |  5 +--
- drivers/net/hyperv/netvsc.c     | 17 ++++++-----
- drivers/uio/uio_hv_generic.c    | 20 ++++++------
- include/linux/hyperv.h          | 12 ++++++--
- 5 files changed, 71 insertions(+), 37 deletions(-)
-
-diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
-index f3761c73b074..cf419eb1de77 100644
---- a/drivers/hv/channel.c
-+++ b/drivers/hv/channel.c
-@@ -17,6 +17,7 @@
+diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
+index dc74d01cb859..e35a3c1556b8 100644
+--- a/arch/x86/hyperv/hv_init.c
++++ b/arch/x86/hyperv/hv_init.c
+@@ -472,6 +472,9 @@ void __init hyperv_init(void)
+ 
+ 		ghcb_base = (void **)this_cpu_ptr(ms_hyperv.ghcb_base);
+ 		*ghcb_base = ghcb_va;
++
++		/* Hyper-V requires to write guest os id via ghcb in SNP IVM. */
++		hv_ghcb_msr_write(HV_X64_MSR_GUEST_OS_ID, guest_id);
+ 	}
+ 
+ 	rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
+@@ -564,6 +567,7 @@ void hyperv_cleanup(void)
+ 
+ 	/* Reset our OS id */
+ 	wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0);
++	hv_ghcb_msr_write(HV_X64_MSR_GUEST_OS_ID, 0);
+ 
+ 	/*
+ 	 * Reset hypercall page reference before reset the page,
+@@ -645,28 +649,6 @@ bool hv_is_hibernation_supported(void)
+ }
+ EXPORT_SYMBOL_GPL(hv_is_hibernation_supported);
+ 
+-enum hv_isolation_type hv_get_isolation_type(void)
+-{
+-	if (!(ms_hyperv.priv_high & HV_ISOLATION))
+-		return HV_ISOLATION_TYPE_NONE;
+-	return FIELD_GET(HV_ISOLATION_TYPE, ms_hyperv.isolation_config_b);
+-}
+-EXPORT_SYMBOL_GPL(hv_get_isolation_type);
+-
+-bool hv_is_isolation_supported(void)
+-{
+-	return hv_get_isolation_type() != HV_ISOLATION_TYPE_NONE;
+-}
+-EXPORT_SYMBOL_GPL(hv_is_isolation_supported);
+-
+-DEFINE_STATIC_KEY_FALSE(isolation_type_snp);
+-
+-bool hv_isolation_type_snp(void)
+-{
+-	return static_branch_unlikely(&isolation_type_snp);
+-}
+-EXPORT_SYMBOL_GPL(hv_isolation_type_snp);
+-
+ /* Bit mask of the extended capability to query: see HV_EXT_CAPABILITY_xxx */
+ bool hv_query_ext_cap(u64 cap_query)
+ {
+diff --git a/arch/x86/hyperv/ivm.c b/arch/x86/hyperv/ivm.c
+index fad1d3024056..fd6dd804beef 100644
+--- a/arch/x86/hyperv/ivm.c
++++ b/arch/x86/hyperv/ivm.c
+@@ -6,12 +6,137 @@
+  *  Tianyu Lan <Tianyu.Lan@microsoft.com>
+  */
+ 
++#include <linux/types.h>
++#include <linux/bitfield.h>
  #include <linux/hyperv.h>
- #include <linux/uio.h>
- #include <linux/interrupt.h>
-+#include <linux/set_memory.h>
- #include <asm/page.h>
+ #include <linux/types.h>
+ #include <linux/bitfield.h>
+ #include <asm/io.h>
++#include <asm/svm.h>
++#include <asm/sev-es.h>
  #include <asm/mshyperv.h>
  
-@@ -456,7 +457,7 @@ static int create_gpadl_header(enum hv_gpadl_type type, void *kbuffer,
- static int __vmbus_establish_gpadl(struct vmbus_channel *channel,
- 				   enum hv_gpadl_type type, void *kbuffer,
- 				   u32 size, u32 send_offset,
--				   u32 *gpadl_handle)
-+				   struct vmbus_gpadl *gpadl)
++union hv_ghcb {
++	struct ghcb ghcb;
++} __packed __aligned(PAGE_SIZE);
++
++void hv_ghcb_msr_write(u64 msr, u64 value)
++{
++	union hv_ghcb *hv_ghcb;
++	void **ghcb_base;
++	unsigned long flags;
++
++	if (!ms_hyperv.ghcb_base)
++		return;
++
++	local_irq_save(flags);
++	ghcb_base = (void **)this_cpu_ptr(ms_hyperv.ghcb_base);
++	hv_ghcb = (union hv_ghcb *)*ghcb_base;
++	if (!hv_ghcb) {
++		local_irq_restore(flags);
++		return;
++	}
++
++	memset(hv_ghcb, 0x00, HV_HYP_PAGE_SIZE);
++
++	hv_ghcb->ghcb.protocol_version = 1;
++	hv_ghcb->ghcb.ghcb_usage = 0;
++
++	ghcb_set_sw_exit_code(&hv_ghcb->ghcb, SVM_EXIT_MSR);
++	ghcb_set_rcx(&hv_ghcb->ghcb, msr);
++	ghcb_set_rax(&hv_ghcb->ghcb, lower_32_bits(value));
++	ghcb_set_rdx(&hv_ghcb->ghcb, value >> 32);
++	ghcb_set_sw_exit_info_1(&hv_ghcb->ghcb, 1);
++	ghcb_set_sw_exit_info_2(&hv_ghcb->ghcb, 0);
++
++	VMGEXIT();
++
++	if ((hv_ghcb->ghcb.save.sw_exit_info_1 & 0xffffffff) == 1)
++		pr_warn("Fail to write msr via ghcb %llx.\n", msr);
++
++	local_irq_restore(flags);
++}
++
++void hv_ghcb_msr_read(u64 msr, u64 *value)
++{
++	union hv_ghcb *hv_ghcb;
++	void **ghcb_base;
++	unsigned long flags;
++
++	if (!ms_hyperv.ghcb_base)
++		return;
++
++	local_irq_save(flags);
++	ghcb_base = (void **)this_cpu_ptr(ms_hyperv.ghcb_base);
++	hv_ghcb = (union hv_ghcb *)*ghcb_base;
++	if (!hv_ghcb) {
++		local_irq_restore(flags);
++		return;
++	}
++
++	memset(hv_ghcb, 0x00, HV_HYP_PAGE_SIZE);
++	hv_ghcb->ghcb.protocol_version = 1;
++	hv_ghcb->ghcb.ghcb_usage = 0;
++
++	ghcb_set_sw_exit_code(&hv_ghcb->ghcb, SVM_EXIT_MSR);
++	ghcb_set_rcx(&hv_ghcb->ghcb, msr);
++	ghcb_set_sw_exit_info_1(&hv_ghcb->ghcb, 0);
++	ghcb_set_sw_exit_info_2(&hv_ghcb->ghcb, 0);
++
++	VMGEXIT();
++
++	if ((hv_ghcb->ghcb.save.sw_exit_info_1 & 0xffffffff) == 1)
++		pr_warn("Fail to read msr via ghcb %llx.\n", msr);
++	else
++		*value = (u64)lower_32_bits(hv_ghcb->ghcb.save.rax)
++			| ((u64)lower_32_bits(hv_ghcb->ghcb.save.rdx) << 32);
++	local_irq_restore(flags);
++}
++
++void hv_sint_rdmsrl_ghcb(u64 msr, u64 *value)
++{
++	hv_ghcb_msr_read(msr, value);
++}
++EXPORT_SYMBOL_GPL(hv_sint_rdmsrl_ghcb);
++
++void hv_sint_wrmsrl_ghcb(u64 msr, u64 value)
++{
++	hv_ghcb_msr_write(msr, value);
++
++	/* Write proxy bit vua wrmsrl instruction. */
++	if (msr >= HV_X64_MSR_SINT0 && msr <= HV_X64_MSR_SINT15)
++		wrmsrl(msr, value | 1 << 20);
++}
++EXPORT_SYMBOL_GPL(hv_sint_wrmsrl_ghcb);
++
++void hv_signal_eom_ghcb(void)
++{
++	hv_sint_wrmsrl_ghcb(HV_X64_MSR_EOM, 0);
++}
++EXPORT_SYMBOL_GPL(hv_signal_eom_ghcb);
++
++enum hv_isolation_type hv_get_isolation_type(void)
++{
++	if (!(ms_hyperv.priv_high & HV_ISOLATION))
++		return HV_ISOLATION_TYPE_NONE;
++	return FIELD_GET(HV_ISOLATION_TYPE, ms_hyperv.isolation_config_b);
++}
++EXPORT_SYMBOL_GPL(hv_get_isolation_type);
++
++bool hv_is_isolation_supported(void)
++{
++	return hv_get_isolation_type() != HV_ISOLATION_TYPE_NONE;
++}
++EXPORT_SYMBOL_GPL(hv_is_isolation_supported);
++
++DEFINE_STATIC_KEY_FALSE(isolation_type_snp);
++
++bool hv_isolation_type_snp(void)
++{
++	return static_branch_unlikely(&isolation_type_snp);
++}
++EXPORT_SYMBOL_GPL(hv_isolation_type_snp);
++
+ /*
+  * hv_mark_gpa_visibility - Set pages visible to host via hvcall.
+  *
+diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
+index 6af9d55ffe3b..eec7f3357d51 100644
+--- a/arch/x86/include/asm/mshyperv.h
++++ b/arch/x86/include/asm/mshyperv.h
+@@ -30,6 +30,63 @@ static inline u64 hv_get_register(unsigned int reg)
+ 	return value;
+ }
+ 
++#define hv_get_sint_reg(val, reg) {		\
++	if (hv_isolation_type_snp())		\
++		hv_get_##reg##_ghcb(&val);	\
++	else					\
++		rdmsrl(HV_X64_MSR_##reg, val);	\
++	}
++
++#define hv_set_sint_reg(val, reg) {		\
++	if (hv_isolation_type_snp())		\
++		hv_set_##reg##_ghcb(val);	\
++	else					\
++		wrmsrl(HV_X64_MSR_##reg, val);	\
++	}
++
++
++#define hv_get_simp(val) hv_get_sint_reg(val, SIMP)
++#define hv_get_siefp(val) hv_get_sint_reg(val, SIEFP)
++
++#define hv_set_simp(val) hv_set_sint_reg(val, SIMP)
++#define hv_set_siefp(val) hv_set_sint_reg(val, SIEFP)
++
++#define hv_get_synic_state(val) {			\
++	if (hv_isolation_type_snp())			\
++		hv_get_synic_state_ghcb(&val);		\
++	else						\
++		rdmsrl(HV_X64_MSR_SCONTROL, val);	\
++	}
++#define hv_set_synic_state(val) {			\
++	if (hv_isolation_type_snp())			\
++		hv_set_synic_state_ghcb(val);		\
++	else						\
++		wrmsrl(HV_X64_MSR_SCONTROL, val);	\
++	}
++
++#define hv_get_vp_index(index) rdmsrl(HV_X64_MSR_VP_INDEX, index)
++
++#define hv_signal_eom() {			 \
++	if (hv_isolation_type_snp() &&		 \
++	    old_msg_type != HVMSG_TIMER_EXPIRED) \
++		hv_signal_eom_ghcb();		 \
++	else					 \
++		wrmsrl(HV_X64_MSR_EOM, 0);	 \
++	}
++
++#define hv_get_synint_state(int_num, val) {		\
++	if (hv_isolation_type_snp())			\
++		hv_get_synint_state_ghcb(int_num, &val);\
++	else						\
++		rdmsrl(HV_X64_MSR_SINT0 + int_num, val);\
++	}
++#define hv_set_synint_state(int_num, val) {		\
++	if (hv_isolation_type_snp())			\
++		hv_set_synint_state_ghcb(int_num, val);	\
++	else						\
++		wrmsrl(HV_X64_MSR_SINT0 + int_num, val);\
++	}
++
+ #define hv_get_raw_timer() rdtsc_ordered()
+ 
+ void hyperv_vector_handler(struct pt_regs *regs);
+@@ -197,6 +254,25 @@ 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_host_visibility(void *kbuffer, size_t size,
+ 			       enum vmbus_page_visibility visibility);
++void hv_sint_wrmsrl_ghcb(u64 msr, u64 value);
++void hv_sint_rdmsrl_ghcb(u64 msr, u64 *value);
++void hv_signal_eom_ghcb(void);
++void hv_ghcb_msr_write(u64 msr, u64 value);
++void hv_ghcb_msr_read(u64 msr, u64 *value);
++
++#define hv_get_synint_state_ghcb(int_num, val)			\
++	hv_sint_rdmsrl_ghcb(HV_X64_MSR_SINT0 + int_num, val)
++#define hv_set_synint_state_ghcb(int_num, val) \
++	hv_sint_wrmsrl_ghcb(HV_X64_MSR_SINT0 + int_num, val)
++
++#define hv_get_SIMP_ghcb(val) hv_sint_rdmsrl_ghcb(HV_X64_MSR_SIMP, val)
++#define hv_set_SIMP_ghcb(val) hv_sint_wrmsrl_ghcb(HV_X64_MSR_SIMP, val)
++
++#define hv_get_SIEFP_ghcb(val) hv_sint_rdmsrl_ghcb(HV_X64_MSR_SIEFP, val)
++#define hv_set_SIEFP_ghcb(val) hv_sint_wrmsrl_ghcb(HV_X64_MSR_SIEFP, val)
++
++#define hv_get_synic_state_ghcb(val) hv_sint_rdmsrl_ghcb(HV_X64_MSR_SCONTROL, val)
++#define hv_set_synic_state_ghcb(val) hv_sint_wrmsrl_ghcb(HV_X64_MSR_SCONTROL, val)
+ #else /* CONFIG_HYPERV */
+ static inline void hyperv_init(void) {}
+ static inline void hyperv_setup_mmu_ops(void) {}
+@@ -213,9 +289,9 @@ static inline int hyperv_flush_guest_mapping_range(u64 as,
  {
- 	struct vmbus_channel_gpadl_header *gpadlmsg;
- 	struct vmbus_channel_gpadl_body *gpadl_body;
-@@ -474,6 +475,15 @@ 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) {
-+		dev_warn(&channel->device_obj->device,
-+			 "Failed to set host visibility for new GPADL %d.\n",
-+			 ret);
-+		return ret;
-+	}
-+
- 	init_completion(&msginfo->waitevent);
- 	msginfo->waiting_channel = channel;
- 
-@@ -537,7 +547,10 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel,
+ 	return -1;
+ }
++static inline void hv_signal_eom_ghcb(void) { };
+ #endif /* CONFIG_HYPERV */
+ 
+-
+ #include <asm-generic/mshyperv.h>
+ 
+ #endif
+diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
+index d1ca36224657..c19e14ec8eec 100644
+--- a/arch/x86/kernel/cpu/mshyperv.c
++++ b/arch/x86/kernel/cpu/mshyperv.c
+@@ -325,6 +325,9 @@ static void __init ms_hyperv_init_platform(void)
+ 
+ 		pr_info("Hyper-V: Isolation Config: Group A 0x%x, Group B 0x%x\n",
+ 			ms_hyperv.isolation_config_a, ms_hyperv.isolation_config_b);
++
++		if (hv_get_isolation_type() == HV_ISOLATION_TYPE_SNP)
++			static_branch_enable(&isolation_type_snp);
  	}
  
- 	/* At this point, we received the gpadl created msg */
--	*gpadl_handle = gpadlmsg->gpadl;
-+	gpadl->gpadl_handle = gpadlmsg->gpadl;
-+	gpadl->buffer = kbuffer;
-+	gpadl->size = size;
-+
- 
- cleanup:
- 	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
-@@ -549,6 +562,11 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel,
+ 	if (ms_hyperv.hints & HV_X64_ENLIGHTENED_VMCS_RECOMMENDED) {
+diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
+index e83507f49676..28faa8364952 100644
+--- a/drivers/hv/hv.c
++++ b/drivers/hv/hv.c
+@@ -136,17 +136,24 @@ int hv_synic_alloc(void)
+ 		tasklet_init(&hv_cpu->msg_dpc,
+ 			     vmbus_on_msg_dpc, (unsigned long) hv_cpu);
+ 
+-		hv_cpu->synic_message_page =
+-			(void *)get_zeroed_page(GFP_ATOMIC);
+-		if (hv_cpu->synic_message_page == NULL) {
+-			pr_err("Unable to allocate SYNIC message page\n");
+-			goto err;
+-		}
++		/*
++		 * Synic message and event pages are allocated by paravisor.
++		 * Skip these pages allocation here.
++		 */
++		if (!hv_isolation_type_snp()) {
++			hv_cpu->synic_message_page =
++				(void *)get_zeroed_page(GFP_ATOMIC);
++			if (hv_cpu->synic_message_page == NULL) {
++				pr_err("Unable to allocate SYNIC message page\n");
++				goto err;
++			}
+ 
+-		hv_cpu->synic_event_page = (void *)get_zeroed_page(GFP_ATOMIC);
+-		if (hv_cpu->synic_event_page == NULL) {
+-			pr_err("Unable to allocate SYNIC event page\n");
+-			goto err;
++			hv_cpu->synic_event_page =
++				(void *)get_zeroed_page(GFP_ATOMIC);
++			if (hv_cpu->synic_event_page == NULL) {
++				pr_err("Unable to allocate SYNIC event page\n");
++				goto err;
++			}
+ 		}
+ 
+ 		hv_cpu->post_msg_page = (void *)get_zeroed_page(GFP_ATOMIC);
+@@ -173,10 +180,17 @@ void hv_synic_free(void)
+ 	for_each_present_cpu(cpu) {
+ 		struct hv_per_cpu_context *hv_cpu
+ 			= per_cpu_ptr(hv_context.cpu_context, cpu);
++		free_page((unsigned long)hv_cpu->post_msg_page);
++
++		/*
++		 * Synic message and event pages are allocated by paravisor.
++		 * Skip free these pages here.
++		 */
++		if (hv_isolation_type_snp())
++			continue;
+ 
+ 		free_page((unsigned long)hv_cpu->synic_event_page);
+ 		free_page((unsigned long)hv_cpu->synic_message_page);
+-		free_page((unsigned long)hv_cpu->post_msg_page);
  	}
  
- 	kfree(msginfo);
-+
-+	if (ret)
-+		set_memory_encrypted((unsigned long)kbuffer,
-+				     HVPFN_UP(size));
-+
- 	return ret;
+ 	kfree(hv_context.hv_numa_map);
+@@ -199,26 +213,43 @@ void hv_synic_enable_regs(unsigned int cpu)
+ 	union hv_synic_scontrol sctrl;
+ 
+ 	/* Setup the Synic's message page */
+-	simp.as_uint64 = hv_get_register(HV_REGISTER_SIMP);
++	hv_get_simp(simp.as_uint64);
+ 	simp.simp_enabled = 1;
+-	simp.base_simp_gpa = virt_to_phys(hv_cpu->synic_message_page)
+-		>> HV_HYP_PAGE_SHIFT;
+ 
+-	hv_set_register(HV_REGISTER_SIMP, simp.as_uint64);
++	if (hv_isolation_type_snp()) {
++		hv_cpu->synic_message_page
++			= ioremap_cache(simp.base_simp_gpa << HV_HYP_PAGE_SHIFT,
++					HV_HYP_PAGE_SIZE);
++		if (!hv_cpu->synic_message_page)
++			pr_err("Fail to map syinc message page.\n");
++	} else {
++		simp.base_simp_gpa = virt_to_phys(hv_cpu->synic_message_page)
++			>> HV_HYP_PAGE_SHIFT;
++	}
++
++	hv_set_simp(simp.as_uint64);
+ 
+ 	/* Setup the Synic's event page */
+-	siefp.as_uint64 = hv_get_register(HV_REGISTER_SIEFP);
++	hv_get_siefp(siefp.as_uint64);
+ 	siefp.siefp_enabled = 1;
+-	siefp.base_siefp_gpa = virt_to_phys(hv_cpu->synic_event_page)
+-		>> HV_HYP_PAGE_SHIFT;
+ 
+-	hv_set_register(HV_REGISTER_SIEFP, siefp.as_uint64);
++	if (hv_isolation_type_snp()) {
++		hv_cpu->synic_event_page =
++			ioremap_cache(siefp.base_siefp_gpa << HV_HYP_PAGE_SHIFT,
++				      HV_HYP_PAGE_SIZE);
++
++		if (!hv_cpu->synic_event_page)
++			pr_err("Fail to map syinc event page.\n");
++	} else {
++		siefp.base_siefp_gpa = virt_to_phys(hv_cpu->synic_event_page)
++			>> HV_HYP_PAGE_SHIFT;
++	}
++	hv_set_siefp(siefp.as_uint64);
+ 
+ 	/* Setup the shared SINT. */
+ 	if (vmbus_irq != -1)
+ 		enable_percpu_irq(vmbus_irq, 0);
+-	shared_sint.as_uint64 = hv_get_register(HV_REGISTER_SINT0 +
+-					VMBUS_MESSAGE_SINT);
++	hv_get_synint_state(VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
+ 
+ 	shared_sint.vector = vmbus_interrupt;
+ 	shared_sint.masked = false;
+@@ -233,14 +264,12 @@ void hv_synic_enable_regs(unsigned int cpu)
+ #else
+ 	shared_sint.auto_eoi = 0;
+ #endif
+-	hv_set_register(HV_REGISTER_SINT0 + VMBUS_MESSAGE_SINT,
+-				shared_sint.as_uint64);
++	hv_set_synint_state(VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
+ 
+ 	/* Enable the global synic bit */
+-	sctrl.as_uint64 = hv_get_register(HV_REGISTER_SCONTROL);
++	hv_get_synic_state(sctrl.as_uint64);
+ 	sctrl.enable = 1;
+-
+-	hv_set_register(HV_REGISTER_SCONTROL, sctrl.as_uint64);
++	hv_set_synic_state(sctrl.as_uint64);
  }
  
-@@ -561,10 +579,10 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel,
-  * @gpadl_handle: some funky thing
-  */
- int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
--			  u32 size, u32 *gpadl_handle)
-+			  u32 size, struct vmbus_gpadl *gpadl)
- {
- 	return __vmbus_establish_gpadl(channel, HV_GPADL_BUFFER, kbuffer, size,
--				       0U, gpadl_handle);
-+				       0U, gpadl);
- }
- EXPORT_SYMBOL_GPL(vmbus_establish_gpadl);
- 
-@@ -639,6 +657,7 @@ static int __vmbus_open(struct vmbus_channel *newchannel,
- 	struct vmbus_channel_open_channel *open_msg;
- 	struct vmbus_channel_msginfo *open_info = NULL;
- 	struct page *page = newchannel->ringbuffer_page;
-+	struct vmbus_gpadl gpadl;
- 	u32 send_pages, recv_pages;
- 	unsigned long flags;
- 	int err;
-@@ -675,7 +694,7 @@ static int __vmbus_open(struct vmbus_channel *newchannel,
- 		goto error_clean_ring;
- 
- 	/* Establish the gpadl for the ring buffer */
--	newchannel->ringbuffer_gpadlhandle = 0;
-+	newchannel->ringbuffer_gpadlhandle.gpadl_handle = 0;
- 
- 	err = __vmbus_establish_gpadl(newchannel, HV_GPADL_RING,
- 				      page_address(newchannel->ringbuffer_page),
-@@ -701,7 +720,8 @@ static int __vmbus_open(struct vmbus_channel *newchannel,
- 	open_msg->header.msgtype = CHANNELMSG_OPENCHANNEL;
- 	open_msg->openid = newchannel->offermsg.child_relid;
- 	open_msg->child_relid = newchannel->offermsg.child_relid;
--	open_msg->ringbuffer_gpadlhandle = newchannel->ringbuffer_gpadlhandle;
-+	open_msg->ringbuffer_gpadlhandle
-+		= newchannel->ringbuffer_gpadlhandle.gpadl_handle;
- 	/*
- 	 * The unit of ->downstream_ringbuffer_pageoffset is HV_HYP_PAGE and
- 	 * the unit of ->ringbuffer_send_offset (i.e. send_pages) is PAGE, so
-@@ -759,8 +779,8 @@ static int __vmbus_open(struct vmbus_channel *newchannel,
- error_free_info:
- 	kfree(open_info);
- error_free_gpadl:
--	vmbus_teardown_gpadl(newchannel, newchannel->ringbuffer_gpadlhandle);
--	newchannel->ringbuffer_gpadlhandle = 0;
-+	vmbus_teardown_gpadl(newchannel, &newchannel->ringbuffer_gpadlhandle);
-+	newchannel->ringbuffer_gpadlhandle.gpadl_handle = 0;
- error_clean_ring:
- 	hv_ringbuffer_cleanup(&newchannel->outbound);
- 	hv_ringbuffer_cleanup(&newchannel->inbound);
-@@ -806,7 +826,7 @@ 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, struct vmbus_gpadl *gpadl)
- {
- 	struct vmbus_channel_gpadl_teardown *msg;
- 	struct vmbus_channel_msginfo *info;
-@@ -825,7 +845,7 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)
- 
- 	msg->header.msgtype = CHANNELMSG_GPADL_TEARDOWN;
- 	msg->child_relid = channel->offermsg.child_relid;
--	msg->gpadl = gpadl_handle;
-+	msg->gpadl = gpadl->gpadl_handle;
- 
- 	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
- 	list_add_tail(&info->msglistentry,
-@@ -859,6 +879,12 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)
- 	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
- 
- 	kfree(info);
-+
-+	ret = set_memory_encrypted((unsigned long)gpadl->buffer,
-+				   HVPFN_UP(gpadl->size));
-+	if (ret)
-+		pr_warn("Fail to set mem host visibility in GPADL teardown %d.\n", ret);
-+
- 	return ret;
- }
- EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl);
-@@ -896,6 +922,7 @@ void vmbus_reset_channel_cb(struct vmbus_channel *channel)
- static int vmbus_close_internal(struct vmbus_channel *channel)
- {
- 	struct vmbus_channel_close_channel *msg;
-+	struct vmbus_gpadl gpadl;
- 	int ret;
- 
- 	vmbus_reset_channel_cb(channel);
-@@ -933,9 +960,8 @@ 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);
-+	else if (channel->ringbuffer_gpadlhandle.gpadl_handle) {
-+		ret = vmbus_teardown_gpadl(channel, &channel->ringbuffer_gpadlhandle);
- 		if (ret) {
- 			pr_err("Close failed: teardown gpadl return %d\n", ret);
- 			/*
-@@ -944,7 +970,7 @@ static int vmbus_close_internal(struct vmbus_channel *channel)
- 			 */
- 		}
- 
--		channel->ringbuffer_gpadlhandle = 0;
-+		channel->ringbuffer_gpadlhandle.gpadl_handle = 0;
- 	}
- 
- 	if (!ret)
-diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
-index bc48855dff10..315278a7cf88 100644
---- a/drivers/net/hyperv/hyperv_net.h
-+++ b/drivers/net/hyperv/hyperv_net.h
-@@ -1075,14 +1075,15 @@ struct netvsc_device {
- 	/* Receive buffer allocated by us but manages by NetVSP */
- 	void *recv_buf;
- 	u32 recv_buf_size; /* allocated bytes */
--	u32 recv_buf_gpadl_handle;
-+	struct vmbus_gpadl recv_buf_gpadl_handle;
- 	u32 recv_section_cnt;
- 	u32 recv_section_size;
- 	u32 recv_completion_cnt;
- 
- 	/* Send buffer allocated by us */
- 	void *send_buf;
--	u32 send_buf_gpadl_handle;
-+	u32 send_buf_size;
-+	struct vmbus_gpadl send_buf_gpadl_handle;
- 	u32 send_section_cnt;
- 	u32 send_section_size;
- 	unsigned long *send_section_map;
-diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
-index 7bd935412853..1f87e570ed2b 100644
---- a/drivers/net/hyperv/netvsc.c
-+++ b/drivers/net/hyperv/netvsc.c
-@@ -278,9 +278,9 @@ static void netvsc_teardown_recv_gpadl(struct hv_device *device,
- {
- 	int ret;
- 
--	if (net_device->recv_buf_gpadl_handle) {
-+	if (net_device->recv_buf_gpadl_handle.gpadl_handle) {
- 		ret = vmbus_teardown_gpadl(device->channel,
--					   net_device->recv_buf_gpadl_handle);
-+					   &net_device->recv_buf_gpadl_handle);
- 
- 		/* If we failed here, we might as well return and have a leak
- 		 * rather than continue and a bugchk
-@@ -290,7 +290,7 @@ static void netvsc_teardown_recv_gpadl(struct hv_device *device,
- 				   "unable to teardown receive buffer's gpadl\n");
- 			return;
- 		}
--		net_device->recv_buf_gpadl_handle = 0;
-+		net_device->recv_buf_gpadl_handle.gpadl_handle = 0;
+ int hv_synic_init(unsigned int cpu)
+@@ -262,32 +291,39 @@ void hv_synic_disable_regs(unsigned int cpu)
+ 	union hv_synic_siefp siefp;
+ 	union hv_synic_scontrol sctrl;
+ 
+-	shared_sint.as_uint64 = hv_get_register(HV_REGISTER_SINT0 +
+-					VMBUS_MESSAGE_SINT);
+-
++	hv_get_synint_state(VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
+ 	shared_sint.masked = 1;
++	hv_set_synint_state(VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
++
+ 
+ 	/* Need to correctly cleanup in the case of SMP!!! */
+ 	/* Disable the interrupt */
+-	hv_set_register(HV_REGISTER_SINT0 + VMBUS_MESSAGE_SINT,
+-				shared_sint.as_uint64);
++	hv_get_simp(simp.as_uint64);
+ 
+-	simp.as_uint64 = hv_get_register(HV_REGISTER_SIMP);
++	/*
++	 * In Isolation VM, sim and sief pages are allocated by
++	 * paravisor. These pages also will be used by kdump
++	 * kernel. So just reset enable bit here and keep page
++	 * addresses.
++	 */
+ 	simp.simp_enabled = 0;
+-	simp.base_simp_gpa = 0;
++	if (!hv_isolation_type_snp())
++		simp.base_simp_gpa = 0;
+ 
+-	hv_set_register(HV_REGISTER_SIMP, simp.as_uint64);
++	hv_set_simp(simp.as_uint64);
+ 
+-	siefp.as_uint64 = hv_get_register(HV_REGISTER_SIEFP);
++	hv_get_siefp(siefp.as_uint64);
+ 	siefp.siefp_enabled = 0;
+-	siefp.base_siefp_gpa = 0;
+ 
+-	hv_set_register(HV_REGISTER_SIEFP, siefp.as_uint64);
++	if (!hv_isolation_type_snp())
++		siefp.base_siefp_gpa = 0;
++
++	hv_set_siefp(siefp.as_uint64);
+ 
+ 	/* Disable the global synic bit */
+-	sctrl.as_uint64 = hv_get_register(HV_REGISTER_SCONTROL);
++	hv_get_synic_state(sctrl.as_uint64);
+ 	sctrl.enable = 0;
+-	hv_set_register(HV_REGISTER_SCONTROL, sctrl.as_uint64);
++	hv_set_synic_state(sctrl.as_uint64);
+ 
+ 	if (vmbus_irq != -1)
+ 		disable_percpu_irq(vmbus_irq);
+diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
+index 2914e27b0429..63e0de2a7c54 100644
+--- a/include/asm-generic/mshyperv.h
++++ b/include/asm-generic/mshyperv.h
+@@ -23,6 +23,7 @@
+ #include <linux/bitops.h>
+ #include <linux/cpumask.h>
+ #include <asm/ptrace.h>
++#include <asm/mshyperv.h>
+ #include <asm/hyperv-tlfs.h>
+ 
+ struct ms_hyperv_info {
+@@ -51,6 +52,7 @@ extern struct ms_hyperv_info ms_hyperv;
+ 
+ extern u64 hv_do_hypercall(u64 control, void *inputaddr, void *outputaddr);
+ extern u64 hv_do_fast_hypercall8(u16 control, u64 input8);
++extern bool hv_isolation_type_snp(void);
+ 
+ /* Helper functions that provide a consistent pattern for checking Hyper-V hypercall status. */
+ static inline int hv_result(u64 status)
+@@ -145,7 +147,7 @@ static inline void vmbus_signal_eom(struct hv_message *msg, u32 old_msg_type)
+ 		 * possibly deliver another msg from the
+ 		 * hypervisor
+ 		 */
+-		hv_set_register(HV_REGISTER_EOM, 0);
++		hv_signal_eom();
  	}
  }
- 
-@@ -300,9 +300,9 @@ static void netvsc_teardown_send_gpadl(struct hv_device *device,
- {
- 	int ret;
- 
--	if (net_device->send_buf_gpadl_handle) {
-+	if (net_device->send_buf_gpadl_handle.gpadl_handle) {
- 		ret = vmbus_teardown_gpadl(device->channel,
--					   net_device->send_buf_gpadl_handle);
-+					   &net_device->send_buf_gpadl_handle);
- 
- 		/* If we failed here, we might as well return and have a leak
- 		 * rather than continue and a bugchk
-@@ -312,7 +312,7 @@ static void netvsc_teardown_send_gpadl(struct hv_device *device,
- 				   "unable to teardown send buffer's gpadl\n");
- 			return;
- 		}
--		net_device->send_buf_gpadl_handle = 0;
-+		net_device->send_buf_gpadl_handle.gpadl_handle = 0;
- 	}
- }
- 
-@@ -380,7 +380,7 @@ static int netvsc_init_buf(struct hv_device *device,
- 	memset(init_packet, 0, sizeof(struct nvsp_message));
- 	init_packet->hdr.msg_type = NVSP_MSG1_TYPE_SEND_RECV_BUF;
- 	init_packet->msg.v1_msg.send_recv_buf.
--		gpadl_handle = net_device->recv_buf_gpadl_handle;
-+		gpadl_handle = net_device->recv_buf_gpadl_handle.gpadl_handle;
- 	init_packet->msg.v1_msg.
- 		send_recv_buf.id = NETVSC_RECEIVE_BUFFER_ID;
- 
-@@ -463,6 +463,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
-@@ -482,7 +483,7 @@ static int netvsc_init_buf(struct hv_device *device,
- 	memset(init_packet, 0, sizeof(struct nvsp_message));
- 	init_packet->hdr.msg_type = NVSP_MSG1_TYPE_SEND_SEND_BUF;
- 	init_packet->msg.v1_msg.send_send_buf.gpadl_handle =
--		net_device->send_buf_gpadl_handle;
-+		net_device->send_buf_gpadl_handle.gpadl_handle;
- 	init_packet->msg.v1_msg.send_send_buf.id = NETVSC_SEND_BUFFER_ID;
- 
- 	trace_nvsp_send(ndev, init_packet);
-diff --git a/drivers/uio/uio_hv_generic.c b/drivers/uio/uio_hv_generic.c
-index 652fe2547587..548243dcd895 100644
---- a/drivers/uio/uio_hv_generic.c
-+++ b/drivers/uio/uio_hv_generic.c
-@@ -58,11 +58,11 @@ struct hv_uio_private_data {
- 	atomic_t refcnt;
- 
- 	void	*recv_buf;
--	u32	recv_gpadl;
-+	struct vmbus_gpadl recv_gpadl;
- 	char	recv_name[32];	/* "recv_4294967295" */
- 
- 	void	*send_buf;
--	u32	send_gpadl;
-+	struct vmbus_gpadl send_gpadl;
- 	char	send_name[32];
- };
- 
-@@ -179,15 +179,15 @@ hv_uio_new_channel(struct vmbus_channel *new_sc)
- 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);
--		pdata->send_gpadl = 0;
-+	if (pdata->send_gpadl.gpadl_handle) {
-+		vmbus_teardown_gpadl(dev->channel, &pdata->send_gpadl);
-+		pdata->send_gpadl.gpadl_handle = 0;
- 		vfree(pdata->send_buf);
- 	}
- 
--	if (pdata->recv_gpadl) {
--		vmbus_teardown_gpadl(dev->channel, pdata->recv_gpadl);
--		pdata->recv_gpadl = 0;
-+	if (pdata->recv_gpadl.gpadl_handle) {
-+		vmbus_teardown_gpadl(dev->channel, &pdata->recv_gpadl);
-+		pdata->recv_gpadl.gpadl_handle = 0;
- 		vfree(pdata->recv_buf);
- 	}
- }
-@@ -303,7 +303,7 @@ hv_uio_probe(struct hv_device *dev,
- 
- 	/* put Global Physical Address Label in name */
- 	snprintf(pdata->recv_name, sizeof(pdata->recv_name),
--		 "recv:%u", pdata->recv_gpadl);
-+		 "recv:%u", pdata->recv_gpadl.gpadl_handle);
- 	pdata->info.mem[RECV_BUF_MAP].name = pdata->recv_name;
- 	pdata->info.mem[RECV_BUF_MAP].addr
- 		= (uintptr_t)pdata->recv_buf;
-@@ -324,7 +324,7 @@ hv_uio_probe(struct hv_device *dev,
- 	}
- 
- 	snprintf(pdata->send_name, sizeof(pdata->send_name),
--		 "send:%u", pdata->send_gpadl);
-+		 "send:%u", pdata->send_gpadl.gpadl_handle);
- 	pdata->info.mem[SEND_BUF_MAP].name = pdata->send_name;
- 	pdata->info.mem[SEND_BUF_MAP].addr
- 		= (uintptr_t)pdata->send_buf;
-diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
-index ddc8713ce57b..a9e0bc3b1511 100644
---- a/include/linux/hyperv.h
-+++ b/include/linux/hyperv.h
-@@ -803,6 +803,12 @@ struct vmbus_device {
- 
- #define VMBUS_DEFAULT_MAX_PKT_SIZE 4096
- 
-+struct vmbus_gpadl {
-+	u32 gpadl_handle;
-+	u32 size;
-+	void *buffer;
-+};
-+
- struct vmbus_channel {
- 	struct list_head listentry;
- 
-@@ -822,7 +828,7 @@ struct vmbus_channel {
- 	bool rescind_ref; /* got rescind msg, got channel reference */
- 	struct completion rescind_event;
- 
--	u32 ringbuffer_gpadlhandle;
-+	struct vmbus_gpadl ringbuffer_gpadlhandle;
- 
- 	/* Allocated memory for ring buffer */
- 	struct page *ringbuffer_page;
-@@ -1192,10 +1198,10 @@ extern int vmbus_sendpacket_mpb_desc(struct vmbus_channel *channel,
- extern int vmbus_establish_gpadl(struct vmbus_channel *channel,
- 				      void *kbuffer,
- 				      u32 size,
--				      u32 *gpadl_handle);
-+				      struct vmbus_gpadl *gpadl);
- 
- extern int vmbus_teardown_gpadl(struct vmbus_channel *channel,
--				     u32 gpadl_handle);
-+				     struct vmbus_gpadl *gpadl);
- 
- void vmbus_reset_channel_cb(struct vmbus_channel *channel);
  
 -- 
 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