Subject: [PATCH RFC 7/7] KVM: ARM: Support KVM being compiled as a kernel module

From: Shannon Zhao <[email-masked]>
Date: Thu, 24 Oct 2019 18:27:50 +0800

This patch adds support for KVM ARM64 to be compiled as a kernel module.
It makes the CONFIG_KVM_ARM_HOST as a tristate option and adds a new
config option CONFIG_KVM_ARM_HOST_VHE_ONLY to ensure that kernel module
feature only supports for VHE system.

Signed-off-by: Shannon Zhao <[email-masked]>
---
 arch/arm64/include/asm/cache.h       | 16 ++---------
 arch/arm64/include/asm/cpufeature.h  | 11 +-------
 arch/arm64/include/asm/fpsimd.h      |  6 +---
 arch/arm64/include/asm/kvm_host.h    |  3 --
 arch/arm64/include/asm/kvm_mmu.h     |  4 +++
 arch/arm64/include/asm/perf_event.h  |  2 ++
 arch/arm64/kernel/acpi.c             |  1 +
 arch/arm64/kernel/asm-offsets.c      |  2 +-
 arch/arm64/kernel/cpu_errata.c       | 15 +++++++++-
 arch/arm64/kernel/cpufeature.c       |  2 ++
 arch/arm64/kernel/cpuinfo.c          | 16 +++++++++++
 arch/arm64/kernel/entry-fpsimd.S     |  2 ++
 arch/arm64/kernel/entry.S            |  1 +
 arch/arm64/kernel/fpsimd.c           | 11 ++++++++
 arch/arm64/kernel/head.S             |  1 +
 arch/arm64/kernel/hibernate.c        |  6 ++++
 arch/arm64/kernel/hyp-stub.S         |  1 +
 arch/arm64/kernel/insn.c             |  2 ++
 arch/arm64/kernel/perf_event.c       | 19 +++++++++++--
 arch/arm64/kernel/probes/kprobes.c   |  2 ++
 arch/arm64/kernel/smp.c              |  1 +
 arch/arm64/kernel/traps.c            |  2 ++
 arch/arm64/kvm/Kconfig               | 19 ++++++++++---
 arch/arm64/kvm/Makefile              | 53 ++++++++++++++++++++----------------
 arch/arm64/kvm/hyp/Makefile          | 22 +++++++--------
 arch/arm64/kvm/va_layout.c           |  7 ++++-
 arch/arm64/mm/cache.S                |  2 ++
 arch/arm64/mm/hugetlbpage.c          |  2 ++
 arch/arm64/mm/mmu.c                  |  4 +++
 drivers/clocksource/arm_arch_timer.c |  1 +
 drivers/irqchip/irq-gic-common.c     |  1 +
 drivers/irqchip/irq-gic-v4.c         |  8 ++++++
 include/linux/interrupt.h            |  6 +---
 kernel/irq/manage.c                  |  6 ++++
 mm/pgtable-generic.c                 |  1 +
 virt/kvm/arm/arm.c                   | 36 ++++++++++++++++++++++--
 virt/kvm/arm/mmu.c                   |  4 +++
 37 files changed, 215 insertions(+), 83 deletions(-)

diff --git a/arch/arm64/include/asm/cache.h b/arch/arm64/include/asm/cache.h
index 43da6dd..db79fc9 100644
--- a/arch/arm64/include/asm/cache.h
+++ b/arch/arm64/include/asm/cache.h
@@ -57,21 +57,9 @@
 
 #define ICACHEF_ALIASING	0
 #define ICACHEF_VPIPT		1
-extern unsigned long __icache_flags;
 
-/*
- * Whilst the D-side always behaves as PIPT on AArch64, aliasing is
- * permitted in the I-cache.
- */
-static inline int icache_is_aliasing(void)
-{
-	return test_bit(ICACHEF_ALIASING, &__icache_flags);
-}
-
-static inline int icache_is_vpipt(void)
-{
-	return test_bit(ICACHEF_VPIPT, &__icache_flags);
-}
+int icache_is_aliasing(void);
+int icache_is_vpipt(void);
 
 static inline u32 cache_type_cwg(void)
 {
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 9cde5d2..eea7215 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -625,16 +625,7 @@ static inline bool system_has_prio_mask_debugging(void)
 #define ARM64_SSBD_FORCE_ENABLE		2
 #define ARM64_SSBD_MITIGATED		3
 
-static inline int arm64_get_ssbd_state(void)
-{
-#ifdef CONFIG_ARM64_SSBD
-	extern int ssbd_state;
-	return ssbd_state;
-#else
-	return ARM64_SSBD_UNKNOWN;
-#endif
-}
-
+int arm64_get_ssbd_state(void);
 void arm64_set_ssbd_mitigation(bool state);
 
 extern int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt);
diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
index 59f10dd..b0e04b8 100644
--- a/arch/arm64/include/asm/fpsimd.h
+++ b/arch/arm64/include/asm/fpsimd.h
@@ -95,11 +95,7 @@ static inline unsigned int __bit_to_vq(unsigned int bit)
 	return SVE_VQ_MAX - bit;
 }
 
-/* Ensure vq >= SVE_VQ_MIN && vq <= SVE_VQ_MAX before calling this function */
-static inline bool sve_vq_available(unsigned int vq)
-{
-	return test_bit(__vq_to_bit(vq), sve_vq_map);
-}
+bool sve_vq_available(unsigned int vq);
 
 #ifdef CONFIG_ARM64_SVE
 
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index f656169..4f89322 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -582,9 +582,6 @@ static inline int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)
 
 void kvm_vcpu_pmu_restore_guest(struct kvm_vcpu *vcpu);
 void kvm_vcpu_pmu_restore_host(struct kvm_vcpu *vcpu);
-#else
-static inline void kvm_set_pmu_events(u32 set, struct perf_event_attr *attr) {}
-static inline void kvm_clr_pmu_events(u32 clr) {}
 #endif
 
 static inline void kvm_arm_vhe_guest_enter(void)
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index befe37d..f67e5b5 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -72,6 +72,7 @@
  * specific registers encoded in the instructions).
  */
 .macro kern_hyp_va	reg
