Inter-revision diff: patch 5

Comparing v1 (message) to v4 (message)

--- v1
+++ v4
@@ -1,89 +1,34 @@
 From: Tianyu Lan <Tianyu.Lan@microsoft.com>
 
-Hyper-V provides GHCB protocol to write Synthetic Interrupt
-Controller MSR registers in Isolation VM with AMD SEV SNP
-and these registers are emulated by hypervisor directly.
-Hyper-V requires to write SINTx MSR registers twice. First
-writes MSR via GHCB page to communicate with hypervisor
-and then writes wrmsr instruction to talk with paravisor
-which runs in VMPL0. Guest OS ID MSR also needs to be set
-via GHCB.
+Hyper-V provides ghcb hvcall to handle VMBus
+HVCALL_SIGNAL_EVENT and HVCALL_POST_MESSAGE
+msg in SNP Isolation VM. Add such support.
 
 Signed-off-by: Tianyu Lan <Tianyu.Lan@microsoft.com>
 ---
- arch/x86/hyperv/hv_init.c       |  16 +----
- arch/x86/hyperv/ivm.c           | 114 ++++++++++++++++++++++++++++++
- arch/x86/include/asm/mshyperv.h |  78 +++++++++++++++++++-
- arch/x86/include/asm/sev.h      |   4 ++
- arch/x86/kernel/cpu/mshyperv.c  |   3 +
- arch/x86/kernel/sev-shared.c    |  21 ++++--
- drivers/hv/hv.c                 | 121 ++++++++++++++++++++++----------
- include/asm-generic/mshyperv.h  |  12 +++-
- 8 files changed, 307 insertions(+), 62 deletions(-)
+ arch/x86/hyperv/ivm.c           | 42 +++++++++++++++++++++++++++++++++
+ arch/x86/include/asm/mshyperv.h |  1 +
+ drivers/hv/connection.c         |  6 ++++-
+ drivers/hv/hv.c                 |  8 ++++++-
+ include/asm-generic/mshyperv.h  | 29 +++++++++++++++++++++++
+ 5 files changed, 84 insertions(+), 2 deletions(-)
 
-diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
-index ee449c076ef4..b99f6b3930b7 100644
---- a/arch/x86/hyperv/hv_init.c
-+++ b/arch/x86/hyperv/hv_init.c
-@@ -392,7 +392,7 @@ void __init hyperv_init(void)
- 		goto clean_guest_os_id;
- 
- 	if (hv_isolation_type_snp()) {
--		ms_hyperv.ghcb_base = alloc_percpu(void *);
-+		ms_hyperv.ghcb_base = alloc_percpu(union hv_ghcb __percpu *);
- 		if (!ms_hyperv.ghcb_base)
- 			goto clean_guest_os_id;
- 
-@@ -485,6 +485,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,
-@@ -558,16 +559,3 @@ bool hv_is_hyperv_initialized(void)
- 	return hypercall_msr.enable;
- }
- EXPORT_SYMBOL_GPL(hv_is_hyperv_initialized);
--
--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;
--}
 diff --git a/arch/x86/hyperv/ivm.c b/arch/x86/hyperv/ivm.c
-index 24a58795abd8..9c30d5bb7b64 100644
+index c7b54631ca0d..8a6f4e9e3d6c 100644
 --- a/arch/x86/hyperv/ivm.c
 +++ b/arch/x86/hyperv/ivm.c
-@@ -6,6 +6,8 @@
-  *  Tianyu Lan <Tianyu.Lan@microsoft.com>
-  */
- 
-+#include <linux/types.h>
-+#include <linux/bitfield.h>
- #include <linux/hyperv.h>
- #include <linux/types.h>
- #include <linux/bitfield.h>
-@@ -13,6 +15,118 @@
+@@ -15,6 +15,48 @@
  #include <asm/io.h>
  #include <asm/mshyperv.h>
  
