[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 23 July 2013 19:18, Ian Campbell <ian.campbell@xxxxxxxxxx> wrote:
> 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?

I was thinking to provide a "high level" function to retrieve an
instruction just in case we need it in the future.

>> +        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...

Only r0p4 (for instance the arndale board) should be impacted by this errata.

> 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.

Sounds good. I will rework the patch with this solution.

>> +    {
>> +        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 a high-level helper to read an instruction is not needed, I will directly
mix this function with the decode part below.

>> +        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;
>
>



--
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.