aboutsummaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorJames Morse <james.morse@arm.com>2016-03-30 18:33:04 +0100
committerAlex Shi <alex.shi@linaro.org>2016-05-24 22:39:32 +0800
commitd6c1376ab351962a53fa73542abdaef73172eace (patch)
treeb557ea6b2950a845ea68391d8e94853c8a0db9ff /arch
parent5aa75c8a63ce9b417ffa9c050203cf769af0f018 (diff)
arm64: KVM: Register CPU notifiers when the kernel runs at HYP
When the kernel is running at EL2, it doesn't need init_hyp_mode() to configure page tables for HYP. This function also registers the CPU hotplug and lower power notifiers that cause HYP to be re-initialised after the CPU has been reset. To avoid losing the register state that controls stage2 translation, move the registering of these notifiers into init_subsystems(), and add a is_kernel_in_hyp_mode() path to each callback. Acked-by: Marc Zyngier <marc.zyngier@arm.com> Acked-by: Christoffer Dall <christoffer.dall@linaro.org> Fixes: 1e947bad0b6 ("arm64: KVM: Skip HYP setup when already running in HYP") Signed-off-by: James Morse <james.morse@arm.com> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org> (cherry picked from commit 5f5560b1c5f3a80e91c6babb2da34a51943bbdec) Signed-off-by: Alex Shi <alex.shi@linaro.org> Conflicts: skip vimd in arch/arm/kvm/arm.c
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/kvm/arm.c52
1 files changed, 33 insertions, 19 deletions
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 17749163feb1..d10c75ba44e8 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -938,15 +938,27 @@ static void cpu_init_hyp_mode(void *dummy)
kvm_arm_init_debug();
}
+static void cpu_hyp_reinit(void)
+{
+ if (is_kernel_in_hyp_mode()) {
+ /*
+ * cpu_init_stage2() is safe to call even if the PM
+ * event was cancelled before the CPU was reset.
+ */
+ cpu_init_stage2(NULL);
+ } else {
+ if (__hyp_get_vectors() == hyp_default_vectors)
+ cpu_init_hyp_mode(NULL);
+ }
+}
+
static int hyp_init_cpu_notify(struct notifier_block *self,
unsigned long action, void *cpu)
{
switch (action) {
case CPU_STARTING:
case CPU_STARTING_FROZEN:
- if (__hyp_get_vectors() == hyp_default_vectors)
- cpu_init_hyp_mode(NULL);
- break;
+ cpu_hyp_reinit();
}
return NOTIFY_OK;
@@ -961,9 +973,8 @@ static int hyp_init_cpu_pm_notifier(struct notifier_block *self,
unsigned long cmd,
void *v)
{
- if (cmd == CPU_PM_EXIT &&
- __hyp_get_vectors() == hyp_default_vectors) {
- cpu_init_hyp_mode(NULL);
+ if (cmd == CPU_PM_EXIT) {
+ cpu_hyp_reinit();
return NOTIFY_OK;
}
@@ -1005,6 +1016,22 @@ static int init_subsystems(void)
int err;
/*
+ * Register CPU Hotplug notifier
+ */
+ cpu_notifier_register_begin();
+ err = __register_cpu_notifier(&hyp_init_cpu_nb);
+ cpu_notifier_register_done();
+ if (err) {
+ kvm_err("Cannot register KVM init CPU notifier (%d)\n", err);
+ return err;
+ }
+
+ /*
+ * Register CPU lower-power notifier
+ */
+ hyp_cpu_pm_init();
+
+ /*
* Init HYP view of VGIC
*/
err = kvm_vgic_hyp_init();
@@ -1145,19 +1172,6 @@ static int init_hyp_mode(void)
free_boot_hyp_pgd();
#endif
- cpu_notifier_register_begin();
-
- err = __register_cpu_notifier(&hyp_init_cpu_nb);
-
- cpu_notifier_register_done();
-
- if (err) {
- kvm_err("Cannot register HYP init CPU notifier (%d)\n", err);
- goto out_err;
- }
-
- hyp_cpu_pm_init();
-
kvm_info("Hyp mode initialized successfully\n");
return 0;