Re: [PATCH] MIPS: Add emulation for fpureg-mem unaligned access

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

some comments ...

On 16 June 2012 00:22, Lluis Batlle i Rossell <viric@xxxxxxxxxx> wrote:
> Reusing most of the code from lw,ld,sw,sd emulation,
> I add the emulation for lwc1,ldc1,swc1,sdc1.

What about lwxc1, ldxc1, swxc1 and sdxc1? These also require alignment.

> This avoids the direct SIGBUS sent to userspace processes that have
> misaligned memory accesses.
>
> I've tested the change in Loongson2F, with an own test program, and
> WebKit 1.4.0, as both were killed by sigbus without this patch.
>
> Signed-off: Lluis Batlle i Rossell <viric@xxxxxxxxxx>
> ---
>  arch/mips/kernel/unaligned.c |   43 +++++++++++++++++++++++++++++-------------
>  1 file changed, 30 insertions(+), 13 deletions(-)
>
> diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
> index 9c58bdf..4531e6c 100644
> --- a/arch/mips/kernel/unaligned.c
> +++ b/arch/mips/kernel/unaligned.c
> @@ -85,6 +85,7 @@
>  #include <asm/cop2.h>
>  #include <asm/inst.h>
>  #include <asm/uaccess.h>
> +#include <asm/fpu.h>
>
>  #define STR(x)  __STR(x)
>  #define __STR(x)  #x
> @@ -108,6 +109,7 @@ static void emulate_load_store_insn(struct pt_regs *regs,
>        union mips_instruction insn;
>        unsigned long value;
>        unsigned int res;
> +       fpureg_t *fpuregs;
>
>        perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
>
> @@ -183,6 +185,7 @@ static void emulate_load_store_insn(struct pt_regs *regs,
>                break;
>
>        case lw_op:
> +       case lwc1_op:
>                if (!access_ok(VERIFY_READ, addr, 4))
>                        goto sigbus;
>
> @@ -209,7 +212,12 @@ static void emulate_load_store_insn(struct pt_regs *regs,
>                if (res)
>                        goto fault;
>                compute_return_epc(regs);
> -               regs->regs[insn.i_format.rt] = value;
> +               if (insn.i_format.opcode == lw_op) {
> +                       regs->regs[insn.i_format.rt] = value;
> +               } else {
> +                       fpuregs = get_fpu_regs(current);
> +                       fpuregs[insn.i_format.rt] = value;
> +               }
>                break;
>
>        case lhu_op:
> @@ -291,6 +299,7 @@ static void emulate_load_store_insn(struct pt_regs *regs,
>                goto sigill;
>
>        case ld_op:
> +       case ldc1_op:
>  #ifdef CONFIG_64BIT

>From what I can tell, ldc1 is a valid MIPS32 instruction, so this
should probably be something like

        case ld_op:
#ifndef CONFIG_64BIT
                return sigill;
#endif
        case ldc1_op:
...

>                /*
>                 * A 32-bit kernel might be running on a 64-bit processor.  But
> @@ -325,7 +334,12 @@ static void emulate_load_store_insn(struct pt_regs *regs,
>                if (res)
>                        goto fault;
>                compute_return_epc(regs);
> -               regs->regs[insn.i_format.rt] = value;
> +               if (insn.i_format.opcode == ld_op) {
> +                       regs->regs[insn.i_format.rt] = value;
> +               } else {
> +                       fpuregs = get_fpu_regs(current);
> +                       fpuregs[insn.i_format.rt] = value;
> +               }
>                break;
>  #endif /* CONFIG_64BIT */
>
> @@ -370,10 +384,16 @@ static void emulate_load_store_insn(struct pt_regs *regs,
>                break;
>
>        case sw_op:
> +       case swc1_op:
>                if (!access_ok(VERIFY_WRITE, addr, 4))
>                        goto sigbus;
>
> -               value = regs->regs[insn.i_format.rt];
> +               if (insn.i_format.opcode == sw_op) {
> +                       value = regs->regs[insn.i_format.rt];
> +               } else {
> +                       fpuregs = get_fpu_regs(current);
> +                       value = fpuregs[insn.i_format.rt];
> +               }
>                __asm__ __volatile__ (
>  #ifdef __BIG_ENDIAN
>                        "1:\tswl\t%1,(%2)\n"
> @@ -401,6 +421,7 @@ static void emulate_load_store_insn(struct pt_regs *regs,
>                break;
>
>        case sd_op:
> +       case sdc1_op:
>  #ifdef CONFIG_64BIT

Same here.

>                /*
>                 * A 32-bit kernel might be running on a 64-bit processor.  But


Regards,
Jonas



[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux