--- 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