mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 02:50:49 +09:00
ANDROID: KVM: arm64: Add HVC handling for protected guests at EL2
Rather than forwarding guest hypercalls back to the host for handling, implement some basic handling at EL2 which will later be extending to provide additional functionality such as PSCI. Signed-off-by: Fuad Tabba <tabba@google.com> Signed-off-by: Will Deacon <willdeacon@google.com> Bug: 233587962 Change-Id: I14613c416078818b25bb29ed8899d7b71f8c40cc
This commit is contained in:
@@ -94,4 +94,6 @@ bool kvm_handle_pvm_restricted(struct kvm_vcpu *vcpu, u64 *exit_code);
|
||||
void kvm_reset_pvm_sys_regs(struct kvm_vcpu *vcpu);
|
||||
int kvm_check_pvm_sysreg_table(void);
|
||||
|
||||
bool kvm_handle_pvm_hvc64(struct kvm_vcpu *vcpu, u64 *exit_code);
|
||||
|
||||
#endif /* __ARM64_KVM_NVHE_PKVM_H__ */
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
* Author: Andrew Scull <ascull@google.com>
|
||||
*/
|
||||
|
||||
#include <kvm/arm_hypercalls.h>
|
||||
|
||||
#include <hyp/adjust_pc.h>
|
||||
|
||||
#include <asm/pgtable-types.h>
|
||||
@@ -44,6 +46,13 @@ static void handle_pvm_entry_wfx(struct pkvm_hyp_vcpu *hyp_vcpu)
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_pvm_entry_hvc64(struct pkvm_hyp_vcpu *hyp_vcpu)
|
||||
{
|
||||
u64 ret = READ_ONCE(hyp_vcpu->host_vcpu->arch.ctxt.regs.regs[0]);
|
||||
|
||||
vcpu_set_reg(&hyp_vcpu->vcpu, 0, ret);
|
||||
}
|
||||
|
||||
static void handle_pvm_entry_sys64(struct pkvm_hyp_vcpu *hyp_vcpu)
|
||||
{
|
||||
struct kvm_vcpu *host_vcpu = hyp_vcpu->host_vcpu;
|
||||
@@ -177,6 +186,21 @@ static void handle_pvm_exit_sys64(struct pkvm_hyp_vcpu *hyp_vcpu)
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_pvm_exit_hvc64(struct pkvm_hyp_vcpu *hyp_vcpu)
|
||||
{
|
||||
struct kvm_vcpu *host_vcpu = hyp_vcpu->host_vcpu;
|
||||
int i;
|
||||
|
||||
WRITE_ONCE(host_vcpu->arch.fault.esr_el2,
|
||||
hyp_vcpu->vcpu.arch.fault.esr_el2);
|
||||
|
||||
/* Pass the hvc function id (r0) as well as any potential arguments. */
|
||||
for (i = 0; i < 8; i++) {
|
||||
WRITE_ONCE(host_vcpu->arch.ctxt.regs.regs[i],
|
||||
vcpu_get_reg(&hyp_vcpu->vcpu, i));
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_pvm_exit_iabt(struct pkvm_hyp_vcpu *hyp_vcpu)
|
||||
{
|
||||
WRITE_ONCE(hyp_vcpu->host_vcpu->arch.fault.esr_el2,
|
||||
@@ -250,6 +274,7 @@ static void handle_vm_exit_abt(struct pkvm_hyp_vcpu *hyp_vcpu)
|
||||
static const hyp_entry_exit_handler_fn entry_hyp_pvm_handlers[] = {
|
||||
[0 ... ESR_ELx_EC_MAX] = NULL,
|
||||
[ESR_ELx_EC_WFx] = handle_pvm_entry_wfx,
|
||||
[ESR_ELx_EC_HVC64] = handle_pvm_entry_hvc64,
|
||||
[ESR_ELx_EC_SYS64] = handle_pvm_entry_sys64,
|
||||
[ESR_ELx_EC_IABT_LOW] = handle_pvm_entry_iabt,
|
||||
[ESR_ELx_EC_DABT_LOW] = handle_pvm_entry_dabt,
|
||||
@@ -258,6 +283,7 @@ static const hyp_entry_exit_handler_fn entry_hyp_pvm_handlers[] = {
|
||||
static const hyp_entry_exit_handler_fn exit_hyp_pvm_handlers[] = {
|
||||
[0 ... ESR_ELx_EC_MAX] = NULL,
|
||||
[ESR_ELx_EC_WFx] = handle_pvm_exit_wfx,
|
||||
[ESR_ELx_EC_HVC64] = handle_pvm_exit_hvc64,
|
||||
[ESR_ELx_EC_SYS64] = handle_pvm_exit_sys64,
|
||||
[ESR_ELx_EC_IABT_LOW] = handle_pvm_exit_iabt,
|
||||
[ESR_ELx_EC_DABT_LOW] = handle_pvm_exit_dabt,
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include <linux/kvm_host.h>
|
||||
#include <linux/mm.h>
|
||||
|
||||
#include <kvm/arm_hypercalls.h>
|
||||
|
||||
#include <asm/kvm_emulate.h>
|
||||
|
||||
#include <nvhe/mem_protect.h>
|
||||
@@ -803,3 +805,23 @@ err_unlock:
|
||||
hyp_spin_unlock(&vm_table_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handler for protected VM HVC calls.
|
||||
*
|
||||
* Returns true if the hypervisor has handled the exit, and control should go
|
||||
* back to the guest, or false if it hasn't.
|
||||
*/
|
||||
bool kvm_handle_pvm_hvc64(struct kvm_vcpu *vcpu, u64 *exit_code)
|
||||
{
|
||||
u32 fn = smccc_get_function(vcpu);
|
||||
|
||||
switch (fn) {
|
||||
case ARM_SMCCC_VERSION_FUNC_ID:
|
||||
/* Nothing to be handled by the host. Go back to the guest. */
|
||||
smccc_set_retval(vcpu, ARM_SMCCC_VERSION_1_1, 0, 0, 0);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,6 +217,7 @@ static const exit_handler_fn hyp_exit_handlers[] = {
|
||||
|
||||
static const exit_handler_fn pvm_exit_handlers[] = {
|
||||
[0 ... ESR_ELx_EC_MAX] = NULL,
|
||||
[ESR_ELx_EC_HVC64] = kvm_handle_pvm_hvc64,
|
||||
[ESR_ELx_EC_SYS64] = kvm_handle_pvm_sys64,
|
||||
[ESR_ELx_EC_SVE] = kvm_handle_pvm_restricted,
|
||||
[ESR_ELx_EC_FP_ASIMD] = kvm_hyp_handle_fpsimd,
|
||||
|
||||
Reference in New Issue
Block a user