-+void hv_ghcb_msr_write(u64 msr, u64 value)
++u64 hv_ghcb_hypercall(u64 control, void *input, void *output, u32 input_size)
 +{
 +	union hv_ghcb *hv_ghcb;
 +	void **ghcb_base;
 +	unsigned long flags;
 +
 +	if (!ms_hyperv.ghcb_base)
-+		return;
++		return -EFAULT;
 +
 +	WARN_ON(in_nmi());
 +
@@ -92,534 +37,122 @@
 +	hv_ghcb = (union hv_ghcb *)*ghcb_base;
 +	if (!hv_ghcb) {
 +		local_irq_restore(flags);
-+		return;
++		return -EFAULT;
 +	}
 +
 +	memset(hv_ghcb, 0x00, HV_HYP_PAGE_SIZE);
++	hv_ghcb->ghcb.protocol_version = 1;
++	hv_ghcb->ghcb.ghcb_usage = 1;
 +
-+	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);
++	hv_ghcb->hypercall.outputgpa = (u64)output;
++	hv_ghcb->hypercall.hypercallinput.asuint64 = 0;
++	hv_ghcb->hypercall.hypercallinput.callcode = control;
 +
-+	if (sev_es_ghcb_hv_call(&hv_ghcb->ghcb, NULL, SVM_EXIT_MSR, 1, 0))
-+		pr_warn("Fail to write msr via ghcb %llx.\n", msr);
++	if (input_size)
++		memcpy(hv_ghcb->hypercall.hypercalldata, input, input_size);
++
++	VMGEXIT();
++
++	hv_ghcb->ghcb.ghcb_usage = 0xffffffff;
++	memset(hv_ghcb->ghcb.save.valid_bitmap, 0,
++	       sizeof(hv_ghcb->ghcb.save.valid_bitmap));
 +
 +	local_irq_restore(flags);
++
++	return hv_ghcb->hypercall.hypercalloutput.callstatus;
 +}
++EXPORT_SYMBOL_GPL(hv_ghcb_hypercall);
 +
-+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;
-+
-+	WARN_ON(in_nmi());
-+
-+	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);
-+
-+	ghcb_set_rcx(&hv_ghcb->ghcb, msr);
-+	if (sev_es_ghcb_hv_call(&hv_ghcb->ghcb, NULL, SVM_EXIT_MSR, 0, 0))
-+		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);
-+
-+/*
-+ * hv_is_isolation_supported - Check system runs in the Hyper-V
-+ * isolation VM.
-+ */
-+bool hv_is_isolation_supported(void)
-+{
-+	return hv_get_isolation_type() != HV_ISOLATION_TYPE_NONE;
-+}
-+
-+DEFINE_STATIC_KEY_FALSE(isolation_type_snp);
-+
-+/*
-+ * hv_isolation_type_snp - Check system runs in the AMD SEV-SNP based
-+ * isolation VM.
-+ */
-+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.
-  *
+ void hv_ghcb_msr_write(u64 msr, u64 value)
+ {
+ 	union hv_ghcb *hv_ghcb;
 diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
-index 68dd207c2603..3c0cafdf7309 100644
+index f9cc3753040a..fe03e3e833ac 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;
+@@ -258,6 +258,7 @@ 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);
++u64 hv_ghcb_hypercall(u64 control, void *input, void *output, u32 input_size);
+ 
+ #define hv_get_synint_state_ghcb(int_num, val)			\
+ 	hv_sint_rdmsrl_ghcb(HV_X64_MSR_SINT0 + int_num, val)
+diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c
+index 311cd005b3be..186fd4c8acd4 100644
+--- a/drivers/hv/connection.c
++++ b/drivers/hv/connection.c
+@@ -445,6 +445,10 @@ void vmbus_set_event(struct vmbus_channel *channel)
+ 
+ 	++channel->sig_events;
+ 
+-	hv_do_fast_hypercall8(HVCALL_SIGNAL_EVENT, channel->sig_event);
++	if (hv_isolation_type_snp())
++		hv_ghcb_hypercall(HVCALL_SIGNAL_EVENT, &channel->sig_event,
++				NULL, sizeof(u64));
++	else
++		hv_do_fast_hypercall8(HVCALL_SIGNAL_EVENT, channel->sig_event);
  }
