On Mon, Jan 09, 2017 at 01:24:05AM -0500, Jintack Lim wrote: > From: Christoffer Dall <christoffer.dall@xxxxxxxxxx> > > When entering virtual EL2, we need to reflect virtual EL2 register > states to corresponding shadow EL1 registers. We can simply copy them if > their formats are identical. Otherwise, we need to convert EL2 register > state to EL1 register state. > > Signed-off-by: Christoffer Dall <christoffer.dall@xxxxxxxxxx> > Signed-off-by: Jintack Lim <jintack@xxxxxxxxxxxxxxx> > --- > arch/arm64/kvm/context.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++ Looking at this again, I'm not sure 'context.c' is a very meaningful name. > 1 file changed, 71 insertions(+) > > diff --git a/arch/arm64/kvm/context.c b/arch/arm64/kvm/context.c > index acb4b1e..2e9e386 100644 > --- a/arch/arm64/kvm/context.c > +++ b/arch/arm64/kvm/context.c > @@ -17,6 +17,76 @@ > > #include <linux/kvm_host.h> > #include <asm/kvm_emulate.h> > +#include <asm/esr.h> > + > +struct el1_el2_map { > + enum vcpu_sysreg el1; > + enum el2_regs el2; > +}; > + > +/* > + * List of EL2 registers which can be directly applied to EL1 registers to > + * emulate running EL2 in EL1. The EL1 registers here must either be trapped > + * or paravirtualized in EL1. This series doesn't deal with paravirtualizaion but only targets 8.3 so we should clean up references to paravirtualization. > + */ > +static const struct el1_el2_map el1_el2_map[] = { > + { AMAIR_EL1, AMAIR_EL2 }, > + { MAIR_EL1, MAIR_EL2 }, > + { TTBR0_EL1, TTBR0_EL2 }, > + { ACTLR_EL1, ACTLR_EL2 }, > + { AFSR0_EL1, AFSR0_EL2 }, > + { AFSR1_EL1, AFSR1_EL2 }, > + { SCTLR_EL1, SCTLR_EL2 }, > + { VBAR_EL1, VBAR_EL2 }, > +}; > + > +static inline u64 tcr_el2_ips_to_tcr_el1_ps(u64 tcr_el2) > +{ > + return ((tcr_el2 & TCR_EL2_PS_MASK) >> TCR_EL2_PS_SHIFT) > + << TCR_IPS_SHIFT; > +} > + > +static inline u64 cptr_el2_to_cpacr_el1(u64 cptr_el2) > +{ > + u64 cpacr_el1 = 0; > + > + if (!(cptr_el2 & CPTR_EL2_TFP)) > + cpacr_el1 |= CPACR_EL1_FPEN; > + if (cptr_el2 & CPTR_EL2_TTA) > + cpacr_el1 |= CPACR_EL1_TTA; > + > + return cpacr_el1; > +} > + > +static void create_shadow_el1_sysregs(struct kvm_vcpu *vcpu) > +{ > + u64 *s_sys_regs = vcpu->arch.ctxt.shadow_sys_regs; > + u64 *el2_regs = vcpu->arch.ctxt.el2_regs; > + u64 tcr_el2; > + int i; > + > + for (i = 0; i < ARRAY_SIZE(el1_el2_map); i++) { > + const struct el1_el2_map *map = &el1_el2_map[i]; > + > + s_sys_regs[map->el1] = el2_regs[map->el2]; > + } > + > + tcr_el2 = el2_regs[TCR_EL2]; > + s_sys_regs[TCR_EL1] = > + TCR_EPD1 | /* disable TTBR1_EL1 */ > + ((tcr_el2 & TCR_EL2_TBI) ? TCR_TBI0 : 0) | > + tcr_el2_ips_to_tcr_el1_ps(tcr_el2) | > + (tcr_el2 & TCR_EL2_TG0_MASK) | > + (tcr_el2 & TCR_EL2_ORGN0_MASK) | > + (tcr_el2 & TCR_EL2_IRGN0_MASK) | > + (tcr_el2 & TCR_EL2_T0SZ_MASK); > + > + /* Rely on separate VMID for VA context, always use ASID 0 */ > + s_sys_regs[TTBR0_EL1] &= ~GENMASK_ULL(63, 48); > + s_sys_regs[TTBR1_EL1] = 0; > + > + s_sys_regs[CPACR_EL1] = cptr_el2_to_cpacr_el1(el2_regs[CPTR_EL2]); > +} > > /** > * kvm_arm_setup_shadow_state -- prepare shadow state based on emulated mode > @@ -37,6 +107,7 @@ void kvm_arm_setup_shadow_state(struct kvm_vcpu *vcpu) > else > ctxt->hw_pstate |= PSR_MODE_EL1t; > > + create_shadow_el1_sysregs(vcpu); > ctxt->hw_sys_regs = ctxt->shadow_sys_regs; > ctxt->hw_sp_el1 = ctxt->el2_regs[SP_EL2]; > } else { > -- > 1.9.1 > >