diff options
Diffstat (limited to 'arch/powerpc/kernel/align.c')
-rw-r--r-- | arch/powerpc/kernel/align.c | 27 |
1 files changed, 19 insertions, 8 deletions
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c index cbc7c42cdb74..ec7a8b099dd9 100644 --- a/arch/powerpc/kernel/align.c +++ b/arch/powerpc/kernel/align.c | |||
@@ -807,14 +807,25 @@ int fix_alignment(struct pt_regs *regs) | |||
807 | nb = aligninfo[instr].len; | 807 | nb = aligninfo[instr].len; |
808 | flags = aligninfo[instr].flags; | 808 | flags = aligninfo[instr].flags; |
809 | 809 | ||
810 | /* ldbrx/stdbrx overlap lfs/stfs in the DSISR unfortunately */ | 810 | /* |
811 | if (IS_XFORM(instruction) && ((instruction >> 1) & 0x3ff) == 532) { | 811 | * Handle some cases which give overlaps in the DSISR values. |
812 | nb = 8; | 812 | */ |
813 | flags = LD+SW; | 813 | if (IS_XFORM(instruction)) { |
814 | } else if (IS_XFORM(instruction) && | 814 | switch (get_xop(instruction)) { |
815 | ((instruction >> 1) & 0x3ff) == 660) { | 815 | case 532: /* ldbrx */ |
816 | nb = 8; | 816 | nb = 8; |
817 | flags = ST+SW; | 817 | flags = LD+SW; |
818 | break; | ||
819 | case 660: /* stdbrx */ | ||
820 | nb = 8; | ||
821 | flags = ST+SW; | ||
822 | break; | ||
823 | case 20: /* lwarx */ | ||
824 | case 84: /* ldarx */ | ||
825 | case 116: /* lharx */ | ||
826 | case 276: /* lqarx */ | ||
827 | return 0; /* not emulated ever */ | ||
828 | } | ||
818 | } | 829 | } |
819 | 830 | ||
820 | /* Byteswap little endian loads and stores */ | 831 | /* Byteswap little endian loads and stores */ |