+#if !defined(CONFIG_KVM_ARM_HOST_VHE_ONLY)
 alternative_cb kvm_update_va_mask
 	and     \reg, \reg, #1		/* mask with va_mask */
 	ror	\reg, \reg, #1		/* rotate to the first tag bit */
@@ -79,6 +80,7 @@
 	add	\reg, \reg, #0, lsl 12	/* insert the top 12 bits of the tag */
 	ror	\reg, \reg, #63		/* rotate back */
 alternative_cb_end
+#endif
 .endm
 
 #else
@@ -94,6 +96,7 @@ void kvm_update_va_mask(struct alt_instr *alt,
 
 static inline unsigned long __kern_hyp_va(unsigned long v)
 {
+#if !defined(CONFIG_KVM_ARM_HOST_VHE_ONLY)
 	asm volatile(ALTERNATIVE_CB("and %0, %0, #1\n"
 				    "ror %0, %0, #1\n"
 				    "add %0, %0, #0\n"
@@ -101,6 +104,7 @@ static inline unsigned long __kern_hyp_va(unsigned long v)
 				    "ror %0, %0, #63\n",
 				    kvm_update_va_mask)
 		     : "+r" (v));
+#endif
 	return v;
 }
 
diff --git a/arch/arm64/include/asm/perf_event.h b/arch/arm64/include/asm/perf_event.h
index 2bdbc79..cfd602c 100644
--- a/arch/arm64/include/asm/perf_event.h
+++ b/arch/arm64/include/asm/perf_event.h
@@ -223,4 +223,6 @@
 	(regs)->pstate = PSR_MODE_EL1h;	\
 }
 
+void perf_event_register_kvm_pmu_events_handler(void *set, void *clr);
+
 #endif
diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
index 3a58e9d..7295ead 100644
--- a/arch/arm64/kernel/acpi.c
+++ b/arch/arm64/kernel/acpi.c
@@ -288,3 +288,4 @@ int apei_claim_sea(struct pt_regs *regs)
 
 	return err;
 }
+EXPORT_SYMBOL(apei_claim_sea);
diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
index 2146857..63c818c 100644
--- a/arch/arm64/kernel/asm-offsets.c
+++ b/arch/arm64/kernel/asm-offsets.c
@@ -88,7 +88,7 @@ int main(void)
   DEFINE(CPU_BOOT_STACK,	offsetof(struct secondary_data, stack));
   DEFINE(CPU_BOOT_TASK,		offsetof(struct secondary_data, task));
   BLANK();
-#ifdef CONFIG_KVM_ARM_HOST
+#if IS_ENABLED(CONFIG_KVM_ARM_HOST)
   DEFINE(VCPU_CONTEXT,		offsetof(struct kvm_vcpu, arch.ctxt));
   DEFINE(VCPU_FAULT_DISR,	offsetof(struct kvm_vcpu, arch.fault.disr_el1));
   DEFINE(VCPU_WORKAROUND_FLAGS,	offsetof(struct kvm_vcpu, arch.workaround_flags));
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 6c3b10a..c846dde 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -267,8 +267,19 @@ static int detect_harden_bp_fw(void)
 }
 
 DEFINE_PER_CPU_READ_MOSTLY(u64, arm64_ssbd_callback_required);
+EXPORT_SYMBOL(arm64_ssbd_callback_required);
 
 int ssbd_state __read_mostly = ARM64_SSBD_KERNEL;
