--- v2
+++ v3
@@ -7,80 +7,76 @@
Signed-off-by: Tianyu Lan <Tianyu.Lan@microsoft.com>
---
- arch/x86/hyperv/hv_init.c | 69 +++++++++++++++++++++++++++++++--
- arch/x86/include/asm/mshyperv.h | 2 +
- include/asm-generic/mshyperv.h | 2 +
- 3 files changed, 69 insertions(+), 4 deletions(-)
+ arch/x86/hyperv/hv_init.c | 60 ++++++++++++++++++++++++++++++---
+ arch/x86/include/asm/mshyperv.h | 2 ++
+ include/asm-generic/mshyperv.h | 2 ++
+ 3 files changed, 60 insertions(+), 4 deletions(-)
diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
-index 4a643a85d570..247df301491f 100644
+index bb0ae4b5c00f..dc74d01cb859 100644
--- a/arch/x86/hyperv/hv_init.c
+++ b/arch/x86/hyperv/hv_init.c
-@@ -20,6 +20,7 @@
- #include <linux/kexec.h>
- #include <linux/version.h>
- #include <linux/vmalloc.h>
-+#include <linux/io.h>
- #include <linux/mm.h>
- #include <linux/hyperv.h>
- #include <linux/slab.h>
-@@ -42,6 +43,31 @@ static void *hv_hypercall_pg_saved;
- struct hv_vp_assist_page **hv_vp_assist_page;
- EXPORT_SYMBOL_GPL(hv_vp_assist_page);
-
-+static int hyperv_init_ghcb(void)
-+{
+@@ -60,6 +60,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;
-+
-+ if (!ms_hyperv.ghcb_base)
-+ return -EINVAL;
-+
-+ /*
-+ * GHCB page is allocated by paravisor. The address
-+ * returned by MSR_AMD64_SEV_ES_GHCB is above shared
-+ * ghcb boundary and map it here.
-+ */
-+ rdmsrl(MSR_AMD64_SEV_ES_GHCB, ghcb_gpa);
-+ ghcb_va = memremap(ghcb_gpa, HV_HYP_PAGE_SIZE, MEMREMAP_WB);
-+ if (!ghcb_va)
-+ return -ENOMEM;
-+
-+ ghcb_base = (void **)this_cpu_ptr(ms_hyperv.ghcb_base);
-+ *ghcb_base = ghcb_va;
-+
-+ return 0;
-+}
-+
- static int hv_cpu_init(unsigned int cpu)
- {
- struct hv_vp_assist_page **hvp = &hv_vp_assist_page[smp_processor_id()];
-@@ -75,6 +101,8 @@ static int hv_cpu_init(unsigned int cpu)
+
+ /* 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);
+@@ -106,6 +109,17 @@ static int hv_cpu_init(unsigned int cpu)
wrmsrl(HV_X64_MSR_VP_ASSIST_PAGE, val);
}
-+ hyperv_init_ghcb();
++ if (ms_hyperv.ghcb_base) {
++ rdmsrl(MSR_AMD64_SEV_ES_GHCB, ghcb_gpa);
++
++ ghcb_va = ioremap_cache(ghcb_gpa, HV_HYP_PAGE_SIZE);
++ if (!ghcb_va)
++ return -ENOMEM;
++
++ ghcb_base = (void **)this_cpu_ptr(ms_hyperv.ghcb_base);
++ *ghcb_base = ghcb_va;
++ }
+
return 0;
}
-@@ -167,6 +195,14 @@ static int hv_cpu_die(unsigned int cpu)
- {
- struct hv_reenlightenment_control re_ctrl;
- unsigned int new_cpu;
+@@ -201,6 +215,7 @@ static int hv_cpu_die(unsigned int cpu)
+ unsigned long flags;
+ void **input_arg;
+ void *pg;
+ void **ghcb_va = NULL;
-+
+
+ local_irq_save(flags);
+ input_arg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg);
+@@ -214,6 +229,13 @@ static int hv_cpu_die(unsigned int cpu)
+ *output_arg = NULL;
+ }
+
+ if (ms_hyperv.ghcb_base) {
+ ghcb_va = (void **)this_cpu_ptr(ms_hyperv.ghcb_base);
+ if (*ghcb_va)
-+ memunmap(*ghcb_va);
++ iounmap(*ghcb_va);
+ *ghcb_va = NULL;
+ }
++
+ local_irq_restore(flags);
- hv_common_cpu_die(cpu);
+ free_pages((unsigned long)pg, hv_root_partition ? 1 : 0);
+@@ -369,6 +391,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;
-@@ -340,9 +376,22 @@ void __init hyperv_init(void)
+ if (x86_hyper_type != X86_HYPER_MS_HYPERV)
+ return;
+@@ -429,9 +454,24 @@ void __init hyperv_init(void)
VMALLOC_END, GFP_KERNEL, PAGE_KERNEL_ROX,
VM_FLUSH_RESET_PERMS, NUMA_NO_NODE,
__builtin_return_address(0));
@@ -95,18 +91,20 @@
+ if (!ms_hyperv.ghcb_base)
+ goto clean_guest_os_id;
+
-+ if (hyperv_init_ghcb()) {
++ 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;
+ }
+
-+ /* 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);
++ ghcb_base = (void **)this_cpu_ptr(ms_hyperv.ghcb_base);
++ *ghcb_base = ghcb_va;
}
rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
-@@ -403,7 +452,8 @@ void __init hyperv_init(void)
+@@ -502,7 +542,8 @@ void __init hyperv_init(void)
hv_query_ext_cap(0);
return;
@@ -116,7 +114,7 @@
cpuhp_remove_state(cpuhp);
free_vp_assist_page:
kfree(hv_vp_assist_page);
-@@ -431,6 +481,9 @@ void hyperv_cleanup(void)
+@@ -531,6 +572,9 @@ void hyperv_cleanup(void)
*/
hv_hypercall_pg = NULL;
@@ -126,11 +124,10 @@
/* Reset the hypercall page */
hypercall_msr.as_uint64 = 0;
wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
-@@ -506,3 +559,11 @@ bool hv_is_isolation_supported(void)
- {
- return hv_get_isolation_type() != HV_ISOLATION_TYPE_NONE;
+@@ -615,6 +659,14 @@ bool hv_is_isolation_supported(void)
}
-+
+ EXPORT_SYMBOL_GPL(hv_is_isolation_supported);
+
+DEFINE_STATIC_KEY_FALSE(isolation_type_snp);
+
+bool hv_isolation_type_snp(void)
@@ -138,8 +135,12 @@
+ 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/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
-index adccbc209169..6627cfd2bfba 100644
+index 67ff0d637e55..aeacca7c4da8 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -11,6 +11,8 @@
@@ -152,10 +153,10 @@
struct hv_guest_mapping_flush_list *flush,
void *data);
diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
-index c1ab6a6e72b5..4269f3174e58 100644
+index 9a000ba2bb75..3ae56a29594f 100644
--- a/include/asm-generic/mshyperv.h
+++ b/include/asm-generic/mshyperv.h
-@@ -36,6 +36,7 @@ struct ms_hyperv_info {
+@@ -35,6 +35,7 @@ struct ms_hyperv_info {
u32 max_lp_index;
u32 isolation_config_a;
u32 isolation_config_b;
@@ -163,7 +164,7 @@
};
extern struct ms_hyperv_info ms_hyperv;
-@@ -237,6 +238,7 @@ bool hv_is_hyperv_initialized(void);
+@@ -224,6 +225,7 @@ bool hv_is_hyperv_initialized(void);
bool hv_is_hibernation_supported(void);
enum hv_isolation_type hv_get_isolation_type(void);
bool hv_is_isolation_supported(void);