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

From: Shannon Zhao
Date: Thu Oct 24 2019 - 06:28:06 EST


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 <shannon.zhao@xxxxxxxxxxxxxxxxx>
---
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