Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5f5560b1 authored by James Morse's avatar James Morse Committed by Christoffer Dall
Browse files

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: default avatarMarc Zyngier <marc.zyngier@arm.com>
Acked-by: default avatarChristoffer Dall <christoffer.dall@linaro.org>
Fixes: 1e947bad ("arm64: KVM: Skip HYP setup when already running in HYP")
Signed-off-by: default avatarJames Morse <james.morse@arm.com>
Signed-off-by: default avatarChristoffer Dall <christoffer.dall@linaro.org>
parent cb678d60
Loading
Loading
Loading
Loading
+33 −19
Original line number Diff line number Diff line
@@ -1061,15 +1061,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;
@@ -1084,9 +1096,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;
	}

@@ -1127,6 +1138,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
	 */
@@ -1270,19 +1297,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();

	/* set size of VMID supported by CPU */
	kvm_vmid_bits = kvm_get_vmid_bits();
	kvm_info("%d-bit VMID\n", kvm_vmid_bits);