[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 3/3] xen/arm: errata 766422: decode thumb store during data abort
On Tue, 2013-07-23 at 19:05 +0100, Julien Grall wrote: > From the errata document: > > When a non-secure non-hypervisor memory operation instruction generates a > stage2 page table translation fault, a trap to the hypervisor will be > triggered. > For an architecturally defined subset of instructions, the Hypervisor Syndrome > Register (HSR) will have the Instruction Syndrome Valid (ISV) bit set to 1âb1, > and the Rt field should reflect the source register (for stores) or > destination > register for loads. > On Cortex-A15, for Thumb and ThumbEE stores, the Rt value may be incorrect > and should not be used, even if the ISV bit is set. All loads, and all ARM > instruction set loads and stores, will have the correct Rt value if the ISV > bit is set. > > To avoid this issue, Xen needs to decode thumb store instruction and update > the transfer register. > > Signed-off-by: Julien Grall <julien.grall@xxxxxxxxxx> > --- > xen/arch/arm/traps.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 47 insertions(+) > > diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c > index d6dc37d..da2bef6 100644 > --- a/xen/arch/arm/traps.c > +++ b/xen/arch/arm/traps.c > @@ -35,6 +35,7 @@ > #include <asm/regs.h> > #include <asm/cpregs.h> > #include <asm/psci.h> > +#include <asm/guest_access.h> > > #include "io.h" > #include "vtimer.h" > @@ -996,6 +997,31 @@ done: > if (first) unmap_domain_page(first); > } > > +static int read_instruction(struct cpu_user_regs *regs, unsigned len, > + uint32_t *instr) > +{ > + int rc; > + > + rc = raw_copy_from_guest(instr, (void * __user)regs->pc, len); > + > + if ( rc ) > + return rc; > + > + switch ( len ) > + { > + /* 16-bit instruction */ > + case 2: > + *instr &= 0xffff; > + break; > + /* 32-bit instruction */ > + case 4: > + *instr = (*instr & 0xffff) << 16 | (*instr & 0xffff0000) >> 16; Since you only ever consult bits 12..15 or 0..3 of the result couldn't you just read two bytes from pc+2 instead of reading 4 bytes and swapping etc? > + break; > + } > + > + return 0; > +} > + > static void do_trap_data_abort_guest(struct cpu_user_regs *regs, > struct hsr_dabt dabt) > { > @@ -1021,6 +1047,27 @@ static void do_trap_data_abort_guest(struct > cpu_user_regs *regs, > if ( !dabt.valid ) > goto bad_data_abort; > > + /* > + * Errata 766422: Thumb store translation fault to Hypervisor may > + * not have correct HSR Rt value. > + */ > + if ( (regs->cpsr & PSR_THUMB) && dabt.write ) Is there some way to more precisely identify the processors with this errata? It'd be better to avoid this rigmarole when we can... I'd think about implementing this as a pseudo-cpuinfo thing setup either via identify_cpu or perhaps via a processor callback in proc-v7.S and friends. Then you can define and use something like cpu_has_errata766422 in the conditional and force it to zero for arm64 builds. > + { > + uint32_t instr = 0; > + > + rc = read_instruction(regs, dabt.len ? 4 : 2, &instr); You might as well just pass dabt.len directly I think, since you just decode it again with a switch. > + if ( rc ) > + goto bad_data_abort; > + > + /* Retrieve the transfer register from the instruction */ > + if ( dabt.len ) > + /* With 32-bit store instruction, the register is in [12..15] */ > + info.dabt.reg = (instr & 0xf000) >> 12; > + else > + /* With 16-bit store instruction, the register is in [0..3] */ > + info.dabt.reg = instr & 0x7; > + } > + > if (handle_mmio(&info)) > { > regs->pc += dabt.len ? 4 : 2; _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |