ANDROID: KVM: arm64: Move vgic state between host and hypervisor vcpu structures
Since the world switch vgic code operates on the hypervisor data structure, move the state back and forth between the host and hypervisor vcpu. This is currently limited to the VMCR and APR registers, but further patches will deal with the rest of the state. Note that some of the control settings (such as SRE) are always set to the same value. This will eventually be moved to initialisation time for the hypervisor structures. Bug: 357781595 Change-Id: I8a3a9009ce3408fe06ea272504f4f71c3d47b7bf Signed-off-by: Marc Zyngier <maz@kernel.org>
This commit is contained in:
committed by
Keir Fraser
parent
70e62ab0bf
commit
1fbada8c2c
@@ -659,6 +659,16 @@ static struct kvm_vcpu *__get_host_hyp_vcpus(struct kvm_vcpu *arg,
|
||||
__get_host_hyp_vcpus(__vcpu, hyp_vcpup); \
|
||||
})
|
||||
|
||||
#define get_host_hyp_vcpus_from_vgic_v3_cpu_if(ctxt, regnr, hyp_vcpup) \
|
||||
({ \
|
||||
DECLARE_REG(struct vgic_v3_cpu_if *, cif, ctxt, regnr); \
|
||||
struct kvm_vcpu *__vcpu = container_of(cif, \
|
||||
struct kvm_vcpu, \
|
||||
arch.vgic_cpu.vgic_v3); \
|
||||
\
|
||||
__get_host_hyp_vcpus(__vcpu, hyp_vcpup); \
|
||||
})
|
||||
|
||||
static void handle___kvm_vcpu_run(struct kvm_cpu_context *host_ctxt)
|
||||
{
|
||||
struct pkvm_hyp_vcpu *hyp_vcpu;
|
||||
@@ -837,16 +847,63 @@ static void handle___kvm_get_mdcr_el2(struct kvm_cpu_context *host_ctxt)
|
||||
|
||||
static void handle___vgic_v3_save_vmcr_aprs(struct kvm_cpu_context *host_ctxt)
|
||||
{
|
||||
DECLARE_REG(struct vgic_v3_cpu_if *, cpu_if, host_ctxt, 1);
|
||||
struct pkvm_hyp_vcpu *hyp_vcpu;
|
||||
struct kvm_vcpu *host_vcpu;
|
||||
|
||||
__vgic_v3_save_vmcr_aprs(kern_hyp_va(cpu_if));
|
||||
host_vcpu = get_host_hyp_vcpus_from_vgic_v3_cpu_if(host_ctxt, 1,
|
||||
&hyp_vcpu);
|
||||
if (!host_vcpu)
|
||||
return;
|
||||
|
||||
if (unlikely(hyp_vcpu)) {
|
||||
struct vgic_v3_cpu_if *hyp_cpu_if, *host_cpu_if;
|
||||
int i;
|
||||
|
||||
hyp_cpu_if = &hyp_vcpu->vcpu.arch.vgic_cpu.vgic_v3;
|
||||
__vgic_v3_save_vmcr_aprs(hyp_cpu_if);
|
||||
|
||||
host_cpu_if = &host_vcpu->arch.vgic_cpu.vgic_v3;
|
||||
host_cpu_if->vgic_vmcr = hyp_cpu_if->vgic_vmcr;
|
||||
for (i = 0; i < ARRAY_SIZE(host_cpu_if->vgic_ap0r); i++) {
|
||||
host_cpu_if->vgic_ap0r[i] = hyp_cpu_if->vgic_ap0r[i];
|
||||
host_cpu_if->vgic_ap1r[i] = hyp_cpu_if->vgic_ap1r[i];
|
||||
}
|
||||
} else {
|
||||
__vgic_v3_save_vmcr_aprs(&host_vcpu->arch.vgic_cpu.vgic_v3);
|
||||
}
|
||||
}
|
||||
|
||||
static void handle___vgic_v3_restore_vmcr_aprs(struct kvm_cpu_context *host_ctxt)
|
||||
{
|
||||
DECLARE_REG(struct vgic_v3_cpu_if *, cpu_if, host_ctxt, 1);
|
||||
struct pkvm_hyp_vcpu *hyp_vcpu;
|
||||
struct kvm_vcpu *host_vcpu;
|
||||
|
||||
__vgic_v3_restore_vmcr_aprs(kern_hyp_va(cpu_if));
|
||||
host_vcpu = get_host_hyp_vcpus_from_vgic_v3_cpu_if(host_ctxt, 1,
|
||||
&hyp_vcpu);
|
||||
if (!host_vcpu)
|
||||
return;
|
||||
|
||||
if (unlikely(hyp_vcpu)) {
|
||||
struct vgic_v3_cpu_if *hyp_cpu_if, *host_cpu_if;
|
||||
int i;
|
||||
|
||||
hyp_cpu_if = &hyp_vcpu->vcpu.arch.vgic_cpu.vgic_v3;
|
||||
host_cpu_if = &host_vcpu->arch.vgic_cpu.vgic_v3;
|
||||
|
||||
hyp_cpu_if->vgic_vmcr = host_cpu_if->vgic_vmcr;
|
||||
/* Should be a one-off */
|
||||
hyp_cpu_if->vgic_sre = (ICC_SRE_EL1_DIB |
|
||||
ICC_SRE_EL1_DFB |
|
||||
ICC_SRE_EL1_SRE);
|
||||
for (i = 0; i < ARRAY_SIZE(host_cpu_if->vgic_ap0r); i++) {
|
||||
hyp_cpu_if->vgic_ap0r[i] = host_cpu_if->vgic_ap0r[i];
|
||||
hyp_cpu_if->vgic_ap1r[i] = host_cpu_if->vgic_ap1r[i];
|
||||
}
|
||||
|
||||
__vgic_v3_restore_vmcr_aprs(hyp_cpu_if);
|
||||
} else {
|
||||
__vgic_v3_restore_vmcr_aprs(&host_vcpu->arch.vgic_cpu.vgic_v3);
|
||||
}
|
||||
}
|
||||
|
||||
static void handle___pkvm_init(struct kvm_cpu_context *host_ctxt)
|
||||
|
||||
Reference in New Issue
Block a user