Commit 8579a185 authored by Will Deacon's avatar Will Deacon Committed by Marc Zyngier
Browse files

KVM: arm64: Reject stub hypercalls after pKVM has been initialised



The stub hypercalls provide mechanisms to reset and replace the EL2 code,
so uninstall them once pKVM has been initialised in order to ensure the
integrity of the hypervisor code.

To ensure pKVM initialisation remains functional, split cpu_hyp_reinit()
into two helper functions to separate usage of the stub from usage of
pkvm hypercalls either side of __pkvm_init on the boot CPU.

Cc: Marc Zyngier <maz@kernel.org>
Cc: Quentin Perret <qperret@google.com>
Signed-off-by: default avatarWill Deacon <will@kernel.org>
Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20211008135839.1193-4-will@kernel.org
parent 8f4566f1
Loading
Loading
Loading
Loading
+23 −8
Original line number Diff line number Diff line
@@ -1579,25 +1579,33 @@ static void cpu_set_hyp_vector(void)
		kvm_call_hyp_nvhe(__pkvm_cpu_set_vector, data->slot);
}

static void cpu_hyp_reinit(void)
static void cpu_hyp_init_context(void)
{
	kvm_init_host_cpu_context(&this_cpu_ptr_hyp_sym(kvm_host_data)->host_ctxt);

	cpu_hyp_reset();

	if (is_kernel_in_hyp_mode())
		kvm_timer_init_vhe();
	else
	if (!is_kernel_in_hyp_mode())
		cpu_init_hyp_mode();
}

static void cpu_hyp_init_features(void)
{
	cpu_set_hyp_vector();

	kvm_arm_init_debug();

	if (is_kernel_in_hyp_mode())
		kvm_timer_init_vhe();

	if (vgic_present)
		kvm_vgic_init_cpu_hardware();
}

static void cpu_hyp_reinit(void)
{
	cpu_hyp_reset();
	cpu_hyp_init_context();
	cpu_hyp_init_features();
}

static void _kvm_arch_hardware_enable(void *discard)
{
	if (!__this_cpu_read(kvm_arm_hardware_enabled)) {
@@ -1788,10 +1796,17 @@ static int do_pkvm_init(u32 hyp_va_bits)
	int ret;

	preempt_disable();
	hyp_install_host_vector();
	cpu_hyp_init_context();
	ret = kvm_call_hyp_nvhe(__pkvm_init, hyp_mem_base, hyp_mem_size,
				num_possible_cpus(), kern_hyp_va(per_cpu_base),
				hyp_va_bits);
	cpu_hyp_init_features();

	/*
	 * The stub hypercalls are now disabled, so set our local flag to
	 * prevent a later re-init attempt in kvm_arch_hardware_enable().
	 */
	__this_cpu_write(kvm_arm_hardware_enabled, 1);
	preempt_enable();

	return ret;
+17 −9
Original line number Diff line number Diff line
@@ -110,17 +110,14 @@ SYM_FUNC_START(__hyp_do_panic)
	b	__host_enter_for_panic
SYM_FUNC_END(__hyp_do_panic)

.macro host_el1_sync_vect
	.align 7
.L__vect_start\@:
	stp	x0, x1, [sp, #-16]!
	mrs	x0, esr_el2
	lsr	x0, x0, #ESR_ELx_EC_SHIFT
	cmp	x0, #ESR_ELx_EC_HVC64
	b.ne	__host_exit

SYM_FUNC_START(__host_hvc)
	ldp	x0, x1, [sp]		// Don't fixup the stack yet

	/* No stub for you, sonny Jim */
alternative_if ARM64_KVM_PROTECTED_MODE
	b	__host_exit
alternative_else_nop_endif

	/* Check for a stub HVC call */
	cmp	x0, #HVC_STUB_HCALL_NR
	b.hs	__host_exit
@@ -137,6 +134,17 @@ SYM_FUNC_END(__hyp_do_panic)
	ldr	x5, =__kvm_handle_stub_hvc
	hyp_pa	x5, x6
	br	x5
SYM_FUNC_END(__host_hvc)

.macro host_el1_sync_vect
	.align 7
.L__vect_start\@:
	stp	x0, x1, [sp, #-16]!
	mrs	x0, esr_el2
	lsr	x0, x0, #ESR_ELx_EC_SHIFT
	cmp	x0, #ESR_ELx_EC_HVC64
	b.eq	__host_hvc
	b	__host_exit
.L__vect_end\@:
.if ((.L__vect_end\@ - .L__vect_start\@) > 0x80)
	.error "host_el1_sync_vect larger than vector entry"