mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 03:15:31 +09:00
ANDROID: KVM: arm64: pkvm: Manage the non-protected guest dirty state from EL1
In order to deal with state synchronisation between EL1 and EL2, we use the following setup: - On exit from EL2, the state is forcefully marked clean. - Should a trap be handled, the state is synchronised and immediately marked dirty - On vcpu_put(), the state is also marked dirty, since it can be modified by userspace Signed-off-by: Marc Zyngier <maz@kernel.org> Bug: 209580772 Change-Id: I47a889ca5432566f236de4630d81753348632f8a Signed-off-by: Will Deacon <willdeacon@google.com>
This commit is contained in:
committed by
Will Deacon
parent
a282cd5146
commit
28f12f0fa0
@@ -585,6 +585,10 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
|
||||
kvm_call_hyp(__vgic_v3_save_vmcr_aprs,
|
||||
&vcpu->arch.vgic_cpu.vgic_v3);
|
||||
kvm_call_hyp_nvhe(__pkvm_vcpu_put, vcpu);
|
||||
|
||||
/* __pkvm_vcpu_put implies a sync of the state */
|
||||
if (!kvm_vm_is_protected(vcpu->kvm))
|
||||
vcpu->arch.flags |= KVM_ARM64_PKVM_STATE_DIRTY;
|
||||
}
|
||||
|
||||
kvm_arch_vcpu_put_debug_state_flags(vcpu);
|
||||
@@ -791,8 +795,12 @@ int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)
|
||||
static_branch_inc(&userspace_irqchip_in_use);
|
||||
}
|
||||
|
||||
if (is_protected_kvm_enabled())
|
||||
if (is_protected_kvm_enabled()) {
|
||||
/* Start with the vcpu in a dirty state */
|
||||
if (!kvm_vm_is_protected(vcpu->kvm))
|
||||
vcpu->arch.flags |= KVM_ARM64_PKVM_STATE_DIRTY;
|
||||
ret = create_el2_shadow(kvm);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -201,6 +201,21 @@ static int handle_trap_exceptions(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
int handled;
|
||||
|
||||
/*
|
||||
* If we run a non-protected VM when protection is enabled
|
||||
* system-wide, resync the state from the hypervisor and mark
|
||||
* it as dirty on the host side if it wasn't dirty already
|
||||
* (which could happen if preemption has taken place).
|
||||
*/
|
||||
if (is_protected_kvm_enabled() && !kvm_vm_is_protected(vcpu->kvm)) {
|
||||
preempt_disable();
|
||||
if (!(vcpu->arch.flags & KVM_ARM64_PKVM_STATE_DIRTY)) {
|
||||
kvm_call_hyp_nvhe(__pkvm_vcpu_sync_state, vcpu);
|
||||
vcpu->arch.flags |= KVM_ARM64_PKVM_STATE_DIRTY;
|
||||
}
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
/*
|
||||
* See ARM ARM B1.14.1: "Hyp traps on instructions
|
||||
* that fail their condition code check"
|
||||
@@ -260,6 +275,13 @@ int handle_exit(struct kvm_vcpu *vcpu, int exception_index)
|
||||
/* For exit types that need handling before we can be preempted */
|
||||
void handle_exit_early(struct kvm_vcpu *vcpu, int exception_index)
|
||||
{
|
||||
/*
|
||||
* We just exited, so the state is clean from a hypervisor
|
||||
* perspective.
|
||||
*/
|
||||
if (is_protected_kvm_enabled())
|
||||
vcpu->arch.flags &= ~KVM_ARM64_PKVM_STATE_DIRTY;
|
||||
|
||||
if (ARM_SERROR_PENDING(exception_index)) {
|
||||
if (this_cpu_has_cap(ARM64_HAS_RAS_EXTN)) {
|
||||
u64 disr = kvm_vcpu_get_disr(vcpu);
|
||||
|
||||
Reference in New Issue
Block a user