Message ID | 20190621093843.220980-10-marc.zyngier@arm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | KVM: arm64: ARMv8.3 Nested Virtualization support | expand |
On Fri, Jun 21, 2019 at 10:37:53AM +0100, Marc Zyngier wrote: > From: Christoffer Dall <christoffer.dall@arm.com> > > When running a nested hypervisor we commonly have to figure out if > the VCPU mode is running in the context of a guest hypervisor or guest > guest, or just a normal guest. > > Add convenient primitives for this. > > Signed-off-by: Christoffer Dall <christoffer.dall@arm.com> > Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> > --- > arch/arm64/include/asm/kvm_emulate.h | 55 ++++++++++++++++++++++++++++ > 1 file changed, 55 insertions(+) > > diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h > index 39ffe41855bc..8f201ea56f6e 100644 > --- a/arch/arm64/include/asm/kvm_emulate.h > +++ b/arch/arm64/include/asm/kvm_emulate.h > @@ -191,6 +191,61 @@ static inline void vcpu_set_reg(struct kvm_vcpu *vcpu, u8 reg_num, > vcpu_gp_regs(vcpu)->regs.regs[reg_num] = val; > } > > +static inline bool vcpu_mode_el2_ctxt(const struct kvm_cpu_context *ctxt) > +{ > + unsigned long cpsr = ctxt->gp_regs.regs.pstate; > + u32 mode; > + > + if (cpsr & PSR_MODE32_BIT) > + return false; > + > + mode = cpsr & PSR_MODE_MASK; > + > + return mode == PSR_MODE_EL2h || mode == PSR_MODE_EL2t; We could also treat PSR_MODE32_BIT and PSR_MODE_MASK as a single field, similarly as in the next patch, say: switch (ctxt->gp_regs.regs.pstate & (PSR_MODE32_BIT | PSR_MODE_MASK)) { case PSR_MODE_EL2h: case PSR_MODE_EL2t: return true; } return false; (This is blatant bikeshedding...) [...] Cheers ---Dave
diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h index 39ffe41855bc..8f201ea56f6e 100644 --- a/arch/arm64/include/asm/kvm_emulate.h +++ b/arch/arm64/include/asm/kvm_emulate.h @@ -191,6 +191,61 @@ static inline void vcpu_set_reg(struct kvm_vcpu *vcpu, u8 reg_num, vcpu_gp_regs(vcpu)->regs.regs[reg_num] = val; } +static inline bool vcpu_mode_el2_ctxt(const struct kvm_cpu_context *ctxt) +{ + unsigned long cpsr = ctxt->gp_regs.regs.pstate; + u32 mode; + + if (cpsr & PSR_MODE32_BIT) + return false; + + mode = cpsr & PSR_MODE_MASK; + + return mode == PSR_MODE_EL2h || mode == PSR_MODE_EL2t; +} + +static inline bool vcpu_mode_el2(const struct kvm_vcpu *vcpu) +{ + return vcpu_mode_el2_ctxt(&vcpu->arch.ctxt); +} + +static inline bool __vcpu_el2_e2h_is_set(const struct kvm_cpu_context *ctxt) +{ + return ctxt->sys_regs[HCR_EL2] & HCR_E2H; +} + +static inline bool vcpu_el2_e2h_is_set(const struct kvm_vcpu *vcpu) +{ + return __vcpu_el2_e2h_is_set(&vcpu->arch.ctxt); +} + +static inline bool __vcpu_el2_tge_is_set(const struct kvm_cpu_context *ctxt) +{ + return ctxt->sys_regs[HCR_EL2] & HCR_TGE; +} + +static inline bool vcpu_el2_tge_is_set(const struct kvm_vcpu *vcpu) +{ + return __vcpu_el2_tge_is_set(&vcpu->arch.ctxt); +} + +static inline bool __is_hyp_ctxt(const struct kvm_cpu_context *ctxt) +{ + /* + * We are in a hypervisor context if the vcpu mode is EL2 or + * E2H and TGE bits are set. The latter means we are in the user space + * of the VHE kernel. ARMv8.1 ARM describes this as 'InHost' + */ + return vcpu_mode_el2_ctxt(ctxt) || + (__vcpu_el2_e2h_is_set(ctxt) && __vcpu_el2_tge_is_set(ctxt)) || + WARN_ON(__vcpu_el2_tge_is_set(ctxt)); +} + +static inline bool is_hyp_ctxt(const struct kvm_vcpu *vcpu) +{ + return __is_hyp_ctxt(&vcpu->arch.ctxt); +} + static inline unsigned long vcpu_read_spsr(const struct kvm_vcpu *vcpu) { if (vcpu_mode_is_32bit(vcpu))