--- vrfc
+++ v4
@@ -1,170 +1,133 @@
From: Tianyu Lan <Tianyu.Lan@microsoft.com>
-Hyper-V exposes GHCB page via SEV ES GHCB MSR for SNP guest
-to communicate with hypervisor. Map GHCB page for all
-cpus to read/write MSR register and submit hvcall request
-via GHCB. Hyper-V also exposes shared memory boundary via
-cpuid HYPERV_CPUID_ISOLATION_CONFIG and store it in the
-shared_gpa_boundary of ms_hyperv struct. This prepares
-to share memory with host for SNP guest.
+Mark vmbus ring buffer visible with set_memory_decrypted() when
+establish gpadl handle.
Signed-off-by: Tianyu Lan <Tianyu.Lan@microsoft.com>
---
- arch/x86/hyperv/hv_init.c | 52 +++++++++++++++++++++++++++++++---
- arch/x86/kernel/cpu/mshyperv.c | 2 ++
- include/asm-generic/mshyperv.h | 14 ++++++++-
- 3 files changed, 63 insertions(+), 5 deletions(-)
+ drivers/hv/channel.c | 38 ++++++++++++++++++++++++++++++++++++--
+ include/linux/hyperv.h | 10 ++++++++++
+ 2 files changed, 46 insertions(+), 2 deletions(-)
-diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
-index 0db5137d5b81..90e65fbf4c58 100644
---- a/arch/x86/hyperv/hv_init.c
-+++ b/arch/x86/hyperv/hv_init.c
-@@ -82,6 +82,9 @@ static int hv_cpu_init(unsigned int cpu)
- struct hv_vp_assist_page **hvp = &hv_vp_assist_page[smp_processor_id()];
- void **input_arg;
- struct page *pg;
-+ u64 ghcb_gpa;
-+ void *ghcb_va;
-+ void **ghcb_base;
+diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
+index f3761c73b074..01048bb07082 100644
+--- a/drivers/hv/channel.c
++++ b/drivers/hv/channel.c
+@@ -17,6 +17,7 @@
+ #include <linux/hyperv.h>
+ #include <linux/uio.h>
+ #include <linux/interrupt.h>
++#include <linux/set_memory.h>
+ #include <asm/page.h>
+ #include <asm/mshyperv.h>
- /* hv_cpu_init() can be called with IRQs disabled from hv_resume() */
- pg = alloc_pages(irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL, hv_root_partition ? 1 : 0);
-@@ -128,6 +131,17 @@ static int hv_cpu_init(unsigned int cpu)
- wrmsrl(HV_X64_MSR_VP_ASSIST_PAGE, val);
+@@ -465,7 +466,7 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel,
+ struct list_head *curr;
+ u32 next_gpadl_handle;
+ unsigned long flags;
+- int ret = 0;
++ int ret = 0, index;
+
+ next_gpadl_handle =
+ (atomic_inc_return(&vmbus_connection.next_gpadl_handle) - 1);
+@@ -474,6 +475,13 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel,
+ if (ret)
+ return ret;
+
++ ret = set_memory_decrypted((unsigned long)kbuffer,
++ HVPFN_UP(size));
++ if (ret) {
++ pr_warn("Failed to set host visibility.\n");
++ return ret;
++ }
++
+ init_completion(&msginfo->waitevent);
+ msginfo->waiting_channel = channel;
+
+@@ -539,6 +547,15 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel,
+ /* At this point, we received the gpadl created msg */
+ *gpadl_handle = gpadlmsg->gpadl;
+
++ if (type == HV_GPADL_BUFFER)
++ index = 0;
++ else
++ index = channel->gpadl_range[1].gpadlhandle ? 2 : 1;
++
++ channel->gpadl_range[index].size = size;
++ channel->gpadl_range[index].buffer = kbuffer;
++ channel->gpadl_range[index].gpadlhandle = *gpadl_handle;
++
+ cleanup:
+ spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+ list_del(&msginfo->msglistentry);
+@@ -549,6 +566,11 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel,
}
-+ if (ms_hyperv.ghcb_base) {
-+ rdmsrl(MSR_AMD64_SEV_ES_GHCB, ghcb_gpa);
+ kfree(msginfo);
+
-+ ghcb_va = ioremap_cache(ghcb_gpa, HV_HYP_PAGE_SIZE);
-+ if (!ghcb_va)
-+ return -ENOMEM;
++ if (ret)
++ set_memory_encrypted((unsigned long)kbuffer,
++ HVPFN_UP(size));
+
-+ ghcb_base = (void **)this_cpu_ptr(ms_hyperv.ghcb_base);
-+ *ghcb_base = ghcb_va;
-+ }
-+
- return 0;
+ return ret;
}
-@@ -223,6 +237,7 @@ static int hv_cpu_die(unsigned int cpu)
+@@ -811,7 +833,7 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)
+ struct vmbus_channel_gpadl_teardown *msg;
+ struct vmbus_channel_msginfo *info;
unsigned long flags;
- void **input_arg;
- void *pg;
-+ void **ghcb_va = NULL;
+- int ret;
++ int ret, i;
- local_irq_save(flags);
- input_arg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg);
-@@ -236,6 +251,13 @@ static int hv_cpu_die(unsigned int cpu)
- *output_arg = NULL;
- }
+ info = kzalloc(sizeof(*info) +
+ sizeof(struct vmbus_channel_gpadl_teardown), GFP_KERNEL);
+@@ -859,6 +881,18 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)
+ spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
-+ if (ms_hyperv.ghcb_base) {
-+ ghcb_va = (void **)this_cpu_ptr(ms_hyperv.ghcb_base);
-+ if (*ghcb_va)
-+ iounmap(*ghcb_va);
-+ *ghcb_va = NULL;
-+ }
+ kfree(info);
+
- local_irq_restore(flags);
++ /* Find gpadl buffer virtual address and size. */
++ for (i = 0; i < VMBUS_GPADL_RANGE_COUNT; i++)
++ if (channel->gpadl_range[i].gpadlhandle == gpadl_handle)
++ break;
++
++ if (set_memory_encrypted((unsigned long)channel->gpadl_range[i].buffer,
++ HVPFN_UP(channel->gpadl_range[i].size)))
++ pr_warn("Fail to set mem host visibility.\n");
++
++ channel->gpadl_range[i].gpadlhandle = 0;
++
+ return ret;
+ }
+ EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl);
+diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
+index 2e859d2f9609..06eccaba10c5 100644
+--- a/include/linux/hyperv.h
++++ b/include/linux/hyperv.h
+@@ -809,6 +809,14 @@ struct vmbus_device {
- free_pages((unsigned long)pg, hv_root_partition ? 1 : 0);
-@@ -372,6 +394,9 @@ void __init hyperv_init(void)
- u64 guest_id, required_msrs;
- union hv_x64_msr_hypercall_contents hypercall_msr;
- int cpuhp, i;
-+ u64 ghcb_gpa;
-+ void *ghcb_va;
-+ void **ghcb_base;
+ #define VMBUS_DEFAULT_MAX_PKT_SIZE 4096
- if (x86_hyper_type != X86_HYPER_MS_HYPERV)
- return;
-@@ -432,9 +457,24 @@ void __init hyperv_init(void)
- VMALLOC_END, GFP_KERNEL, PAGE_KERNEL_ROX,
- VM_FLUSH_RESET_PERMS, NUMA_NO_NODE,
- __builtin_return_address(0));
-- if (hv_hypercall_pg == NULL) {
-- wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0);
-- goto remove_cpuhp_state;
-+ if (hv_hypercall_pg == NULL)
-+ goto clean_guest_os_id;
++struct vmbus_gpadl_range {
++ u32 gpadlhandle;
++ u32 size;
++ void *buffer;
++};
+
-+ if (hv_isolation_type_snp()) {
-+ ms_hyperv.ghcb_base = alloc_percpu(void *);
-+ if (!ms_hyperv.ghcb_base)
-+ goto clean_guest_os_id;
++#define VMBUS_GPADL_RANGE_COUNT 3
+
-+ rdmsrl(MSR_AMD64_SEV_ES_GHCB, ghcb_gpa);
-+ ghcb_va = ioremap_cache(ghcb_gpa, HV_HYP_PAGE_SIZE);
-+ if (!ghcb_va) {
-+ free_percpu(ms_hyperv.ghcb_base);
-+ ms_hyperv.ghcb_base = NULL;
-+ goto clean_guest_os_id;
-+ }
-+
-+ ghcb_base = (void **)this_cpu_ptr(ms_hyperv.ghcb_base);
-+ *ghcb_base = ghcb_va;
- }
+ struct vmbus_channel {
+ struct list_head listentry;
- rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
-@@ -499,7 +539,8 @@ void __init hyperv_init(void)
+@@ -829,6 +837,8 @@ struct vmbus_channel {
+ struct completion rescind_event;
- return;
+ u32 ringbuffer_gpadlhandle;
++ /* GPADL_RING and Send/Receive GPADL_BUFFER. */
++ struct vmbus_gpadl_range gpadl_range[VMBUS_GPADL_RANGE_COUNT];
--remove_cpuhp_state:
-+clean_guest_os_id:
-+ wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0);
- cpuhp_remove_state(cpuhp);
- free_vp_assist_page:
- kfree(hv_vp_assist_page);
-@@ -528,6 +569,9 @@ void hyperv_cleanup(void)
- */
- hv_hypercall_pg = NULL;
-
-+ if (ms_hyperv.ghcb_base)
-+ free_percpu(ms_hyperv.ghcb_base);
-+
- /* Reset the hypercall page */
- hypercall_msr.as_uint64 = 0;
- wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
-diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
-index 347c32eac8fd..d6c363456cbf 100644
---- a/arch/x86/kernel/cpu/mshyperv.c
-+++ b/arch/x86/kernel/cpu/mshyperv.c
-@@ -330,6 +330,8 @@ static void __init ms_hyperv_init_platform(void)
- if (ms_hyperv.features_b & HV_ISOLATION) {
- ms_hyperv.isolation_config_a = cpuid_eax(HYPERV_CPUID_ISOLATION_CONFIG);
- ms_hyperv.isolation_config_b = cpuid_ebx(HYPERV_CPUID_ISOLATION_CONFIG);
-+ ms_hyperv.shared_gpa_boundary =
-+ (u64)1 << ms_hyperv.shared_gpa_boundary_bits;
-
- 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);
-diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
-index dff58a3db5d5..ad0e33776668 100644
---- a/include/asm-generic/mshyperv.h
-+++ b/include/asm-generic/mshyperv.h
-@@ -34,7 +34,19 @@ struct ms_hyperv_info {
- u32 max_vp_index;
- u32 max_lp_index;
- u32 isolation_config_a;
-- u32 isolation_config_b;
-+ union
-+ {
-+ u32 isolation_config_b;;
-+ struct {
-+ u32 cvm_type : 4;
-+ u32 Reserved11 : 1;
-+ u32 shared_gpa_boundary_active : 1;
-+ u32 shared_gpa_boundary_bits : 6;
-+ u32 Reserved12 : 20;
-+ };
-+ };
-+ void __percpu **ghcb_base;
-+ u64 shared_gpa_boundary;
- };
- extern struct ms_hyperv_info ms_hyperv;
-
+ /* Allocated memory for ring buffer */
+ struct page *ringbuffer_page;
--
2.25.1