Hi, On 1/8/20 11:12 AM, Mark Rutland wrote: > Hi Alex, > > On Fri, Dec 27, 2019 at 01:01:57PM +0000, Alexandru Elisei wrote: >> On 12/20/19 3:05 PM, Mark Rutland wrote: >>> When KVM injects an exception into a guest, it generates the PSTATE >>> value from scratch, configuring PSTATE.{M[4:0],DAIF}, and setting all >>> other bits to zero. >>> >>> This isn't correct, as the architecture specifies that some PSTATE bits >>> are (conditionally) cleared or set upon an exception, and others are >>> unchanged from the original context. >>> >>> This patch adds logic to match the architectural behaviour. To make this >>> simple to follow/audit/extend, documentation references are provided, >>> and bits are configured in order of their layout in SPSR_EL2. This >>> layout can be seen in the diagram on ARM DDI 0487E.a page C5-429. >>> +/* >>> + * When an exception is taken, most PSTATE fields are left unchanged in the >>> + * handler. However, some are explicitly overridden (e.g. M[4:0]). Luckily all >>> + * of the inherited bits have the same position in the AArch64/AArch32 SPSR_ELx >>> + * layouts, so we don't need to shuffle these for exceptions from AArch32 EL0. >>> + * >>> + * For the SPSR_ELx layout for AArch64, see ARM DDI 0487E.a page C5-429. >>> + * For the SPSR_ELx layout for AArch32, see ARM DDI 0487E.a page C5-426. >> The commit message mentions only the SPSR_ELx layout for AArch64. > That was intentional; there I was only providing rationale for how to > review the patch... > >>> + * Here we manipulate the fields in order of the AArch64 SPSR_ELx layout, from >>> + * MSB to LSB. > ... as also commented here. > > I can drop the reference from the commit message, if that's confusing? It's fine as it is, no need to change it. > >>> + */ >>> +static unsigned long get_except64_pstate(struct kvm_vcpu *vcpu) >>> +{ >>> + unsigned long sctlr = vcpu_read_sys_reg(vcpu, SCTLR_EL1); >>> + unsigned long old, new; >>> + >>> + old = *vcpu_cpsr(vcpu); >>> + new = 0; >>> + >>> + new |= (old & PSR_N_BIT); >>> + new |= (old & PSR_Z_BIT); >>> + new |= (old & PSR_C_BIT); >>> + new |= (old & PSR_V_BIT); >>> + >>> + // TODO: TCO (if/when ARMv8.5-MemTag is exposed to guests) >>> + >>> + new |= (old & PSR_DIT_BIT); >>> + >>> + // PSTATE.UAO is set to zero upon any exception to AArch64 >>> + // See ARM DDI 0487E.a, page D5-2579. >>> + >>> + // PSTATE.PAN is unchanged unless overridden by SCTLR_ELx.SPAN >>> + // See ARM DDI 0487E.a, page D5-2578. >>> + new |= (old & PSR_PAN_BIT); >>> + if (sctlr & SCTLR_EL1_SPAN) >>> + new |= PSR_PAN_BIT; >> On page D13-3264, it is stated that the PAN bit is set unconditionally if >> SCTLR_EL1.SPAN is clear, not set. > very good spot, and that's a much better reference. > > I had mistakenly assumed SPAN took effect when 0b1, since it wasn't > called nSPAN, and page D5-2578 doesn't mention the polarity of the bit: > > | When ARMv8.1-PAN is implemented, the SCTLR_EL1.SPAN and SCTLR_EL2.SPAN > | bits are used to control whether the PAN bit is set on an exception to > | EL1 or EL2. > > I've updated this to be: > > | // PSTATE.PAN is unchanged unless SCTLR_ELx.SPAN == 0b0 > | // SCTLR_ELx.SPAN is RES1 when ARMv8.1-PAN is not implemented > | // See ARM DDI 0487E.a, page D13-3264. > | new |= (old & PSR_PAN_BIT); > | if (!(sctlr & SCTLR_EL1_SPAN)) > | new |= PSR_PAN_BIT; Looks good. > > [...] > >> I've also checked the ARM ARM pages mentioned in the comments, and the >> references are correct. The SPSR_EL2 layouts for exceptions taken from AArch64, >> respectively AArch32, states are compatible with the way we create the SPSR_EL2 >> that will be used for eret'ing to the guest, just like the comment says. > Thanks for confirming this! > >> I have a suggestion. I think that in ARM ARM, shuffling things between sections >> happens a lot less often than adding/removing things from one particular >> section, so the pages referenced are more likely to change in later versions. >> How about referencing the section instead of the exact page? Something like: >> "This layout can be seen in the diagram on ARM DDI 0487E.a, section C5.2.18, >> when an exception is taken from AArch64 state"? > I did something like that initially, but the comments got very verbose, > and so I moved to doc + page/section numbers alone. > > The section numbers and headings also vary between revisions of the ARM > ARM, so I'd prefer to leave this as-is for now. I think it's always > going to be necessary to look at the referenced version of the ARM ARM > (in addition to a subsequent revision when updating things). Makes sense. Thanks, Alex > > Thanks, > Mark