- 
-+#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);
-@@ -192,6 +249,25 @@ int hv_map_ioapic_interrupt(int ioapic_id, bool level, int vcpu, int vector,
- 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);
-+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) {}
-@@ -208,9 +284,9 @@ static inline int hyperv_flush_guest_mapping_range(u64 as,
- {
- 	return -1;
- }
-+static inline void hv_signal_eom_ghcb(void) { };
- #endif /* CONFIG_HYPERV */
- 
--
- #include <asm-generic/mshyperv.h>
- 
- #endif
-diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
-index fa5cd05d3b5b..4249fde0a30e 100644
---- a/arch/x86/include/asm/sev.h
-+++ b/arch/x86/include/asm/sev.h
-@@ -81,6 +81,10 @@ static __always_inline void sev_es_nmi_complete(void)
- 		__sev_es_nmi_complete();
- }
- extern int __init sev_es_efi_map_ghcbs(pgd_t *pgd);
-+extern enum es_result sev_es_ghcb_hv_call(struct ghcb *ghcb,
-+				   struct es_em_ctxt *ctxt,
-+				   u64 exit_code, u64 exit_info_1,
-+				   u64 exit_info_2);
- #else
- static inline void sev_es_ist_enter(struct pt_regs *regs) { }
- static inline void sev_es_ist_exit(void) { }
-diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
-index 773e84e134b3..46a09cdfa77a 100644
---- a/arch/x86/kernel/cpu/mshyperv.c
-+++ b/arch/x86/kernel/cpu/mshyperv.c
-@@ -332,6 +332,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);
- 	}
- 
- 	if (hv_max_functions_eax >= HYPERV_CPUID_NESTED_FEATURES) {
-diff --git a/arch/x86/kernel/sev-shared.c b/arch/x86/kernel/sev-shared.c
-index 9f90f460a28c..e039e55b9c72 100644
---- a/arch/x86/kernel/sev-shared.c
-+++ b/arch/x86/kernel/sev-shared.c
-@@ -94,10 +94,10 @@ static void vc_finish_insn(struct es_em_ctxt *ctxt)
- 	ctxt->regs->ip += ctxt->insn.length;
- }
- 
--static enum es_result sev_es_ghcb_hv_call(struct ghcb *ghcb,
--					  struct es_em_ctxt *ctxt,
--					  u64 exit_code, u64 exit_info_1,
--					  u64 exit_info_2)
-+enum es_result sev_es_ghcb_hv_call(struct ghcb *ghcb,
-+				   struct es_em_ctxt *ctxt,
-+				   u64 exit_code, u64 exit_info_1,
-+				   u64 exit_info_2)
- {
- 	enum es_result ret;
- 
-@@ -109,7 +109,16 @@ static enum es_result sev_es_ghcb_hv_call(struct ghcb *ghcb,
- 	ghcb_set_sw_exit_info_1(ghcb, exit_info_1);
- 	ghcb_set_sw_exit_info_2(ghcb, exit_info_2);
- 
--	sev_es_wr_ghcb_msr(__pa(ghcb));
-+	/*
-+	 * Hyper-V runs paravisor with SEV. Ghcb page is allocated by
-+	 * paravisor and not needs to be updated in the Linux guest.
-+	 * Otherwise, the ghcb page's PA reported by paravisor is above
-+	 * VTOM. Hyper-V use this function with NULL for ctxt point and
-+	 * skip setting ghcb page in such case.
-+	 */
-+	if (ctxt)
-+		sev_es_wr_ghcb_msr(__pa(ghcb));
-+
- 	VMGEXIT();
- 
- 	if ((ghcb->save.sw_exit_info_1 & 0xffffffff) == 1) {
-@@ -120,7 +129,7 @@ static enum es_result sev_es_ghcb_hv_call(struct ghcb *ghcb,
- 		v = info & SVM_EVTINJ_VEC_MASK;
- 
- 		/* Check if exception information from hypervisor is sane. */
--		if ((info & SVM_EVTINJ_VALID) &&
-+		if (ctxt && (info & SVM_EVTINJ_VALID) &&
- 		    ((v == X86_TRAP_GP) || (v == X86_TRAP_UD)) &&
- 		    ((info & SVM_EVTINJ_TYPE_MASK) == SVM_EVTINJ_TYPE_EXEPT)) {
- 			ctxt->fi.vector = v;
+ EXPORT_SYMBOL_GPL(vmbus_set_event);
 diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
-index e83507f49676..59f7173c4d9f 100644
+index 59f7173c4d9f..e5c9fc467893 100644
 --- a/drivers/hv/hv.c
 +++ b/drivers/hv/hv.c
-@@ -8,6 +8,7 @@
-  */
- #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+@@ -98,7 +98,13 @@ int hv_post_message(union hv_connection_id connection_id,
+ 	aligned_msg->payload_size = payload_size;
+ 	memcpy((void *)aligned_msg->payload, payload, payload_size);
  
-+#include <linux/io.h>
- #include <linux/kernel.h>
- #include <linux/mm.h>
- #include <linux/slab.h>
-@@ -136,17 +137,24 @@ int hv_synic_alloc(void)
- 		tasklet_init(&hv_cpu->msg_dpc,
- 			     vmbus_on_msg_dpc, (unsigned long) hv_cpu);
+-	status = hv_do_hypercall(HVCALL_POST_MESSAGE, aligned_msg, NULL);
++	if (hv_isolation_type_snp())
++		status = hv_ghcb_hypercall(HVCALL_POST_MESSAGE,
++				(void *)aligned_msg, NULL,
++				sizeof(struct hv_input_post_message));
++	else
++		status = hv_do_hypercall(HVCALL_POST_MESSAGE,
++				aligned_msg, NULL);
  
--		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 +181,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(hv_context.hv_numa_map);
-@@ -199,26 +214,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
-+			= memremap(simp.base_simp_gpa << HV_HYP_PAGE_SHIFT,
-+				   HV_HYP_PAGE_SIZE, MEMREMAP_WB);
-+		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 =
-+			memremap(siefp.base_siefp_gpa << HV_HYP_PAGE_SHIFT,
-+				 HV_HYP_PAGE_SIZE, MEMREMAP_WB);
-+
-+		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 +265,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);
- }
- 
- int hv_synic_init(unsigned int cpu)
-@@ -257,37 +287,50 @@ int hv_synic_init(unsigned int cpu)
-  */
- void hv_synic_disable_regs(unsigned int cpu)
- {
-+	struct hv_per_cpu_context *hv_cpu
-+		= per_cpu_ptr(hv_context.cpu_context, cpu);
- 	union hv_synic_sint shared_sint;
- 	union hv_synic_simp simp;
- 	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())
-+		memunmap(hv_cpu->synic_message_page);
-+	else
-+		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())
-+		memunmap(hv_cpu->synic_event_page);
-+	else
-+		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);
+ 	/* Preemption must remain disabled until after the hypercall
+ 	 * so some other thread can't get scheduled onto this cpu and
 diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
-index aa26d24a5ca9..b0cfc25dffaa 100644
+index e6d6886faed1..8f6f283fb5b5 100644
 --- a/include/asm-generic/mshyperv.h
 +++ b/include/asm-generic/mshyperv.h
-@@ -23,9 +23,16 @@
- #include <linux/bitops.h>
- #include <linux/cpumask.h>
- #include <linux/nmi.h>
-+#include <asm/svm.h>
-+#include <asm/sev.h>
- #include <asm/ptrace.h>
-+#include <asm/mshyperv.h>
- #include <asm/hyperv-tlfs.h>
+@@ -30,6 +30,35 @@
  
-+union hv_ghcb {
-+	struct ghcb ghcb;
-+} __packed __aligned(PAGE_SIZE);
-+
+ union hv_ghcb {
+ 	struct ghcb ghcb;
++	struct {
++		u64 hypercalldata[509];
++		u64 outputgpa;
++		union {
++			union {
++				struct {
++					u32 callcode        : 16;
++					u32 isfast          : 1;
++					u32 reserved1       : 14;
++					u32 isnested        : 1;
++					u32 countofelements : 12;
++					u32 reserved2       : 4;
++					u32 repstartindex   : 12;
++					u32 reserved3       : 4;
++				};
++				u64 asuint64;
++			} hypercallinput;
++			union {
++				struct {
++					u16 callstatus;
++					u16 reserved1;
++					u32 elementsprocessed : 12;
++					u32 reserved2         : 20;
++				};
++				u64 asunit64;
++			} hypercalloutput;
++		};
++		u64 reserved2;
++	} hypercall;
+ } __packed __aligned(PAGE_SIZE);
+ 
  struct ms_hyperv_info {
- 	u32 features;
- 	u32 priv_high;
-@@ -45,7 +52,7 @@ struct ms_hyperv_info {
- 			u32 Reserved12 : 20;
- 		};
- 	};
--	void  __percpu **ghcb_base;
-+	union hv_ghcb __percpu **ghcb_base;
- 	u64 shared_gpa_boundary;
- };
- extern struct ms_hyperv_info ms_hyperv;
-@@ -55,6 +62,7 @@ extern void  __percpu  **hyperv_pcpu_output_arg;
- 
- 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)
-@@ -149,7 +157,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();
- 	}
- }
- 
 -- 
 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