+int arm64_get_ssbd_state(void)
+{
+#ifdef CONFIG_ARM64_SSBD
+	return ssbd_state;
+#else
+	return ARM64_SSBD_UNKNOWN;
+#endif
+}
+EXPORT_SYMBOL(arm64_get_ssbd_state);
+
 static bool __ssb_safe = true;
 
 static const struct ssbd_options {
@@ -323,7 +334,7 @@ void __init arm64_update_smccc_conduit(struct alt_instr *alt,
 	*updptr = cpu_to_le32(insn);
 }
 
-void __init arm64_enable_wa2_handling(struct alt_instr *alt,
+void arm64_enable_wa2_handling(struct alt_instr *alt,
 				      __le32 *origptr, __le32 *updptr,
 				      int nr_inst)
 {
@@ -336,6 +347,7 @@ void __init arm64_enable_wa2_handling(struct alt_instr *alt,
 	if (arm64_get_ssbd_state() == ARM64_SSBD_KERNEL)
 		*updptr = cpu_to_le32(aarch64_insn_gen_nop());
 }
+EXPORT_SYMBOL(arm64_enable_wa2_handling);
 
 void arm64_set_ssbd_mitigation(bool state)
 {
@@ -565,6 +577,7 @@ int get_spectre_v2_workaround_state(void)
 
 	return ARM64_BP_HARDEN_WA_NEEDED;
 }
+EXPORT_SYMBOL(get_spectre_v2_workaround_state);
 
 /*
  * List of CPUs that do not need any Spectre-v2 mitigation at all.
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 80f459a..54f666f 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -807,6 +807,7 @@ u64 read_sanitised_ftr_reg(u32 id)
 	BUG_ON(!regp);
 	return regp->sys_val;
 }
+EXPORT_SYMBOL(read_sanitised_ftr_reg);
 
 #define read_sysreg_case(r)	\
 	case r:		return read_sysreg_s(r)
@@ -2006,6 +2007,7 @@ bool this_cpu_has_cap(unsigned int n)
 
 	return false;
 }
+EXPORT_SYMBOL(this_cpu_has_cap);
 
 void cpu_set_feature(unsigned int num)
 {
diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index 05933c0..288d0c4 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -42,6 +42,22 @@
 
 unsigned long __icache_flags;
 
+/*
+ * Whilst the D-side always behaves as PIPT on AArch64, aliasing is
+ * permitted in the I-cache.
+ */
+int icache_is_aliasing(void)
+{
+	return test_bit(ICACHEF_ALIASING, &__icache_flags);
+}
+EXPORT_SYMBOL(icache_is_aliasing);
+
+int icache_is_vpipt(void)
+{
+	return test_bit(ICACHEF_VPIPT, &__icache_flags);
+}
+EXPORT_SYMBOL(icache_is_vpipt);
+
 static const char *const hwcap_str[] = {
 	"fp",
 	"asimd",
diff --git a/arch/arm64/kernel/entry-fpsimd.S b/arch/arm64/kernel/entry-fpsimd.S
index 0f24eae..4419fe2 100644
--- a/arch/arm64/kernel/entry-fpsimd.S
+++ b/arch/arm64/kernel/entry-fpsimd.S
@@ -36,11 +36,13 @@ ENTRY(sve_save_state)
 	sve_save 0, x1, 2
 	ret
 ENDPROC(sve_save_state)
+EXPORT_SYMBOL(sve_save_state)
 
 ENTRY(sve_load_state)
 	sve_load 0, x1, x2, 3, x4
 	ret
 ENDPROC(sve_load_state)
+EXPORT_SYMBOL(sve_load_state)
 
 ENTRY(sve_get_vl)
 	_sve_rdvl	0, 1
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index cf3bd29..cb2a9ca 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -493,6 +493,7 @@ ENTRY(vectors)
 	kernel_ventry	0, error_invalid, 32		// Error 32-bit EL0
 #endif
 END(vectors)
+EXPORT_SYMBOL(vectors)
 
 #ifdef CONFIG_VMAP_STACK
 	/*
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 37d3912..9645807 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -125,7 +125,9 @@ struct fpsimd_last_state_struct {
 
 /* Maximum supported vector length across all CPUs (initially poisoned) */
 int __ro_after_init sve_max_vl = SVE_VL_MIN;
+EXPORT_SYMBOL(sve_max_vl);
 int __ro_after_init sve_max_virtualisable_vl = SVE_VL_MIN;
+EXPORT_SYMBOL(sve_max_virtualisable_vl);
 
 /*
  * Set of available vector lengths,
@@ -146,6 +148,13 @@ struct fpsimd_last_state_struct {
 
 #endif /* ! CONFIG_ARM64_SVE */
 
+/* Ensure vq >= SVE_VQ_MIN && vq <= SVE_VQ_MAX before calling this function */
+bool sve_vq_available(unsigned int vq)
+{
+	return test_bit(__vq_to_bit(vq), sve_vq_map);
+}
+EXPORT_SYMBOL(sve_vq_available);
+
 DEFINE_PER_CPU(bool, fpsimd_context_busy);
 EXPORT_PER_CPU_SYMBOL(fpsimd_context_busy);
 
@@ -1120,6 +1129,7 @@ void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *st, void *sve_state,
 	last->sve_state = sve_state;
 	last->sve_vl = sve_vl;
 }
+EXPORT_SYMBOL(fpsimd_bind_state_to_cpu);
 
 /*
  * Load the userland FPSIMD state of 'current' from memory, but only if the
@@ -1209,6 +1219,7 @@ void fpsimd_save_and_flush_cpu_state(void)
 	fpsimd_flush_cpu_state();
 	__put_cpu_fpsimd_context();
 }
+EXPORT_SYMBOL(fpsimd_save_and_flush_cpu_state);
 
 #ifdef CONFIG_KERNEL_MODE_NEON
 
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index 989b194..a30c2f8 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -670,6 +670,7 @@ ENDPROC(set_cpu_boot_mode_flag)
 ENTRY(__boot_cpu_mode)
 	.long	BOOT_CPU_MODE_EL2
 	.long	BOOT_CPU_MODE_EL1
+EXPORT_SYMBOL(__boot_cpu_mode)
 /*
  * The booting CPU updates the failed status @__early_cpu_boot_status,
  * with MMU turned off.
diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c
index a96b292..e7f3994 100644
--- a/arch/arm64/kernel/hibernate.c
+++ b/arch/arm64/kernel/hibernate.c
@@ -127,10 +127,12 @@ int arch_hibernation_header_save(void *addr, unsigned int max_size)
 	hdr->ttbr1_el1		= __pa_symbol(swapper_pg_dir);
 	hdr->reenter_kernel	= _cpu_resume;
 
+#if !defined(CONFIG_KVM_ARM_HOST_VHE_ONLY)
 	/* We can't use __hyp_get_vectors() because kvm may still be loaded */
 	if (el2_reset_needed())
 		hdr->__hyp_stub_vectors = __pa_symbol(__hyp_stub_vectors);
 	else
+#endif
 		hdr->__hyp_stub_vectors = 0;
 
 	/* Save the mpidr of the cpu we called cpu_suspend() on... */
@@ -304,11 +306,13 @@ int swsusp_arch_suspend(void)
 		dcache_clean_range(__mmuoff_data_start, __mmuoff_data_end);
 		dcache_clean_range(__idmap_text_start, __idmap_text_end);
 
+#if !defined(CONFIG_KVM_ARM_HOST_VHE_ONLY)
 		/* Clean kvm setup code to PoC? */
 		if (el2_reset_needed()) {
 			dcache_clean_range(__hyp_idmap_text_start, __hyp_idmap_text_end);
 			dcache_clean_range(__hyp_text_start, __hyp_text_end);
 		}
+#endif
 
 		/* make the crash dump kernel image protected again */
 		crash_post_resume();
@@ -549,6 +553,7 @@ int swsusp_arch_resume(void)
 	 *
 	 * We can skip this step if we booted at EL1, or are running with VHE.
 	 */
+#if !defined(CONFIG_KVM_ARM_HOST_VHE_ONLY)
 	if (el2_reset_needed()) {
 		phys_addr_t el2_vectors = phys_hibernate_exit;  /* base */
 		el2_vectors += hibernate_el2_vectors -
@@ -556,6 +561,7 @@ int swsusp_arch_resume(void)
 
 		__hyp_set_vectors(el2_vectors);
 	}
+#endif
 
 	hibernate_exit(virt_to_phys(tmp_pg_dir), resume_hdr.ttbr1_el1,
 		       resume_hdr.reenter_kernel, restore_pblist,
diff --git a/arch/arm64/kernel/hyp-stub.S b/arch/arm64/kernel/hyp-stub.S
index 73d4607..c5633d6 100644
--- a/arch/arm64/kernel/hyp-stub.S
+++ b/arch/arm64/kernel/hyp-stub.S
@@ -42,6 +42,7 @@ ENTRY(__hyp_stub_vectors)
 	ventry	el1_fiq_invalid			// FIQ 32-bit EL1
 	ventry	el1_error_invalid		// Error 32-bit EL1
 ENDPROC(__hyp_stub_vectors)
+EXPORT_SYMBOL(__hyp_stub_vectors)
 
 	.align 11
 
diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
index d801a70..e1acf5a 100644
--- a/arch/arm64/kernel/insn.c
+++ b/arch/arm64/kernel/insn.c
@@ -569,6 +569,7 @@ u32 __kprobes aarch64_insn_gen_nop(void)
 {
 	return aarch64_insn_gen_hint(AARCH64_INSN_HINT_NOP);
 }
+EXPORT_SYMBOL(aarch64_insn_gen_nop);
 
 u32 aarch64_insn_gen_branch_reg(enum aarch64_insn_register reg,
 				enum aarch64_insn_branch_type type)
@@ -1661,3 +1662,4 @@ u32 aarch64_insn_gen_extr(enum aarch64_insn_variant variant,
 	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, Rn);
 	return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RM, insn, Rm);
 }
+EXPORT_SYMBOL(aarch64_insn_gen_extr);
diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
index a0b4f1b..7d2c9c2 100644
--- a/arch/arm64/kernel/perf_event.c
+++ b/arch/arm64/kernel/perf_event.c
@@ -516,6 +516,16 @@ static inline int armv8pmu_enable_counter(int idx)
 	return idx;
 }
 
+static void (* kvm_set_pmu_events_ptr)(u32 set, struct perf_event_attr *attr) = NULL;
+static void (* kvm_clr_pmu_events_ptr)(u32 clr) = NULL;
+
+void perf_event_register_kvm_pmu_events_handler(void *set, void* clr)
+{
+	kvm_set_pmu_events_ptr = set;
+	kvm_clr_pmu_events_ptr = clr;
+}
+EXPORT_SYMBOL(perf_event_register_kvm_pmu_events_handler);
+
 static inline void armv8pmu_enable_event_counter(struct perf_event *event)
 {
 	struct perf_event_attr *attr = &event->attr;
@@ -525,7 +535,8 @@ static inline void armv8pmu_enable_event_counter(struct perf_event *event)
 	if (armv8pmu_event_is_chained(event))
 		counter_bits |= BIT(ARMV8_IDX_TO_COUNTER(idx - 1));
 
-	kvm_set_pmu_events(counter_bits, attr);
+	if (kvm_set_pmu_events_ptr)
+		(*kvm_set_pmu_events_ptr)(counter_bits, attr);
 
 	/* We rely on the hypervisor switch code to enable guest counters */
 	if (!kvm_pmu_counter_deferred(attr)) {
@@ -552,7 +563,8 @@ static inline void armv8pmu_disable_event_counter(struct perf_event *event)
 	if (armv8pmu_event_is_chained(event))
 		counter_bits |= BIT(ARMV8_IDX_TO_COUNTER(idx - 1));
 
-	kvm_clr_pmu_events(counter_bits);
+	if (kvm_clr_pmu_events_ptr)
+		(*kvm_clr_pmu_events_ptr)(counter_bits);
 
 	/* We rely on the hypervisor switch code to disable guest counters */
 	if (!kvm_pmu_counter_deferred(attr)) {
@@ -883,7 +895,8 @@ static void armv8pmu_reset(void *info)
 	}
 
 	/* Clear the counters we flip at guest entry/exit */
-	kvm_clr_pmu_events(U32_MAX);
+	if (kvm_clr_pmu_events_ptr)
+		kvm_clr_pmu_events_ptr(U32_MAX);
 
 	/*
 	 * Initialize & Reset PMNC. Request overflow interrupt for
diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
index c445282..34e5dd4 100644
--- a/arch/arm64/kernel/probes/kprobes.c
+++ b/arch/arm64/kernel/probes/kprobes.c
@@ -461,6 +461,7 @@ int __init arch_populate_kprobe_blacklist(void)
 		return ret;
 	ret = kprobe_add_area_blacklist((unsigned long)__idmap_text_start,
 					(unsigned long)__idmap_text_end);
+#if !defined(CONFIG_KVM_ARM_HOST_VHE_ONLY)
 	if (ret)
 		return ret;
 	ret = kprobe_add_area_blacklist((unsigned long)__hyp_text_start,
@@ -469,6 +470,7 @@ int __init arch_populate_kprobe_blacklist(void)
 		return ret;
 	ret = kprobe_add_area_blacklist((unsigned long)__hyp_idmap_text_start,
 					(unsigned long)__hyp_idmap_text_end);
+#endif
 	return ret;
 }
 
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index dc9fe87..c7a4c82 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -947,6 +947,7 @@ void smp_send_reschedule(int cpu)
 {
 	smp_cross_call(cpumask_of(cpu), IPI_RESCHEDULE);
 }
+EXPORT_SYMBOL(smp_send_reschedule);
 
 #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
 void tick_broadcast(const struct cpumask *mask)
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index 34739e8..46f0256 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -772,6 +772,7 @@ const char *esr_get_class_string(u32 esr)
 {
 	return esr_class_str[ESR_ELx_EC(esr)];
 }
+EXPORT_SYMBOL(esr_get_class_string);
 
 /*
  * bad_mode handles the impossible case in the exception vector. This is always
@@ -887,6 +888,7 @@ bool arm64_is_fatal_ras_serror(struct pt_regs *regs, unsigned int esr)
 		arm64_serror_panic(regs, esr);
 	}
 }
+EXPORT_SYMBOL(arm64_is_fatal_ras_serror);
 
 asmlinkage void do_serror(struct pt_regs *regs, unsigned int esr)
 {
diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
index a67121d..0681051 100644
--- a/arch/arm64/kvm/Kconfig
+++ b/arch/arm64/kvm/Kconfig
@@ -18,7 +18,7 @@ menuconfig VIRTUALIZATION
 
 if VIRTUALIZATION
 
-config KVM
+menuconfig KVM
 	bool "Kernel-based Virtual Machine (KVM) support"
 	depends on OF
 	select MMU_NOTIFIER
@@ -26,13 +26,11 @@ config KVM
 	select HAVE_KVM_CPU_RELAX_INTERCEPT
 	select HAVE_KVM_ARCH_TLB_FLUSH_ALL
 	select KVM_MMIO
-	select KVM_ARM_HOST
 	select KVM_GENERIC_DIRTYLOG_READ_PROTECT
 	select SRCU
 	select KVM_VFIO
 	select HAVE_KVM_EVENTFD
 	select HAVE_KVM_IRQFD
-	select KVM_ARM_PMU if HW_PERF_EVENTS
 	select HAVE_KVM_MSI
 	select HAVE_KVM_IRQCHIP
 	select HAVE_KVM_IRQ_ROUTING
@@ -45,11 +43,22 @@ config KVM
 	  levels of fake page tables.
 
 	  If unsure, say N.
+if KVM
 
 config KVM_ARM_HOST
-	bool
+	tristate "KVM support for ARM64"
+	select KVM_ARM_HOST_VHE_ONLY if KVM_ARM_HOST=m
+	select KVM_ARM_PMU if HW_PERF_EVENTS
+	default y
 	---help---
 	  Provides host support for ARM processors.
+	  To compile this as a module, choose M here: the module
+	  will be called kvm. Note it only works for VHE platform.
+
+config KVM_ARM_HOST_VHE_ONLY
+	bool
+	depends on KVM_ARM_HOST=m
+	default n
 
 config KVM_ARM_PMU
 	bool
@@ -60,6 +69,8 @@ config KVM_ARM_PMU
 config KVM_INDIRECT_VECTORS
        def_bool KVM && (HARDEN_BRANCH_PREDICTOR || HARDEN_EL2_VECTORS)
 
+endif # KVM
+
 source "drivers/vhost/Kconfig"
 
 endif # VIRTUALIZATION
diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
index 3ac1a64..0aefb9c 100644
--- a/arch/arm64/kvm/Makefile
+++ b/arch/arm64/kvm/Makefile
@@ -8,30 +8,37 @@ ccflags-y += -I $(srctree)/$(src) -I $(srctree)/virt/kvm/arm/vgic
 KVM=../../../virt/kvm
 
 obj-$(CONFIG_KVM_ARM_HOST) += kvm.o
-obj-$(CONFIG_KVM_ARM_HOST) += hyp/
+#obj-$(CONFIG_KVM_ARM_HOST) += hyp/
 
-kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o $(KVM)/vfio.o
-kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/arm.o $(KVM)/arm/mmu.o $(KVM)/arm/mmio.o
-kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/psci.o $(KVM)/arm/perf.o
+#kvm-y += hyp/
+kvm-y += $(addprefix hyp/, debug-sr.o fpsimd.o hyp-entry.o entry.o switch.o sysreg-sr.o tlb.o vgic-v2-cpuif-proxy.o)
+kvm-y += $(KVM)/arm/hyp/vgic-v3-sr.o
+kvm-y += $(KVM)/arm/hyp/timer-sr.o
+kvm-y += $(KVM)/arm/hyp/aarch32.o
+kvm-y += hyp.o hyp-init.o va_layout.o
 
-kvm-$(CONFIG_KVM_ARM_HOST) += inject_fault.o regmap.o va_layout.o
-kvm-$(CONFIG_KVM_ARM_HOST) += hyp.o hyp-init.o handle_exit.o
-kvm-$(CONFIG_KVM_ARM_HOST) += guest.o debug.o reset.o sys_regs.o sys_regs_generic_v8.o
-kvm-$(CONFIG_KVM_ARM_HOST) += vgic-sys-reg-v3.o fpsimd.o pmu.o
-kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/aarch32.o
+kvm-y += $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o $(KVM)/vfio.o
+kvm-y += $(KVM)/arm/arm.o $(KVM)/arm/mmu.o $(KVM)/arm/mmio.o
+kvm-y += $(KVM)/arm/psci.o $(KVM)/arm/perf.o
 
-kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic.o
-kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-init.o
-kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-irqfd.o
-kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-v2.o
-kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-v3.o
-kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-v4.o
-kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio.o
-kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v2.o
-kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v3.o
-kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-kvm-device.o
-kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-its.o
-kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-debug.o
-kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/irqchip.o
-kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/arch_timer.o
+kvm-y += inject_fault.o regmap.o va_layout.o
+kvm-y += hyp.o hyp-init.o handle_exit.o
+kvm-y += guest.o debug.o reset.o sys_regs.o sys_regs_generic_v8.o
+kvm-y += vgic-sys-reg-v3.o fpsimd.o pmu.o
+kvm-y += $(KVM)/arm/aarch32.o
+
+kvm-y += $(KVM)/arm/vgic/vgic.o
+kvm-y += $(KVM)/arm/vgic/vgic-init.o
+kvm-y += $(KVM)/arm/vgic/vgic-irqfd.o
+kvm-y += $(KVM)/arm/vgic/vgic-v2.o
+kvm-y += $(KVM)/arm/vgic/vgic-v3.o
+kvm-y += $(KVM)/arm/vgic/vgic-v4.o
+kvm-y += $(KVM)/arm/vgic/vgic-mmio.o
+kvm-y += $(KVM)/arm/vgic/vgic-mmio-v2.o
+kvm-y += $(KVM)/arm/vgic/vgic-mmio-v3.o
+kvm-y += $(KVM)/arm/vgic/vgic-kvm-device.o
+kvm-y += $(KVM)/arm/vgic/vgic-its.o
+kvm-y += $(KVM)/arm/vgic/vgic-debug.o
+kvm-y += $(KVM)/irqchip.o
+kvm-y += $(KVM)/arm/arch_timer.o
 kvm-$(CONFIG_KVM_ARM_PMU) += $(KVM)/arm/pmu.o
diff --git a/arch/arm64/kvm/hyp/Makefile b/arch/arm64/kvm/hyp/Makefile
index ea710f6..f91ac14 100644
--- a/arch/arm64/kvm/hyp/Makefile
+++ b/arch/arm64/kvm/hyp/Makefile
@@ -8,18 +8,18 @@ ccflags-y += -fno-stack-protector -DDISABLE_BRANCH_PROFILING \
 
 KVM=../../../../virt/kvm
 
-obj-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hyp/vgic-v3-sr.o
-obj-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hyp/timer-sr.o
-obj-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hyp/aarch32.o
+obj-y += $(KVM)/arm/hyp/vgic-v3-sr.o
+obj-y += $(KVM)/arm/hyp/timer-sr.o
+obj-y += $(KVM)/arm/hyp/aarch32.o
 
-obj-$(CONFIG_KVM_ARM_HOST) += vgic-v2-cpuif-proxy.o
-obj-$(CONFIG_KVM_ARM_HOST) += sysreg-sr.o
-obj-$(CONFIG_KVM_ARM_HOST) += debug-sr.o
-obj-$(CONFIG_KVM_ARM_HOST) += entry.o
-obj-$(CONFIG_KVM_ARM_HOST) += switch.o
-obj-$(CONFIG_KVM_ARM_HOST) += fpsimd.o
-obj-$(CONFIG_KVM_ARM_HOST) += tlb.o
-obj-$(CONFIG_KVM_ARM_HOST) += hyp-entry.o
+obj-y += vgic-v2-cpuif-proxy.o
+obj-y += sysreg-sr.o
+obj-y += debug-sr.o
+obj-y += entry.o
+obj-y += switch.o
+obj-y += fpsimd.o
+obj-y += tlb.o
+obj-y += hyp-entry.o
 
 # KVM code is run at a different exception code with a different map, so
 # compiler instrumentation that inserts callbacks or checks into the code may
diff --git a/arch/arm64/kvm/va_layout.c b/arch/arm64/kvm/va_layout.c
index 2cf7d4b..c82c4e2 100644
--- a/arch/arm64/kvm/va_layout.c
+++ b/arch/arm64/kvm/va_layout.c
@@ -12,10 +12,12 @@
 #include <asm/insn.h>
 #include <asm/kvm_mmu.h>
 
+#if !defined(CONFIG_KVM_ARM_HOST_VHE_ONLY)
 /*
  * The LSB of the random hyp VA tag or 0 if no randomization is used.
  */
 static u8 tag_lsb;
+
 /*
  * The random hyp VA tag value with the region bit if hyp randomization is used
  */
@@ -103,7 +105,7 @@ static u32 compute_instruction(int n, u32 rd, u32 rn)
 	return insn;
 }
 
-void __init kvm_update_va_mask(struct alt_instr *alt,
+void kvm_update_va_mask(struct alt_instr *alt,
 			       __le32 *origptr, __le32 *updptr, int nr_inst)
 {
 	int i;
@@ -139,10 +141,12 @@ void __init kvm_update_va_mask(struct alt_instr *alt,
 		updptr[i] = cpu_to_le32(insn);
 	}
 }
+#endif
 
 void *__kvm_bp_vect_base;
 int __kvm_harden_el2_vector_slot;
 
+#if !defined(CONFIG_KVM_ARM_HOST_VHE_ONLY)
 void kvm_patch_vector_branch(struct alt_instr *alt,
 			     __le32 *origptr, __le32 *updptr, int nr_inst)
 {
@@ -213,3 +217,4 @@ void kvm_patch_vector_branch(struct alt_instr *alt,
 					   AARCH64_INSN_BRANCH_NOLINK);
 	*updptr++ = cpu_to_le32(insn);
 }
+#endif
diff --git a/arch/arm64/mm/cache.S b/arch/arm64/mm/cache.S
index db767b0..653087f 100644
--- a/arch/arm64/mm/cache.S
+++ b/arch/arm64/mm/cache.S
@@ -95,6 +95,7 @@ alternative_else_nop_endif
 	mov	x0, #-EFAULT
 	b	1b
 ENDPROC(invalidate_icache_range)
+EXPORT_SYMBOL(invalidate_icache_range)
 
 /*
  *	__flush_dcache_area(kaddr, size)
@@ -109,6 +110,7 @@ ENTRY(__flush_dcache_area)
 	dcache_by_line_op civac, sy, x0, x1, x2, x3
 	ret
 ENDPIPROC(__flush_dcache_area)
+EXPORT_SYMBOL(__flush_dcache_area)
 
 /*
  *	__clean_dcache_area_pou(kaddr, size)
diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c
index bbeb6a5..171cff9 100644
--- a/arch/arm64/mm/hugetlbpage.c
+++ b/arch/arm64/mm/hugetlbpage.c
@@ -43,6 +43,7 @@ int pmd_huge(pmd_t pmd)
 {
 	return pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT);
 }
+EXPORT_SYMBOL(pmd_huge);
 
 int pud_huge(pud_t pud)
 {
@@ -52,6 +53,7 @@ int pud_huge(pud_t pud)
 	return 0;
 #endif
 }
+EXPORT_SYMBOL(pud_huge);
 
 /*
  * Select all bits except the pfn
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 60c929f..828d87e 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -39,7 +39,9 @@
 #define NO_CONT_MAPPINGS	BIT(1)
 
 u64 idmap_t0sz = TCR_T0SZ(VA_BITS);
+EXPORT_SYMBOL(idmap_t0sz);
 u64 idmap_ptrs_per_pgd = PTRS_PER_PGD;
+EXPORT_SYMBOL(idmap_ptrs_per_pgd);
 
 u64 __section(".mmuoff.data.write") vabits_actual;
 EXPORT_SYMBOL(vabits_actual);
@@ -75,6 +77,8 @@ void set_swapper_pgd(pgd_t *pgdp, pgd_t pgd)
 	pgd_clear_fixmap();
 	spin_unlock(&swapper_pgdir_lock);
 }
+EXPORT_SYMBOL(set_swapper_pgd);
+EXPORT_SYMBOL(swapper_pg_dir);
 
 pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
 			      unsigned long size, pgprot_t vma_prot)
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 9a5464c..cc858a5 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -956,6 +956,7 @@ struct arch_timer_kvm_info *arch_timer_get_kvm_info(void)
 {
 	return &arch_timer_kvm_info;
 }
+EXPORT_SYMBOL(arch_timer_get_kvm_info);
 
 static void __init arch_counter_register(unsigned type)
 {
diff --git a/drivers/irqchip/irq-gic-common.c b/drivers/irqchip/irq-gic-common.c
index 8252000..55fab0f 100644
--- a/drivers/irqchip/irq-gic-common.c
+++ b/drivers/irqchip/irq-gic-common.c
@@ -18,6 +18,7 @@ const struct gic_kvm_info *gic_get_kvm_info(void)
 {
 	return gic_kvm_info;
 }
+EXPORT_SYMBOL(gic_get_kvm_info);
 
 void gic_set_kvm_info(const struct gic_kvm_info *info)
 {
diff --git a/drivers/irqchip/irq-gic-v4.c b/drivers/irqchip/irq-gic-v4.c
index 563e87e..3b51535 100644
--- a/drivers/irqchip/irq-gic-v4.c
+++ b/drivers/irqchip/irq-gic-v4.c
@@ -125,6 +125,7 @@ int its_alloc_vcpu_irqs(struct its_vm *vm)
 
 	return -ENOMEM;
 }
+EXPORT_SYMBOL(its_alloc_vcpu_irqs);
 
 void its_free_vcpu_irqs(struct its_vm *vm)
 {
@@ -132,6 +133,7 @@ void its_free_vcpu_irqs(struct its_vm *vm)
 	irq_domain_remove(vm->domain);
 	irq_domain_free_fwnode(vm->fwnode);
 }
+EXPORT_SYMBOL(its_free_vcpu_irqs);
 
 static int its_send_vpe_cmd(struct its_vpe *vpe, struct its_cmd_info *info)
 {
@@ -148,6 +150,7 @@ int its_schedule_vpe(struct its_vpe *vpe, bool on)
 
 	return its_send_vpe_cmd(vpe, &info);
 }
+EXPORT_SYMBOL(its_schedule_vpe);
 
 int its_invall_vpe(struct its_vpe *vpe)
 {
@@ -157,6 +160,7 @@ int its_invall_vpe(struct its_vpe *vpe)
 
 	return its_send_vpe_cmd(vpe, &info);
 }
+EXPORT_SYMBOL(its_invall_vpe);
 
 int its_map_vlpi(int irq, struct its_vlpi_map *map)
 {
@@ -180,6 +184,7 @@ int its_map_vlpi(int irq, struct its_vlpi_map *map)
 
 	return ret;
 }
+EXPORT_SYMBOL(its_map_vlpi);
 
 int its_get_vlpi(int irq, struct its_vlpi_map *map)
 {
@@ -192,12 +197,14 @@ int its_get_vlpi(int irq, struct its_vlpi_map *map)
 
 	return irq_set_vcpu_affinity(irq, &info);
 }
+EXPORT_SYMBOL(its_get_vlpi);
 
 int its_unmap_vlpi(int irq)
 {
 	irq_clear_status_flags(irq, IRQ_DISABLE_UNLAZY);
 	return irq_set_vcpu_affinity(irq, NULL);
 }
+EXPORT_SYMBOL(its_unmap_vlpi);
 
 int its_prop_update_vlpi(int irq, u8 config, bool inv)
 {
@@ -210,6 +217,7 @@ int its_prop_update_vlpi(int irq, u8 config, bool inv)
 
 	return irq_set_vcpu_affinity(irq, &info);
 }
+EXPORT_SYMBOL(its_prop_update_vlpi);
 
 int its_init_v4(struct irq_domain *domain, const struct irq_domain_ops *ops)
 {
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 89fc59d..295acd9 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -310,11 +310,7 @@ extern int __irq_set_affinity(unsigned int irq, const struct cpumask *cpumask,
  *
  * Fails if cpumask does not contain an online CPU
  */
-static inline int
-irq_set_affinity(unsigned int irq, const struct cpumask *cpumask)
-{
-	return __irq_set_affinity(irq, cpumask, false);
-}
+int irq_set_affinity(unsigned int irq, const struct cpumask *cpumask);
 
 /**
  * irq_force_affinity - Force the irq affinity of a given irq
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 1753486..65531465 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -306,6 +306,12 @@ int __irq_set_affinity(unsigned int irq, const struct cpumask *mask, bool force)
 	return ret;
 }
 
+int irq_set_affinity(unsigned int irq, const struct cpumask *cpumask)
+{
+	return __irq_set_affinity(irq, cpumask, false);
+}
+EXPORT_SYMBOL_GPL(irq_set_affinity);
+
 int irq_set_affinity_hint(unsigned int irq, const struct cpumask *m)
 {
 	unsigned long flags;
diff --git a/mm/pgtable-generic.c b/mm/pgtable-generic.c
index 532c292..ff0a7a8 100644
--- a/mm/pgtable-generic.c
+++ b/mm/pgtable-generic.c
@@ -35,6 +35,7 @@ void pud_clear_bad(pud_t *pud)
 	pud_ERROR(*pud);
 	pud_clear(pud);
 }
+EXPORT_SYMBOL(pud_clear_bad);
 
 void pmd_clear_bad(pmd_t *pmd)
 {
diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
index feb6649..31873b5 100644
--- a/virt/kvm/arm/arm.c
+++ b/virt/kvm/arm/arm.c
@@ -45,7 +45,9 @@
 #endif
 
 DEFINE_PER_CPU(kvm_host_data_t, kvm_host_data);
+#if !defined(CONFIG_KVM_ARM_HOST_VHE_ONLY)
 static DEFINE_PER_CPU(unsigned long, kvm_arm_hyp_stack_page);
+#endif
 
 /* Per-CPU variable containing the currently running vcpu. */
 static DEFINE_PER_CPU(struct kvm_vcpu *, kvm_arm_running_vcpu);
@@ -766,7 +768,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
 			ret = kvm_vcpu_run_vhe(vcpu);
 			kvm_arm_vhe_guest_exit();
 		} else {
+#if !defined(CONFIG_KVM_ARM_HOST_VHE_ONLY)
 			ret = kvm_call_hyp_ret(__kvm_vcpu_run_nvhe, vcpu);
+#endif
 		}
 
 		vcpu->mode = OUTSIDE_GUEST_MODE;
@@ -1317,6 +1321,7 @@ long kvm_arch_vm_ioctl(struct file *filp,
 
 static void cpu_init_hyp_mode(void *dummy)
 {
+#if !defined(CONFIG_KVM_ARM_HOST_VHE_ONLY)
 	phys_addr_t pgd_ptr;
 	unsigned long hyp_stack_ptr;
 	unsigned long stack_page;
@@ -1332,12 +1337,15 @@ static void cpu_init_hyp_mode(void *dummy)
 
 	__cpu_init_hyp_mode(pgd_ptr, hyp_stack_ptr, vector_ptr);
 	__cpu_init_stage2();
+#endif
 }
 
 static void cpu_hyp_reset(void)
 {
+#if !defined(CONFIG_KVM_ARM_HOST_VHE_ONLY)
 	if (!is_kernel_in_hyp_mode())
 		__hyp_reset_vectors();
+#endif
 }
 
 static void cpu_hyp_reinit(void)
@@ -1484,6 +1492,7 @@ static int init_subsystems(void)
 	if (err)
 		goto out;
 
+	perf_event_register_kvm_pmu_events_handler(kvm_set_pmu_events, kvm_clr_pmu_events);
 	kvm_perf_init();
 	kvm_coproc_table_init();
 
@@ -1494,6 +1503,7 @@ static int init_subsystems(void)
 	return err;
 }
 
+#if !defined(CONFIG_KVM_ARM_HOST_VHE_ONLY)
 static void teardown_hyp_mode(void)
 {
 	int cpu;
@@ -1600,6 +1610,7 @@ static int init_hyp_mode(void)
 	kvm_err("error initializing Hyp mode: %d\n", err);
 	return err;
 }
+#endif
 
 static void check_kvm_target_cpu(void *ret)
 {
@@ -1696,12 +1707,13 @@ int kvm_arch_init(void *opaque)
 	if (err)
 		return err;
 
+#if !defined(CONFIG_KVM_ARM_HOST_VHE_ONLY)
 	if (!in_hyp_mode) {
 		err = init_hyp_mode();
 		if (err)
 			goto out_err;
 	}
-
+#endif
 	err = init_subsystems();
 	if (err)
 		goto out_hyp;
@@ -1714,15 +1726,18 @@ int kvm_arch_init(void *opaque)
 	return 0;
 
 out_hyp:
+#if !defined(CONFIG_KVM_ARM_HOST_VHE_ONLY)
 	if (!in_hyp_mode)
 		teardown_hyp_mode();
 out_err:
+#endif
 	return err;
 }
 
 /* NOP: Compiling as a module not supported */
 void kvm_arch_exit(void)
 {
+	perf_event_register_kvm_pmu_events_handler(NULL, NULL);
 	kvm_perf_teardown();
 	kvm_timer_hyp_uninit();
 	kvm_vgic_hyp_uninit();
@@ -1731,8 +1746,25 @@ void kvm_arch_exit(void)
 
 static int arm_init(void)
 {
-	int rc = kvm_init(NULL, sizeof(struct kvm_vcpu), 0, THIS_MODULE);
+	int rc;
+
+	if (IS_MODULE(CONFIG_KVM_ARM_HOST) && !is_kernel_in_hyp_mode()) {
+		kvm_err("kvm arm kernel module only supports for VHE system\n");
+		return -ENODEV;
+	}
+
+	rc = kvm_init(NULL, sizeof(struct kvm_vcpu), 0, THIS_MODULE);
+	if (!rc)
+		kvm_info("init kvm-arm successfully\n");
 	return rc;
 }
 
 module_init(arm_init);
+
+static void arm_exit(void)
+{
+       kvm_exit();
+       kvm_info("exit kvm-arm successfully\n");
+}
+
+module_exit(arm_exit);
diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c
index 38b4c91..665886f 100644
--- a/virt/kvm/arm/mmu.c
+++ b/virt/kvm/arm/mmu.c
@@ -28,8 +28,10 @@
 static DEFINE_MUTEX(kvm_hyp_pgd_mutex);
 
 static unsigned long hyp_idmap_start;
+#if !defined(CONFIG_KVM_ARM_HOST_VHE_ONLY)
 static unsigned long hyp_idmap_end;
 static phys_addr_t hyp_idmap_vector;
+#endif
 
 static unsigned long io_map_base;
 
@@ -2150,6 +2152,7 @@ phys_addr_t kvm_mmu_get_httbr(void)
 		return virt_to_phys(hyp_pgd);
 }
 
+#if !defined(CONFIG_KVM_ARM_HOST_VHE_ONLY)
 phys_addr_t kvm_get_idmap_vector(void)
 {
 	return hyp_idmap_vector;
@@ -2243,6 +2246,7 @@ int kvm_mmu_init(void)
 	free_hyp_pgds();
 	return err;
 }
+#endif
 
 void kvm_arch_commit_memory_region(struct kvm *kvm,
 				   const struct kvm_userspace_memory_region *mem,
-- 
1.8.3.1

_______________________________________________
linux-arm-kernel mailing list
[email-masked]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel