All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH RFC 00/67] Add MIPS R6 support
@ 2014-12-18 15:09 ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

Hi,

This RFC patch adds support for MIPS R6. Some bits, (and mostly for the emulator)
have been taken from Leonid's branch on
http://git.linux-mips.org/cgit/yegoshin/mips.git/log/?id=refs/heads/android-linux-mti-r6-3.10

The rest of the stuff have mostly been re-written.

This patch is based on v3.18

The emulator is likely to change once David Daney's patches have been
merged	so treat the emulator patches lightly. It's not needed to run
an R6 userland.

This has been tested with mips32r6/mips64r6 BE/LE builds with
mipsel/mips/mips64/mips64el R6 buildroot and mipsel/mips64el R2
buildroot.

You can get an R6 toolchain from here:
http://community.imgtec.com/developers/mips/tools/codescape-mips-sdk/

A suitable public QEMU R6 tree can be found here:
https://github.com/prplfoundation/qemu.git i6400-mips64r6-PRIP4

Both 32-bit (-cpu mips32r6-generic) and 64-bit (-cpu mips64r6-generic)
R6 options are supported and expected to work with these patches.

You can find all these patches in the following git tree:
git://git.linux-mips.org/pub/scm/mchandras/linux.git 3.18-mipsr6-rfc-1


Leonid Yegoshin (20):
  MIPS: Add generic QEMU R6 PRid and cpu type identifiers
  MIPS: Add cases for CPU_QEMUR6
  MIPS: Add MIPS QEMUR6 probe support
  MIPS: Add build support for the MIPS R6 ISA
  MIPS: mm: uasm: Add signed 9-bit immediate related macros
  MIPS: mm: Add MIPS R6 instruction encodings
  MIPS: asm: module: define MODULE_PROC_FAMILY for MIPS R6
  MIPS: asm: stackframe: Do not preserve the HI/LO registers on MIPS R6
  MIPS: asm: asmmacro: Add MIPS R6 support to the simple EI/DI variants
  MIPS: asm: cpu: Add MIPSR6 ISA definitions
  MIPS: kernel: cpu-bugs64: Do not check R6 cores for existing 64-bit
    bugs
  MIPS: kernel: cevt-r4k: Add MIPS R6 to the c0_compare_interrupt
    handler
  MIPS: kernel: cpu-probe.c: Add support for MIPS R6
  MIPS: kernel: traps: Add MIPS R6 related definitions
  MIPS: kernel: r4k_switch: Add support for MIPS R6
  MIPS: kernel: r4k_fpu: Add support for MIPS R6
  MIPS: lib: memcpy: Add MIPS R6 support
  MIPS: lib: memset: Add MIPS R6 support
  MIPS: mm: tlbex: Add MIPS R6 case for the EHB instruction
  MIPS: kernel: mips-r2-to-r6-emul: Add R2 emulator for MIPS R6

Markos Chandras (47):
  MIPS: asm: asm: Add new macros to set ISA and arch asm annotations
  MIPS: asm: asmmacro: Drop unused 'reg' argument on MIPSR2
  MIPS: asm: asmmacro: Replace add instructions with "addui"
  MIPS: Use generic checksum functions for MIPS R6
  MIPS: asm: hazards: Add MIPSR6 definitions
  MIPS: asm: irqflags: Add MIPS R6 related definitions
  MIPS: asm: r4kcache: Add MIPS R6 cache unroll functions
  MIPS: asm: spram: Add MIPS R6 related definitions
  MIPS: asm: atomic: Update asm and ISA constrains for MIPS R6 support
  MIPS: asm: cmpxchg: Update asm and ISA constrains for MIPS R6 support
  MIPS: asm: bitops: Update asm and ISA constrains for MIPS R6 support
  MIPS: asm: futex: Update asm and ISA constrains for MIPS R6 support
  MIPS: asm: spinlock: Update asm constrains for MIPS R6 support
  MIPS: asm: spinlock: Replace sub instruction with addiu
  MIPS: kernel: entry.S: Add MIPS R6 related definitions
  MIPS: kernel: proc: Add MIPS R6 support to /proc/cpuinfo
  MIPS: kernel: genex: Set correct ISA level
  MIPS: kernel: cps-vec: Replace addi with addiu
  MIPS: uapi: inst: Add new opcodes for COP2 instructions
  MIPS: kernel: unaligned: Add support for the MIPS R6
  MIPS: mm: page: Add MIPS R6 support
  MIPS: mm: c-r4k: Set the correct ISA level
  MIPS: kernel: branch: Prepare the JR instruction for emulation on MIPS
    R6
  MIPS: kernel: branch: Prevent BLTZL emulation for MIPS R6
  MIPS: kernel: branch: Prevent BGEZL emulation for MIPS R6
  MIPS: kernel: branch: Prevent BLTZAL emulation for MIPS R6
  MIPS: kernel: branch: Prevent BGEZAL emulation for MIPS R6
  MIPS: kernel: branch: Prevent BEQL emulation for MIPS R6
  MIPS: kernel: branch: Prevent BNEL emulation for MIPS R6
  MIPS: kernel: branch: Prevent BLEZL emulation for MIPS R6
  MIPS: kernel: branch: Prevent BGTZL emulation for MIPS R6
  MIPS: uapi: inst: Add new BC1EQZ and BC1NEZ MIPS R6 opcodes
  MIPS: kernel: branch: Add support for the BC1{EQ,NE}Z FPU branches
  MIPS: kernel: branch: Add new MIPS R6 B{L,G}ΕZ{AL,}C emulation
  MIPS: kernel: branch: Add new MIPS R6 B{L,G}TZ{AL,}C emulation
  MIPS: kernel: branch: Emulate the branch compact (BC) on MIPS R6
  MIPS: kernel: branch: Emulate the BOVC, BEQC and BEQZALC R6
    instructions
  MIPS: kernel: branch: Emulate the BNVC, BNEC and BNEZLAC R6
    instructions
  MIPS: kernel: branch: Emulate the BALC R6 instruction
  MIPS: kernel: branch: Emulate the BEQZC and JIC instructions
  MIPS: math-emu: cp1emu: Move the fpucondbit struct to a header
  MIPS: Add LLB bit and related feature for the Config 5 CP0 register
  MIPS: asm: mipsregs: Add support for the LLADDR register
  MIPS: Make use of the ERETNC instruction on MIPS R6
  MIPS: Malta: malta-int: Set correct asm ISA level
  MIPS: Malta: Add support for building MIPS R6 kernel
  MIPS: Add Malta QEMU 32R6 defconfig

 arch/mips/Kconfig                           |   66 +-
 arch/mips/Makefile                          |    4 +
 arch/mips/configs/malta_qemu_32r6_defconfig |  193 +++
 arch/mips/include/asm/Kbuild                |    1 +
 arch/mips/include/asm/asm.h                 |   13 +
 arch/mips/include/asm/asmmacro.h            |   22 +-
 arch/mips/include/asm/atomic.h              |   50 +-
 arch/mips/include/asm/bitops.h              |   91 +-
 arch/mips/include/asm/checksum.h            |    6 +
 arch/mips/include/asm/cmpxchg.h             |   28 +-
 arch/mips/include/asm/cpu-features.h        |   17 +-
 arch/mips/include/asm/cpu-type.h            |    5 +
 arch/mips/include/asm/cpu.h                 |   11 +-
 arch/mips/include/asm/fpu_emulator.h        |   12 +
 arch/mips/include/asm/futex.h               |   24 +-
 arch/mips/include/asm/hazards.h             |    8 +-
 arch/mips/include/asm/irqflags.h            |    6 +-
 arch/mips/include/asm/mips-r2-to-r6-emul.h  |   94 ++
 arch/mips/include/asm/mipsregs.h            |    3 +
 arch/mips/include/asm/module.h              |    4 +
 arch/mips/include/asm/r4kcache.h            |  149 +-
 arch/mips/include/asm/spinlock.h            |   60 +-
 arch/mips/include/asm/spram.h               |    4 +-
 arch/mips/include/asm/stackframe.h          |    8 +-
 arch/mips/include/asm/switch_to.h           |    9 +-
 arch/mips/include/asm/thread_info.h         |    2 +-
 arch/mips/include/uapi/asm/inst.h           |   32 +-
 arch/mips/kernel/Makefile                   |    2 +
 arch/mips/kernel/asm-offsets.c              |    1 +
 arch/mips/kernel/branch.c                   |  251 ++-
 arch/mips/kernel/cevt-r4k.c                 |    2 +-
 arch/mips/kernel/cps-vec.S                  |   16 +-
 arch/mips/kernel/cpu-bugs64.c               |   11 +-
 arch/mips/kernel/cpu-probe.c                |   24 +-
 arch/mips/kernel/entry.S                    |   23 +-
 arch/mips/kernel/genex.S                    |    2 +-
 arch/mips/kernel/idle.c                     |    1 +
 arch/mips/kernel/kprobes.c                  |    8 +-
 arch/mips/kernel/mips-r2-to-r6-emul.c       | 2377 +++++++++++++++++++++++++++
 arch/mips/kernel/mips_ksyms.c               |    2 +
 arch/mips/kernel/proc.c                     |    9 +-
 arch/mips/kernel/r4k_fpu.S                  |   10 +-
 arch/mips/kernel/r4k_switch.S               |   12 +-
 arch/mips/kernel/spram.c                    |    1 +
 arch/mips/kernel/traps.c                    |   41 +-
 arch/mips/kernel/unaligned.c                |  398 ++++-
 arch/mips/lib/Makefile                      |    1 +
 arch/mips/lib/memcpy.S                      |   23 +
 arch/mips/lib/memset.S                      |   47 +
 arch/mips/lib/mips-atomic.c                 |    2 +-
 arch/mips/math-emu/cp1emu.c                 |   20 +-
 arch/mips/mm/c-r4k.c                        |    3 +-
 arch/mips/mm/page.c                         |   20 +-
 arch/mips/mm/sc-mips.c                      |    1 +
 arch/mips/mm/tlbex.c                        |    3 +-
 arch/mips/mm/uasm-mips.c                    |   36 +-
 arch/mips/mm/uasm.c                         |   13 +-
 arch/mips/mti-malta/malta-int.c             |    2 +-
 58 files changed, 4008 insertions(+), 276 deletions(-)
 create mode 100644 arch/mips/configs/malta_qemu_32r6_defconfig
 create mode 100644 arch/mips/include/asm/mips-r2-to-r6-emul.h
 create mode 100644 arch/mips/kernel/mips-r2-to-r6-emul.c

-- 
2.2.0

^ permalink raw reply	[flat|nested] 187+ messages in thread

* [PATCH RFC 00/67] Add MIPS R6 support
@ 2014-12-18 15:09 ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

Hi,

This RFC patch adds support for MIPS R6. Some bits, (and mostly for the emulator)
have been taken from Leonid's branch on
http://git.linux-mips.org/cgit/yegoshin/mips.git/log/?id=refs/heads/android-linux-mti-r6-3.10

The rest of the stuff have mostly been re-written.

This patch is based on v3.18

The emulator is likely to change once David Daney's patches have been
merged	so treat the emulator patches lightly. It's not needed to run
an R6 userland.

This has been tested with mips32r6/mips64r6 BE/LE builds with
mipsel/mips/mips64/mips64el R6 buildroot and mipsel/mips64el R2
buildroot.

You can get an R6 toolchain from here:
http://community.imgtec.com/developers/mips/tools/codescape-mips-sdk/

A suitable public QEMU R6 tree can be found here:
https://github.com/prplfoundation/qemu.git i6400-mips64r6-PRIP4

Both 32-bit (-cpu mips32r6-generic) and 64-bit (-cpu mips64r6-generic)
R6 options are supported and expected to work with these patches.

You can find all these patches in the following git tree:
git://git.linux-mips.org/pub/scm/mchandras/linux.git 3.18-mipsr6-rfc-1


Leonid Yegoshin (20):
  MIPS: Add generic QEMU R6 PRid and cpu type identifiers
  MIPS: Add cases for CPU_QEMUR6
  MIPS: Add MIPS QEMUR6 probe support
  MIPS: Add build support for the MIPS R6 ISA
  MIPS: mm: uasm: Add signed 9-bit immediate related macros
  MIPS: mm: Add MIPS R6 instruction encodings
  MIPS: asm: module: define MODULE_PROC_FAMILY for MIPS R6
  MIPS: asm: stackframe: Do not preserve the HI/LO registers on MIPS R6
  MIPS: asm: asmmacro: Add MIPS R6 support to the simple EI/DI variants
  MIPS: asm: cpu: Add MIPSR6 ISA definitions
  MIPS: kernel: cpu-bugs64: Do not check R6 cores for existing 64-bit
    bugs
  MIPS: kernel: cevt-r4k: Add MIPS R6 to the c0_compare_interrupt
    handler
  MIPS: kernel: cpu-probe.c: Add support for MIPS R6
  MIPS: kernel: traps: Add MIPS R6 related definitions
  MIPS: kernel: r4k_switch: Add support for MIPS R6
  MIPS: kernel: r4k_fpu: Add support for MIPS R6
  MIPS: lib: memcpy: Add MIPS R6 support
  MIPS: lib: memset: Add MIPS R6 support
  MIPS: mm: tlbex: Add MIPS R6 case for the EHB instruction
  MIPS: kernel: mips-r2-to-r6-emul: Add R2 emulator for MIPS R6

Markos Chandras (47):
  MIPS: asm: asm: Add new macros to set ISA and arch asm annotations
  MIPS: asm: asmmacro: Drop unused 'reg' argument on MIPSR2
  MIPS: asm: asmmacro: Replace add instructions with "addui"
  MIPS: Use generic checksum functions for MIPS R6
  MIPS: asm: hazards: Add MIPSR6 definitions
  MIPS: asm: irqflags: Add MIPS R6 related definitions
  MIPS: asm: r4kcache: Add MIPS R6 cache unroll functions
  MIPS: asm: spram: Add MIPS R6 related definitions
  MIPS: asm: atomic: Update asm and ISA constrains for MIPS R6 support
  MIPS: asm: cmpxchg: Update asm and ISA constrains for MIPS R6 support
  MIPS: asm: bitops: Update asm and ISA constrains for MIPS R6 support
  MIPS: asm: futex: Update asm and ISA constrains for MIPS R6 support
  MIPS: asm: spinlock: Update asm constrains for MIPS R6 support
  MIPS: asm: spinlock: Replace sub instruction with addiu
  MIPS: kernel: entry.S: Add MIPS R6 related definitions
  MIPS: kernel: proc: Add MIPS R6 support to /proc/cpuinfo
  MIPS: kernel: genex: Set correct ISA level
  MIPS: kernel: cps-vec: Replace addi with addiu
  MIPS: uapi: inst: Add new opcodes for COP2 instructions
  MIPS: kernel: unaligned: Add support for the MIPS R6
  MIPS: mm: page: Add MIPS R6 support
  MIPS: mm: c-r4k: Set the correct ISA level
  MIPS: kernel: branch: Prepare the JR instruction for emulation on MIPS
    R6
  MIPS: kernel: branch: Prevent BLTZL emulation for MIPS R6
  MIPS: kernel: branch: Prevent BGEZL emulation for MIPS R6
  MIPS: kernel: branch: Prevent BLTZAL emulation for MIPS R6
  MIPS: kernel: branch: Prevent BGEZAL emulation for MIPS R6
  MIPS: kernel: branch: Prevent BEQL emulation for MIPS R6
  MIPS: kernel: branch: Prevent BNEL emulation for MIPS R6
  MIPS: kernel: branch: Prevent BLEZL emulation for MIPS R6
  MIPS: kernel: branch: Prevent BGTZL emulation for MIPS R6
  MIPS: uapi: inst: Add new BC1EQZ and BC1NEZ MIPS R6 opcodes
  MIPS: kernel: branch: Add support for the BC1{EQ,NE}Z FPU branches
  MIPS: kernel: branch: Add new MIPS R6 B{L,G}ΕZ{AL,}C emulation
  MIPS: kernel: branch: Add new MIPS R6 B{L,G}TZ{AL,}C emulation
  MIPS: kernel: branch: Emulate the branch compact (BC) on MIPS R6
  MIPS: kernel: branch: Emulate the BOVC, BEQC and BEQZALC R6
    instructions
  MIPS: kernel: branch: Emulate the BNVC, BNEC and BNEZLAC R6
    instructions
  MIPS: kernel: branch: Emulate the BALC R6 instruction
  MIPS: kernel: branch: Emulate the BEQZC and JIC instructions
  MIPS: math-emu: cp1emu: Move the fpucondbit struct to a header
  MIPS: Add LLB bit and related feature for the Config 5 CP0 register
  MIPS: asm: mipsregs: Add support for the LLADDR register
  MIPS: Make use of the ERETNC instruction on MIPS R6
  MIPS: Malta: malta-int: Set correct asm ISA level
  MIPS: Malta: Add support for building MIPS R6 kernel
  MIPS: Add Malta QEMU 32R6 defconfig

 arch/mips/Kconfig                           |   66 +-
 arch/mips/Makefile                          |    4 +
 arch/mips/configs/malta_qemu_32r6_defconfig |  193 +++
 arch/mips/include/asm/Kbuild                |    1 +
 arch/mips/include/asm/asm.h                 |   13 +
 arch/mips/include/asm/asmmacro.h            |   22 +-
 arch/mips/include/asm/atomic.h              |   50 +-
 arch/mips/include/asm/bitops.h              |   91 +-
 arch/mips/include/asm/checksum.h            |    6 +
 arch/mips/include/asm/cmpxchg.h             |   28 +-
 arch/mips/include/asm/cpu-features.h        |   17 +-
 arch/mips/include/asm/cpu-type.h            |    5 +
 arch/mips/include/asm/cpu.h                 |   11 +-
 arch/mips/include/asm/fpu_emulator.h        |   12 +
 arch/mips/include/asm/futex.h               |   24 +-
 arch/mips/include/asm/hazards.h             |    8 +-
 arch/mips/include/asm/irqflags.h            |    6 +-
 arch/mips/include/asm/mips-r2-to-r6-emul.h  |   94 ++
 arch/mips/include/asm/mipsregs.h            |    3 +
 arch/mips/include/asm/module.h              |    4 +
 arch/mips/include/asm/r4kcache.h            |  149 +-
 arch/mips/include/asm/spinlock.h            |   60 +-
 arch/mips/include/asm/spram.h               |    4 +-
 arch/mips/include/asm/stackframe.h          |    8 +-
 arch/mips/include/asm/switch_to.h           |    9 +-
 arch/mips/include/asm/thread_info.h         |    2 +-
 arch/mips/include/uapi/asm/inst.h           |   32 +-
 arch/mips/kernel/Makefile                   |    2 +
 arch/mips/kernel/asm-offsets.c              |    1 +
 arch/mips/kernel/branch.c                   |  251 ++-
 arch/mips/kernel/cevt-r4k.c                 |    2 +-
 arch/mips/kernel/cps-vec.S                  |   16 +-
 arch/mips/kernel/cpu-bugs64.c               |   11 +-
 arch/mips/kernel/cpu-probe.c                |   24 +-
 arch/mips/kernel/entry.S                    |   23 +-
 arch/mips/kernel/genex.S                    |    2 +-
 arch/mips/kernel/idle.c                     |    1 +
 arch/mips/kernel/kprobes.c                  |    8 +-
 arch/mips/kernel/mips-r2-to-r6-emul.c       | 2377 +++++++++++++++++++++++++++
 arch/mips/kernel/mips_ksyms.c               |    2 +
 arch/mips/kernel/proc.c                     |    9 +-
 arch/mips/kernel/r4k_fpu.S                  |   10 +-
 arch/mips/kernel/r4k_switch.S               |   12 +-
 arch/mips/kernel/spram.c                    |    1 +
 arch/mips/kernel/traps.c                    |   41 +-
 arch/mips/kernel/unaligned.c                |  398 ++++-
 arch/mips/lib/Makefile                      |    1 +
 arch/mips/lib/memcpy.S                      |   23 +
 arch/mips/lib/memset.S                      |   47 +
 arch/mips/lib/mips-atomic.c                 |    2 +-
 arch/mips/math-emu/cp1emu.c                 |   20 +-
 arch/mips/mm/c-r4k.c                        |    3 +-
 arch/mips/mm/page.c                         |   20 +-
 arch/mips/mm/sc-mips.c                      |    1 +
 arch/mips/mm/tlbex.c                        |    3 +-
 arch/mips/mm/uasm-mips.c                    |   36 +-
 arch/mips/mm/uasm.c                         |   13 +-
 arch/mips/mti-malta/malta-int.c             |    2 +-
 58 files changed, 4008 insertions(+), 276 deletions(-)
 create mode 100644 arch/mips/configs/malta_qemu_32r6_defconfig
 create mode 100644 arch/mips/include/asm/mips-r2-to-r6-emul.h
 create mode 100644 arch/mips/kernel/mips-r2-to-r6-emul.c

-- 
2.2.0

^ permalink raw reply	[flat|nested] 187+ messages in thread

* [PATCH RFC 01/67] MIPS: Add generic QEMU R6 PRid and cpu type identifiers
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

Latest versions of QEMU added support for mips32r6-generic and
mips64r6-generic cpu types so add related definitions in preparation
of MIPS R6 support.

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/cpu.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index dfdc77ed1839..23a5dbc0ee06 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -93,6 +93,7 @@
  * These are the PRID's for when 23:16 == PRID_COMP_MIPS
  */
 
+#define PRID_IMP_QEMUR6		0x0000
 #define PRID_IMP_4KC		0x8000
 #define PRID_IMP_5KC		0x8100
 #define PRID_IMP_20KC		0x8200
@@ -311,6 +312,8 @@ enum cpu_type_enum {
 	CPU_LOONGSON3, CPU_CAVIUM_OCTEON, CPU_CAVIUM_OCTEON_PLUS,
 	CPU_CAVIUM_OCTEON2, CPU_CAVIUM_OCTEON3, CPU_XLR, CPU_XLP,
 
+	CPU_QEMUR6,
+
 	CPU_LAST
 };
 
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 01/67] MIPS: Add generic QEMU R6 PRid and cpu type identifiers
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

Latest versions of QEMU added support for mips32r6-generic and
mips64r6-generic cpu types so add related definitions in preparation
of MIPS R6 support.

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/cpu.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index dfdc77ed1839..23a5dbc0ee06 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -93,6 +93,7 @@
  * These are the PRID's for when 23:16 == PRID_COMP_MIPS
  */
 
+#define PRID_IMP_QEMUR6		0x0000
 #define PRID_IMP_4KC		0x8000
 #define PRID_IMP_5KC		0x8100
 #define PRID_IMP_20KC		0x8200
@@ -311,6 +312,8 @@ enum cpu_type_enum {
 	CPU_LOONGSON3, CPU_CAVIUM_OCTEON, CPU_CAVIUM_OCTEON_PLUS,
 	CPU_CAVIUM_OCTEON2, CPU_CAVIUM_OCTEON3, CPU_XLR, CPU_XLP,
 
+	CPU_QEMUR6,
+
 	CPU_LAST
 };
 
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 02/67] MIPS: Add cases for CPU_QEMUR6
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

Add a CPU_QEMUR6 case to various switch statements.

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/cpu-type.h | 5 +++++
 arch/mips/kernel/idle.c          | 1 +
 arch/mips/kernel/spram.c         | 1 +
 arch/mips/kernel/traps.c         | 1 +
 arch/mips/mm/c-r4k.c             | 1 +
 arch/mips/mm/sc-mips.c           | 1 +
 arch/mips/mm/tlbex.c             | 1 +
 7 files changed, 11 insertions(+)

diff --git a/arch/mips/include/asm/cpu-type.h b/arch/mips/include/asm/cpu-type.h
index b4e2bd87df50..68fb94592ae3 100644
--- a/arch/mips/include/asm/cpu-type.h
+++ b/arch/mips/include/asm/cpu-type.h
@@ -54,6 +54,11 @@ static inline int __pure __get_cpu_type(const int cpu_type)
 	case CPU_M5150:
 #endif
 
+#if defined(CONFIG_SYS_HAS_CPU_MIPS32_R6) || \
+    defined(CONFIG_SYS_HAS_CPU_MIPS64_R6)
+	case CPU_QEMUR6:
+#endif
+
 #ifdef CONFIG_SYS_HAS_CPU_MIPS64_R1
 	case CPU_5KC:
 	case CPU_5KE:
diff --git a/arch/mips/kernel/idle.c b/arch/mips/kernel/idle.c
index 0b9082b6b683..8abb7336a3d0 100644
--- a/arch/mips/kernel/idle.c
+++ b/arch/mips/kernel/idle.c
@@ -186,6 +186,7 @@ void __init check_wait(void)
 	case CPU_PROAPTIV:
 	case CPU_P5600:
 	case CPU_M5150:
+	case CPU_QEMUR6:
 		cpu_wait = r4k_wait;
 		if (read_c0_config7() & MIPS_CONF7_WII)
 			cpu_wait = r4k_wait_irqoff;
diff --git a/arch/mips/kernel/spram.c b/arch/mips/kernel/spram.c
index 67f2495def1c..35dbad02b040 100644
--- a/arch/mips/kernel/spram.c
+++ b/arch/mips/kernel/spram.c
@@ -208,6 +208,7 @@ void spram_config(void)
 	case CPU_INTERAPTIV:
 	case CPU_PROAPTIV:
 	case CPU_P5600:
+	case CPU_QEMUR6:
 		config0 = read_c0_config();
 		/* FIXME: addresses are Malta specific */
 		if (config0 & (1<<24)) {
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 22b19c275044..b3568c049b72 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1486,6 +1486,7 @@ static inline void parity_protection_init(void)
 	case CPU_INTERAPTIV:
 	case CPU_PROAPTIV:
 	case CPU_P5600:
+	case CPU_QEMUR6:
 		{
 #define ERRCTL_PE	0x80000000
 #define ERRCTL_L2P	0x00800000
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index fbcd8674ff1d..a659770bc539 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -1243,6 +1243,7 @@ static void probe_pcache(void)
 	case CPU_P5600:
 	case CPU_PROAPTIV:
 	case CPU_M5150:
+	case CPU_QEMUR6:
 		if (!(read_c0_config7() & MIPS_CONF7_IAR) &&
 		    (c->icache.waysize > PAGE_SIZE))
 			c->icache.flags |= MIPS_CACHE_ALIASES;
diff --git a/arch/mips/mm/sc-mips.c b/arch/mips/mm/sc-mips.c
index 99eb8fabab60..6133b2de8a9c 100644
--- a/arch/mips/mm/sc-mips.c
+++ b/arch/mips/mm/sc-mips.c
@@ -81,6 +81,7 @@ static inline int mips_sc_is_activated(struct cpuinfo_mips *c)
 	case CPU_PROAPTIV:
 	case CPU_P5600:
 	case CPU_BMIPS5000:
+	case CPU_QEMUR6:
 		if (config2 & (1 << 12))
 			return 0;
 	}
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index e3328a96e809..14e5fae71a06 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -514,6 +514,7 @@ static void build_tlb_write_entry(u32 **p, struct uasm_label **l,
 		case CPU_PROAPTIV:
 		case CPU_P5600:
 		case CPU_M5150:
+		case CPU_QEMUR6:
 			break;
 
 		default:
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 02/67] MIPS: Add cases for CPU_QEMUR6
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

Add a CPU_QEMUR6 case to various switch statements.

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/cpu-type.h | 5 +++++
 arch/mips/kernel/idle.c          | 1 +
 arch/mips/kernel/spram.c         | 1 +
 arch/mips/kernel/traps.c         | 1 +
 arch/mips/mm/c-r4k.c             | 1 +
 arch/mips/mm/sc-mips.c           | 1 +
 arch/mips/mm/tlbex.c             | 1 +
 7 files changed, 11 insertions(+)

diff --git a/arch/mips/include/asm/cpu-type.h b/arch/mips/include/asm/cpu-type.h
index b4e2bd87df50..68fb94592ae3 100644
--- a/arch/mips/include/asm/cpu-type.h
+++ b/arch/mips/include/asm/cpu-type.h
@@ -54,6 +54,11 @@ static inline int __pure __get_cpu_type(const int cpu_type)
 	case CPU_M5150:
 #endif
 
+#if defined(CONFIG_SYS_HAS_CPU_MIPS32_R6) || \
+    defined(CONFIG_SYS_HAS_CPU_MIPS64_R6)
+	case CPU_QEMUR6:
+#endif
+
 #ifdef CONFIG_SYS_HAS_CPU_MIPS64_R1
 	case CPU_5KC:
 	case CPU_5KE:
diff --git a/arch/mips/kernel/idle.c b/arch/mips/kernel/idle.c
index 0b9082b6b683..8abb7336a3d0 100644
--- a/arch/mips/kernel/idle.c
+++ b/arch/mips/kernel/idle.c
@@ -186,6 +186,7 @@ void __init check_wait(void)
 	case CPU_PROAPTIV:
 	case CPU_P5600:
 	case CPU_M5150:
+	case CPU_QEMUR6:
 		cpu_wait = r4k_wait;
 		if (read_c0_config7() & MIPS_CONF7_WII)
 			cpu_wait = r4k_wait_irqoff;
diff --git a/arch/mips/kernel/spram.c b/arch/mips/kernel/spram.c
index 67f2495def1c..35dbad02b040 100644
--- a/arch/mips/kernel/spram.c
+++ b/arch/mips/kernel/spram.c
@@ -208,6 +208,7 @@ void spram_config(void)
 	case CPU_INTERAPTIV:
 	case CPU_PROAPTIV:
 	case CPU_P5600:
+	case CPU_QEMUR6:
 		config0 = read_c0_config();
 		/* FIXME: addresses are Malta specific */
 		if (config0 & (1<<24)) {
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 22b19c275044..b3568c049b72 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1486,6 +1486,7 @@ static inline void parity_protection_init(void)
 	case CPU_INTERAPTIV:
 	case CPU_PROAPTIV:
 	case CPU_P5600:
+	case CPU_QEMUR6:
 		{
 #define ERRCTL_PE	0x80000000
 #define ERRCTL_L2P	0x00800000
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index fbcd8674ff1d..a659770bc539 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -1243,6 +1243,7 @@ static void probe_pcache(void)
 	case CPU_P5600:
 	case CPU_PROAPTIV:
 	case CPU_M5150:
+	case CPU_QEMUR6:
 		if (!(read_c0_config7() & MIPS_CONF7_IAR) &&
 		    (c->icache.waysize > PAGE_SIZE))
 			c->icache.flags |= MIPS_CACHE_ALIASES;
diff --git a/arch/mips/mm/sc-mips.c b/arch/mips/mm/sc-mips.c
index 99eb8fabab60..6133b2de8a9c 100644
--- a/arch/mips/mm/sc-mips.c
+++ b/arch/mips/mm/sc-mips.c
@@ -81,6 +81,7 @@ static inline int mips_sc_is_activated(struct cpuinfo_mips *c)
 	case CPU_PROAPTIV:
 	case CPU_P5600:
 	case CPU_BMIPS5000:
+	case CPU_QEMUR6:
 		if (config2 & (1 << 12))
 			return 0;
 	}
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index e3328a96e809..14e5fae71a06 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -514,6 +514,7 @@ static void build_tlb_write_entry(u32 **p, struct uasm_label **l,
 		case CPU_PROAPTIV:
 		case CPU_P5600:
 		case CPU_M5150:
+		case CPU_QEMUR6:
 			break;
 
 		default:
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 03/67] MIPS: Add MIPS QEMUR6 probe support
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

Add a case in cpu_probe_mips for the MIPS QEMUR6 processor ID.

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/cpu-probe.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index dc49cf30c2db..08574035b239 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -836,6 +836,11 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
 {
 	c->writecombine = _CACHE_UNCACHED_ACCELERATED;
 	switch (c->processor_id & PRID_IMP_MASK) {
+	case PRID_IMP_QEMUR6:
+		c->writecombine = _CACHE_UNCACHED;
+		c->cputype = CPU_QEMUR6;
+		__cpu_name[cpu] = "MIPS QEMU R6";
+		break;
 	case PRID_IMP_4KC:
 		c->cputype = CPU_4KC;
 		c->writecombine = _CACHE_UNCACHED;
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 03/67] MIPS: Add MIPS QEMUR6 probe support
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

Add a case in cpu_probe_mips for the MIPS QEMUR6 processor ID.

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/cpu-probe.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index dc49cf30c2db..08574035b239 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -836,6 +836,11 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
 {
 	c->writecombine = _CACHE_UNCACHED_ACCELERATED;
 	switch (c->processor_id & PRID_IMP_MASK) {
+	case PRID_IMP_QEMUR6:
+		c->writecombine = _CACHE_UNCACHED;
+		c->cputype = CPU_QEMUR6;
+		__cpu_name[cpu] = "MIPS QEMU R6";
+		break;
 	case PRID_IMP_4KC:
 		c->cputype = CPU_4KC;
 		c->writecombine = _CACHE_UNCACHED;
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 04/67] MIPS: Add build support for the MIPS R6 ISA
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

Add build support for the latest revision (R6) of the MIPS ISA.
microMIPS is not yet supported.

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/Kconfig  | 46 ++++++++++++++++++++++++++++++++++++++++++----
 arch/mips/Makefile |  4 ++++
 2 files changed, 46 insertions(+), 4 deletions(-)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 9536ef912f59..12e831b815b1 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1268,6 +1268,20 @@ config CPU_MIPS32_R2
 	  specific type of processor in your system, choose those that one
 	  otherwise CPU_MIPS32_R1 is a safe bet for any MIPS32 system.
 
+config CPU_MIPS32_R6
+	bool "MIPS32 Release 6 (EXPERIMENTAL)"
+	depends on SYS_HAS_CPU_MIPS32_R6
+	select CPU_HAS_PREFETCH
+	select CPU_SUPPORTS_32BIT_KERNEL
+	select CPU_SUPPORTS_HIGHMEM
+	select CPU_SUPPORTS_MSA
+	select HAVE_KVM
+	help
+	  Choose this option to build a kernel for release 6 or later of the
+	  MIPS32 architecture.  New MIPS processors, starting with the Warrior
+	  family, are based on a MIPS32r6 processor. If you own an older
+	  processor, you probably need to select MIPS32r1 or MIPS32r2 instead.
+
 config CPU_MIPS64_R1
 	bool "MIPS64 Release 1"
 	depends on SYS_HAS_CPU_MIPS64_R1
@@ -1303,6 +1317,20 @@ config CPU_MIPS64_R2
 	  specific type of processor in your system, choose those that one
 	  otherwise CPU_MIPS64_R1 is a safe bet for any MIPS64 system.
 
+config CPU_MIPS64_R6
+	bool "MIPS64 Release 6 (EXPERIMENTAL)"
+	depends on SYS_HAS_CPU_MIPS64_R6
+	select CPU_HAS_PREFETCH
+	select CPU_SUPPORTS_32BIT_KERNEL
+	select CPU_SUPPORTS_64BIT_KERNEL
+	select CPU_SUPPORTS_HIGHMEM
+	select CPU_SUPPORTS_MSA
+	help
+	  Choose this option to build a kernel for release 6 or later of the
+	  MIPS64 architecture.  New MIPS processors, starting with the Warrior
+	  family, are based on a MIPS64r6 processor. If you own an older
+	  processor, you probably need to select MIPS64r1 or MIPS64r2 instead.
+
 config CPU_R3000
 	bool "R3000"
 	depends on SYS_HAS_CPU_R3000
@@ -1503,7 +1531,7 @@ endchoice
 config CPU_MIPS32_3_5_FEATURES
 	bool "MIPS32 Release 3.5 Features"
 	depends on SYS_HAS_CPU_MIPS32_R3_5
-	depends on CPU_MIPS32_R2
+	depends on CPU_MIPS32_R2 || CPU_MIPS32_R6
 	help
 	  Choose this option to build a kernel for release 2 or later of the
 	  MIPS32 architecture including features from the 3.5 release such as
@@ -1620,12 +1648,18 @@ config SYS_HAS_CPU_MIPS32_R2
 config SYS_HAS_CPU_MIPS32_R3_5
 	bool
 
+config SYS_HAS_CPU_MIPS32_R6
+	bool
+
 config SYS_HAS_CPU_MIPS64_R1
 	bool
 
 config SYS_HAS_CPU_MIPS64_R2
 	bool
 
+config SYS_HAS_CPU_MIPS64_R6
+	bool
+
 config SYS_HAS_CPU_R3000
 	bool
 
@@ -1725,11 +1759,11 @@ endmenu
 #
 config CPU_MIPS32
 	bool
-	default y if CPU_MIPS32_R1 || CPU_MIPS32_R2
+	default y if CPU_MIPS32_R1 || CPU_MIPS32_R2 || CPU_MIPS32_R6
 
 config CPU_MIPS64
 	bool
-	default y if CPU_MIPS64_R1 || CPU_MIPS64_R2
+	default y if CPU_MIPS64_R1 || CPU_MIPS64_R2 || CPU_MIPS64_R6
 
 #
 # These two indicate the revision of the architecture, either Release 1 or Release 2
@@ -1742,6 +1776,10 @@ config CPU_MIPSR2
 	bool
 	default y if CPU_MIPS32_R2 || CPU_MIPS64_R2 || CPU_CAVIUM_OCTEON
 
+config CPU_MIPSR6
+	bool
+	default y if CPU_MIPS32_R6 || CPU_MIPS64_R6
+
 config EVA
 	bool
 
@@ -2122,7 +2160,7 @@ config CPU_HAS_SMARTMIPS
 	  here.
 
 config CPU_MICROMIPS
-	depends on SYS_SUPPORTS_MICROMIPS
+	depends on SYS_SUPPORTS_MICROMIPS || !CPU_MIPSR6
 	bool "microMIPS"
 	help
 	  When this option is enabled the kernel will be built using the
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 58076472bdd8..5f1eb7975546 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -156,10 +156,14 @@ cflags-$(CONFIG_CPU_MIPS32_R1)	+= $(call cc-option,-march=mips32,-mips32 -U_MIPS
 			-Wa,-mips32 -Wa,--trap
 cflags-$(CONFIG_CPU_MIPS32_R2)	+= $(call cc-option,-march=mips32r2,-mips32r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
 			-Wa,-mips32r2 -Wa,--trap
+cflags-$(CONFIG_CPU_MIPS32_R6)	+= $(call cc-option,-march=mips32r6,-mips32r6 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
+			-Wa,-mips32r6 -Wa,--trap
 cflags-$(CONFIG_CPU_MIPS64_R1)	+= $(call cc-option,-march=mips64,-mips64 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS64) \
 			-Wa,-mips64 -Wa,--trap
 cflags-$(CONFIG_CPU_MIPS64_R2)	+= $(call cc-option,-march=mips64r2,-mips64r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS64) \
 			-Wa,-mips64r2 -Wa,--trap
+cflags-$(CONFIG_CPU_MIPS64_R6)	+= $(call cc-option,-march=mips64r6,-mips64r6 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
+			-Wa,-mips64r6 -Wa,--trap
 cflags-$(CONFIG_CPU_R5000)	+= -march=r5000 -Wa,--trap
 cflags-$(CONFIG_CPU_R5432)	+= $(call cc-option,-march=r5400,-march=r5000) \
 			-Wa,--trap
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 04/67] MIPS: Add build support for the MIPS R6 ISA
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

Add build support for the latest revision (R6) of the MIPS ISA.
microMIPS is not yet supported.

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/Kconfig  | 46 ++++++++++++++++++++++++++++++++++++++++++----
 arch/mips/Makefile |  4 ++++
 2 files changed, 46 insertions(+), 4 deletions(-)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 9536ef912f59..12e831b815b1 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1268,6 +1268,20 @@ config CPU_MIPS32_R2
 	  specific type of processor in your system, choose those that one
 	  otherwise CPU_MIPS32_R1 is a safe bet for any MIPS32 system.
 
+config CPU_MIPS32_R6
+	bool "MIPS32 Release 6 (EXPERIMENTAL)"
+	depends on SYS_HAS_CPU_MIPS32_R6
+	select CPU_HAS_PREFETCH
+	select CPU_SUPPORTS_32BIT_KERNEL
+	select CPU_SUPPORTS_HIGHMEM
+	select CPU_SUPPORTS_MSA
+	select HAVE_KVM
+	help
+	  Choose this option to build a kernel for release 6 or later of the
+	  MIPS32 architecture.  New MIPS processors, starting with the Warrior
+	  family, are based on a MIPS32r6 processor. If you own an older
+	  processor, you probably need to select MIPS32r1 or MIPS32r2 instead.
+
 config CPU_MIPS64_R1
 	bool "MIPS64 Release 1"
 	depends on SYS_HAS_CPU_MIPS64_R1
@@ -1303,6 +1317,20 @@ config CPU_MIPS64_R2
 	  specific type of processor in your system, choose those that one
 	  otherwise CPU_MIPS64_R1 is a safe bet for any MIPS64 system.
 
+config CPU_MIPS64_R6
+	bool "MIPS64 Release 6 (EXPERIMENTAL)"
+	depends on SYS_HAS_CPU_MIPS64_R6
+	select CPU_HAS_PREFETCH
+	select CPU_SUPPORTS_32BIT_KERNEL
+	select CPU_SUPPORTS_64BIT_KERNEL
+	select CPU_SUPPORTS_HIGHMEM
+	select CPU_SUPPORTS_MSA
+	help
+	  Choose this option to build a kernel for release 6 or later of the
+	  MIPS64 architecture.  New MIPS processors, starting with the Warrior
+	  family, are based on a MIPS64r6 processor. If you own an older
+	  processor, you probably need to select MIPS64r1 or MIPS64r2 instead.
+
 config CPU_R3000
 	bool "R3000"
 	depends on SYS_HAS_CPU_R3000
@@ -1503,7 +1531,7 @@ endchoice
 config CPU_MIPS32_3_5_FEATURES
 	bool "MIPS32 Release 3.5 Features"
 	depends on SYS_HAS_CPU_MIPS32_R3_5
-	depends on CPU_MIPS32_R2
+	depends on CPU_MIPS32_R2 || CPU_MIPS32_R6
 	help
 	  Choose this option to build a kernel for release 2 or later of the
 	  MIPS32 architecture including features from the 3.5 release such as
@@ -1620,12 +1648,18 @@ config SYS_HAS_CPU_MIPS32_R2
 config SYS_HAS_CPU_MIPS32_R3_5
 	bool
 
+config SYS_HAS_CPU_MIPS32_R6
+	bool
+
 config SYS_HAS_CPU_MIPS64_R1
 	bool
 
 config SYS_HAS_CPU_MIPS64_R2
 	bool
 
+config SYS_HAS_CPU_MIPS64_R6
+	bool
+
 config SYS_HAS_CPU_R3000
 	bool
 
@@ -1725,11 +1759,11 @@ endmenu
 #
 config CPU_MIPS32
 	bool
-	default y if CPU_MIPS32_R1 || CPU_MIPS32_R2
+	default y if CPU_MIPS32_R1 || CPU_MIPS32_R2 || CPU_MIPS32_R6
 
 config CPU_MIPS64
 	bool
-	default y if CPU_MIPS64_R1 || CPU_MIPS64_R2
+	default y if CPU_MIPS64_R1 || CPU_MIPS64_R2 || CPU_MIPS64_R6
 
 #
 # These two indicate the revision of the architecture, either Release 1 or Release 2
@@ -1742,6 +1776,10 @@ config CPU_MIPSR2
 	bool
 	default y if CPU_MIPS32_R2 || CPU_MIPS64_R2 || CPU_CAVIUM_OCTEON
 
+config CPU_MIPSR6
+	bool
+	default y if CPU_MIPS32_R6 || CPU_MIPS64_R6
+
 config EVA
 	bool
 
@@ -2122,7 +2160,7 @@ config CPU_HAS_SMARTMIPS
 	  here.
 
 config CPU_MICROMIPS
-	depends on SYS_SUPPORTS_MICROMIPS
+	depends on SYS_SUPPORTS_MICROMIPS || !CPU_MIPSR6
 	bool "microMIPS"
 	help
 	  When this option is enabled the kernel will be built using the
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 58076472bdd8..5f1eb7975546 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -156,10 +156,14 @@ cflags-$(CONFIG_CPU_MIPS32_R1)	+= $(call cc-option,-march=mips32,-mips32 -U_MIPS
 			-Wa,-mips32 -Wa,--trap
 cflags-$(CONFIG_CPU_MIPS32_R2)	+= $(call cc-option,-march=mips32r2,-mips32r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
 			-Wa,-mips32r2 -Wa,--trap
+cflags-$(CONFIG_CPU_MIPS32_R6)	+= $(call cc-option,-march=mips32r6,-mips32r6 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
+			-Wa,-mips32r6 -Wa,--trap
 cflags-$(CONFIG_CPU_MIPS64_R1)	+= $(call cc-option,-march=mips64,-mips64 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS64) \
 			-Wa,-mips64 -Wa,--trap
 cflags-$(CONFIG_CPU_MIPS64_R2)	+= $(call cc-option,-march=mips64r2,-mips64r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS64) \
 			-Wa,-mips64r2 -Wa,--trap
+cflags-$(CONFIG_CPU_MIPS64_R6)	+= $(call cc-option,-march=mips64r6,-mips64r6 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
+			-Wa,-mips64r6 -Wa,--trap
 cflags-$(CONFIG_CPU_R5000)	+= -march=r5000 -Wa,--trap
 cflags-$(CONFIG_CPU_R5432)	+= $(call cc-option,-march=r5400,-march=r5000) \
 			-Wa,--trap
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 05/67] MIPS: mm: uasm: Add signed 9-bit immediate related macros
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

MIPS R6 redefines several instructions and reduces the immediate
field to 9-bits so add related macros for the microassembler.

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/mm/uasm.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c
index a01b0d6cedd2..1cc8ac30be47 100644
--- a/arch/mips/mm/uasm.c
+++ b/arch/mips/mm/uasm.c
@@ -24,7 +24,8 @@ enum fields {
 	JIMM = 0x080,
 	FUNC = 0x100,
 	SET = 0x200,
-	SCIMM = 0x400
+	SCIMM = 0x400,
+	SIMM9 = 0x800,
 };
 
 #define OP_MASK		0x3f
@@ -41,6 +42,8 @@ enum fields {
 #define FUNC_SH		0
 #define SET_MASK	0x7
 #define SET_SH		0
+#define SIMM9_SH	7
+#define SIMM9_MASK	0x1ff
 
 enum opcode {
 	insn_invalid,
@@ -116,6 +119,14 @@ static inline u32 build_scimm(u32 arg)
 	return (arg & SCIMM_MASK) << SCIMM_SH;
 }
 
+static inline u32 build_scimm9(s32 arg)
+{
+	WARN((arg > 0x1ff || arg < -0x200),
+	       KERN_WARNING "Micro-assembler field overflow\n");
+
+	return (arg & SIMM9_MASK) << SIMM9_SH;
+}
+
 static inline u32 build_func(u32 arg)
 {
 	WARN(arg & ~FUNC_MASK, KERN_WARNING "Micro-assembler field overflow\n");
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 05/67] MIPS: mm: uasm: Add signed 9-bit immediate related macros
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

MIPS R6 redefines several instructions and reduces the immediate
field to 9-bits so add related macros for the microassembler.

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/mm/uasm.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c
index a01b0d6cedd2..1cc8ac30be47 100644
--- a/arch/mips/mm/uasm.c
+++ b/arch/mips/mm/uasm.c
@@ -24,7 +24,8 @@ enum fields {
 	JIMM = 0x080,
 	FUNC = 0x100,
 	SET = 0x200,
-	SCIMM = 0x400
+	SCIMM = 0x400,
+	SIMM9 = 0x800,
 };
 
 #define OP_MASK		0x3f
@@ -41,6 +42,8 @@ enum fields {
 #define FUNC_SH		0
 #define SET_MASK	0x7
 #define SET_SH		0
+#define SIMM9_SH	7
+#define SIMM9_MASK	0x1ff
 
 enum opcode {
 	insn_invalid,
@@ -116,6 +119,14 @@ static inline u32 build_scimm(u32 arg)
 	return (arg & SCIMM_MASK) << SCIMM_SH;
 }
 
+static inline u32 build_scimm9(s32 arg)
+{
+	WARN((arg > 0x1ff || arg < -0x200),
+	       KERN_WARNING "Micro-assembler field overflow\n");
+
+	return (arg & SIMM9_MASK) << SIMM9_SH;
+}
+
 static inline u32 build_func(u32 arg)
 {
 	WARN(arg & ~FUNC_MASK, KERN_WARNING "Micro-assembler field overflow\n");
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 06/67] MIPS: mm: Add MIPS R6 instruction encodings
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

MIPS R6 defines new opcodes for ll, sc, cache and pref instructions
so we need to take these into consideration in the micro-assembler.

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/uapi/asm/inst.h |  9 ++++++---
 arch/mips/mm/uasm-mips.c          | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 38 insertions(+), 3 deletions(-)

diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h
index 4bfdb9d4c186..c330de057558 100644
--- a/arch/mips/include/uapi/asm/inst.h
+++ b/arch/mips/include/uapi/asm/inst.h
@@ -83,9 +83,12 @@ enum spec3_op {
 	swe_op    = 0x1f, bshfl_op  = 0x20,
 	swle_op   = 0x21, swre_op   = 0x22,
 	prefe_op  = 0x23, dbshfl_op = 0x24,
-	lbue_op   = 0x28, lhue_op   = 0x29,
-	lbe_op    = 0x2c, lhe_op    = 0x2d,
-	lle_op    = 0x2e, lwe_op    = 0x2f,
+	cache6_op = 0x25, sc6_op    = 0x26,
+	scd6_op   = 0x27, lbue_op   = 0x28,
+	lhue_op   = 0x29, lbe_op    = 0x2c,
+	lhe_op    = 0x2d, lle_op    = 0x2e,
+	lwe_op    = 0x2f, pref6_op  = 0x35,
+	ll6_op    = 0x36, lld6_op   = 0x37,
 	rdhwr_op  = 0x3b
 };
 
diff --git a/arch/mips/mm/uasm-mips.c b/arch/mips/mm/uasm-mips.c
index 6708a2dbf934..c1fb8bdfb06d 100644
--- a/arch/mips/mm/uasm-mips.c
+++ b/arch/mips/mm/uasm-mips.c
@@ -38,6 +38,14 @@
 	 | (e) << RE_SH						\
 	 | (f) << FUNC_SH)
 
+/* This macro sets the non-variable bits of an R6 instruction. */
+#define M6(a, b, c, d, e)					\
+	((a) << OP_SH						\
+	 | (b) << RS_SH						\
+	 | (c) << RT_SH						\
+	 | (d) << SIMM9_SH					\
+	 | (e) << FUNC_SH)
+
 /* Define these when we are not the ISA the kernel is being compiled with. */
 #ifdef CONFIG_CPU_MICROMIPS
 #define CL_uasm_i_b(buf, off) ISAOPC(_beq)(buf, 0, 0, off)
@@ -62,7 +70,11 @@ static struct insn insn_table[] = {
 	{ insn_bltzl, M(bcond_op, 0, bltzl_op, 0, 0, 0), RS | BIMM },
 	{ insn_bltz, M(bcond_op, 0, bltz_op, 0, 0, 0), RS | BIMM },
 	{ insn_bne, M(bne_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
+#ifndef CONFIG_MIPS_R6
 	{ insn_cache,  M(cache_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
+#else
+	{ insn_cache,  M6(cache_op, 0, 0, 0, 0, cache6_op),  RS | RT | SIMM9 },
+#endif
 	{ insn_daddiu, M(daddiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
 	{ insn_daddu, M(spec_op, 0, 0, 0, 0, daddu_op), RS | RT | RD },
 	{ insn_dinsm, M(spec3_op, 0, 0, 0, 0, dinsm_op), RS | RT | RD | RE },
@@ -85,13 +97,22 @@ static struct insn insn_table[] = {
 	{ insn_jal,  M(jal_op, 0, 0, 0, 0, 0),	JIMM },
 	{ insn_jalr,  M(spec_op, 0, 0, 0, 0, jalr_op), RS | RD },
 	{ insn_j,  M(j_op, 0, 0, 0, 0, 0),  JIMM },
+#ifndef CONFIG_CPU_MIPSR6
 	{ insn_jr,  M(spec_op, 0, 0, 0, 0, jr_op),  RS },
+#else
+	{ insn_jr,  M(spec_op, 0, 0, 0, 0, jalr_op),  RS },
+#endif
 	{ insn_lb, M(lb_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
 	{ insn_ld,  M(ld_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
 	{ insn_ldx, M(spec3_op, 0, 0, 0, ldx_op, lx_op), RS | RT | RD },
 	{ insn_lh,  M(lh_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
+#ifndef CONFIG_CPU_MIPSR6
 	{ insn_lld,  M(lld_op, 0, 0, 0, 0, 0),	RS | RT | SIMM },
 	{ insn_ll,  M(ll_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
+#else
+	{ insn_lld,  M6(spec3_op, 0, 0, 0, lld6_op),  RS | RT | SIMM9 },
+	{ insn_ll,  M6(spec3_op, 0, 0, 0, ll6_op),  RS | RT | SIMM9 },
+#endif
 	{ insn_lui,  M(lui_op, 0, 0, 0, 0, 0),	RT | SIMM },
 	{ insn_lw,  M(lw_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
 	{ insn_lwx, M(spec3_op, 0, 0, 0, lwx_op, lx_op), RS | RT | RD },
@@ -102,11 +123,20 @@ static struct insn insn_table[] = {
 	{ insn_mul, M(spec2_op, 0, 0, 0, 0, mul_op), RS | RT | RD},
 	{ insn_ori,  M(ori_op, 0, 0, 0, 0, 0),	RS | RT | UIMM },
 	{ insn_or,  M(spec_op, 0, 0, 0, 0, or_op),  RS | RT | RD },
+#ifndef CONFIG_CPU_MIPSR6
 	{ insn_pref,  M(pref_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
+#else
+	{ insn_pref,  M6(spec3_op, 0, 0, 0, pref6_op),  RS | RT | SIMM9 },
+#endif
 	{ insn_rfe,  M(cop0_op, cop_op, 0, 0, 0, rfe_op),  0 },
 	{ insn_rotr,  M(spec_op, 1, 0, 0, 0, srl_op),  RT | RD | RE },
+#ifndef CONFIG_CPU_MIPSR6
 	{ insn_scd,  M(scd_op, 0, 0, 0, 0, 0),	RS | RT | SIMM },
 	{ insn_sc,  M(sc_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
+#else
+	{ insn_scd,  M6(spec3_op, 0, 0, 0, scd6_op),  RS | RT | SIMM9 },
+	{ insn_sc,  M6(spec3_op, 0, 0, 0, sc6_op),  RS | RT | SIMM9 },
+#endif
 	{ insn_sd,  M(sd_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
 	{ insn_sll,  M(spec_op, 0, 0, 0, 0, sll_op),  RT | RD | RE },
 	{ insn_sllv,  M(spec_op, 0, 0, 0, 0, sllv_op),  RS | RT | RD },
@@ -196,6 +226,8 @@ static void build_insn(u32 **buf, enum opcode opc, ...)
 		op |= build_set(va_arg(ap, u32));
 	if (ip->fields & SCIMM)
 		op |= build_scimm(va_arg(ap, u32));
+	if (ip->fields & SIMM9)
+		op |= build_scimm9(va_arg(ap, u32));
 	va_end(ap);
 
 	**buf = op;
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 06/67] MIPS: mm: Add MIPS R6 instruction encodings
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

MIPS R6 defines new opcodes for ll, sc, cache and pref instructions
so we need to take these into consideration in the micro-assembler.

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/uapi/asm/inst.h |  9 ++++++---
 arch/mips/mm/uasm-mips.c          | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 38 insertions(+), 3 deletions(-)

diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h
index 4bfdb9d4c186..c330de057558 100644
--- a/arch/mips/include/uapi/asm/inst.h
+++ b/arch/mips/include/uapi/asm/inst.h
@@ -83,9 +83,12 @@ enum spec3_op {
 	swe_op    = 0x1f, bshfl_op  = 0x20,
 	swle_op   = 0x21, swre_op   = 0x22,
 	prefe_op  = 0x23, dbshfl_op = 0x24,
-	lbue_op   = 0x28, lhue_op   = 0x29,
-	lbe_op    = 0x2c, lhe_op    = 0x2d,
-	lle_op    = 0x2e, lwe_op    = 0x2f,
+	cache6_op = 0x25, sc6_op    = 0x26,
+	scd6_op   = 0x27, lbue_op   = 0x28,
+	lhue_op   = 0x29, lbe_op    = 0x2c,
+	lhe_op    = 0x2d, lle_op    = 0x2e,
+	lwe_op    = 0x2f, pref6_op  = 0x35,
+	ll6_op    = 0x36, lld6_op   = 0x37,
 	rdhwr_op  = 0x3b
 };
 
diff --git a/arch/mips/mm/uasm-mips.c b/arch/mips/mm/uasm-mips.c
index 6708a2dbf934..c1fb8bdfb06d 100644
--- a/arch/mips/mm/uasm-mips.c
+++ b/arch/mips/mm/uasm-mips.c
@@ -38,6 +38,14 @@
 	 | (e) << RE_SH						\
 	 | (f) << FUNC_SH)
 
+/* This macro sets the non-variable bits of an R6 instruction. */
+#define M6(a, b, c, d, e)					\
+	((a) << OP_SH						\
+	 | (b) << RS_SH						\
+	 | (c) << RT_SH						\
+	 | (d) << SIMM9_SH					\
+	 | (e) << FUNC_SH)
+
 /* Define these when we are not the ISA the kernel is being compiled with. */
 #ifdef CONFIG_CPU_MICROMIPS
 #define CL_uasm_i_b(buf, off) ISAOPC(_beq)(buf, 0, 0, off)
@@ -62,7 +70,11 @@ static struct insn insn_table[] = {
 	{ insn_bltzl, M(bcond_op, 0, bltzl_op, 0, 0, 0), RS | BIMM },
 	{ insn_bltz, M(bcond_op, 0, bltz_op, 0, 0, 0), RS | BIMM },
 	{ insn_bne, M(bne_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
+#ifndef CONFIG_MIPS_R6
 	{ insn_cache,  M(cache_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
+#else
+	{ insn_cache,  M6(cache_op, 0, 0, 0, 0, cache6_op),  RS | RT | SIMM9 },
+#endif
 	{ insn_daddiu, M(daddiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
 	{ insn_daddu, M(spec_op, 0, 0, 0, 0, daddu_op), RS | RT | RD },
 	{ insn_dinsm, M(spec3_op, 0, 0, 0, 0, dinsm_op), RS | RT | RD | RE },
@@ -85,13 +97,22 @@ static struct insn insn_table[] = {
 	{ insn_jal,  M(jal_op, 0, 0, 0, 0, 0),	JIMM },
 	{ insn_jalr,  M(spec_op, 0, 0, 0, 0, jalr_op), RS | RD },
 	{ insn_j,  M(j_op, 0, 0, 0, 0, 0),  JIMM },
+#ifndef CONFIG_CPU_MIPSR6
 	{ insn_jr,  M(spec_op, 0, 0, 0, 0, jr_op),  RS },
+#else
+	{ insn_jr,  M(spec_op, 0, 0, 0, 0, jalr_op),  RS },
+#endif
 	{ insn_lb, M(lb_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
 	{ insn_ld,  M(ld_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
 	{ insn_ldx, M(spec3_op, 0, 0, 0, ldx_op, lx_op), RS | RT | RD },
 	{ insn_lh,  M(lh_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
+#ifndef CONFIG_CPU_MIPSR6
 	{ insn_lld,  M(lld_op, 0, 0, 0, 0, 0),	RS | RT | SIMM },
 	{ insn_ll,  M(ll_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
+#else
+	{ insn_lld,  M6(spec3_op, 0, 0, 0, lld6_op),  RS | RT | SIMM9 },
+	{ insn_ll,  M6(spec3_op, 0, 0, 0, ll6_op),  RS | RT | SIMM9 },
+#endif
 	{ insn_lui,  M(lui_op, 0, 0, 0, 0, 0),	RT | SIMM },
 	{ insn_lw,  M(lw_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
 	{ insn_lwx, M(spec3_op, 0, 0, 0, lwx_op, lx_op), RS | RT | RD },
@@ -102,11 +123,20 @@ static struct insn insn_table[] = {
 	{ insn_mul, M(spec2_op, 0, 0, 0, 0, mul_op), RS | RT | RD},
 	{ insn_ori,  M(ori_op, 0, 0, 0, 0, 0),	RS | RT | UIMM },
 	{ insn_or,  M(spec_op, 0, 0, 0, 0, or_op),  RS | RT | RD },
+#ifndef CONFIG_CPU_MIPSR6
 	{ insn_pref,  M(pref_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
+#else
+	{ insn_pref,  M6(spec3_op, 0, 0, 0, pref6_op),  RS | RT | SIMM9 },
+#endif
 	{ insn_rfe,  M(cop0_op, cop_op, 0, 0, 0, rfe_op),  0 },
 	{ insn_rotr,  M(spec_op, 1, 0, 0, 0, srl_op),  RT | RD | RE },
+#ifndef CONFIG_CPU_MIPSR6
 	{ insn_scd,  M(scd_op, 0, 0, 0, 0, 0),	RS | RT | SIMM },
 	{ insn_sc,  M(sc_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
+#else
+	{ insn_scd,  M6(spec3_op, 0, 0, 0, scd6_op),  RS | RT | SIMM9 },
+	{ insn_sc,  M6(spec3_op, 0, 0, 0, sc6_op),  RS | RT | SIMM9 },
+#endif
 	{ insn_sd,  M(sd_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
 	{ insn_sll,  M(spec_op, 0, 0, 0, 0, sll_op),  RT | RD | RE },
 	{ insn_sllv,  M(spec_op, 0, 0, 0, 0, sllv_op),  RS | RT | RD },
@@ -196,6 +226,8 @@ static void build_insn(u32 **buf, enum opcode opc, ...)
 		op |= build_set(va_arg(ap, u32));
 	if (ip->fields & SCIMM)
 		op |= build_scimm(va_arg(ap, u32));
+	if (ip->fields & SIMM9)
+		op |= build_scimm9(va_arg(ap, u32));
 	va_end(ap);
 
 	**buf = op;
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 07/67] MIPS: asm: asm: Add new macros to set ISA and arch asm annotations
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

There are certain places where the code uses .set mips32 or .set mips64
or .set arch=r4000. In preparation of MIPS R6 support, and in order to
use as less #ifdefs as possible, we define new macros to set similar
annotations for MIPS R6

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/asm.h | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/arch/mips/include/asm/asm.h b/arch/mips/include/asm/asm.h
index 7c26b28bf252..bb857a87ccd1 100644
--- a/arch/mips/include/asm/asm.h
+++ b/arch/mips/include/asm/asm.h
@@ -342,6 +342,19 @@ symbol		=	value
 #define LONGLOG		3
 #endif
 
+#ifdef CONFIG_CPU_MIPSR6
+#define MIPS_ISA_LEVEL_RAW mips64r6
+#define MIPS_ISA_LEVEL "mips64r6"
+#define MIPS_ISA_ARCH_LEVEL_RAW MIPS_ISA_LEVEL_RAW
+#define MIPS_ISA_ARCH_LEVEL MIPS_ISA_LEVEL
+#else
+/* MIPS64 is a superset of MIPS32 */
+#define MIPS_ISA_LEVEL_RAW mips64
+#define MIPS_ISA_LEVEL "mips64"
+#define MIPS_ISA_ARCH_LEVEL_RAW arch=r4000
+#define MIPS_ISA_ARCH_LEVEL "arch=r4000"
+#endif /* CONFIG_CPU_MIPSR6 */
+
 /*
  * How to add/sub/load/store/shift pointers.
  */
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 07/67] MIPS: asm: asm: Add new macros to set ISA and arch asm annotations
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

There are certain places where the code uses .set mips32 or .set mips64
or .set arch=r4000. In preparation of MIPS R6 support, and in order to
use as less #ifdefs as possible, we define new macros to set similar
annotations for MIPS R6

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/asm.h | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/arch/mips/include/asm/asm.h b/arch/mips/include/asm/asm.h
index 7c26b28bf252..bb857a87ccd1 100644
--- a/arch/mips/include/asm/asm.h
+++ b/arch/mips/include/asm/asm.h
@@ -342,6 +342,19 @@ symbol		=	value
 #define LONGLOG		3
 #endif
 
+#ifdef CONFIG_CPU_MIPSR6
+#define MIPS_ISA_LEVEL_RAW mips64r6
+#define MIPS_ISA_LEVEL "mips64r6"
+#define MIPS_ISA_ARCH_LEVEL_RAW MIPS_ISA_LEVEL_RAW
+#define MIPS_ISA_ARCH_LEVEL MIPS_ISA_LEVEL
+#else
+/* MIPS64 is a superset of MIPS32 */
+#define MIPS_ISA_LEVEL_RAW mips64
+#define MIPS_ISA_LEVEL "mips64"
+#define MIPS_ISA_ARCH_LEVEL_RAW arch=r4000
+#define MIPS_ISA_ARCH_LEVEL "arch=r4000"
+#endif /* CONFIG_CPU_MIPSR6 */
+
 /*
  * How to add/sub/load/store/shift pointers.
  */
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 08/67] MIPS: asm: module: define MODULE_PROC_FAMILY for MIPS R6
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

Define the MODULE_PROC_FAMILY for the MIPS R6 ISA.

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/module.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/mips/include/asm/module.h b/arch/mips/include/asm/module.h
index 800fe578dc99..0aaf9a01ea50 100644
--- a/arch/mips/include/asm/module.h
+++ b/arch/mips/include/asm/module.h
@@ -88,10 +88,14 @@ search_module_dbetables(unsigned long addr)
 #define MODULE_PROC_FAMILY "MIPS32_R1 "
 #elif defined CONFIG_CPU_MIPS32_R2
 #define MODULE_PROC_FAMILY "MIPS32_R2 "
+#elif defined CONFIG_CPU_MIPS32_R6
+#define MODULE_PROC_FAMILY "MIPS32_R6 "
 #elif defined CONFIG_CPU_MIPS64_R1
 #define MODULE_PROC_FAMILY "MIPS64_R1 "
 #elif defined CONFIG_CPU_MIPS64_R2
 #define MODULE_PROC_FAMILY "MIPS64_R2 "
+#elif defined CONFIG_CPU_MIPS64_R6
+#define MODULE_PROC_FAMILY "MIPS64_R6 "
 #elif defined CONFIG_CPU_R3000
 #define MODULE_PROC_FAMILY "R3000 "
 #elif defined CONFIG_CPU_TX39XX
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 08/67] MIPS: asm: module: define MODULE_PROC_FAMILY for MIPS R6
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

Define the MODULE_PROC_FAMILY for the MIPS R6 ISA.

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/module.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/mips/include/asm/module.h b/arch/mips/include/asm/module.h
index 800fe578dc99..0aaf9a01ea50 100644
--- a/arch/mips/include/asm/module.h
+++ b/arch/mips/include/asm/module.h
@@ -88,10 +88,14 @@ search_module_dbetables(unsigned long addr)
 #define MODULE_PROC_FAMILY "MIPS32_R1 "
 #elif defined CONFIG_CPU_MIPS32_R2
 #define MODULE_PROC_FAMILY "MIPS32_R2 "
+#elif defined CONFIG_CPU_MIPS32_R6
+#define MODULE_PROC_FAMILY "MIPS32_R6 "
 #elif defined CONFIG_CPU_MIPS64_R1
 #define MODULE_PROC_FAMILY "MIPS64_R1 "
 #elif defined CONFIG_CPU_MIPS64_R2
 #define MODULE_PROC_FAMILY "MIPS64_R2 "
+#elif defined CONFIG_CPU_MIPS64_R6
+#define MODULE_PROC_FAMILY "MIPS64_R6 "
 #elif defined CONFIG_CPU_R3000
 #define MODULE_PROC_FAMILY "R3000 "
 #elif defined CONFIG_CPU_TX39XX
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 09/67] MIPS: asm: stackframe: Do not preserve the HI/LO registers on MIPS R6
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

The HI/LO registers have been removed from MIPS R6. Instructions
such as MULT and DIV have been replaced with a new pair of
instructions for the HI/LO operations for example:

MULT -> MUL, MUH
DIV -> DIV, MOD

So we avoid preserving the pre-R6 HI/LO registers in MIPS R6

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/stackframe.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/mips/include/asm/stackframe.h b/arch/mips/include/asm/stackframe.h
index b188c797565c..28d6d9364bd1 100644
--- a/arch/mips/include/asm/stackframe.h
+++ b/arch/mips/include/asm/stackframe.h
@@ -40,7 +40,7 @@
 		LONG_S	v1, PT_HI(sp)
 		mflhxu	v1
 		LONG_S	v1, PT_ACX(sp)
-#else
+#elif !defined(CONFIG_CPU_MIPSR6)
 		mfhi	v1
 #endif
 #ifdef CONFIG_32BIT
@@ -50,7 +50,7 @@
 		LONG_S	$10, PT_R10(sp)
 		LONG_S	$11, PT_R11(sp)
 		LONG_S	$12, PT_R12(sp)
-#ifndef CONFIG_CPU_HAS_SMARTMIPS
+#if !defined(CONFIG_CPU_HAS_SMARTMIPS) && !defined(CONFIG_CPU_MIPSR6)
 		LONG_S	v1, PT_HI(sp)
 		mflo	v1
 #endif
@@ -58,7 +58,7 @@
 		LONG_S	$14, PT_R14(sp)
 		LONG_S	$15, PT_R15(sp)
 		LONG_S	$24, PT_R24(sp)
-#ifndef CONFIG_CPU_HAS_SMARTMIPS
+#if !defined(CONFIG_CPU_HAS_SMARTMIPS) && !defined(CONFIG_CPU_MIPSR6)
 		LONG_S	v1, PT_LO(sp)
 #endif
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
@@ -226,7 +226,7 @@
 		mtlhx	$24
 		LONG_L	$24, PT_LO(sp)
 		mtlhx	$24
-#else
+#elif !defined(CONFIG_CPU_MIPSR6)
 		LONG_L	$24, PT_LO(sp)
 		mtlo	$24
 		LONG_L	$24, PT_HI(sp)
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 09/67] MIPS: asm: stackframe: Do not preserve the HI/LO registers on MIPS R6
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

The HI/LO registers have been removed from MIPS R6. Instructions
such as MULT and DIV have been replaced with a new pair of
instructions for the HI/LO operations for example:

MULT -> MUL, MUH
DIV -> DIV, MOD

So we avoid preserving the pre-R6 HI/LO registers in MIPS R6

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/stackframe.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/mips/include/asm/stackframe.h b/arch/mips/include/asm/stackframe.h
index b188c797565c..28d6d9364bd1 100644
--- a/arch/mips/include/asm/stackframe.h
+++ b/arch/mips/include/asm/stackframe.h
@@ -40,7 +40,7 @@
 		LONG_S	v1, PT_HI(sp)
 		mflhxu	v1
 		LONG_S	v1, PT_ACX(sp)
-#else
+#elif !defined(CONFIG_CPU_MIPSR6)
 		mfhi	v1
 #endif
 #ifdef CONFIG_32BIT
@@ -50,7 +50,7 @@
 		LONG_S	$10, PT_R10(sp)
 		LONG_S	$11, PT_R11(sp)
 		LONG_S	$12, PT_R12(sp)
-#ifndef CONFIG_CPU_HAS_SMARTMIPS
+#if !defined(CONFIG_CPU_HAS_SMARTMIPS) && !defined(CONFIG_CPU_MIPSR6)
 		LONG_S	v1, PT_HI(sp)
 		mflo	v1
 #endif
@@ -58,7 +58,7 @@
 		LONG_S	$14, PT_R14(sp)
 		LONG_S	$15, PT_R15(sp)
 		LONG_S	$24, PT_R24(sp)
-#ifndef CONFIG_CPU_HAS_SMARTMIPS
+#if !defined(CONFIG_CPU_HAS_SMARTMIPS) && !defined(CONFIG_CPU_MIPSR6)
 		LONG_S	v1, PT_LO(sp)
 #endif
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
@@ -226,7 +226,7 @@
 		mtlhx	$24
 		LONG_L	$24, PT_LO(sp)
 		mtlhx	$24
-#else
+#elif !defined(CONFIG_CPU_MIPSR6)
 		LONG_L	$24, PT_LO(sp)
 		mtlo	$24
 		LONG_L	$24, PT_HI(sp)
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 10/67] MIPS: asm: asmmacro: Drop unused 'reg' argument on MIPSR2
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

The local_irq_{enable, disable} macros do not use the reg argument
so drop it.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/asmmacro.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h
index 6caf8766b80f..90f69c334a75 100644
--- a/arch/mips/include/asm/asmmacro.h
+++ b/arch/mips/include/asm/asmmacro.h
@@ -20,12 +20,12 @@
 #endif
 
 #ifdef CONFIG_CPU_MIPSR2
-	.macro	local_irq_enable reg=t0
+	.macro	local_irq_enable
 	ei
 	irq_enable_hazard
 	.endm
 
-	.macro	local_irq_disable reg=t0
+	.macro	local_irq_disable
 	di
 	irq_disable_hazard
 	.endm
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 10/67] MIPS: asm: asmmacro: Drop unused 'reg' argument on MIPSR2
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

The local_irq_{enable, disable} macros do not use the reg argument
so drop it.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/asmmacro.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h
index 6caf8766b80f..90f69c334a75 100644
--- a/arch/mips/include/asm/asmmacro.h
+++ b/arch/mips/include/asm/asmmacro.h
@@ -20,12 +20,12 @@
 #endif
 
 #ifdef CONFIG_CPU_MIPSR2
-	.macro	local_irq_enable reg=t0
+	.macro	local_irq_enable
 	ei
 	irq_enable_hazard
 	.endm
 
-	.macro	local_irq_disable reg=t0
+	.macro	local_irq_disable
 	di
 	irq_disable_hazard
 	.endm
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 11/67] MIPS: asm: asmmacro: Add MIPS R6 support to the simple EI/DI variants
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

EI/DI instructions are available in MIPS R6 so add the needed
definitions.

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/asmmacro.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h
index 90f69c334a75..fe08084f5adb 100644
--- a/arch/mips/include/asm/asmmacro.h
+++ b/arch/mips/include/asm/asmmacro.h
@@ -19,7 +19,7 @@
 #include <asm/asmmacro-64.h>
 #endif
 
-#ifdef CONFIG_CPU_MIPSR2
+#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
 	.macro	local_irq_enable
 	ei
 	irq_enable_hazard
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 11/67] MIPS: asm: asmmacro: Add MIPS R6 support to the simple EI/DI variants
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

EI/DI instructions are available in MIPS R6 so add the needed
definitions.

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/asmmacro.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h
index 90f69c334a75..fe08084f5adb 100644
--- a/arch/mips/include/asm/asmmacro.h
+++ b/arch/mips/include/asm/asmmacro.h
@@ -19,7 +19,7 @@
 #include <asm/asmmacro-64.h>
 #endif
 
-#ifdef CONFIG_CPU_MIPSR2
+#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
 	.macro	local_irq_enable
 	ei
 	irq_enable_hazard
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 12/67] MIPS: asm: asmmacro: Replace add instructions with "addui"
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

The use of "add" instruction for immediate operations is wrong and
relies to gas being smart enough to notice that and replace it with
either addi or addui. However, MIPS R6 removed the addi instruction
so, fix this problem properly by using the correct instruction
directly.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/asmmacro.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h
index fe08084f5adb..55c07c40c199 100644
--- a/arch/mips/include/asm/asmmacro.h
+++ b/arch/mips/include/asm/asmmacro.h
@@ -304,7 +304,7 @@
 	.set	push
 	.set	noat
 	SET_HARDFLOAT
-	add	$1, \base, \off
+	addiu	$1, \base, \off
 	.word	LDD_MSA_INSN | (\wd << 6)
 	.set	pop
 	.endm
@@ -313,7 +313,7 @@
 	.set	push
 	.set	noat
 	SET_HARDFLOAT
-	add	$1, \base, \off
+	addiu	$1, \base, \off
 	.word	STD_MSA_INSN | (\wd << 6)
 	.set	pop
 	.endm
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 12/67] MIPS: asm: asmmacro: Replace add instructions with "addui"
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

The use of "add" instruction for immediate operations is wrong and
relies to gas being smart enough to notice that and replace it with
either addi or addui. However, MIPS R6 removed the addi instruction
so, fix this problem properly by using the correct instruction
directly.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/asmmacro.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h
index fe08084f5adb..55c07c40c199 100644
--- a/arch/mips/include/asm/asmmacro.h
+++ b/arch/mips/include/asm/asmmacro.h
@@ -304,7 +304,7 @@
 	.set	push
 	.set	noat
 	SET_HARDFLOAT
-	add	$1, \base, \off
+	addiu	$1, \base, \off
 	.word	LDD_MSA_INSN | (\wd << 6)
 	.set	pop
 	.endm
@@ -313,7 +313,7 @@
 	.set	push
 	.set	noat
 	SET_HARDFLOAT
-	add	$1, \base, \off
+	addiu	$1, \base, \off
 	.word	STD_MSA_INSN | (\wd << 6)
 	.set	pop
 	.endm
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 13/67] MIPS: Use generic checksum functions for MIPS R6
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

The following instructions have been removed from MIPS R6

ulw, ulh, swl, lwr, lwl, swr.

However, all of them are used in the MIPS specific checksum implementation.
As a result of which, we will use the generic checksum on MIPS R6

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/Kconfig                | 5 +++++
 arch/mips/include/asm/Kbuild     | 1 +
 arch/mips/include/asm/checksum.h | 6 ++++++
 arch/mips/kernel/mips_ksyms.c    | 2 ++
 arch/mips/lib/Makefile           | 1 +
 5 files changed, 15 insertions(+)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 12e831b815b1..544e62369bbc 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -994,6 +994,9 @@ config MIPS_MACHINE
 config NO_IOPORT_MAP
 	def_bool n
 
+config GENERIC_CSUM
+	bool
+
 config GENERIC_ISA_DMA
 	bool
 	select ZONE_DMA if GENERIC_ISA_DMA_SUPPORT_BROKEN=n
@@ -1275,6 +1278,7 @@ config CPU_MIPS32_R6
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_HIGHMEM
 	select CPU_SUPPORTS_MSA
+	select GENERIC_CSUM
 	select HAVE_KVM
 	help
 	  Choose this option to build a kernel for release 6 or later of the
@@ -1325,6 +1329,7 @@ config CPU_MIPS64_R6
 	select CPU_SUPPORTS_64BIT_KERNEL
 	select CPU_SUPPORTS_HIGHMEM
 	select CPU_SUPPORTS_MSA
+	select GENERIC_CSUM
 	help
 	  Choose this option to build a kernel for release 6 or later of the
 	  MIPS64 architecture.  New MIPS processors, starting with the Warrior
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 72e1cf1cab00..c304e093eee3 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -1,4 +1,5 @@
 # MIPS headers
+generic-(CONFIG_GENERIC_CSUM) += checksum.h
 generic-y += cputime.h
 generic-y += current.h
 generic-y += dma-contiguous.h
diff --git a/arch/mips/include/asm/checksum.h b/arch/mips/include/asm/checksum.h
index 3418c51e1151..8464b62443b2 100644
--- a/arch/mips/include/asm/checksum.h
+++ b/arch/mips/include/asm/checksum.h
@@ -12,6 +12,10 @@
 #ifndef _ASM_CHECKSUM_H
 #define _ASM_CHECKSUM_H
 
+#ifdef CONFIG_GENERIC_CSUM
+#include <asm-generic/checksum.h>
+#else
+
 #include <linux/in6.h>
 
 #include <asm/uaccess.h>
@@ -287,4 +291,6 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
 	return csum_fold(sum);
 }
 
+#endif /* CONFIG_GENERIC_CSUM */
+
 #endif /* _ASM_CHECKSUM_H */
diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c
index 2607c3a4ff7e..631f6fed6092 100644
--- a/arch/mips/kernel/mips_ksyms.c
+++ b/arch/mips/kernel/mips_ksyms.c
@@ -71,11 +71,13 @@ EXPORT_SYMBOL(__strnlen_kernel_asm);
 EXPORT_SYMBOL(__strnlen_user_nocheck_asm);
 EXPORT_SYMBOL(__strnlen_user_asm);
 
+#ifndef CONFIG_CPU_MIPSR6
 EXPORT_SYMBOL(csum_partial);
 EXPORT_SYMBOL(csum_partial_copy_nocheck);
 EXPORT_SYMBOL(__csum_partial_copy_kernel);
 EXPORT_SYMBOL(__csum_partial_copy_to_user);
 EXPORT_SYMBOL(__csum_partial_copy_from_user);
+#endif
 
 EXPORT_SYMBOL(invalid_pte_table);
 #ifdef CONFIG_FUNCTION_TRACER
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index eeddc58802e1..1e9e900cd3c3 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -8,6 +8,7 @@ lib-y	+= bitops.o csum_partial.o delay.o memcpy.o memset.o \
 
 obj-y			+= iomap.o
 obj-$(CONFIG_PCI)	+= iomap-pci.o
+lib-$(CONFIG_GENERIC_CSUM)	:= $(filter-out csum_partial.o, $(lib-y))
 
 obj-$(CONFIG_CPU_GENERIC_DUMP_TLB) += dump_tlb.o
 obj-$(CONFIG_CPU_R3000)		+= r3k_dump_tlb.o
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 13/67] MIPS: Use generic checksum functions for MIPS R6
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

The following instructions have been removed from MIPS R6

ulw, ulh, swl, lwr, lwl, swr.

However, all of them are used in the MIPS specific checksum implementation.
As a result of which, we will use the generic checksum on MIPS R6

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/Kconfig                | 5 +++++
 arch/mips/include/asm/Kbuild     | 1 +
 arch/mips/include/asm/checksum.h | 6 ++++++
 arch/mips/kernel/mips_ksyms.c    | 2 ++
 arch/mips/lib/Makefile           | 1 +
 5 files changed, 15 insertions(+)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 12e831b815b1..544e62369bbc 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -994,6 +994,9 @@ config MIPS_MACHINE
 config NO_IOPORT_MAP
 	def_bool n
 
+config GENERIC_CSUM
+	bool
+
 config GENERIC_ISA_DMA
 	bool
 	select ZONE_DMA if GENERIC_ISA_DMA_SUPPORT_BROKEN=n
@@ -1275,6 +1278,7 @@ config CPU_MIPS32_R6
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_HIGHMEM
 	select CPU_SUPPORTS_MSA
+	select GENERIC_CSUM
 	select HAVE_KVM
 	help
 	  Choose this option to build a kernel for release 6 or later of the
@@ -1325,6 +1329,7 @@ config CPU_MIPS64_R6
 	select CPU_SUPPORTS_64BIT_KERNEL
 	select CPU_SUPPORTS_HIGHMEM
 	select CPU_SUPPORTS_MSA
+	select GENERIC_CSUM
 	help
 	  Choose this option to build a kernel for release 6 or later of the
 	  MIPS64 architecture.  New MIPS processors, starting with the Warrior
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 72e1cf1cab00..c304e093eee3 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -1,4 +1,5 @@
 # MIPS headers
+generic-(CONFIG_GENERIC_CSUM) += checksum.h
 generic-y += cputime.h
 generic-y += current.h
 generic-y += dma-contiguous.h
diff --git a/arch/mips/include/asm/checksum.h b/arch/mips/include/asm/checksum.h
index 3418c51e1151..8464b62443b2 100644
--- a/arch/mips/include/asm/checksum.h
+++ b/arch/mips/include/asm/checksum.h
@@ -12,6 +12,10 @@
 #ifndef _ASM_CHECKSUM_H
 #define _ASM_CHECKSUM_H
 
+#ifdef CONFIG_GENERIC_CSUM
+#include <asm-generic/checksum.h>
+#else
+
 #include <linux/in6.h>
 
 #include <asm/uaccess.h>
@@ -287,4 +291,6 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
 	return csum_fold(sum);
 }
 
+#endif /* CONFIG_GENERIC_CSUM */
+
 #endif /* _ASM_CHECKSUM_H */
diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c
index 2607c3a4ff7e..631f6fed6092 100644
--- a/arch/mips/kernel/mips_ksyms.c
+++ b/arch/mips/kernel/mips_ksyms.c
@@ -71,11 +71,13 @@ EXPORT_SYMBOL(__strnlen_kernel_asm);
 EXPORT_SYMBOL(__strnlen_user_nocheck_asm);
 EXPORT_SYMBOL(__strnlen_user_asm);
 
+#ifndef CONFIG_CPU_MIPSR6
 EXPORT_SYMBOL(csum_partial);
 EXPORT_SYMBOL(csum_partial_copy_nocheck);
 EXPORT_SYMBOL(__csum_partial_copy_kernel);
 EXPORT_SYMBOL(__csum_partial_copy_to_user);
 EXPORT_SYMBOL(__csum_partial_copy_from_user);
+#endif
 
 EXPORT_SYMBOL(invalid_pte_table);
 #ifdef CONFIG_FUNCTION_TRACER
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index eeddc58802e1..1e9e900cd3c3 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -8,6 +8,7 @@ lib-y	+= bitops.o csum_partial.o delay.o memcpy.o memset.o \
 
 obj-y			+= iomap.o
 obj-$(CONFIG_PCI)	+= iomap-pci.o
+lib-$(CONFIG_GENERIC_CSUM)	:= $(filter-out csum_partial.o, $(lib-y))
 
 obj-$(CONFIG_CPU_GENERIC_DUMP_TLB) += dump_tlb.o
 obj-$(CONFIG_CPU_R3000)		+= r3k_dump_tlb.o
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 14/67] MIPS: asm: cpu: Add MIPSR6 ISA definitions
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

Add MIPS R6 to the ISA definitions

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/cpu-features.h | 14 +++++++++++---
 arch/mips/include/asm/cpu.h          |  7 +++++--
 2 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h
index 3325f3eb248c..5830557539c0 100644
--- a/arch/mips/include/asm/cpu-features.h
+++ b/arch/mips/include/asm/cpu-features.h
@@ -189,12 +189,18 @@
 #ifndef cpu_has_mips32r2
 # define cpu_has_mips32r2	(cpu_data[0].isa_level & MIPS_CPU_ISA_M32R2)
 #endif
+#ifndef cpu_has_mips32r6
+# define cpu_has_mips32r6	(cpu_data[0].isa_level & MIPS_CPU_ISA_M32R6)
+#endif
 #ifndef cpu_has_mips64r1
 # define cpu_has_mips64r1	(cpu_data[0].isa_level & MIPS_CPU_ISA_M64R1)
 #endif
 #ifndef cpu_has_mips64r2
 # define cpu_has_mips64r2	(cpu_data[0].isa_level & MIPS_CPU_ISA_M64R2)
 #endif
+#ifndef cpu_has_mips64r6
+# define cpu_has_mips64r6	(cpu_data[0].isa_level & MIPS_CPU_ISA_M64R6)
+#endif
 
 /*
  * Shortcuts ...
@@ -210,15 +216,17 @@
 
 #define cpu_has_mips_4_5_r2	(cpu_has_mips_4_5 | cpu_has_mips_r2)
 
-#define cpu_has_mips32	(cpu_has_mips32r1 | cpu_has_mips32r2)
+#define cpu_has_mips32	(cpu_has_mips32r1 | cpu_has_mips32r2 | cpu_has_mips32r6)
 #define cpu_has_mips64	(cpu_has_mips64r1 | cpu_has_mips64r2)
 #define cpu_has_mips_r1 (cpu_has_mips32r1 | cpu_has_mips64r1)
 #define cpu_has_mips_r2 (cpu_has_mips32r2 | cpu_has_mips64r2)
+#define cpu_has_mips_r6	(cpu_has_mips32r6 | cpu_has_mips64r6)
 #define cpu_has_mips_r	(cpu_has_mips32r1 | cpu_has_mips32r2 | \
-			 cpu_has_mips64r1 | cpu_has_mips64r2)
+			 cpu_has_mips32r6 | cpu_has_mips64r1 | \
+			 cpu_has_mips64r2 | cpu_has_mips64r6)
 
 #ifndef cpu_has_mips_r2_exec_hazard
-#define cpu_has_mips_r2_exec_hazard cpu_has_mips_r2
+#define cpu_has_mips_r2_exec_hazard (cpu_has_mips_r2 | cpu_has_mips_r6)
 #endif
 
 /*
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index 23a5dbc0ee06..c525f5060773 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -331,11 +331,14 @@ enum cpu_type_enum {
 #define MIPS_CPU_ISA_M32R2	0x00000020
 #define MIPS_CPU_ISA_M64R1	0x00000040
 #define MIPS_CPU_ISA_M64R2	0x00000080
+#define MIPS_CPU_ISA_M32R6	0x00000100
+#define MIPS_CPU_ISA_M64R6	0x00000200
 
 #define MIPS_CPU_ISA_32BIT (MIPS_CPU_ISA_II | MIPS_CPU_ISA_M32R1 | \
-	MIPS_CPU_ISA_M32R2)
+	MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M32R6)
 #define MIPS_CPU_ISA_64BIT (MIPS_CPU_ISA_III | MIPS_CPU_ISA_IV | \
-	MIPS_CPU_ISA_V | MIPS_CPU_ISA_M64R1 | MIPS_CPU_ISA_M64R2)
+	MIPS_CPU_ISA_V | MIPS_CPU_ISA_M64R1 | MIPS_CPU_ISA_M64R2 | \
+	MIPS_CPU_ISA_M64R6)
 
 /*
  * CPU Option encodings
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 14/67] MIPS: asm: cpu: Add MIPSR6 ISA definitions
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

Add MIPS R6 to the ISA definitions

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/cpu-features.h | 14 +++++++++++---
 arch/mips/include/asm/cpu.h          |  7 +++++--
 2 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h
index 3325f3eb248c..5830557539c0 100644
--- a/arch/mips/include/asm/cpu-features.h
+++ b/arch/mips/include/asm/cpu-features.h
@@ -189,12 +189,18 @@
 #ifndef cpu_has_mips32r2
 # define cpu_has_mips32r2	(cpu_data[0].isa_level & MIPS_CPU_ISA_M32R2)
 #endif
+#ifndef cpu_has_mips32r6
+# define cpu_has_mips32r6	(cpu_data[0].isa_level & MIPS_CPU_ISA_M32R6)
+#endif
 #ifndef cpu_has_mips64r1
 # define cpu_has_mips64r1	(cpu_data[0].isa_level & MIPS_CPU_ISA_M64R1)
 #endif
 #ifndef cpu_has_mips64r2
 # define cpu_has_mips64r2	(cpu_data[0].isa_level & MIPS_CPU_ISA_M64R2)
 #endif
+#ifndef cpu_has_mips64r6
+# define cpu_has_mips64r6	(cpu_data[0].isa_level & MIPS_CPU_ISA_M64R6)
+#endif
 
 /*
  * Shortcuts ...
@@ -210,15 +216,17 @@
 
 #define cpu_has_mips_4_5_r2	(cpu_has_mips_4_5 | cpu_has_mips_r2)
 
-#define cpu_has_mips32	(cpu_has_mips32r1 | cpu_has_mips32r2)
+#define cpu_has_mips32	(cpu_has_mips32r1 | cpu_has_mips32r2 | cpu_has_mips32r6)
 #define cpu_has_mips64	(cpu_has_mips64r1 | cpu_has_mips64r2)
 #define cpu_has_mips_r1 (cpu_has_mips32r1 | cpu_has_mips64r1)
 #define cpu_has_mips_r2 (cpu_has_mips32r2 | cpu_has_mips64r2)
+#define cpu_has_mips_r6	(cpu_has_mips32r6 | cpu_has_mips64r6)
 #define cpu_has_mips_r	(cpu_has_mips32r1 | cpu_has_mips32r2 | \
-			 cpu_has_mips64r1 | cpu_has_mips64r2)
+			 cpu_has_mips32r6 | cpu_has_mips64r1 | \
+			 cpu_has_mips64r2 | cpu_has_mips64r6)
 
 #ifndef cpu_has_mips_r2_exec_hazard
-#define cpu_has_mips_r2_exec_hazard cpu_has_mips_r2
+#define cpu_has_mips_r2_exec_hazard (cpu_has_mips_r2 | cpu_has_mips_r6)
 #endif
 
 /*
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index 23a5dbc0ee06..c525f5060773 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -331,11 +331,14 @@ enum cpu_type_enum {
 #define MIPS_CPU_ISA_M32R2	0x00000020
 #define MIPS_CPU_ISA_M64R1	0x00000040
 #define MIPS_CPU_ISA_M64R2	0x00000080
+#define MIPS_CPU_ISA_M32R6	0x00000100
+#define MIPS_CPU_ISA_M64R6	0x00000200
 
 #define MIPS_CPU_ISA_32BIT (MIPS_CPU_ISA_II | MIPS_CPU_ISA_M32R1 | \
-	MIPS_CPU_ISA_M32R2)
+	MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M32R6)
 #define MIPS_CPU_ISA_64BIT (MIPS_CPU_ISA_III | MIPS_CPU_ISA_IV | \
-	MIPS_CPU_ISA_V | MIPS_CPU_ISA_M64R1 | MIPS_CPU_ISA_M64R2)
+	MIPS_CPU_ISA_V | MIPS_CPU_ISA_M64R1 | MIPS_CPU_ISA_M64R2 | \
+	MIPS_CPU_ISA_M64R6)
 
 /*
  * CPU Option encodings
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 15/67] MIPS: asm: hazards: Add MIPSR6 definitions
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

Add the MIPSR6 related definitions to MIPS hazards

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/hazards.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/mips/include/asm/hazards.h b/arch/mips/include/asm/hazards.h
index e3ee92d4dbe7..beb55bac40a1 100644
--- a/arch/mips/include/asm/hazards.h
+++ b/arch/mips/include/asm/hazards.h
@@ -21,7 +21,7 @@
 /*
  * TLB hazards
  */
-#if defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_CPU_CAVIUM_OCTEON)
+#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) && !defined(CONFIG_CPU_CAVIUM_OCTEON)
 
 /*
  * MIPSR2 defines ehb for hazard avoidance
@@ -58,7 +58,7 @@ do {									\
 	unsigned long tmp;						\
 									\
 	__asm__ __volatile__(						\
-	"	.set	mips64r2				\n"	\
+	"	.set "MIPS_ISA_LEVEL"				\n"	\
 	"	dla	%0, 1f					\n"	\
 	"	jr.hb	%0					\n"	\
 	"	.set	mips0					\n"	\
@@ -132,7 +132,7 @@ do {									\
 
 #define instruction_hazard()						\
 do {									\
-	if (cpu_has_mips_r2)						\
+	if (cpu_has_mips_r2 || cpu_has_mips_r6)						\
 		__instruction_hazard();					\
 } while (0)
 
@@ -240,7 +240,7 @@ do {									\
 
 #define __disable_fpu_hazard
 
-#elif defined(CONFIG_CPU_MIPSR2)
+#elif defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
 
 #define __enable_fpu_hazard						\
 	___ehb
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 15/67] MIPS: asm: hazards: Add MIPSR6 definitions
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

Add the MIPSR6 related definitions to MIPS hazards

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/hazards.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/mips/include/asm/hazards.h b/arch/mips/include/asm/hazards.h
index e3ee92d4dbe7..beb55bac40a1 100644
--- a/arch/mips/include/asm/hazards.h
+++ b/arch/mips/include/asm/hazards.h
@@ -21,7 +21,7 @@
 /*
  * TLB hazards
  */
-#if defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_CPU_CAVIUM_OCTEON)
+#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) && !defined(CONFIG_CPU_CAVIUM_OCTEON)
 
 /*
  * MIPSR2 defines ehb for hazard avoidance
@@ -58,7 +58,7 @@ do {									\
 	unsigned long tmp;						\
 									\
 	__asm__ __volatile__(						\
-	"	.set	mips64r2				\n"	\
+	"	.set "MIPS_ISA_LEVEL"				\n"	\
 	"	dla	%0, 1f					\n"	\
 	"	jr.hb	%0					\n"	\
 	"	.set	mips0					\n"	\
@@ -132,7 +132,7 @@ do {									\
 
 #define instruction_hazard()						\
 do {									\
-	if (cpu_has_mips_r2)						\
+	if (cpu_has_mips_r2 || cpu_has_mips_r6)						\
 		__instruction_hazard();					\
 } while (0)
 
@@ -240,7 +240,7 @@ do {									\
 
 #define __disable_fpu_hazard
 
-#elif defined(CONFIG_CPU_MIPSR2)
+#elif defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
 
 #define __enable_fpu_hazard						\
 	___ehb
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 16/67] MIPS: asm: irqflags: Add MIPS R6 related definitions
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

Add the MIPS R6 related definitions to the IRQ related macros

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/irqflags.h | 6 +++---
 arch/mips/lib/mips-atomic.c      | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/mips/include/asm/irqflags.h b/arch/mips/include/asm/irqflags.h
index 0fa5fdcd1f01..204b4de56f2a 100644
--- a/arch/mips/include/asm/irqflags.h
+++ b/arch/mips/include/asm/irqflags.h
@@ -17,7 +17,7 @@
 #include <linux/stringify.h>
 #include <asm/hazards.h>
 
-#ifdef CONFIG_CPU_MIPSR2
+#if defined(CONFIG_CPU_MIPSR2) || defined (CONFIG_CPU_MIPSR6)
 
 static inline void arch_local_irq_disable(void)
 {
@@ -118,7 +118,7 @@ void arch_local_irq_disable(void);
 unsigned long arch_local_irq_save(void);
 void arch_local_irq_restore(unsigned long flags);
 void __arch_local_irq_restore(unsigned long flags);
-#endif /* CONFIG_CPU_MIPSR2 */
+#endif /* CONFIG_CPU_MIPSR2 || CONFIG_CPU_MIPSR6 */
 
 static inline void arch_local_irq_enable(void)
 {
@@ -126,7 +126,7 @@ static inline void arch_local_irq_enable(void)
 	"	.set	push						\n"
 	"	.set	reorder						\n"
 	"	.set	noat						\n"
-#if   defined(CONFIG_CPU_MIPSR2)
+#if   defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
 	"	ei							\n"
 #else
 	"	mfc0	$1,$12						\n"
diff --git a/arch/mips/lib/mips-atomic.c b/arch/mips/lib/mips-atomic.c
index 57bcdaf1f1c8..8071422f2831 100644
--- a/arch/mips/lib/mips-atomic.c
+++ b/arch/mips/lib/mips-atomic.c
@@ -15,7 +15,7 @@
 #include <linux/export.h>
 #include <linux/stringify.h>
 
-#ifndef CONFIG_CPU_MIPSR2
+#if !defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_CPU_MIPSR6)
 
 /*
  * For cli() we have to insert nops to make sure that the new value
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 16/67] MIPS: asm: irqflags: Add MIPS R6 related definitions
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

Add the MIPS R6 related definitions to the IRQ related macros

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/irqflags.h | 6 +++---
 arch/mips/lib/mips-atomic.c      | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/mips/include/asm/irqflags.h b/arch/mips/include/asm/irqflags.h
index 0fa5fdcd1f01..204b4de56f2a 100644
--- a/arch/mips/include/asm/irqflags.h
+++ b/arch/mips/include/asm/irqflags.h
@@ -17,7 +17,7 @@
 #include <linux/stringify.h>
 #include <asm/hazards.h>
 
-#ifdef CONFIG_CPU_MIPSR2
+#if defined(CONFIG_CPU_MIPSR2) || defined (CONFIG_CPU_MIPSR6)
 
 static inline void arch_local_irq_disable(void)
 {
@@ -118,7 +118,7 @@ void arch_local_irq_disable(void);
 unsigned long arch_local_irq_save(void);
 void arch_local_irq_restore(unsigned long flags);
 void __arch_local_irq_restore(unsigned long flags);
-#endif /* CONFIG_CPU_MIPSR2 */
+#endif /* CONFIG_CPU_MIPSR2 || CONFIG_CPU_MIPSR6 */
 
 static inline void arch_local_irq_enable(void)
 {
@@ -126,7 +126,7 @@ static inline void arch_local_irq_enable(void)
 	"	.set	push						\n"
 	"	.set	reorder						\n"
 	"	.set	noat						\n"
-#if   defined(CONFIG_CPU_MIPSR2)
+#if   defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
 	"	ei							\n"
 #else
 	"	mfc0	$1,$12						\n"
diff --git a/arch/mips/lib/mips-atomic.c b/arch/mips/lib/mips-atomic.c
index 57bcdaf1f1c8..8071422f2831 100644
--- a/arch/mips/lib/mips-atomic.c
+++ b/arch/mips/lib/mips-atomic.c
@@ -15,7 +15,7 @@
 #include <linux/export.h>
 #include <linux/stringify.h>
 
-#ifndef CONFIG_CPU_MIPSR2
+#if !defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_CPU_MIPSR6)
 
 /*
  * For cli() we have to insert nops to make sure that the new value
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 17/67] MIPS: asm: r4kcache: Add MIPS R6 cache unroll functions
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 changed the 'cache' instruction opcode and reduced the
offset field to 8 bits. This means we now have to adjust the
base register every 256 bytes and as a result of which we can
no longer use the previous cache functions.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/r4kcache.h | 149 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 147 insertions(+), 2 deletions(-)

diff --git a/arch/mips/include/asm/r4kcache.h b/arch/mips/include/asm/r4kcache.h
index cd6e0afc6833..6a32e16a45d8 100644
--- a/arch/mips/include/asm/r4kcache.h
+++ b/arch/mips/include/asm/r4kcache.h
@@ -39,7 +39,7 @@ extern void (*r4k_blast_icache)(void);
 	__asm__ __volatile__(						\
 	"	.set	push					\n"	\
 	"	.set	noreorder				\n"	\
-	"	.set	arch=r4000				\n"	\
+	"	.set "MIPS_ISA_ARCH_LEVEL"			\n"	\
 	"	cache	%0, %1					\n"	\
 	"	.set	pop					\n"	\
 	:								\
@@ -206,7 +206,7 @@ static inline void flush_scache_line(unsigned long addr)
 	__asm__ __volatile__(					\
 	"	.set	push			\n"		\
 	"	.set	noreorder		\n"		\
-	"	.set	arch=r4000		\n"		\
+	"	.set "MIPS_ISA_ARCH_LEVEL"	\n"		\
 	"1:	cache	%0, (%1)		\n"		\
 	"2:	.set	pop			\n"		\
 	"	.section __ex_table,\"a\"	\n"		\
@@ -277,6 +277,7 @@ static inline void invalidate_tcache_page(unsigned long addr)
 	cache_op(Page_Invalidate_T, addr);
 }
 
+#ifndef CONFIG_CPU_MIPSR6
 #define cache16_unroll32(base,op)					\
 	__asm__ __volatile__(						\
 	"	.set push					\n"	\
@@ -381,6 +382,150 @@ static inline void invalidate_tcache_page(unsigned long addr)
 		: "r" (base),						\
 		  "i" (op));
 
+#else
+/*
+ * MIPS R6 changed the cache opcode and moved to a 8-bit offset field.
+ * This means we now need to increment the base register before we flush
+ * more cache lines
+ */
+#define cache16_unroll32(base,op)				\
+	__asm__ __volatile__(					\
+	"	.set push\n"					\
+	"	.set noreorder\n"				\
+	"	.set mips64r6\n"				\
+	"	.set noat\n"					\
+	"	cache %1, 0x000(%0); cache %1, 0x010(%0)\n"	\
+	"	cache %1, 0x020(%0); cache %1, 0x030(%0)\n"	\
+	"	cache %1, 0x040(%0); cache %1, 0x050(%0)\n"	\
+	"	cache %1, 0x060(%0); cache %1, 0x070(%0)\n"	\
+	"	cache %1, 0x080(%0); cache %1, 0x090(%0)\n"	\
+	"	cache %1, 0x0a0(%0); cache %1, 0x0b0(%0)\n"	\
+	"	cache %1, 0x0c0(%0); cache %1, 0x0d0(%0)\n"	\
+	"	cache %1, 0x0e0(%0); cache %1, 0x0f0(%0)\n"	\
+	"	addiu $1, $0, 0x100			\n"	\
+	"	cache %1, 0x000($1); cache %1, 0x010($1)\n"	\
+	"	cache %1, 0x020($1); cache %1, 0x030($1)\n"	\
+	"	cache %1, 0x040($1); cache %1, 0x050($1)\n"	\
+	"	cache %1, 0x060($1); cache %1, 0x070($1)\n"	\
+	"	cache %1, 0x080($1); cache %1, 0x090($1)\n"	\
+	"	cache %1, 0x0a0($1); cache %1, 0x0b0($1)\n"	\
+	"	cache %1, 0x0c0($1); cache %1, 0x0d0($1)\n"	\
+	"	cache %1, 0x0e0($1); cache %1, 0x0f0($1)\n"	\
+	"	.set pop\n"					\
+		:						\
+		: "r" (base),					\
+		  "i" (op));
+
+#define cache32_unroll32(base,op)				\
+	__asm__ __volatile__(					\
+	"	.set push\n"					\
+	"	.set noreorder\n"				\
+	"	.set mips64r6\n"				\
+	"	.set noat\n"					\
+	"	cache %1, 0x000(%0); cache %1, 0x020(%0)\n"	\
+	"	cache %1, 0x040(%0); cache %1, 0x060(%0)\n"	\
+	"	cache %1, 0x080(%0); cache %1, 0x0a0(%0)\n"	\
+	"	cache %1, 0x0c0(%0); cache %1, 0x0e0(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000($1); cache %1, 0x020($1)\n"	\
+	"	cache %1, 0x040($1); cache %1, 0x060($1)\n"	\
+	"	cache %1, 0x080($1); cache %1, 0x0a0($1)\n"	\
+	"	cache %1, 0x0c0($1); cache %1, 0x0e0($1)\n"	\
+	"	addiu $1, $1, 0x100\n"				\
+	"	cache %1, 0x000($1); cache %1, 0x020($1)\n"	\
+	"	cache %1, 0x040($1); cache %1, 0x060($1)\n"	\
+	"	cache %1, 0x080($1); cache %1, 0x0a0($1)\n"	\
+	"	cache %1, 0x0c0($1); cache %1, 0x0e0($1)\n"	\
+	"	addiu $1, $1, 0x100\n"				\
+	"	cache %1, 0x000($1); cache %1, 0x020($1)\n"	\
+	"	cache %1, 0x040($1); cache %1, 0x060($1)\n"	\
+	"	cache %1, 0x080($1); cache %1, 0x0a0($1)\n"	\
+	"	cache %1, 0x0c0($1); cache %1, 0x0e0($1)\n"	\
+	"	.set pop\n"					\
+		:						\
+		: "r" (base),					\
+		  "i" (op));
+
+#define cache64_unroll32(base,op)				\
+	__asm__ __volatile__(					\
+	"	.set push\n"					\
+	"	.set noreorder\n"				\
+	"	.set mips64r6\n"				\
+	"	.set noat\n"					\
+	"	cache %1, 0x000(%0); cache %1, 0x040(%0)\n"	\
+	"	cache %1, 0x080(%0); cache %1, 0x0c0(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000($1); cache %1, 0x040($1)\n"	\
+	"	cache %1, 0x080($1); cache %1, 0x0c0($1)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000($1); cache %1, 0x040($1)\n"	\
+	"	cache %1, 0x080($1); cache %1, 0x0c0($1)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000($1); cache %1, 0x040($1)\n"	\
+	"	cache %1, 0x080($1); cache %1, 0x0c0($1)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000($1); cache %1, 0x040($1)\n"	\
+	"	cache %1, 0x080($1); cache %1, 0x0c0($1)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000($1); cache %1, 0x040($1)\n"	\
+	"	cache %1, 0x080($1); cache %1, 0x0c0($1)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000($1); cache %1, 0x040($1)\n"	\
+	"	cache %1, 0x080($1); cache %1, 0x0c0($1)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000($1); cache %1, 0x040($1)\n"	\
+	"	cache %1, 0x080($1); cache %1, 0x0c0($1)\n"	\
+	"	.set pop\n"					\
+		:						\
+		: "r" (base),					\
+		  "i" (op));
+
+#define cache128_unroll32(base,op)				\
+	__asm__ __volatile__(					\
+	"	.set push\n"					\
+	"	.set noreorder\n"				\
+	"	.set mips64r6\n"				\
+	"	.set noat\n"					\
+	"	cache %1, 0x000(%0); cache %1, 0x080(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000(%0); cache %1, 0x080(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000(%0); cache %1, 0x080(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000(%0); cache %1, 0x080(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000(%0); cache %1, 0x080(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000(%0); cache %1, 0x080(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000(%0); cache %1, 0x080(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000(%0); cache %1, 0x080(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000(%0); cache %1, 0x080(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000(%0); cache %1, 0x080(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000(%0); cache %1, 0x080(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000(%0); cache %1, 0x080(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000(%0); cache %1, 0x080(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000(%0); cache %1, 0x080(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000(%0); cache %1, 0x080(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000(%0); cache %1, 0x080(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000(%0); cache %1, 0x080(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	.set pop\n"					\
+		:						\
+		: "r" (base),					\
+		  "i" (op));
+#endif /* CONFIG_CPU_MIPSR6 */
+
 /*
  * Perform the cache operation specified by op using a user mode virtual
  * address while in kernel mode.
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 17/67] MIPS: asm: r4kcache: Add MIPS R6 cache unroll functions
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 changed the 'cache' instruction opcode and reduced the
offset field to 8 bits. This means we now have to adjust the
base register every 256 bytes and as a result of which we can
no longer use the previous cache functions.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/r4kcache.h | 149 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 147 insertions(+), 2 deletions(-)

diff --git a/arch/mips/include/asm/r4kcache.h b/arch/mips/include/asm/r4kcache.h
index cd6e0afc6833..6a32e16a45d8 100644
--- a/arch/mips/include/asm/r4kcache.h
+++ b/arch/mips/include/asm/r4kcache.h
@@ -39,7 +39,7 @@ extern void (*r4k_blast_icache)(void);
 	__asm__ __volatile__(						\
 	"	.set	push					\n"	\
 	"	.set	noreorder				\n"	\
-	"	.set	arch=r4000				\n"	\
+	"	.set "MIPS_ISA_ARCH_LEVEL"			\n"	\
 	"	cache	%0, %1					\n"	\
 	"	.set	pop					\n"	\
 	:								\
@@ -206,7 +206,7 @@ static inline void flush_scache_line(unsigned long addr)
 	__asm__ __volatile__(					\
 	"	.set	push			\n"		\
 	"	.set	noreorder		\n"		\
-	"	.set	arch=r4000		\n"		\
+	"	.set "MIPS_ISA_ARCH_LEVEL"	\n"		\
 	"1:	cache	%0, (%1)		\n"		\
 	"2:	.set	pop			\n"		\
 	"	.section __ex_table,\"a\"	\n"		\
@@ -277,6 +277,7 @@ static inline void invalidate_tcache_page(unsigned long addr)
 	cache_op(Page_Invalidate_T, addr);
 }
 
+#ifndef CONFIG_CPU_MIPSR6
 #define cache16_unroll32(base,op)					\
 	__asm__ __volatile__(						\
 	"	.set push					\n"	\
@@ -381,6 +382,150 @@ static inline void invalidate_tcache_page(unsigned long addr)
 		: "r" (base),						\
 		  "i" (op));
 
+#else
+/*
+ * MIPS R6 changed the cache opcode and moved to a 8-bit offset field.
+ * This means we now need to increment the base register before we flush
+ * more cache lines
+ */
+#define cache16_unroll32(base,op)				\
+	__asm__ __volatile__(					\
+	"	.set push\n"					\
+	"	.set noreorder\n"				\
+	"	.set mips64r6\n"				\
+	"	.set noat\n"					\
+	"	cache %1, 0x000(%0); cache %1, 0x010(%0)\n"	\
+	"	cache %1, 0x020(%0); cache %1, 0x030(%0)\n"	\
+	"	cache %1, 0x040(%0); cache %1, 0x050(%0)\n"	\
+	"	cache %1, 0x060(%0); cache %1, 0x070(%0)\n"	\
+	"	cache %1, 0x080(%0); cache %1, 0x090(%0)\n"	\
+	"	cache %1, 0x0a0(%0); cache %1, 0x0b0(%0)\n"	\
+	"	cache %1, 0x0c0(%0); cache %1, 0x0d0(%0)\n"	\
+	"	cache %1, 0x0e0(%0); cache %1, 0x0f0(%0)\n"	\
+	"	addiu $1, $0, 0x100			\n"	\
+	"	cache %1, 0x000($1); cache %1, 0x010($1)\n"	\
+	"	cache %1, 0x020($1); cache %1, 0x030($1)\n"	\
+	"	cache %1, 0x040($1); cache %1, 0x050($1)\n"	\
+	"	cache %1, 0x060($1); cache %1, 0x070($1)\n"	\
+	"	cache %1, 0x080($1); cache %1, 0x090($1)\n"	\
+	"	cache %1, 0x0a0($1); cache %1, 0x0b0($1)\n"	\
+	"	cache %1, 0x0c0($1); cache %1, 0x0d0($1)\n"	\
+	"	cache %1, 0x0e0($1); cache %1, 0x0f0($1)\n"	\
+	"	.set pop\n"					\
+		:						\
+		: "r" (base),					\
+		  "i" (op));
+
+#define cache32_unroll32(base,op)				\
+	__asm__ __volatile__(					\
+	"	.set push\n"					\
+	"	.set noreorder\n"				\
+	"	.set mips64r6\n"				\
+	"	.set noat\n"					\
+	"	cache %1, 0x000(%0); cache %1, 0x020(%0)\n"	\
+	"	cache %1, 0x040(%0); cache %1, 0x060(%0)\n"	\
+	"	cache %1, 0x080(%0); cache %1, 0x0a0(%0)\n"	\
+	"	cache %1, 0x0c0(%0); cache %1, 0x0e0(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000($1); cache %1, 0x020($1)\n"	\
+	"	cache %1, 0x040($1); cache %1, 0x060($1)\n"	\
+	"	cache %1, 0x080($1); cache %1, 0x0a0($1)\n"	\
+	"	cache %1, 0x0c0($1); cache %1, 0x0e0($1)\n"	\
+	"	addiu $1, $1, 0x100\n"				\
+	"	cache %1, 0x000($1); cache %1, 0x020($1)\n"	\
+	"	cache %1, 0x040($1); cache %1, 0x060($1)\n"	\
+	"	cache %1, 0x080($1); cache %1, 0x0a0($1)\n"	\
+	"	cache %1, 0x0c0($1); cache %1, 0x0e0($1)\n"	\
+	"	addiu $1, $1, 0x100\n"				\
+	"	cache %1, 0x000($1); cache %1, 0x020($1)\n"	\
+	"	cache %1, 0x040($1); cache %1, 0x060($1)\n"	\
+	"	cache %1, 0x080($1); cache %1, 0x0a0($1)\n"	\
+	"	cache %1, 0x0c0($1); cache %1, 0x0e0($1)\n"	\
+	"	.set pop\n"					\
+		:						\
+		: "r" (base),					\
+		  "i" (op));
+
+#define cache64_unroll32(base,op)				\
+	__asm__ __volatile__(					\
+	"	.set push\n"					\
+	"	.set noreorder\n"				\
+	"	.set mips64r6\n"				\
+	"	.set noat\n"					\
+	"	cache %1, 0x000(%0); cache %1, 0x040(%0)\n"	\
+	"	cache %1, 0x080(%0); cache %1, 0x0c0(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000($1); cache %1, 0x040($1)\n"	\
+	"	cache %1, 0x080($1); cache %1, 0x0c0($1)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000($1); cache %1, 0x040($1)\n"	\
+	"	cache %1, 0x080($1); cache %1, 0x0c0($1)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000($1); cache %1, 0x040($1)\n"	\
+	"	cache %1, 0x080($1); cache %1, 0x0c0($1)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000($1); cache %1, 0x040($1)\n"	\
+	"	cache %1, 0x080($1); cache %1, 0x0c0($1)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000($1); cache %1, 0x040($1)\n"	\
+	"	cache %1, 0x080($1); cache %1, 0x0c0($1)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000($1); cache %1, 0x040($1)\n"	\
+	"	cache %1, 0x080($1); cache %1, 0x0c0($1)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000($1); cache %1, 0x040($1)\n"	\
+	"	cache %1, 0x080($1); cache %1, 0x0c0($1)\n"	\
+	"	.set pop\n"					\
+		:						\
+		: "r" (base),					\
+		  "i" (op));
+
+#define cache128_unroll32(base,op)				\
+	__asm__ __volatile__(					\
+	"	.set push\n"					\
+	"	.set noreorder\n"				\
+	"	.set mips64r6\n"				\
+	"	.set noat\n"					\
+	"	cache %1, 0x000(%0); cache %1, 0x080(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000(%0); cache %1, 0x080(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000(%0); cache %1, 0x080(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000(%0); cache %1, 0x080(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000(%0); cache %1, 0x080(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000(%0); cache %1, 0x080(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000(%0); cache %1, 0x080(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000(%0); cache %1, 0x080(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000(%0); cache %1, 0x080(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000(%0); cache %1, 0x080(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000(%0); cache %1, 0x080(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000(%0); cache %1, 0x080(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000(%0); cache %1, 0x080(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000(%0); cache %1, 0x080(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000(%0); cache %1, 0x080(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000(%0); cache %1, 0x080(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	cache %1, 0x000(%0); cache %1, 0x080(%0)\n"	\
+	"	addiu $1, %0, 0x100\n"				\
+	"	.set pop\n"					\
+		:						\
+		: "r" (base),					\
+		  "i" (op));
+#endif /* CONFIG_CPU_MIPSR6 */
+
 /*
  * Perform the cache operation specified by op using a user mode virtual
  * address while in kernel mode.
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 18/67] MIPS: asm: spram: Add MIPS R6 related definitions
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6, just like MIPS R2, can use the spram_config() function
in spram.c

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/spram.h | 4 ++--
 arch/mips/kernel/Makefile     | 1 +
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/mips/include/asm/spram.h b/arch/mips/include/asm/spram.h
index 0b89006e4907..e02a1961c542 100644
--- a/arch/mips/include/asm/spram.h
+++ b/arch/mips/include/asm/spram.h
@@ -1,10 +1,10 @@
 #ifndef _MIPS_SPRAM_H
 #define _MIPS_SPRAM_H
 
-#ifdef CONFIG_CPU_MIPSR2
+#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
 extern __init void spram_config(void);
 #else
 static inline void spram_config(void) { };
-#endif /* CONFIG_CPU_MIPSR2 */
+#endif /* CONFIG_CPU_MIPSR2 || CONFIG_CPU_MIPSR6 */
 
 #endif /* _MIPS_SPRAM_H */
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 008a2fed0584..f6ee8cc1f7c2 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -54,6 +54,7 @@ obj-$(CONFIG_MIPS_CMP)		+= smp-cmp.o
 obj-$(CONFIG_MIPS_CPS)		+= smp-cps.o cps-vec.o
 obj-$(CONFIG_MIPS_GIC_IPI)	+= smp-gic.o
 obj-$(CONFIG_CPU_MIPSR2)	+= spram.o
+obj-$(CONFIG_CPU_MIPSR6)	+= spram.o
 
 obj-$(CONFIG_MIPS_VPE_LOADER)	+= vpe.o
 obj-$(CONFIG_MIPS_VPE_LOADER_CMP) += vpe-cmp.o
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 18/67] MIPS: asm: spram: Add MIPS R6 related definitions
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6, just like MIPS R2, can use the spram_config() function
in spram.c

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/spram.h | 4 ++--
 arch/mips/kernel/Makefile     | 1 +
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/mips/include/asm/spram.h b/arch/mips/include/asm/spram.h
index 0b89006e4907..e02a1961c542 100644
--- a/arch/mips/include/asm/spram.h
+++ b/arch/mips/include/asm/spram.h
@@ -1,10 +1,10 @@
 #ifndef _MIPS_SPRAM_H
 #define _MIPS_SPRAM_H
 
-#ifdef CONFIG_CPU_MIPSR2
+#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
 extern __init void spram_config(void);
 #else
 static inline void spram_config(void) { };
-#endif /* CONFIG_CPU_MIPSR2 */
+#endif /* CONFIG_CPU_MIPSR2 || CONFIG_CPU_MIPSR6 */
 
 #endif /* _MIPS_SPRAM_H */
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 008a2fed0584..f6ee8cc1f7c2 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -54,6 +54,7 @@ obj-$(CONFIG_MIPS_CMP)		+= smp-cmp.o
 obj-$(CONFIG_MIPS_CPS)		+= smp-cps.o cps-vec.o
 obj-$(CONFIG_MIPS_GIC_IPI)	+= smp-gic.o
 obj-$(CONFIG_CPU_MIPSR2)	+= spram.o
+obj-$(CONFIG_CPU_MIPSR6)	+= spram.o
 
 obj-$(CONFIG_MIPS_VPE_LOADER)	+= vpe.o
 obj-$(CONFIG_MIPS_VPE_LOADER_CMP) += vpe-cmp.o
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 19/67] MIPS: asm: atomic: Update asm and ISA constrains for MIPS R6 support
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Matthew Fortune

MIPS R6 changed the opcodes for LL/SC instructions and reduced the
offset field to 9-bits. This has some undesired effects with the "m"
constrain since it implies a 16-bit immediate. As a result of which,
add a register ("r") constrain as well to make sure the entire address
is loaded to a register before the LL/SC operations. Also use macro
to set the appropriate ISA for the asm blocks

Cc: Matthew Fortune <Matthew.Fortune@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/atomic.h | 50 +++++++++++++++++++++---------------------
 1 file changed, 25 insertions(+), 25 deletions(-)

diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h
index 6dd6bfc607e9..8669e0ec97e3 100644
--- a/arch/mips/include/asm/atomic.h
+++ b/arch/mips/include/asm/atomic.h
@@ -60,13 +60,13 @@ static __inline__ void atomic_##op(int i, atomic_t * v)				\
 										\
 		do {								\
 			__asm__ __volatile__(					\
-			"	.set	arch=r4000			\n"	\
-			"	ll	%0, %1		# atomic_" #op "\n"	\
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"	\
+			"	ll	%0, 0(%3)	# atomic_" #op "\n"	\
 			"	" #asm_op " %0, %2			\n"	\
-			"	sc	%0, %1				\n"	\
+			"	sc	%0, 0(%3)			\n"	\
 			"	.set	mips0				\n"	\
 			: "=&r" (temp), "+m" (v->counter)			\
-			: "Ir" (i));						\
+			: "Ir" (i), "r" (&v->counter));				\
 		} while (unlikely(!temp));					\
 	} else {								\
 		unsigned long flags;						\
@@ -102,13 +102,13 @@ static __inline__ int atomic_##op##_return(int i, atomic_t * v)			\
 										\
 		do {								\
 			__asm__ __volatile__(					\
-			"	.set	arch=r4000			\n"	\
-			"	ll	%1, %2	# atomic_" #op "_return	\n"	\
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"	\
+			"	ll	%1, 0(%4) # atomic_" #op "_return\n"	\
 			"	" #asm_op " %0, %1, %3			\n"	\
-			"	sc	%0, %2				\n"	\
+			"	sc	%0, 0(%4)			\n"	\
 			"	.set	mips0				\n"	\
 			: "=&r" (result), "=&r" (temp), "+m" (v->counter)	\
-			: "Ir" (i));						\
+			: "Ir" (i), "r" (&v->counter));				\
 		} while (unlikely(!result));					\
 										\
 		result = temp; result c_op i;					\
@@ -174,11 +174,11 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
 		int temp;
 
 		__asm__ __volatile__(
-		"	.set	arch=r4000				\n"
-		"1:	ll	%1, %2		# atomic_sub_if_positive\n"
+		"	.set	"MIPS_ISA_ARCH_LEVEL"			\n"
+		"1:	ll	%1, 0(%4)	# atomic_sub_if_positive\n"
 		"	subu	%0, %1, %3				\n"
 		"	bltz	%0, 1f					\n"
-		"	sc	%0, %2					\n"
+		"	sc	%0, 0(%4)				\n"
 		"	.set	noreorder				\n"
 		"	beqz	%0, 1b					\n"
 		"	 subu	%0, %1, %3				\n"
@@ -186,7 +186,7 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
 		"1:							\n"
 		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp), "+m" (v->counter)
-		: "Ir" (i));
+		: "Ir" (i), "r" (&v->counter));
 	} else {
 		unsigned long flags;
 
@@ -335,13 +335,13 @@ static __inline__ void atomic64_##op(long i, atomic64_t * v)			\
 										\
 		do {								\
 			__asm__ __volatile__(					\
-			"	.set	arch=r4000			\n"	\
-			"	lld	%0, %1		# atomic64_" #op "\n"	\
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"	\
+			"	lld	%0, 0(%3)     # atomic64_" #op "\n"	\
 			"	" #asm_op " %0, %2			\n"	\
-			"	scd	%0, %1				\n"	\
+			"	scd	%0, 0(%3)			\n"	\
 			"	.set	mips0				\n"	\
 			: "=&r" (temp), "+m" (v->counter)			\
-			: "Ir" (i));						\
+			: "Ir" (i), "r" (&v->counter));				\
 		} while (unlikely(!temp));					\
 	} else {								\
 		unsigned long flags;						\
@@ -377,13 +377,13 @@ static __inline__ long atomic64_##op##_return(long i, atomic64_t * v)		\
 										\
 		do {								\
 			__asm__ __volatile__(					\
-			"	.set	arch=r4000			\n"	\
-			"	lld	%1, %2	# atomic64_" #op "_return\n"	\
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"	\
+			"	lld	%1, 0(%4)# atomic64_" #op "_return\n"	\
 			"	" #asm_op " %0, %1, %3			\n"	\
-			"	scd	%0, %2				\n"	\
+			"	scd	%0, 0(%4)			\n"	\
 			"	.set	mips0				\n"	\
-			: "=&r" (result), "=&r" (temp), "=m" (v->counter)	\
-			: "Ir" (i), "m" (v->counter)				\
+			: "=&r" (result), "=&r" (temp), "+m" (v->counter)	\
+			: "Ir" (i), "r" (&v->counter)				\
 			: "memory");						\
 		} while (unlikely(!result));					\
 										\
@@ -450,11 +450,11 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
 		long temp;
 
 		__asm__ __volatile__(
-		"	.set	arch=r4000				\n"
-		"1:	lld	%1, %2		# atomic64_sub_if_positive\n"
+		"	.set	"MIPS_ISA_ARCH_LEVEL"			\n"
+		"1:	lld	%1, 0(%4)	# atomic64_sub_if_positive\n"
 		"	dsubu	%0, %1, %3				\n"
 		"	bltz	%0, 1f					\n"
-		"	scd	%0, %2					\n"
+		"	scd	%0, 0(%4)				\n"
 		"	.set	noreorder				\n"
 		"	beqz	%0, 1b					\n"
 		"	 dsubu	%0, %1, %3				\n"
@@ -462,7 +462,7 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
 		"1:							\n"
 		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp), "+m" (v->counter)
-		: "Ir" (i));
+		: "Ir" (i), "r"(&v->counter));
 	} else {
 		unsigned long flags;
 
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 19/67] MIPS: asm: atomic: Update asm and ISA constrains for MIPS R6 support
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Matthew Fortune

MIPS R6 changed the opcodes for LL/SC instructions and reduced the
offset field to 9-bits. This has some undesired effects with the "m"
constrain since it implies a 16-bit immediate. As a result of which,
add a register ("r") constrain as well to make sure the entire address
is loaded to a register before the LL/SC operations. Also use macro
to set the appropriate ISA for the asm blocks

Cc: Matthew Fortune <Matthew.Fortune@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/atomic.h | 50 +++++++++++++++++++++---------------------
 1 file changed, 25 insertions(+), 25 deletions(-)

diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h
index 6dd6bfc607e9..8669e0ec97e3 100644
--- a/arch/mips/include/asm/atomic.h
+++ b/arch/mips/include/asm/atomic.h
@@ -60,13 +60,13 @@ static __inline__ void atomic_##op(int i, atomic_t * v)				\
 										\
 		do {								\
 			__asm__ __volatile__(					\
-			"	.set	arch=r4000			\n"	\
-			"	ll	%0, %1		# atomic_" #op "\n"	\
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"	\
+			"	ll	%0, 0(%3)	# atomic_" #op "\n"	\
 			"	" #asm_op " %0, %2			\n"	\
-			"	sc	%0, %1				\n"	\
+			"	sc	%0, 0(%3)			\n"	\
 			"	.set	mips0				\n"	\
 			: "=&r" (temp), "+m" (v->counter)			\
-			: "Ir" (i));						\
+			: "Ir" (i), "r" (&v->counter));				\
 		} while (unlikely(!temp));					\
 	} else {								\
 		unsigned long flags;						\
@@ -102,13 +102,13 @@ static __inline__ int atomic_##op##_return(int i, atomic_t * v)			\
 										\
 		do {								\
 			__asm__ __volatile__(					\
-			"	.set	arch=r4000			\n"	\
-			"	ll	%1, %2	# atomic_" #op "_return	\n"	\
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"	\
+			"	ll	%1, 0(%4) # atomic_" #op "_return\n"	\
 			"	" #asm_op " %0, %1, %3			\n"	\
-			"	sc	%0, %2				\n"	\
+			"	sc	%0, 0(%4)			\n"	\
 			"	.set	mips0				\n"	\
 			: "=&r" (result), "=&r" (temp), "+m" (v->counter)	\
-			: "Ir" (i));						\
+			: "Ir" (i), "r" (&v->counter));				\
 		} while (unlikely(!result));					\
 										\
 		result = temp; result c_op i;					\
@@ -174,11 +174,11 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
 		int temp;
 
 		__asm__ __volatile__(
-		"	.set	arch=r4000				\n"
-		"1:	ll	%1, %2		# atomic_sub_if_positive\n"
+		"	.set	"MIPS_ISA_ARCH_LEVEL"			\n"
+		"1:	ll	%1, 0(%4)	# atomic_sub_if_positive\n"
 		"	subu	%0, %1, %3				\n"
 		"	bltz	%0, 1f					\n"
-		"	sc	%0, %2					\n"
+		"	sc	%0, 0(%4)				\n"
 		"	.set	noreorder				\n"
 		"	beqz	%0, 1b					\n"
 		"	 subu	%0, %1, %3				\n"
@@ -186,7 +186,7 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
 		"1:							\n"
 		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp), "+m" (v->counter)
-		: "Ir" (i));
+		: "Ir" (i), "r" (&v->counter));
 	} else {
 		unsigned long flags;
 
@@ -335,13 +335,13 @@ static __inline__ void atomic64_##op(long i, atomic64_t * v)			\
 										\
 		do {								\
 			__asm__ __volatile__(					\
-			"	.set	arch=r4000			\n"	\
-			"	lld	%0, %1		# atomic64_" #op "\n"	\
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"	\
+			"	lld	%0, 0(%3)     # atomic64_" #op "\n"	\
 			"	" #asm_op " %0, %2			\n"	\
-			"	scd	%0, %1				\n"	\
+			"	scd	%0, 0(%3)			\n"	\
 			"	.set	mips0				\n"	\
 			: "=&r" (temp), "+m" (v->counter)			\
-			: "Ir" (i));						\
+			: "Ir" (i), "r" (&v->counter));				\
 		} while (unlikely(!temp));					\
 	} else {								\
 		unsigned long flags;						\
@@ -377,13 +377,13 @@ static __inline__ long atomic64_##op##_return(long i, atomic64_t * v)		\
 										\
 		do {								\
 			__asm__ __volatile__(					\
-			"	.set	arch=r4000			\n"	\
-			"	lld	%1, %2	# atomic64_" #op "_return\n"	\
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"	\
+			"	lld	%1, 0(%4)# atomic64_" #op "_return\n"	\
 			"	" #asm_op " %0, %1, %3			\n"	\
-			"	scd	%0, %2				\n"	\
+			"	scd	%0, 0(%4)			\n"	\
 			"	.set	mips0				\n"	\
-			: "=&r" (result), "=&r" (temp), "=m" (v->counter)	\
-			: "Ir" (i), "m" (v->counter)				\
+			: "=&r" (result), "=&r" (temp), "+m" (v->counter)	\
+			: "Ir" (i), "r" (&v->counter)				\
 			: "memory");						\
 		} while (unlikely(!result));					\
 										\
@@ -450,11 +450,11 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
 		long temp;
 
 		__asm__ __volatile__(
-		"	.set	arch=r4000				\n"
-		"1:	lld	%1, %2		# atomic64_sub_if_positive\n"
+		"	.set	"MIPS_ISA_ARCH_LEVEL"			\n"
+		"1:	lld	%1, 0(%4)	# atomic64_sub_if_positive\n"
 		"	dsubu	%0, %1, %3				\n"
 		"	bltz	%0, 1f					\n"
-		"	scd	%0, %2					\n"
+		"	scd	%0, 0(%4)				\n"
 		"	.set	noreorder				\n"
 		"	beqz	%0, 1b					\n"
 		"	 dsubu	%0, %1, %3				\n"
@@ -462,7 +462,7 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
 		"1:							\n"
 		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp), "+m" (v->counter)
-		: "Ir" (i));
+		: "Ir" (i), "r"(&v->counter));
 	} else {
 		unsigned long flags;
 
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 20/67] MIPS: asm: cmpxchg: Update asm and ISA constrains for MIPS R6 support
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Matthew Fortune

MIPS R6 changed the opcodes for LL/SC instructions and reduced the
offset field to 9-bits. This has some undesired effects with the "m"
constrain since it implies a 16-bit immediate. As a result of which,
add a register ("r") constrain as well to make sure the entire address
is loaded to a register before the LL/SC operations. Also use macro
to set the appropriate ISA for the asm blocks

Cc: Matthew Fortune <Matthew.Fortune@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/cmpxchg.h | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/arch/mips/include/asm/cmpxchg.h b/arch/mips/include/asm/cmpxchg.h
index eefcaa363a87..86a76f125bc8 100644
--- a/arch/mips/include/asm/cmpxchg.h
+++ b/arch/mips/include/asm/cmpxchg.h
@@ -38,15 +38,15 @@ static inline unsigned long __xchg_u32(volatile int * m, unsigned int val)
 
 		do {
 			__asm__ __volatile__(
-			"	.set	arch=r4000			\n"
-			"	ll	%0, %3		# xchg_u32	\n"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
+			"	ll	%0, 0(%3)	# xchg_u32	\n"
 			"	.set	mips0				\n"
 			"	move	%2, %z4				\n"
-			"	.set	arch=r4000			\n"
-			"	sc	%2, %1				\n"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
+			"	sc	%2, 0(%3)			\n"
 			"	.set	mips0				\n"
 			: "=&r" (retval), "=m" (*m), "=&r" (dummy)
-			: "R" (*m), "Jr" (val)
+			: "r" (m), "Jr" (val)
 			: "memory");
 		} while (unlikely(!dummy));
 	} else {
@@ -88,13 +88,13 @@ static inline __u64 __xchg_u64(volatile __u64 * m, __u64 val)
 
 		do {
 			__asm__ __volatile__(
-			"	.set	arch=r4000			\n"
-			"	lld	%0, %3		# xchg_u64	\n"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
+			"	lld	%0, 0(%3)	# xchg_u64	\n"
 			"	move	%2, %z4				\n"
-			"	scd	%2, %1				\n"
+			"	scd	%2, 0(%3)			\n"
 			"	.set	mips0				\n"
 			: "=&r" (retval), "=m" (*m), "=&r" (dummy)
-			: "R" (*m), "Jr" (val)
+			: "r" (m), "Jr" (val)
 			: "memory");
 		} while (unlikely(!dummy));
 	} else {
@@ -162,18 +162,18 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
 		__asm__ __volatile__(					\
 		"	.set	push				\n"	\
 		"	.set	noat				\n"	\
-		"	.set	arch=r4000			\n"	\
-		"1:	" ld "	%0, %2		# __cmpxchg_asm \n"	\
+		"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"	\
+		"1:	" ld "	%0, 0(%2)	# __cmpxchg_asm \n"	\
 		"	bne	%0, %z3, 2f			\n"	\
 		"	.set	mips0				\n"	\
 		"	move	$1, %z4				\n"	\
-		"	.set	arch=r4000			\n"	\
-		"	" st "	$1, %1				\n"	\
+		"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"	\
+		"	" st "	$1, 0(%2)			\n"	\
 		"	beqz	$1, 1b				\n"	\
 		"	.set	pop				\n"	\
 		"2:						\n"	\
 		: "=&r" (__ret), "=R" (*m)				\
-		: "R" (*m), "Jr" (old), "Jr" (new)			\
+		: "r" (m), "Jr" (old), "Jr" (new)			\
 		: "memory");						\
 	} else {							\
 		unsigned long __flags;					\
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 20/67] MIPS: asm: cmpxchg: Update asm and ISA constrains for MIPS R6 support
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Matthew Fortune

MIPS R6 changed the opcodes for LL/SC instructions and reduced the
offset field to 9-bits. This has some undesired effects with the "m"
constrain since it implies a 16-bit immediate. As a result of which,
add a register ("r") constrain as well to make sure the entire address
is loaded to a register before the LL/SC operations. Also use macro
to set the appropriate ISA for the asm blocks

Cc: Matthew Fortune <Matthew.Fortune@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/cmpxchg.h | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/arch/mips/include/asm/cmpxchg.h b/arch/mips/include/asm/cmpxchg.h
index eefcaa363a87..86a76f125bc8 100644
--- a/arch/mips/include/asm/cmpxchg.h
+++ b/arch/mips/include/asm/cmpxchg.h
@@ -38,15 +38,15 @@ static inline unsigned long __xchg_u32(volatile int * m, unsigned int val)
 
 		do {
 			__asm__ __volatile__(
-			"	.set	arch=r4000			\n"
-			"	ll	%0, %3		# xchg_u32	\n"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
+			"	ll	%0, 0(%3)	# xchg_u32	\n"
 			"	.set	mips0				\n"
 			"	move	%2, %z4				\n"
-			"	.set	arch=r4000			\n"
-			"	sc	%2, %1				\n"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
+			"	sc	%2, 0(%3)			\n"
 			"	.set	mips0				\n"
 			: "=&r" (retval), "=m" (*m), "=&r" (dummy)
-			: "R" (*m), "Jr" (val)
+			: "r" (m), "Jr" (val)
 			: "memory");
 		} while (unlikely(!dummy));
 	} else {
@@ -88,13 +88,13 @@ static inline __u64 __xchg_u64(volatile __u64 * m, __u64 val)
 
 		do {
 			__asm__ __volatile__(
-			"	.set	arch=r4000			\n"
-			"	lld	%0, %3		# xchg_u64	\n"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
+			"	lld	%0, 0(%3)	# xchg_u64	\n"
 			"	move	%2, %z4				\n"
-			"	scd	%2, %1				\n"
+			"	scd	%2, 0(%3)			\n"
 			"	.set	mips0				\n"
 			: "=&r" (retval), "=m" (*m), "=&r" (dummy)
-			: "R" (*m), "Jr" (val)
+			: "r" (m), "Jr" (val)
 			: "memory");
 		} while (unlikely(!dummy));
 	} else {
@@ -162,18 +162,18 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
 		__asm__ __volatile__(					\
 		"	.set	push				\n"	\
 		"	.set	noat				\n"	\
-		"	.set	arch=r4000			\n"	\
-		"1:	" ld "	%0, %2		# __cmpxchg_asm \n"	\
+		"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"	\
+		"1:	" ld "	%0, 0(%2)	# __cmpxchg_asm \n"	\
 		"	bne	%0, %z3, 2f			\n"	\
 		"	.set	mips0				\n"	\
 		"	move	$1, %z4				\n"	\
-		"	.set	arch=r4000			\n"	\
-		"	" st "	$1, %1				\n"	\
+		"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"	\
+		"	" st "	$1, 0(%2)			\n"	\
 		"	beqz	$1, 1b				\n"	\
 		"	.set	pop				\n"	\
 		"2:						\n"	\
 		: "=&r" (__ret), "=R" (*m)				\
-		: "R" (*m), "Jr" (old), "Jr" (new)			\
+		: "r" (m), "Jr" (old), "Jr" (new)			\
 		: "memory");						\
 	} else {							\
 		unsigned long __flags;					\
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 21/67] MIPS: asm: bitops: Update asm and ISA constrains for MIPS R6 support
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Matthew Fortune

MIPS R6 changed the opcodes for LL/SC instructions and reduced the
offset field to 9-bits. This has some undesired effects with the "m"
constrain since it implies a 16-bit immediate. As a result of which,
add a register ("r") constrain as well to make sure the entire address
is loaded to a register before the LL/SC operations. Also use macro
to set the appropriate ISA for the asm blocks

Cc: Matthew Fortune <Matthew.Fortune@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/bitops.h | 91 +++++++++++++++++++++---------------------
 1 file changed, 46 insertions(+), 45 deletions(-)

diff --git a/arch/mips/include/asm/bitops.h b/arch/mips/include/asm/bitops.h
index bae6b0fa8ab5..7036a228b6cb 100644
--- a/arch/mips/include/asm/bitops.h
+++ b/arch/mips/include/asm/bitops.h
@@ -15,6 +15,7 @@
 
 #include <linux/compiler.h>
 #include <linux/types.h>
+#include <asm/asm.h>
 #include <asm/barrier.h>
 #include <asm/byteorder.h>		/* sigh ... */
 #include <asm/cpu-features.h>
@@ -80,27 +81,27 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
 		"	.set	mips0					\n"
 		: "=&r" (temp), "=m" (*m)
 		: "ir" (1UL << bit), "m" (*m));
-#ifdef CONFIG_CPU_MIPSR2
+#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
 	} else if (kernel_uses_llsc && __builtin_constant_p(bit)) {
 		do {
 			__asm__ __volatile__(
-			"	" __LL "%0, %1		# set_bit	\n"
+			"	" __LL "%0, 0(%4)	# set_bit	\n"
 			"	" __INS "%0, %3, %2, 1			\n"
-			"	" __SC "%0, %1				\n"
+			"	" __SC "%0, 0(%4)			\n"
 			: "=&r" (temp), "+m" (*m)
-			: "ir" (bit), "r" (~0));
+			: "ir" (bit), "r" (~0), "r" (m));
 		} while (unlikely(!temp));
-#endif /* CONFIG_CPU_MIPSR2 */
+#endif /* CONFIG_CPU_MIPSR2 || CONFIG_CPU_MIPSR6 */
 	} else if (kernel_uses_llsc) {
 		do {
 			__asm__ __volatile__(
-			"	.set	arch=r4000			\n"
-			"	" __LL "%0, %1		# set_bit	\n"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
+			"	" __LL "%0, 0(%3)	# set_bit	\n"
 			"	or	%0, %2				\n"
-			"	" __SC	"%0, %1				\n"
+			"	" __SC	"%0, 0(%3)			\n"
 			"	.set	mips0				\n"
 			: "=&r" (temp), "+m" (*m)
-			: "ir" (1UL << bit));
+			: "ir" (1UL << bit), "r" (m));
 		} while (unlikely(!temp));
 	} else
 		__mips_set_bit(nr, addr);
@@ -132,27 +133,27 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
 		"	.set	mips0					\n"
 		: "=&r" (temp), "+m" (*m)
 		: "ir" (~(1UL << bit)));
-#ifdef CONFIG_CPU_MIPSR2
+#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
 	} else if (kernel_uses_llsc && __builtin_constant_p(bit)) {
 		do {
 			__asm__ __volatile__(
-			"	" __LL "%0, %1		# clear_bit	\n"
+			"	" __LL "%0, 0(%3)	# clear_bit	\n"
 			"	" __INS "%0, $0, %2, 1			\n"
-			"	" __SC "%0, %1				\n"
+			"	" __SC "%0, 0(%3)			\n"
 			: "=&r" (temp), "+m" (*m)
-			: "ir" (bit));
+			: "ir" (bit), "r" (m));
 		} while (unlikely(!temp));
-#endif /* CONFIG_CPU_MIPSR2 */
+#endif /* CONFIG_CPU_MIPSR2 || CONFIG_CPU_MIPSR6 */
 	} else if (kernel_uses_llsc) {
 		do {
 			__asm__ __volatile__(
-			"	.set	arch=r4000			\n"
-			"	" __LL "%0, %1		# clear_bit	\n"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
+			"	" __LL "%0, 0(%3)	# clear_bit	\n"
 			"	and	%0, %2				\n"
-			"	" __SC "%0, %1				\n"
+			"	" __SC "%0, 0(%3)			\n"
 			"	.set	mips0				\n"
 			: "=&r" (temp), "+m" (*m)
-			: "ir" (~(1UL << bit)));
+			: "ir" (~(1UL << bit)), "r" (m));
 		} while (unlikely(!temp));
 	} else
 		__mips_clear_bit(nr, addr);
@@ -204,13 +205,13 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
 
 		do {
 			__asm__ __volatile__(
-			"	.set	arch=r4000			\n"
-			"	" __LL "%0, %1		# change_bit	\n"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
+			"	" __LL "%0, 0(%3)	# change_bit	\n"
 			"	xor	%0, %2				\n"
-			"	" __SC	"%0, %1				\n"
+			"	" __SC	"%0, 0(%3)			\n"
 			"	.set	mips0				\n"
 			: "=&r" (temp), "+m" (*m)
-			: "ir" (1UL << bit));
+			: "ir" (1UL << bit), "r" (m));
 		} while (unlikely(!temp));
 	} else
 		__mips_change_bit(nr, addr);
@@ -253,13 +254,13 @@ static inline int test_and_set_bit(unsigned long nr,
 
 		do {
 			__asm__ __volatile__(
-			"	.set	arch=r4000			\n"
-			"	" __LL "%0, %1	# test_and_set_bit	\n"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
+			"	" __LL "%0, 0(%4)# test_and_set_bit	\n"
 			"	or	%2, %0, %3			\n"
-			"	" __SC	"%2, %1				\n"
+			"	" __SC	"%2, 0(%4)			\n"
 			"	.set	mips0				\n"
 			: "=&r" (temp), "+m" (*m), "=&r" (res)
-			: "r" (1UL << bit)
+			: "r" (1UL << bit), "r" (m)
 			: "memory");
 		} while (unlikely(!res));
 
@@ -307,13 +308,13 @@ static inline int test_and_set_bit_lock(unsigned long nr,
 
 		do {
 			__asm__ __volatile__(
-			"	.set	arch=r4000			\n"
-			"	" __LL "%0, %1	# test_and_set_bit	\n"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
+			"	" __LL "%0, 0(%4)# test_and_set_bit	\n"
 			"	or	%2, %0, %3			\n"
-			"	" __SC	"%2, %1				\n"
+			"	" __SC	"%2, 0(%4)			\n"
 			"	.set	mips0				\n"
 			: "=&r" (temp), "+m" (*m), "=&r" (res)
-			: "r" (1UL << bit)
+			: "r" (1UL << bit), "r" (m)
 			: "memory");
 		} while (unlikely(!res));
 
@@ -357,19 +358,19 @@ static inline int test_and_clear_bit(unsigned long nr,
 		: "=&r" (temp), "+m" (*m), "=&r" (res)
 		: "r" (1UL << bit)
 		: "memory");
-#ifdef CONFIG_CPU_MIPSR2
+#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
 	} else if (kernel_uses_llsc && __builtin_constant_p(nr)) {
 		unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
 		unsigned long temp;
 
 		do {
 			__asm__ __volatile__(
-			"	" __LL	"%0, %1 # test_and_clear_bit	\n"
+			"	" __LL	"%0, 0(%4)# test_and_clear_bit	\n"
 			"	" __EXT "%2, %0, %3, 1			\n"
 			"	" __INS "%0, $0, %3, 1			\n"
-			"	" __SC	"%0, %1				\n"
+			"	" __SC	"%0, 0(%4)			\n"
 			: "=&r" (temp), "+m" (*m), "=&r" (res)
-			: "ir" (bit)
+			: "ir" (bit), "r" (m)
 			: "memory");
 		} while (unlikely(!temp));
 #endif
@@ -379,14 +380,14 @@ static inline int test_and_clear_bit(unsigned long nr,
 
 		do {
 			__asm__ __volatile__(
-			"	.set	arch=r4000			\n"
-			"	" __LL	"%0, %1 # test_and_clear_bit	\n"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
+			"	" __LL	"%0, 0(%4) # test_and_clear_bit	\n"
 			"	or	%2, %0, %3			\n"
 			"	xor	%2, %3				\n"
-			"	" __SC	"%2, %1				\n"
+			"	" __SC	"%2, 0(%4)			\n"
 			"	.set	mips0				\n"
 			: "=&r" (temp), "+m" (*m), "=&r" (res)
-			: "r" (1UL << bit)
+			: "r" (1UL << bit), "r" (m)
 			: "memory");
 		} while (unlikely(!res));
 
@@ -436,13 +437,13 @@ static inline int test_and_change_bit(unsigned long nr,
 
 		do {
 			__asm__ __volatile__(
-			"	.set	arch=r4000			\n"
-			"	" __LL	"%0, %1 # test_and_change_bit	\n"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
+			"	" __LL	"%0, 0(%4)# test_and_change_bit	\n"
 			"	xor	%2, %0, %3			\n"
-			"	" __SC	"\t%2, %1			\n"
+			"	" __SC	"%2, 0(%4)			\n"
 			"	.set	mips0				\n"
 			: "=&r" (temp), "+m" (*m), "=&r" (res)
-			: "r" (1UL << bit)
+			: "r" (1UL << bit), "r" (m)
 			: "memory");
 		} while (unlikely(!res));
 
@@ -484,7 +485,7 @@ static inline unsigned long __fls(unsigned long word)
 	    __builtin_constant_p(cpu_has_clo_clz) && cpu_has_clo_clz) {
 		__asm__(
 		"	.set	push					\n"
-		"	.set	mips32					\n"
+		"	.set	"MIPS_ISA_LEVEL"			\n"
 		"	clz	%0, %1					\n"
 		"	.set	pop					\n"
 		: "=r" (num)
@@ -497,7 +498,7 @@ static inline unsigned long __fls(unsigned long word)
 	    __builtin_constant_p(cpu_has_mips64) && cpu_has_mips64) {
 		__asm__(
 		"	.set	push					\n"
-		"	.set	mips64					\n"
+		"	.set	"MIPS_ISA_LEVEL"			\n"
 		"	dclz	%0, %1					\n"
 		"	.set	pop					\n"
 		: "=r" (num)
@@ -561,7 +562,7 @@ static inline int fls(int x)
 	if (__builtin_constant_p(cpu_has_clo_clz) && cpu_has_clo_clz) {
 		__asm__(
 		"	.set	push					\n"
-		"	.set	mips32					\n"
+		"	.set	"MIPS_ISA_LEVEL"			\n"
 		"	clz	%0, %1					\n"
 		"	.set	pop					\n"
 		: "=r" (x)
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 21/67] MIPS: asm: bitops: Update asm and ISA constrains for MIPS R6 support
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Matthew Fortune

MIPS R6 changed the opcodes for LL/SC instructions and reduced the
offset field to 9-bits. This has some undesired effects with the "m"
constrain since it implies a 16-bit immediate. As a result of which,
add a register ("r") constrain as well to make sure the entire address
is loaded to a register before the LL/SC operations. Also use macro
to set the appropriate ISA for the asm blocks

Cc: Matthew Fortune <Matthew.Fortune@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/bitops.h | 91 +++++++++++++++++++++---------------------
 1 file changed, 46 insertions(+), 45 deletions(-)

diff --git a/arch/mips/include/asm/bitops.h b/arch/mips/include/asm/bitops.h
index bae6b0fa8ab5..7036a228b6cb 100644
--- a/arch/mips/include/asm/bitops.h
+++ b/arch/mips/include/asm/bitops.h
@@ -15,6 +15,7 @@
 
 #include <linux/compiler.h>
 #include <linux/types.h>
+#include <asm/asm.h>
 #include <asm/barrier.h>
 #include <asm/byteorder.h>		/* sigh ... */
 #include <asm/cpu-features.h>
@@ -80,27 +81,27 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
 		"	.set	mips0					\n"
 		: "=&r" (temp), "=m" (*m)
 		: "ir" (1UL << bit), "m" (*m));
-#ifdef CONFIG_CPU_MIPSR2
+#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
 	} else if (kernel_uses_llsc && __builtin_constant_p(bit)) {
 		do {
 			__asm__ __volatile__(
-			"	" __LL "%0, %1		# set_bit	\n"
+			"	" __LL "%0, 0(%4)	# set_bit	\n"
 			"	" __INS "%0, %3, %2, 1			\n"
-			"	" __SC "%0, %1				\n"
+			"	" __SC "%0, 0(%4)			\n"
 			: "=&r" (temp), "+m" (*m)
-			: "ir" (bit), "r" (~0));
+			: "ir" (bit), "r" (~0), "r" (m));
 		} while (unlikely(!temp));
-#endif /* CONFIG_CPU_MIPSR2 */
+#endif /* CONFIG_CPU_MIPSR2 || CONFIG_CPU_MIPSR6 */
 	} else if (kernel_uses_llsc) {
 		do {
 			__asm__ __volatile__(
-			"	.set	arch=r4000			\n"
-			"	" __LL "%0, %1		# set_bit	\n"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
+			"	" __LL "%0, 0(%3)	# set_bit	\n"
 			"	or	%0, %2				\n"
-			"	" __SC	"%0, %1				\n"
+			"	" __SC	"%0, 0(%3)			\n"
 			"	.set	mips0				\n"
 			: "=&r" (temp), "+m" (*m)
-			: "ir" (1UL << bit));
+			: "ir" (1UL << bit), "r" (m));
 		} while (unlikely(!temp));
 	} else
 		__mips_set_bit(nr, addr);
@@ -132,27 +133,27 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
 		"	.set	mips0					\n"
 		: "=&r" (temp), "+m" (*m)
 		: "ir" (~(1UL << bit)));
-#ifdef CONFIG_CPU_MIPSR2
+#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
 	} else if (kernel_uses_llsc && __builtin_constant_p(bit)) {
 		do {
 			__asm__ __volatile__(
-			"	" __LL "%0, %1		# clear_bit	\n"
+			"	" __LL "%0, 0(%3)	# clear_bit	\n"
 			"	" __INS "%0, $0, %2, 1			\n"
-			"	" __SC "%0, %1				\n"
+			"	" __SC "%0, 0(%3)			\n"
 			: "=&r" (temp), "+m" (*m)
-			: "ir" (bit));
+			: "ir" (bit), "r" (m));
 		} while (unlikely(!temp));
-#endif /* CONFIG_CPU_MIPSR2 */
+#endif /* CONFIG_CPU_MIPSR2 || CONFIG_CPU_MIPSR6 */
 	} else if (kernel_uses_llsc) {
 		do {
 			__asm__ __volatile__(
-			"	.set	arch=r4000			\n"
-			"	" __LL "%0, %1		# clear_bit	\n"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
+			"	" __LL "%0, 0(%3)	# clear_bit	\n"
 			"	and	%0, %2				\n"
-			"	" __SC "%0, %1				\n"
+			"	" __SC "%0, 0(%3)			\n"
 			"	.set	mips0				\n"
 			: "=&r" (temp), "+m" (*m)
-			: "ir" (~(1UL << bit)));
+			: "ir" (~(1UL << bit)), "r" (m));
 		} while (unlikely(!temp));
 	} else
 		__mips_clear_bit(nr, addr);
@@ -204,13 +205,13 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
 
 		do {
 			__asm__ __volatile__(
-			"	.set	arch=r4000			\n"
-			"	" __LL "%0, %1		# change_bit	\n"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
+			"	" __LL "%0, 0(%3)	# change_bit	\n"
 			"	xor	%0, %2				\n"
-			"	" __SC	"%0, %1				\n"
+			"	" __SC	"%0, 0(%3)			\n"
 			"	.set	mips0				\n"
 			: "=&r" (temp), "+m" (*m)
-			: "ir" (1UL << bit));
+			: "ir" (1UL << bit), "r" (m));
 		} while (unlikely(!temp));
 	} else
 		__mips_change_bit(nr, addr);
@@ -253,13 +254,13 @@ static inline int test_and_set_bit(unsigned long nr,
 
 		do {
 			__asm__ __volatile__(
-			"	.set	arch=r4000			\n"
-			"	" __LL "%0, %1	# test_and_set_bit	\n"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
+			"	" __LL "%0, 0(%4)# test_and_set_bit	\n"
 			"	or	%2, %0, %3			\n"
-			"	" __SC	"%2, %1				\n"
+			"	" __SC	"%2, 0(%4)			\n"
 			"	.set	mips0				\n"
 			: "=&r" (temp), "+m" (*m), "=&r" (res)
-			: "r" (1UL << bit)
+			: "r" (1UL << bit), "r" (m)
 			: "memory");
 		} while (unlikely(!res));
 
@@ -307,13 +308,13 @@ static inline int test_and_set_bit_lock(unsigned long nr,
 
 		do {
 			__asm__ __volatile__(
-			"	.set	arch=r4000			\n"
-			"	" __LL "%0, %1	# test_and_set_bit	\n"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
+			"	" __LL "%0, 0(%4)# test_and_set_bit	\n"
 			"	or	%2, %0, %3			\n"
-			"	" __SC	"%2, %1				\n"
+			"	" __SC	"%2, 0(%4)			\n"
 			"	.set	mips0				\n"
 			: "=&r" (temp), "+m" (*m), "=&r" (res)
-			: "r" (1UL << bit)
+			: "r" (1UL << bit), "r" (m)
 			: "memory");
 		} while (unlikely(!res));
 
@@ -357,19 +358,19 @@ static inline int test_and_clear_bit(unsigned long nr,
 		: "=&r" (temp), "+m" (*m), "=&r" (res)
 		: "r" (1UL << bit)
 		: "memory");
-#ifdef CONFIG_CPU_MIPSR2
+#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
 	} else if (kernel_uses_llsc && __builtin_constant_p(nr)) {
 		unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
 		unsigned long temp;
 
 		do {
 			__asm__ __volatile__(
-			"	" __LL	"%0, %1 # test_and_clear_bit	\n"
+			"	" __LL	"%0, 0(%4)# test_and_clear_bit	\n"
 			"	" __EXT "%2, %0, %3, 1			\n"
 			"	" __INS "%0, $0, %3, 1			\n"
-			"	" __SC	"%0, %1				\n"
+			"	" __SC	"%0, 0(%4)			\n"
 			: "=&r" (temp), "+m" (*m), "=&r" (res)
-			: "ir" (bit)
+			: "ir" (bit), "r" (m)
 			: "memory");
 		} while (unlikely(!temp));
 #endif
@@ -379,14 +380,14 @@ static inline int test_and_clear_bit(unsigned long nr,
 
 		do {
 			__asm__ __volatile__(
-			"	.set	arch=r4000			\n"
-			"	" __LL	"%0, %1 # test_and_clear_bit	\n"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
+			"	" __LL	"%0, 0(%4) # test_and_clear_bit	\n"
 			"	or	%2, %0, %3			\n"
 			"	xor	%2, %3				\n"
-			"	" __SC	"%2, %1				\n"
+			"	" __SC	"%2, 0(%4)			\n"
 			"	.set	mips0				\n"
 			: "=&r" (temp), "+m" (*m), "=&r" (res)
-			: "r" (1UL << bit)
+			: "r" (1UL << bit), "r" (m)
 			: "memory");
 		} while (unlikely(!res));
 
@@ -436,13 +437,13 @@ static inline int test_and_change_bit(unsigned long nr,
 
 		do {
 			__asm__ __volatile__(
-			"	.set	arch=r4000			\n"
-			"	" __LL	"%0, %1 # test_and_change_bit	\n"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
+			"	" __LL	"%0, 0(%4)# test_and_change_bit	\n"
 			"	xor	%2, %0, %3			\n"
-			"	" __SC	"\t%2, %1			\n"
+			"	" __SC	"%2, 0(%4)			\n"
 			"	.set	mips0				\n"
 			: "=&r" (temp), "+m" (*m), "=&r" (res)
-			: "r" (1UL << bit)
+			: "r" (1UL << bit), "r" (m)
 			: "memory");
 		} while (unlikely(!res));
 
@@ -484,7 +485,7 @@ static inline unsigned long __fls(unsigned long word)
 	    __builtin_constant_p(cpu_has_clo_clz) && cpu_has_clo_clz) {
 		__asm__(
 		"	.set	push					\n"
-		"	.set	mips32					\n"
+		"	.set	"MIPS_ISA_LEVEL"			\n"
 		"	clz	%0, %1					\n"
 		"	.set	pop					\n"
 		: "=r" (num)
@@ -497,7 +498,7 @@ static inline unsigned long __fls(unsigned long word)
 	    __builtin_constant_p(cpu_has_mips64) && cpu_has_mips64) {
 		__asm__(
 		"	.set	push					\n"
-		"	.set	mips64					\n"
+		"	.set	"MIPS_ISA_LEVEL"			\n"
 		"	dclz	%0, %1					\n"
 		"	.set	pop					\n"
 		: "=r" (num)
@@ -561,7 +562,7 @@ static inline int fls(int x)
 	if (__builtin_constant_p(cpu_has_clo_clz) && cpu_has_clo_clz) {
 		__asm__(
 		"	.set	push					\n"
-		"	.set	mips32					\n"
+		"	.set	"MIPS_ISA_LEVEL"			\n"
 		"	clz	%0, %1					\n"
 		"	.set	pop					\n"
 		: "=r" (x)
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 22/67] MIPS: asm: futex: Update asm and ISA constrains for MIPS R6 support
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Matthew Fortune

MIPS R6 changed the opcodes for LL/SC instructions and reduced the
offset field to 9-bits. This has some undesired effects with the "m"
constrain since it implies a 16-bit immediate. As a result of which,
add a register ("r") constrain as well to make sure the entire address
is loaded to a register before the LL/SC operations. Also use macro
to set the appropriate ISA for the asm blocks

Cc: Matthew Fortune <Matthew.Fortune@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/futex.h | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/arch/mips/include/asm/futex.h b/arch/mips/include/asm/futex.h
index 194cda0396a3..8867726b85e2 100644
--- a/arch/mips/include/asm/futex.h
+++ b/arch/mips/include/asm/futex.h
@@ -49,12 +49,12 @@
 		__asm__ __volatile__(					\
 		"	.set	push				\n"	\
 		"	.set	noat				\n"	\
-		"	.set	arch=r4000			\n"	\
-		"1:	"user_ll("%1", "%4")" # __futex_atomic_op\n"	\
+		"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"	\
+		"1:	"user_ll("%1", "0(%4)")" # __futex_atomic_op\n"	\
 		"	.set	mips0				\n"	\
 		"	" insn	"				\n"	\
-		"	.set	arch=r4000			\n"	\
-		"2:	"user_sc("$1", "%2")"			\n"	\
+		"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"	\
+		"2:	"user_sc("$1", "0(%4)")"		\n"	\
 		"	beqz	$1, 1b				\n"	\
 		__WEAK_LLSC_MB						\
 		"3:						\n"	\
@@ -68,8 +68,8 @@
 		"	"__UA_ADDR "\t1b, 4b			\n"	\
 		"	"__UA_ADDR "\t2b, 4b			\n"	\
 		"	.previous				\n"	\
-		: "=r" (ret), "=&r" (oldval), "=R" (*uaddr)		\
-		: "0" (0), "R" (*uaddr), "Jr" (oparg), "i" (-EFAULT)	\
+		: "=r" (ret), "=&r" (oldval), "+m" (uaddr)		\
+		: "0" (0), "r" (uaddr), "Jr" (oparg), "i" (-EFAULT)	\
 		: "memory");						\
 	} else								\
 		ret = -ENOSYS;						\
@@ -174,13 +174,13 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
 		"# futex_atomic_cmpxchg_inatomic			\n"
 		"	.set	push					\n"
 		"	.set	noat					\n"
-		"	.set	arch=r4000				\n"
-		"1:	"user_ll("%1", "%3")"				\n"
+		"	.set	"MIPS_ISA_ARCH_LEVEL"			\n"
+		"1:	"user_ll("%1", "0(%3)")"			\n"
 		"	bne	%1, %z4, 3f				\n"
 		"	.set	mips0					\n"
 		"	move	$1, %z5					\n"
-		"	.set	arch=r4000				\n"
-		"2:	"user_sc("$1", "%2")"				\n"
+		"	.set	"MIPS_ISA_ARCH_LEVEL"			\n"
+		"2:	"user_sc("$1", "0(%3)")"			\n"
 		"	beqz	$1, 1b					\n"
 		__WEAK_LLSC_MB
 		"3:							\n"
@@ -193,8 +193,8 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
 		"	"__UA_ADDR "\t1b, 4b				\n"
 		"	"__UA_ADDR "\t2b, 4b				\n"
 		"	.previous					\n"
-		: "+r" (ret), "=&r" (val), "=R" (*uaddr)
-		: "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT)
+		: "+r" (ret), "=&r" (val), "+m" (uaddr)
+		: "r" (uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT)
 		: "memory");
 	} else
 		return -ENOSYS;
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 22/67] MIPS: asm: futex: Update asm and ISA constrains for MIPS R6 support
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Matthew Fortune

MIPS R6 changed the opcodes for LL/SC instructions and reduced the
offset field to 9-bits. This has some undesired effects with the "m"
constrain since it implies a 16-bit immediate. As a result of which,
add a register ("r") constrain as well to make sure the entire address
is loaded to a register before the LL/SC operations. Also use macro
to set the appropriate ISA for the asm blocks

Cc: Matthew Fortune <Matthew.Fortune@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/futex.h | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/arch/mips/include/asm/futex.h b/arch/mips/include/asm/futex.h
index 194cda0396a3..8867726b85e2 100644
--- a/arch/mips/include/asm/futex.h
+++ b/arch/mips/include/asm/futex.h
@@ -49,12 +49,12 @@
 		__asm__ __volatile__(					\
 		"	.set	push				\n"	\
 		"	.set	noat				\n"	\
-		"	.set	arch=r4000			\n"	\
-		"1:	"user_ll("%1", "%4")" # __futex_atomic_op\n"	\
+		"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"	\
+		"1:	"user_ll("%1", "0(%4)")" # __futex_atomic_op\n"	\
 		"	.set	mips0				\n"	\
 		"	" insn	"				\n"	\
-		"	.set	arch=r4000			\n"	\
-		"2:	"user_sc("$1", "%2")"			\n"	\
+		"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"	\
+		"2:	"user_sc("$1", "0(%4)")"		\n"	\
 		"	beqz	$1, 1b				\n"	\
 		__WEAK_LLSC_MB						\
 		"3:						\n"	\
@@ -68,8 +68,8 @@
 		"	"__UA_ADDR "\t1b, 4b			\n"	\
 		"	"__UA_ADDR "\t2b, 4b			\n"	\
 		"	.previous				\n"	\
-		: "=r" (ret), "=&r" (oldval), "=R" (*uaddr)		\
-		: "0" (0), "R" (*uaddr), "Jr" (oparg), "i" (-EFAULT)	\
+		: "=r" (ret), "=&r" (oldval), "+m" (uaddr)		\
+		: "0" (0), "r" (uaddr), "Jr" (oparg), "i" (-EFAULT)	\
 		: "memory");						\
 	} else								\
 		ret = -ENOSYS;						\
@@ -174,13 +174,13 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
 		"# futex_atomic_cmpxchg_inatomic			\n"
 		"	.set	push					\n"
 		"	.set	noat					\n"
-		"	.set	arch=r4000				\n"
-		"1:	"user_ll("%1", "%3")"				\n"
+		"	.set	"MIPS_ISA_ARCH_LEVEL"			\n"
+		"1:	"user_ll("%1", "0(%3)")"			\n"
 		"	bne	%1, %z4, 3f				\n"
 		"	.set	mips0					\n"
 		"	move	$1, %z5					\n"
-		"	.set	arch=r4000				\n"
-		"2:	"user_sc("$1", "%2")"				\n"
+		"	.set	"MIPS_ISA_ARCH_LEVEL"			\n"
+		"2:	"user_sc("$1", "0(%3)")"			\n"
 		"	beqz	$1, 1b					\n"
 		__WEAK_LLSC_MB
 		"3:							\n"
@@ -193,8 +193,8 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
 		"	"__UA_ADDR "\t1b, 4b				\n"
 		"	"__UA_ADDR "\t2b, 4b				\n"
 		"	.previous					\n"
-		: "+r" (ret), "=&r" (val), "=R" (*uaddr)
-		: "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT)
+		: "+r" (ret), "=&r" (val), "+m" (uaddr)
+		: "r" (uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT)
 		: "memory");
 	} else
 		return -ENOSYS;
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 23/67] MIPS: asm: spinlock: Update asm constrains for MIPS R6 support
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Matthew Fortune

MIPS R6 changed the opcodes for LL/SC instructions and reduced the
offset field to 9-bits. This has some undesired effects with the "m"
constrain since it implies a 16-bit immediate. As a result of which,
add a register ("r") constrain as well to make sure the entire address
is loaded to a register before the LL/SC operations.

Cc: Matthew Fortune <Matthew.Fortune@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/spinlock.h | 58 +++++++++++++++++++++-------------------
 1 file changed, 30 insertions(+), 28 deletions(-)

diff --git a/arch/mips/include/asm/spinlock.h b/arch/mips/include/asm/spinlock.h
index 78d201fb6c87..f63b3543c1a4 100644
--- a/arch/mips/include/asm/spinlock.h
+++ b/arch/mips/include/asm/spinlock.h
@@ -98,9 +98,9 @@ static inline void arch_spin_lock(arch_spinlock_t *lock)
 		"	.set push		# arch_spin_lock	\n"
 		"	.set noreorder					\n"
 		"							\n"
-		"1:	ll	%[ticket], %[ticket_ptr]		\n"
+		"1:	ll	%[ticket], 0(%[ticket_ptr])		\n"
 		"	addu	%[my_ticket], %[ticket], %[inc]		\n"
-		"	sc	%[my_ticket], %[ticket_ptr]		\n"
+		"	sc	%[my_ticket], 0(%[ticket_ptr])		\n"
 		"	beqz	%[my_ticket], 1b			\n"
 		"	 srl	%[my_ticket], %[ticket], 16		\n"
 		"	andi	%[ticket], %[ticket], 0xffff		\n"
@@ -121,11 +121,12 @@ static inline void arch_spin_lock(arch_spinlock_t *lock)
 		"	 subu	%[ticket], %[ticket], 1			\n"
 		"	.previous					\n"
 		"	.set pop					\n"
-		: [ticket_ptr] "+m" (lock->lock),
+		: "+m" (lock->lock),
 		  [serving_now_ptr] "+m" (lock->h.serving_now),
 		  [ticket] "=&r" (tmp),
 		  [my_ticket] "=&r" (my_ticket)
-		: [inc] "r" (inc));
+		: [inc] "r" (inc),
+		  [ticket_ptr] "r" (&lock->lock));
 	}
 
 	smp_llsc_mb();
@@ -173,12 +174,12 @@ static inline unsigned int arch_spin_trylock(arch_spinlock_t *lock)
 		"	.set push		# arch_spin_trylock	\n"
 		"	.set noreorder					\n"
 		"							\n"
-		"1:	ll	%[ticket], %[ticket_ptr]		\n"
+		"1:	ll	%[ticket], 0(%[ticket_ptr])		\n"
 		"	srl	%[my_ticket], %[ticket], 16		\n"
 		"	andi	%[now_serving], %[ticket], 0xffff	\n"
 		"	bne	%[my_ticket], %[now_serving], 3f	\n"
 		"	 addu	%[ticket], %[ticket], %[inc]		\n"
-		"	sc	%[ticket], %[ticket_ptr]		\n"
+		"	sc	%[ticket], 0(%[ticket_ptr])		\n"
 		"	beqz	%[ticket], 1b				\n"
 		"	 li	%[ticket], 1				\n"
 		"2:							\n"
@@ -187,11 +188,12 @@ static inline unsigned int arch_spin_trylock(arch_spinlock_t *lock)
 		"	 li	%[ticket], 0				\n"
 		"	.previous					\n"
 		"	.set pop					\n"
-		: [ticket_ptr] "+m" (lock->lock),
+		: "+m" (lock->lock),
 		  [ticket] "=&r" (tmp),
 		  [my_ticket] "=&r" (tmp2),
 		  [now_serving] "=&r" (tmp3)
-		: [inc] "r" (inc));
+		: [inc] "r" (inc),
+		  [ticket_ptr] "r" (&lock->lock));
 	}
 
 	smp_llsc_mb();
@@ -240,12 +242,12 @@ static inline void arch_read_lock(arch_rwlock_t *rw)
 	} else {
 		do {
 			__asm__ __volatile__(
-			"1:	ll	%1, %2	# arch_read_lock	\n"
+			"1:	ll	%1, 0(%2)# arch_read_lock	\n"
 			"	bltz	%1, 1b				\n"
 			"	 addu	%1, 1				\n"
-			"2:	sc	%1, %0				\n"
-			: "=m" (rw->lock), "=&r" (tmp)
-			: "m" (rw->lock)
+			"2:	sc	%1, 0(%2)			\n"
+			: "+m" (rw->lock), "=&r" (tmp)
+			: "r" (&rw->lock)
 			: "memory");
 		} while (unlikely(!tmp));
 	}
@@ -274,11 +276,11 @@ static inline void arch_read_unlock(arch_rwlock_t *rw)
 	} else {
 		do {
 			__asm__ __volatile__(
-			"1:	ll	%1, %2	# arch_read_unlock	\n"
+			"1:	ll	%1, 0(%2)# arch_read_unlock	\n"
 			"	sub	%1, 1				\n"
-			"	sc	%1, %0				\n"
-			: "=m" (rw->lock), "=&r" (tmp)
-			: "m" (rw->lock)
+			"	sc	%1, 0(%2)			\n"
+			: "+m" (rw->lock), "=&r" (tmp)
+			: "r" (&rw->lock)
 			: "memory");
 		} while (unlikely(!tmp));
 	}
@@ -304,12 +306,12 @@ static inline void arch_write_lock(arch_rwlock_t *rw)
 	} else {
 		do {
 			__asm__ __volatile__(
-			"1:	ll	%1, %2	# arch_write_lock	\n"
+			"1:	ll	%1, 0(%2)# arch_write_lock	\n"
 			"	bnez	%1, 1b				\n"
 			"	 lui	%1, 0x8000			\n"
-			"2:	sc	%1, %0				\n"
-			: "=m" (rw->lock), "=&r" (tmp)
-			: "m" (rw->lock)
+			"2:	sc	%1, 0(%2)			\n"
+			: "+m" (rw->lock), "=&r" (tmp)
+			: "r" (&rw->lock)
 			: "memory");
 		} while (unlikely(!tmp));
 	}
@@ -355,18 +357,18 @@ static inline int arch_read_trylock(arch_rwlock_t *rw)
 		__asm__ __volatile__(
 		"	.set	noreorder	# arch_read_trylock	\n"
 		"	li	%2, 0					\n"
-		"1:	ll	%1, %3					\n"
+		"1:	ll	%1, 0(%3)				\n"
 		"	bltz	%1, 2f					\n"
 		"	 addu	%1, 1					\n"
-		"	sc	%1, %0					\n"
+		"	sc	%1, 0(%3)				\n"
 		"	beqz	%1, 1b					\n"
 		"	 nop						\n"
 		"	.set	reorder					\n"
 		__WEAK_LLSC_MB
 		"	li	%2, 1					\n"
 		"2:							\n"
-		: "=m" (rw->lock), "=&r" (tmp), "=&r" (ret)
-		: "m" (rw->lock)
+		: "+m" (rw->lock), "=&r" (tmp), "=&r" (ret)
+		: "r" (&rw->lock)
 		: "memory");
 	}
 
@@ -398,15 +400,15 @@ static inline int arch_write_trylock(arch_rwlock_t *rw)
 	} else {
 		do {
 			__asm__ __volatile__(
-			"	ll	%1, %3	# arch_write_trylock	\n"
+			"	ll	%1, 0(%3)# arch_write_trylock	\n"
 			"	li	%2, 0				\n"
 			"	bnez	%1, 2f				\n"
 			"	lui	%1, 0x8000			\n"
-			"	sc	%1, %0				\n"
+			"	sc	%1, 0(%3)			\n"
 			"	li	%2, 1				\n"
 			"2:						\n"
-			: "=m" (rw->lock), "=&r" (tmp), "=&r" (ret)
-			: "m" (rw->lock)
+			: "+m" (rw->lock), "=&r" (tmp), "=&r" (ret)
+			: "r" (&rw->lock)
 			: "memory");
 		} while (unlikely(!tmp));
 
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 23/67] MIPS: asm: spinlock: Update asm constrains for MIPS R6 support
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Matthew Fortune

MIPS R6 changed the opcodes for LL/SC instructions and reduced the
offset field to 9-bits. This has some undesired effects with the "m"
constrain since it implies a 16-bit immediate. As a result of which,
add a register ("r") constrain as well to make sure the entire address
is loaded to a register before the LL/SC operations.

Cc: Matthew Fortune <Matthew.Fortune@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/spinlock.h | 58 +++++++++++++++++++++-------------------
 1 file changed, 30 insertions(+), 28 deletions(-)

diff --git a/arch/mips/include/asm/spinlock.h b/arch/mips/include/asm/spinlock.h
index 78d201fb6c87..f63b3543c1a4 100644
--- a/arch/mips/include/asm/spinlock.h
+++ b/arch/mips/include/asm/spinlock.h
@@ -98,9 +98,9 @@ static inline void arch_spin_lock(arch_spinlock_t *lock)
 		"	.set push		# arch_spin_lock	\n"
 		"	.set noreorder					\n"
 		"							\n"
-		"1:	ll	%[ticket], %[ticket_ptr]		\n"
+		"1:	ll	%[ticket], 0(%[ticket_ptr])		\n"
 		"	addu	%[my_ticket], %[ticket], %[inc]		\n"
-		"	sc	%[my_ticket], %[ticket_ptr]		\n"
+		"	sc	%[my_ticket], 0(%[ticket_ptr])		\n"
 		"	beqz	%[my_ticket], 1b			\n"
 		"	 srl	%[my_ticket], %[ticket], 16		\n"
 		"	andi	%[ticket], %[ticket], 0xffff		\n"
@@ -121,11 +121,12 @@ static inline void arch_spin_lock(arch_spinlock_t *lock)
 		"	 subu	%[ticket], %[ticket], 1			\n"
 		"	.previous					\n"
 		"	.set pop					\n"
-		: [ticket_ptr] "+m" (lock->lock),
+		: "+m" (lock->lock),
 		  [serving_now_ptr] "+m" (lock->h.serving_now),
 		  [ticket] "=&r" (tmp),
 		  [my_ticket] "=&r" (my_ticket)
-		: [inc] "r" (inc));
+		: [inc] "r" (inc),
+		  [ticket_ptr] "r" (&lock->lock));
 	}
 
 	smp_llsc_mb();
@@ -173,12 +174,12 @@ static inline unsigned int arch_spin_trylock(arch_spinlock_t *lock)
 		"	.set push		# arch_spin_trylock	\n"
 		"	.set noreorder					\n"
 		"							\n"
-		"1:	ll	%[ticket], %[ticket_ptr]		\n"
+		"1:	ll	%[ticket], 0(%[ticket_ptr])		\n"
 		"	srl	%[my_ticket], %[ticket], 16		\n"
 		"	andi	%[now_serving], %[ticket], 0xffff	\n"
 		"	bne	%[my_ticket], %[now_serving], 3f	\n"
 		"	 addu	%[ticket], %[ticket], %[inc]		\n"
-		"	sc	%[ticket], %[ticket_ptr]		\n"
+		"	sc	%[ticket], 0(%[ticket_ptr])		\n"
 		"	beqz	%[ticket], 1b				\n"
 		"	 li	%[ticket], 1				\n"
 		"2:							\n"
@@ -187,11 +188,12 @@ static inline unsigned int arch_spin_trylock(arch_spinlock_t *lock)
 		"	 li	%[ticket], 0				\n"
 		"	.previous					\n"
 		"	.set pop					\n"
-		: [ticket_ptr] "+m" (lock->lock),
+		: "+m" (lock->lock),
 		  [ticket] "=&r" (tmp),
 		  [my_ticket] "=&r" (tmp2),
 		  [now_serving] "=&r" (tmp3)
-		: [inc] "r" (inc));
+		: [inc] "r" (inc),
+		  [ticket_ptr] "r" (&lock->lock));
 	}
 
 	smp_llsc_mb();
@@ -240,12 +242,12 @@ static inline void arch_read_lock(arch_rwlock_t *rw)
 	} else {
 		do {
 			__asm__ __volatile__(
-			"1:	ll	%1, %2	# arch_read_lock	\n"
+			"1:	ll	%1, 0(%2)# arch_read_lock	\n"
 			"	bltz	%1, 1b				\n"
 			"	 addu	%1, 1				\n"
-			"2:	sc	%1, %0				\n"
-			: "=m" (rw->lock), "=&r" (tmp)
-			: "m" (rw->lock)
+			"2:	sc	%1, 0(%2)			\n"
+			: "+m" (rw->lock), "=&r" (tmp)
+			: "r" (&rw->lock)
 			: "memory");
 		} while (unlikely(!tmp));
 	}
@@ -274,11 +276,11 @@ static inline void arch_read_unlock(arch_rwlock_t *rw)
 	} else {
 		do {
 			__asm__ __volatile__(
-			"1:	ll	%1, %2	# arch_read_unlock	\n"
+			"1:	ll	%1, 0(%2)# arch_read_unlock	\n"
 			"	sub	%1, 1				\n"
-			"	sc	%1, %0				\n"
-			: "=m" (rw->lock), "=&r" (tmp)
-			: "m" (rw->lock)
+			"	sc	%1, 0(%2)			\n"
+			: "+m" (rw->lock), "=&r" (tmp)
+			: "r" (&rw->lock)
 			: "memory");
 		} while (unlikely(!tmp));
 	}
@@ -304,12 +306,12 @@ static inline void arch_write_lock(arch_rwlock_t *rw)
 	} else {
 		do {
 			__asm__ __volatile__(
-			"1:	ll	%1, %2	# arch_write_lock	\n"
+			"1:	ll	%1, 0(%2)# arch_write_lock	\n"
 			"	bnez	%1, 1b				\n"
 			"	 lui	%1, 0x8000			\n"
-			"2:	sc	%1, %0				\n"
-			: "=m" (rw->lock), "=&r" (tmp)
-			: "m" (rw->lock)
+			"2:	sc	%1, 0(%2)			\n"
+			: "+m" (rw->lock), "=&r" (tmp)
+			: "r" (&rw->lock)
 			: "memory");
 		} while (unlikely(!tmp));
 	}
@@ -355,18 +357,18 @@ static inline int arch_read_trylock(arch_rwlock_t *rw)
 		__asm__ __volatile__(
 		"	.set	noreorder	# arch_read_trylock	\n"
 		"	li	%2, 0					\n"
-		"1:	ll	%1, %3					\n"
+		"1:	ll	%1, 0(%3)				\n"
 		"	bltz	%1, 2f					\n"
 		"	 addu	%1, 1					\n"
-		"	sc	%1, %0					\n"
+		"	sc	%1, 0(%3)				\n"
 		"	beqz	%1, 1b					\n"
 		"	 nop						\n"
 		"	.set	reorder					\n"
 		__WEAK_LLSC_MB
 		"	li	%2, 1					\n"
 		"2:							\n"
-		: "=m" (rw->lock), "=&r" (tmp), "=&r" (ret)
-		: "m" (rw->lock)
+		: "+m" (rw->lock), "=&r" (tmp), "=&r" (ret)
+		: "r" (&rw->lock)
 		: "memory");
 	}
 
@@ -398,15 +400,15 @@ static inline int arch_write_trylock(arch_rwlock_t *rw)
 	} else {
 		do {
 			__asm__ __volatile__(
-			"	ll	%1, %3	# arch_write_trylock	\n"
+			"	ll	%1, 0(%3)# arch_write_trylock	\n"
 			"	li	%2, 0				\n"
 			"	bnez	%1, 2f				\n"
 			"	lui	%1, 0x8000			\n"
-			"	sc	%1, %0				\n"
+			"	sc	%1, 0(%3)			\n"
 			"	li	%2, 1				\n"
 			"2:						\n"
-			: "=m" (rw->lock), "=&r" (tmp), "=&r" (ret)
-			: "m" (rw->lock)
+			: "+m" (rw->lock), "=&r" (tmp), "=&r" (ret)
+			: "r" (&rw->lock)
 			: "memory");
 		} while (unlikely(!tmp));
 
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 24/67] MIPS: asm: spinlock: Replace sub instruction with addiu
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

sub $reg, imm is not a real MIPS instruction. The assembler replaces
that with 'addi $reg, -imm'. However, addi has been removed from R6,
so we replace the 'sub' instruction with 'addiu' instead.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/spinlock.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/mips/include/asm/spinlock.h b/arch/mips/include/asm/spinlock.h
index f63b3543c1a4..c82fc0eefbec 100644
--- a/arch/mips/include/asm/spinlock.h
+++ b/arch/mips/include/asm/spinlock.h
@@ -277,7 +277,7 @@ static inline void arch_read_unlock(arch_rwlock_t *rw)
 		do {
 			__asm__ __volatile__(
 			"1:	ll	%1, 0(%2)# arch_read_unlock	\n"
-			"	sub	%1, 1				\n"
+			"	addiu	%1, -1				\n"
 			"	sc	%1, 0(%2)			\n"
 			: "+m" (rw->lock), "=&r" (tmp)
 			: "r" (&rw->lock)
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 24/67] MIPS: asm: spinlock: Replace sub instruction with addiu
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

sub $reg, imm is not a real MIPS instruction. The assembler replaces
that with 'addi $reg, -imm'. However, addi has been removed from R6,
so we replace the 'sub' instruction with 'addiu' instead.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/spinlock.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/mips/include/asm/spinlock.h b/arch/mips/include/asm/spinlock.h
index f63b3543c1a4..c82fc0eefbec 100644
--- a/arch/mips/include/asm/spinlock.h
+++ b/arch/mips/include/asm/spinlock.h
@@ -277,7 +277,7 @@ static inline void arch_read_unlock(arch_rwlock_t *rw)
 		do {
 			__asm__ __volatile__(
 			"1:	ll	%1, 0(%2)# arch_read_unlock	\n"
-			"	sub	%1, 1				\n"
+			"	addiu	%1, -1				\n"
 			"	sc	%1, 0(%2)			\n"
 			: "+m" (rw->lock), "=&r" (tmp)
 			: "r" (&rw->lock)
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 25/67] MIPS: kernel: cpu-bugs64: Do not check R6 cores for existing 64-bit bugs
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

The current HW bugs checked in cpu-bugs64, do not apply to R6 cores
and they cause compilation problems due to removed <R6 instructions,
so do not check for them for the time being.

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/cpu-bugs64.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/arch/mips/kernel/cpu-bugs64.c b/arch/mips/kernel/cpu-bugs64.c
index 2d80b5f1aeae..09f4034f239f 100644
--- a/arch/mips/kernel/cpu-bugs64.c
+++ b/arch/mips/kernel/cpu-bugs64.c
@@ -244,7 +244,7 @@ static inline void check_daddi(void)
 	panic(bug64hit, !DADDI_WAR ? daddiwar : nowar);
 }
 
-int daddiu_bug	= -1;
+int daddiu_bug	= config_enabled(CONFIG_CPU_MIPSR6) ? 0 : -1;
 
 static inline void check_daddiu(void)
 {
@@ -314,11 +314,14 @@ static inline void check_daddiu(void)
 
 void __init check_bugs64_early(void)
 {
-	check_mult_sh();
-	check_daddiu();
+	if (!config_enabled(CONFIG_CPU_MIPSR6)) {
+		check_mult_sh();
+		check_daddiu();
+	}
 }
 
 void __init check_bugs64(void)
 {
-	check_daddi();
+	if (!config_enabled(CONFIG_CPU_MIPSR6))
+		check_daddi();
 }
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 25/67] MIPS: kernel: cpu-bugs64: Do not check R6 cores for existing 64-bit bugs
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

The current HW bugs checked in cpu-bugs64, do not apply to R6 cores
and they cause compilation problems due to removed <R6 instructions,
so do not check for them for the time being.

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/cpu-bugs64.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/arch/mips/kernel/cpu-bugs64.c b/arch/mips/kernel/cpu-bugs64.c
index 2d80b5f1aeae..09f4034f239f 100644
--- a/arch/mips/kernel/cpu-bugs64.c
+++ b/arch/mips/kernel/cpu-bugs64.c
@@ -244,7 +244,7 @@ static inline void check_daddi(void)
 	panic(bug64hit, !DADDI_WAR ? daddiwar : nowar);
 }
 
-int daddiu_bug	= -1;
+int daddiu_bug	= config_enabled(CONFIG_CPU_MIPSR6) ? 0 : -1;
 
 static inline void check_daddiu(void)
 {
@@ -314,11 +314,14 @@ static inline void check_daddiu(void)
 
 void __init check_bugs64_early(void)
 {
-	check_mult_sh();
-	check_daddiu();
+	if (!config_enabled(CONFIG_CPU_MIPSR6)) {
+		check_mult_sh();
+		check_daddiu();
+	}
 }
 
 void __init check_bugs64(void)
 {
-	check_daddi();
+	if (!config_enabled(CONFIG_CPU_MIPSR6))
+		check_daddi();
 }
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 26/67] MIPS: kernel: cevt-r4k: Add MIPS R6 to the c0_compare_interrupt handler
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

Just like MIPS R2, in MIPS R6 it is possible to determine if a
timer interrupt has happened or not.

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/cevt-r4k.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c
index bc127e22fdab..1bf23140ad1b 100644
--- a/arch/mips/kernel/cevt-r4k.c
+++ b/arch/mips/kernel/cevt-r4k.c
@@ -40,7 +40,7 @@ int cp0_timer_irq_installed;
 
 irqreturn_t c0_compare_interrupt(int irq, void *dev_id)
 {
-	const int r2 = cpu_has_mips_r2;
+	const int r2 = cpu_has_mips_r2 | cpu_has_mips_r6;
 	struct clock_event_device *cd;
 	int cpu = smp_processor_id();
 
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 26/67] MIPS: kernel: cevt-r4k: Add MIPS R6 to the c0_compare_interrupt handler
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

Just like MIPS R2, in MIPS R6 it is possible to determine if a
timer interrupt has happened or not.

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/cevt-r4k.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c
index bc127e22fdab..1bf23140ad1b 100644
--- a/arch/mips/kernel/cevt-r4k.c
+++ b/arch/mips/kernel/cevt-r4k.c
@@ -40,7 +40,7 @@ int cp0_timer_irq_installed;
 
 irqreturn_t c0_compare_interrupt(int irq, void *dev_id)
 {
-	const int r2 = cpu_has_mips_r2;
+	const int r2 = cpu_has_mips_r2 | cpu_has_mips_r6;
 	struct clock_event_device *cd;
 	int cpu = smp_processor_id();
 
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 27/67] MIPS: kernel: cpu-probe.c: Add support for MIPS R6
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

Add MIPS R6 support when decoding the config0 c0 register.
Also add MIPS R6 support when examining the ebase c0 register
to get the core number and when getting the shadow set number
from the srsctl c0 register.

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/cpu-probe.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 08574035b239..3a0b6c11d34b 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -180,6 +180,13 @@ static void set_isa(struct cpuinfo_mips *c, unsigned int isa)
 		c->isa_level |= MIPS_CPU_ISA_II | MIPS_CPU_ISA_III;
 		break;
 
+	/* R6 incopatible with everything else */
+	case MIPS_CPU_ISA_M64R6:
+		c->isa_level |= MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6;
+	case MIPS_CPU_ISA_M32R6:
+		c->isa_level |= MIPS_CPU_ISA_M32R6;
+		/* Break here so we don't add incopatible ISAs */
+		break;
 	case MIPS_CPU_ISA_M32R2:
 		c->isa_level |= MIPS_CPU_ISA_M32R2;
 	case MIPS_CPU_ISA_M32R1:
@@ -269,6 +276,9 @@ static inline unsigned int decode_config0(struct cpuinfo_mips *c)
 		case 1:
 			set_isa(c, MIPS_CPU_ISA_M32R2);
 			break;
+		case 2:
+			set_isa(c, MIPS_CPU_ISA_M32R6);
+			break;
 		default:
 			goto unknown;
 		}
@@ -281,6 +291,9 @@ static inline unsigned int decode_config0(struct cpuinfo_mips *c)
 		case 1:
 			set_isa(c, MIPS_CPU_ISA_M64R2);
 			break;
+		case 2:
+			set_isa(c, MIPS_CPU_ISA_M64R6);
+			break;
 		default:
 			goto unknown;
 		}
@@ -481,7 +494,7 @@ static void decode_configs(struct cpuinfo_mips *c)
 	}
 
 #ifndef CONFIG_MIPS_CPS
-	if (cpu_has_mips_r2) {
+	if (cpu_has_mips_r2 || cpu_has_mips_r6) {
 		c->core = get_ebase_cpunum();
 		if (cpu_has_mipsmt)
 			c->core >>= fls(core_nvpes()) - 1;
@@ -1296,7 +1309,7 @@ void cpu_probe(void)
 		}
 	}
 
-	if (cpu_has_mips_r2) {
+	if (cpu_has_mips_r2 || cpu_has_mips_r6) {
 		c->srsets = ((read_c0_srsctl() >> 26) & 0x0f) + 1;
 		/* R2 has Performance Counter Interrupt indicator */
 		c->options |= MIPS_CPU_PCI;
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 27/67] MIPS: kernel: cpu-probe.c: Add support for MIPS R6
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

Add MIPS R6 support when decoding the config0 c0 register.
Also add MIPS R6 support when examining the ebase c0 register
to get the core number and when getting the shadow set number
from the srsctl c0 register.

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/cpu-probe.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 08574035b239..3a0b6c11d34b 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -180,6 +180,13 @@ static void set_isa(struct cpuinfo_mips *c, unsigned int isa)
 		c->isa_level |= MIPS_CPU_ISA_II | MIPS_CPU_ISA_III;
 		break;
 
+	/* R6 incopatible with everything else */
+	case MIPS_CPU_ISA_M64R6:
+		c->isa_level |= MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6;
+	case MIPS_CPU_ISA_M32R6:
+		c->isa_level |= MIPS_CPU_ISA_M32R6;
+		/* Break here so we don't add incopatible ISAs */
+		break;
 	case MIPS_CPU_ISA_M32R2:
 		c->isa_level |= MIPS_CPU_ISA_M32R2;
 	case MIPS_CPU_ISA_M32R1:
@@ -269,6 +276,9 @@ static inline unsigned int decode_config0(struct cpuinfo_mips *c)
 		case 1:
 			set_isa(c, MIPS_CPU_ISA_M32R2);
 			break;
+		case 2:
+			set_isa(c, MIPS_CPU_ISA_M32R6);
+			break;
 		default:
 			goto unknown;
 		}
@@ -281,6 +291,9 @@ static inline unsigned int decode_config0(struct cpuinfo_mips *c)
 		case 1:
 			set_isa(c, MIPS_CPU_ISA_M64R2);
 			break;
+		case 2:
+			set_isa(c, MIPS_CPU_ISA_M64R6);
+			break;
 		default:
 			goto unknown;
 		}
@@ -481,7 +494,7 @@ static void decode_configs(struct cpuinfo_mips *c)
 	}
 
 #ifndef CONFIG_MIPS_CPS
-	if (cpu_has_mips_r2) {
+	if (cpu_has_mips_r2 || cpu_has_mips_r6) {
 		c->core = get_ebase_cpunum();
 		if (cpu_has_mipsmt)
 			c->core >>= fls(core_nvpes()) - 1;
@@ -1296,7 +1309,7 @@ void cpu_probe(void)
 		}
 	}
 
-	if (cpu_has_mips_r2) {
+	if (cpu_has_mips_r2 || cpu_has_mips_r6) {
 		c->srsets = ((read_c0_srsctl() >> 26) & 0x0f) + 1;
 		/* R2 has Performance Counter Interrupt indicator */
 		c->options |= MIPS_CPU_PCI;
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 28/67] MIPS: kernel: entry.S: Add MIPS R6 related definitions
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

The instruction hazard barrier in the form of:

jr.hb	ra
nop

is valid on MIPS R6 as well.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/entry.S | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
index 4353d323f017..d5ab21c3fd12 100644
--- a/arch/mips/kernel/entry.S
+++ b/arch/mips/kernel/entry.S
@@ -158,7 +158,8 @@ syscall_exit_work:
 	jal	syscall_trace_leave
 	b	resume_userspace
 
-#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_MIPS_MT)
+#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) || \
+    defined(CONFIG_MIPS_MT)
 
 /*
  * MIPS32R2 Instruction Hazard Barrier - must be called
@@ -171,4 +172,4 @@ LEAF(mips_ihb)
 	nop
 	END(mips_ihb)
 
-#endif /* CONFIG_CPU_MIPSR2 or CONFIG_MIPS_MT */
+#endif /* CONFIG_CPU_MIPSR2 or CONFIG_CPU_MIPSR6 or CONFIG_MIPS_MT */
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 28/67] MIPS: kernel: entry.S: Add MIPS R6 related definitions
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

The instruction hazard barrier in the form of:

jr.hb	ra
nop

is valid on MIPS R6 as well.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/entry.S | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
index 4353d323f017..d5ab21c3fd12 100644
--- a/arch/mips/kernel/entry.S
+++ b/arch/mips/kernel/entry.S
@@ -158,7 +158,8 @@ syscall_exit_work:
 	jal	syscall_trace_leave
 	b	resume_userspace
 
-#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_MIPS_MT)
+#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) || \
+    defined(CONFIG_MIPS_MT)
 
 /*
  * MIPS32R2 Instruction Hazard Barrier - must be called
@@ -171,4 +172,4 @@ LEAF(mips_ihb)
 	nop
 	END(mips_ihb)
 
-#endif /* CONFIG_CPU_MIPSR2 or CONFIG_MIPS_MT */
+#endif /* CONFIG_CPU_MIPSR2 or CONFIG_CPU_MIPSR6 or CONFIG_MIPS_MT */
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 29/67] MIPS: kernel: proc: Add MIPS R6 support to /proc/cpuinfo
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

Print 'mips64r6' and/or 'mips32r6' if the kernel is running on
a MIPS R6 core.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/proc.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
index 097fc8d14e42..b2194770878d 100644
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -82,7 +82,10 @@ static int show_cpuinfo(struct seq_file *m, void *v)
 		seq_printf(m, "]\n");
 	}
 
-	seq_printf(m, "isa\t\t\t: mips1");
+	if (!cpu_has_mips_r6)
+		seq_printf(m, "isa\t\t\t: mips1");
+	else
+		seq_printf(m, "isa\t\t\t:");
 	if (cpu_has_mips_2)
 		seq_printf(m, "%s", " mips2");
 	if (cpu_has_mips_3)
@@ -95,10 +98,14 @@ static int show_cpuinfo(struct seq_file *m, void *v)
 		seq_printf(m, "%s", " mips32r1");
 	if (cpu_has_mips32r2)
 		seq_printf(m, "%s", " mips32r2");
+	if (cpu_has_mips32r6)
+		seq_printf(m, "%s", " mips32r6");
 	if (cpu_has_mips64r1)
 		seq_printf(m, "%s", " mips64r1");
 	if (cpu_has_mips64r2)
 		seq_printf(m, "%s", " mips64r2");
+	if (cpu_has_mips64r6)
+		seq_printf(m, "%s", " mips64r6");
 	seq_printf(m, "\n");
 
 	seq_printf(m, "ASEs implemented\t:");
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 29/67] MIPS: kernel: proc: Add MIPS R6 support to /proc/cpuinfo
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

Print 'mips64r6' and/or 'mips32r6' if the kernel is running on
a MIPS R6 core.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/proc.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
index 097fc8d14e42..b2194770878d 100644
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -82,7 +82,10 @@ static int show_cpuinfo(struct seq_file *m, void *v)
 		seq_printf(m, "]\n");
 	}
 
-	seq_printf(m, "isa\t\t\t: mips1");
+	if (!cpu_has_mips_r6)
+		seq_printf(m, "isa\t\t\t: mips1");
+	else
+		seq_printf(m, "isa\t\t\t:");
 	if (cpu_has_mips_2)
 		seq_printf(m, "%s", " mips2");
 	if (cpu_has_mips_3)
@@ -95,10 +98,14 @@ static int show_cpuinfo(struct seq_file *m, void *v)
 		seq_printf(m, "%s", " mips32r1");
 	if (cpu_has_mips32r2)
 		seq_printf(m, "%s", " mips32r2");
+	if (cpu_has_mips32r6)
+		seq_printf(m, "%s", " mips32r6");
 	if (cpu_has_mips64r1)
 		seq_printf(m, "%s", " mips64r1");
 	if (cpu_has_mips64r2)
 		seq_printf(m, "%s", " mips64r2");
+	if (cpu_has_mips64r6)
+		seq_printf(m, "%s", " mips64r6");
 	seq_printf(m, "\n");
 
 	seq_printf(m, "ASEs implemented\t:");
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 30/67] MIPS: kernel: traps: Add MIPS R6 related definitions
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

Add MIPS R6 support to cache and ftlb exceptions, as well as
to the hwrena and ebase register configuration.

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/traps.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index b3568c049b72..5223f173a5db 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1576,7 +1576,7 @@ asmlinkage void cache_parity_error(void)
 	printk("Decoded c0_cacheerr: %s cache fault in %s reference.\n",
 	       reg_val & (1<<30) ? "secondary" : "primary",
 	       reg_val & (1<<31) ? "data" : "insn");
-	if (cpu_has_mips_r2 &&
+	if ((cpu_has_mips_r2 || cpu_has_mips_r6) &&
 	    ((current_cpu_data.processor_id & 0xff0000) == PRID_COMP_MIPS)) {
 		pr_err("Error bits: %s%s%s%s%s%s%s%s\n",
 			reg_val & (1<<29) ? "ED " : "",
@@ -1616,7 +1616,7 @@ asmlinkage void do_ftlb(void)
 	unsigned int reg_val;
 
 	/* For the moment, report the problem and hang. */
-	if (cpu_has_mips_r2 &&
+	if ((cpu_has_mips_r2 || cpu_has_mips_r6) &&
 	    ((current_cpu_data.processor_id & 0xff0000) == PRID_COMP_MIPS)) {
 		pr_err("FTLB error exception, cp0_ecc=0x%08x:\n",
 		       read_c0_ecc());
@@ -1905,7 +1905,7 @@ static void configure_hwrena(void)
 {
 	unsigned int hwrena = cpu_hwrena_impl_bits;
 
-	if (cpu_has_mips_r2)
+	if (cpu_has_mips_r2 || cpu_has_mips_r6)
 		hwrena |= 0x0000000f;
 
 	if (!noulri && cpu_has_userlocal)
@@ -1949,7 +1949,7 @@ void per_cpu_trap_init(bool is_boot_cpu)
 	 *  o read IntCtl.IPTI to determine the timer interrupt
 	 *  o read IntCtl.IPPCI to determine the performance counter interrupt
 	 */
-	if (cpu_has_mips_r2) {
+	if (cpu_has_mips_r2 || cpu_has_mips_r6) {
 		cp0_compare_irq_shift = CAUSEB_TI - CAUSEB_IP;
 		cp0_compare_irq = (read_c0_intctl() >> INTCTLB_IPTI) & 7;
 		cp0_perfcount_irq = (read_c0_intctl() >> INTCTLB_IPPCI) & 7;
@@ -2040,7 +2040,7 @@ void __init trap_init(void)
 #else
         ebase = CKSEG0;
 #endif
-		if (cpu_has_mips_r2)
+		if (cpu_has_mips_r2 || cpu_has_mips_r6)
 			ebase += (read_c0_ebase() & 0x3ffff000);
 	}
 
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 30/67] MIPS: kernel: traps: Add MIPS R6 related definitions
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

Add MIPS R6 support to cache and ftlb exceptions, as well as
to the hwrena and ebase register configuration.

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/traps.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index b3568c049b72..5223f173a5db 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1576,7 +1576,7 @@ asmlinkage void cache_parity_error(void)
 	printk("Decoded c0_cacheerr: %s cache fault in %s reference.\n",
 	       reg_val & (1<<30) ? "secondary" : "primary",
 	       reg_val & (1<<31) ? "data" : "insn");
-	if (cpu_has_mips_r2 &&
+	if ((cpu_has_mips_r2 || cpu_has_mips_r6) &&
 	    ((current_cpu_data.processor_id & 0xff0000) == PRID_COMP_MIPS)) {
 		pr_err("Error bits: %s%s%s%s%s%s%s%s\n",
 			reg_val & (1<<29) ? "ED " : "",
@@ -1616,7 +1616,7 @@ asmlinkage void do_ftlb(void)
 	unsigned int reg_val;
 
 	/* For the moment, report the problem and hang. */
-	if (cpu_has_mips_r2 &&
+	if ((cpu_has_mips_r2 || cpu_has_mips_r6) &&
 	    ((current_cpu_data.processor_id & 0xff0000) == PRID_COMP_MIPS)) {
 		pr_err("FTLB error exception, cp0_ecc=0x%08x:\n",
 		       read_c0_ecc());
@@ -1905,7 +1905,7 @@ static void configure_hwrena(void)
 {
 	unsigned int hwrena = cpu_hwrena_impl_bits;
 
-	if (cpu_has_mips_r2)
+	if (cpu_has_mips_r2 || cpu_has_mips_r6)
 		hwrena |= 0x0000000f;
 
 	if (!noulri && cpu_has_userlocal)
@@ -1949,7 +1949,7 @@ void per_cpu_trap_init(bool is_boot_cpu)
 	 *  o read IntCtl.IPTI to determine the timer interrupt
 	 *  o read IntCtl.IPPCI to determine the performance counter interrupt
 	 */
-	if (cpu_has_mips_r2) {
+	if (cpu_has_mips_r2 || cpu_has_mips_r6) {
 		cp0_compare_irq_shift = CAUSEB_TI - CAUSEB_IP;
 		cp0_compare_irq = (read_c0_intctl() >> INTCTLB_IPTI) & 7;
 		cp0_perfcount_irq = (read_c0_intctl() >> INTCTLB_IPPCI) & 7;
@@ -2040,7 +2040,7 @@ void __init trap_init(void)
 #else
         ebase = CKSEG0;
 #endif
-		if (cpu_has_mips_r2)
+		if (cpu_has_mips_r2 || cpu_has_mips_r6)
 			ebase += (read_c0_ebase() & 0x3ffff000);
 	}
 
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 31/67] MIPS: kernel: r4k_switch: Add support for MIPS R6
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

Add the MIPS R6 related preprocessor definitions for save/restore
FPU related functions. We also set the appropriate ISA level
so the final return instruction "jr ra" will produce the correct
opcode on R6.

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/asmmacro.h | 12 +++++++-----
 arch/mips/kernel/r4k_switch.S    | 12 +++++++-----
 2 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h
index 55c07c40c199..f3b75346536a 100644
--- a/arch/mips/include/asm/asmmacro.h
+++ b/arch/mips/include/asm/asmmacro.h
@@ -104,7 +104,8 @@
 	.endm
 
 	.macro	fpu_save_double thread status tmp
-#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2)
+#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) || \
+		defined(CONFIG_CPU_MIPS32_R6)
 	sll	\tmp, \status, 5
 	bgez	\tmp, 10f
 	fpu_save_16odd \thread
@@ -160,7 +161,8 @@
 	.endm
 
 	.macro	fpu_restore_double thread status tmp
-#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2)
+#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) || \
+		defined(CONFIG_CPU_MIPS32_R6)
 	sll	\tmp, \status, 5
 	bgez	\tmp, 10f				# 16 register mode?
 
@@ -170,16 +172,16 @@
 	fpu_restore_16even \thread \tmp
 	.endm
 
-#ifdef CONFIG_CPU_MIPSR2
+#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
 	.macro	_EXT	rd, rs, p, s
 	ext	\rd, \rs, \p, \s
 	.endm
-#else /* !CONFIG_CPU_MIPSR2 */
+#else /* !CONFIG_CPU_MIPSR2 || !CONFIG_CPU_MIPSR6 */
 	.macro	_EXT	rd, rs, p, s
 	srl	\rd, \rs, \p
 	andi	\rd, \rd, (1 << \s) - 1
 	.endm
-#endif /* !CONFIG_CPU_MIPSR2 */
+#endif /* !CONFIG_CPU_MIPSR2 || !CONFIG_CPU_MIPSR6 */
 
 /*
  * Temporary until all gas have MT ASE support
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
index 64591e671878..08e5a8f5c276 100644
--- a/arch/mips/kernel/r4k_switch.S
+++ b/arch/mips/kernel/r4k_switch.S
@@ -115,7 +115,8 @@
  * Save a thread's fp context.
  */
 LEAF(_save_fp)
-#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2)
+#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) || \
+		defined(CONFIG_CPU_MIPS32_R6)
 	mfc0	t0, CP0_STATUS
 #endif
 	fpu_save_double a0 t0 t1		# clobbers t1
@@ -126,7 +127,8 @@ LEAF(_save_fp)
  * Restore a thread's fp context.
  */
 LEAF(_restore_fp)
-#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2)
+#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) || \
+		defined(CONFIG_CPU_MIPS32_R6)
 	mfc0	t0, CP0_STATUS
 #endif
 	fpu_restore_double a0 t0 t1		# clobbers t1
@@ -240,7 +242,7 @@ LEAF(_init_fpu)
 	mtc1	t1, $f30
 	mtc1	t1, $f31
 
-#ifdef CONFIG_CPU_MIPS32_R2
+#if defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_CPU_MIPS32_R6)
 	.set    push
 	.set    mips32r2
 	.set	fp=64
@@ -280,9 +282,9 @@ LEAF(_init_fpu)
 	mthc1   t1, $f30
 	mthc1   t1, $f31
 1:	.set    pop
-#endif /* CONFIG_CPU_MIPS32_R2 */
+#endif /* CONFIG_CPU_MIPS32_R2 || CONFIG_CPU_MIPS32_R6 */
 #else
-	.set	arch=r4000
+	.set	MIPS_ISA_ARCH_LEVEL_RAW
 	dmtc1	t1, $f0
 	dmtc1	t1, $f2
 	dmtc1	t1, $f4
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 31/67] MIPS: kernel: r4k_switch: Add support for MIPS R6
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

Add the MIPS R6 related preprocessor definitions for save/restore
FPU related functions. We also set the appropriate ISA level
so the final return instruction "jr ra" will produce the correct
opcode on R6.

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/asmmacro.h | 12 +++++++-----
 arch/mips/kernel/r4k_switch.S    | 12 +++++++-----
 2 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h
index 55c07c40c199..f3b75346536a 100644
--- a/arch/mips/include/asm/asmmacro.h
+++ b/arch/mips/include/asm/asmmacro.h
@@ -104,7 +104,8 @@
 	.endm
 
 	.macro	fpu_save_double thread status tmp
-#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2)
+#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) || \
+		defined(CONFIG_CPU_MIPS32_R6)
 	sll	\tmp, \status, 5
 	bgez	\tmp, 10f
 	fpu_save_16odd \thread
@@ -160,7 +161,8 @@
 	.endm
 
 	.macro	fpu_restore_double thread status tmp
-#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2)
+#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) || \
+		defined(CONFIG_CPU_MIPS32_R6)
 	sll	\tmp, \status, 5
 	bgez	\tmp, 10f				# 16 register mode?
 
@@ -170,16 +172,16 @@
 	fpu_restore_16even \thread \tmp
 	.endm
 
-#ifdef CONFIG_CPU_MIPSR2
+#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
 	.macro	_EXT	rd, rs, p, s
 	ext	\rd, \rs, \p, \s
 	.endm
-#else /* !CONFIG_CPU_MIPSR2 */
+#else /* !CONFIG_CPU_MIPSR2 || !CONFIG_CPU_MIPSR6 */
 	.macro	_EXT	rd, rs, p, s
 	srl	\rd, \rs, \p
 	andi	\rd, \rd, (1 << \s) - 1
 	.endm
-#endif /* !CONFIG_CPU_MIPSR2 */
+#endif /* !CONFIG_CPU_MIPSR2 || !CONFIG_CPU_MIPSR6 */
 
 /*
  * Temporary until all gas have MT ASE support
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
index 64591e671878..08e5a8f5c276 100644
--- a/arch/mips/kernel/r4k_switch.S
+++ b/arch/mips/kernel/r4k_switch.S
@@ -115,7 +115,8 @@
  * Save a thread's fp context.
  */
 LEAF(_save_fp)
-#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2)
+#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) || \
+		defined(CONFIG_CPU_MIPS32_R6)
 	mfc0	t0, CP0_STATUS
 #endif
 	fpu_save_double a0 t0 t1		# clobbers t1
@@ -126,7 +127,8 @@ LEAF(_save_fp)
  * Restore a thread's fp context.
  */
 LEAF(_restore_fp)
-#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2)
+#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) || \
+		defined(CONFIG_CPU_MIPS32_R6)
 	mfc0	t0, CP0_STATUS
 #endif
 	fpu_restore_double a0 t0 t1		# clobbers t1
@@ -240,7 +242,7 @@ LEAF(_init_fpu)
 	mtc1	t1, $f30
 	mtc1	t1, $f31
 
-#ifdef CONFIG_CPU_MIPS32_R2
+#if defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_CPU_MIPS32_R6)
 	.set    push
 	.set    mips32r2
 	.set	fp=64
@@ -280,9 +282,9 @@ LEAF(_init_fpu)
 	mthc1   t1, $f30
 	mthc1   t1, $f31
 1:	.set    pop
-#endif /* CONFIG_CPU_MIPS32_R2 */
+#endif /* CONFIG_CPU_MIPS32_R2 || CONFIG_CPU_MIPS32_R6 */
 #else
-	.set	arch=r4000
+	.set	MIPS_ISA_ARCH_LEVEL_RAW
 	dmtc1	t1, $f0
 	dmtc1	t1, $f2
 	dmtc1	t1, $f4
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 32/67] MIPS: kernel: r4k_fpu: Add support for MIPS R6
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

Add the MIPS R6 related preprocessor definitions for FPU signal
related functions. MIPS R6 only has FR=1 so avoid checking that
bit on the C0/Status register.

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/r4k_fpu.S | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/arch/mips/kernel/r4k_fpu.S b/arch/mips/kernel/r4k_fpu.S
index 6c160c67984c..fb7b21721c11 100644
--- a/arch/mips/kernel/r4k_fpu.S
+++ b/arch/mips/kernel/r4k_fpu.S
@@ -42,7 +42,8 @@ LEAF(_save_fp_context)
 	cfc1	t1, fcr31
 	.set	pop
 
-#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2)
+#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) || \
+		defined(CONFIG_CPU_MIPS32_R6)
 	.set	push
 	SET_HARDFLOAT
 #ifdef CONFIG_CPU_MIPS32_R2
@@ -105,10 +106,12 @@ LEAF(_save_fp_context32)
 	SET_HARDFLOAT
 	cfc1	t1, fcr31
 
+#ifndef CONFIG_CPU_MIPS64_R6
 	mfc0	t0, CP0_STATUS
 	sll	t0, t0, 5
 	bgez	t0, 1f			# skip storing odd if FR=0
 	 nop
+#endif
 
 	/* Store the 16 odd double precision registers */
 	EX      sdc1 $f1, SC32_FPREGS+8(a0)
@@ -163,7 +166,8 @@ LEAF(_save_fp_context32)
 LEAF(_restore_fp_context)
 	EX	lw t1, SC_FPC_CSR(a0)
 
-#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2)
+#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2)  || \
+		defined(CONFIG_CPU_MIPS32_R6)
 	.set	push
 	SET_HARDFLOAT
 #ifdef CONFIG_CPU_MIPS32_R2
@@ -223,10 +227,12 @@ LEAF(_restore_fp_context32)
 	SET_HARDFLOAT
 	EX	lw t1, SC32_FPC_CSR(a0)
 
+#ifndef CONFIG_CPU_MIPS64_R6
 	mfc0	t0, CP0_STATUS
 	sll	t0, t0, 5
 	bgez	t0, 1f			# skip loading odd if FR=0
 	 nop
+#endif
 
 	EX      ldc1 $f1, SC32_FPREGS+8(a0)
 	EX      ldc1 $f3, SC32_FPREGS+24(a0)
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 32/67] MIPS: kernel: r4k_fpu: Add support for MIPS R6
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

Add the MIPS R6 related preprocessor definitions for FPU signal
related functions. MIPS R6 only has FR=1 so avoid checking that
bit on the C0/Status register.

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/r4k_fpu.S | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/arch/mips/kernel/r4k_fpu.S b/arch/mips/kernel/r4k_fpu.S
index 6c160c67984c..fb7b21721c11 100644
--- a/arch/mips/kernel/r4k_fpu.S
+++ b/arch/mips/kernel/r4k_fpu.S
@@ -42,7 +42,8 @@ LEAF(_save_fp_context)
 	cfc1	t1, fcr31
 	.set	pop
 
-#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2)
+#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) || \
+		defined(CONFIG_CPU_MIPS32_R6)
 	.set	push
 	SET_HARDFLOAT
 #ifdef CONFIG_CPU_MIPS32_R2
@@ -105,10 +106,12 @@ LEAF(_save_fp_context32)
 	SET_HARDFLOAT
 	cfc1	t1, fcr31
 
+#ifndef CONFIG_CPU_MIPS64_R6
 	mfc0	t0, CP0_STATUS
 	sll	t0, t0, 5
 	bgez	t0, 1f			# skip storing odd if FR=0
 	 nop
+#endif
 
 	/* Store the 16 odd double precision registers */
 	EX      sdc1 $f1, SC32_FPREGS+8(a0)
@@ -163,7 +166,8 @@ LEAF(_save_fp_context32)
 LEAF(_restore_fp_context)
 	EX	lw t1, SC_FPC_CSR(a0)
 
-#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2)
+#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2)  || \
+		defined(CONFIG_CPU_MIPS32_R6)
 	.set	push
 	SET_HARDFLOAT
 #ifdef CONFIG_CPU_MIPS32_R2
@@ -223,10 +227,12 @@ LEAF(_restore_fp_context32)
 	SET_HARDFLOAT
 	EX	lw t1, SC32_FPC_CSR(a0)
 
+#ifndef CONFIG_CPU_MIPS64_R6
 	mfc0	t0, CP0_STATUS
 	sll	t0, t0, 5
 	bgez	t0, 1f			# skip loading odd if FR=0
 	 nop
+#endif
 
 	EX      ldc1 $f1, SC32_FPREGS+8(a0)
 	EX      ldc1 $f3, SC32_FPREGS+24(a0)
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 33/67] MIPS: kernel: genex: Set correct ISA level
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

The jr instruction opcode has changed in R6 so make sure
the correct ISA level is set prior using that instruction.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/genex.S | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index a5e26dd90592..2ebaabe3af15 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -125,7 +125,7 @@ LEAF(__r4k_wait)
 	nop
 	nop
 #endif
-	.set	arch=r4000
+	.set	MIPS_ISA_ARCH_LEVEL_RAW
 	wait
 	/* end of rollback region (the region size must be power of two) */
 1:
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 33/67] MIPS: kernel: genex: Set correct ISA level
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

The jr instruction opcode has changed in R6 so make sure
the correct ISA level is set prior using that instruction.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/genex.S | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index a5e26dd90592..2ebaabe3af15 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -125,7 +125,7 @@ LEAF(__r4k_wait)
 	nop
 	nop
 #endif
-	.set	arch=r4000
+	.set	MIPS_ISA_ARCH_LEVEL_RAW
 	wait
 	/* end of rollback region (the region size must be power of two) */
 1:
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 34/67] MIPS: kernel: cps-vec: Replace addi with addiu
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Paul Burton

MIPS R6 removed the addi instruction so we replace it with addiu.

Cc: Paul Burton <paul.burton@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/cps-vec.S | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/arch/mips/kernel/cps-vec.S b/arch/mips/kernel/cps-vec.S
index 0384b05ab5a0..55b759a0019e 100644
--- a/arch/mips/kernel/cps-vec.S
+++ b/arch/mips/kernel/cps-vec.S
@@ -99,11 +99,11 @@ not_nmi:
 	xori	t2, t1, 0x7
 	beqz	t2, 1f
 	 li	t3, 32
-	addi	t1, t1, 1
+	addiu	t1, t1, 1
 	sllv	t1, t3, t1
 1:	/* At this point t1 == I-cache sets per way */
 	_EXT	t2, v0, MIPS_CONF1_IA_SHF, MIPS_CONF1_IA_SZ
-	addi	t2, t2, 1
+	addiu	t2, t2, 1
 	mul	t1, t1, t0
 	mul	t1, t1, t2
 
@@ -126,11 +126,11 @@ icache_done:
 	xori	t2, t1, 0x7
 	beqz	t2, 1f
 	 li	t3, 32
-	addi	t1, t1, 1
+	addiu	t1, t1, 1
 	sllv	t1, t3, t1
 1:	/* At this point t1 == D-cache sets per way */
 	_EXT	t2, v0, MIPS_CONF1_DA_SHF, MIPS_CONF1_DA_SZ
-	addi	t2, t2, 1
+	addiu	t2, t2, 1
 	mul	t1, t1, t0
 	mul	t1, t1, t2
 
@@ -250,7 +250,7 @@ LEAF(mips_cps_core_init)
 	mfc0	t0, CP0_MVPCONF0
 	srl	t0, t0, MVPCONF0_PVPE_SHIFT
 	andi	t0, t0, (MVPCONF0_PVPE >> MVPCONF0_PVPE_SHIFT)
-	addi	t7, t0, 1
+	addiu	t7, t0, 1
 
 	/* If there's only 1, we're done */
 	beqz	t0, 2f
@@ -280,7 +280,7 @@ LEAF(mips_cps_core_init)
 	mttc0	t0, CP0_TCHALT
 
 	/* Next VPE */
-	addi	t5, t5, 1
+	addiu	t5, t5, 1
 	slt	t0, t5, t7
 	bnez	t0, 1b
 	 nop
@@ -317,7 +317,7 @@ LEAF(mips_cps_boot_vpes)
 	mfc0	t1, CP0_MVPCONF0
 	srl	t1, t1, MVPCONF0_PVPE_SHIFT
 	andi	t1, t1, MVPCONF0_PVPE >> MVPCONF0_PVPE_SHIFT
-	addi	t1, t1, 1
+	addiu	t1, t1, 1
 
 	/* Calculate a mask for the VPE ID from EBase.CPUNum */
 	clz	t1, t1
@@ -424,7 +424,7 @@ LEAF(mips_cps_boot_vpes)
 
 	/* Next VPE */
 2:	srl	t6, t6, 1
-	addi	t5, t5, 1
+	addiu	t5, t5, 1
 	bnez	t6, 1b
 	 nop
 
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 34/67] MIPS: kernel: cps-vec: Replace addi with addiu
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Paul Burton

MIPS R6 removed the addi instruction so we replace it with addiu.

Cc: Paul Burton <paul.burton@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/cps-vec.S | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/arch/mips/kernel/cps-vec.S b/arch/mips/kernel/cps-vec.S
index 0384b05ab5a0..55b759a0019e 100644
--- a/arch/mips/kernel/cps-vec.S
+++ b/arch/mips/kernel/cps-vec.S
@@ -99,11 +99,11 @@ not_nmi:
 	xori	t2, t1, 0x7
 	beqz	t2, 1f
 	 li	t3, 32
-	addi	t1, t1, 1
+	addiu	t1, t1, 1
 	sllv	t1, t3, t1
 1:	/* At this point t1 == I-cache sets per way */
 	_EXT	t2, v0, MIPS_CONF1_IA_SHF, MIPS_CONF1_IA_SZ
-	addi	t2, t2, 1
+	addiu	t2, t2, 1
 	mul	t1, t1, t0
 	mul	t1, t1, t2
 
@@ -126,11 +126,11 @@ icache_done:
 	xori	t2, t1, 0x7
 	beqz	t2, 1f
 	 li	t3, 32
-	addi	t1, t1, 1
+	addiu	t1, t1, 1
 	sllv	t1, t3, t1
 1:	/* At this point t1 == D-cache sets per way */
 	_EXT	t2, v0, MIPS_CONF1_DA_SHF, MIPS_CONF1_DA_SZ
-	addi	t2, t2, 1
+	addiu	t2, t2, 1
 	mul	t1, t1, t0
 	mul	t1, t1, t2
 
@@ -250,7 +250,7 @@ LEAF(mips_cps_core_init)
 	mfc0	t0, CP0_MVPCONF0
 	srl	t0, t0, MVPCONF0_PVPE_SHIFT
 	andi	t0, t0, (MVPCONF0_PVPE >> MVPCONF0_PVPE_SHIFT)
-	addi	t7, t0, 1
+	addiu	t7, t0, 1
 
 	/* If there's only 1, we're done */
 	beqz	t0, 2f
@@ -280,7 +280,7 @@ LEAF(mips_cps_core_init)
 	mttc0	t0, CP0_TCHALT
 
 	/* Next VPE */
-	addi	t5, t5, 1
+	addiu	t5, t5, 1
 	slt	t0, t5, t7
 	bnez	t0, 1b
 	 nop
@@ -317,7 +317,7 @@ LEAF(mips_cps_boot_vpes)
 	mfc0	t1, CP0_MVPCONF0
 	srl	t1, t1, MVPCONF0_PVPE_SHIFT
 	andi	t1, t1, MVPCONF0_PVPE >> MVPCONF0_PVPE_SHIFT
-	addi	t1, t1, 1
+	addiu	t1, t1, 1
 
 	/* Calculate a mask for the VPE ID from EBase.CPUNum */
 	clz	t1, t1
@@ -424,7 +424,7 @@ LEAF(mips_cps_boot_vpes)
 
 	/* Next VPE */
 2:	srl	t6, t6, 1
-	addi	t5, t5, 1
+	addiu	t5, t5, 1
 	bnez	t6, 1b
 	 nop
 
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 35/67] MIPS: uapi: inst: Add new opcodes for COP2 instructions
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 redefined the opcodes for LWC2, SWC2, LDC2 and SDC2
so add the new ones for R6.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/uapi/asm/inst.h | 16 ++++++++++++----
 arch/mips/kernel/branch.c         |  8 ++++----
 arch/mips/kernel/kprobes.c        |  8 ++++----
 arch/mips/kernel/unaligned.c      |  8 ++++----
 arch/mips/math-emu/cp1emu.c       |  8 ++++----
 arch/mips/mm/uasm-mips.c          |  4 ++--
 6 files changed, 30 insertions(+), 22 deletions(-)

diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h
index c330de057558..b7aa4c788983 100644
--- a/arch/mips/include/uapi/asm/inst.h
+++ b/arch/mips/include/uapi/asm/inst.h
@@ -31,10 +31,10 @@ enum major_op {
 	lbu_op, lhu_op, lwr_op, lwu_op,
 	sb_op, sh_op, swl_op, sw_op,
 	sdl_op, sdr_op, swr_op, cache_op,
-	ll_op, lwc1_op, lwc2_op, pref_op,
-	lld_op, ldc1_op, ldc2_op, ld_op,
-	sc_op, swc1_op, swc2_op, major_3b_op,
-	scd_op, sdc1_op, sdc2_op, sd_op
+	ll_op, lwc1_op, lwc2_or_bc_op, pref_op,
+	lld_op, ldc1_op, ldc2_or_bzcjic_op, ld_op,
+	sc_op, swc1_op, swc2_or_balc_op, major_3b_op,
+	scd_op, sdc1_op, sdc2_or_bnzcjialc_op, sd_op
 };
 
 /*
@@ -188,6 +188,14 @@ enum cop1x_func {
 };
 
 /*
+ * minor opcode for cop2 instructions (R6)
+ */
+enum cop2r6_minor_op {
+	lwc2r6_op    = 0x0a, swc2r6_op     = 0x0b,
+	ldc2r6_op    = 0x0e, sdc2r6_op     = 0x0f
+};
+
+/*
  * func field for mad opcodes (MIPS IV).
  */
 enum mad_func {
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 4d7d99d601cc..b7dd0926e87f 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -595,7 +595,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 		}
 		break;
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
-	case lwc2_op: /* This is bbit0 on Octeon */
+	case lwc2_or_bc_op: /* This is bbit0 on Octeon */
 		if ((regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt))
 		     == 0)
 			epc = epc + 4 + (insn.i_format.simmediate << 2);
@@ -603,7 +603,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 			epc += 8;
 		regs->cp0_epc = epc;
 		break;
-	case ldc2_op: /* This is bbit032 on Octeon */
+	case ldc2_or_bzcjic_op: /* This is bbit032 on Octeon */
 		if ((regs->regs[insn.i_format.rs] &
 		    (1ull<<(insn.i_format.rt+32))) == 0)
 			epc = epc + 4 + (insn.i_format.simmediate << 2);
@@ -611,14 +611,14 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 			epc += 8;
 		regs->cp0_epc = epc;
 		break;
-	case swc2_op: /* This is bbit1 on Octeon */
+	case swc2_or_balc_op: /* This is bbit1 on Octeon */
 		if (regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt))
 			epc = epc + 4 + (insn.i_format.simmediate << 2);
 		else
 			epc += 8;
 		regs->cp0_epc = epc;
 		break;
-	case sdc2_op: /* This is bbit132 on Octeon */
+	case sdc2_or_bnzcjialc_op: /* This is bbit132 on Octeon */
 		if (regs->regs[insn.i_format.rs] &
 		    (1ull<<(insn.i_format.rt+32)))
 			epc = epc + 4 + (insn.i_format.simmediate << 2);
diff --git a/arch/mips/kernel/kprobes.c b/arch/mips/kernel/kprobes.c
index 212f46f2014e..c12d50b241fa 100644
--- a/arch/mips/kernel/kprobes.c
+++ b/arch/mips/kernel/kprobes.c
@@ -101,10 +101,10 @@ static int __kprobes insn_has_delayslot(union mips_instruction insn)
 	case cop1_op:
 
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
-	case lwc2_op: /* This is bbit0 on Octeon */
-	case ldc2_op: /* This is bbit032 on Octeon */
-	case swc2_op: /* This is bbit1 on Octeon */
-	case sdc2_op: /* This is bbit132 on Octeon */
+	case lwc2_or_bc_op: /* This is bbit0 on Octeon */
+	case ldc2_or_bzcjic_op: /* This is bbit032 on Octeon */
+	case swc2_or_balc_op: /* This is bbit1 on Octeon */
+	case sdc2_or_bnzcjialc_op: /* This is bbit132 on Octeon */
 #endif
 		return 1;
 	default:
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
index e11906dff885..3665905cbbe2 100644
--- a/arch/mips/kernel/unaligned.c
+++ b/arch/mips/kernel/unaligned.c
@@ -708,19 +708,19 @@ static void emulate_load_store_insn(struct pt_regs *regs,
 	 * It's up to applications to register a notifier chain and do
 	 * whatever they have to do, including possible sending of signals.
 	 */
-	case lwc2_op:
+	case lwc2_or_bc_op:
 		cu2_notifier_call_chain(CU2_LWC2_OP, regs);
 		break;
 
-	case ldc2_op:
+	case ldc2_or_bzcjic_op:
 		cu2_notifier_call_chain(CU2_LDC2_OP, regs);
 		break;
 
-	case swc2_op:
+	case swc2_or_balc_op:
 		cu2_notifier_call_chain(CU2_SWC2_OP, regs);
 		break;
 
-	case sdc2_op:
+	case sdc2_or_bnzcjialc_op:
 		cu2_notifier_call_chain(CU2_SDC2_OP, regs);
 		break;
 
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index cac529a405b8..a426c176ee54 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -552,25 +552,25 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 				dec_insn.next_pc_inc;
 		return 1;
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
-	case lwc2_op: /* This is bbit0 on Octeon */
+	case lwc2_or_bc_op: /* This is bbit0 on Octeon */
 		if ((regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt)) == 0)
 			*contpc = regs->cp0_epc + 4 + (insn.i_format.simmediate << 2);
 		else
 			*contpc = regs->cp0_epc + 8;
 		return 1;
-	case ldc2_op: /* This is bbit032 on Octeon */
+	case ldc2_or_bzcjic_op: /* This is bbit032 on Octeon */
 		if ((regs->regs[insn.i_format.rs] & (1ull<<(insn.i_format.rt + 32))) == 0)
 			*contpc = regs->cp0_epc + 4 + (insn.i_format.simmediate << 2);
 		else
 			*contpc = regs->cp0_epc + 8;
 		return 1;
-	case swc2_op: /* This is bbit1 on Octeon */
+	case swc2_balc_op: /* This is bbit1 on Octeon */
 		if (regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt))
 			*contpc = regs->cp0_epc + 4 + (insn.i_format.simmediate << 2);
 		else
 			*contpc = regs->cp0_epc + 8;
 		return 1;
-	case sdc2_op: /* This is bbit132 on Octeon */
+	case sdc2_bnzcjialc_op: /* This is bbit132 on Octeon */
 		if (regs->regs[insn.i_format.rs] & (1ull<<(insn.i_format.rt + 32)))
 			*contpc = regs->cp0_epc + 4 + (insn.i_format.simmediate << 2);
 		else
diff --git a/arch/mips/mm/uasm-mips.c b/arch/mips/mm/uasm-mips.c
index c1fb8bdfb06d..97b0a5c80360 100644
--- a/arch/mips/mm/uasm-mips.c
+++ b/arch/mips/mm/uasm-mips.c
@@ -61,8 +61,8 @@ static struct insn insn_table[] = {
 	{ insn_addu, M(spec_op, 0, 0, 0, 0, addu_op), RS | RT | RD },
 	{ insn_andi, M(andi_op, 0, 0, 0, 0, 0), RS | RT | UIMM },
 	{ insn_and, M(spec_op, 0, 0, 0, 0, and_op), RS | RT | RD },
-	{ insn_bbit0, M(lwc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
-	{ insn_bbit1, M(swc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
+	{ insn_bbit0, M(lwc2_or_bc_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
+	{ insn_bbit1, M(swc2_or_balc_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
 	{ insn_beql, M(beql_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
 	{ insn_beq, M(beq_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
 	{ insn_bgezl, M(bcond_op, 0, bgezl_op, 0, 0, 0), RS | BIMM },
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 35/67] MIPS: uapi: inst: Add new opcodes for COP2 instructions
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 redefined the opcodes for LWC2, SWC2, LDC2 and SDC2
so add the new ones for R6.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/uapi/asm/inst.h | 16 ++++++++++++----
 arch/mips/kernel/branch.c         |  8 ++++----
 arch/mips/kernel/kprobes.c        |  8 ++++----
 arch/mips/kernel/unaligned.c      |  8 ++++----
 arch/mips/math-emu/cp1emu.c       |  8 ++++----
 arch/mips/mm/uasm-mips.c          |  4 ++--
 6 files changed, 30 insertions(+), 22 deletions(-)

diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h
index c330de057558..b7aa4c788983 100644
--- a/arch/mips/include/uapi/asm/inst.h
+++ b/arch/mips/include/uapi/asm/inst.h
@@ -31,10 +31,10 @@ enum major_op {
 	lbu_op, lhu_op, lwr_op, lwu_op,
 	sb_op, sh_op, swl_op, sw_op,
 	sdl_op, sdr_op, swr_op, cache_op,
-	ll_op, lwc1_op, lwc2_op, pref_op,
-	lld_op, ldc1_op, ldc2_op, ld_op,
-	sc_op, swc1_op, swc2_op, major_3b_op,
-	scd_op, sdc1_op, sdc2_op, sd_op
+	ll_op, lwc1_op, lwc2_or_bc_op, pref_op,
+	lld_op, ldc1_op, ldc2_or_bzcjic_op, ld_op,
+	sc_op, swc1_op, swc2_or_balc_op, major_3b_op,
+	scd_op, sdc1_op, sdc2_or_bnzcjialc_op, sd_op
 };
 
 /*
@@ -188,6 +188,14 @@ enum cop1x_func {
 };
 
 /*
+ * minor opcode for cop2 instructions (R6)
+ */
+enum cop2r6_minor_op {
+	lwc2r6_op    = 0x0a, swc2r6_op     = 0x0b,
+	ldc2r6_op    = 0x0e, sdc2r6_op     = 0x0f
+};
+
+/*
  * func field for mad opcodes (MIPS IV).
  */
 enum mad_func {
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 4d7d99d601cc..b7dd0926e87f 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -595,7 +595,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 		}
 		break;
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
-	case lwc2_op: /* This is bbit0 on Octeon */
+	case lwc2_or_bc_op: /* This is bbit0 on Octeon */
 		if ((regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt))
 		     == 0)
 			epc = epc + 4 + (insn.i_format.simmediate << 2);
@@ -603,7 +603,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 			epc += 8;
 		regs->cp0_epc = epc;
 		break;
-	case ldc2_op: /* This is bbit032 on Octeon */
+	case ldc2_or_bzcjic_op: /* This is bbit032 on Octeon */
 		if ((regs->regs[insn.i_format.rs] &
 		    (1ull<<(insn.i_format.rt+32))) == 0)
 			epc = epc + 4 + (insn.i_format.simmediate << 2);
@@ -611,14 +611,14 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 			epc += 8;
 		regs->cp0_epc = epc;
 		break;
-	case swc2_op: /* This is bbit1 on Octeon */
+	case swc2_or_balc_op: /* This is bbit1 on Octeon */
 		if (regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt))
 			epc = epc + 4 + (insn.i_format.simmediate << 2);
 		else
 			epc += 8;
 		regs->cp0_epc = epc;
 		break;
-	case sdc2_op: /* This is bbit132 on Octeon */
+	case sdc2_or_bnzcjialc_op: /* This is bbit132 on Octeon */
 		if (regs->regs[insn.i_format.rs] &
 		    (1ull<<(insn.i_format.rt+32)))
 			epc = epc + 4 + (insn.i_format.simmediate << 2);
diff --git a/arch/mips/kernel/kprobes.c b/arch/mips/kernel/kprobes.c
index 212f46f2014e..c12d50b241fa 100644
--- a/arch/mips/kernel/kprobes.c
+++ b/arch/mips/kernel/kprobes.c
@@ -101,10 +101,10 @@ static int __kprobes insn_has_delayslot(union mips_instruction insn)
 	case cop1_op:
 
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
-	case lwc2_op: /* This is bbit0 on Octeon */
-	case ldc2_op: /* This is bbit032 on Octeon */
-	case swc2_op: /* This is bbit1 on Octeon */
-	case sdc2_op: /* This is bbit132 on Octeon */
+	case lwc2_or_bc_op: /* This is bbit0 on Octeon */
+	case ldc2_or_bzcjic_op: /* This is bbit032 on Octeon */
+	case swc2_or_balc_op: /* This is bbit1 on Octeon */
+	case sdc2_or_bnzcjialc_op: /* This is bbit132 on Octeon */
 #endif
 		return 1;
 	default:
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
index e11906dff885..3665905cbbe2 100644
--- a/arch/mips/kernel/unaligned.c
+++ b/arch/mips/kernel/unaligned.c
@@ -708,19 +708,19 @@ static void emulate_load_store_insn(struct pt_regs *regs,
 	 * It's up to applications to register a notifier chain and do
 	 * whatever they have to do, including possible sending of signals.
 	 */
-	case lwc2_op:
+	case lwc2_or_bc_op:
 		cu2_notifier_call_chain(CU2_LWC2_OP, regs);
 		break;
 
-	case ldc2_op:
+	case ldc2_or_bzcjic_op:
 		cu2_notifier_call_chain(CU2_LDC2_OP, regs);
 		break;
 
-	case swc2_op:
+	case swc2_or_balc_op:
 		cu2_notifier_call_chain(CU2_SWC2_OP, regs);
 		break;
 
-	case sdc2_op:
+	case sdc2_or_bnzcjialc_op:
 		cu2_notifier_call_chain(CU2_SDC2_OP, regs);
 		break;
 
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index cac529a405b8..a426c176ee54 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -552,25 +552,25 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 				dec_insn.next_pc_inc;
 		return 1;
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
-	case lwc2_op: /* This is bbit0 on Octeon */
+	case lwc2_or_bc_op: /* This is bbit0 on Octeon */
 		if ((regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt)) == 0)
 			*contpc = regs->cp0_epc + 4 + (insn.i_format.simmediate << 2);
 		else
 			*contpc = regs->cp0_epc + 8;
 		return 1;
-	case ldc2_op: /* This is bbit032 on Octeon */
+	case ldc2_or_bzcjic_op: /* This is bbit032 on Octeon */
 		if ((regs->regs[insn.i_format.rs] & (1ull<<(insn.i_format.rt + 32))) == 0)
 			*contpc = regs->cp0_epc + 4 + (insn.i_format.simmediate << 2);
 		else
 			*contpc = regs->cp0_epc + 8;
 		return 1;
-	case swc2_op: /* This is bbit1 on Octeon */
+	case swc2_balc_op: /* This is bbit1 on Octeon */
 		if (regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt))
 			*contpc = regs->cp0_epc + 4 + (insn.i_format.simmediate << 2);
 		else
 			*contpc = regs->cp0_epc + 8;
 		return 1;
-	case sdc2_op: /* This is bbit132 on Octeon */
+	case sdc2_bnzcjialc_op: /* This is bbit132 on Octeon */
 		if (regs->regs[insn.i_format.rs] & (1ull<<(insn.i_format.rt + 32)))
 			*contpc = regs->cp0_epc + 4 + (insn.i_format.simmediate << 2);
 		else
diff --git a/arch/mips/mm/uasm-mips.c b/arch/mips/mm/uasm-mips.c
index c1fb8bdfb06d..97b0a5c80360 100644
--- a/arch/mips/mm/uasm-mips.c
+++ b/arch/mips/mm/uasm-mips.c
@@ -61,8 +61,8 @@ static struct insn insn_table[] = {
 	{ insn_addu, M(spec_op, 0, 0, 0, 0, addu_op), RS | RT | RD },
 	{ insn_andi, M(andi_op, 0, 0, 0, 0, 0), RS | RT | UIMM },
 	{ insn_and, M(spec_op, 0, 0, 0, 0, and_op), RS | RT | RD },
-	{ insn_bbit0, M(lwc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
-	{ insn_bbit1, M(swc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
+	{ insn_bbit0, M(lwc2_or_bc_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
+	{ insn_bbit1, M(swc2_or_balc_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
 	{ insn_beql, M(beql_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
 	{ insn_beq, M(beq_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
 	{ insn_bgezl, M(bcond_op, 0, bgezl_op, 0, 0, 0), RS | BIMM },
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 36/67] MIPS: kernel: unaligned: Add support for the MIPS R6
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

The load/store unaligned instructions have been removed in MIPS R6
so we need to re-implement the related macros using the regular
load/store instructions. Moreover, the load/store from coprocessor 2
instructions have been reallocated in Release 6 so we will handle them
in the emulator instead.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/unaligned.c | 390 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 386 insertions(+), 4 deletions(-)

diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
index 3665905cbbe2..039ada90ed69 100644
--- a/arch/mips/kernel/unaligned.c
+++ b/arch/mips/kernel/unaligned.c
@@ -129,6 +129,7 @@ extern void show_registers(struct pt_regs *regs);
 			: "=&r" (value), "=r" (res)         \
 			: "r" (addr), "i" (-EFAULT));
 
+#ifndef CONFIG_CPU_MIPSR6
 #define     LoadW(addr, value, res)   \
 		__asm__ __volatile__ (                      \
 			"1:\t"user_lwl("%0", "(%2)")"\n"    \
@@ -146,6 +147,39 @@ extern void show_registers(struct pt_regs *regs);
 			".previous"                         \
 			: "=&r" (value), "=r" (res)         \
 			: "r" (addr), "i" (-EFAULT));
+#else
+/* MIPSR6 has no lwl instruction */
+#define     LoadW(addr, value, res) \
+		__asm__ __volatile__ (			    \
+			".set\tpush\n"			    \
+			".set\tnoat\n\t"		    \
+			"1:"user_lb("%0", "0(%2)")"\n\t"    \
+			"2:"user_lbu("$1", "1(%2)")"\n\t"   \
+			"sll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"3:"user_lbu("$1", "2(%2)")"\n\t"   \
+			"sll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"4:"user_lbu("$1", "3(%2)")"\n\t"   \
+			"sll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"li\t%1, 0\n"			    \
+			".set\tpop\n"			    \
+			"10:\n\t"			    \
+			".insn\n\t"			    \
+			".section\t.fixup,\"ax\"\n\t"	    \
+			"11:\tli\t%1, %3\n\t"		    \
+			"j\t10b\n\t"			    \
+			".previous\n\t"			    \
+			".section\t__ex_table,\"a\"\n\t"    \
+			STR(PTR)"\t1b, 11b\n\t"		    \
+			STR(PTR)"\t2b, 11b\n\t"		    \
+			STR(PTR)"\t3b, 11b\n\t"		    \
+			STR(PTR)"\t4b, 11b\n\t"		    \
+			".previous"			    \
+			: "=&r" (value), "=r" (res)	    \
+			: "r" (addr), "i" (-EFAULT));
+#endif /* CONFIG_MIPS_R6 */
 
 #define     LoadHWU(addr, value, res) \
 		__asm__ __volatile__ (                      \
@@ -169,6 +203,7 @@ extern void show_registers(struct pt_regs *regs);
 			: "=&r" (value), "=r" (res)         \
 			: "r" (addr), "i" (-EFAULT));
 
+#ifndef CONFIG_CPU_MIPSR6
 #define     LoadWU(addr, value, res)  \
 		__asm__ __volatile__ (                      \
 			"1:\t"user_lwl("%0", "(%2)")"\n"    \
@@ -206,6 +241,87 @@ extern void show_registers(struct pt_regs *regs);
 			".previous"                         \
 			: "=&r" (value), "=r" (res)         \
 			: "r" (addr), "i" (-EFAULT));
+#else
+/* MIPSR6 has not lwl and ldl instructions */
+#define	    LoadWU(addr, value, res) \
+		__asm__ __volatile__ (			    \
+			".set\tpush\n\t"		    \
+			".set\tnoat\n\t"		    \
+			"1:"user_lbu("%0", "0(%2)")"\n\t"   \
+			"2:"user_lbu("$1", "1(%2)")"\n\t"   \
+			"sll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"3:"user_lbu("$1", "2(%2)")"\n\t"   \
+			"sll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"4:"user_lbu("$1", "3(%2)")"\n\t"   \
+			"sll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"li\t%1, 0\n"			    \
+			".set\tpop\n"			    \
+			"10:\n\t"			    \
+			".insn\n\t"			    \
+			".section\t.fixup,\"ax\"\n\t"	    \
+			"11:\tli\t%1, %3\n\t"		    \
+			"j\t10b\n\t"			    \
+			".previous\n\t"			    \
+			".section\t__ex_table,\"a\"\n\t"    \
+			STR(PTR)"\t1b, 11b\n\t"		    \
+			STR(PTR)"\t2b, 11b\n\t"		    \
+			STR(PTR)"\t3b, 11b\n\t"		    \
+			STR(PTR)"\t4b, 11b\n\t"		    \
+			".previous"			    \
+			: "=&r" (value), "=r" (res)	    \
+			: "r" (addr), "i" (-EFAULT));
+
+#define     LoadDW(addr, value, res)  \
+		__asm__ __volatile__ (			    \
+			".set\tpush\n\t"		    \
+			".set\tnoat\n\t"		    \
+			"1:lb\t%0, 0(%2)\n\t"    	    \
+			"2:lbu\t $1, 1(%2)\n\t"   	    \
+			"dsll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"3:lbu\t$1, 2(%2)\n\t"   	    \
+			"dsll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"4:lbu\t$1, 3(%2)\n\t"   	    \
+			"dsll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"5:lbu\t$1, 4(%2)\n\t"   	    \
+			"dsll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"6:lbu\t$1, 5(%2)\n\t"   	    \
+			"dsll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"7:lbu\t$1, 6(%2)\n\t"   	    \
+			"dsll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"8:lbu\t$1, 7(%2)\n\t"   	    \
+			"dsll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"li\t%1, 0\n"			    \
+			".set\tpop\n\t"			    \
+			"10:\n\t"			    \
+			".insn\n\t"			    \
+			".section\t.fixup,\"ax\"\n\t"	    \
+			"11:\tli\t%1, %3\n\t"		    \
+			"j\t10b\n\t"			    \
+			".previous\n\t"			    \
+			".section\t__ex_table,\"a\"\n\t"    \
+			STR(PTR)"\t1b, 11b\n\t"		    \
+			STR(PTR)"\t2b, 11b\n\t"		    \
+			STR(PTR)"\t3b, 11b\n\t"		    \
+			STR(PTR)"\t4b, 11b\n\t"		    \
+			STR(PTR)"\t5b, 11b\n\t"		    \
+			STR(PTR)"\t6b, 11b\n\t"		    \
+			STR(PTR)"\t7b, 11b\n\t"		    \
+			STR(PTR)"\t8b, 11b\n\t"		    \
+			".previous"			    \
+			: "=&r" (value), "=r" (res)	    \
+			: "r" (addr), "i" (-EFAULT));
+#endif /* CONFIG_CPU_MIPSR6 */
+
 
 #define     StoreHW(addr, value, res) \
 		__asm__ __volatile__ (                      \
@@ -228,6 +344,7 @@ extern void show_registers(struct pt_regs *regs);
 			: "=r" (res)                        \
 			: "r" (value), "r" (addr), "i" (-EFAULT));
 
+#ifndef CONFIG_CPU_MIPSR6
 #define     StoreW(addr, value, res)  \
 		__asm__ __volatile__ (                      \
 			"1:\t"user_swl("%1", "(%2)")"\n"    \
@@ -263,9 +380,82 @@ extern void show_registers(struct pt_regs *regs);
 			".previous"                         \
 		: "=r" (res)                                \
 		: "r" (value), "r" (addr), "i" (-EFAULT));
-#endif
+#else
+/* MIPSR6 has no swl and sdl instructions */
+#define     StoreW(addr, value, res)  \
+		__asm__ __volatile__ (                      \
+			".set\tpush\n\t"		    \
+			".set\tnoat\n\t"		    \
+			"1:"user_sb("%1", "3(%2)")"\n\t"    \
+			"srl\t$1, %1, 0x8\n\t"		    \
+			"2:"user_sb("$1", "2(%2)")"\n\t"    \
+			"srl\t$1, $1,  0x8\n\t"		    \
+			"3:"user_sb("$1", "1(%2)")"\n\t"    \
+			"srl\t$1, $1, 0x8\n\t"		    \
+			"4:"user_sb("$1", "0(%2)")"\n\t"    \
+			".set\tpop\n\t"			    \
+			"li\t%0, 0\n"			    \
+			"10:\n\t"			    \
+			".insn\n\t"			    \
+			".section\t.fixup,\"ax\"\n\t"	    \
+			"11:\tli\t%0, %3\n\t"		    \
+			"j\t10b\n\t"			    \
+			".previous\n\t"			    \
+			".section\t__ex_table,\"a\"\n\t"    \
+			STR(PTR)"\t1b, 11b\n\t"		    \
+			STR(PTR)"\t2b, 11b\n\t"		    \
+			STR(PTR)"\t3b, 11b\n\t"		    \
+			STR(PTR)"\t4b, 11b\n\t"		    \
+			".previous"			    \
+		: "=&r" (res)			    	    \
+		: "r" (value), "r" (addr), "i" (-EFAULT)    \
+		: "memory");
+
+#define     StoreDW(addr, value, res) \
+		__asm__ __volatile__ (                      \
+			".set\tpush\n\t"		    \
+			".set\tnoat\n\t"		    \
+			"1:sb\t%1, 7(%2)\n\t"    	    \
+			"dsrl\t$1, %1, 0x8\n\t"		    \
+			"2:sb\t$1, 6(%2)\n\t"    	    \
+			"dsrl\t$1, $1, 0x8\n\t"		    \
+			"3:sb\t$1, 5(%2)\n\t"    	    \
+			"dsrl\t$1, $1, 0x8\n\t"		    \
+			"4:sb\t$1, 4(%2)\n\t"    	    \
+			"dsrl\t$1, $1, 0x8\n\t"		    \
+			"5:sb\t$1, 3(%2)\n\t"    	    \
+			"dsrl\t$1, $1, 0x8\n\t"		    \
+			"6:sb\t$1, 2(%2)\n\t"    	    \
+			"dsrl\t$1, $1, 0x8\n\t"		    \
+			"7:sb\t$1, 1(%2)\n\t"    	    \
+			"dsrl\t$1, $1, 0x8\n\t"		    \
+			"8:sb\t$1, 0(%2)\n\t"    	    \
+			"dsrl\t$1, $1, 0x8\n\t"		    \
+			".set\tpop\n\t"			    \
+			"li\t%0, 0\n"			    \
+			"10:\n\t"			    \
+			".insn\n\t"			    \
+			".section\t.fixup,\"ax\"\n\t"	    \
+			"11:\tli\t%0, %3\n\t"		    \
+			"j\t10b\n\t"			    \
+			".previous\n\t"			    \
+			".section\t__ex_table,\"a\"\n\t"    \
+			STR(PTR)"\t1b, 11b\n\t"		    \
+			STR(PTR)"\t2b, 11b\n\t"		    \
+			STR(PTR)"\t3b, 11b\n\t"		    \
+			STR(PTR)"\t4b, 11b\n\t"		    \
+			STR(PTR)"\t5b, 11b\n\t"		    \
+			STR(PTR)"\t6b, 11b\n\t"		    \
+			STR(PTR)"\t7b, 11b\n\t"		    \
+			STR(PTR)"\t8b, 11b\n\t"		    \
+			".previous"			    \
+		: "=&r" (res)			    	    \
+		: "r" (value), "r" (addr), "i" (-EFAULT)    \
+		: "memory");
+#endif /* CONFIG_CPU_MIPSR6 */
+
+#else /* __BIG_ENDIAN */
 
-#ifdef __LITTLE_ENDIAN
 #define     LoadHW(addr, value, res)  \
 		__asm__ __volatile__ (".set\tnoat\n"        \
 			"1:\t"user_lb("%0", "1(%2)")"\n"    \
@@ -286,6 +476,7 @@ extern void show_registers(struct pt_regs *regs);
 			: "=&r" (value), "=r" (res)         \
 			: "r" (addr), "i" (-EFAULT));
 
+#ifndef CONFIG_CPU_MIPSR6
 #define     LoadW(addr, value, res)   \
 		__asm__ __volatile__ (                      \
 			"1:\t"user_lwl("%0", "3(%2)")"\n"   \
@@ -303,6 +494,40 @@ extern void show_registers(struct pt_regs *regs);
 			".previous"                         \
 			: "=&r" (value), "=r" (res)         \
 			: "r" (addr), "i" (-EFAULT));
+#else
+/* MIPSR6 has no lwl instruction */
+#define     LoadW(addr, value, res) \
+		__asm__ __volatile__ (			    \
+			".set\tpush\n"			    \
+			".set\tnoat\n\t"		    \
+			"1:"user_lb("%0", "3(%2)")"\n\t"    \
+			"2:"user_lbu("$1", "2(%2)")"\n\t"   \
+			"sll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"3:"user_lbu("$1", "1(%2)")"\n\t"   \
+			"sll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"4:"user_lbu("$1", "0(%2)")"\n\t"   \
+			"sll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"li\t%1, 0\n"			    \
+			".set\tpop\n"			    \
+			"10:\n\t"			    \
+			".insn\n\t"			    \
+			".section\t.fixup,\"ax\"\n\t"	    \
+			"11:\tli\t%1, %3\n\t"		    \
+			"j\t10b\n\t"			    \
+			".previous\n\t"			    \
+			".section\t__ex_table,\"a\"\n\t"    \
+			STR(PTR)"\t1b, 11b\n\t"		    \
+			STR(PTR)"\t2b, 11b\n\t"		    \
+			STR(PTR)"\t3b, 11b\n\t"		    \
+			STR(PTR)"\t4b, 11b\n\t"		    \
+			".previous"			    \
+			: "=&r" (value), "=r" (res)	    \
+			: "r" (addr), "i" (-EFAULT));
+#endif /* CONFIG_CPU_MIPSR6 */
+
 
 #define     LoadHWU(addr, value, res) \
 		__asm__ __volatile__ (                      \
@@ -326,6 +551,7 @@ extern void show_registers(struct pt_regs *regs);
 			: "=&r" (value), "=r" (res)         \
 			: "r" (addr), "i" (-EFAULT));
 
+#ifndef CONFIG_CPU_MIPSR6
 #define     LoadWU(addr, value, res)  \
 		__asm__ __volatile__ (                      \
 			"1:\t"user_lwl("%0", "3(%2)")"\n"   \
@@ -363,6 +589,86 @@ extern void show_registers(struct pt_regs *regs);
 			".previous"                         \
 			: "=&r" (value), "=r" (res)         \
 			: "r" (addr), "i" (-EFAULT));
+#else
+/* MIPSR6 has not lwl and ldl instructions */
+#define	    LoadWU(addr, value, res) \
+		__asm__ __volatile__ (			    \
+			".set\tpush\n\t"		    \
+			".set\tnoat\n\t"		    \
+			"1:"user_lbu("%0", "3(%2)")"\n\t"   \
+			"2:"user_lbu("$1", "2(%2)")"\n\t"   \
+			"sll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"3:"user_lbu("$1", "1(%2)")"\n\t"   \
+			"sll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"4:"user_lbu("$1", "0(%2)")"\n\t"   \
+			"sll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"li\t%1, 0\n"			    \
+			".set\tpop\n"			    \
+			"10:\n\t"			    \
+			".insn\n\t"			    \
+			".section\t.fixup,\"ax\"\n\t"	    \
+			"11:\tli\t%1, %3\n\t"		    \
+			"j\t10b\n\t"			    \
+			".previous\n\t"			    \
+			".section\t__ex_table,\"a\"\n\t"    \
+			STR(PTR)"\t1b, 11b\n\t"		    \
+			STR(PTR)"\t2b, 11b\n\t"		    \
+			STR(PTR)"\t3b, 11b\n\t"		    \
+			STR(PTR)"\t4b, 11b\n\t"		    \
+			".previous"			    \
+			: "=&r" (value), "=r" (res)	    \
+			: "r" (addr), "i" (-EFAULT));
+
+#define     LoadDW(addr, value, res)  \
+		__asm__ __volatile__ (			    \
+			".set\tpush\n\t"		    \
+			".set\tnoat\n\t"		    \
+			"1:lb\t%0, 7(%2)\n\t"    	    \
+			"2:lbu\t$1, 6(%2)\n\t"   	    \
+			"dsll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"3:lbu\t$1, 5(%2)\n\t"   	    \
+			"dsll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"4:lbu\t$1, 4(%2)\n\t"   	    \
+			"dsll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"5:lbu\t$1, 3(%2)\n\t"   	    \
+			"dsll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"6:lbu\t$1, 2(%2)\n\t"   	    \
+			"dsll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"7:lbu\t$1, 1(%2)\n\t"   	    \
+			"dsll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"8:lbu\t$1, 0(%2)\n\t"   	    \
+			"dsll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"li\t%1, 0\n"			    \
+			".set\tpop\n\t"			    \
+			"10:\n\t"			    \
+			".insn\n\t"			    \
+			".section\t.fixup,\"ax\"\n\t"	    \
+			"11:\tli\t%1, %3\n\t"		    \
+			"j\t10b\n\t"			    \
+			".previous\n\t"			    \
+			".section\t__ex_table,\"a\"\n\t"    \
+			STR(PTR)"\t1b, 11b\n\t"		    \
+			STR(PTR)"\t2b, 11b\n\t"		    \
+			STR(PTR)"\t3b, 11b\n\t"		    \
+			STR(PTR)"\t4b, 11b\n\t"		    \
+			STR(PTR)"\t5b, 11b\n\t"		    \
+			STR(PTR)"\t6b, 11b\n\t"		    \
+			STR(PTR)"\t7b, 11b\n\t"		    \
+			STR(PTR)"\t8b, 11b\n\t"		    \
+			".previous"			    \
+			: "=&r" (value), "=r" (res)	    \
+			: "r" (addr), "i" (-EFAULT));
+#endif /* CONFIG_CPU_MIPSR6 */
 
 #define     StoreHW(addr, value, res) \
 		__asm__ __volatile__ (                      \
@@ -384,7 +690,7 @@ extern void show_registers(struct pt_regs *regs);
 			".previous"                         \
 			: "=r" (res)                        \
 			: "r" (value), "r" (addr), "i" (-EFAULT));
-
+#ifndef CONFIG_CPU_MIPSR6
 #define     StoreW(addr, value, res)  \
 		__asm__ __volatile__ (                      \
 			"1:\t"user_swl("%1", "3(%2)")"\n"   \
@@ -420,6 +726,79 @@ extern void show_registers(struct pt_regs *regs);
 			".previous"                         \
 		: "=r" (res)                                \
 		: "r" (value), "r" (addr), "i" (-EFAULT));
+#else
+/* MIPSR6 has no swl and sdl instructions */
+#define     StoreW(addr, value, res)  \
+		__asm__ __volatile__ (                      \
+			".set\tpush\n\t"		    \
+			".set\tnoat\n\t"		    \
+			"1:"user_sb("%1", "0(%2)")"\n\t"    \
+			"srl\t$1, %1, 0x8\n\t"		    \
+			"2:"user_sb("$1", "1(%2)")"\n\t"    \
+			"srl\t$1, $1,  0x8\n\t"		    \
+			"3:"user_sb("$1", "2(%2)")"\n\t"    \
+			"srl\t$1, $1, 0x8\n\t"		    \
+			"4:"user_sb("$1", "3(%2)")"\n\t"    \
+			".set\tpop\n\t"			    \
+			"li\t%0, 0\n"			    \
+			"10:\n\t"			    \
+			".insn\n\t"			    \
+			".section\t.fixup,\"ax\"\n\t"	    \
+			"11:\tli\t%0, %3\n\t"		    \
+			"j\t10b\n\t"			    \
+			".previous\n\t"			    \
+			".section\t__ex_table,\"a\"\n\t"    \
+			STR(PTR)"\t1b, 11b\n\t"		    \
+			STR(PTR)"\t2b, 11b\n\t"		    \
+			STR(PTR)"\t3b, 11b\n\t"		    \
+			STR(PTR)"\t4b, 11b\n\t"		    \
+			".previous"			    \
+		: "=&r" (res)			    	    \
+		: "r" (value), "r" (addr), "i" (-EFAULT)    \
+		: "memory");
+
+#define     StoreDW(addr, value, res) \
+		__asm__ __volatile__ (                      \
+			".set\tpush\n\t"		    \
+			".set\tnoat\n\t"		    \
+			"1:sb\t%1, 0(%2)\n\t"    	    \
+			"dsrl\t$1, %1, 0x8\n\t"		    \
+			"2:sb\t$1, 1(%2)\n\t"    	    \
+			"dsrl\t$1, $1, 0x8\n\t"		    \
+			"3:sb\t$1, 2(%2)\n\t"    	    \
+			"dsrl\t$1, $1, 0x8\n\t"		    \
+			"4:sb\t$1, 3(%2)\n\t"    	    \
+			"dsrl\t$1, $1, 0x8\n\t"		    \
+			"5:sb\t$1, 4(%2)\n\t"    	    \
+			"dsrl\t$1, $1, 0x8\n\t"		    \
+			"6:sb\t$1, 5(%2)\n\t"    	    \
+			"dsrl\t$1, $1, 0x8\n\t"		    \
+			"7:sb\t$1, 6(%2)\n\t"    	    \
+			"dsrl\t$1, $1, 0x8\n\t"		    \
+			"8:sb\t$1, 7(%2)\n\t"    	    \
+			"dsrl\t$1, $1, 0x8\n\t"		    \
+			".set\tpop\n\t"			    \
+			"li\t%0, 0\n"			    \
+			"10:\n\t"			    \
+			".insn\n\t"			    \
+			".section\t.fixup,\"ax\"\n\t"	    \
+			"11:\tli\t%0, %3\n\t"		    \
+			"j\t10b\n\t"			    \
+			".previous\n\t"			    \
+			".section\t__ex_table,\"a\"\n\t"    \
+			STR(PTR)"\t1b, 11b\n\t"		    \
+			STR(PTR)"\t2b, 11b\n\t"		    \
+			STR(PTR)"\t3b, 11b\n\t"		    \
+			STR(PTR)"\t4b, 11b\n\t"		    \
+			STR(PTR)"\t5b, 11b\n\t"		    \
+			STR(PTR)"\t6b, 11b\n\t"		    \
+			STR(PTR)"\t7b, 11b\n\t"		    \
+			STR(PTR)"\t8b, 11b\n\t"		    \
+			".previous"			    \
+		: "=&r" (res)			    	    \
+		: "r" (value), "r" (addr), "i" (-EFAULT)    \
+		: "memory");
+#endif /* CONFIG_CPU_MIPSR6 */
 #endif
 
 static void emulate_load_store_insn(struct pt_regs *regs,
@@ -703,10 +1082,13 @@ static void emulate_load_store_insn(struct pt_regs *regs,
 			break;
 		return;
 
+#ifndef CONFIG_MIPS_R6
 	/*
 	 * COP2 is available to implementor for application specific use.
 	 * It's up to applications to register a notifier chain and do
 	 * whatever they have to do, including possible sending of signals.
+	 *
+	 * This instruction has been reallocated in Release 6
 	 */
 	case lwc2_or_bc_op:
 		cu2_notifier_call_chain(CU2_LWC2_OP, regs);
@@ -723,7 +1105,7 @@ static void emulate_load_store_insn(struct pt_regs *regs,
 	case sdc2_or_bnzcjialc_op:
 		cu2_notifier_call_chain(CU2_SDC2_OP, regs);
 		break;
-
+#endif
 	default:
 		/*
 		 * Pheeee...  We encountered an yet unknown instruction or
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 36/67] MIPS: kernel: unaligned: Add support for the MIPS R6
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

The load/store unaligned instructions have been removed in MIPS R6
so we need to re-implement the related macros using the regular
load/store instructions. Moreover, the load/store from coprocessor 2
instructions have been reallocated in Release 6 so we will handle them
in the emulator instead.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/unaligned.c | 390 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 386 insertions(+), 4 deletions(-)

diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
index 3665905cbbe2..039ada90ed69 100644
--- a/arch/mips/kernel/unaligned.c
+++ b/arch/mips/kernel/unaligned.c
@@ -129,6 +129,7 @@ extern void show_registers(struct pt_regs *regs);
 			: "=&r" (value), "=r" (res)         \
 			: "r" (addr), "i" (-EFAULT));
 
+#ifndef CONFIG_CPU_MIPSR6
 #define     LoadW(addr, value, res)   \
 		__asm__ __volatile__ (                      \
 			"1:\t"user_lwl("%0", "(%2)")"\n"    \
@@ -146,6 +147,39 @@ extern void show_registers(struct pt_regs *regs);
 			".previous"                         \
 			: "=&r" (value), "=r" (res)         \
 			: "r" (addr), "i" (-EFAULT));
+#else
+/* MIPSR6 has no lwl instruction */
+#define     LoadW(addr, value, res) \
+		__asm__ __volatile__ (			    \
+			".set\tpush\n"			    \
+			".set\tnoat\n\t"		    \
+			"1:"user_lb("%0", "0(%2)")"\n\t"    \
+			"2:"user_lbu("$1", "1(%2)")"\n\t"   \
+			"sll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"3:"user_lbu("$1", "2(%2)")"\n\t"   \
+			"sll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"4:"user_lbu("$1", "3(%2)")"\n\t"   \
+			"sll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"li\t%1, 0\n"			    \
+			".set\tpop\n"			    \
+			"10:\n\t"			    \
+			".insn\n\t"			    \
+			".section\t.fixup,\"ax\"\n\t"	    \
+			"11:\tli\t%1, %3\n\t"		    \
+			"j\t10b\n\t"			    \
+			".previous\n\t"			    \
+			".section\t__ex_table,\"a\"\n\t"    \
+			STR(PTR)"\t1b, 11b\n\t"		    \
+			STR(PTR)"\t2b, 11b\n\t"		    \
+			STR(PTR)"\t3b, 11b\n\t"		    \
+			STR(PTR)"\t4b, 11b\n\t"		    \
+			".previous"			    \
+			: "=&r" (value), "=r" (res)	    \
+			: "r" (addr), "i" (-EFAULT));
+#endif /* CONFIG_MIPS_R6 */
 
 #define     LoadHWU(addr, value, res) \
 		__asm__ __volatile__ (                      \
@@ -169,6 +203,7 @@ extern void show_registers(struct pt_regs *regs);
 			: "=&r" (value), "=r" (res)         \
 			: "r" (addr), "i" (-EFAULT));
 
+#ifndef CONFIG_CPU_MIPSR6
 #define     LoadWU(addr, value, res)  \
 		__asm__ __volatile__ (                      \
 			"1:\t"user_lwl("%0", "(%2)")"\n"    \
@@ -206,6 +241,87 @@ extern void show_registers(struct pt_regs *regs);
 			".previous"                         \
 			: "=&r" (value), "=r" (res)         \
 			: "r" (addr), "i" (-EFAULT));
+#else
+/* MIPSR6 has not lwl and ldl instructions */
+#define	    LoadWU(addr, value, res) \
+		__asm__ __volatile__ (			    \
+			".set\tpush\n\t"		    \
+			".set\tnoat\n\t"		    \
+			"1:"user_lbu("%0", "0(%2)")"\n\t"   \
+			"2:"user_lbu("$1", "1(%2)")"\n\t"   \
+			"sll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"3:"user_lbu("$1", "2(%2)")"\n\t"   \
+			"sll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"4:"user_lbu("$1", "3(%2)")"\n\t"   \
+			"sll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"li\t%1, 0\n"			    \
+			".set\tpop\n"			    \
+			"10:\n\t"			    \
+			".insn\n\t"			    \
+			".section\t.fixup,\"ax\"\n\t"	    \
+			"11:\tli\t%1, %3\n\t"		    \
+			"j\t10b\n\t"			    \
+			".previous\n\t"			    \
+			".section\t__ex_table,\"a\"\n\t"    \
+			STR(PTR)"\t1b, 11b\n\t"		    \
+			STR(PTR)"\t2b, 11b\n\t"		    \
+			STR(PTR)"\t3b, 11b\n\t"		    \
+			STR(PTR)"\t4b, 11b\n\t"		    \
+			".previous"			    \
+			: "=&r" (value), "=r" (res)	    \
+			: "r" (addr), "i" (-EFAULT));
+
+#define     LoadDW(addr, value, res)  \
+		__asm__ __volatile__ (			    \
+			".set\tpush\n\t"		    \
+			".set\tnoat\n\t"		    \
+			"1:lb\t%0, 0(%2)\n\t"    	    \
+			"2:lbu\t $1, 1(%2)\n\t"   	    \
+			"dsll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"3:lbu\t$1, 2(%2)\n\t"   	    \
+			"dsll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"4:lbu\t$1, 3(%2)\n\t"   	    \
+			"dsll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"5:lbu\t$1, 4(%2)\n\t"   	    \
+			"dsll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"6:lbu\t$1, 5(%2)\n\t"   	    \
+			"dsll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"7:lbu\t$1, 6(%2)\n\t"   	    \
+			"dsll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"8:lbu\t$1, 7(%2)\n\t"   	    \
+			"dsll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"li\t%1, 0\n"			    \
+			".set\tpop\n\t"			    \
+			"10:\n\t"			    \
+			".insn\n\t"			    \
+			".section\t.fixup,\"ax\"\n\t"	    \
+			"11:\tli\t%1, %3\n\t"		    \
+			"j\t10b\n\t"			    \
+			".previous\n\t"			    \
+			".section\t__ex_table,\"a\"\n\t"    \
+			STR(PTR)"\t1b, 11b\n\t"		    \
+			STR(PTR)"\t2b, 11b\n\t"		    \
+			STR(PTR)"\t3b, 11b\n\t"		    \
+			STR(PTR)"\t4b, 11b\n\t"		    \
+			STR(PTR)"\t5b, 11b\n\t"		    \
+			STR(PTR)"\t6b, 11b\n\t"		    \
+			STR(PTR)"\t7b, 11b\n\t"		    \
+			STR(PTR)"\t8b, 11b\n\t"		    \
+			".previous"			    \
+			: "=&r" (value), "=r" (res)	    \
+			: "r" (addr), "i" (-EFAULT));
+#endif /* CONFIG_CPU_MIPSR6 */
+
 
 #define     StoreHW(addr, value, res) \
 		__asm__ __volatile__ (                      \
@@ -228,6 +344,7 @@ extern void show_registers(struct pt_regs *regs);
 			: "=r" (res)                        \
 			: "r" (value), "r" (addr), "i" (-EFAULT));
 
+#ifndef CONFIG_CPU_MIPSR6
 #define     StoreW(addr, value, res)  \
 		__asm__ __volatile__ (                      \
 			"1:\t"user_swl("%1", "(%2)")"\n"    \
@@ -263,9 +380,82 @@ extern void show_registers(struct pt_regs *regs);
 			".previous"                         \
 		: "=r" (res)                                \
 		: "r" (value), "r" (addr), "i" (-EFAULT));
-#endif
+#else
+/* MIPSR6 has no swl and sdl instructions */
+#define     StoreW(addr, value, res)  \
+		__asm__ __volatile__ (                      \
+			".set\tpush\n\t"		    \
+			".set\tnoat\n\t"		    \
+			"1:"user_sb("%1", "3(%2)")"\n\t"    \
+			"srl\t$1, %1, 0x8\n\t"		    \
+			"2:"user_sb("$1", "2(%2)")"\n\t"    \
+			"srl\t$1, $1,  0x8\n\t"		    \
+			"3:"user_sb("$1", "1(%2)")"\n\t"    \
+			"srl\t$1, $1, 0x8\n\t"		    \
+			"4:"user_sb("$1", "0(%2)")"\n\t"    \
+			".set\tpop\n\t"			    \
+			"li\t%0, 0\n"			    \
+			"10:\n\t"			    \
+			".insn\n\t"			    \
+			".section\t.fixup,\"ax\"\n\t"	    \
+			"11:\tli\t%0, %3\n\t"		    \
+			"j\t10b\n\t"			    \
+			".previous\n\t"			    \
+			".section\t__ex_table,\"a\"\n\t"    \
+			STR(PTR)"\t1b, 11b\n\t"		    \
+			STR(PTR)"\t2b, 11b\n\t"		    \
+			STR(PTR)"\t3b, 11b\n\t"		    \
+			STR(PTR)"\t4b, 11b\n\t"		    \
+			".previous"			    \
+		: "=&r" (res)			    	    \
+		: "r" (value), "r" (addr), "i" (-EFAULT)    \
+		: "memory");
+
+#define     StoreDW(addr, value, res) \
+		__asm__ __volatile__ (                      \
+			".set\tpush\n\t"		    \
+			".set\tnoat\n\t"		    \
+			"1:sb\t%1, 7(%2)\n\t"    	    \
+			"dsrl\t$1, %1, 0x8\n\t"		    \
+			"2:sb\t$1, 6(%2)\n\t"    	    \
+			"dsrl\t$1, $1, 0x8\n\t"		    \
+			"3:sb\t$1, 5(%2)\n\t"    	    \
+			"dsrl\t$1, $1, 0x8\n\t"		    \
+			"4:sb\t$1, 4(%2)\n\t"    	    \
+			"dsrl\t$1, $1, 0x8\n\t"		    \
+			"5:sb\t$1, 3(%2)\n\t"    	    \
+			"dsrl\t$1, $1, 0x8\n\t"		    \
+			"6:sb\t$1, 2(%2)\n\t"    	    \
+			"dsrl\t$1, $1, 0x8\n\t"		    \
+			"7:sb\t$1, 1(%2)\n\t"    	    \
+			"dsrl\t$1, $1, 0x8\n\t"		    \
+			"8:sb\t$1, 0(%2)\n\t"    	    \
+			"dsrl\t$1, $1, 0x8\n\t"		    \
+			".set\tpop\n\t"			    \
+			"li\t%0, 0\n"			    \
+			"10:\n\t"			    \
+			".insn\n\t"			    \
+			".section\t.fixup,\"ax\"\n\t"	    \
+			"11:\tli\t%0, %3\n\t"		    \
+			"j\t10b\n\t"			    \
+			".previous\n\t"			    \
+			".section\t__ex_table,\"a\"\n\t"    \
+			STR(PTR)"\t1b, 11b\n\t"		    \
+			STR(PTR)"\t2b, 11b\n\t"		    \
+			STR(PTR)"\t3b, 11b\n\t"		    \
+			STR(PTR)"\t4b, 11b\n\t"		    \
+			STR(PTR)"\t5b, 11b\n\t"		    \
+			STR(PTR)"\t6b, 11b\n\t"		    \
+			STR(PTR)"\t7b, 11b\n\t"		    \
+			STR(PTR)"\t8b, 11b\n\t"		    \
+			".previous"			    \
+		: "=&r" (res)			    	    \
+		: "r" (value), "r" (addr), "i" (-EFAULT)    \
+		: "memory");
+#endif /* CONFIG_CPU_MIPSR6 */
+
+#else /* __BIG_ENDIAN */
 
-#ifdef __LITTLE_ENDIAN
 #define     LoadHW(addr, value, res)  \
 		__asm__ __volatile__ (".set\tnoat\n"        \
 			"1:\t"user_lb("%0", "1(%2)")"\n"    \
@@ -286,6 +476,7 @@ extern void show_registers(struct pt_regs *regs);
 			: "=&r" (value), "=r" (res)         \
 			: "r" (addr), "i" (-EFAULT));
 
+#ifndef CONFIG_CPU_MIPSR6
 #define     LoadW(addr, value, res)   \
 		__asm__ __volatile__ (                      \
 			"1:\t"user_lwl("%0", "3(%2)")"\n"   \
@@ -303,6 +494,40 @@ extern void show_registers(struct pt_regs *regs);
 			".previous"                         \
 			: "=&r" (value), "=r" (res)         \
 			: "r" (addr), "i" (-EFAULT));
+#else
+/* MIPSR6 has no lwl instruction */
+#define     LoadW(addr, value, res) \
+		__asm__ __volatile__ (			    \
+			".set\tpush\n"			    \
+			".set\tnoat\n\t"		    \
+			"1:"user_lb("%0", "3(%2)")"\n\t"    \
+			"2:"user_lbu("$1", "2(%2)")"\n\t"   \
+			"sll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"3:"user_lbu("$1", "1(%2)")"\n\t"   \
+			"sll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"4:"user_lbu("$1", "0(%2)")"\n\t"   \
+			"sll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"li\t%1, 0\n"			    \
+			".set\tpop\n"			    \
+			"10:\n\t"			    \
+			".insn\n\t"			    \
+			".section\t.fixup,\"ax\"\n\t"	    \
+			"11:\tli\t%1, %3\n\t"		    \
+			"j\t10b\n\t"			    \
+			".previous\n\t"			    \
+			".section\t__ex_table,\"a\"\n\t"    \
+			STR(PTR)"\t1b, 11b\n\t"		    \
+			STR(PTR)"\t2b, 11b\n\t"		    \
+			STR(PTR)"\t3b, 11b\n\t"		    \
+			STR(PTR)"\t4b, 11b\n\t"		    \
+			".previous"			    \
+			: "=&r" (value), "=r" (res)	    \
+			: "r" (addr), "i" (-EFAULT));
+#endif /* CONFIG_CPU_MIPSR6 */
+
 
 #define     LoadHWU(addr, value, res) \
 		__asm__ __volatile__ (                      \
@@ -326,6 +551,7 @@ extern void show_registers(struct pt_regs *regs);
 			: "=&r" (value), "=r" (res)         \
 			: "r" (addr), "i" (-EFAULT));
 
+#ifndef CONFIG_CPU_MIPSR6
 #define     LoadWU(addr, value, res)  \
 		__asm__ __volatile__ (                      \
 			"1:\t"user_lwl("%0", "3(%2)")"\n"   \
@@ -363,6 +589,86 @@ extern void show_registers(struct pt_regs *regs);
 			".previous"                         \
 			: "=&r" (value), "=r" (res)         \
 			: "r" (addr), "i" (-EFAULT));
+#else
+/* MIPSR6 has not lwl and ldl instructions */
+#define	    LoadWU(addr, value, res) \
+		__asm__ __volatile__ (			    \
+			".set\tpush\n\t"		    \
+			".set\tnoat\n\t"		    \
+			"1:"user_lbu("%0", "3(%2)")"\n\t"   \
+			"2:"user_lbu("$1", "2(%2)")"\n\t"   \
+			"sll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"3:"user_lbu("$1", "1(%2)")"\n\t"   \
+			"sll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"4:"user_lbu("$1", "0(%2)")"\n\t"   \
+			"sll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"li\t%1, 0\n"			    \
+			".set\tpop\n"			    \
+			"10:\n\t"			    \
+			".insn\n\t"			    \
+			".section\t.fixup,\"ax\"\n\t"	    \
+			"11:\tli\t%1, %3\n\t"		    \
+			"j\t10b\n\t"			    \
+			".previous\n\t"			    \
+			".section\t__ex_table,\"a\"\n\t"    \
+			STR(PTR)"\t1b, 11b\n\t"		    \
+			STR(PTR)"\t2b, 11b\n\t"		    \
+			STR(PTR)"\t3b, 11b\n\t"		    \
+			STR(PTR)"\t4b, 11b\n\t"		    \
+			".previous"			    \
+			: "=&r" (value), "=r" (res)	    \
+			: "r" (addr), "i" (-EFAULT));
+
+#define     LoadDW(addr, value, res)  \
+		__asm__ __volatile__ (			    \
+			".set\tpush\n\t"		    \
+			".set\tnoat\n\t"		    \
+			"1:lb\t%0, 7(%2)\n\t"    	    \
+			"2:lbu\t$1, 6(%2)\n\t"   	    \
+			"dsll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"3:lbu\t$1, 5(%2)\n\t"   	    \
+			"dsll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"4:lbu\t$1, 4(%2)\n\t"   	    \
+			"dsll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"5:lbu\t$1, 3(%2)\n\t"   	    \
+			"dsll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"6:lbu\t$1, 2(%2)\n\t"   	    \
+			"dsll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"7:lbu\t$1, 1(%2)\n\t"   	    \
+			"dsll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"8:lbu\t$1, 0(%2)\n\t"   	    \
+			"dsll\t%0, 0x8\n\t"		    \
+			"or\t%0, $1\n\t"		    \
+			"li\t%1, 0\n"			    \
+			".set\tpop\n\t"			    \
+			"10:\n\t"			    \
+			".insn\n\t"			    \
+			".section\t.fixup,\"ax\"\n\t"	    \
+			"11:\tli\t%1, %3\n\t"		    \
+			"j\t10b\n\t"			    \
+			".previous\n\t"			    \
+			".section\t__ex_table,\"a\"\n\t"    \
+			STR(PTR)"\t1b, 11b\n\t"		    \
+			STR(PTR)"\t2b, 11b\n\t"		    \
+			STR(PTR)"\t3b, 11b\n\t"		    \
+			STR(PTR)"\t4b, 11b\n\t"		    \
+			STR(PTR)"\t5b, 11b\n\t"		    \
+			STR(PTR)"\t6b, 11b\n\t"		    \
+			STR(PTR)"\t7b, 11b\n\t"		    \
+			STR(PTR)"\t8b, 11b\n\t"		    \
+			".previous"			    \
+			: "=&r" (value), "=r" (res)	    \
+			: "r" (addr), "i" (-EFAULT));
+#endif /* CONFIG_CPU_MIPSR6 */
 
 #define     StoreHW(addr, value, res) \
 		__asm__ __volatile__ (                      \
@@ -384,7 +690,7 @@ extern void show_registers(struct pt_regs *regs);
 			".previous"                         \
 			: "=r" (res)                        \
 			: "r" (value), "r" (addr), "i" (-EFAULT));
-
+#ifndef CONFIG_CPU_MIPSR6
 #define     StoreW(addr, value, res)  \
 		__asm__ __volatile__ (                      \
 			"1:\t"user_swl("%1", "3(%2)")"\n"   \
@@ -420,6 +726,79 @@ extern void show_registers(struct pt_regs *regs);
 			".previous"                         \
 		: "=r" (res)                                \
 		: "r" (value), "r" (addr), "i" (-EFAULT));
+#else
+/* MIPSR6 has no swl and sdl instructions */
+#define     StoreW(addr, value, res)  \
+		__asm__ __volatile__ (                      \
+			".set\tpush\n\t"		    \
+			".set\tnoat\n\t"		    \
+			"1:"user_sb("%1", "0(%2)")"\n\t"    \
+			"srl\t$1, %1, 0x8\n\t"		    \
+			"2:"user_sb("$1", "1(%2)")"\n\t"    \
+			"srl\t$1, $1,  0x8\n\t"		    \
+			"3:"user_sb("$1", "2(%2)")"\n\t"    \
+			"srl\t$1, $1, 0x8\n\t"		    \
+			"4:"user_sb("$1", "3(%2)")"\n\t"    \
+			".set\tpop\n\t"			    \
+			"li\t%0, 0\n"			    \
+			"10:\n\t"			    \
+			".insn\n\t"			    \
+			".section\t.fixup,\"ax\"\n\t"	    \
+			"11:\tli\t%0, %3\n\t"		    \
+			"j\t10b\n\t"			    \
+			".previous\n\t"			    \
+			".section\t__ex_table,\"a\"\n\t"    \
+			STR(PTR)"\t1b, 11b\n\t"		    \
+			STR(PTR)"\t2b, 11b\n\t"		    \
+			STR(PTR)"\t3b, 11b\n\t"		    \
+			STR(PTR)"\t4b, 11b\n\t"		    \
+			".previous"			    \
+		: "=&r" (res)			    	    \
+		: "r" (value), "r" (addr), "i" (-EFAULT)    \
+		: "memory");
+
+#define     StoreDW(addr, value, res) \
+		__asm__ __volatile__ (                      \
+			".set\tpush\n\t"		    \
+			".set\tnoat\n\t"		    \
+			"1:sb\t%1, 0(%2)\n\t"    	    \
+			"dsrl\t$1, %1, 0x8\n\t"		    \
+			"2:sb\t$1, 1(%2)\n\t"    	    \
+			"dsrl\t$1, $1, 0x8\n\t"		    \
+			"3:sb\t$1, 2(%2)\n\t"    	    \
+			"dsrl\t$1, $1, 0x8\n\t"		    \
+			"4:sb\t$1, 3(%2)\n\t"    	    \
+			"dsrl\t$1, $1, 0x8\n\t"		    \
+			"5:sb\t$1, 4(%2)\n\t"    	    \
+			"dsrl\t$1, $1, 0x8\n\t"		    \
+			"6:sb\t$1, 5(%2)\n\t"    	    \
+			"dsrl\t$1, $1, 0x8\n\t"		    \
+			"7:sb\t$1, 6(%2)\n\t"    	    \
+			"dsrl\t$1, $1, 0x8\n\t"		    \
+			"8:sb\t$1, 7(%2)\n\t"    	    \
+			"dsrl\t$1, $1, 0x8\n\t"		    \
+			".set\tpop\n\t"			    \
+			"li\t%0, 0\n"			    \
+			"10:\n\t"			    \
+			".insn\n\t"			    \
+			".section\t.fixup,\"ax\"\n\t"	    \
+			"11:\tli\t%0, %3\n\t"		    \
+			"j\t10b\n\t"			    \
+			".previous\n\t"			    \
+			".section\t__ex_table,\"a\"\n\t"    \
+			STR(PTR)"\t1b, 11b\n\t"		    \
+			STR(PTR)"\t2b, 11b\n\t"		    \
+			STR(PTR)"\t3b, 11b\n\t"		    \
+			STR(PTR)"\t4b, 11b\n\t"		    \
+			STR(PTR)"\t5b, 11b\n\t"		    \
+			STR(PTR)"\t6b, 11b\n\t"		    \
+			STR(PTR)"\t7b, 11b\n\t"		    \
+			STR(PTR)"\t8b, 11b\n\t"		    \
+			".previous"			    \
+		: "=&r" (res)			    	    \
+		: "r" (value), "r" (addr), "i" (-EFAULT)    \
+		: "memory");
+#endif /* CONFIG_CPU_MIPSR6 */
 #endif
 
 static void emulate_load_store_insn(struct pt_regs *regs,
@@ -703,10 +1082,13 @@ static void emulate_load_store_insn(struct pt_regs *regs,
 			break;
 		return;
 
+#ifndef CONFIG_MIPS_R6
 	/*
 	 * COP2 is available to implementor for application specific use.
 	 * It's up to applications to register a notifier chain and do
 	 * whatever they have to do, including possible sending of signals.
+	 *
+	 * This instruction has been reallocated in Release 6
 	 */
 	case lwc2_or_bc_op:
 		cu2_notifier_call_chain(CU2_LWC2_OP, regs);
@@ -723,7 +1105,7 @@ static void emulate_load_store_insn(struct pt_regs *regs,
 	case sdc2_or_bnzcjialc_op:
 		cu2_notifier_call_chain(CU2_SDC2_OP, regs);
 		break;
-
+#endif
 	default:
 		/*
 		 * Pheeee...  We encountered an yet unknown instruction or
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 37/67] MIPS: lib: memcpy: Add MIPS R6 support
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

MIPS R6 does not support the unaligned load and store instructions
so we add a special MIPS R6 case to copy one byte at a time if we
need to read/write to unaligned memory addresses.

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/lib/memcpy.S | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/arch/mips/lib/memcpy.S b/arch/mips/lib/memcpy.S
index 5d3238af9b5c..9245e1705e69 100644
--- a/arch/mips/lib/memcpy.S
+++ b/arch/mips/lib/memcpy.S
@@ -293,9 +293,14 @@
 	 and	t0, src, ADDRMASK
 	PREFS(	0, 2*32(src) )
 	PREFD(	1, 2*32(dst) )
+#ifndef CONFIG_CPU_MIPSR6
 	bnez	t1, .Ldst_unaligned\@
 	 nop
 	bnez	t0, .Lsrc_unaligned_dst_aligned\@
+#else
+	or	t0, t0, t1
+	bnez	t0, .Lcopy_unaligned_bytes\@
+#endif
 	/*
 	 * use delay slot for fall-through
 	 * src and dst are aligned; need to compute rem
@@ -376,6 +381,7 @@
 	bne	rem, len, 1b
 	.set	noreorder
 
+#ifndef CONFIG_CPU_MIPSR6
 	/*
 	 * src and dst are aligned, need to copy rem bytes (rem < NBYTES)
 	 * A loop would do only a byte at a time with possible branch
@@ -477,6 +483,7 @@
 	bne	len, rem, 1b
 	.set	noreorder
 
+#endif /* !CONFIG_CPU_MIPSR6 */
 .Lcopy_bytes_checklen\@:
 	beqz	len, .Ldone\@
 	 nop
@@ -504,6 +511,22 @@
 .Ldone\@:
 	jr	ra
 	 nop
+
+#ifdef CONFIG_CPU_MIPSR6
+.Lcopy_unaligned_bytes\@:
+1:
+	COPY_BYTE(0)
+	COPY_BYTE(1)
+	COPY_BYTE(2)
+	COPY_BYTE(3)
+	COPY_BYTE(4)
+	COPY_BYTE(5)
+	COPY_BYTE(6)
+	COPY_BYTE(7)
+	ADD	src, src, 8
+	b	1b
+	 ADD	dst, dst, 8
+#endif /* CONFIG_CPU_MIPSR6 */
 	.if __memcpy == 1
 	END(memcpy)
 	.set __memcpy, 0
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 37/67] MIPS: lib: memcpy: Add MIPS R6 support
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

MIPS R6 does not support the unaligned load and store instructions
so we add a special MIPS R6 case to copy one byte at a time if we
need to read/write to unaligned memory addresses.

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/lib/memcpy.S | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/arch/mips/lib/memcpy.S b/arch/mips/lib/memcpy.S
index 5d3238af9b5c..9245e1705e69 100644
--- a/arch/mips/lib/memcpy.S
+++ b/arch/mips/lib/memcpy.S
@@ -293,9 +293,14 @@
 	 and	t0, src, ADDRMASK
 	PREFS(	0, 2*32(src) )
 	PREFD(	1, 2*32(dst) )
+#ifndef CONFIG_CPU_MIPSR6
 	bnez	t1, .Ldst_unaligned\@
 	 nop
 	bnez	t0, .Lsrc_unaligned_dst_aligned\@
+#else
+	or	t0, t0, t1
+	bnez	t0, .Lcopy_unaligned_bytes\@
+#endif
 	/*
 	 * use delay slot for fall-through
 	 * src and dst are aligned; need to compute rem
@@ -376,6 +381,7 @@
 	bne	rem, len, 1b
 	.set	noreorder
 
+#ifndef CONFIG_CPU_MIPSR6
 	/*
 	 * src and dst are aligned, need to copy rem bytes (rem < NBYTES)
 	 * A loop would do only a byte at a time with possible branch
@@ -477,6 +483,7 @@
 	bne	len, rem, 1b
 	.set	noreorder
 
+#endif /* !CONFIG_CPU_MIPSR6 */
 .Lcopy_bytes_checklen\@:
 	beqz	len, .Ldone\@
 	 nop
@@ -504,6 +511,22 @@
 .Ldone\@:
 	jr	ra
 	 nop
+
+#ifdef CONFIG_CPU_MIPSR6
+.Lcopy_unaligned_bytes\@:
+1:
+	COPY_BYTE(0)
+	COPY_BYTE(1)
+	COPY_BYTE(2)
+	COPY_BYTE(3)
+	COPY_BYTE(4)
+	COPY_BYTE(5)
+	COPY_BYTE(6)
+	COPY_BYTE(7)
+	ADD	src, src, 8
+	b	1b
+	 ADD	dst, dst, 8
+#endif /* CONFIG_CPU_MIPSR6 */
 	.if __memcpy == 1
 	END(memcpy)
 	.set __memcpy, 0
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 38/67] MIPS: lib: memset: Add MIPS R6 support
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

MIPS R6 dropped the unaligned load and store instructions so
we need to re-write this part of the code for R6 to store
one byte at a time.

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/lib/memset.S | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/arch/mips/lib/memset.S b/arch/mips/lib/memset.S
index 7b0e5462ca51..a08c2c7222c0 100644
--- a/arch/mips/lib/memset.S
+++ b/arch/mips/lib/memset.S
@@ -111,6 +111,7 @@
 	.set		at
 #endif
 
+#ifndef CONFIG_CPU_MIPSR6
 	R10KCBARRIER(0(ra))
 #ifdef __MIPSEB__
 	EX(LONG_S_L, a1, (a0), .Lfirst_fixup\@)	/* make word/dword aligned */
@@ -121,6 +122,30 @@
 	PTR_SUBU	a0, t0			/* long align ptr */
 	PTR_ADDU	a2, t0			/* correct size */
 
+#else /* CONFIG_CPU_MIPSR6 */
+#define STORE_BYTE(N)				\
+	EX(sb, a1, N(a0), .Lbyte_fixup\@);	\
+	beqz		t0, 0f;			\
+	PTR_ADDU	t0, 1;
+
+	PTR_ADDU	a2, t0			/* correct size */
+	PTR_ADDU	t0, 1
+	STORE_BYTE(0)
+	STORE_BYTE(1)
+#if LONGSIZE == 4
+	EX(sb, a1, 2(a0), .Lbyte_fixup\@)
+#else
+	STORE_BYTE(2)
+	STORE_BYTE(3)
+	STORE_BYTE(4)
+	STORE_BYTE(5)
+	EX(sb, a1, 6(a0), .Lbyte_fixup\@)
+#endif
+0:
+	ori		a0, STORMASK
+	xori		a0, STORMASK
+	PTR_ADDIU	a0, STORSIZE
+#endif /* CONFIG_CPU_MIPS_R6 */
 1:	ori		t1, a2, 0x3f		/* # of full blocks */
 	xori		t1, 0x3f
 	beqz		t1, .Lmemset_partial\@	/* no block to fill */
@@ -160,6 +185,7 @@
 	andi		a2, STORMASK		/* At most one long to go */
 
 	beqz		a2, 1f
+#ifndef CONFIG_CPU_MIPSR6
 	PTR_ADDU	a0, a2			/* What's left */
 	R10KCBARRIER(0(ra))
 #ifdef __MIPSEB__
@@ -168,6 +194,22 @@
 #ifdef __MIPSEL__
 	EX(LONG_S_L, a1, -1(a0), .Llast_fixup\@)
 #endif
+#else
+	PTR_SUBU	t0, $0, a2
+	PTR_ADDIU	t0, 1
+	STORE_BYTE(0)
+	STORE_BYTE(1)
+#if LONGSIZE == 4
+	EX(sb, a1, 2(a0), .Lbyte_fixup\@)
+#else
+	STORE_BYTE(2)
+	STORE_BYTE(3)
+	STORE_BYTE(4)
+	STORE_BYTE(5)
+	EX(sb, a1, 6(a0), .Lbyte_fixup\@)
+#endif
+0:
+#endif
 1:	jr		ra
 	move		a2, zero
 
@@ -188,6 +230,11 @@
 	.hidden __memset
 	.endif
 
+.Lbyte_fixup\@:
+	PTR_SUBU	a2, $0, t0
+	jr		ra
+	 PTR_ADDIU	a2, 1
+
 .Lfirst_fixup\@:
 	jr	ra
 	nop
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 38/67] MIPS: lib: memset: Add MIPS R6 support
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

MIPS R6 dropped the unaligned load and store instructions so
we need to re-write this part of the code for R6 to store
one byte at a time.

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/lib/memset.S | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/arch/mips/lib/memset.S b/arch/mips/lib/memset.S
index 7b0e5462ca51..a08c2c7222c0 100644
--- a/arch/mips/lib/memset.S
+++ b/arch/mips/lib/memset.S
@@ -111,6 +111,7 @@
 	.set		at
 #endif
 
+#ifndef CONFIG_CPU_MIPSR6
 	R10KCBARRIER(0(ra))
 #ifdef __MIPSEB__
 	EX(LONG_S_L, a1, (a0), .Lfirst_fixup\@)	/* make word/dword aligned */
@@ -121,6 +122,30 @@
 	PTR_SUBU	a0, t0			/* long align ptr */
 	PTR_ADDU	a2, t0			/* correct size */
 
+#else /* CONFIG_CPU_MIPSR6 */
+#define STORE_BYTE(N)				\
+	EX(sb, a1, N(a0), .Lbyte_fixup\@);	\
+	beqz		t0, 0f;			\
+	PTR_ADDU	t0, 1;
+
+	PTR_ADDU	a2, t0			/* correct size */
+	PTR_ADDU	t0, 1
+	STORE_BYTE(0)
+	STORE_BYTE(1)
+#if LONGSIZE == 4
+	EX(sb, a1, 2(a0), .Lbyte_fixup\@)
+#else
+	STORE_BYTE(2)
+	STORE_BYTE(3)
+	STORE_BYTE(4)
+	STORE_BYTE(5)
+	EX(sb, a1, 6(a0), .Lbyte_fixup\@)
+#endif
+0:
+	ori		a0, STORMASK
+	xori		a0, STORMASK
+	PTR_ADDIU	a0, STORSIZE
+#endif /* CONFIG_CPU_MIPS_R6 */
 1:	ori		t1, a2, 0x3f		/* # of full blocks */
 	xori		t1, 0x3f
 	beqz		t1, .Lmemset_partial\@	/* no block to fill */
@@ -160,6 +185,7 @@
 	andi		a2, STORMASK		/* At most one long to go */
 
 	beqz		a2, 1f
+#ifndef CONFIG_CPU_MIPSR6
 	PTR_ADDU	a0, a2			/* What's left */
 	R10KCBARRIER(0(ra))
 #ifdef __MIPSEB__
@@ -168,6 +194,22 @@
 #ifdef __MIPSEL__
 	EX(LONG_S_L, a1, -1(a0), .Llast_fixup\@)
 #endif
+#else
+	PTR_SUBU	t0, $0, a2
+	PTR_ADDIU	t0, 1
+	STORE_BYTE(0)
+	STORE_BYTE(1)
+#if LONGSIZE == 4
+	EX(sb, a1, 2(a0), .Lbyte_fixup\@)
+#else
+	STORE_BYTE(2)
+	STORE_BYTE(3)
+	STORE_BYTE(4)
+	STORE_BYTE(5)
+	EX(sb, a1, 6(a0), .Lbyte_fixup\@)
+#endif
+0:
+#endif
 1:	jr		ra
 	move		a2, zero
 
@@ -188,6 +230,11 @@
 	.hidden __memset
 	.endif
 
+.Lbyte_fixup\@:
+	PTR_SUBU	a2, $0, t0
+	jr		ra
+	 PTR_ADDIU	a2, 1
+
 .Lfirst_fixup\@:
 	jr	ra
 	nop
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 39/67] MIPS: mm: page: Add MIPS R6 support
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

The MIPS R6 pref instruction only have 9 bits for the immediate
field so skip the micro-assembler PREF instruction is the offset
does not fit in 9 bits.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/mm/page.c | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/arch/mips/mm/page.c b/arch/mips/mm/page.c
index b611102e23b5..199a98c77547 100644
--- a/arch/mips/mm/page.c
+++ b/arch/mips/mm/page.c
@@ -72,6 +72,20 @@ static struct uasm_reloc relocs[5];
 #define cpu_is_r4600_v1_x()	((read_c0_prid() & 0xfffffff0) == 0x00002010)
 #define cpu_is_r4600_v2_x()	((read_c0_prid() & 0xfffffff0) == 0x00002020)
 
+/*
+ * R6 has a limited offset of the pref instruction.
+ * Skip it if the offset is more than 9 bits.
+ */
+#define _uasm_i_pref(a, b, c, d)		\
+do {						\
+	if (cpu_has_mips_r6) {			\
+	    if ((d > 0xff) || (d < -0xff))	\
+		uasm_i_pref(a, b, c, d);	\
+	} else {				\
+		uasm_i_pref(a, b, c, d);	\
+	}					\
+} while(0)
+
 static int pref_bias_clear_store;
 static int pref_bias_copy_load;
 static int pref_bias_copy_store;
@@ -214,7 +228,7 @@ static inline void build_clear_pref(u32 **buf, int off)
 		return;
 
 	if (pref_bias_clear_store) {
-		uasm_i_pref(buf, pref_dst_mode, pref_bias_clear_store + off,
+		_uasm_i_pref(buf, pref_dst_mode, pref_bias_clear_store + off,
 			    A0);
 	} else if (cache_line_size == (half_clear_loop_size << 1)) {
 		if (cpu_has_cache_cdex_s) {
@@ -357,7 +371,7 @@ static inline void build_copy_load_pref(u32 **buf, int off)
 		return;
 
 	if (pref_bias_copy_load)
-		uasm_i_pref(buf, pref_src_mode, pref_bias_copy_load + off, A1);
+		_uasm_i_pref(buf, pref_src_mode, pref_bias_copy_load + off, A1);
 }
 
 static inline void build_copy_store_pref(u32 **buf, int off)
@@ -366,7 +380,7 @@ static inline void build_copy_store_pref(u32 **buf, int off)
 		return;
 
 	if (pref_bias_copy_store) {
-		uasm_i_pref(buf, pref_dst_mode, pref_bias_copy_store + off,
+		_uasm_i_pref(buf, pref_dst_mode, pref_bias_copy_store + off,
 			    A0);
 	} else if (cache_line_size == (half_copy_loop_size << 1)) {
 		if (cpu_has_cache_cdex_s) {
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 39/67] MIPS: mm: page: Add MIPS R6 support
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

The MIPS R6 pref instruction only have 9 bits for the immediate
field so skip the micro-assembler PREF instruction is the offset
does not fit in 9 bits.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/mm/page.c | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/arch/mips/mm/page.c b/arch/mips/mm/page.c
index b611102e23b5..199a98c77547 100644
--- a/arch/mips/mm/page.c
+++ b/arch/mips/mm/page.c
@@ -72,6 +72,20 @@ static struct uasm_reloc relocs[5];
 #define cpu_is_r4600_v1_x()	((read_c0_prid() & 0xfffffff0) == 0x00002010)
 #define cpu_is_r4600_v2_x()	((read_c0_prid() & 0xfffffff0) == 0x00002020)
 
+/*
+ * R6 has a limited offset of the pref instruction.
+ * Skip it if the offset is more than 9 bits.
+ */
+#define _uasm_i_pref(a, b, c, d)		\
+do {						\
+	if (cpu_has_mips_r6) {			\
+	    if ((d > 0xff) || (d < -0xff))	\
+		uasm_i_pref(a, b, c, d);	\
+	} else {				\
+		uasm_i_pref(a, b, c, d);	\
+	}					\
+} while(0)
+
 static int pref_bias_clear_store;
 static int pref_bias_copy_load;
 static int pref_bias_copy_store;
@@ -214,7 +228,7 @@ static inline void build_clear_pref(u32 **buf, int off)
 		return;
 
 	if (pref_bias_clear_store) {
-		uasm_i_pref(buf, pref_dst_mode, pref_bias_clear_store + off,
+		_uasm_i_pref(buf, pref_dst_mode, pref_bias_clear_store + off,
 			    A0);
 	} else if (cache_line_size == (half_clear_loop_size << 1)) {
 		if (cpu_has_cache_cdex_s) {
@@ -357,7 +371,7 @@ static inline void build_copy_load_pref(u32 **buf, int off)
 		return;
 
 	if (pref_bias_copy_load)
-		uasm_i_pref(buf, pref_src_mode, pref_bias_copy_load + off, A1);
+		_uasm_i_pref(buf, pref_src_mode, pref_bias_copy_load + off, A1);
 }
 
 static inline void build_copy_store_pref(u32 **buf, int off)
@@ -366,7 +380,7 @@ static inline void build_copy_store_pref(u32 **buf, int off)
 		return;
 
 	if (pref_bias_copy_store) {
-		uasm_i_pref(buf, pref_dst_mode, pref_bias_copy_store + off,
+		_uasm_i_pref(buf, pref_dst_mode, pref_bias_copy_store + off,
 			    A0);
 	} else if (cache_line_size == (half_copy_loop_size << 1)) {
 		if (cpu_has_cache_cdex_s) {
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 40/67] MIPS: mm: tlbex: Add MIPS R6 case for the EHB instruction
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

The EHB instruction is supported by MIPS R6 so add the relevant
option.

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/mm/tlbex.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 14e5fae71a06..8a8a86a8942f 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -501,7 +501,7 @@ static void build_tlb_write_entry(u32 **p, struct uasm_label **l,
 	case tlb_indexed: tlbw = uasm_i_tlbwi; break;
 	}
 
-	if (cpu_has_mips_r2) {
+	if (cpu_has_mips_r2 || cpu_has_mips_r6) {
 		/*
 		 * The architecture spec says an ehb is required here,
 		 * but a number of cores do not have the hazard and
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 40/67] MIPS: mm: tlbex: Add MIPS R6 case for the EHB instruction
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

The EHB instruction is supported by MIPS R6 so add the relevant
option.

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/mm/tlbex.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 14e5fae71a06..8a8a86a8942f 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -501,7 +501,7 @@ static void build_tlb_write_entry(u32 **p, struct uasm_label **l,
 	case tlb_indexed: tlbw = uasm_i_tlbwi; break;
 	}
 
-	if (cpu_has_mips_r2) {
+	if (cpu_has_mips_r2 || cpu_has_mips_r6) {
 		/*
 		 * The architecture spec says an ehb is required here,
 		 * but a number of cores do not have the hazard and
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 41/67] MIPS: mm: c-r4k: Set the correct ISA level
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

The local_r4k_flush_cache_sigtramp function uses the 'cache'
instruction inside an asm block. However, MIPS R6 changed the
opcode for the cache instruction and as a result of which we
need to set the correct ISA level.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/mm/c-r4k.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index a659770bc539..6e79be368645 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -794,7 +794,7 @@ static void local_r4k_flush_cache_sigtramp(void * arg)
 		__asm__ __volatile__ (
 			".set push\n\t"
 			".set noat\n\t"
-			".set mips3\n\t"
+			".set "MIPS_ISA_LEVEL"\n\t"
 #ifdef CONFIG_32BIT
 			"la	$at,1f\n\t"
 #endif
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 41/67] MIPS: mm: c-r4k: Set the correct ISA level
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

The local_r4k_flush_cache_sigtramp function uses the 'cache'
instruction inside an asm block. However, MIPS R6 changed the
opcode for the cache instruction and as a result of which we
need to set the correct ISA level.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/mm/c-r4k.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index a659770bc539..6e79be368645 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -794,7 +794,7 @@ static void local_r4k_flush_cache_sigtramp(void * arg)
 		__asm__ __volatile__ (
 			".set push\n\t"
 			".set noat\n\t"
-			".set mips3\n\t"
+			".set "MIPS_ISA_LEVEL"\n\t"
 #ifdef CONFIG_32BIT
 			"la	$at,1f\n\t"
 #endif
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 42/67] MIPS: kernel: branch: Prepare the JR instruction for emulation on MIPS R6
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

The MIPS R6 JR instruction is an alias to the JALR one, so it may
needs emulation for non-R6 userlands.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/branch.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index b7dd0926e87f..3df013ef7622 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -19,6 +19,9 @@
 #include <asm/ptrace.h>
 #include <asm/uaccess.h>
 
+static int mipsr2_emulation = 0;
+#define NO_R6EMU	(cpu_has_mips_r6 && !mipsr2_emulation)
+
 /*
  * Calculate and return exception PC in case of branch delay slot
  * for microMIPS and MIPS16e. It does not clear the ISA mode bit.
@@ -417,6 +420,11 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 			regs->regs[insn.r_format.rd] = epc + 8;
 			/* Fall through */
 		case jr_op:
+			if (NO_R6EMU && insn.r_format.func == jr_op) {
+				ret = -SIGILL;
+				/* For R6, JR already emulated in jalr_op */
+				break;
+			}
 			regs->cp0_epc = regs->regs[insn.r_format.rs];
 			break;
 		}
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 42/67] MIPS: kernel: branch: Prepare the JR instruction for emulation on MIPS R6
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

The MIPS R6 JR instruction is an alias to the JALR one, so it may
needs emulation for non-R6 userlands.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/branch.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index b7dd0926e87f..3df013ef7622 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -19,6 +19,9 @@
 #include <asm/ptrace.h>
 #include <asm/uaccess.h>
 
+static int mipsr2_emulation = 0;
+#define NO_R6EMU	(cpu_has_mips_r6 && !mipsr2_emulation)
+
 /*
  * Calculate and return exception PC in case of branch delay slot
  * for microMIPS and MIPS16e. It does not clear the ISA mode bit.
@@ -417,6 +420,11 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 			regs->regs[insn.r_format.rd] = epc + 8;
 			/* Fall through */
 		case jr_op:
+			if (NO_R6EMU && insn.r_format.func == jr_op) {
+				ret = -SIGILL;
+				/* For R6, JR already emulated in jalr_op */
+				break;
+			}
 			regs->cp0_epc = regs->regs[insn.r_format.rs];
 			break;
 		}
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 43/67] MIPS: kernel: branch: Prevent BLTZL emulation for MIPS R6
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 removed the BLTZL instruction so do not try to emulate it
if the R2-to-R6 emulator is not present.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/branch.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 3df013ef7622..964ee68dcfe6 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -439,6 +439,11 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 		switch (insn.i_format.rt) {
 		case bltz_op:
 		case bltzl_op:
+			if (NO_R6EMU && insn.i_format.rt == bltzl_op) {
+				ret = -SIGILL;
+				/* not emulating the branch likely for R6 */
+				break;
+			}
 			if ((long)regs->regs[insn.i_format.rs] < 0) {
 				epc = epc + 4 + (insn.i_format.simmediate << 2);
 				if (insn.i_format.rt == bltzl_op)
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 43/67] MIPS: kernel: branch: Prevent BLTZL emulation for MIPS R6
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 removed the BLTZL instruction so do not try to emulate it
if the R2-to-R6 emulator is not present.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/branch.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 3df013ef7622..964ee68dcfe6 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -439,6 +439,11 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 		switch (insn.i_format.rt) {
 		case bltz_op:
 		case bltzl_op:
+			if (NO_R6EMU && insn.i_format.rt == bltzl_op) {
+				ret = -SIGILL;
+				/* not emulating the branch likely for R6 */
+				break;
+			}
 			if ((long)regs->regs[insn.i_format.rs] < 0) {
 				epc = epc + 4 + (insn.i_format.simmediate << 2);
 				if (insn.i_format.rt == bltzl_op)
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 44/67] MIPS: kernel: branch: Prevent BGEZL emulation for MIPS R6
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 removed the BGEZL instruction so do not try to emulate it
if the R2-to-R6 emulator is not present.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/branch.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 964ee68dcfe6..592db72123f2 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -455,6 +455,11 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 
 		case bgez_op:
 		case bgezl_op:
+			if (NO_R6EMU && insn.i_format.rt == bgezl_op) {
+				/* not emulating the branch likely for R6 */
+				ret = -SIGILL;
+				break;
+			}
 			if ((long)regs->regs[insn.i_format.rs] >= 0) {
 				epc = epc + 4 + (insn.i_format.simmediate << 2);
 				if (insn.i_format.rt == bgezl_op)
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 44/67] MIPS: kernel: branch: Prevent BGEZL emulation for MIPS R6
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 removed the BGEZL instruction so do not try to emulate it
if the R2-to-R6 emulator is not present.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/branch.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 964ee68dcfe6..592db72123f2 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -455,6 +455,11 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 
 		case bgez_op:
 		case bgezl_op:
+			if (NO_R6EMU && insn.i_format.rt == bgezl_op) {
+				/* not emulating the branch likely for R6 */
+				ret = -SIGILL;
+				break;
+			}
 			if ((long)regs->regs[insn.i_format.rs] >= 0) {
 				epc = epc + 4 + (insn.i_format.simmediate << 2);
 				if (insn.i_format.rt == bgezl_op)
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 45/67] MIPS: kernel: branch: Prevent BLTZAL emulation for MIPS R6
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 removed the BLTZAL instruction so do not try to emulate it
if the R2-to-R6 emulator is not present.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/branch.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 592db72123f2..f1f8ee374f14 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -471,7 +471,29 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 
 		case bltzal_op:
 		case bltzall_op:
+			if (NO_R6EMU && (insn.i_format.rs ||
+			    insn.i_format.rt == bltzall_op)) {
+				ret = -SIGILL;
+				break;
+			}
 			regs->regs[31] = epc + 8;
+			/*
+			 * OK we are here either because we hit a NAL
+			 * instruction or because we are emulating an
+			 * old bltzal{,l} one. Lets figure out what the
+			 * case really is.
+			 */
+			if (!insn.i_format.rs) {
+				/*
+				 * NAL or BLTZAL with rs == 0
+				 * Doesn't matter if we are R6 or not. The
+				 * result is the same
+				 */
+				regs->cp0_epc += 4 +
+					(insn.i_format.simmediate << 2);
+				break;
+			}
+			/* Now do the real thing for non-R6 BLTZAL{,L} */
 			if ((long)regs->regs[insn.i_format.rs] < 0) {
 				epc = epc + 4 + (insn.i_format.simmediate << 2);
 				if (insn.i_format.rt == bltzall_op)
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 45/67] MIPS: kernel: branch: Prevent BLTZAL emulation for MIPS R6
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 removed the BLTZAL instruction so do not try to emulate it
if the R2-to-R6 emulator is not present.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/branch.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 592db72123f2..f1f8ee374f14 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -471,7 +471,29 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 
 		case bltzal_op:
 		case bltzall_op:
+			if (NO_R6EMU && (insn.i_format.rs ||
+			    insn.i_format.rt == bltzall_op)) {
+				ret = -SIGILL;
+				break;
+			}
 			regs->regs[31] = epc + 8;
+			/*
+			 * OK we are here either because we hit a NAL
+			 * instruction or because we are emulating an
+			 * old bltzal{,l} one. Lets figure out what the
+			 * case really is.
+			 */
+			if (!insn.i_format.rs) {
+				/*
+				 * NAL or BLTZAL with rs == 0
+				 * Doesn't matter if we are R6 or not. The
+				 * result is the same
+				 */
+				regs->cp0_epc += 4 +
+					(insn.i_format.simmediate << 2);
+				break;
+			}
+			/* Now do the real thing for non-R6 BLTZAL{,L} */
 			if ((long)regs->regs[insn.i_format.rs] < 0) {
 				epc = epc + 4 + (insn.i_format.simmediate << 2);
 				if (insn.i_format.rt == bltzall_op)
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 46/67] MIPS: kernel: branch: Prevent BGEZAL emulation for MIPS R6
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 removed the BGEZAL instruction so do not try to emulate it
if the R2-to-R6 emulator is not present.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/branch.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index f1f8ee374f14..5f2a168c37fd 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -505,7 +505,29 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 
 		case bgezal_op:
 		case bgezall_op:
+			if (NO_R6EMU && (insn.i_format.rs ||
+			    insn.i_format.rt == bgezall_op)) {
+				ret = -SIGILL;
+				break;
+			}
 			regs->regs[31] = epc + 8;
+			/*
+			 * OK we are here either because we hit a BAL
+			 * instruction or because we are emulating an
+			 * old bgezal{,l} one. Lets figure out what the
+			 * case really is.
+			 */
+			if (!insn.i_format.rs) {
+				/*
+				 * BAL or BGEZAL with rs == 0
+				 * Doesn't matter if we are R6 or not. The
+				 * result is the same
+				 */
+				regs->cp0_epc += 4 +
+					(insn.i_format.simmediate << 2);
+				break;
+			}
+			/* Now do the real thing for non-R6 BGEZAL{,L} */
 			if ((long)regs->regs[insn.i_format.rs] >= 0) {
 				epc = epc + 4 + (insn.i_format.simmediate << 2);
 				if (insn.i_format.rt == bgezall_op)
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 46/67] MIPS: kernel: branch: Prevent BGEZAL emulation for MIPS R6
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 removed the BGEZAL instruction so do not try to emulate it
if the R2-to-R6 emulator is not present.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/branch.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index f1f8ee374f14..5f2a168c37fd 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -505,7 +505,29 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 
 		case bgezal_op:
 		case bgezall_op:
+			if (NO_R6EMU && (insn.i_format.rs ||
+			    insn.i_format.rt == bgezall_op)) {
+				ret = -SIGILL;
+				break;
+			}
 			regs->regs[31] = epc + 8;
+			/*
+			 * OK we are here either because we hit a BAL
+			 * instruction or because we are emulating an
+			 * old bgezal{,l} one. Lets figure out what the
+			 * case really is.
+			 */
+			if (!insn.i_format.rs) {
+				/*
+				 * BAL or BGEZAL with rs == 0
+				 * Doesn't matter if we are R6 or not. The
+				 * result is the same
+				 */
+				regs->cp0_epc += 4 +
+					(insn.i_format.simmediate << 2);
+				break;
+			}
+			/* Now do the real thing for non-R6 BGEZAL{,L} */
 			if ((long)regs->regs[insn.i_format.rs] >= 0) {
 				epc = epc + 4 + (insn.i_format.simmediate << 2);
 				if (insn.i_format.rt == bgezall_op)
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 47/67] MIPS: kernel: branch: Prevent BEQL emulation for MIPS R6
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 removed the BEQL instruction so do not try to emulate it
if the R2-to-R6 emulator is not present.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/branch.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 5f2a168c37fd..539d059ba4fb 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -572,6 +572,10 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 	 */
 	case beq_op:
 	case beql_op:
+		if (NO_R6EMU && insn.i_format.opcode == beql_op) {
+			ret = -SIGILL;
+			break;
+		}
 		if (regs->regs[insn.i_format.rs] ==
 		    regs->regs[insn.i_format.rt]) {
 			epc = epc + 4 + (insn.i_format.simmediate << 2);
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 47/67] MIPS: kernel: branch: Prevent BEQL emulation for MIPS R6
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 removed the BEQL instruction so do not try to emulate it
if the R2-to-R6 emulator is not present.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/branch.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 5f2a168c37fd..539d059ba4fb 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -572,6 +572,10 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 	 */
 	case beq_op:
 	case beql_op:
+		if (NO_R6EMU && insn.i_format.opcode == beql_op) {
+			ret = -SIGILL;
+			break;
+		}
 		if (regs->regs[insn.i_format.rs] ==
 		    regs->regs[insn.i_format.rt]) {
 			epc = epc + 4 + (insn.i_format.simmediate << 2);
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 48/67] MIPS: kernel: branch: Prevent BNEL emulation for MIPS R6
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 removed the BNEL instruction so do not try to emulate it
if the R2-to-R6 emulator is not present.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/branch.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 539d059ba4fb..979aa489754c 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -588,6 +588,10 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 
 	case bne_op:
 	case bnel_op:
+		if (NO_R6EMU && insn.i_format.opcode == bnel_op) {
+			ret = -SIGILL;
+			break;
+		}
 		if (regs->regs[insn.i_format.rs] !=
 		    regs->regs[insn.i_format.rt]) {
 			epc = epc + 4 + (insn.i_format.simmediate << 2);
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 48/67] MIPS: kernel: branch: Prevent BNEL emulation for MIPS R6
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 removed the BNEL instruction so do not try to emulate it
if the R2-to-R6 emulator is not present.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/branch.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 539d059ba4fb..979aa489754c 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -588,6 +588,10 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 
 	case bne_op:
 	case bnel_op:
+		if (NO_R6EMU && insn.i_format.opcode == bnel_op) {
+			ret = -SIGILL;
+			break;
+		}
 		if (regs->regs[insn.i_format.rs] !=
 		    regs->regs[insn.i_format.rt]) {
 			epc = epc + 4 + (insn.i_format.simmediate << 2);
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 49/67] MIPS: kernel: branch: Prevent BLEZL emulation for MIPS R6
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 removed the BLEZL instruction so do not try to emulate it
if the R2-to-R6 emulator is not present.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/branch.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 979aa489754c..bed4716117f8 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -604,6 +604,11 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 
 	case blez_op: /* not really i_format */
 	case blezl_op:
+		if (NO_R6EMU && insn.i_format.opcode == blezl_op) {
+			/* not emulating the branch likely for R6 */
+			ret = -SIGILL;
+			break;
+		}
 		/* rt field assumed to be zero */
 		if ((long)regs->regs[insn.i_format.rs] <= 0) {
 			epc = epc + 4 + (insn.i_format.simmediate << 2);
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 49/67] MIPS: kernel: branch: Prevent BLEZL emulation for MIPS R6
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 removed the BLEZL instruction so do not try to emulate it
if the R2-to-R6 emulator is not present.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/branch.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 979aa489754c..bed4716117f8 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -604,6 +604,11 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 
 	case blez_op: /* not really i_format */
 	case blezl_op:
+		if (NO_R6EMU && insn.i_format.opcode == blezl_op) {
+			/* not emulating the branch likely for R6 */
+			ret = -SIGILL;
+			break;
+		}
 		/* rt field assumed to be zero */
 		if ((long)regs->regs[insn.i_format.rs] <= 0) {
 			epc = epc + 4 + (insn.i_format.simmediate << 2);
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 50/67] MIPS: kernel: branch: Prevent BGTZL emulation for MIPS R6
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 removed the BGTZL instruction so do not try to emulate it
if the R2-to-R6 emulator is not present.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/branch.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index bed4716117f8..ba68c005aeab 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -621,6 +621,9 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 
 	case bgtz_op:
 	case bgtzl_op:
+		if (NO_R6EMU && insn.i_format.opcode == bgtzl_op)
+			/* not emulating the branch likely for R6 */
+			break;
 		/* rt field assumed to be zero */
 		if ((long)regs->regs[insn.i_format.rs] > 0) {
 			epc = epc + 4 + (insn.i_format.simmediate << 2);
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 50/67] MIPS: kernel: branch: Prevent BGTZL emulation for MIPS R6
@ 2014-12-18 15:09   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:09 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 removed the BGTZL instruction so do not try to emulate it
if the R2-to-R6 emulator is not present.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/branch.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index bed4716117f8..ba68c005aeab 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -621,6 +621,9 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 
 	case bgtz_op:
 	case bgtzl_op:
+		if (NO_R6EMU && insn.i_format.opcode == bgtzl_op)
+			/* not emulating the branch likely for R6 */
+			break;
 		/* rt field assumed to be zero */
 		if ((long)regs->regs[insn.i_format.rs] > 0) {
 			epc = epc + 4 + (insn.i_format.simmediate << 2);
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 51/67] MIPS: uapi: inst: Add new BC1EQZ and BC1NEZ MIPS R6 opcodes
@ 2014-12-18 15:10   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:10 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

Add new opcodes for the BC1EQZ and BC1NEZ instructions:

BC1EQZ: Branch if Cop1 (FPR) Register Bit 0 is Equal to Zero
BC1NEZ: Branch if Cop1 (FPR) Register Bit 0 is Not Equal to Zero

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/uapi/asm/inst.h | 3 ++-
 arch/mips/kernel/branch.c         | 4 +++-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h
index b7aa4c788983..648addfe1e1c 100644
--- a/arch/mips/include/uapi/asm/inst.h
+++ b/arch/mips/include/uapi/asm/inst.h
@@ -114,7 +114,8 @@ enum cop_op {
 	cfc_op	      = 0x02, mfhc_op	    = 0x03,
 	mtc_op        = 0x04, dmtc_op	    = 0x05,
 	ctc_op	      = 0x06, mthc_op	    = 0x07,
-	bc_op	      = 0x08, cop_op	    = 0x10,
+	bc_op	      = 0x08, bc1eqz_op     = 0x09,
+	bc1nez_op     = 0x0d, cop_op	    = 0x10,
 	copm_op	      = 0x18
 };
 
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index ba68c005aeab..a6f7af2aa6ee 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -621,9 +621,11 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 
 	case bgtz_op:
 	case bgtzl_op:
-		if (NO_R6EMU && insn.i_format.opcode == bgtzl_op)
+		if (NO_R6EMU && insn.i_format.opcode == bgtzl_op) {
 			/* not emulating the branch likely for R6 */
+			ret = -SIGILL;
 			break;
+		}
 		/* rt field assumed to be zero */
 		if ((long)regs->regs[insn.i_format.rs] > 0) {
 			epc = epc + 4 + (insn.i_format.simmediate << 2);
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 51/67] MIPS: uapi: inst: Add new BC1EQZ and BC1NEZ MIPS R6 opcodes
@ 2014-12-18 15:10   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:10 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

Add new opcodes for the BC1EQZ and BC1NEZ instructions:

BC1EQZ: Branch if Cop1 (FPR) Register Bit 0 is Equal to Zero
BC1NEZ: Branch if Cop1 (FPR) Register Bit 0 is Not Equal to Zero

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/uapi/asm/inst.h | 3 ++-
 arch/mips/kernel/branch.c         | 4 +++-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h
index b7aa4c788983..648addfe1e1c 100644
--- a/arch/mips/include/uapi/asm/inst.h
+++ b/arch/mips/include/uapi/asm/inst.h
@@ -114,7 +114,8 @@ enum cop_op {
 	cfc_op	      = 0x02, mfhc_op	    = 0x03,
 	mtc_op        = 0x04, dmtc_op	    = 0x05,
 	ctc_op	      = 0x06, mthc_op	    = 0x07,
-	bc_op	      = 0x08, cop_op	    = 0x10,
+	bc_op	      = 0x08, bc1eqz_op     = 0x09,
+	bc1nez_op     = 0x0d, cop_op	    = 0x10,
 	copm_op	      = 0x18
 };
 
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index ba68c005aeab..a6f7af2aa6ee 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -621,9 +621,11 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 
 	case bgtz_op:
 	case bgtzl_op:
-		if (NO_R6EMU && insn.i_format.opcode == bgtzl_op)
+		if (NO_R6EMU && insn.i_format.opcode == bgtzl_op) {
 			/* not emulating the branch likely for R6 */
+			ret = -SIGILL;
 			break;
+		}
 		/* rt field assumed to be zero */
 		if ((long)regs->regs[insn.i_format.rs] > 0) {
 			epc = epc + 4 + (insn.i_format.simmediate << 2);
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 52/67] MIPS: kernel: branch: Add support for the BC1{EQ,NE}Z FPU branches
@ 2014-12-18 15:10   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:10 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 introduced the following two branch instructions for COP1:

BC1EQZ: Branch if Cop1 (FPR) Register Bit 0 is Equal to Zero
BC1NEZ: Branch if Cop1 (FPR) Register Bit 0 is Not Equal to Zero

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/branch.c | 100 ++++++++++++++++++++++++++++++++--------------
 1 file changed, 71 insertions(+), 29 deletions(-)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index a6f7af2aa6ee..e6d78ab52aa7 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -406,7 +406,7 @@ int __MIPS16e_compute_return_epc(struct pt_regs *regs)
 int __compute_return_epc_for_insn(struct pt_regs *regs,
 				   union mips_instruction insn)
 {
-	unsigned int bit, fcr31, dspcontrol;
+	unsigned int bit, fcr31, dspcontrol, reg;
 	long epc = regs->cp0_epc;
 	int ret = 0;
 
@@ -640,40 +640,82 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 	 * And now the FPA/cp1 branch instructions.
 	 */
 	case cop1_op:
-		preempt_disable();
-		if (is_fpu_owner())
-		        fcr31 = read_32bit_cp1_register(CP1_STATUS);
-		else
-			fcr31 = current->thread.fpu.fcr31;
-		preempt_enable();
-
-		bit = (insn.i_format.rt >> 2);
-		bit += (bit != 0);
-		bit += 23;
-		switch (insn.i_format.rt & 3) {
-		case 0: /* bc1f */
-		case 2: /* bc1fl */
-			if (~fcr31 & (1 << bit)) {
-				epc = epc + 4 + (insn.i_format.simmediate << 2);
-				if (insn.i_format.rt == 2)
-					ret = BRANCH_LIKELY_TAKEN;
-			} else
+		if ((insn.i_format.rs == bc1eqz_op && cpu_has_mips_r6) ||
+		    (insn.i_format.rs == bc1nez_op && cpu_has_mips_r6)) {
+			if (!used_math()) { /* First time FPU user */
+				ret = init_fpu();
+				if (ret && NO_R6EMU) {
+					ret = -ret;
+					break;
+				}
+				ret = 0;
+				set_used_math();
+			}
+			lose_fpu(1);    /* Save FPU state for the emulator. */
+			reg = insn.i_format.rt;
+			bit = 0;
+			switch (insn.i_format.rs) {
+			case bc1eqz_op:
+				/* Test bit 0 */
+				if (get_fpr32(&current->thread.fpu.fpr[reg], 0)
+				    & 0x1)
+					bit = 1;
+				break;
+			case bc1nez_op:
+				/* Test bit 0 */
+				if (!(get_fpr32(&current->thread.fpu.fpr[reg], 0)
+				      & 0x1))
+					bit = 1;
+				break;
+			}
+			own_fpu(1);
+			if (bit)
+				epc = epc + 4 +
+					(insn.i_format.simmediate << 2);
+			else
 				epc += 8;
 			regs->cp0_epc = epc;
+
 			break;
+		} else {
 
-		case 1: /* bc1t */
-		case 3: /* bc1tl */
-			if (fcr31 & (1 << bit)) {
-				epc = epc + 4 + (insn.i_format.simmediate << 2);
-				if (insn.i_format.rt == 3)
-					ret = BRANCH_LIKELY_TAKEN;
-			} else
-				epc += 8;
-			regs->cp0_epc = epc;
+			preempt_disable();
+			if (is_fpu_owner())
+			        fcr31 = read_32bit_cp1_register(CP1_STATUS);
+			else
+				fcr31 = current->thread.fpu.fcr31;
+			preempt_enable();
+
+			bit = (insn.i_format.rt >> 2);
+			bit += (bit != 0);
+			bit += 23;
+			switch (insn.i_format.rt & 3) {
+			case 0: /* bc1f */
+			case 2: /* bc1fl */
+				if (~fcr31 & (1 << bit)) {
+					epc = epc + 4 +
+						(insn.i_format.simmediate << 2);
+					if (insn.i_format.rt == 2)
+						ret = BRANCH_LIKELY_TAKEN;
+				} else
+					epc += 8;
+				regs->cp0_epc = epc;
+				break;
+
+			case 1: /* bc1t */
+			case 3: /* bc1tl */
+				if (fcr31 & (1 << bit)) {
+					epc = epc + 4 +
+						(insn.i_format.simmediate << 2);
+					if (insn.i_format.rt == 3)
+						ret = BRANCH_LIKELY_TAKEN;
+				} else
+					epc += 8;
+				regs->cp0_epc = epc;
+				break;
+			}
 			break;
 		}
-		break;
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
 	case lwc2_or_bc_op: /* This is bbit0 on Octeon */
 		if ((regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt))
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 52/67] MIPS: kernel: branch: Add support for the BC1{EQ,NE}Z FPU branches
@ 2014-12-18 15:10   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:10 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 introduced the following two branch instructions for COP1:

BC1EQZ: Branch if Cop1 (FPR) Register Bit 0 is Equal to Zero
BC1NEZ: Branch if Cop1 (FPR) Register Bit 0 is Not Equal to Zero

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/branch.c | 100 ++++++++++++++++++++++++++++++++--------------
 1 file changed, 71 insertions(+), 29 deletions(-)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index a6f7af2aa6ee..e6d78ab52aa7 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -406,7 +406,7 @@ int __MIPS16e_compute_return_epc(struct pt_regs *regs)
 int __compute_return_epc_for_insn(struct pt_regs *regs,
 				   union mips_instruction insn)
 {
-	unsigned int bit, fcr31, dspcontrol;
+	unsigned int bit, fcr31, dspcontrol, reg;
 	long epc = regs->cp0_epc;
 	int ret = 0;
 
@@ -640,40 +640,82 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 	 * And now the FPA/cp1 branch instructions.
 	 */
 	case cop1_op:
-		preempt_disable();
-		if (is_fpu_owner())
-		        fcr31 = read_32bit_cp1_register(CP1_STATUS);
-		else
-			fcr31 = current->thread.fpu.fcr31;
-		preempt_enable();
-
-		bit = (insn.i_format.rt >> 2);
-		bit += (bit != 0);
-		bit += 23;
-		switch (insn.i_format.rt & 3) {
-		case 0: /* bc1f */
-		case 2: /* bc1fl */
-			if (~fcr31 & (1 << bit)) {
-				epc = epc + 4 + (insn.i_format.simmediate << 2);
-				if (insn.i_format.rt == 2)
-					ret = BRANCH_LIKELY_TAKEN;
-			} else
+		if ((insn.i_format.rs == bc1eqz_op && cpu_has_mips_r6) ||
+		    (insn.i_format.rs == bc1nez_op && cpu_has_mips_r6)) {
+			if (!used_math()) { /* First time FPU user */
+				ret = init_fpu();
+				if (ret && NO_R6EMU) {
+					ret = -ret;
+					break;
+				}
+				ret = 0;
+				set_used_math();
+			}
+			lose_fpu(1);    /* Save FPU state for the emulator. */
+			reg = insn.i_format.rt;
+			bit = 0;
+			switch (insn.i_format.rs) {
+			case bc1eqz_op:
+				/* Test bit 0 */
+				if (get_fpr32(&current->thread.fpu.fpr[reg], 0)
+				    & 0x1)
+					bit = 1;
+				break;
+			case bc1nez_op:
+				/* Test bit 0 */
+				if (!(get_fpr32(&current->thread.fpu.fpr[reg], 0)
+				      & 0x1))
+					bit = 1;
+				break;
+			}
+			own_fpu(1);
+			if (bit)
+				epc = epc + 4 +
+					(insn.i_format.simmediate << 2);
+			else
 				epc += 8;
 			regs->cp0_epc = epc;
+
 			break;
+		} else {
 
-		case 1: /* bc1t */
-		case 3: /* bc1tl */
-			if (fcr31 & (1 << bit)) {
-				epc = epc + 4 + (insn.i_format.simmediate << 2);
-				if (insn.i_format.rt == 3)
-					ret = BRANCH_LIKELY_TAKEN;
-			} else
-				epc += 8;
-			regs->cp0_epc = epc;
+			preempt_disable();
+			if (is_fpu_owner())
+			        fcr31 = read_32bit_cp1_register(CP1_STATUS);
+			else
+				fcr31 = current->thread.fpu.fcr31;
+			preempt_enable();
+
+			bit = (insn.i_format.rt >> 2);
+			bit += (bit != 0);
+			bit += 23;
+			switch (insn.i_format.rt & 3) {
+			case 0: /* bc1f */
+			case 2: /* bc1fl */
+				if (~fcr31 & (1 << bit)) {
+					epc = epc + 4 +
+						(insn.i_format.simmediate << 2);
+					if (insn.i_format.rt == 2)
+						ret = BRANCH_LIKELY_TAKEN;
+				} else
+					epc += 8;
+				regs->cp0_epc = epc;
+				break;
+
+			case 1: /* bc1t */
+			case 3: /* bc1tl */
+				if (fcr31 & (1 << bit)) {
+					epc = epc + 4 +
+						(insn.i_format.simmediate << 2);
+					if (insn.i_format.rt == 3)
+						ret = BRANCH_LIKELY_TAKEN;
+				} else
+					epc += 8;
+				regs->cp0_epc = epc;
+				break;
+			}
 			break;
 		}
-		break;
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
 	case lwc2_or_bc_op: /* This is bbit0 on Octeon */
 		if ((regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt))
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 53/67] MIPS: kernel: branch: Add new MIPS R6 B{L,G}ΕZ{AL,}C emulation
@ 2014-12-18 15:10   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:10 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 added the following four instructions which share the
BLEZ and BLEZL opcodes:

BLEZALC: Compact branch-and-link if GPR rt is <= to zero
BGEZALC: Compact branch-and-link if GPR rt is >= to zero
BLEZC: Compact branch if GPR rt is < to zero
BGEZC: Compact branch if GPR rt is > to zero

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/branch.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index e6d78ab52aa7..7bc2df026b51 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -402,6 +402,16 @@ int __MIPS16e_compute_return_epc(struct pt_regs *regs)
  * @returns:	-EFAULT on error and forces SIGBUS, and on success
  *		returns 0 or BRANCH_LIKELY_TAKEN as appropriate after
  *		evaluating the branch.
+ *
+ * MIPS R6 Compact branches and forbidden slots:
+ *	Compact branches do not throw exceptions because they do
+ *	not have delay slots. The forbidden slot instruction ($PC+4)
+ *	is only executed if the branch was not taken. Otherwise the
+ *	forbidden slot is skipped entirely. This means that they
+ *	only possible reason to be here because of a MIPS R6 compact
+ *	branch instruction is that the forbidden slot has thrown one.
+ *	In that case the branch was not taken, so the EPC can be safely
+ *	set to EPC + 8.
  */
 int __compute_return_epc_for_insn(struct pt_regs *regs,
 				   union mips_instruction insn)
@@ -609,6 +619,18 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 			ret = -SIGILL;
 			break;
 		}
+		/* blezalc, bgezalc, blezc, bgezc */
+		if (cpu_has_mips_r6) {
+			if (insn.i_format.rt) {
+				if (insn.i_format.opcode == blez_op)
+					if ((insn.i_format.rs ==
+					     insn.i_format.rt) ||
+					    !insn.i_format.rs)
+						regs->regs[31] = epc + 4;
+				regs->cp0_epc += 8;
+				break;
+			}
+		}
 		/* rt field assumed to be zero */
 		if ((long)regs->regs[insn.i_format.rs] <= 0) {
 			epc = epc + 4 + (insn.i_format.simmediate << 2);
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 53/67] MIPS: kernel: branch: Add new MIPS R6 B{L,G}ΕZ{AL,}C emulation
@ 2014-12-18 15:10   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:10 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 added the following four instructions which share the
BLEZ and BLEZL opcodes:

BLEZALC: Compact branch-and-link if GPR rt is <= to zero
BGEZALC: Compact branch-and-link if GPR rt is >= to zero
BLEZC: Compact branch if GPR rt is < to zero
BGEZC: Compact branch if GPR rt is > to zero

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/branch.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index e6d78ab52aa7..7bc2df026b51 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -402,6 +402,16 @@ int __MIPS16e_compute_return_epc(struct pt_regs *regs)
  * @returns:	-EFAULT on error and forces SIGBUS, and on success
  *		returns 0 or BRANCH_LIKELY_TAKEN as appropriate after
  *		evaluating the branch.
+ *
+ * MIPS R6 Compact branches and forbidden slots:
+ *	Compact branches do not throw exceptions because they do
+ *	not have delay slots. The forbidden slot instruction ($PC+4)
+ *	is only executed if the branch was not taken. Otherwise the
+ *	forbidden slot is skipped entirely. This means that they
+ *	only possible reason to be here because of a MIPS R6 compact
+ *	branch instruction is that the forbidden slot has thrown one.
+ *	In that case the branch was not taken, so the EPC can be safely
+ *	set to EPC + 8.
  */
 int __compute_return_epc_for_insn(struct pt_regs *regs,
 				   union mips_instruction insn)
@@ -609,6 +619,18 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 			ret = -SIGILL;
 			break;
 		}
+		/* blezalc, bgezalc, blezc, bgezc */
+		if (cpu_has_mips_r6) {
+			if (insn.i_format.rt) {
+				if (insn.i_format.opcode == blez_op)
+					if ((insn.i_format.rs ==
+					     insn.i_format.rt) ||
+					    !insn.i_format.rs)
+						regs->regs[31] = epc + 4;
+				regs->cp0_epc += 8;
+				break;
+			}
+		}
 		/* rt field assumed to be zero */
 		if ((long)regs->regs[insn.i_format.rs] <= 0) {
 			epc = epc + 4 + (insn.i_format.simmediate << 2);
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 54/67] MIPS: kernel: branch: Add new MIPS R6 B{L,G}TZ{AL,}C emulation
@ 2014-12-18 15:10   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:10 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 added the following four instructions which share the
BGTZ and BGTZL opcode:

BLTZALC: Compact branch-and-link if GPR rt is < to zero
BGEZALC: Compact branch-and-link if GPR rt is > to zero
BGTZL: Compact branch if GPR rt is < to zero
BGEZL: Compact branch if GPR rt is > to zero

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/branch.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 7bc2df026b51..ca102557fa3c 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -648,6 +648,19 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 			ret = -SIGILL;
 			break;
 		}
+		/* bgtzalc, bltzalc, bgtzc, bltzc */
+		if (cpu_has_mips_r6) {
+			if (insn.i_format.rt) {
+				if (insn.i_format.opcode == blez_op)
+					if (insn.i_format.rs ==
+					    insn.i_format.rt ||
+					    !insn.i_format.rs)
+						regs->regs[31] = epc + 4;
+				regs->cp0_epc += 8;
+				break;
+			}
+		}
+
 		/* rt field assumed to be zero */
 		if ((long)regs->regs[insn.i_format.rs] > 0) {
 			epc = epc + 4 + (insn.i_format.simmediate << 2);
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 54/67] MIPS: kernel: branch: Add new MIPS R6 B{L,G}TZ{AL,}C emulation
@ 2014-12-18 15:10   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:10 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 added the following four instructions which share the
BGTZ and BGTZL opcode:

BLTZALC: Compact branch-and-link if GPR rt is < to zero
BGEZALC: Compact branch-and-link if GPR rt is > to zero
BGTZL: Compact branch if GPR rt is < to zero
BGEZL: Compact branch if GPR rt is > to zero

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/branch.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 7bc2df026b51..ca102557fa3c 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -648,6 +648,19 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 			ret = -SIGILL;
 			break;
 		}
+		/* bgtzalc, bltzalc, bgtzc, bltzc */
+		if (cpu_has_mips_r6) {
+			if (insn.i_format.rt) {
+				if (insn.i_format.opcode == blez_op)
+					if (insn.i_format.rs ==
+					    insn.i_format.rt ||
+					    !insn.i_format.rs)
+						regs->regs[31] = epc + 4;
+				regs->cp0_epc += 8;
+				break;
+			}
+		}
+
 		/* rt field assumed to be zero */
 		if ((long)regs->regs[insn.i_format.rs] > 0) {
 			epc = epc + 4 + (insn.i_format.simmediate << 2);
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 55/67] MIPS: kernel: branch: Emulate the branch compact (BC) on MIPS R6
@ 2014-12-18 15:10   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:10 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 uses the <R6 LWC2 opcode for the new BC instruction.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/branch.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index ca102557fa3c..d9e3a0d72a64 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -784,6 +784,11 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 		regs->cp0_epc = epc;
 		break;
 #endif
+#ifdef CONFIG_CPU_MIPSR6
+	case lwc2_or_bc_op:
+		regs->cp0_epc += 8;
+		break;
+#endif
 	}
 
 	return ret;
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 55/67] MIPS: kernel: branch: Emulate the branch compact (BC) on MIPS R6
@ 2014-12-18 15:10   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:10 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 uses the <R6 LWC2 opcode for the new BC instruction.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/branch.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index ca102557fa3c..d9e3a0d72a64 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -784,6 +784,11 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 		regs->cp0_epc = epc;
 		break;
 #endif
+#ifdef CONFIG_CPU_MIPSR6
+	case lwc2_or_bc_op:
+		regs->cp0_epc += 8;
+		break;
+#endif
 	}
 
 	return ret;
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 56/67] MIPS: kernel: branch: Emulate the BOVC, BEQC and BEQZALC R6 instructions
@ 2014-12-18 15:10   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:10 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 uses the <R6 ADDI opcode for the new BOVC, BEQC and
BEQZALC instructions.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/uapi/asm/inst.h | 2 +-
 arch/mips/kernel/branch.c         | 6 ++++++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h
index 648addfe1e1c..b95363e0551f 100644
--- a/arch/mips/include/uapi/asm/inst.h
+++ b/arch/mips/include/uapi/asm/inst.h
@@ -21,7 +21,7 @@
 enum major_op {
 	spec_op, bcond_op, j_op, jal_op,
 	beq_op, bne_op, blez_op, bgtz_op,
-	addi_op, addiu_op, slti_op, sltiu_op,
+	addi_or_cbcond0_op, addiu_op, slti_op, sltiu_op,
 	andi_op, ori_op, xori_op, lui_op,
 	cop0_op, cop1_op, cop2_op, cop1x_op,
 	beql_op, bnel_op, blezl_op, bgtzl_op,
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index d9e3a0d72a64..cf390c76ba95 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -788,6 +788,12 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 	case lwc2_or_bc_op:
 		regs->cp0_epc += 8;
 		break;
+	case addi_or_cbcond0_op:
+		/* Compact branches: bovc, beqc, beqzalc */
+		if (insn.i_format.rt && !insn.i_format.rs)
+			regs->regs[31] = epc + 4;
+		regs->cp0_epc += 8;
+		break;
 #endif
 	}
 
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 56/67] MIPS: kernel: branch: Emulate the BOVC, BEQC and BEQZALC R6 instructions
@ 2014-12-18 15:10   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:10 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 uses the <R6 ADDI opcode for the new BOVC, BEQC and
BEQZALC instructions.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/uapi/asm/inst.h | 2 +-
 arch/mips/kernel/branch.c         | 6 ++++++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h
index 648addfe1e1c..b95363e0551f 100644
--- a/arch/mips/include/uapi/asm/inst.h
+++ b/arch/mips/include/uapi/asm/inst.h
@@ -21,7 +21,7 @@
 enum major_op {
 	spec_op, bcond_op, j_op, jal_op,
 	beq_op, bne_op, blez_op, bgtz_op,
-	addi_op, addiu_op, slti_op, sltiu_op,
+	addi_or_cbcond0_op, addiu_op, slti_op, sltiu_op,
 	andi_op, ori_op, xori_op, lui_op,
 	cop0_op, cop1_op, cop2_op, cop1x_op,
 	beql_op, bnel_op, blezl_op, bgtzl_op,
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index d9e3a0d72a64..cf390c76ba95 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -788,6 +788,12 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 	case lwc2_or_bc_op:
 		regs->cp0_epc += 8;
 		break;
+	case addi_or_cbcond0_op:
+		/* Compact branches: bovc, beqc, beqzalc */
+		if (insn.i_format.rt && !insn.i_format.rs)
+			regs->regs[31] = epc + 4;
+		regs->cp0_epc += 8;
+		break;
 #endif
 	}
 
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 57/67] MIPS: kernel: branch: Emulate the BNVC, BNEC and BNEZLAC R6 instructions
@ 2014-12-18 15:10   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:10 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 uses the <R6 DADDI opcode for the new BNVC, BNEC and
BNEZLAC instructions.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/uapi/asm/inst.h | 2 +-
 arch/mips/kernel/branch.c         | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h
index b95363e0551f..096f32153ce2 100644
--- a/arch/mips/include/uapi/asm/inst.h
+++ b/arch/mips/include/uapi/asm/inst.h
@@ -25,7 +25,7 @@ enum major_op {
 	andi_op, ori_op, xori_op, lui_op,
 	cop0_op, cop1_op, cop2_op, cop1x_op,
 	beql_op, bnel_op, blezl_op, bgtzl_op,
-	daddi_op, daddiu_op, ldl_op, ldr_op,
+	daddi_or_cbcond1_op, daddiu_op, ldl_op, ldr_op,
 	spec2_op, jalx_op, mdmx_op, spec3_op,
 	lb_op, lh_op, lwl_op, lw_op,
 	lbu_op, lhu_op, lwr_op, lwu_op,
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index cf390c76ba95..4cc9070682e1 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -790,6 +790,8 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 		break;
 	case addi_or_cbcond0_op:
 		/* Compact branches: bovc, beqc, beqzalc */
+	case daddi_or_cbcond1_op:
+		/* Compact branches: bnvc, bnec, bnezlac */
 		if (insn.i_format.rt && !insn.i_format.rs)
 			regs->regs[31] = epc + 4;
 		regs->cp0_epc += 8;
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 57/67] MIPS: kernel: branch: Emulate the BNVC, BNEC and BNEZLAC R6 instructions
@ 2014-12-18 15:10   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:10 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 uses the <R6 DADDI opcode for the new BNVC, BNEC and
BNEZLAC instructions.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/uapi/asm/inst.h | 2 +-
 arch/mips/kernel/branch.c         | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h
index b95363e0551f..096f32153ce2 100644
--- a/arch/mips/include/uapi/asm/inst.h
+++ b/arch/mips/include/uapi/asm/inst.h
@@ -25,7 +25,7 @@ enum major_op {
 	andi_op, ori_op, xori_op, lui_op,
 	cop0_op, cop1_op, cop2_op, cop1x_op,
 	beql_op, bnel_op, blezl_op, bgtzl_op,
-	daddi_op, daddiu_op, ldl_op, ldr_op,
+	daddi_or_cbcond1_op, daddiu_op, ldl_op, ldr_op,
 	spec2_op, jalx_op, mdmx_op, spec3_op,
 	lb_op, lh_op, lwl_op, lw_op,
 	lbu_op, lhu_op, lwr_op, lwu_op,
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index cf390c76ba95..4cc9070682e1 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -790,6 +790,8 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 		break;
 	case addi_or_cbcond0_op:
 		/* Compact branches: bovc, beqc, beqzalc */
+	case daddi_or_cbcond1_op:
+		/* Compact branches: bnvc, bnec, bnezlac */
 		if (insn.i_format.rt && !insn.i_format.rs)
 			regs->regs[31] = epc + 4;
 		regs->cp0_epc += 8;
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 58/67] MIPS: kernel: branch: Emulate the BALC R6 instruction
@ 2014-12-18 15:10   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:10 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 uses the <R6 swc2 opcode for the new BALC instructions.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/branch.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 4cc9070682e1..426f876403d0 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -796,6 +796,12 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 			regs->regs[31] = epc + 4;
 		regs->cp0_epc += 8;
 		break;
+	case swc2_or_balc_op:
+		/* Compact branch: BALC */
+		regs->regs[31] = epc + 4;
+		epc = epc + 4 + (insn.i_format.simmediate << 2);
+		regs->cp0_epc = epc;
+		break;
 #endif
 	}
 
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 58/67] MIPS: kernel: branch: Emulate the BALC R6 instruction
@ 2014-12-18 15:10   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:10 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 uses the <R6 swc2 opcode for the new BALC instructions.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/branch.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 4cc9070682e1..426f876403d0 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -796,6 +796,12 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 			regs->regs[31] = epc + 4;
 		regs->cp0_epc += 8;
 		break;
+	case swc2_or_balc_op:
+		/* Compact branch: BALC */
+		regs->regs[31] = epc + 4;
+		epc = epc + 4 + (insn.i_format.simmediate << 2);
+		regs->cp0_epc = epc;
+		break;
 #endif
 	}
 
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 59/67] MIPS: kernel: branch: Emulate the BEQZC and JIC instructions
@ 2014-12-18 15:10   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:10 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 uses the <R6 ldc2 opcode for the new BEQZC and JIC instructions

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/branch.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 426f876403d0..4473c23cacf2 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -802,6 +802,15 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 		epc = epc + 4 + (insn.i_format.simmediate << 2);
 		regs->cp0_epc = epc;
 		break;
+	case ldc2_or_bzcjic_op:
+		/* Compact branch: BEQZC || JIC */
+		if (insn.i_format.rs) /* BEQZC */
+			epc = epc + 8;
+		else /* JIC */
+			epc = regs->regs[insn.i_format.rt] +
+				insn.i_format.simmediate;
+		regs->cp0_epc = epc;
+		break;
 #endif
 	}
 
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 59/67] MIPS: kernel: branch: Emulate the BEQZC and JIC instructions
@ 2014-12-18 15:10   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:10 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 uses the <R6 ldc2 opcode for the new BEQZC and JIC instructions

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/branch.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 426f876403d0..4473c23cacf2 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -802,6 +802,15 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 		epc = epc + 4 + (insn.i_format.simmediate << 2);
 		regs->cp0_epc = epc;
 		break;
+	case ldc2_or_bzcjic_op:
+		/* Compact branch: BEQZC || JIC */
+		if (insn.i_format.rs) /* BEQZC */
+			epc = epc + 8;
+		else /* JIC */
+			epc = regs->regs[insn.i_format.rt] +
+				insn.i_format.simmediate;
+		regs->cp0_epc = epc;
+		break;
 #endif
 	}
 
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 60/67] MIPS: math-emu: cp1emu: Move the fpucondbit struct to a header
@ 2014-12-18 15:10   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:10 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

The fpucondbit struct will be used later on by the MIPS R2 instruction
emulator, so in order to access it, we need to move it to a header.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/fpu_emulator.h | 12 ++++++++++++
 arch/mips/math-emu/cp1emu.c          | 12 ------------
 2 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/arch/mips/include/asm/fpu_emulator.h b/arch/mips/include/asm/fpu_emulator.h
index 3ee347713307..d7670bd80855 100644
--- a/arch/mips/include/asm/fpu_emulator.h
+++ b/arch/mips/include/asm/fpu_emulator.h
@@ -30,6 +30,18 @@
 #include <asm/local.h>
 #include <asm/processor.h>
 
+/* convert condition code register number to csr bit */
+static const unsigned int fpucondbit[8] = {
+	FPU_CSR_COND0,
+	FPU_CSR_COND1,
+	FPU_CSR_COND2,
+	FPU_CSR_COND3,
+	FPU_CSR_COND4,
+	FPU_CSR_COND5,
+	FPU_CSR_COND6,
+	FPU_CSR_COND7
+};
+
 #ifdef CONFIG_DEBUG_FS
 
 struct mips_fpu_emulator_stats {
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index a426c176ee54..0aabdfc90d19 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -67,18 +67,6 @@ static int fpux_emu(struct pt_regs *,
 /* Determine rounding mode from the RM bits of the FCSR */
 #define modeindex(v) ((v) & FPU_CSR_RM)
 
-/* convert condition code register number to csr bit */
-static const unsigned int fpucondbit[8] = {
-	FPU_CSR_COND0,
-	FPU_CSR_COND1,
-	FPU_CSR_COND2,
-	FPU_CSR_COND3,
-	FPU_CSR_COND4,
-	FPU_CSR_COND5,
-	FPU_CSR_COND6,
-	FPU_CSR_COND7
-};
-
 /* (microMIPS) Convert certain microMIPS instructions to MIPS32 format. */
 static const int sd_format[] = {16, 17, 0, 0, 0, 0, 0, 0};
 static const int sdps_format[] = {16, 17, 22, 0, 0, 0, 0, 0};
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 60/67] MIPS: math-emu: cp1emu: Move the fpucondbit struct to a header
@ 2014-12-18 15:10   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:10 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

The fpucondbit struct will be used later on by the MIPS R2 instruction
emulator, so in order to access it, we need to move it to a header.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/fpu_emulator.h | 12 ++++++++++++
 arch/mips/math-emu/cp1emu.c          | 12 ------------
 2 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/arch/mips/include/asm/fpu_emulator.h b/arch/mips/include/asm/fpu_emulator.h
index 3ee347713307..d7670bd80855 100644
--- a/arch/mips/include/asm/fpu_emulator.h
+++ b/arch/mips/include/asm/fpu_emulator.h
@@ -30,6 +30,18 @@
 #include <asm/local.h>
 #include <asm/processor.h>
 
+/* convert condition code register number to csr bit */
+static const unsigned int fpucondbit[8] = {
+	FPU_CSR_COND0,
+	FPU_CSR_COND1,
+	FPU_CSR_COND2,
+	FPU_CSR_COND3,
+	FPU_CSR_COND4,
+	FPU_CSR_COND5,
+	FPU_CSR_COND6,
+	FPU_CSR_COND7
+};
+
 #ifdef CONFIG_DEBUG_FS
 
 struct mips_fpu_emulator_stats {
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index a426c176ee54..0aabdfc90d19 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -67,18 +67,6 @@ static int fpux_emu(struct pt_regs *,
 /* Determine rounding mode from the RM bits of the FCSR */
 #define modeindex(v) ((v) & FPU_CSR_RM)
 
-/* convert condition code register number to csr bit */
-static const unsigned int fpucondbit[8] = {
-	FPU_CSR_COND0,
-	FPU_CSR_COND1,
-	FPU_CSR_COND2,
-	FPU_CSR_COND3,
-	FPU_CSR_COND4,
-	FPU_CSR_COND5,
-	FPU_CSR_COND6,
-	FPU_CSR_COND7
-};
-
 /* (microMIPS) Convert certain microMIPS instructions to MIPS32 format. */
 static const int sd_format[] = {16, 17, 0, 0, 0, 0, 0, 0};
 static const int sdps_format[] = {16, 17, 22, 0, 0, 0, 0, 0};
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 61/67] MIPS: Add LLB bit and related feature for the Config 5 CP0 register
@ 2014-12-18 15:10   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:10 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

The LLBIT (bit 4) in the Config5 CP0 register indicates the software
availability of the Load-Linked bit. This bit is only set by hardware
and it has the following meaning:

0: LLB functionality is not supported
1: LLB functionality is supported. The following feature are also
supported:

- ERETNC instruction. Similar to ERET but it does not clear the LLB
bit in the LLAddr register.
- CP0 LLAddr/LLB bit must be set
- LLbit is software accessible through the LLAddr[0]

This will be used later on to emulate R2 LL/SC instructions.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/cpu-features.h | 3 +++
 arch/mips/include/asm/cpu.h          | 1 +
 arch/mips/include/asm/mipsregs.h     | 1 +
 arch/mips/kernel/cpu-probe.c         | 2 ++
 4 files changed, 7 insertions(+)

diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h
index 5830557539c0..1b88905f3e21 100644
--- a/arch/mips/include/asm/cpu-features.h
+++ b/arch/mips/include/asm/cpu-features.h
@@ -38,6 +38,9 @@
 #ifndef cpu_has_maar
 #define cpu_has_maar		(cpu_data[0].options & MIPS_CPU_MAAR)
 #endif
+#ifndef cpu_has_rw_llb
+#define cpu_has_rw_llb		(cpu_data[0].options & MIPS_CPU_RW_LLB)
+#endif
 
 /*
  * For the moment we don't consider R6000 and R8000 so we can assume that
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index c525f5060773..27a8dbce8a79 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -374,6 +374,7 @@ enum cpu_type_enum {
 #define MIPS_CPU_HTW		0x100000000ull /* CPU support Hardware Page Table Walker */
 #define MIPS_CPU_RIXIEX		0x200000000ull /* CPU has unique exception codes for {Read, Execute}-Inhibit exceptions */
 #define MIPS_CPU_MAAR		0x400000000ull /* MAAR(I) registers are present */
+#define MIPS_CPU_RW_LLB		0x800000000ull /* LLADDR/LLB writes are allowed */
 
 /*
  * CPU ASE encodings
diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index 22a135ac91de..8b27e17c1cad 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -653,6 +653,7 @@
 #define MIPS_CONF5_NF		(_ULCAST_(1) << 0)
 #define MIPS_CONF5_UFR		(_ULCAST_(1) << 2)
 #define MIPS_CONF5_MRP		(_ULCAST_(1) << 3)
+#define MIPS_CONF5_LLB		(_ULCAST_(1) << 4)
 #define MIPS_CONF5_MSAEN	(_ULCAST_(1) << 27)
 #define MIPS_CONF5_EVA		(_ULCAST_(1) << 28)
 #define MIPS_CONF5_CV		(_ULCAST_(1) << 29)
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 3a0b6c11d34b..30253329aa48 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -452,6 +452,8 @@ static inline unsigned int decode_config5(struct cpuinfo_mips *c)
 		c->options |= MIPS_CPU_EVA;
 	if (config5 & MIPS_CONF5_MRP)
 		c->options |= MIPS_CPU_MAAR;
+	if (config5 & MIPS_CONF5_LLB)
+		c->options |= MIPS_CPU_RW_LLB;
 
 	return config5 & MIPS_CONF_M;
 }
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 61/67] MIPS: Add LLB bit and related feature for the Config 5 CP0 register
@ 2014-12-18 15:10   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:10 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

The LLBIT (bit 4) in the Config5 CP0 register indicates the software
availability of the Load-Linked bit. This bit is only set by hardware
and it has the following meaning:

0: LLB functionality is not supported
1: LLB functionality is supported. The following feature are also
supported:

- ERETNC instruction. Similar to ERET but it does not clear the LLB
bit in the LLAddr register.
- CP0 LLAddr/LLB bit must be set
- LLbit is software accessible through the LLAddr[0]

This will be used later on to emulate R2 LL/SC instructions.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/cpu-features.h | 3 +++
 arch/mips/include/asm/cpu.h          | 1 +
 arch/mips/include/asm/mipsregs.h     | 1 +
 arch/mips/kernel/cpu-probe.c         | 2 ++
 4 files changed, 7 insertions(+)

diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h
index 5830557539c0..1b88905f3e21 100644
--- a/arch/mips/include/asm/cpu-features.h
+++ b/arch/mips/include/asm/cpu-features.h
@@ -38,6 +38,9 @@
 #ifndef cpu_has_maar
 #define cpu_has_maar		(cpu_data[0].options & MIPS_CPU_MAAR)
 #endif
+#ifndef cpu_has_rw_llb
+#define cpu_has_rw_llb		(cpu_data[0].options & MIPS_CPU_RW_LLB)
+#endif
 
 /*
  * For the moment we don't consider R6000 and R8000 so we can assume that
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index c525f5060773..27a8dbce8a79 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -374,6 +374,7 @@ enum cpu_type_enum {
 #define MIPS_CPU_HTW		0x100000000ull /* CPU support Hardware Page Table Walker */
 #define MIPS_CPU_RIXIEX		0x200000000ull /* CPU has unique exception codes for {Read, Execute}-Inhibit exceptions */
 #define MIPS_CPU_MAAR		0x400000000ull /* MAAR(I) registers are present */
+#define MIPS_CPU_RW_LLB		0x800000000ull /* LLADDR/LLB writes are allowed */
 
 /*
  * CPU ASE encodings
diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index 22a135ac91de..8b27e17c1cad 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -653,6 +653,7 @@
 #define MIPS_CONF5_NF		(_ULCAST_(1) << 0)
 #define MIPS_CONF5_UFR		(_ULCAST_(1) << 2)
 #define MIPS_CONF5_MRP		(_ULCAST_(1) << 3)
+#define MIPS_CONF5_LLB		(_ULCAST_(1) << 4)
 #define MIPS_CONF5_MSAEN	(_ULCAST_(1) << 27)
 #define MIPS_CONF5_EVA		(_ULCAST_(1) << 28)
 #define MIPS_CONF5_CV		(_ULCAST_(1) << 29)
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 3a0b6c11d34b..30253329aa48 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -452,6 +452,8 @@ static inline unsigned int decode_config5(struct cpuinfo_mips *c)
 		c->options |= MIPS_CPU_EVA;
 	if (config5 & MIPS_CONF5_MRP)
 		c->options |= MIPS_CPU_MAAR;
+	if (config5 & MIPS_CONF5_LLB)
+		c->options |= MIPS_CPU_RW_LLB;
 
 	return config5 & MIPS_CONF_M;
 }
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 62/67] MIPS: asm: mipsregs: Add support for the LLADDR register
@ 2014-12-18 15:10   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:10 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

If Config5/LLB is set in the core, then software can write the LLB
bit in the LLADDR register.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/mipsregs.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index 8b27e17c1cad..1746a039a491 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -1085,6 +1085,8 @@ do {									\
 #define write_c0_config6(val)	__write_32bit_c0_register($16, 6, val)
 #define write_c0_config7(val)	__write_32bit_c0_register($16, 7, val)
 
+#define read_c0_lladdr()	__read_ulong_c0_register($17, 0)
+#define write_c0_lladdr(val)	__write_ulong_c0_register($17, 0, val)
 #define read_c0_maar()		__read_ulong_c0_register($17, 1)
 #define write_c0_maar(val)	__write_ulong_c0_register($17, 1, val)
 #define read_c0_maari()		__read_32bit_c0_register($17, 2)
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 62/67] MIPS: asm: mipsregs: Add support for the LLADDR register
@ 2014-12-18 15:10   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:10 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

If Config5/LLB is set in the core, then software can write the LLB
bit in the LLADDR register.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/mipsregs.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index 8b27e17c1cad..1746a039a491 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -1085,6 +1085,8 @@ do {									\
 #define write_c0_config6(val)	__write_32bit_c0_register($16, 6, val)
 #define write_c0_config7(val)	__write_32bit_c0_register($16, 7, val)
 
+#define read_c0_lladdr()	__read_ulong_c0_register($17, 0)
+#define write_c0_lladdr(val)	__write_ulong_c0_register($17, 0, val)
 #define read_c0_maar()		__read_ulong_c0_register($17, 1)
 #define write_c0_maar(val)	__write_ulong_c0_register($17, 1, val)
 #define read_c0_maari()		__read_32bit_c0_register($17, 2)
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 63/67] MIPS: kernel: mips-r2-to-r6-emul: Add R2 emulator for MIPS R6
@ 2014-12-18 15:10   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:10 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

MIPS R6 removed quite a few R2 instructions. However, there
is plenty of <R6 userland code so we add an in-kernel emulator
so we can still be able to execute all R2 userland out there.

The emulator comes with a handy debugfs under /mips/ directory
(r2-emul-stats) to provide some basic statistics of the
instructions that are being emulated.

Below are some statistics from booting a minimal buildroot image:

Instruction     Total   BDslot
------------------------------
movs            236969  0
hilo            56686   0
muls            55279   0
divs            10941   0
dsps            0       0
bops            1       0
traps           0       0
fpus            0       0
loads           214981  17
stores          103364  0
llsc            56898   0
dsemul          150418  0
jr              370158
bltzl           43
bgezl           1594
bltzll          0
bgezll          0
bltzal          39
bgezal          39
beql            14503
bnel            138741
blezl           0
bgtzl           3988

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/Kconfig                          |   13 +
 arch/mips/include/asm/mips-r2-to-r6-emul.h |   94 ++
 arch/mips/kernel/Makefile                  |    1 +
 arch/mips/kernel/branch.c                  |    2 +-
 arch/mips/kernel/mips-r2-to-r6-emul.c      | 2377 ++++++++++++++++++++++++++++
 arch/mips/kernel/traps.c                   |   28 +-
 6 files changed, 2513 insertions(+), 2 deletions(-)
 create mode 100644 arch/mips/include/asm/mips-r2-to-r6-emul.h
 create mode 100644 arch/mips/kernel/mips-r2-to-r6-emul.c

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 544e62369bbc..3fe856572d2e 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -2027,6 +2027,19 @@ config MIPS_MT_FPAFF
 	default y
 	depends on MIPS_MT_SMP
 
+config MIPSR2_TO_R6_EMULATOR
+	bool "MIPS R2-to-R6 emulator"
+	depends on CPU_MIPSR6 && !SMP
+	default y
+	help
+	  Choose this option if you want to run non-R6 MIPS userland code.
+	  Even if you say 'Y' here, the emulator will still be disabled by
+	  default. You can enable it using the 'mipsr2emul' kernel option.
+	  The only reason this is a build-time option is to save ~14K from the
+	  final kernel image.
+comment "MIPS R2-to-R6 emulator is only available for UP kernels"
+	depends on SMP && CPU_MIPSR6
+
 config MIPS_VPE_LOADER
 	bool "VPE loader support."
 	depends on SYS_SUPPORTS_MULTITHREADING && MODULES
diff --git a/arch/mips/include/asm/mips-r2-to-r6-emul.h b/arch/mips/include/asm/mips-r2-to-r6-emul.h
new file mode 100644
index 000000000000..8d5fe0d716f5
--- /dev/null
+++ b/arch/mips/include/asm/mips-r2-to-r6-emul.h
@@ -0,0 +1,94 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2014 Imagination Technologies Ltd.
+ * Author: Markos Chandras <markos.chandras@imgtec.com>
+ */
+
+#ifndef __ASM_MIPS_R2_TO_R6_EMUL_H
+#define __ASM_MIPS_R2_TO_R6_EMUL_H
+
+#ifdef CONFIG_DEBUG_FS
+
+struct mips_r2_emulator_stats {
+	u64 movs;
+	u64 hilo;
+	u64 muls;
+	u64 divs;
+	u64 dsps;
+	u64 bops;
+	u64 traps;
+	u64 fpus;
+	u64 loads;
+	u64 stores;
+	u64 llsc;
+	u64 dsemul;
+};
+
+#define MIPS_R2_STATS(M)						\
+do {									\
+	u32 nir;							\
+	int err;							\
+									\
+	preempt_disable();						\
+	__get_cpu_var(mipsr2emustats).M++;				\
+	err = __get_user(nir, (u32 __user *)regs->cp0_epc);		\
+	if (!err) {							\
+		if (nir == BREAK_MATH)					\
+			__get_cpu_var(mipsr2bdemustats).M++;		\
+	}								\
+	preempt_enable();						\
+} while (0)
+
+struct mips_r2br_emulator_stats {
+	u64 jrs;
+	u64 bltzl;
+	u64 bgezl;
+	u64 bltzll;
+	u64 bgezll;
+	u64 bltzall;
+	u64 bgezall;
+	u64 bltzal;
+	u64 bgezal;
+	u64 beql;
+	u64 bnel;
+	u64 blezl;
+	u64 bgtzl;
+};
+
+#define MIPS_R2BR_STATS(M)					\
+do {								\
+	preempt_disable();					\
+	__get_cpu_var(mipsr2bremustats).M++;			\
+	preempt_enable();					\
+} while (0)
+
+#else
+
+#define MIPS_R2_STATS(M)          do { } while (0)
+#define MIPS_R2BR_STATS(M)        do { } while (0)
+
+#endif /* CONFIG_DEBUG_FS */
+
+struct r2_decoder_table {
+	u32     mask;
+	u32     code;
+	int     (*func)(struct pt_regs *regs, u32 inst);
+};
+
+
+extern void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
+			  const char *str);
+
+#ifndef CONFIG_MIPSR2_TO_R6_EMULATOR
+static int mipsr2_emulation;
+static __maybe_unused int mipsr2_decoder(struct pt_regs *regs, u32 inst) { return 0; };
+#else
+/* MIPS R2 Emulator ON/OFF */
+extern int mipsr2_emulation;
+extern int mipsr2_decoder(struct pt_regs *regs, u32 inst);
+#endif /* CONFIG_MIPSR2_TO_R6_EMULATOR */
+
+#endif /* __ASM_MIPS_R2_TO_R6_EMUL_H */
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index f6ee8cc1f7c2..c3918e7693f9 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -93,6 +93,7 @@ obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
 obj-$(CONFIG_EARLY_PRINTK_8250)	+= early_printk_8250.o
 obj-$(CONFIG_SPINLOCK_TEST)	+= spinlock_test.o
 obj-$(CONFIG_MIPS_MACHINE)	+= mips_machine.o
+obj-$(CONFIG_MIPSR2_TO_R6_EMULATOR)	+= mips-r2-to-r6-emul.o
 
 CFLAGS_cpu-bugs64.o	= $(shell if $(CC) $(KBUILD_CFLAGS) -Wa,-mdaddi -c -o /dev/null -x c /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi)
 
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 4473c23cacf2..438162e8db06 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -16,10 +16,10 @@
 #include <asm/fpu.h>
 #include <asm/fpu_emulator.h>
 #include <asm/inst.h>
+#include <asm/mips-r2-to-r6-emul.h>
 #include <asm/ptrace.h>
 #include <asm/uaccess.h>
 
-static int mipsr2_emulation = 0;
 #define NO_R6EMU	(cpu_has_mips_r6 && !mipsr2_emulation)
 
 /*
diff --git a/arch/mips/kernel/mips-r2-to-r6-emul.c b/arch/mips/kernel/mips-r2-to-r6-emul.c
new file mode 100644
index 000000000000..45b1cb536523
--- /dev/null
+++ b/arch/mips/kernel/mips-r2-to-r6-emul.c
@@ -0,0 +1,2377 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2014 Imagination Technologies Ltd.
+ * Author: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
+ * Author: Markos Chandras <markos.chandras@imgtec.com>
+ *
+ *      MIPS R2 user space instruction emulator for MIPS R6
+ *
+ */
+#include <linux/bug.h>
+#include <linux/compiler.h>
+#include <linux/debugfs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/ptrace.h>
+#include <linux/seq_file.h>
+
+#include <asm/asm.h>
+#include <asm/branch.h>
+#include <asm/break.h>
+#include <asm/fpu.h>
+#include <asm/fpu_emulator.h>
+#include <asm/inst.h>
+#include <asm/mips-r2-to-r6-emul.h>
+#include <asm/local.h>
+#include <asm/ptrace.h>
+#include <asm/uaccess.h>
+
+#ifdef CONFIG_64BIT
+#define ADDIU	"daddiu "
+#define INS	"dins "
+#define EXT	"dext "
+#else
+#define ADDIU	"addiu "
+#define INS	"ins "
+#define EXT	"ext "
+#endif /* CONFIG_64BIT */
+
+#define SB	"sb "
+#define LB	"lb "
+#define LL	"ll "
+#define SC	"sc "
+
+DEFINE_PER_CPU(struct mips_r2_emulator_stats, mipsr2emustats);
+DEFINE_PER_CPU(struct mips_r2_emulator_stats, mipsr2bdemustats);
+DEFINE_PER_CPU(struct mips_r2br_emulator_stats, mipsr2bremustats);
+
+#define MIPS_R2_EMUL_TOTAL_PASS	10
+
+int mipsr2_emulation = 0;
+
+static int __init mipsr2emu_enable(char *s)
+{
+	mipsr2_emulation = 1;
+
+	pr_info("MIPS R2-to-R6 Emulator Enabled!");
+
+	return 1;
+}
+__setup("mipsr2emu", mipsr2emu_enable);
+
+/**
+ * mipsr6_emul - Emulate some frequent R2/R5/R6 instructions in delay slot
+ * for performance instead of the traditional way of using a stack trampoline
+ * which is rather slow.
+ * @regs: Process register set
+ * @ir: Instruction
+ */
+static inline int mipsr6_emul(struct pt_regs *regs, u32 ir)
+{
+	switch (MIPSInst_OPCODE(ir)) {
+	case addiu_op:
+		if (MIPSInst_RT(ir))
+			regs->regs[MIPSInst_RT(ir)] =
+				(s32)regs->regs[MIPSInst_RS(ir)] +
+				(s32)MIPSInst_SIMM(ir);
+		return 0;
+	case daddiu_op:
+		if (config_enabled(CONFIG_32BIT))
+			break;
+
+		if (MIPSInst_RT(ir))
+			regs->regs[MIPSInst_RT(ir)] =
+				(s64)regs->regs[MIPSInst_RS(ir)] +
+				(s64)MIPSInst_SIMM(ir);
+		return 0;
+	case lwc1_op:
+	case swc1_op:
+	case cop1_op:
+	case cop1x_op:
+		/* FPU instructions in delay slot */
+		return -SIGFPE;
+	case spec_op:
+		switch (MIPSInst_FUNC(ir)) {
+		case or_op:
+			if (MIPSInst_RD(ir))
+				regs->regs[MIPSInst_RD(ir)] =
+					regs->regs[MIPSInst_RS(ir)] |
+					regs->regs[MIPSInst_RT(ir)];
+			return 0;
+		case sll_op:
+			if (MIPSInst_RS(ir))
+				break;
+
+			if (MIPSInst_RD(ir))
+				regs->regs[MIPSInst_RD(ir)] =
+					(s32)(((u32)regs->regs[MIPSInst_RT(ir)]) <<
+						MIPSInst_FD(ir));
+			return 0;
+		case srl_op:
+			if (MIPSInst_RS(ir))
+				break;
+
+			if (MIPSInst_RD(ir))
+				regs->regs[MIPSInst_RD(ir)] =
+					(s32)(((u32)regs->regs[MIPSInst_RT(ir)]) >>
+						MIPSInst_FD(ir));
+			return 0;
+		case addu_op:
+			if (MIPSInst_FD(ir))
+				break;
+
+			if (MIPSInst_RD(ir))
+				regs->regs[MIPSInst_RD(ir)] =
+					(s32)((u32)regs->regs[MIPSInst_RS(ir)] +
+					      (u32)regs->regs[MIPSInst_RT(ir)]);
+			return 0;
+		case subu_op:
+			if (MIPSInst_FD(ir))
+				break;
+
+			if (MIPSInst_RD(ir))
+				regs->regs[MIPSInst_RD(ir)] =
+					(s32)((u32)regs->regs[MIPSInst_RS(ir)] -
+					      (u32)regs->regs[MIPSInst_RT(ir)]);
+			return 0;
+		case dsll_op:
+			if (config_enabled(CONFIG_32BIT) || MIPSInst_RS(ir))
+				break;
+
+			if (MIPSInst_RD(ir))
+				regs->regs[MIPSInst_RD(ir)] =
+					(s64)(((u64)regs->regs[MIPSInst_RT(ir)]) <<
+						MIPSInst_FD(ir));
+			return 0;
+		case dsrl_op:
+			if (config_enabled(CONFIG_32BIT) || MIPSInst_RS(ir))
+				break;
+
+			if (MIPSInst_RD(ir))
+				regs->regs[MIPSInst_RD(ir)] =
+					(s64)(((u64)regs->regs[MIPSInst_RT(ir)]) >>
+						MIPSInst_FD(ir));
+			return 0;
+		case daddu_op:
+			if (config_enabled(CONFIG_32BIT) || MIPSInst_FD(ir))
+				break;
+
+			if (MIPSInst_RD(ir))
+				regs->regs[MIPSInst_RD(ir)] =
+					(u64)regs->regs[MIPSInst_RS(ir)] +
+					(u64)regs->regs[MIPSInst_RT(ir)];
+			return 0;
+		case dsubu_op:
+			if (config_enabled(CONFIG_32BIT) || MIPSInst_FD(ir))
+				break;
+
+			if (MIPSInst_RD(ir))
+				regs->regs[MIPSInst_RD(ir)] =
+					(s64)((u64)regs->regs[MIPSInst_RS(ir)] -
+					      (u64)regs->regs[MIPSInst_RT(ir)]);
+			return 0;
+		}
+		break;
+	default:
+		pr_debug("No fastpath BD emulation for instruction 0x%08x (op: %02x)\n",
+			 ir, MIPSInst_OPCODE(ir));
+	}
+
+	return SIGILL;
+}
+
+/**
+ * movt_func - Emulate a MOVT instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int movf_func(struct pt_regs *regs, u32 ir)
+{
+	u32 csr;
+	u32 cond;
+
+	csr = current->thread.fpu.fcr31;
+	cond = fpucondbit[MIPSInst_RT(ir) >> 2];
+	if (((csr & cond) == 0) && MIPSInst_RD(ir))
+		regs->regs[MIPSInst_RD(ir)] = regs->regs[MIPSInst_RS(ir)];
+	MIPS_R2_STATS(movs);
+	return 0;
+}
+
+/**
+ * movt_func - Emulate a MOVT instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int movt_func(struct pt_regs *regs, u32 ir)
+{
+	u32 csr;
+	u32 cond;
+
+	csr = current->thread.fpu.fcr31;
+	cond = fpucondbit[MIPSInst_RT(ir) >> 2];
+
+	if (((csr & cond) != 0) && MIPSInst_RD(ir))
+		regs->regs[MIPSInst_RD(ir)] = regs->regs[MIPSInst_RS(ir)];
+
+	MIPS_R2_STATS(movs);
+
+	return 0;
+}
+
+/**
+ * jr_func - Emulate a JR instruction.
+ * @pt_regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns SIGILL if JR was in delay slot, SIGEMT if we
+ * can't compute the EPC, SIGSEGV if we can't access the
+ * userland instruction or 0 on success.
+ */
+static int jr_func(struct pt_regs *regs, u32 ir)
+{
+	int err;
+	unsigned long cepc, epc, nepc;
+	u32 nir;
+
+	if (delay_slot(regs))
+		return SIGILL;
+
+	/* EPC after the RI/JR instruction */
+	nepc = regs->cp0_epc;
+	/* Roll back to the reserved R2 JR instruction */
+	regs->cp0_epc -= 4;
+	epc = regs->cp0_epc;
+	err = __compute_return_epc(regs);
+
+	if (err < 0)
+		return SIGEMT;
+
+
+	/* Computed EPC */
+	cepc = regs->cp0_epc;
+
+	/* Get DS instruction */
+	err = __get_user(nir, (u32 __user *)nepc);
+	if (err)
+		return SIGSEGV;
+
+	MIPS_R2BR_STATS(jrs);
+
+	/* If nir == 0(NOP), then nothing else to do */
+	if (nir) {
+		/*
+		 * Negative err means FPU instruction in BD-slot,
+		 * Zero err means 'BD-slot emulation done'
+		 * For anything else we go back to trampoline emulation.
+		 */
+		err = mipsr6_emul(regs, nir);
+		if (err > 0) {
+			regs->cp0_epc = nepc;
+			err = mips_dsemul(regs, nir, cepc);
+			if (err == SIGILL)
+				err = SIGEMT;
+			MIPS_R2_STATS(dsemul);
+		}
+	}
+
+	return err;
+}
+
+/**
+ * movz_func - Emulate a MOVZ instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int movz_func(struct pt_regs *regs, u32 ir)
+{
+	if (((regs->regs[MIPSInst_RT(ir)]) == 0) && MIPSInst_RD(ir))
+		regs->regs[MIPSInst_RD(ir)] = regs->regs[MIPSInst_RS(ir)];
+	MIPS_R2_STATS(movs);
+
+	return 0;
+}
+
+/**
+ * movn_func - Emulate a MOVZ instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int movn_func(struct pt_regs *regs, u32 ir)
+{
+	if (((regs->regs[MIPSInst_RT(ir)]) != 0) && MIPSInst_RD(ir))
+		regs->regs[MIPSInst_RD(ir)] = regs->regs[MIPSInst_RS(ir)];
+	MIPS_R2_STATS(movs);
+
+	return 0;
+}
+
+/**
+ * mfhi_func - Emulate a MFHI instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int mfhi_func(struct pt_regs *regs, u32 ir)
+{
+	if (MIPSInst_RD(ir))
+		regs->regs[MIPSInst_RD(ir)] = regs->hi;
+
+	MIPS_R2_STATS(hilo);
+
+	return 0;
+}
+
+/**
+ * mthi_func - Emulate a MTHI instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int mthi_func(struct pt_regs *regs, u32 ir)
+{
+	regs->hi = regs->regs[MIPSInst_RS(ir)];
+
+	MIPS_R2_STATS(hilo);
+
+	return 0;
+}
+
+/**
+ * mflo_func - Emulate a MFLO instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int mflo_func(struct pt_regs *regs, u32 ir)
+{
+	if (MIPSInst_RD(ir))
+		regs->regs[MIPSInst_RD(ir)] = regs->lo;
+
+	MIPS_R2_STATS(hilo);
+
+	return 0;
+}
+
+/**
+ * mtlo_func - Emulate a MTLO instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int mtlo_func(struct pt_regs *regs, u32 ir)
+{
+	regs->lo = regs->regs[MIPSInst_RS(ir)];
+
+	MIPS_R2_STATS(hilo);
+
+	return 0;
+}
+
+/**
+ * mult_func - Emulate a MULT instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int mult_func(struct pt_regs *regs, u32 ir)
+{
+	s64 res;
+	s32 rt, rs;
+
+	rt = regs->regs[MIPSInst_RT(ir)];
+	rs = regs->regs[MIPSInst_RS(ir)];
+	res = (s64)rt * (s64)rs;
+
+	rs = res;
+	regs->lo = (s64)rs;
+	rt = res >> 32;
+	res = (s64)rt;
+	regs->hi = res;
+
+	MIPS_R2_STATS(muls);
+
+	return 0;
+}
+
+/**
+ * multu_func - Emulate a MULTU instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int multu_func(struct pt_regs *regs, u32 ir)
+{
+	u64 res;
+	u32 rt, rs;
+
+	rt = regs->regs[MIPSInst_RT(ir)];
+	rs = regs->regs[MIPSInst_RS(ir)];
+	res = (u64)rt * (u64)rs;
+	rt = res;
+	regs->lo = (s64)rt;
+	regs->hi = (s64)(res >> 32);
+
+	MIPS_R2_STATS(muls);
+
+	return 0;
+}
+
+/**
+ * div_func - Emulate a DIV instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int div_func(struct pt_regs *regs, u32 ir)
+{
+	s32 rt, rs;
+
+	rt = regs->regs[MIPSInst_RT(ir)];
+	rs = regs->regs[MIPSInst_RS(ir)];
+
+	regs->lo = (s64)(rs / rt);
+	regs->hi = (s64)(rs % rt);
+
+	MIPS_R2_STATS(divs);
+
+	return 0;
+}
+
+/**
+ * divu_func - Emulate a DIVU instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int divu_func(struct pt_regs *regs, u32 ir)
+{
+	u32 rt, rs;
+
+	rt = regs->regs[MIPSInst_RT(ir)];
+	rs = regs->regs[MIPSInst_RS(ir)];
+
+	regs->lo = (s64)(rs / rt);
+	regs->hi = (s64)(rs % rt);
+
+	MIPS_R2_STATS(divs);
+
+	return 0;
+}
+
+/**
+ * dmult_func - Emulate a DMULT instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 on success or SIGILL for 32-bit kernels.
+ */
+static int dmult_func(struct pt_regs *regs, u32 ir)
+{
+	s64 res;
+	s64 rt, rs;
+
+	if (config_enabled(CONFIG_32BIT))
+		return SIGILL;
+
+	rt = regs->regs[MIPSInst_RT(ir)];
+	rs = regs->regs[MIPSInst_RS(ir)];
+	res = rt * rs;
+
+	regs->lo = res;
+	__asm__ __volatile__(
+		"dmuh %0, %1, %2\t\n"
+		: "=r"(res)
+		: "r"(rt), "r"(rs));
+
+	regs->hi = res;
+
+	MIPS_R2_STATS(muls);
+
+	return 0;
+}
+
+/**
+ * dmultu_func - Emulate a DMULTU instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 on success or SIGILL for 32-bit kernels.
+ */
+static int dmultu_func(struct pt_regs *regs, u32 ir)
+{
+	u64 res;
+	u64 rt, rs;
+
+	if (config_enabled(CONFIG_32BIT))
+		return SIGILL;
+
+	rt = regs->regs[MIPSInst_RT(ir)];
+	rs = regs->regs[MIPSInst_RS(ir)];
+	res = rt * rs;
+
+	regs->lo = res;
+	__asm__ __volatile__(
+		"dmuhu %0, %1, %2\t\n"
+		: "=r"(res)
+		: "r"(rt), "r"(rs));
+
+	regs->hi = res;
+
+	MIPS_R2_STATS(muls);
+
+	return 0;
+}
+
+/**
+ * ddiv_func - Emulate a DDIV instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 on success or SIGILL for 32-bit kernels.
+ */
+static int ddiv_func(struct pt_regs *regs, u32 ir)
+{
+	s64 rt, rs;
+
+	if (config_enabled(CONFIG_32BIT))
+		return SIGILL;
+
+	rt = regs->regs[MIPSInst_RT(ir)];
+	rs = regs->regs[MIPSInst_RS(ir)];
+
+	regs->lo = rs / rt;
+	regs->hi = rs % rt;
+
+	MIPS_R2_STATS(divs);
+
+	return 0;
+}
+
+/**
+ * ddivu_func - Emulate a DDIVU instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 on success or SIGILL for 32-bit kernels.
+ */
+static int ddivu_func(struct pt_regs *regs, u32 ir)
+{
+	u64 rt, rs;
+
+	if (config_enabled(CONFIG_32BIT))
+		return SIGILL;
+
+	rt = regs->regs[MIPSInst_RT(ir)];
+	rs = regs->regs[MIPSInst_RS(ir)];
+
+	regs->lo = rs / rt;
+	regs->hi = rs % rt;
+
+	MIPS_R2_STATS(divs);
+
+	return 0;
+}
+
+/* R6 removed instructions for the SPECIAL opcode */
+static struct r2_decoder_table spec_op_table[] = {
+	{ 0xfc1ff83f, 0x00000008, jr_func },
+	{ 0xfc00ffff, 0x00000018, mult_func },
+	{ 0xfc00ffff, 0x00000019, multu_func },
+	{ 0xfc00ffff, 0x0000001c, dmult_func },
+	{ 0xfc00ffff, 0x0000001d, dmultu_func },
+	{ 0xffff07ff, 0x00000010, mfhi_func },
+	{ 0xfc1fffff, 0x00000011, mthi_func },
+	{ 0xffff07ff, 0x00000012, mflo_func },
+	{ 0xfc1fffff, 0x00000013, mtlo_func },
+	{ 0xfc0307ff, 0x00000001, movf_func },
+	{ 0xfc0307ff, 0x00010001, movt_func },
+	{ 0xfc0007ff, 0x0000000a, movz_func },
+	{ 0xfc0007ff, 0x0000000b, movn_func },
+	{ 0xfc00ffff, 0x0000001a, div_func },
+	{ 0xfc00ffff, 0x0000001b, divu_func },
+	{ 0xfc00ffff, 0x0000001e, ddiv_func },
+	{ 0xfc00ffff, 0x0000001f, ddivu_func },
+	{}
+};
+
+/**
+ * madd_func - Emulate a MADD instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int madd_func(struct pt_regs *regs, u32 ir)
+{
+	s64 res;
+	s32 rt, rs;
+
+	rt = regs->regs[MIPSInst_RT(ir)];
+	rs = regs->regs[MIPSInst_RS(ir)];
+	res = (s64)rt * (s64)rs;
+	rt = regs->hi;
+	rs = regs->lo;
+	res += ((((s64)rt) << 32) | (u32)rs);
+
+	rt = res;
+	regs->lo = (s64)rt;
+	rs = res >> 32;
+	regs->hi = (s64)rs;
+
+	MIPS_R2_STATS(dsps);
+
+	return 0;
+}
+
+/**
+ * maddu_func - Emulate a MADDU instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int maddu_func(struct pt_regs *regs, u32 ir)
+{
+	u64 res;
+	u32 rt, rs;
+
+	rt = regs->regs[MIPSInst_RT(ir)];
+	rs = regs->regs[MIPSInst_RS(ir)];
+	res = (u64)rt * (u64)rs;
+	rt = regs->hi;
+	rs = regs->lo;
+	res += ((((s64)rt) << 32) | (u32)rs);
+
+	rt = res;
+	regs->lo = (s64)rt;
+	rs = res >> 32;
+	regs->hi = (s64)rs;
+
+	MIPS_R2_STATS(dsps);
+
+	return 0;
+}
+
+/**
+ * msub_func - Emulate a MSUB instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int msub_func(struct pt_regs *regs, u32 ir)
+{
+	s64 res;
+	s32 rt, rs;
+
+	rt = regs->regs[MIPSInst_RT(ir)];
+	rs = regs->regs[MIPSInst_RS(ir)];
+	res = (s64)rt * (s64)rs;
+	rt = regs->hi;
+	rs = regs->lo;
+	res = ((((s64)rt) << 32) | (u32)rs) - res;
+
+	rt = res;
+	regs->lo = (s64)rt;
+	rs = res >> 32;
+	regs->hi = (s64)rs;
+
+	MIPS_R2_STATS(dsps);
+
+	return 0;
+}
+
+/**
+ * msubu_func - Emulate a MSUBU instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int msubu_func(struct pt_regs *regs, u32 ir)
+{
+	u64 res;
+	u32 rt, rs;
+
+	rt = regs->regs[MIPSInst_RT(ir)];
+	rs = regs->regs[MIPSInst_RS(ir)];
+	res = (u64)rt * (u64)rs;
+	rt = regs->hi;
+	rs = regs->lo;
+	res = ((((s64)rt) << 32) | (u32)rs) - res;
+
+	rt = res;
+	regs->lo = (s64)rt;
+	rs = res >> 32;
+	regs->hi = (s64)rs;
+
+	MIPS_R2_STATS(dsps);
+
+	return 0;
+}
+
+/**
+ * mul_func - Emulate a MUL instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int mul_func(struct pt_regs *regs, u32 ir)
+{
+	s64 res;
+	s32 rt, rs;
+
+	if (!MIPSInst_RD(ir))
+		return 0;
+	rt = regs->regs[MIPSInst_RT(ir)];
+	rs = regs->regs[MIPSInst_RS(ir)];
+	res = (s64)rt * (s64)rs;
+
+	rs = res;
+	regs->regs[MIPSInst_RD(ir)] = (s64)rs;
+
+	MIPS_R2_STATS(muls);
+
+	return 0;
+}
+
+/**
+ * clz_func - Emulate a CLZ instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int clz_func(struct pt_regs *regs, u32 ir)
+{
+	u32 res;
+	u32 rs;
+
+	if (!MIPSInst_RD(ir))
+		return 0;
+
+	rs = regs->regs[MIPSInst_RS(ir)];
+	__asm__ __volatile__("clz %0, %1" : "=r"(res) : "r"(rs));
+	regs->regs[MIPSInst_RD(ir)] = res;
+
+	MIPS_R2_STATS(bops);
+
+	return 0;
+}
+
+/**
+ * clo_func - Emulate a CLO instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+
+static int clo_func(struct pt_regs *regs, u32 ir)
+{
+	u32 res;
+	u32 rs;
+
+	if (!MIPSInst_RD(ir))
+		return 0;
+
+	rs = regs->regs[MIPSInst_RS(ir)];
+	__asm__ __volatile__("clo %0, %1" : "=r"(res) : "r"(rs));
+	regs->regs[MIPSInst_RD(ir)] = res;
+
+	MIPS_R2_STATS(bops);
+
+	return 0;
+}
+
+/**
+ * dclz_func - Emulate a DCLZ instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int dclz_func(struct pt_regs *regs, u32 ir)
+{
+	u64 res;
+	u64 rs;
+
+	if (config_enabled(CONFIG_32BIT))
+		return SIGILL;
+
+	if (!MIPSInst_RD(ir))
+		return 0;
+
+	rs = regs->regs[MIPSInst_RS(ir)];
+	__asm__ __volatile__("dclz %0, %1" : "=r"(res) : "r"(rs));
+	regs->regs[MIPSInst_RD(ir)] = res;
+
+	MIPS_R2_STATS(bops);
+
+	return 0;
+}
+
+/**
+ * dclo_func - Emulate a DCLO instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int dclo_func(struct pt_regs *regs, u32 ir)
+{
+	u64 res;
+	u64 rs;
+
+	if (config_enabled(CONFIG_32BIT))
+		return SIGILL;
+
+	if (!MIPSInst_RD(ir))
+		return 0;
+
+	rs = regs->regs[MIPSInst_RS(ir)];
+	__asm__ __volatile__("dclo %0, %1" : "=r"(res) : "r"(rs));
+	regs->regs[MIPSInst_RD(ir)] = res;
+
+	MIPS_R2_STATS(bops);
+
+	return 0;
+}
+
+/* R6 removed instructions for the SPECIAL2 opcode */
+static struct r2_decoder_table spec2_op_table[] = {
+	{ 0xfc00ffff, 0x70000000, madd_func },
+	{ 0xfc00ffff, 0x70000001, maddu_func },
+	{ 0xfc0007ff, 0x70000002, mul_func },
+	{ 0xfc00ffff, 0x70000004, msub_func },
+	{ 0xfc00ffff, 0x70000005, msubu_func },
+	{ 0xfc0007ff, 0x70000020, clz_func },
+	{ 0xfc0007ff, 0x70000021, clo_func },
+	{ 0xfc0007ff, 0x70000024, dclz_func },
+	{ 0xfc0007ff, 0x70000025, dclo_func },
+	{ }
+};
+
+static inline int mipsr2_find_op_func(struct pt_regs *regs, u32 inst,
+				      struct r2_decoder_table *table)
+{
+	struct r2_decoder_table *p;
+	int err;
+
+	for (p = table; p->func; p++) {
+		if ((inst & p->mask) == p->code) {
+			err = (p->func)(regs, inst);
+			return err;
+		}
+	}
+	return SIGILL;
+}
+
+/**
+ * mipsr2_decoder: Decode and emulate a MIPS R2 instruction
+ * @regs: Process register set
+ * @inst: Instruction to decode and emulate
+ */
+int mipsr2_decoder(struct pt_regs *regs, u32 inst)
+{
+	int err = 0;
+	unsigned long vaddr;
+	u32 nir;
+	unsigned long cpc, epc, nepc, r31, res, rs, rt;
+
+	void __user *fault_addr = NULL;
+	int pass = 0;
+
+repeat:
+	r31 = regs->regs[31];
+	epc = regs->cp0_epc;
+	err = compute_return_epc(regs);
+	if (err < 0) {
+		BUG();
+		return SIGEMT;
+	}
+	pr_debug("Emulating the 0x%08x R2 instruction @ 0x%08lx (pass=%d))\n",
+		 inst, epc, pass);
+
+	switch (MIPSInst_OPCODE(inst)) {
+	case spec_op:
+		err = mipsr2_find_op_func(regs, inst, spec_op_table);
+		if (err < 0) {
+			/* FPU instruction under JR */
+			regs->cp0_cause |= CAUSEF_BD;
+			goto fpu_emul;
+		}
+		break;
+	case spec2_op:
+		err = mipsr2_find_op_func(regs, inst, spec2_op_table);
+		break;
+	case bcond_op:
+		rt = MIPSInst_RT(inst);
+		rs = MIPSInst_RS(inst);
+		switch (rt) {
+		case tgei_op:
+			if ((long)regs->regs[rs] >= MIPSInst_SIMM(inst))
+				do_trap_or_bp(regs, 0, "TGEI");
+
+			MIPS_R2_STATS(traps);
+
+			break;
+		case tgeiu_op:
+			if (regs->regs[rs] >= MIPSInst_UIMM(inst))
+				do_trap_or_bp(regs, 0, "TGEIU");
+
+			MIPS_R2_STATS(traps);
+
+			break;
+		case tlti_op:
+			if ((long)regs->regs[rs] < MIPSInst_SIMM(inst))
+				do_trap_or_bp(regs, 0, "TLTI");
+
+			MIPS_R2_STATS(traps);
+
+			break;
+		case tltiu_op:
+			if (regs->regs[rs] < MIPSInst_UIMM(inst))
+				do_trap_or_bp(regs, 0, "TLTIU");
+
+			MIPS_R2_STATS(traps);
+
+			break;
+		case teqi_op:
+			if (regs->regs[rs] == MIPSInst_SIMM(inst))
+				do_trap_or_bp(regs, 0, "TEQI");
+
+			MIPS_R2_STATS(traps);
+
+			break;
+		case tnei_op:
+			if (regs->regs[rs] != MIPSInst_SIMM(inst))
+				do_trap_or_bp(regs, 0, "TNEI");
+
+			MIPS_R2_STATS(traps);
+
+			break;
+		case bltzl_op:
+		case bgezl_op:
+		case bltzall_op:
+		case bgezall_op:
+			if (delay_slot(regs)) {
+				err = SIGILL;
+				break;
+			}
+			regs->regs[31] = r31;
+			regs->cp0_epc = epc;
+			err = __compute_return_epc(regs);
+			if (err < 0)
+				return SIGEMT;
+			if (err != BRANCH_LIKELY_TAKEN)
+				break;
+			cpc = regs->cp0_epc;
+			nepc = epc + 4;
+			err = __get_user(nir, (u32 __user *)nepc);
+			if (err) {
+				err = SIGSEGV;
+				break;
+			}
+			/*
+			 * This will probably be optimized away when
+			 * CONFIG_DEBUG_FS is not enabled
+			 */
+			switch (rt) {
+			case bltzl_op:
+				MIPS_R2BR_STATS(bltzl);
+				break;
+			case bgezl_op:
+				MIPS_R2BR_STATS(bgezl);
+				break;
+			case bltzall_op:
+				MIPS_R2BR_STATS(bltzall);
+				break;
+			case bgezall_op:
+				MIPS_R2BR_STATS(bgezall);
+				break;
+			}
+
+			switch (MIPSInst_OPCODE(nir)) {
+			case cop1_op:
+			case cop1x_op:
+			case lwc1_op:
+			case swc1_op:
+				regs->cp0_cause |= CAUSEF_BD;
+				goto fpu_emul;
+			}
+			if (nir) {
+				err = mipsr6_emul(regs, nir);
+				if (err > 0) {
+					err = mips_dsemul(regs, nir, cpc);
+					if (err == SIGILL)
+						err = SIGEMT;
+					MIPS_R2_STATS(dsemul);
+				}
+			}
+			break;
+		case bltzal_op:
+		case bgezal_op:
+			if (delay_slot(regs)) {
+				err = SIGILL;
+				break;
+			}
+			regs->regs[31] = r31;
+			regs->cp0_epc = epc;
+			err = __compute_return_epc(regs);
+			if (err < 0)
+				return SIGEMT;
+			cpc = regs->cp0_epc;
+			nepc = epc + 4;
+			err = __get_user(nir, (u32 __user *)nepc);
+			if (err) {
+				err = SIGSEGV;
+				break;
+			}
+			/*
+			 * This will probably be optimized away when
+			 * CONFIG_DEBUG_FS is not enabled
+			 */
+			switch (rt) {
+			case bltzal_op:
+				MIPS_R2BR_STATS(bltzal);
+				break;
+			case bgezal_op:
+				MIPS_R2BR_STATS(bgezal);
+				break;
+			}
+
+			switch (MIPSInst_OPCODE(nir)) {
+			case cop1_op:
+			case cop1x_op:
+			case lwc1_op:
+			case swc1_op:
+				regs->cp0_cause |= CAUSEF_BD;
+				goto fpu_emul;
+			}
+			if (nir) {
+				err = mipsr6_emul(regs, nir);
+				if (err > 0) {
+					err = mips_dsemul(regs, nir, cpc);
+					if (err == SIGILL)
+						err = SIGEMT;
+					MIPS_R2_STATS(dsemul);
+				}
+			}
+			break;
+		default:
+			regs->regs[31] = r31;
+			regs->cp0_epc = epc;
+			err = SIGILL;
+			break;
+		}
+		break;
+
+	case beql_op:
+	case bnel_op:
+	case blezl_op:
+	case bgtzl_op:
+		if (delay_slot(regs)) {
+			err = SIGILL;
+			break;
+		}
+		regs->regs[31] = r31;
+		regs->cp0_epc = epc;
+		err = __compute_return_epc(regs);
+		if (err < 0)
+			return SIGEMT;
+		if (err != BRANCH_LIKELY_TAKEN)
+			break;
+		cpc = regs->cp0_epc;
+		nepc = epc + 4;
+		err = __get_user(nir, (u32 __user *)nepc);
+		if (err) {
+			err = SIGSEGV;
+			break;
+		}
+		/*
+		 * This will probably be optimized away when
+		 * CONFIG_DEBUG_FS is not enabled
+		 */
+		switch (MIPSInst_OPCODE(inst)) {
+		case beql_op:
+			MIPS_R2BR_STATS(beql);
+			break;
+		case bnel_op:
+			MIPS_R2BR_STATS(bnel);
+			break;
+		case blezl_op:
+			MIPS_R2BR_STATS(blezl);
+			break;
+		case bgtzl_op:
+			MIPS_R2BR_STATS(bgtzl);
+			break;
+		}
+
+		switch (MIPSInst_OPCODE(nir)) {
+		case cop1_op:
+		case cop1x_op:
+		case lwc1_op:
+		case swc1_op:
+			regs->cp0_cause |= CAUSEF_BD;
+			goto fpu_emul;
+		}
+		if (nir) {
+			err = mipsr6_emul(regs, nir);
+			if (err > 0) {
+				err = mips_dsemul(regs, nir, cpc);
+				if (err == SIGILL)
+					err = SIGEMT;
+				MIPS_R2_STATS(dsemul);
+			}
+		}
+		break;
+	case lwc1_op:
+	case swc1_op:
+	case cop1_op:
+	case cop1x_op:
+fpu_emul:
+		regs->regs[31] = r31;
+		regs->cp0_epc = epc;
+		if (!used_math()) {     /* First time FPU user.  */
+			err = init_fpu();
+			set_used_math();
+		}
+		lose_fpu(1);    /* Save FPU state for the emulator. */
+
+		err = fpu_emulator_cop1Handler(regs, &current->thread.fpu, 0,
+					       &fault_addr);
+
+		/*
+		 * this is a tricky issue - lose_fpu() uses LL/SC atomics
+		 * if FPU is owned and effectively cancels user level LL/SC.
+		 * So, it could be logical to don't restore FPU ownership here.
+		 * But the sequence of multiple FPU instructions is much much
+		 * more often than LL-FPU-SC and I prefer loop here until
+		 * next scheduler cycle cancels FPU ownership
+		 */
+		own_fpu(1);	/* Restore FPU state. */
+
+		if (err)
+			current->thread.cp0_baduaddr = (unsigned long)fault_addr;
+
+		MIPS_R2_STATS(fpus);
+
+		break;
+
+	case lwl_op:
+		rt = regs->regs[MIPSInst_RT(inst)];
+		vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst);
+		if (!access_ok(VERIFY_READ, vaddr, 4)) {
+			current->thread.cp0_baduaddr = vaddr;
+			err = SIGSEGV;
+			break;
+		}
+		__asm__ __volatile__(
+			"	.set	push\n"
+			"	.set	reorder\n"
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+			"1:"	LB	"%1, 0(%2)\n"
+				INS	"%0, %1, 24, 8\n"
+			"	andi	%1, %2, 0x3\n"
+			"	beq	$0, %1, 9f\n"
+				ADDIU	"%2, %2, -1\n"
+			"2:"	LB	"%1, 0(%2)\n"
+				INS	"%0, %1, 16, 8\n"
+			"	andi	%1, %2, 0x3\n"
+			"	beq	$0, %1, 9f\n"
+				ADDIU	"%2, %2, -1\n"
+			"3:"	LB	"%1, 0(%2)\n"
+				INS	"%0, %1, 8, 8\n"
+			"	andi	%1, %2, 0x3\n"
+			"	beq	$0, %1, 9f\n"
+				ADDIU	"%2, %2, -1\n"
+			"4:"	LB	"%1, 0(%2)\n"
+				INS	"%0, %1, 0, 8\n"
+#else /* !CONFIG_CPU_LITTLE_ENDIAN */
+			"1:"	LB	"%1, 0(%2)\n"
+				INS	"%0, %1, 24, 8\n"
+				ADDIU	"%2, %2, 1\n"
+			"	andi	%1, %2, 0x3\n"
+			"	beq	$0, %1, 9f\n"
+			"2:"	LB	"%1, 0(%2)\n"
+				INS	"%0, %1, 16, 8\n"
+				ADDIU	"%2, %2, 1\n"
+			"	andi	%1, %2, 0x3\n"
+			"	beq	$0, %1, 9f\n"
+			"3:"	LB	"%1, 0(%2)\n"
+				INS	"%0, %1, 8, 8\n"
+				ADDIU	"%2, %2, 1\n"
+			"	andi	%1, %2, 0x3\n"
+			"	beq	$0, %1, 9f\n"
+			"4:"	LB	"%1, 0(%2)\n"
+				INS	"%0, %1, 0, 8\n"
+#endif /* CONFIG_CPU_LITTLE_ENDIAN */
+			"9:	sll	%0, %0, 0\n"
+			"10:\n"
+			"	.insn\n"
+			"	.section	.fixup,\"ax\"\n"
+			"8:	li	%3,%4\n"
+			"	j	10b\n"
+			"	.previous\n"
+			"	.section	__ex_table,\"a\"\n"
+			"	.word	1b,8b\n"
+			"	.word	2b,8b\n"
+			"	.word	3b,8b\n"
+			"	.word	4b,8b\n"
+			"	.previous\n"
+			"	.set	pop\n"
+			: "+&r"(rt), "=&r"(rs),
+			  "+&r"(vaddr), "+&r"(err)
+			: "i"(SIGSEGV));
+
+		if (MIPSInst_RT(inst) && !err)
+			regs->regs[MIPSInst_RT(inst)] = rt;
+
+		MIPS_R2_STATS(loads);
+
+		break;
+
+	case lwr_op:
+		rt = regs->regs[MIPSInst_RT(inst)];
+		vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst);
+		if (!access_ok(VERIFY_READ, vaddr, 4)) {
+			current->thread.cp0_baduaddr = vaddr;
+			err = SIGSEGV;
+			break;
+		}
+		__asm__ __volatile__(
+			"       .set	push\n"
+			"       .set	reorder\n"
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+			"1:"    LB	"%1, 0(%2)\n"
+				INS	"%0, %1, 0, 8\n"
+				ADDIU	"%2, %2, 1\n"
+			"       andi	%1, %2, 0x3\n"
+			"       beq	$0, %1, 9f\n"
+			"2:"    LB	"%1, 0(%2)\n"
+				INS	"%0, %1, 8, 8\n"
+				ADDIU	"%2, %2, 1\n"
+			"       andi	%1, %2, 0x3\n"
+			"       beq	$0, %1, 9f\n"
+			"3:"    LB	"%1, 0(%2)\n"
+				INS	"%0, %1, 16, 8\n"
+				ADDIU	"%2, %2, 1\n"
+			"       andi	%1, %2, 0x3\n"
+			"       beq	$0, %1, 9f\n"
+			"4:"    LB	"%1, 0(%2)\n"
+				INS	"%0, %1, 24, 8\n"
+			"       sll	%0, %0, 0\n"
+#else /* !CONFIG_CPU_LITTLE_ENDIAN */
+			"1:"    LB	"%1, 0(%2)\n"
+				INS	"%0, %1, 0, 8\n"
+			"       andi	%1, %2, 0x3\n"
+			"       beq	$0, %1, 9f\n"
+				ADDIU	"%2, %2, -1\n"
+			"2:"    LB	"%1, 0(%2)\n"
+				INS	"%0, %1, 8, 8\n"
+			"       andi	%1, %2, 0x3\n"
+			"       beq	$0, %1, 9f\n"
+				ADDIU	"%2, %2, -1\n"
+			"3:"    LB	"%1, 0(%2)\n"
+				INS	"%0, %1, 16, 8\n"
+			"       andi	%1, %2, 0x3\n"
+			"       beq	$0, %1, 9f\n"
+				ADDIU	"%2, %2, -1\n"
+			"4:"    LB	"%1, 0(%2)\n"
+				INS	"%0, %1, 24, 8\n"
+			"       sll	%0, %0, 0\n"
+#endif /* CONFIG_CPU_LITTLE_ENDIAN */
+			"9:\n"
+			"10:\n"
+			"	.insn\n"
+			"	.section	.fixup,\"ax\"\n"
+			"8:	li	%3,%4\n"
+			"	j	10b\n"
+			"       .previous\n"
+			"	.section	__ex_table,\"a\"\n"
+			"	.word	1b,8b\n"
+			"	.word	2b,8b\n"
+			"	.word	3b,8b\n"
+			"	.word	4b,8b\n"
+			"	.previous\n"
+			"	.set	pop\n"
+			: "+&r"(rt), "=&r"(rs),
+			  "+&r"(vaddr), "+&r"(err)
+			: "i"(SIGSEGV));
+		if (MIPSInst_RT(inst) && !err)
+			regs->regs[MIPSInst_RT(inst)] = rt;
+
+		MIPS_R2_STATS(loads);
+
+		break;
+
+	case swl_op:
+		rt = regs->regs[MIPSInst_RT(inst)];
+		vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst);
+		if (!access_ok(VERIFY_WRITE, vaddr, 4)) {
+			current->thread.cp0_baduaddr = vaddr;
+			err = SIGSEGV;
+			break;
+		}
+		__asm__ __volatile__(
+			"	.set	push\n"
+			"	.set	reorder\n"
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+				EXT	"%1, %0, 24, 8\n"
+			"1:"	SB	"%1, 0(%2)\n"
+			"	andi	%1, %2, 0x3\n"
+			"	beq	$0, %1, 9f\n"
+				ADDIU	"%2, %2, -1\n"
+				EXT	"%1, %0, 16, 8\n"
+			"2:"	SB	"%1, 0(%2)\n"
+			"	andi	%1, %2, 0x3\n"
+			"	beq	$0, %1, 9f\n"
+				ADDIU	"%2, %2, -1\n"
+				EXT	"%1, %0, 8, 8\n"
+			"3:"	SB	"%1, 0(%2)\n"
+			"	andi	%1, %2, 0x3\n"
+			"	beq	$0, %1, 9f\n"
+				ADDIU	"%2, %2, -1\n"
+				EXT	"%1, %0, 0, 8\n"
+			"4:"	SB	"%1, 0(%2)\n"
+#else /* !CONFIG_CPU_LITTLE_ENDIAN */
+				EXT	"%1, %0, 24, 8\n"
+			"1:"	SB	"%1, 0(%2)\n"
+				ADDIU	"%2, %2, 1\n"
+			"	andi	%1, %2, 0x3\n"
+			"	beq	$0, %1, 9f\n"
+				EXT	"%1, %0, 16, 8\n"
+			"2:"	SB	"%1, 0(%2)\n"
+				ADDIU	"%2, %2, 1\n"
+			"	andi	%1, %2, 0x3\n"
+			"	beq	$0, %1, 9f\n"
+				EXT	"%1, %0, 8, 8\n"
+			"3:"	SB	"%1, 0(%2)\n"
+				ADDIU	"%2, %2, 1\n"
+			"	andi	%1, %2, 0x3\n"
+			"	beq	$0, %1, 9f\n"
+				EXT	"%1, %0, 0, 8\n"
+			"4:"	SB	"%1, 0(%2)\n"
+#endif /* CONFIG_CPU_LITTLE_ENDIAN */
+			"9:\n"
+			"	.insn\n"
+			"       .section        .fixup,\"ax\"\n"
+			"8:	li	%3,%4\n"
+			"	j	9b\n"
+			"	.previous\n"
+			"	.section        __ex_table,\"a\"\n"
+			"	.word	1b,8b\n"
+			"	.word	2b,8b\n"
+			"	.word	3b,8b\n"
+			"	.word	4b,8b\n"
+			"	.previous\n"
+			"	.set	pop\n"
+			: "+&r"(rt), "=&r"(rs),
+			  "+&r"(vaddr), "+&r"(err)
+			: "i"(SIGSEGV)
+			: "memory");
+
+		MIPS_R2_STATS(stores);
+
+		break;
+
+	case swr_op:
+		rt = regs->regs[MIPSInst_RT(inst)];
+		vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst);
+		if (!access_ok(VERIFY_WRITE, vaddr, 4)) {
+			current->thread.cp0_baduaddr = vaddr;
+			err = SIGSEGV;
+			break;
+		}
+		__asm__ __volatile__(
+			"	.set	push\n"
+			"	.set	reorder\n"
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+				EXT	"%1, %0, 0, 8\n"
+			"1:"	SB	"%1, 0(%2)\n"
+				ADDIU	"%2, %2, 1\n"
+			"	andi	%1, %2, 0x3\n"
+			"	beq	$0, %1, 9f\n"
+				EXT	"%1, %0, 8, 8\n"
+			"2:"	SB	"%1, 0(%2)\n"
+				ADDIU	"%2, %2, 1\n"
+			"	andi	%1, %2, 0x3\n"
+			"	beq	$0, %1, 9f\n"
+				EXT	"%1, %0, 16, 8\n"
+			"3:"	SB	"%1, 0(%2)\n"
+				ADDIU	"%2, %2, 1\n"
+			"	andi	%1, %2, 0x3\n"
+			"	beq	$0, %1, 9f\n"
+				EXT	"%1, %0, 24, 8\n"
+			"4:"	SB	"%1, 0(%2)\n"
+#else /* !CONFIG_CPU_LITTLE_ENDIAN */
+				EXT	"%1, %0, 0, 8\n"
+			"1:"	SB	"%1, 0(%2)\n"
+			"	andi	%1, %2, 0x3\n"
+			"	beq	$0, %1, 9f\n"
+				ADDIU	"%2, %2, -1\n"
+				EXT	"%1, %0, 8, 8\n"
+			"2:"	SB	"%1, 0(%2)\n"
+			"	andi	%1, %2, 0x3\n"
+			"	beq	$0, %1, 9f\n"
+				ADDIU	"%2, %2, -1\n"
+				EXT	"%1, %0, 16, 8\n"
+			"3:"	SB	"%1, 0(%2)\n"
+			"	andi	%1, %2, 0x3\n"
+			"	beq	$0, %1, 9f\n"
+				ADDIU	"%2, %2, -1\n"
+				EXT	"%1, %0, 24, 8\n"
+			"4:"	SB	"%1, 0(%2)\n"
+#endif /* CONFIG_CPU_LITTLE_ENDIAN */
+			"9:\n"
+			"	.insn\n"
+			"	.section        .fixup,\"ax\"\n"
+			"8:	li	%3,%4\n"
+			"	j	9b\n"
+			"	.previous\n"
+			"	.section        __ex_table,\"a\"\n"
+			"	.word	1b,8b\n"
+			"	.word	2b,8b\n"
+			"	.word	3b,8b\n"
+			"	.word	4b,8b\n"
+			"	.previous\n"
+			"	.set	pop\n"
+			: "+&r"(rt), "=&r"(rs),
+			  "+&r"(vaddr), "+&r"(err)
+			: "i"(SIGSEGV)
+			: "memory");
+
+		MIPS_R2_STATS(stores);
+
+		break;
+
+	case ldl_op:
+		if (config_enabled(CONFIG_32BIT)) {
+		    err = SIGILL;
+		    break;
+		}
+
+		rt = regs->regs[MIPSInst_RT(inst)];
+		vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst);
+		if (!access_ok(VERIFY_READ, vaddr, 8)) {
+			current->thread.cp0_baduaddr = vaddr;
+			err = SIGSEGV;
+			break;
+		}
+		__asm__ __volatile__(
+			"	.set    push\n"
+			"	.set    reorder\n"
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+			"1:	lb	%1, 0(%2)\n"
+			"	dinsu	%0, %1, 56, 8\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	daddiu	%2, %2, -1\n"
+			"2:	lb	%1, 0(%2)\n"
+			"	dinsu	%0, %1, 48, 8\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	daddiu	%2, %2, -1\n"
+			"3:	lb	%1, 0(%2)\n"
+			"	dinsu	%0, %1, 40, 8\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	daddiu	%2, %2, -1\n"
+			"4:	lb	%1, 0(%2)\n"
+			"	dinsu	%0, %1, 32, 8\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	daddiu	%2, %2, -1\n"
+			"5:	lb	%1, 0(%2)\n"
+			"	dins	%0, %1, 24, 8\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	daddiu	%2, %2, -1\n"
+			"6:	lb	%1, 0(%2)\n"
+			"	dins	%0, %1, 16, 8\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	daddiu	%2, %2, -1\n"
+			"7:	lb	%1, 0(%2)\n"
+			"	dins	%0, %1, 8, 8\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	daddiu	%2, %2, -1\n"
+			"0:	lb	%1, 0(%2)\n"
+			"	dins	%0, %1, 0, 8\n"
+#else /* !CONFIG_CPU_LITTLE_ENDIAN */
+			"1:	lb	%1, 0(%2)\n"
+			"	dinsu	%0, %1, 56, 8\n"
+			"	daddiu	%2, %2, 1\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"2:	lb	%1, 0(%2)\n"
+			"	dinsu	%0, %1, 48, 8\n"
+			"	daddiu	%2, %2, 1\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"3:	lb	%1, 0(%2)\n"
+			"	dinsu	%0, %1, 40, 8\n"
+			"	daddiu  %2, %2, 1\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"4:	lb	%1, 0(%2)\n"
+			"	dinsu	%0, %1, 32, 8\n"
+			"	daddiu	%2, %2, 1\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"5:	lb	%1, 0(%2)\n"
+			"	dins	%0, %1, 24, 8\n"
+			"	daddiu	%2, %2, 1\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"6:	lb	%1, 0(%2)\n"
+			"	dins	%0, %1, 16, 8\n"
+			"	daddiu	%2, %2, 1\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"7:	lb	%1, 0(%2)\n"
+			"	dins	%0, %1, 8, 8\n"
+			"	daddiu	%2, %2, 1\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"0:	lb	%1, 0(%2)\n"
+			"	dins	%0, %1, 0, 8\n"
+#endif /* CONFIG_CPU_LITTLE_ENDIAN */
+			"9:\n"
+			"	.insn\n"
+			"	.section        .fixup,\"ax\"\n"
+			"8:	li	%3,%4\n"
+			"	j	9b\n"
+			"	.previous\n"
+			"	.section        __ex_table,\"a\"\n"
+			"	.word	1b,8b\n"
+			"	.word	2b,8b\n"
+			"	.word	3b,8b\n"
+			"	.word	4b,8b\n"
+			"	.word	5b,8b\n"
+			"	.word	6b,8b\n"
+			"	.word	7b,8b\n"
+			"	.word	0b,8b\n"
+			"	.previous\n"
+			"	.set	pop\n"
+			: "+&r"(rt), "=&r"(rs),
+			  "+&r"(vaddr), "+&r"(err)
+			: "i"(SIGSEGV));
+		if (MIPSInst_RT(inst) && !err)
+			regs->regs[MIPSInst_RT(inst)] = rt;
+
+		MIPS_R2_STATS(loads);
+		break;
+
+	case ldr_op:
+		if (config_enabled(CONFIG_32BIT)) {
+		    err = SIGILL;
+		    break;
+		}
+
+		rt = regs->regs[MIPSInst_RT(inst)];
+		vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst);
+		if (!access_ok(VERIFY_READ, vaddr, 8)) {
+			current->thread.cp0_baduaddr = vaddr;
+			err = SIGSEGV;
+			break;
+		}
+		__asm__ __volatile__(
+			"	.set    push\n"
+			"	.set    reorder\n"
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+			"1:	lb      %1, 0(%2)\n"
+			"	dins   %0, %1, 0, 8\n"
+			"	daddiu  %2, %2, 1\n"
+			"	andi    %1, %2, 0x7\n"
+			"	beq     $0, %1, 9f\n"
+			"2:	lb      %1, 0(%2)\n"
+			"	dins   %0, %1, 8, 8\n"
+			"	daddiu  %2, %2, 1\n"
+			"	andi    %1, %2, 0x7\n"
+			"	beq     $0, %1, 9f\n"
+			"3:	lb      %1, 0(%2)\n"
+			"	dins   %0, %1, 16, 8\n"
+			"	daddiu  %2, %2, 1\n"
+			"	andi    %1, %2, 0x7\n"
+			"	beq     $0, %1, 9f\n"
+			"4:	lb      %1, 0(%2)\n"
+			"	dins   %0, %1, 24, 8\n"
+			"	daddiu  %2, %2, 1\n"
+			"	andi    %1, %2, 0x7\n"
+			"	beq     $0, %1, 9f\n"
+			"5:	lb      %1, 0(%2)\n"
+			"	dinsu    %0, %1, 32, 8\n"
+			"	daddiu  %2, %2, 1\n"
+			"	andi    %1, %2, 0x7\n"
+			"	beq     $0, %1, 9f\n"
+			"6:	lb      %1, 0(%2)\n"
+			"	dinsu    %0, %1, 40, 8\n"
+			"	daddiu  %2, %2, 1\n"
+			"	andi    %1, %2, 0x7\n"
+			"	beq     $0, %1, 9f\n"
+			"7:	lb      %1, 0(%2)\n"
+			"	dinsu    %0, %1, 48, 8\n"
+			"	daddiu  %2, %2, 1\n"
+			"	andi    %1, %2, 0x7\n"
+			"	beq     $0, %1, 9f\n"
+			"0:	lb      %1, 0(%2)\n"
+			"	dinsu    %0, %1, 56, 8\n"
+#else /* !CONFIG_CPU_LITTLE_ENDIAN */
+			"1:	lb      %1, 0(%2)\n"
+			"	dins   %0, %1, 0, 8\n"
+			"	andi    %1, %2, 0x7\n"
+			"	beq     $0, %1, 9f\n"
+			"	daddiu  %2, %2, -1\n"
+			"2:	lb      %1, 0(%2)\n"
+			"	dins   %0, %1, 8, 8\n"
+			"	andi    %1, %2, 0x7\n"
+			"	beq     $0, %1, 9f\n"
+			"	daddiu  %2, %2, -1\n"
+			"3:	lb      %1, 0(%2)\n"
+			"	dins   %0, %1, 16, 8\n"
+			"	andi    %1, %2, 0x7\n"
+			"	beq     $0, %1, 9f\n"
+			"	daddiu  %2, %2, -1\n"
+			"4:	lb      %1, 0(%2)\n"
+			"	dins   %0, %1, 24, 8\n"
+			"	andi    %1, %2, 0x7\n"
+			"	beq     $0, %1, 9f\n"
+			"	daddiu  %2, %2, -1\n"
+			"5:	lb      %1, 0(%2)\n"
+			"	dinsu    %0, %1, 32, 8\n"
+			"	andi    %1, %2, 0x7\n"
+			"	beq     $0, %1, 9f\n"
+			"	daddiu  %2, %2, -1\n"
+			"6:	lb      %1, 0(%2)\n"
+			"	dinsu    %0, %1, 40, 8\n"
+			"	andi    %1, %2, 0x7\n"
+			"	beq     $0, %1, 9f\n"
+			"	daddiu  %2, %2, -1\n"
+			"7:	lb      %1, 0(%2)\n"
+			"	dinsu    %0, %1, 48, 8\n"
+			"	andi    %1, %2, 0x7\n"
+			"	beq     $0, %1, 9f\n"
+			"	daddiu  %2, %2, -1\n"
+			"0:	lb      %1, 0(%2)\n"
+			"	dinsu    %0, %1, 56, 8\n"
+#endif /* CONFIG_CPU_LITTLE_ENDIAN */
+			"9:\n"
+			"	.insn\n"
+			"	.section        .fixup,\"ax\"\n"
+			"8:	li     %3,%4\n"
+			"	j      9b\n"
+			"	.previous\n"
+			"	.section        __ex_table,\"a\"\n"
+			"	.word  1b,8b\n"
+			"	.word  2b,8b\n"
+			"	.word  3b,8b\n"
+			"	.word  4b,8b\n"
+			"	.word  5b,8b\n"
+			"	.word  6b,8b\n"
+			"	.word  7b,8b\n"
+			"	.word  0b,8b\n"
+			"	.previous\n"
+			"	.set    pop\n"
+			: "+&r"(rt), "=&r"(rs),
+			  "+&r"(vaddr), "+&r"(err)
+			: "i"(SIGSEGV));
+		if (MIPSInst_RT(inst) && !err)
+			regs->regs[MIPSInst_RT(inst)] = rt;
+
+		MIPS_R2_STATS(loads);
+		break;
+
+	case sdl_op:
+		if (config_enabled(CONFIG_32BIT)) {
+		    err = SIGILL;
+		    break;
+		}
+
+		rt = regs->regs[MIPSInst_RT(inst)];
+		vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst);
+		if (!access_ok(VERIFY_WRITE, vaddr, 8)) {
+			current->thread.cp0_baduaddr = vaddr;
+			err = SIGSEGV;
+			break;
+		}
+		__asm__ __volatile__(
+			"	.set	push\n"
+			"	.set	reorder\n"
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+			"	dextu	%1, %0, 56, 8\n"
+			"1:	sb	%1, 0(%2)\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	daddiu	%2, %2, -1\n"
+			"	dextu	%1, %0, 48, 8\n"
+			"2:	sb	%1, 0(%2)\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	daddiu	%2, %2, -1\n"
+			"	dextu	%1, %0, 40, 8\n"
+			"3:	sb	%1, 0(%2)\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	daddiu	%2, %2, -1\n"
+			"	dextu	%1, %0, 32, 8\n"
+			"4:	sb	%1, 0(%2)\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	daddiu	%2, %2, -1\n"
+			"	dext	%1, %0, 24, 8\n"
+			"5:	sb	%1, 0(%2)\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	daddiu	%2, %2, -1\n"
+			"	dext	%1, %0, 16, 8\n"
+			"6:	sb	%1, 0(%2)\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	daddiu	%2, %2, -1\n"
+			"	dext	%1, %0, 8, 8\n"
+			"7:	sb	%1, 0(%2)\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	daddiu	%2, %2, -1\n"
+			"	dext	%1, %0, 0, 8\n"
+			"0:	sb	%1, 0(%2)\n"
+#else /* !CONFIG_CPU_LITTLE_ENDIAN */
+			"	dextu	%1, %0, 56, 8\n"
+			"1:	sb	%1, 0(%2)\n"
+			"	daddiu	%2, %2, 1\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	dextu	%1, %0, 48, 8\n"
+			"2:	sb	%1, 0(%2)\n"
+			"	daddiu	%2, %2, 1\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	dextu	%1, %0, 40, 8\n"
+			"3:	sb	%1, 0(%2)\n"
+			"	daddiu	%2, %2, 1\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	dextu	%1, %0, 32, 8\n"
+			"4:	sb	%1, 0(%2)\n"
+			"	daddiu	%2, %2, 1\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	dext	%1, %0, 24, 8\n"
+			"5:	sb	%1, 0(%2)\n"
+			"	daddiu	%2, %2, 1\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	dext	%1, %0, 16, 8\n"
+			"6:	sb	%1, 0(%2)\n"
+			"	daddiu	%2, %2, 1\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	dext	%1, %0, 8, 8\n"
+			"7:	sb	%1, 0(%2)\n"
+			"	daddiu	%2, %2, 1\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	dext	%1, %0, 0, 8\n"
+			"0:	sb	%1, 0(%2)\n"
+#endif /* CONFIG_CPU_LITTLE_ENDIAN */
+			"9:\n"
+			"	.insn\n"
+			"	.section        .fixup,\"ax\"\n"
+			"8:	li	%3,%4\n"
+			"	j	9b\n"
+			"	.previous\n"
+			"	.section        __ex_table,\"a\"\n"
+			"	.word	1b,8b\n"
+			"	.word	2b,8b\n"
+			"	.word	3b,8b\n"
+			"	.word	4b,8b\n"
+			"	.word	5b,8b\n"
+			"	.word	6b,8b\n"
+			"	.word	7b,8b\n"
+			"	.word	0b,8b\n"
+			"	.previous\n"
+			"	.set	pop\n"
+			: "+&r"(rt), "=&r"(rs),
+			  "+&r"(vaddr), "+&r"(err)
+			: "i"(SIGSEGV)
+			: "memory");
+
+		MIPS_R2_STATS(stores);
+		break;
+
+	case sdr_op:
+		if (config_enabled(CONFIG_32BIT)) {
+		    err = SIGILL;
+		    break;
+		}
+
+		rt = regs->regs[MIPSInst_RT(inst)];
+		vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst);
+		if (!access_ok(VERIFY_WRITE, vaddr, 8)) {
+			current->thread.cp0_baduaddr = vaddr;
+			err = SIGSEGV;
+			break;
+		}
+		__asm__ __volatile__(
+			"       .set	push\n"
+			"       .set	reorder\n"
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+			"       dext	%1, %0, 0, 8\n"
+			"1:     sb	%1, 0(%2)\n"
+			"       daddiu	%2, %2, 1\n"
+			"       andi	%1, %2, 0x7\n"
+			"       beq	$0, %1, 9f\n"
+			"       dext	%1, %0, 8, 8\n"
+			"2:     sb	%1, 0(%2)\n"
+			"       daddiu	%2, %2, 1\n"
+			"       andi	%1, %2, 0x7\n"
+			"       beq	$0, %1, 9f\n"
+			"       dext	%1, %0, 16, 8\n"
+			"3:     sb	%1, 0(%2)\n"
+			"       daddiu	%2, %2, 1\n"
+			"       andi	%1, %2, 0x7\n"
+			"       beq	$0, %1, 9f\n"
+			"       dext	%1, %0, 24, 8\n"
+			"4:     sb	%1, 0(%2)\n"
+			"       daddiu	%2, %2, 1\n"
+			"       andi	%1, %2, 0x7\n"
+			"       beq	$0, %1, 9f\n"
+			"       dextu	%1, %0, 32, 8\n"
+			"5:     sb	%1, 0(%2)\n"
+			"       daddiu	%2, %2, 1\n"
+			"       andi	%1, %2, 0x7\n"
+			"       beq	$0, %1, 9f\n"
+			"       dextu	%1, %0, 40, 8\n"
+			"6:     sb	%1, 0(%2)\n"
+			"       daddiu	%2, %2, 1\n"
+			"       andi	%1, %2, 0x7\n"
+			"       beq	$0, %1, 9f\n"
+			"       dextu	%1, %0, 48, 8\n"
+			"7:     sb	%1, 0(%2)\n"
+			"       daddiu	%2, %2, 1\n"
+			"       andi	%1, %2, 0x7\n"
+			"       beq	$0, %1, 9f\n"
+			"       dextu	%1, %0, 56, 8\n"
+			"0:     sb	%1, 0(%2)\n"
+#else /* !CONFIG_CPU_LITTLE_ENDIAN */
+			"       dext	%1, %0, 0, 8\n"
+			"1:     sb	%1, 0(%2)\n"
+			"       andi	%1, %2, 0x7\n"
+			"       beq	$0, %1, 9f\n"
+			"       daddiu	%2, %2, -1\n"
+			"       dext	%1, %0, 8, 8\n"
+			"2:     sb	%1, 0(%2)\n"
+			"       andi	%1, %2, 0x7\n"
+			"       beq	$0, %1, 9f\n"
+			"       daddiu	%2, %2, -1\n"
+			"       dext	%1, %0, 16, 8\n"
+			"3:     sb	%1, 0(%2)\n"
+			"       andi	%1, %2, 0x7\n"
+			"       beq	$0, %1, 9f\n"
+			"       daddiu	%2, %2, -1\n"
+			"       dext	%1, %0, 24, 8\n"
+			"4:     sb	%1, 0(%2)\n"
+			"       andi	%1, %2, 0x7\n"
+			"       beq	$0, %1, 9f\n"
+			"       daddiu	%2, %2, -1\n"
+			"       dextu	%1, %0, 32, 8\n"
+			"5:     sb	%1, 0(%2)\n"
+			"       andi	%1, %2, 0x7\n"
+			"       beq	$0, %1, 9f\n"
+			"       daddiu	%2, %2, -1\n"
+			"       dextu	%1, %0, 40, 8\n"
+			"6:     sb	%1, 0(%2)\n"
+			"       andi	%1, %2, 0x7\n"
+			"       beq	$0, %1, 9f\n"
+			"       daddiu	%2, %2, -1\n"
+			"       dextu	%1, %0, 48, 8\n"
+			"7:     sb	%1, 0(%2)\n"
+			"       andi	%1, %2, 0x7\n"
+			"       beq	$0, %1, 9f\n"
+			"       daddiu	%2, %2, -1\n"
+			"       dextu	%1, %0, 56, 8\n"
+			"0:     sb	%1, 0(%2)\n"
+#endif /* CONFIG_CPU_LITTLE_ENDIAN */
+			"9:\n"
+			"       .insn\n"
+			"       .section        .fixup,\"ax\"\n"
+			"8:     li	%3,%4\n"
+			"       j	9b\n"
+			"       .previous\n"
+			"       .section        __ex_table,\"a\"\n"
+			"       .word	1b,8b\n"
+			"       .word	2b,8b\n"
+			"       .word	3b,8b\n"
+			"       .word	4b,8b\n"
+			"       .word	5b,8b\n"
+			"       .word	6b,8b\n"
+			"       .word	7b,8b\n"
+			"       .word	0b,8b\n"
+			"       .previous\n"
+			"       .set	pop\n"
+			: "+&r"(rt), "=&r"(rs),
+			  "+&r"(vaddr), "+&r"(err)
+			: "i"(SIGSEGV)
+			: "memory");
+
+		MIPS_R2_STATS(stores);
+
+		break;
+	case ll_op:
+		vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst);
+		if (vaddr & 0x3) {
+			current->thread.cp0_baduaddr = vaddr;
+			err = SIGBUS;
+			break;
+		}
+		if (!access_ok(VERIFY_READ, vaddr, 4)) {
+			current->thread.cp0_baduaddr = vaddr;
+			err = SIGBUS;
+			break;
+		}
+
+		if (!cpu_has_rw_llb) {
+			/*
+			 * An LL/SC block can't be safely emulated without
+			 * a Config5/LLB availability. So it's probably time to
+			 * kill our process before things get any worse. This is
+			 * because Config5/LLB allows us to use ERETNC so that
+			 * the LLAddr/LLB bit is not cleared when we return from
+			 * an exception. MIPS R2 LL/SC instructions trap with an
+			 * RI exception so once we emulate them here, we return
+			 * back to userland with ERETNC. That preserves the
+			 * LLAddr/LLB so the subsequent SC instruction will
+			 * succeed preserving the atomic semantics of the LL/SC
+			 * block. Without that, there is no safe way to emulate
+			 * an LL/SC block in MIPSR2 userland.
+			 */
+			pr_err("Can't emulate MIPSR2 LL/SC without Config5/LLB\n");
+			err = SIGKILL;
+			break;
+		}
+
+		__asm__ __volatile__(
+			"1:\n"
+			"ll	%0, 0(%2)\n"
+			"2:\n"
+			".insn\n"
+			".section        .fixup,\"ax\"\n"
+			"3:\n"
+			"li	%1, %3\n"
+			"j	2b\n"
+			".previous\n"
+			".section        __ex_table,\"a\"\n"
+			".word  1b, 3b\n"
+			".previous\n"
+			: "=&r"(res), "+&r"(err)
+			: "r"(vaddr), "i"(SIGSEGV)
+			: "memory");
+
+		if (MIPSInst_RT(inst) && !err)
+			regs->regs[MIPSInst_RT(inst)] = res;
+		MIPS_R2_STATS(llsc);
+
+		break;
+
+	case sc_op:
+		vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst);
+		if (vaddr & 0x3) {
+			current->thread.cp0_baduaddr = vaddr;
+			err = SIGBUS;
+			break;
+		}
+		if (!access_ok(VERIFY_WRITE, vaddr, 4)) {
+			current->thread.cp0_baduaddr = vaddr;
+			err = SIGBUS;
+			break;
+		}
+
+		if (!cpu_has_rw_llb) {
+			/*
+			 * An LL/SC block can't be safely emulated without
+			 * a Config5/LLB availability. So it's probably time to
+			 * kill our process before things get any worse. This is
+			 * because Config5/LLB allows us to use ERETNC so that
+			 * the LLAddr/LLB bit is not cleared when we return from
+			 * an exception. MIPS R2 LL/SC instructions trap with an
+			 * RI exception so once we emulate them here, we return
+			 * back to userland with ERETNC. That preserves the
+			 * LLAddr/LLB so the subsequent SC instruction will
+			 * succeed preserving the atomic semantics of the LL/SC
+			 * block. Without that, there is no safe way to emulate
+			 * an LL/SC block in MIPSR2 userland.
+			 */
+			pr_err("Can't emulate MIPSR2 LL/SC without Config5/LLB\n");
+			err = SIGKILL;
+			break;
+		}
+
+		res = regs->regs[MIPSInst_RT(inst)];
+
+		__asm__ __volatile__(
+			"1:\n"
+			"sc	%0, 0(%2)\n"
+			"2:\n"
+			".insn\n"
+			".section        .fixup,\"ax\"\n"
+			"3:\n"
+			"li	%1, %3\n"
+			"j	2b\n"
+			".previous\n"
+			".section        __ex_table,\"a\"\n"
+			".word	1b, 3b\n"
+			".previous\n"
+			: "+&r"(res), "+&r"(err)
+			: "r"(vaddr), "i"(SIGSEGV));
+
+		if (MIPSInst_RT(inst) && !err)
+			regs->regs[MIPSInst_RT(inst)] = res;
+
+		MIPS_R2_STATS(llsc);
+
+		break;
+
+	case lld_op:
+		if (config_enabled(CONFIG_32BIT)) {
+		    err = SIGILL;
+		    break;
+		}
+
+		vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst);
+		if (vaddr & 0x7) {
+			current->thread.cp0_baduaddr = vaddr;
+			err = SIGBUS;
+			break;
+		}
+		if (!access_ok(VERIFY_READ, vaddr, 8)) {
+			current->thread.cp0_baduaddr = vaddr;
+			err = SIGBUS;
+			break;
+		}
+
+		if (!cpu_has_rw_llb) {
+			/*
+			 * An LL/SC block can't be safely emulated without
+			 * a Config5/LLB availability. So it's probably time to
+			 * kill our process before things get any worse. This is
+			 * because Config5/LLB allows us to use ERETNC so that
+			 * the LLAddr/LLB bit is not cleared when we return from
+			 * an exception. MIPS R2 LL/SC instructions trap with an
+			 * RI exception so once we emulate them here, we return
+			 * back to userland with ERETNC. That preserves the
+			 * LLAddr/LLB so the subsequent SC instruction will
+			 * succeed preserving the atomic semantics of the LL/SC
+			 * block. Without that, there is no safe way to emulate
+			 * an LL/SC block in MIPSR2 userland.
+			 */
+			pr_err("Can't emulate MIPSR2 LL/SC without Config5/LLB\n");
+			err = SIGKILL;
+			break;
+		}
+
+		__asm__ __volatile__(
+			"1:\n"
+			"lld	%0, 0(%2)\n"
+			"2:\n"
+			".insn\n"
+			".section        .fixup,\"ax\"\n"
+			"3:\n"
+			"li	%1, %3\n"
+			"j	2b\n"
+			".previous\n"
+			".section        __ex_table,\"a\"\n"
+			".word  1b, 3b\n"
+			".previous\n"
+			: "=&r"(res), "+&r"(err)
+			: "r"(vaddr), "i"(SIGSEGV)
+			: "memory");
+		if (MIPSInst_RT(inst) && !err)
+			regs->regs[MIPSInst_RT(inst)] = res;
+
+		MIPS_R2_STATS(llsc);
+
+		break;
+
+	case scd_op:
+		if (config_enabled(CONFIG_32BIT)) {
+		    err = SIGILL;
+		    break;
+		}
+
+		vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst);
+		if (vaddr & 0x7) {
+			current->thread.cp0_baduaddr = vaddr;
+			err = SIGBUS;
+			break;
+		}
+		if (!access_ok(VERIFY_WRITE, vaddr, 8)) {
+			current->thread.cp0_baduaddr = vaddr;
+			err = SIGBUS;
+			break;
+		}
+
+		if (!cpu_has_rw_llb) {
+			/*
+			 * An LL/SC block can't be safely emulated without
+			 * a Config5/LLB availability. So it's probably time to
+			 * kill our process before things get any worse. This is
+			 * because Config5/LLB allows us to use ERETNC so that
+			 * the LLAddr/LLB bit is not cleared when we return from
+			 * an exception. MIPS R2 LL/SC instructions trap with an
+			 * RI exception so once we emulate them here, we return
+			 * back to userland with ERETNC. That preserves the
+			 * LLAddr/LLB so the subsequent SC instruction will
+			 * succeed preserving the atomic semantics of the LL/SC
+			 * block. Without that, there is no safe way to emulate
+			 * an LL/SC block in MIPSR2 userland.
+			 */
+			pr_err("Can't emulate MIPSR2 LL/SC without Config5/LLB\n");
+			err = SIGKILL;
+			break;
+		}
+
+		res = regs->regs[MIPSInst_RT(inst)];
+
+		__asm__ __volatile__(
+			"1:\n"
+			"scd	%0, 0(%2)\n"
+			"2:\n"
+			".insn\n"
+			".section        .fixup,\"ax\"\n"
+			"3:\n"
+			"li	%1, %3\n"
+			"j	2b\n"
+			".previous\n"
+			".section        __ex_table,\"a\"\n"
+			".word	1b, 3b\n"
+			".previous\n"
+			: "+&r"(res), "+&r"(err)
+			: "r"(vaddr), "i"(SIGSEGV));
+
+		if (MIPSInst_RT(inst) && !err)
+			regs->regs[MIPSInst_RT(inst)] = res;
+
+		MIPS_R2_STATS(llsc);
+
+		break;
+	case pref_op:
+		/* skip it */
+		break;
+	default:
+		err = SIGILL;
+	}
+
+	/*
+	 * Lets not return to userland just yet. It's constly and
+	 * it's likely we have more R2 instructions to emulate
+	 */
+	if (!err && (pass++ < MIPS_R2_EMUL_TOTAL_PASS)) {
+		regs->cp0_cause &= ~CAUSEF_BD;
+		err = get_user(inst, (u32 __user *)regs->cp0_epc);
+		if (!err)
+			goto repeat;
+
+		if (err < 0)
+			err = SIGSEGV;
+	}
+
+	if (err && (err != SIGEMT)) {
+		regs->regs[31] = r31;
+		regs->cp0_epc = epc;
+	}
+
+	/* Likely a MIPS R6 compatible instruction */
+	if (pass && (err == SIGILL))
+		err = 0;
+
+	return err;
+}
+
+#ifdef CONFIG_DEBUG_FS
+
+static int mipsr2_stats_show(struct seq_file *s, void *unused)
+{
+
+	seq_printf(s, "Instruction\tTotal\tBDslot\n------------------------------\n");
+	seq_printf(s, "movs\t\t%ld\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2emustats).movs,
+		   (unsigned long)__get_cpu_var(mipsr2bdemustats).movs);
+	seq_printf(s, "hilo\t\t%ld\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2emustats).hilo,
+		   (unsigned long)__get_cpu_var(mipsr2bdemustats).hilo);
+	seq_printf(s, "muls\t\t%ld\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2emustats).muls,
+		   (unsigned long)__get_cpu_var(mipsr2bdemustats).muls);
+	seq_printf(s, "divs\t\t%ld\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2emustats).divs,
+		   (unsigned long)__get_cpu_var(mipsr2bdemustats).divs);
+	seq_printf(s, "dsps\t\t%ld\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2emustats).dsps,
+		   (unsigned long)__get_cpu_var(mipsr2bdemustats).dsps);
+	seq_printf(s, "bops\t\t%ld\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2emustats).bops,
+		   (unsigned long)__get_cpu_var(mipsr2bdemustats).bops);
+	seq_printf(s, "traps\t\t%ld\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2emustats).traps,
+		   (unsigned long)__get_cpu_var(mipsr2bdemustats).traps);
+	seq_printf(s, "fpus\t\t%ld\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2emustats).fpus,
+		   (unsigned long)__get_cpu_var(mipsr2bdemustats).fpus);
+	seq_printf(s, "loads\t\t%ld\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2emustats).loads,
+		   (unsigned long)__get_cpu_var(mipsr2bdemustats).loads);
+	seq_printf(s, "stores\t\t%ld\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2emustats).stores,
+		   (unsigned long)__get_cpu_var(mipsr2bdemustats).stores);
+	seq_printf(s, "llsc\t\t%ld\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2emustats).llsc,
+		   (unsigned long)__get_cpu_var(mipsr2bdemustats).llsc);
+	seq_printf(s, "dsemul\t\t%ld\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2emustats).dsemul,
+		   (unsigned long)__get_cpu_var(mipsr2bdemustats).dsemul);
+	seq_printf(s, "jr\t\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2bremustats).jrs);
+	seq_printf(s, "bltzl\t\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2bremustats).bltzl);
+	seq_printf(s, "bgezl\t\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2bremustats).bgezl);
+	seq_printf(s, "bltzll\t\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2bremustats).bltzll);
+	seq_printf(s, "bgezll\t\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2bremustats).bgezll);
+	seq_printf(s, "bltzal\t\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2bremustats).bltzal);
+	seq_printf(s, "bgezal\t\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2bremustats).bgezal);
+	seq_printf(s, "beql\t\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2bremustats).beql);
+	seq_printf(s, "bnel\t\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2bremustats).bnel);
+	seq_printf(s, "blezl\t\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2bremustats).blezl);
+	seq_printf(s, "bgtzl\t\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2bremustats).bgtzl);
+
+	return 0;
+}
+
+static int mipsr2_stats_clear_show(struct seq_file *s, void *unused)
+{
+	mipsr2_stats_show(s, unused);
+
+	__get_cpu_var(mipsr2emustats).movs    = 0;
+	__get_cpu_var(mipsr2bdemustats).movs  = 0;
+	__get_cpu_var(mipsr2emustats).hilo    = 0;
+	__get_cpu_var(mipsr2bdemustats).hilo  = 0;
+	__get_cpu_var(mipsr2emustats).muls    = 0;
+	__get_cpu_var(mipsr2bdemustats).muls  = 0;
+	__get_cpu_var(mipsr2emustats).divs    = 0;
+	__get_cpu_var(mipsr2bdemustats).divs  = 0;
+	__get_cpu_var(mipsr2emustats).dsps    = 0;
+	__get_cpu_var(mipsr2bdemustats).dsps  = 0;
+	__get_cpu_var(mipsr2emustats).bops    = 0;
+	__get_cpu_var(mipsr2bdemustats).bops  = 0;
+	__get_cpu_var(mipsr2emustats).traps   = 0;
+	__get_cpu_var(mipsr2bdemustats).traps = 0;
+	__get_cpu_var(mipsr2emustats).fpus    = 0;
+	__get_cpu_var(mipsr2bdemustats).fpus  = 0;
+	__get_cpu_var(mipsr2emustats).loads   = 0;
+	__get_cpu_var(mipsr2bdemustats).loads = 0;
+	__get_cpu_var(mipsr2emustats).stores  = 0;
+	__get_cpu_var(mipsr2bdemustats).stores = 0;
+	__get_cpu_var(mipsr2emustats).llsc    = 0;
+	__get_cpu_var(mipsr2bdemustats).llsc  = 0;
+	__get_cpu_var(mipsr2emustats).dsemul  = 0;
+	__get_cpu_var(mipsr2bdemustats).dsemul = 0;
+
+	__get_cpu_var(mipsr2bremustats).jrs   = 0;
+	__get_cpu_var(mipsr2bremustats).bltzl = 0;
+	__get_cpu_var(mipsr2bremustats).bgezl = 0;
+	__get_cpu_var(mipsr2bremustats).bltzll = 0;
+	__get_cpu_var(mipsr2bremustats).bgezll = 0;
+	__get_cpu_var(mipsr2bremustats).bltzal = 0;
+	__get_cpu_var(mipsr2bremustats).bgezal = 0;
+	__get_cpu_var(mipsr2bremustats).beql  = 0;
+	__get_cpu_var(mipsr2bremustats).bnel  = 0;
+	__get_cpu_var(mipsr2bremustats).blezl = 0;
+	__get_cpu_var(mipsr2bremustats).bgtzl = 0;
+
+	return 0;
+}
+
+static int mipsr2_stats_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, mipsr2_stats_show, inode->i_private);
+}
+
+static int mipsr2_stats_clear_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, mipsr2_stats_clear_show, inode->i_private);
+}
+
+static const struct file_operations mipsr2_emul_fops = {
+	.open                   = mipsr2_stats_open,
+	.read			= seq_read,
+	.llseek			= seq_lseek,
+	.release		= single_release,
+};
+
+static const struct file_operations mipsr2_clear_fops = {
+	.open                   = mipsr2_stats_clear_open,
+	.read			= seq_read,
+	.llseek			= seq_lseek,
+	.release		= single_release,
+};
+
+
+static int __init mipsr2_init_debugfs(void)
+{
+	extern struct dentry	*mips_debugfs_dir;
+	struct dentry		*mipsr2_emul;
+
+	if (!mips_debugfs_dir)
+		return -ENODEV;
+
+	mipsr2_emul = debugfs_create_file("r2_emul_stats", S_IRUGO,
+					  mips_debugfs_dir, NULL,
+					  &mipsr2_emul_fops);
+	if (!mipsr2_emul)
+		return -ENOMEM;
+
+	mipsr2_emul = debugfs_create_file("r2_emul_stats_clear", S_IRUGO,
+					  mips_debugfs_dir, NULL,
+					  &mipsr2_clear_fops);
+	if (!mipsr2_emul)
+		return -ENOMEM;
+
+	return 0;
+}
+
+device_initcall(mipsr2_init_debugfs);
+
+#endif /* CONFIG_DEBUG_FS */
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 5223f173a5db..da0836574918 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -46,6 +46,7 @@
 #include <asm/fpu.h>
 #include <asm/fpu_emulator.h>
 #include <asm/idle.h>
+#include <asm/mips-r2-to-r6-emul.h>
 #include <asm/mipsregs.h>
 #include <asm/mipsmtregs.h>
 #include <asm/module.h>
@@ -793,7 +794,7 @@ out:
 	exception_exit(prev_state);
 }
 
-static void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
+void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
 	const char *str)
 {
 	siginfo_t info;
@@ -983,7 +984,32 @@ asmlinkage void do_ri(struct pt_regs *regs)
 	unsigned int opcode = 0;
 	int status = -1;
 
+	/*
+	 * Avoid any kernel code. Just emulate the R2 instruction
+	 * as quickly as possible.
+	 */
+	if (mipsr2_emulation && cpu_has_mips_r6 &&
+	    likely(user_mode(regs))) {
+		if (likely(get_user(opcode, epc) >= 0)) {
+			status = mipsr2_decoder(regs, opcode);
+			switch (status) {
+			case 0:
+			case SIGEMT:
+				return;
+			case SIGILL:
+				goto no_r2_instr;
+			default:
+				process_fpemu_return(status,
+						     &current->thread.cp0_baduaddr);
+				return;
+			}
+		}
+	}
+
+no_r2_instr:
+
 	prev_state = exception_enter();
+
 	if (notify_die(DIE_RI, "RI Fault", regs, 0, regs_to_trapnr(regs),
 		       SIGILL) == NOTIFY_STOP)
 		goto out;
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 63/67] MIPS: kernel: mips-r2-to-r6-emul: Add R2 emulator for MIPS R6
@ 2014-12-18 15:10   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:10 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>

MIPS R6 removed quite a few R2 instructions. However, there
is plenty of <R6 userland code so we add an in-kernel emulator
so we can still be able to execute all R2 userland out there.

The emulator comes with a handy debugfs under /mips/ directory
(r2-emul-stats) to provide some basic statistics of the
instructions that are being emulated.

Below are some statistics from booting a minimal buildroot image:

Instruction     Total   BDslot
------------------------------
movs            236969  0
hilo            56686   0
muls            55279   0
divs            10941   0
dsps            0       0
bops            1       0
traps           0       0
fpus            0       0
loads           214981  17
stores          103364  0
llsc            56898   0
dsemul          150418  0
jr              370158
bltzl           43
bgezl           1594
bltzll          0
bgezll          0
bltzal          39
bgezal          39
beql            14503
bnel            138741
blezl           0
bgtzl           3988

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/Kconfig                          |   13 +
 arch/mips/include/asm/mips-r2-to-r6-emul.h |   94 ++
 arch/mips/kernel/Makefile                  |    1 +
 arch/mips/kernel/branch.c                  |    2 +-
 arch/mips/kernel/mips-r2-to-r6-emul.c      | 2377 ++++++++++++++++++++++++++++
 arch/mips/kernel/traps.c                   |   28 +-
 6 files changed, 2513 insertions(+), 2 deletions(-)
 create mode 100644 arch/mips/include/asm/mips-r2-to-r6-emul.h
 create mode 100644 arch/mips/kernel/mips-r2-to-r6-emul.c

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 544e62369bbc..3fe856572d2e 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -2027,6 +2027,19 @@ config MIPS_MT_FPAFF
 	default y
 	depends on MIPS_MT_SMP
 
+config MIPSR2_TO_R6_EMULATOR
+	bool "MIPS R2-to-R6 emulator"
+	depends on CPU_MIPSR6 && !SMP
+	default y
+	help
+	  Choose this option if you want to run non-R6 MIPS userland code.
+	  Even if you say 'Y' here, the emulator will still be disabled by
+	  default. You can enable it using the 'mipsr2emul' kernel option.
+	  The only reason this is a build-time option is to save ~14K from the
+	  final kernel image.
+comment "MIPS R2-to-R6 emulator is only available for UP kernels"
+	depends on SMP && CPU_MIPSR6
+
 config MIPS_VPE_LOADER
 	bool "VPE loader support."
 	depends on SYS_SUPPORTS_MULTITHREADING && MODULES
diff --git a/arch/mips/include/asm/mips-r2-to-r6-emul.h b/arch/mips/include/asm/mips-r2-to-r6-emul.h
new file mode 100644
index 000000000000..8d5fe0d716f5
--- /dev/null
+++ b/arch/mips/include/asm/mips-r2-to-r6-emul.h
@@ -0,0 +1,94 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2014 Imagination Technologies Ltd.
+ * Author: Markos Chandras <markos.chandras@imgtec.com>
+ */
+
+#ifndef __ASM_MIPS_R2_TO_R6_EMUL_H
+#define __ASM_MIPS_R2_TO_R6_EMUL_H
+
+#ifdef CONFIG_DEBUG_FS
+
+struct mips_r2_emulator_stats {
+	u64 movs;
+	u64 hilo;
+	u64 muls;
+	u64 divs;
+	u64 dsps;
+	u64 bops;
+	u64 traps;
+	u64 fpus;
+	u64 loads;
+	u64 stores;
+	u64 llsc;
+	u64 dsemul;
+};
+
+#define MIPS_R2_STATS(M)						\
+do {									\
+	u32 nir;							\
+	int err;							\
+									\
+	preempt_disable();						\
+	__get_cpu_var(mipsr2emustats).M++;				\
+	err = __get_user(nir, (u32 __user *)regs->cp0_epc);		\
+	if (!err) {							\
+		if (nir == BREAK_MATH)					\
+			__get_cpu_var(mipsr2bdemustats).M++;		\
+	}								\
+	preempt_enable();						\
+} while (0)
+
+struct mips_r2br_emulator_stats {
+	u64 jrs;
+	u64 bltzl;
+	u64 bgezl;
+	u64 bltzll;
+	u64 bgezll;
+	u64 bltzall;
+	u64 bgezall;
+	u64 bltzal;
+	u64 bgezal;
+	u64 beql;
+	u64 bnel;
+	u64 blezl;
+	u64 bgtzl;
+};
+
+#define MIPS_R2BR_STATS(M)					\
+do {								\
+	preempt_disable();					\
+	__get_cpu_var(mipsr2bremustats).M++;			\
+	preempt_enable();					\
+} while (0)
+
+#else
+
+#define MIPS_R2_STATS(M)          do { } while (0)
+#define MIPS_R2BR_STATS(M)        do { } while (0)
+
+#endif /* CONFIG_DEBUG_FS */
+
+struct r2_decoder_table {
+	u32     mask;
+	u32     code;
+	int     (*func)(struct pt_regs *regs, u32 inst);
+};
+
+
+extern void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
+			  const char *str);
+
+#ifndef CONFIG_MIPSR2_TO_R6_EMULATOR
+static int mipsr2_emulation;
+static __maybe_unused int mipsr2_decoder(struct pt_regs *regs, u32 inst) { return 0; };
+#else
+/* MIPS R2 Emulator ON/OFF */
+extern int mipsr2_emulation;
+extern int mipsr2_decoder(struct pt_regs *regs, u32 inst);
+#endif /* CONFIG_MIPSR2_TO_R6_EMULATOR */
+
+#endif /* __ASM_MIPS_R2_TO_R6_EMUL_H */
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index f6ee8cc1f7c2..c3918e7693f9 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -93,6 +93,7 @@ obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
 obj-$(CONFIG_EARLY_PRINTK_8250)	+= early_printk_8250.o
 obj-$(CONFIG_SPINLOCK_TEST)	+= spinlock_test.o
 obj-$(CONFIG_MIPS_MACHINE)	+= mips_machine.o
+obj-$(CONFIG_MIPSR2_TO_R6_EMULATOR)	+= mips-r2-to-r6-emul.o
 
 CFLAGS_cpu-bugs64.o	= $(shell if $(CC) $(KBUILD_CFLAGS) -Wa,-mdaddi -c -o /dev/null -x c /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi)
 
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 4473c23cacf2..438162e8db06 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -16,10 +16,10 @@
 #include <asm/fpu.h>
 #include <asm/fpu_emulator.h>
 #include <asm/inst.h>
+#include <asm/mips-r2-to-r6-emul.h>
 #include <asm/ptrace.h>
 #include <asm/uaccess.h>
 
-static int mipsr2_emulation = 0;
 #define NO_R6EMU	(cpu_has_mips_r6 && !mipsr2_emulation)
 
 /*
diff --git a/arch/mips/kernel/mips-r2-to-r6-emul.c b/arch/mips/kernel/mips-r2-to-r6-emul.c
new file mode 100644
index 000000000000..45b1cb536523
--- /dev/null
+++ b/arch/mips/kernel/mips-r2-to-r6-emul.c
@@ -0,0 +1,2377 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2014 Imagination Technologies Ltd.
+ * Author: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
+ * Author: Markos Chandras <markos.chandras@imgtec.com>
+ *
+ *      MIPS R2 user space instruction emulator for MIPS R6
+ *
+ */
+#include <linux/bug.h>
+#include <linux/compiler.h>
+#include <linux/debugfs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/ptrace.h>
+#include <linux/seq_file.h>
+
+#include <asm/asm.h>
+#include <asm/branch.h>
+#include <asm/break.h>
+#include <asm/fpu.h>
+#include <asm/fpu_emulator.h>
+#include <asm/inst.h>
+#include <asm/mips-r2-to-r6-emul.h>
+#include <asm/local.h>
+#include <asm/ptrace.h>
+#include <asm/uaccess.h>
+
+#ifdef CONFIG_64BIT
+#define ADDIU	"daddiu "
+#define INS	"dins "
+#define EXT	"dext "
+#else
+#define ADDIU	"addiu "
+#define INS	"ins "
+#define EXT	"ext "
+#endif /* CONFIG_64BIT */
+
+#define SB	"sb "
+#define LB	"lb "
+#define LL	"ll "
+#define SC	"sc "
+
+DEFINE_PER_CPU(struct mips_r2_emulator_stats, mipsr2emustats);
+DEFINE_PER_CPU(struct mips_r2_emulator_stats, mipsr2bdemustats);
+DEFINE_PER_CPU(struct mips_r2br_emulator_stats, mipsr2bremustats);
+
+#define MIPS_R2_EMUL_TOTAL_PASS	10
+
+int mipsr2_emulation = 0;
+
+static int __init mipsr2emu_enable(char *s)
+{
+	mipsr2_emulation = 1;
+
+	pr_info("MIPS R2-to-R6 Emulator Enabled!");
+
+	return 1;
+}
+__setup("mipsr2emu", mipsr2emu_enable);
+
+/**
+ * mipsr6_emul - Emulate some frequent R2/R5/R6 instructions in delay slot
+ * for performance instead of the traditional way of using a stack trampoline
+ * which is rather slow.
+ * @regs: Process register set
+ * @ir: Instruction
+ */
+static inline int mipsr6_emul(struct pt_regs *regs, u32 ir)
+{
+	switch (MIPSInst_OPCODE(ir)) {
+	case addiu_op:
+		if (MIPSInst_RT(ir))
+			regs->regs[MIPSInst_RT(ir)] =
+				(s32)regs->regs[MIPSInst_RS(ir)] +
+				(s32)MIPSInst_SIMM(ir);
+		return 0;
+	case daddiu_op:
+		if (config_enabled(CONFIG_32BIT))
+			break;
+
+		if (MIPSInst_RT(ir))
+			regs->regs[MIPSInst_RT(ir)] =
+				(s64)regs->regs[MIPSInst_RS(ir)] +
+				(s64)MIPSInst_SIMM(ir);
+		return 0;
+	case lwc1_op:
+	case swc1_op:
+	case cop1_op:
+	case cop1x_op:
+		/* FPU instructions in delay slot */
+		return -SIGFPE;
+	case spec_op:
+		switch (MIPSInst_FUNC(ir)) {
+		case or_op:
+			if (MIPSInst_RD(ir))
+				regs->regs[MIPSInst_RD(ir)] =
+					regs->regs[MIPSInst_RS(ir)] |
+					regs->regs[MIPSInst_RT(ir)];
+			return 0;
+		case sll_op:
+			if (MIPSInst_RS(ir))
+				break;
+
+			if (MIPSInst_RD(ir))
+				regs->regs[MIPSInst_RD(ir)] =
+					(s32)(((u32)regs->regs[MIPSInst_RT(ir)]) <<
+						MIPSInst_FD(ir));
+			return 0;
+		case srl_op:
+			if (MIPSInst_RS(ir))
+				break;
+
+			if (MIPSInst_RD(ir))
+				regs->regs[MIPSInst_RD(ir)] =
+					(s32)(((u32)regs->regs[MIPSInst_RT(ir)]) >>
+						MIPSInst_FD(ir));
+			return 0;
+		case addu_op:
+			if (MIPSInst_FD(ir))
+				break;
+
+			if (MIPSInst_RD(ir))
+				regs->regs[MIPSInst_RD(ir)] =
+					(s32)((u32)regs->regs[MIPSInst_RS(ir)] +
+					      (u32)regs->regs[MIPSInst_RT(ir)]);
+			return 0;
+		case subu_op:
+			if (MIPSInst_FD(ir))
+				break;
+
+			if (MIPSInst_RD(ir))
+				regs->regs[MIPSInst_RD(ir)] =
+					(s32)((u32)regs->regs[MIPSInst_RS(ir)] -
+					      (u32)regs->regs[MIPSInst_RT(ir)]);
+			return 0;
+		case dsll_op:
+			if (config_enabled(CONFIG_32BIT) || MIPSInst_RS(ir))
+				break;
+
+			if (MIPSInst_RD(ir))
+				regs->regs[MIPSInst_RD(ir)] =
+					(s64)(((u64)regs->regs[MIPSInst_RT(ir)]) <<
+						MIPSInst_FD(ir));
+			return 0;
+		case dsrl_op:
+			if (config_enabled(CONFIG_32BIT) || MIPSInst_RS(ir))
+				break;
+
+			if (MIPSInst_RD(ir))
+				regs->regs[MIPSInst_RD(ir)] =
+					(s64)(((u64)regs->regs[MIPSInst_RT(ir)]) >>
+						MIPSInst_FD(ir));
+			return 0;
+		case daddu_op:
+			if (config_enabled(CONFIG_32BIT) || MIPSInst_FD(ir))
+				break;
+
+			if (MIPSInst_RD(ir))
+				regs->regs[MIPSInst_RD(ir)] =
+					(u64)regs->regs[MIPSInst_RS(ir)] +
+					(u64)regs->regs[MIPSInst_RT(ir)];
+			return 0;
+		case dsubu_op:
+			if (config_enabled(CONFIG_32BIT) || MIPSInst_FD(ir))
+				break;
+
+			if (MIPSInst_RD(ir))
+				regs->regs[MIPSInst_RD(ir)] =
+					(s64)((u64)regs->regs[MIPSInst_RS(ir)] -
+					      (u64)regs->regs[MIPSInst_RT(ir)]);
+			return 0;
+		}
+		break;
+	default:
+		pr_debug("No fastpath BD emulation for instruction 0x%08x (op: %02x)\n",
+			 ir, MIPSInst_OPCODE(ir));
+	}
+
+	return SIGILL;
+}
+
+/**
+ * movt_func - Emulate a MOVT instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int movf_func(struct pt_regs *regs, u32 ir)
+{
+	u32 csr;
+	u32 cond;
+
+	csr = current->thread.fpu.fcr31;
+	cond = fpucondbit[MIPSInst_RT(ir) >> 2];
+	if (((csr & cond) == 0) && MIPSInst_RD(ir))
+		regs->regs[MIPSInst_RD(ir)] = regs->regs[MIPSInst_RS(ir)];
+	MIPS_R2_STATS(movs);
+	return 0;
+}
+
+/**
+ * movt_func - Emulate a MOVT instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int movt_func(struct pt_regs *regs, u32 ir)
+{
+	u32 csr;
+	u32 cond;
+
+	csr = current->thread.fpu.fcr31;
+	cond = fpucondbit[MIPSInst_RT(ir) >> 2];
+
+	if (((csr & cond) != 0) && MIPSInst_RD(ir))
+		regs->regs[MIPSInst_RD(ir)] = regs->regs[MIPSInst_RS(ir)];
+
+	MIPS_R2_STATS(movs);
+
+	return 0;
+}
+
+/**
+ * jr_func - Emulate a JR instruction.
+ * @pt_regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns SIGILL if JR was in delay slot, SIGEMT if we
+ * can't compute the EPC, SIGSEGV if we can't access the
+ * userland instruction or 0 on success.
+ */
+static int jr_func(struct pt_regs *regs, u32 ir)
+{
+	int err;
+	unsigned long cepc, epc, nepc;
+	u32 nir;
+
+	if (delay_slot(regs))
+		return SIGILL;
+
+	/* EPC after the RI/JR instruction */
+	nepc = regs->cp0_epc;
+	/* Roll back to the reserved R2 JR instruction */
+	regs->cp0_epc -= 4;
+	epc = regs->cp0_epc;
+	err = __compute_return_epc(regs);
+
+	if (err < 0)
+		return SIGEMT;
+
+
+	/* Computed EPC */
+	cepc = regs->cp0_epc;
+
+	/* Get DS instruction */
+	err = __get_user(nir, (u32 __user *)nepc);
+	if (err)
+		return SIGSEGV;
+
+	MIPS_R2BR_STATS(jrs);
+
+	/* If nir == 0(NOP), then nothing else to do */
+	if (nir) {
+		/*
+		 * Negative err means FPU instruction in BD-slot,
+		 * Zero err means 'BD-slot emulation done'
+		 * For anything else we go back to trampoline emulation.
+		 */
+		err = mipsr6_emul(regs, nir);
+		if (err > 0) {
+			regs->cp0_epc = nepc;
+			err = mips_dsemul(regs, nir, cepc);
+			if (err == SIGILL)
+				err = SIGEMT;
+			MIPS_R2_STATS(dsemul);
+		}
+	}
+
+	return err;
+}
+
+/**
+ * movz_func - Emulate a MOVZ instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int movz_func(struct pt_regs *regs, u32 ir)
+{
+	if (((regs->regs[MIPSInst_RT(ir)]) == 0) && MIPSInst_RD(ir))
+		regs->regs[MIPSInst_RD(ir)] = regs->regs[MIPSInst_RS(ir)];
+	MIPS_R2_STATS(movs);
+
+	return 0;
+}
+
+/**
+ * movn_func - Emulate a MOVZ instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int movn_func(struct pt_regs *regs, u32 ir)
+{
+	if (((regs->regs[MIPSInst_RT(ir)]) != 0) && MIPSInst_RD(ir))
+		regs->regs[MIPSInst_RD(ir)] = regs->regs[MIPSInst_RS(ir)];
+	MIPS_R2_STATS(movs);
+
+	return 0;
+}
+
+/**
+ * mfhi_func - Emulate a MFHI instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int mfhi_func(struct pt_regs *regs, u32 ir)
+{
+	if (MIPSInst_RD(ir))
+		regs->regs[MIPSInst_RD(ir)] = regs->hi;
+
+	MIPS_R2_STATS(hilo);
+
+	return 0;
+}
+
+/**
+ * mthi_func - Emulate a MTHI instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int mthi_func(struct pt_regs *regs, u32 ir)
+{
+	regs->hi = regs->regs[MIPSInst_RS(ir)];
+
+	MIPS_R2_STATS(hilo);
+
+	return 0;
+}
+
+/**
+ * mflo_func - Emulate a MFLO instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int mflo_func(struct pt_regs *regs, u32 ir)
+{
+	if (MIPSInst_RD(ir))
+		regs->regs[MIPSInst_RD(ir)] = regs->lo;
+
+	MIPS_R2_STATS(hilo);
+
+	return 0;
+}
+
+/**
+ * mtlo_func - Emulate a MTLO instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int mtlo_func(struct pt_regs *regs, u32 ir)
+{
+	regs->lo = regs->regs[MIPSInst_RS(ir)];
+
+	MIPS_R2_STATS(hilo);
+
+	return 0;
+}
+
+/**
+ * mult_func - Emulate a MULT instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int mult_func(struct pt_regs *regs, u32 ir)
+{
+	s64 res;
+	s32 rt, rs;
+
+	rt = regs->regs[MIPSInst_RT(ir)];
+	rs = regs->regs[MIPSInst_RS(ir)];
+	res = (s64)rt * (s64)rs;
+
+	rs = res;
+	regs->lo = (s64)rs;
+	rt = res >> 32;
+	res = (s64)rt;
+	regs->hi = res;
+
+	MIPS_R2_STATS(muls);
+
+	return 0;
+}
+
+/**
+ * multu_func - Emulate a MULTU instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int multu_func(struct pt_regs *regs, u32 ir)
+{
+	u64 res;
+	u32 rt, rs;
+
+	rt = regs->regs[MIPSInst_RT(ir)];
+	rs = regs->regs[MIPSInst_RS(ir)];
+	res = (u64)rt * (u64)rs;
+	rt = res;
+	regs->lo = (s64)rt;
+	regs->hi = (s64)(res >> 32);
+
+	MIPS_R2_STATS(muls);
+
+	return 0;
+}
+
+/**
+ * div_func - Emulate a DIV instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int div_func(struct pt_regs *regs, u32 ir)
+{
+	s32 rt, rs;
+
+	rt = regs->regs[MIPSInst_RT(ir)];
+	rs = regs->regs[MIPSInst_RS(ir)];
+
+	regs->lo = (s64)(rs / rt);
+	regs->hi = (s64)(rs % rt);
+
+	MIPS_R2_STATS(divs);
+
+	return 0;
+}
+
+/**
+ * divu_func - Emulate a DIVU instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int divu_func(struct pt_regs *regs, u32 ir)
+{
+	u32 rt, rs;
+
+	rt = regs->regs[MIPSInst_RT(ir)];
+	rs = regs->regs[MIPSInst_RS(ir)];
+
+	regs->lo = (s64)(rs / rt);
+	regs->hi = (s64)(rs % rt);
+
+	MIPS_R2_STATS(divs);
+
+	return 0;
+}
+
+/**
+ * dmult_func - Emulate a DMULT instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 on success or SIGILL for 32-bit kernels.
+ */
+static int dmult_func(struct pt_regs *regs, u32 ir)
+{
+	s64 res;
+	s64 rt, rs;
+
+	if (config_enabled(CONFIG_32BIT))
+		return SIGILL;
+
+	rt = regs->regs[MIPSInst_RT(ir)];
+	rs = regs->regs[MIPSInst_RS(ir)];
+	res = rt * rs;
+
+	regs->lo = res;
+	__asm__ __volatile__(
+		"dmuh %0, %1, %2\t\n"
+		: "=r"(res)
+		: "r"(rt), "r"(rs));
+
+	regs->hi = res;
+
+	MIPS_R2_STATS(muls);
+
+	return 0;
+}
+
+/**
+ * dmultu_func - Emulate a DMULTU instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 on success or SIGILL for 32-bit kernels.
+ */
+static int dmultu_func(struct pt_regs *regs, u32 ir)
+{
+	u64 res;
+	u64 rt, rs;
+
+	if (config_enabled(CONFIG_32BIT))
+		return SIGILL;
+
+	rt = regs->regs[MIPSInst_RT(ir)];
+	rs = regs->regs[MIPSInst_RS(ir)];
+	res = rt * rs;
+
+	regs->lo = res;
+	__asm__ __volatile__(
+		"dmuhu %0, %1, %2\t\n"
+		: "=r"(res)
+		: "r"(rt), "r"(rs));
+
+	regs->hi = res;
+
+	MIPS_R2_STATS(muls);
+
+	return 0;
+}
+
+/**
+ * ddiv_func - Emulate a DDIV instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 on success or SIGILL for 32-bit kernels.
+ */
+static int ddiv_func(struct pt_regs *regs, u32 ir)
+{
+	s64 rt, rs;
+
+	if (config_enabled(CONFIG_32BIT))
+		return SIGILL;
+
+	rt = regs->regs[MIPSInst_RT(ir)];
+	rs = regs->regs[MIPSInst_RS(ir)];
+
+	regs->lo = rs / rt;
+	regs->hi = rs % rt;
+
+	MIPS_R2_STATS(divs);
+
+	return 0;
+}
+
+/**
+ * ddivu_func - Emulate a DDIVU instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 on success or SIGILL for 32-bit kernels.
+ */
+static int ddivu_func(struct pt_regs *regs, u32 ir)
+{
+	u64 rt, rs;
+
+	if (config_enabled(CONFIG_32BIT))
+		return SIGILL;
+
+	rt = regs->regs[MIPSInst_RT(ir)];
+	rs = regs->regs[MIPSInst_RS(ir)];
+
+	regs->lo = rs / rt;
+	regs->hi = rs % rt;
+
+	MIPS_R2_STATS(divs);
+
+	return 0;
+}
+
+/* R6 removed instructions for the SPECIAL opcode */
+static struct r2_decoder_table spec_op_table[] = {
+	{ 0xfc1ff83f, 0x00000008, jr_func },
+	{ 0xfc00ffff, 0x00000018, mult_func },
+	{ 0xfc00ffff, 0x00000019, multu_func },
+	{ 0xfc00ffff, 0x0000001c, dmult_func },
+	{ 0xfc00ffff, 0x0000001d, dmultu_func },
+	{ 0xffff07ff, 0x00000010, mfhi_func },
+	{ 0xfc1fffff, 0x00000011, mthi_func },
+	{ 0xffff07ff, 0x00000012, mflo_func },
+	{ 0xfc1fffff, 0x00000013, mtlo_func },
+	{ 0xfc0307ff, 0x00000001, movf_func },
+	{ 0xfc0307ff, 0x00010001, movt_func },
+	{ 0xfc0007ff, 0x0000000a, movz_func },
+	{ 0xfc0007ff, 0x0000000b, movn_func },
+	{ 0xfc00ffff, 0x0000001a, div_func },
+	{ 0xfc00ffff, 0x0000001b, divu_func },
+	{ 0xfc00ffff, 0x0000001e, ddiv_func },
+	{ 0xfc00ffff, 0x0000001f, ddivu_func },
+	{}
+};
+
+/**
+ * madd_func - Emulate a MADD instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int madd_func(struct pt_regs *regs, u32 ir)
+{
+	s64 res;
+	s32 rt, rs;
+
+	rt = regs->regs[MIPSInst_RT(ir)];
+	rs = regs->regs[MIPSInst_RS(ir)];
+	res = (s64)rt * (s64)rs;
+	rt = regs->hi;
+	rs = regs->lo;
+	res += ((((s64)rt) << 32) | (u32)rs);
+
+	rt = res;
+	regs->lo = (s64)rt;
+	rs = res >> 32;
+	regs->hi = (s64)rs;
+
+	MIPS_R2_STATS(dsps);
+
+	return 0;
+}
+
+/**
+ * maddu_func - Emulate a MADDU instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int maddu_func(struct pt_regs *regs, u32 ir)
+{
+	u64 res;
+	u32 rt, rs;
+
+	rt = regs->regs[MIPSInst_RT(ir)];
+	rs = regs->regs[MIPSInst_RS(ir)];
+	res = (u64)rt * (u64)rs;
+	rt = regs->hi;
+	rs = regs->lo;
+	res += ((((s64)rt) << 32) | (u32)rs);
+
+	rt = res;
+	regs->lo = (s64)rt;
+	rs = res >> 32;
+	regs->hi = (s64)rs;
+
+	MIPS_R2_STATS(dsps);
+
+	return 0;
+}
+
+/**
+ * msub_func - Emulate a MSUB instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int msub_func(struct pt_regs *regs, u32 ir)
+{
+	s64 res;
+	s32 rt, rs;
+
+	rt = regs->regs[MIPSInst_RT(ir)];
+	rs = regs->regs[MIPSInst_RS(ir)];
+	res = (s64)rt * (s64)rs;
+	rt = regs->hi;
+	rs = regs->lo;
+	res = ((((s64)rt) << 32) | (u32)rs) - res;
+
+	rt = res;
+	regs->lo = (s64)rt;
+	rs = res >> 32;
+	regs->hi = (s64)rs;
+
+	MIPS_R2_STATS(dsps);
+
+	return 0;
+}
+
+/**
+ * msubu_func - Emulate a MSUBU instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int msubu_func(struct pt_regs *regs, u32 ir)
+{
+	u64 res;
+	u32 rt, rs;
+
+	rt = regs->regs[MIPSInst_RT(ir)];
+	rs = regs->regs[MIPSInst_RS(ir)];
+	res = (u64)rt * (u64)rs;
+	rt = regs->hi;
+	rs = regs->lo;
+	res = ((((s64)rt) << 32) | (u32)rs) - res;
+
+	rt = res;
+	regs->lo = (s64)rt;
+	rs = res >> 32;
+	regs->hi = (s64)rs;
+
+	MIPS_R2_STATS(dsps);
+
+	return 0;
+}
+
+/**
+ * mul_func - Emulate a MUL instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int mul_func(struct pt_regs *regs, u32 ir)
+{
+	s64 res;
+	s32 rt, rs;
+
+	if (!MIPSInst_RD(ir))
+		return 0;
+	rt = regs->regs[MIPSInst_RT(ir)];
+	rs = regs->regs[MIPSInst_RS(ir)];
+	res = (s64)rt * (s64)rs;
+
+	rs = res;
+	regs->regs[MIPSInst_RD(ir)] = (s64)rs;
+
+	MIPS_R2_STATS(muls);
+
+	return 0;
+}
+
+/**
+ * clz_func - Emulate a CLZ instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int clz_func(struct pt_regs *regs, u32 ir)
+{
+	u32 res;
+	u32 rs;
+
+	if (!MIPSInst_RD(ir))
+		return 0;
+
+	rs = regs->regs[MIPSInst_RS(ir)];
+	__asm__ __volatile__("clz %0, %1" : "=r"(res) : "r"(rs));
+	regs->regs[MIPSInst_RD(ir)] = res;
+
+	MIPS_R2_STATS(bops);
+
+	return 0;
+}
+
+/**
+ * clo_func - Emulate a CLO instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+
+static int clo_func(struct pt_regs *regs, u32 ir)
+{
+	u32 res;
+	u32 rs;
+
+	if (!MIPSInst_RD(ir))
+		return 0;
+
+	rs = regs->regs[MIPSInst_RS(ir)];
+	__asm__ __volatile__("clo %0, %1" : "=r"(res) : "r"(rs));
+	regs->regs[MIPSInst_RD(ir)] = res;
+
+	MIPS_R2_STATS(bops);
+
+	return 0;
+}
+
+/**
+ * dclz_func - Emulate a DCLZ instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int dclz_func(struct pt_regs *regs, u32 ir)
+{
+	u64 res;
+	u64 rs;
+
+	if (config_enabled(CONFIG_32BIT))
+		return SIGILL;
+
+	if (!MIPSInst_RD(ir))
+		return 0;
+
+	rs = regs->regs[MIPSInst_RS(ir)];
+	__asm__ __volatile__("dclz %0, %1" : "=r"(res) : "r"(rs));
+	regs->regs[MIPSInst_RD(ir)] = res;
+
+	MIPS_R2_STATS(bops);
+
+	return 0;
+}
+
+/**
+ * dclo_func - Emulate a DCLO instruction
+ * @regs: Process register set
+ * @ir: Instruction
+ *
+ * Returns 0 since it always succeeds.
+ */
+static int dclo_func(struct pt_regs *regs, u32 ir)
+{
+	u64 res;
+	u64 rs;
+
+	if (config_enabled(CONFIG_32BIT))
+		return SIGILL;
+
+	if (!MIPSInst_RD(ir))
+		return 0;
+
+	rs = regs->regs[MIPSInst_RS(ir)];
+	__asm__ __volatile__("dclo %0, %1" : "=r"(res) : "r"(rs));
+	regs->regs[MIPSInst_RD(ir)] = res;
+
+	MIPS_R2_STATS(bops);
+
+	return 0;
+}
+
+/* R6 removed instructions for the SPECIAL2 opcode */
+static struct r2_decoder_table spec2_op_table[] = {
+	{ 0xfc00ffff, 0x70000000, madd_func },
+	{ 0xfc00ffff, 0x70000001, maddu_func },
+	{ 0xfc0007ff, 0x70000002, mul_func },
+	{ 0xfc00ffff, 0x70000004, msub_func },
+	{ 0xfc00ffff, 0x70000005, msubu_func },
+	{ 0xfc0007ff, 0x70000020, clz_func },
+	{ 0xfc0007ff, 0x70000021, clo_func },
+	{ 0xfc0007ff, 0x70000024, dclz_func },
+	{ 0xfc0007ff, 0x70000025, dclo_func },
+	{ }
+};
+
+static inline int mipsr2_find_op_func(struct pt_regs *regs, u32 inst,
+				      struct r2_decoder_table *table)
+{
+	struct r2_decoder_table *p;
+	int err;
+
+	for (p = table; p->func; p++) {
+		if ((inst & p->mask) == p->code) {
+			err = (p->func)(regs, inst);
+			return err;
+		}
+	}
+	return SIGILL;
+}
+
+/**
+ * mipsr2_decoder: Decode and emulate a MIPS R2 instruction
+ * @regs: Process register set
+ * @inst: Instruction to decode and emulate
+ */
+int mipsr2_decoder(struct pt_regs *regs, u32 inst)
+{
+	int err = 0;
+	unsigned long vaddr;
+	u32 nir;
+	unsigned long cpc, epc, nepc, r31, res, rs, rt;
+
+	void __user *fault_addr = NULL;
+	int pass = 0;
+
+repeat:
+	r31 = regs->regs[31];
+	epc = regs->cp0_epc;
+	err = compute_return_epc(regs);
+	if (err < 0) {
+		BUG();
+		return SIGEMT;
+	}
+	pr_debug("Emulating the 0x%08x R2 instruction @ 0x%08lx (pass=%d))\n",
+		 inst, epc, pass);
+
+	switch (MIPSInst_OPCODE(inst)) {
+	case spec_op:
+		err = mipsr2_find_op_func(regs, inst, spec_op_table);
+		if (err < 0) {
+			/* FPU instruction under JR */
+			regs->cp0_cause |= CAUSEF_BD;
+			goto fpu_emul;
+		}
+		break;
+	case spec2_op:
+		err = mipsr2_find_op_func(regs, inst, spec2_op_table);
+		break;
+	case bcond_op:
+		rt = MIPSInst_RT(inst);
+		rs = MIPSInst_RS(inst);
+		switch (rt) {
+		case tgei_op:
+			if ((long)regs->regs[rs] >= MIPSInst_SIMM(inst))
+				do_trap_or_bp(regs, 0, "TGEI");
+
+			MIPS_R2_STATS(traps);
+
+			break;
+		case tgeiu_op:
+			if (regs->regs[rs] >= MIPSInst_UIMM(inst))
+				do_trap_or_bp(regs, 0, "TGEIU");
+
+			MIPS_R2_STATS(traps);
+
+			break;
+		case tlti_op:
+			if ((long)regs->regs[rs] < MIPSInst_SIMM(inst))
+				do_trap_or_bp(regs, 0, "TLTI");
+
+			MIPS_R2_STATS(traps);
+
+			break;
+		case tltiu_op:
+			if (regs->regs[rs] < MIPSInst_UIMM(inst))
+				do_trap_or_bp(regs, 0, "TLTIU");
+
+			MIPS_R2_STATS(traps);
+
+			break;
+		case teqi_op:
+			if (regs->regs[rs] == MIPSInst_SIMM(inst))
+				do_trap_or_bp(regs, 0, "TEQI");
+
+			MIPS_R2_STATS(traps);
+
+			break;
+		case tnei_op:
+			if (regs->regs[rs] != MIPSInst_SIMM(inst))
+				do_trap_or_bp(regs, 0, "TNEI");
+
+			MIPS_R2_STATS(traps);
+
+			break;
+		case bltzl_op:
+		case bgezl_op:
+		case bltzall_op:
+		case bgezall_op:
+			if (delay_slot(regs)) {
+				err = SIGILL;
+				break;
+			}
+			regs->regs[31] = r31;
+			regs->cp0_epc = epc;
+			err = __compute_return_epc(regs);
+			if (err < 0)
+				return SIGEMT;
+			if (err != BRANCH_LIKELY_TAKEN)
+				break;
+			cpc = regs->cp0_epc;
+			nepc = epc + 4;
+			err = __get_user(nir, (u32 __user *)nepc);
+			if (err) {
+				err = SIGSEGV;
+				break;
+			}
+			/*
+			 * This will probably be optimized away when
+			 * CONFIG_DEBUG_FS is not enabled
+			 */
+			switch (rt) {
+			case bltzl_op:
+				MIPS_R2BR_STATS(bltzl);
+				break;
+			case bgezl_op:
+				MIPS_R2BR_STATS(bgezl);
+				break;
+			case bltzall_op:
+				MIPS_R2BR_STATS(bltzall);
+				break;
+			case bgezall_op:
+				MIPS_R2BR_STATS(bgezall);
+				break;
+			}
+
+			switch (MIPSInst_OPCODE(nir)) {
+			case cop1_op:
+			case cop1x_op:
+			case lwc1_op:
+			case swc1_op:
+				regs->cp0_cause |= CAUSEF_BD;
+				goto fpu_emul;
+			}
+			if (nir) {
+				err = mipsr6_emul(regs, nir);
+				if (err > 0) {
+					err = mips_dsemul(regs, nir, cpc);
+					if (err == SIGILL)
+						err = SIGEMT;
+					MIPS_R2_STATS(dsemul);
+				}
+			}
+			break;
+		case bltzal_op:
+		case bgezal_op:
+			if (delay_slot(regs)) {
+				err = SIGILL;
+				break;
+			}
+			regs->regs[31] = r31;
+			regs->cp0_epc = epc;
+			err = __compute_return_epc(regs);
+			if (err < 0)
+				return SIGEMT;
+			cpc = regs->cp0_epc;
+			nepc = epc + 4;
+			err = __get_user(nir, (u32 __user *)nepc);
+			if (err) {
+				err = SIGSEGV;
+				break;
+			}
+			/*
+			 * This will probably be optimized away when
+			 * CONFIG_DEBUG_FS is not enabled
+			 */
+			switch (rt) {
+			case bltzal_op:
+				MIPS_R2BR_STATS(bltzal);
+				break;
+			case bgezal_op:
+				MIPS_R2BR_STATS(bgezal);
+				break;
+			}
+
+			switch (MIPSInst_OPCODE(nir)) {
+			case cop1_op:
+			case cop1x_op:
+			case lwc1_op:
+			case swc1_op:
+				regs->cp0_cause |= CAUSEF_BD;
+				goto fpu_emul;
+			}
+			if (nir) {
+				err = mipsr6_emul(regs, nir);
+				if (err > 0) {
+					err = mips_dsemul(regs, nir, cpc);
+					if (err == SIGILL)
+						err = SIGEMT;
+					MIPS_R2_STATS(dsemul);
+				}
+			}
+			break;
+		default:
+			regs->regs[31] = r31;
+			regs->cp0_epc = epc;
+			err = SIGILL;
+			break;
+		}
+		break;
+
+	case beql_op:
+	case bnel_op:
+	case blezl_op:
+	case bgtzl_op:
+		if (delay_slot(regs)) {
+			err = SIGILL;
+			break;
+		}
+		regs->regs[31] = r31;
+		regs->cp0_epc = epc;
+		err = __compute_return_epc(regs);
+		if (err < 0)
+			return SIGEMT;
+		if (err != BRANCH_LIKELY_TAKEN)
+			break;
+		cpc = regs->cp0_epc;
+		nepc = epc + 4;
+		err = __get_user(nir, (u32 __user *)nepc);
+		if (err) {
+			err = SIGSEGV;
+			break;
+		}
+		/*
+		 * This will probably be optimized away when
+		 * CONFIG_DEBUG_FS is not enabled
+		 */
+		switch (MIPSInst_OPCODE(inst)) {
+		case beql_op:
+			MIPS_R2BR_STATS(beql);
+			break;
+		case bnel_op:
+			MIPS_R2BR_STATS(bnel);
+			break;
+		case blezl_op:
+			MIPS_R2BR_STATS(blezl);
+			break;
+		case bgtzl_op:
+			MIPS_R2BR_STATS(bgtzl);
+			break;
+		}
+
+		switch (MIPSInst_OPCODE(nir)) {
+		case cop1_op:
+		case cop1x_op:
+		case lwc1_op:
+		case swc1_op:
+			regs->cp0_cause |= CAUSEF_BD;
+			goto fpu_emul;
+		}
+		if (nir) {
+			err = mipsr6_emul(regs, nir);
+			if (err > 0) {
+				err = mips_dsemul(regs, nir, cpc);
+				if (err == SIGILL)
+					err = SIGEMT;
+				MIPS_R2_STATS(dsemul);
+			}
+		}
+		break;
+	case lwc1_op:
+	case swc1_op:
+	case cop1_op:
+	case cop1x_op:
+fpu_emul:
+		regs->regs[31] = r31;
+		regs->cp0_epc = epc;
+		if (!used_math()) {     /* First time FPU user.  */
+			err = init_fpu();
+			set_used_math();
+		}
+		lose_fpu(1);    /* Save FPU state for the emulator. */
+
+		err = fpu_emulator_cop1Handler(regs, &current->thread.fpu, 0,
+					       &fault_addr);
+
+		/*
+		 * this is a tricky issue - lose_fpu() uses LL/SC atomics
+		 * if FPU is owned and effectively cancels user level LL/SC.
+		 * So, it could be logical to don't restore FPU ownership here.
+		 * But the sequence of multiple FPU instructions is much much
+		 * more often than LL-FPU-SC and I prefer loop here until
+		 * next scheduler cycle cancels FPU ownership
+		 */
+		own_fpu(1);	/* Restore FPU state. */
+
+		if (err)
+			current->thread.cp0_baduaddr = (unsigned long)fault_addr;
+
+		MIPS_R2_STATS(fpus);
+
+		break;
+
+	case lwl_op:
+		rt = regs->regs[MIPSInst_RT(inst)];
+		vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst);
+		if (!access_ok(VERIFY_READ, vaddr, 4)) {
+			current->thread.cp0_baduaddr = vaddr;
+			err = SIGSEGV;
+			break;
+		}
+		__asm__ __volatile__(
+			"	.set	push\n"
+			"	.set	reorder\n"
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+			"1:"	LB	"%1, 0(%2)\n"
+				INS	"%0, %1, 24, 8\n"
+			"	andi	%1, %2, 0x3\n"
+			"	beq	$0, %1, 9f\n"
+				ADDIU	"%2, %2, -1\n"
+			"2:"	LB	"%1, 0(%2)\n"
+				INS	"%0, %1, 16, 8\n"
+			"	andi	%1, %2, 0x3\n"
+			"	beq	$0, %1, 9f\n"
+				ADDIU	"%2, %2, -1\n"
+			"3:"	LB	"%1, 0(%2)\n"
+				INS	"%0, %1, 8, 8\n"
+			"	andi	%1, %2, 0x3\n"
+			"	beq	$0, %1, 9f\n"
+				ADDIU	"%2, %2, -1\n"
+			"4:"	LB	"%1, 0(%2)\n"
+				INS	"%0, %1, 0, 8\n"
+#else /* !CONFIG_CPU_LITTLE_ENDIAN */
+			"1:"	LB	"%1, 0(%2)\n"
+				INS	"%0, %1, 24, 8\n"
+				ADDIU	"%2, %2, 1\n"
+			"	andi	%1, %2, 0x3\n"
+			"	beq	$0, %1, 9f\n"
+			"2:"	LB	"%1, 0(%2)\n"
+				INS	"%0, %1, 16, 8\n"
+				ADDIU	"%2, %2, 1\n"
+			"	andi	%1, %2, 0x3\n"
+			"	beq	$0, %1, 9f\n"
+			"3:"	LB	"%1, 0(%2)\n"
+				INS	"%0, %1, 8, 8\n"
+				ADDIU	"%2, %2, 1\n"
+			"	andi	%1, %2, 0x3\n"
+			"	beq	$0, %1, 9f\n"
+			"4:"	LB	"%1, 0(%2)\n"
+				INS	"%0, %1, 0, 8\n"
+#endif /* CONFIG_CPU_LITTLE_ENDIAN */
+			"9:	sll	%0, %0, 0\n"
+			"10:\n"
+			"	.insn\n"
+			"	.section	.fixup,\"ax\"\n"
+			"8:	li	%3,%4\n"
+			"	j	10b\n"
+			"	.previous\n"
+			"	.section	__ex_table,\"a\"\n"
+			"	.word	1b,8b\n"
+			"	.word	2b,8b\n"
+			"	.word	3b,8b\n"
+			"	.word	4b,8b\n"
+			"	.previous\n"
+			"	.set	pop\n"
+			: "+&r"(rt), "=&r"(rs),
+			  "+&r"(vaddr), "+&r"(err)
+			: "i"(SIGSEGV));
+
+		if (MIPSInst_RT(inst) && !err)
+			regs->regs[MIPSInst_RT(inst)] = rt;
+
+		MIPS_R2_STATS(loads);
+
+		break;
+
+	case lwr_op:
+		rt = regs->regs[MIPSInst_RT(inst)];
+		vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst);
+		if (!access_ok(VERIFY_READ, vaddr, 4)) {
+			current->thread.cp0_baduaddr = vaddr;
+			err = SIGSEGV;
+			break;
+		}
+		__asm__ __volatile__(
+			"       .set	push\n"
+			"       .set	reorder\n"
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+			"1:"    LB	"%1, 0(%2)\n"
+				INS	"%0, %1, 0, 8\n"
+				ADDIU	"%2, %2, 1\n"
+			"       andi	%1, %2, 0x3\n"
+			"       beq	$0, %1, 9f\n"
+			"2:"    LB	"%1, 0(%2)\n"
+				INS	"%0, %1, 8, 8\n"
+				ADDIU	"%2, %2, 1\n"
+			"       andi	%1, %2, 0x3\n"
+			"       beq	$0, %1, 9f\n"
+			"3:"    LB	"%1, 0(%2)\n"
+				INS	"%0, %1, 16, 8\n"
+				ADDIU	"%2, %2, 1\n"
+			"       andi	%1, %2, 0x3\n"
+			"       beq	$0, %1, 9f\n"
+			"4:"    LB	"%1, 0(%2)\n"
+				INS	"%0, %1, 24, 8\n"
+			"       sll	%0, %0, 0\n"
+#else /* !CONFIG_CPU_LITTLE_ENDIAN */
+			"1:"    LB	"%1, 0(%2)\n"
+				INS	"%0, %1, 0, 8\n"
+			"       andi	%1, %2, 0x3\n"
+			"       beq	$0, %1, 9f\n"
+				ADDIU	"%2, %2, -1\n"
+			"2:"    LB	"%1, 0(%2)\n"
+				INS	"%0, %1, 8, 8\n"
+			"       andi	%1, %2, 0x3\n"
+			"       beq	$0, %1, 9f\n"
+				ADDIU	"%2, %2, -1\n"
+			"3:"    LB	"%1, 0(%2)\n"
+				INS	"%0, %1, 16, 8\n"
+			"       andi	%1, %2, 0x3\n"
+			"       beq	$0, %1, 9f\n"
+				ADDIU	"%2, %2, -1\n"
+			"4:"    LB	"%1, 0(%2)\n"
+				INS	"%0, %1, 24, 8\n"
+			"       sll	%0, %0, 0\n"
+#endif /* CONFIG_CPU_LITTLE_ENDIAN */
+			"9:\n"
+			"10:\n"
+			"	.insn\n"
+			"	.section	.fixup,\"ax\"\n"
+			"8:	li	%3,%4\n"
+			"	j	10b\n"
+			"       .previous\n"
+			"	.section	__ex_table,\"a\"\n"
+			"	.word	1b,8b\n"
+			"	.word	2b,8b\n"
+			"	.word	3b,8b\n"
+			"	.word	4b,8b\n"
+			"	.previous\n"
+			"	.set	pop\n"
+			: "+&r"(rt), "=&r"(rs),
+			  "+&r"(vaddr), "+&r"(err)
+			: "i"(SIGSEGV));
+		if (MIPSInst_RT(inst) && !err)
+			regs->regs[MIPSInst_RT(inst)] = rt;
+
+		MIPS_R2_STATS(loads);
+
+		break;
+
+	case swl_op:
+		rt = regs->regs[MIPSInst_RT(inst)];
+		vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst);
+		if (!access_ok(VERIFY_WRITE, vaddr, 4)) {
+			current->thread.cp0_baduaddr = vaddr;
+			err = SIGSEGV;
+			break;
+		}
+		__asm__ __volatile__(
+			"	.set	push\n"
+			"	.set	reorder\n"
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+				EXT	"%1, %0, 24, 8\n"
+			"1:"	SB	"%1, 0(%2)\n"
+			"	andi	%1, %2, 0x3\n"
+			"	beq	$0, %1, 9f\n"
+				ADDIU	"%2, %2, -1\n"
+				EXT	"%1, %0, 16, 8\n"
+			"2:"	SB	"%1, 0(%2)\n"
+			"	andi	%1, %2, 0x3\n"
+			"	beq	$0, %1, 9f\n"
+				ADDIU	"%2, %2, -1\n"
+				EXT	"%1, %0, 8, 8\n"
+			"3:"	SB	"%1, 0(%2)\n"
+			"	andi	%1, %2, 0x3\n"
+			"	beq	$0, %1, 9f\n"
+				ADDIU	"%2, %2, -1\n"
+				EXT	"%1, %0, 0, 8\n"
+			"4:"	SB	"%1, 0(%2)\n"
+#else /* !CONFIG_CPU_LITTLE_ENDIAN */
+				EXT	"%1, %0, 24, 8\n"
+			"1:"	SB	"%1, 0(%2)\n"
+				ADDIU	"%2, %2, 1\n"
+			"	andi	%1, %2, 0x3\n"
+			"	beq	$0, %1, 9f\n"
+				EXT	"%1, %0, 16, 8\n"
+			"2:"	SB	"%1, 0(%2)\n"
+				ADDIU	"%2, %2, 1\n"
+			"	andi	%1, %2, 0x3\n"
+			"	beq	$0, %1, 9f\n"
+				EXT	"%1, %0, 8, 8\n"
+			"3:"	SB	"%1, 0(%2)\n"
+				ADDIU	"%2, %2, 1\n"
+			"	andi	%1, %2, 0x3\n"
+			"	beq	$0, %1, 9f\n"
+				EXT	"%1, %0, 0, 8\n"
+			"4:"	SB	"%1, 0(%2)\n"
+#endif /* CONFIG_CPU_LITTLE_ENDIAN */
+			"9:\n"
+			"	.insn\n"
+			"       .section        .fixup,\"ax\"\n"
+			"8:	li	%3,%4\n"
+			"	j	9b\n"
+			"	.previous\n"
+			"	.section        __ex_table,\"a\"\n"
+			"	.word	1b,8b\n"
+			"	.word	2b,8b\n"
+			"	.word	3b,8b\n"
+			"	.word	4b,8b\n"
+			"	.previous\n"
+			"	.set	pop\n"
+			: "+&r"(rt), "=&r"(rs),
+			  "+&r"(vaddr), "+&r"(err)
+			: "i"(SIGSEGV)
+			: "memory");
+
+		MIPS_R2_STATS(stores);
+
+		break;
+
+	case swr_op:
+		rt = regs->regs[MIPSInst_RT(inst)];
+		vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst);
+		if (!access_ok(VERIFY_WRITE, vaddr, 4)) {
+			current->thread.cp0_baduaddr = vaddr;
+			err = SIGSEGV;
+			break;
+		}
+		__asm__ __volatile__(
+			"	.set	push\n"
+			"	.set	reorder\n"
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+				EXT	"%1, %0, 0, 8\n"
+			"1:"	SB	"%1, 0(%2)\n"
+				ADDIU	"%2, %2, 1\n"
+			"	andi	%1, %2, 0x3\n"
+			"	beq	$0, %1, 9f\n"
+				EXT	"%1, %0, 8, 8\n"
+			"2:"	SB	"%1, 0(%2)\n"
+				ADDIU	"%2, %2, 1\n"
+			"	andi	%1, %2, 0x3\n"
+			"	beq	$0, %1, 9f\n"
+				EXT	"%1, %0, 16, 8\n"
+			"3:"	SB	"%1, 0(%2)\n"
+				ADDIU	"%2, %2, 1\n"
+			"	andi	%1, %2, 0x3\n"
+			"	beq	$0, %1, 9f\n"
+				EXT	"%1, %0, 24, 8\n"
+			"4:"	SB	"%1, 0(%2)\n"
+#else /* !CONFIG_CPU_LITTLE_ENDIAN */
+				EXT	"%1, %0, 0, 8\n"
+			"1:"	SB	"%1, 0(%2)\n"
+			"	andi	%1, %2, 0x3\n"
+			"	beq	$0, %1, 9f\n"
+				ADDIU	"%2, %2, -1\n"
+				EXT	"%1, %0, 8, 8\n"
+			"2:"	SB	"%1, 0(%2)\n"
+			"	andi	%1, %2, 0x3\n"
+			"	beq	$0, %1, 9f\n"
+				ADDIU	"%2, %2, -1\n"
+				EXT	"%1, %0, 16, 8\n"
+			"3:"	SB	"%1, 0(%2)\n"
+			"	andi	%1, %2, 0x3\n"
+			"	beq	$0, %1, 9f\n"
+				ADDIU	"%2, %2, -1\n"
+				EXT	"%1, %0, 24, 8\n"
+			"4:"	SB	"%1, 0(%2)\n"
+#endif /* CONFIG_CPU_LITTLE_ENDIAN */
+			"9:\n"
+			"	.insn\n"
+			"	.section        .fixup,\"ax\"\n"
+			"8:	li	%3,%4\n"
+			"	j	9b\n"
+			"	.previous\n"
+			"	.section        __ex_table,\"a\"\n"
+			"	.word	1b,8b\n"
+			"	.word	2b,8b\n"
+			"	.word	3b,8b\n"
+			"	.word	4b,8b\n"
+			"	.previous\n"
+			"	.set	pop\n"
+			: "+&r"(rt), "=&r"(rs),
+			  "+&r"(vaddr), "+&r"(err)
+			: "i"(SIGSEGV)
+			: "memory");
+
+		MIPS_R2_STATS(stores);
+
+		break;
+
+	case ldl_op:
+		if (config_enabled(CONFIG_32BIT)) {
+		    err = SIGILL;
+		    break;
+		}
+
+		rt = regs->regs[MIPSInst_RT(inst)];
+		vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst);
+		if (!access_ok(VERIFY_READ, vaddr, 8)) {
+			current->thread.cp0_baduaddr = vaddr;
+			err = SIGSEGV;
+			break;
+		}
+		__asm__ __volatile__(
+			"	.set    push\n"
+			"	.set    reorder\n"
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+			"1:	lb	%1, 0(%2)\n"
+			"	dinsu	%0, %1, 56, 8\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	daddiu	%2, %2, -1\n"
+			"2:	lb	%1, 0(%2)\n"
+			"	dinsu	%0, %1, 48, 8\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	daddiu	%2, %2, -1\n"
+			"3:	lb	%1, 0(%2)\n"
+			"	dinsu	%0, %1, 40, 8\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	daddiu	%2, %2, -1\n"
+			"4:	lb	%1, 0(%2)\n"
+			"	dinsu	%0, %1, 32, 8\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	daddiu	%2, %2, -1\n"
+			"5:	lb	%1, 0(%2)\n"
+			"	dins	%0, %1, 24, 8\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	daddiu	%2, %2, -1\n"
+			"6:	lb	%1, 0(%2)\n"
+			"	dins	%0, %1, 16, 8\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	daddiu	%2, %2, -1\n"
+			"7:	lb	%1, 0(%2)\n"
+			"	dins	%0, %1, 8, 8\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	daddiu	%2, %2, -1\n"
+			"0:	lb	%1, 0(%2)\n"
+			"	dins	%0, %1, 0, 8\n"
+#else /* !CONFIG_CPU_LITTLE_ENDIAN */
+			"1:	lb	%1, 0(%2)\n"
+			"	dinsu	%0, %1, 56, 8\n"
+			"	daddiu	%2, %2, 1\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"2:	lb	%1, 0(%2)\n"
+			"	dinsu	%0, %1, 48, 8\n"
+			"	daddiu	%2, %2, 1\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"3:	lb	%1, 0(%2)\n"
+			"	dinsu	%0, %1, 40, 8\n"
+			"	daddiu  %2, %2, 1\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"4:	lb	%1, 0(%2)\n"
+			"	dinsu	%0, %1, 32, 8\n"
+			"	daddiu	%2, %2, 1\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"5:	lb	%1, 0(%2)\n"
+			"	dins	%0, %1, 24, 8\n"
+			"	daddiu	%2, %2, 1\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"6:	lb	%1, 0(%2)\n"
+			"	dins	%0, %1, 16, 8\n"
+			"	daddiu	%2, %2, 1\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"7:	lb	%1, 0(%2)\n"
+			"	dins	%0, %1, 8, 8\n"
+			"	daddiu	%2, %2, 1\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"0:	lb	%1, 0(%2)\n"
+			"	dins	%0, %1, 0, 8\n"
+#endif /* CONFIG_CPU_LITTLE_ENDIAN */
+			"9:\n"
+			"	.insn\n"
+			"	.section        .fixup,\"ax\"\n"
+			"8:	li	%3,%4\n"
+			"	j	9b\n"
+			"	.previous\n"
+			"	.section        __ex_table,\"a\"\n"
+			"	.word	1b,8b\n"
+			"	.word	2b,8b\n"
+			"	.word	3b,8b\n"
+			"	.word	4b,8b\n"
+			"	.word	5b,8b\n"
+			"	.word	6b,8b\n"
+			"	.word	7b,8b\n"
+			"	.word	0b,8b\n"
+			"	.previous\n"
+			"	.set	pop\n"
+			: "+&r"(rt), "=&r"(rs),
+			  "+&r"(vaddr), "+&r"(err)
+			: "i"(SIGSEGV));
+		if (MIPSInst_RT(inst) && !err)
+			regs->regs[MIPSInst_RT(inst)] = rt;
+
+		MIPS_R2_STATS(loads);
+		break;
+
+	case ldr_op:
+		if (config_enabled(CONFIG_32BIT)) {
+		    err = SIGILL;
+		    break;
+		}
+
+		rt = regs->regs[MIPSInst_RT(inst)];
+		vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst);
+		if (!access_ok(VERIFY_READ, vaddr, 8)) {
+			current->thread.cp0_baduaddr = vaddr;
+			err = SIGSEGV;
+			break;
+		}
+		__asm__ __volatile__(
+			"	.set    push\n"
+			"	.set    reorder\n"
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+			"1:	lb      %1, 0(%2)\n"
+			"	dins   %0, %1, 0, 8\n"
+			"	daddiu  %2, %2, 1\n"
+			"	andi    %1, %2, 0x7\n"
+			"	beq     $0, %1, 9f\n"
+			"2:	lb      %1, 0(%2)\n"
+			"	dins   %0, %1, 8, 8\n"
+			"	daddiu  %2, %2, 1\n"
+			"	andi    %1, %2, 0x7\n"
+			"	beq     $0, %1, 9f\n"
+			"3:	lb      %1, 0(%2)\n"
+			"	dins   %0, %1, 16, 8\n"
+			"	daddiu  %2, %2, 1\n"
+			"	andi    %1, %2, 0x7\n"
+			"	beq     $0, %1, 9f\n"
+			"4:	lb      %1, 0(%2)\n"
+			"	dins   %0, %1, 24, 8\n"
+			"	daddiu  %2, %2, 1\n"
+			"	andi    %1, %2, 0x7\n"
+			"	beq     $0, %1, 9f\n"
+			"5:	lb      %1, 0(%2)\n"
+			"	dinsu    %0, %1, 32, 8\n"
+			"	daddiu  %2, %2, 1\n"
+			"	andi    %1, %2, 0x7\n"
+			"	beq     $0, %1, 9f\n"
+			"6:	lb      %1, 0(%2)\n"
+			"	dinsu    %0, %1, 40, 8\n"
+			"	daddiu  %2, %2, 1\n"
+			"	andi    %1, %2, 0x7\n"
+			"	beq     $0, %1, 9f\n"
+			"7:	lb      %1, 0(%2)\n"
+			"	dinsu    %0, %1, 48, 8\n"
+			"	daddiu  %2, %2, 1\n"
+			"	andi    %1, %2, 0x7\n"
+			"	beq     $0, %1, 9f\n"
+			"0:	lb      %1, 0(%2)\n"
+			"	dinsu    %0, %1, 56, 8\n"
+#else /* !CONFIG_CPU_LITTLE_ENDIAN */
+			"1:	lb      %1, 0(%2)\n"
+			"	dins   %0, %1, 0, 8\n"
+			"	andi    %1, %2, 0x7\n"
+			"	beq     $0, %1, 9f\n"
+			"	daddiu  %2, %2, -1\n"
+			"2:	lb      %1, 0(%2)\n"
+			"	dins   %0, %1, 8, 8\n"
+			"	andi    %1, %2, 0x7\n"
+			"	beq     $0, %1, 9f\n"
+			"	daddiu  %2, %2, -1\n"
+			"3:	lb      %1, 0(%2)\n"
+			"	dins   %0, %1, 16, 8\n"
+			"	andi    %1, %2, 0x7\n"
+			"	beq     $0, %1, 9f\n"
+			"	daddiu  %2, %2, -1\n"
+			"4:	lb      %1, 0(%2)\n"
+			"	dins   %0, %1, 24, 8\n"
+			"	andi    %1, %2, 0x7\n"
+			"	beq     $0, %1, 9f\n"
+			"	daddiu  %2, %2, -1\n"
+			"5:	lb      %1, 0(%2)\n"
+			"	dinsu    %0, %1, 32, 8\n"
+			"	andi    %1, %2, 0x7\n"
+			"	beq     $0, %1, 9f\n"
+			"	daddiu  %2, %2, -1\n"
+			"6:	lb      %1, 0(%2)\n"
+			"	dinsu    %0, %1, 40, 8\n"
+			"	andi    %1, %2, 0x7\n"
+			"	beq     $0, %1, 9f\n"
+			"	daddiu  %2, %2, -1\n"
+			"7:	lb      %1, 0(%2)\n"
+			"	dinsu    %0, %1, 48, 8\n"
+			"	andi    %1, %2, 0x7\n"
+			"	beq     $0, %1, 9f\n"
+			"	daddiu  %2, %2, -1\n"
+			"0:	lb      %1, 0(%2)\n"
+			"	dinsu    %0, %1, 56, 8\n"
+#endif /* CONFIG_CPU_LITTLE_ENDIAN */
+			"9:\n"
+			"	.insn\n"
+			"	.section        .fixup,\"ax\"\n"
+			"8:	li     %3,%4\n"
+			"	j      9b\n"
+			"	.previous\n"
+			"	.section        __ex_table,\"a\"\n"
+			"	.word  1b,8b\n"
+			"	.word  2b,8b\n"
+			"	.word  3b,8b\n"
+			"	.word  4b,8b\n"
+			"	.word  5b,8b\n"
+			"	.word  6b,8b\n"
+			"	.word  7b,8b\n"
+			"	.word  0b,8b\n"
+			"	.previous\n"
+			"	.set    pop\n"
+			: "+&r"(rt), "=&r"(rs),
+			  "+&r"(vaddr), "+&r"(err)
+			: "i"(SIGSEGV));
+		if (MIPSInst_RT(inst) && !err)
+			regs->regs[MIPSInst_RT(inst)] = rt;
+
+		MIPS_R2_STATS(loads);
+		break;
+
+	case sdl_op:
+		if (config_enabled(CONFIG_32BIT)) {
+		    err = SIGILL;
+		    break;
+		}
+
+		rt = regs->regs[MIPSInst_RT(inst)];
+		vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst);
+		if (!access_ok(VERIFY_WRITE, vaddr, 8)) {
+			current->thread.cp0_baduaddr = vaddr;
+			err = SIGSEGV;
+			break;
+		}
+		__asm__ __volatile__(
+			"	.set	push\n"
+			"	.set	reorder\n"
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+			"	dextu	%1, %0, 56, 8\n"
+			"1:	sb	%1, 0(%2)\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	daddiu	%2, %2, -1\n"
+			"	dextu	%1, %0, 48, 8\n"
+			"2:	sb	%1, 0(%2)\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	daddiu	%2, %2, -1\n"
+			"	dextu	%1, %0, 40, 8\n"
+			"3:	sb	%1, 0(%2)\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	daddiu	%2, %2, -1\n"
+			"	dextu	%1, %0, 32, 8\n"
+			"4:	sb	%1, 0(%2)\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	daddiu	%2, %2, -1\n"
+			"	dext	%1, %0, 24, 8\n"
+			"5:	sb	%1, 0(%2)\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	daddiu	%2, %2, -1\n"
+			"	dext	%1, %0, 16, 8\n"
+			"6:	sb	%1, 0(%2)\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	daddiu	%2, %2, -1\n"
+			"	dext	%1, %0, 8, 8\n"
+			"7:	sb	%1, 0(%2)\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	daddiu	%2, %2, -1\n"
+			"	dext	%1, %0, 0, 8\n"
+			"0:	sb	%1, 0(%2)\n"
+#else /* !CONFIG_CPU_LITTLE_ENDIAN */
+			"	dextu	%1, %0, 56, 8\n"
+			"1:	sb	%1, 0(%2)\n"
+			"	daddiu	%2, %2, 1\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	dextu	%1, %0, 48, 8\n"
+			"2:	sb	%1, 0(%2)\n"
+			"	daddiu	%2, %2, 1\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	dextu	%1, %0, 40, 8\n"
+			"3:	sb	%1, 0(%2)\n"
+			"	daddiu	%2, %2, 1\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	dextu	%1, %0, 32, 8\n"
+			"4:	sb	%1, 0(%2)\n"
+			"	daddiu	%2, %2, 1\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	dext	%1, %0, 24, 8\n"
+			"5:	sb	%1, 0(%2)\n"
+			"	daddiu	%2, %2, 1\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	dext	%1, %0, 16, 8\n"
+			"6:	sb	%1, 0(%2)\n"
+			"	daddiu	%2, %2, 1\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	dext	%1, %0, 8, 8\n"
+			"7:	sb	%1, 0(%2)\n"
+			"	daddiu	%2, %2, 1\n"
+			"	andi	%1, %2, 0x7\n"
+			"	beq	$0, %1, 9f\n"
+			"	dext	%1, %0, 0, 8\n"
+			"0:	sb	%1, 0(%2)\n"
+#endif /* CONFIG_CPU_LITTLE_ENDIAN */
+			"9:\n"
+			"	.insn\n"
+			"	.section        .fixup,\"ax\"\n"
+			"8:	li	%3,%4\n"
+			"	j	9b\n"
+			"	.previous\n"
+			"	.section        __ex_table,\"a\"\n"
+			"	.word	1b,8b\n"
+			"	.word	2b,8b\n"
+			"	.word	3b,8b\n"
+			"	.word	4b,8b\n"
+			"	.word	5b,8b\n"
+			"	.word	6b,8b\n"
+			"	.word	7b,8b\n"
+			"	.word	0b,8b\n"
+			"	.previous\n"
+			"	.set	pop\n"
+			: "+&r"(rt), "=&r"(rs),
+			  "+&r"(vaddr), "+&r"(err)
+			: "i"(SIGSEGV)
+			: "memory");
+
+		MIPS_R2_STATS(stores);
+		break;
+
+	case sdr_op:
+		if (config_enabled(CONFIG_32BIT)) {
+		    err = SIGILL;
+		    break;
+		}
+
+		rt = regs->regs[MIPSInst_RT(inst)];
+		vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst);
+		if (!access_ok(VERIFY_WRITE, vaddr, 8)) {
+			current->thread.cp0_baduaddr = vaddr;
+			err = SIGSEGV;
+			break;
+		}
+		__asm__ __volatile__(
+			"       .set	push\n"
+			"       .set	reorder\n"
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+			"       dext	%1, %0, 0, 8\n"
+			"1:     sb	%1, 0(%2)\n"
+			"       daddiu	%2, %2, 1\n"
+			"       andi	%1, %2, 0x7\n"
+			"       beq	$0, %1, 9f\n"
+			"       dext	%1, %0, 8, 8\n"
+			"2:     sb	%1, 0(%2)\n"
+			"       daddiu	%2, %2, 1\n"
+			"       andi	%1, %2, 0x7\n"
+			"       beq	$0, %1, 9f\n"
+			"       dext	%1, %0, 16, 8\n"
+			"3:     sb	%1, 0(%2)\n"
+			"       daddiu	%2, %2, 1\n"
+			"       andi	%1, %2, 0x7\n"
+			"       beq	$0, %1, 9f\n"
+			"       dext	%1, %0, 24, 8\n"
+			"4:     sb	%1, 0(%2)\n"
+			"       daddiu	%2, %2, 1\n"
+			"       andi	%1, %2, 0x7\n"
+			"       beq	$0, %1, 9f\n"
+			"       dextu	%1, %0, 32, 8\n"
+			"5:     sb	%1, 0(%2)\n"
+			"       daddiu	%2, %2, 1\n"
+			"       andi	%1, %2, 0x7\n"
+			"       beq	$0, %1, 9f\n"
+			"       dextu	%1, %0, 40, 8\n"
+			"6:     sb	%1, 0(%2)\n"
+			"       daddiu	%2, %2, 1\n"
+			"       andi	%1, %2, 0x7\n"
+			"       beq	$0, %1, 9f\n"
+			"       dextu	%1, %0, 48, 8\n"
+			"7:     sb	%1, 0(%2)\n"
+			"       daddiu	%2, %2, 1\n"
+			"       andi	%1, %2, 0x7\n"
+			"       beq	$0, %1, 9f\n"
+			"       dextu	%1, %0, 56, 8\n"
+			"0:     sb	%1, 0(%2)\n"
+#else /* !CONFIG_CPU_LITTLE_ENDIAN */
+			"       dext	%1, %0, 0, 8\n"
+			"1:     sb	%1, 0(%2)\n"
+			"       andi	%1, %2, 0x7\n"
+			"       beq	$0, %1, 9f\n"
+			"       daddiu	%2, %2, -1\n"
+			"       dext	%1, %0, 8, 8\n"
+			"2:     sb	%1, 0(%2)\n"
+			"       andi	%1, %2, 0x7\n"
+			"       beq	$0, %1, 9f\n"
+			"       daddiu	%2, %2, -1\n"
+			"       dext	%1, %0, 16, 8\n"
+			"3:     sb	%1, 0(%2)\n"
+			"       andi	%1, %2, 0x7\n"
+			"       beq	$0, %1, 9f\n"
+			"       daddiu	%2, %2, -1\n"
+			"       dext	%1, %0, 24, 8\n"
+			"4:     sb	%1, 0(%2)\n"
+			"       andi	%1, %2, 0x7\n"
+			"       beq	$0, %1, 9f\n"
+			"       daddiu	%2, %2, -1\n"
+			"       dextu	%1, %0, 32, 8\n"
+			"5:     sb	%1, 0(%2)\n"
+			"       andi	%1, %2, 0x7\n"
+			"       beq	$0, %1, 9f\n"
+			"       daddiu	%2, %2, -1\n"
+			"       dextu	%1, %0, 40, 8\n"
+			"6:     sb	%1, 0(%2)\n"
+			"       andi	%1, %2, 0x7\n"
+			"       beq	$0, %1, 9f\n"
+			"       daddiu	%2, %2, -1\n"
+			"       dextu	%1, %0, 48, 8\n"
+			"7:     sb	%1, 0(%2)\n"
+			"       andi	%1, %2, 0x7\n"
+			"       beq	$0, %1, 9f\n"
+			"       daddiu	%2, %2, -1\n"
+			"       dextu	%1, %0, 56, 8\n"
+			"0:     sb	%1, 0(%2)\n"
+#endif /* CONFIG_CPU_LITTLE_ENDIAN */
+			"9:\n"
+			"       .insn\n"
+			"       .section        .fixup,\"ax\"\n"
+			"8:     li	%3,%4\n"
+			"       j	9b\n"
+			"       .previous\n"
+			"       .section        __ex_table,\"a\"\n"
+			"       .word	1b,8b\n"
+			"       .word	2b,8b\n"
+			"       .word	3b,8b\n"
+			"       .word	4b,8b\n"
+			"       .word	5b,8b\n"
+			"       .word	6b,8b\n"
+			"       .word	7b,8b\n"
+			"       .word	0b,8b\n"
+			"       .previous\n"
+			"       .set	pop\n"
+			: "+&r"(rt), "=&r"(rs),
+			  "+&r"(vaddr), "+&r"(err)
+			: "i"(SIGSEGV)
+			: "memory");
+
+		MIPS_R2_STATS(stores);
+
+		break;
+	case ll_op:
+		vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst);
+		if (vaddr & 0x3) {
+			current->thread.cp0_baduaddr = vaddr;
+			err = SIGBUS;
+			break;
+		}
+		if (!access_ok(VERIFY_READ, vaddr, 4)) {
+			current->thread.cp0_baduaddr = vaddr;
+			err = SIGBUS;
+			break;
+		}
+
+		if (!cpu_has_rw_llb) {
+			/*
+			 * An LL/SC block can't be safely emulated without
+			 * a Config5/LLB availability. So it's probably time to
+			 * kill our process before things get any worse. This is
+			 * because Config5/LLB allows us to use ERETNC so that
+			 * the LLAddr/LLB bit is not cleared when we return from
+			 * an exception. MIPS R2 LL/SC instructions trap with an
+			 * RI exception so once we emulate them here, we return
+			 * back to userland with ERETNC. That preserves the
+			 * LLAddr/LLB so the subsequent SC instruction will
+			 * succeed preserving the atomic semantics of the LL/SC
+			 * block. Without that, there is no safe way to emulate
+			 * an LL/SC block in MIPSR2 userland.
+			 */
+			pr_err("Can't emulate MIPSR2 LL/SC without Config5/LLB\n");
+			err = SIGKILL;
+			break;
+		}
+
+		__asm__ __volatile__(
+			"1:\n"
+			"ll	%0, 0(%2)\n"
+			"2:\n"
+			".insn\n"
+			".section        .fixup,\"ax\"\n"
+			"3:\n"
+			"li	%1, %3\n"
+			"j	2b\n"
+			".previous\n"
+			".section        __ex_table,\"a\"\n"
+			".word  1b, 3b\n"
+			".previous\n"
+			: "=&r"(res), "+&r"(err)
+			: "r"(vaddr), "i"(SIGSEGV)
+			: "memory");
+
+		if (MIPSInst_RT(inst) && !err)
+			regs->regs[MIPSInst_RT(inst)] = res;
+		MIPS_R2_STATS(llsc);
+
+		break;
+
+	case sc_op:
+		vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst);
+		if (vaddr & 0x3) {
+			current->thread.cp0_baduaddr = vaddr;
+			err = SIGBUS;
+			break;
+		}
+		if (!access_ok(VERIFY_WRITE, vaddr, 4)) {
+			current->thread.cp0_baduaddr = vaddr;
+			err = SIGBUS;
+			break;
+		}
+
+		if (!cpu_has_rw_llb) {
+			/*
+			 * An LL/SC block can't be safely emulated without
+			 * a Config5/LLB availability. So it's probably time to
+			 * kill our process before things get any worse. This is
+			 * because Config5/LLB allows us to use ERETNC so that
+			 * the LLAddr/LLB bit is not cleared when we return from
+			 * an exception. MIPS R2 LL/SC instructions trap with an
+			 * RI exception so once we emulate them here, we return
+			 * back to userland with ERETNC. That preserves the
+			 * LLAddr/LLB so the subsequent SC instruction will
+			 * succeed preserving the atomic semantics of the LL/SC
+			 * block. Without that, there is no safe way to emulate
+			 * an LL/SC block in MIPSR2 userland.
+			 */
+			pr_err("Can't emulate MIPSR2 LL/SC without Config5/LLB\n");
+			err = SIGKILL;
+			break;
+		}
+
+		res = regs->regs[MIPSInst_RT(inst)];
+
+		__asm__ __volatile__(
+			"1:\n"
+			"sc	%0, 0(%2)\n"
+			"2:\n"
+			".insn\n"
+			".section        .fixup,\"ax\"\n"
+			"3:\n"
+			"li	%1, %3\n"
+			"j	2b\n"
+			".previous\n"
+			".section        __ex_table,\"a\"\n"
+			".word	1b, 3b\n"
+			".previous\n"
+			: "+&r"(res), "+&r"(err)
+			: "r"(vaddr), "i"(SIGSEGV));
+
+		if (MIPSInst_RT(inst) && !err)
+			regs->regs[MIPSInst_RT(inst)] = res;
+
+		MIPS_R2_STATS(llsc);
+
+		break;
+
+	case lld_op:
+		if (config_enabled(CONFIG_32BIT)) {
+		    err = SIGILL;
+		    break;
+		}
+
+		vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst);
+		if (vaddr & 0x7) {
+			current->thread.cp0_baduaddr = vaddr;
+			err = SIGBUS;
+			break;
+		}
+		if (!access_ok(VERIFY_READ, vaddr, 8)) {
+			current->thread.cp0_baduaddr = vaddr;
+			err = SIGBUS;
+			break;
+		}
+
+		if (!cpu_has_rw_llb) {
+			/*
+			 * An LL/SC block can't be safely emulated without
+			 * a Config5/LLB availability. So it's probably time to
+			 * kill our process before things get any worse. This is
+			 * because Config5/LLB allows us to use ERETNC so that
+			 * the LLAddr/LLB bit is not cleared when we return from
+			 * an exception. MIPS R2 LL/SC instructions trap with an
+			 * RI exception so once we emulate them here, we return
+			 * back to userland with ERETNC. That preserves the
+			 * LLAddr/LLB so the subsequent SC instruction will
+			 * succeed preserving the atomic semantics of the LL/SC
+			 * block. Without that, there is no safe way to emulate
+			 * an LL/SC block in MIPSR2 userland.
+			 */
+			pr_err("Can't emulate MIPSR2 LL/SC without Config5/LLB\n");
+			err = SIGKILL;
+			break;
+		}
+
+		__asm__ __volatile__(
+			"1:\n"
+			"lld	%0, 0(%2)\n"
+			"2:\n"
+			".insn\n"
+			".section        .fixup,\"ax\"\n"
+			"3:\n"
+			"li	%1, %3\n"
+			"j	2b\n"
+			".previous\n"
+			".section        __ex_table,\"a\"\n"
+			".word  1b, 3b\n"
+			".previous\n"
+			: "=&r"(res), "+&r"(err)
+			: "r"(vaddr), "i"(SIGSEGV)
+			: "memory");
+		if (MIPSInst_RT(inst) && !err)
+			regs->regs[MIPSInst_RT(inst)] = res;
+
+		MIPS_R2_STATS(llsc);
+
+		break;
+
+	case scd_op:
+		if (config_enabled(CONFIG_32BIT)) {
+		    err = SIGILL;
+		    break;
+		}
+
+		vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst);
+		if (vaddr & 0x7) {
+			current->thread.cp0_baduaddr = vaddr;
+			err = SIGBUS;
+			break;
+		}
+		if (!access_ok(VERIFY_WRITE, vaddr, 8)) {
+			current->thread.cp0_baduaddr = vaddr;
+			err = SIGBUS;
+			break;
+		}
+
+		if (!cpu_has_rw_llb) {
+			/*
+			 * An LL/SC block can't be safely emulated without
+			 * a Config5/LLB availability. So it's probably time to
+			 * kill our process before things get any worse. This is
+			 * because Config5/LLB allows us to use ERETNC so that
+			 * the LLAddr/LLB bit is not cleared when we return from
+			 * an exception. MIPS R2 LL/SC instructions trap with an
+			 * RI exception so once we emulate them here, we return
+			 * back to userland with ERETNC. That preserves the
+			 * LLAddr/LLB so the subsequent SC instruction will
+			 * succeed preserving the atomic semantics of the LL/SC
+			 * block. Without that, there is no safe way to emulate
+			 * an LL/SC block in MIPSR2 userland.
+			 */
+			pr_err("Can't emulate MIPSR2 LL/SC without Config5/LLB\n");
+			err = SIGKILL;
+			break;
+		}
+
+		res = regs->regs[MIPSInst_RT(inst)];
+
+		__asm__ __volatile__(
+			"1:\n"
+			"scd	%0, 0(%2)\n"
+			"2:\n"
+			".insn\n"
+			".section        .fixup,\"ax\"\n"
+			"3:\n"
+			"li	%1, %3\n"
+			"j	2b\n"
+			".previous\n"
+			".section        __ex_table,\"a\"\n"
+			".word	1b, 3b\n"
+			".previous\n"
+			: "+&r"(res), "+&r"(err)
+			: "r"(vaddr), "i"(SIGSEGV));
+
+		if (MIPSInst_RT(inst) && !err)
+			regs->regs[MIPSInst_RT(inst)] = res;
+
+		MIPS_R2_STATS(llsc);
+
+		break;
+	case pref_op:
+		/* skip it */
+		break;
+	default:
+		err = SIGILL;
+	}
+
+	/*
+	 * Lets not return to userland just yet. It's constly and
+	 * it's likely we have more R2 instructions to emulate
+	 */
+	if (!err && (pass++ < MIPS_R2_EMUL_TOTAL_PASS)) {
+		regs->cp0_cause &= ~CAUSEF_BD;
+		err = get_user(inst, (u32 __user *)regs->cp0_epc);
+		if (!err)
+			goto repeat;
+
+		if (err < 0)
+			err = SIGSEGV;
+	}
+
+	if (err && (err != SIGEMT)) {
+		regs->regs[31] = r31;
+		regs->cp0_epc = epc;
+	}
+
+	/* Likely a MIPS R6 compatible instruction */
+	if (pass && (err == SIGILL))
+		err = 0;
+
+	return err;
+}
+
+#ifdef CONFIG_DEBUG_FS
+
+static int mipsr2_stats_show(struct seq_file *s, void *unused)
+{
+
+	seq_printf(s, "Instruction\tTotal\tBDslot\n------------------------------\n");
+	seq_printf(s, "movs\t\t%ld\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2emustats).movs,
+		   (unsigned long)__get_cpu_var(mipsr2bdemustats).movs);
+	seq_printf(s, "hilo\t\t%ld\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2emustats).hilo,
+		   (unsigned long)__get_cpu_var(mipsr2bdemustats).hilo);
+	seq_printf(s, "muls\t\t%ld\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2emustats).muls,
+		   (unsigned long)__get_cpu_var(mipsr2bdemustats).muls);
+	seq_printf(s, "divs\t\t%ld\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2emustats).divs,
+		   (unsigned long)__get_cpu_var(mipsr2bdemustats).divs);
+	seq_printf(s, "dsps\t\t%ld\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2emustats).dsps,
+		   (unsigned long)__get_cpu_var(mipsr2bdemustats).dsps);
+	seq_printf(s, "bops\t\t%ld\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2emustats).bops,
+		   (unsigned long)__get_cpu_var(mipsr2bdemustats).bops);
+	seq_printf(s, "traps\t\t%ld\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2emustats).traps,
+		   (unsigned long)__get_cpu_var(mipsr2bdemustats).traps);
+	seq_printf(s, "fpus\t\t%ld\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2emustats).fpus,
+		   (unsigned long)__get_cpu_var(mipsr2bdemustats).fpus);
+	seq_printf(s, "loads\t\t%ld\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2emustats).loads,
+		   (unsigned long)__get_cpu_var(mipsr2bdemustats).loads);
+	seq_printf(s, "stores\t\t%ld\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2emustats).stores,
+		   (unsigned long)__get_cpu_var(mipsr2bdemustats).stores);
+	seq_printf(s, "llsc\t\t%ld\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2emustats).llsc,
+		   (unsigned long)__get_cpu_var(mipsr2bdemustats).llsc);
+	seq_printf(s, "dsemul\t\t%ld\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2emustats).dsemul,
+		   (unsigned long)__get_cpu_var(mipsr2bdemustats).dsemul);
+	seq_printf(s, "jr\t\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2bremustats).jrs);
+	seq_printf(s, "bltzl\t\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2bremustats).bltzl);
+	seq_printf(s, "bgezl\t\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2bremustats).bgezl);
+	seq_printf(s, "bltzll\t\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2bremustats).bltzll);
+	seq_printf(s, "bgezll\t\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2bremustats).bgezll);
+	seq_printf(s, "bltzal\t\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2bremustats).bltzal);
+	seq_printf(s, "bgezal\t\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2bremustats).bgezal);
+	seq_printf(s, "beql\t\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2bremustats).beql);
+	seq_printf(s, "bnel\t\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2bremustats).bnel);
+	seq_printf(s, "blezl\t\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2bremustats).blezl);
+	seq_printf(s, "bgtzl\t\t%ld\n",
+		   (unsigned long)__get_cpu_var(mipsr2bremustats).bgtzl);
+
+	return 0;
+}
+
+static int mipsr2_stats_clear_show(struct seq_file *s, void *unused)
+{
+	mipsr2_stats_show(s, unused);
+
+	__get_cpu_var(mipsr2emustats).movs    = 0;
+	__get_cpu_var(mipsr2bdemustats).movs  = 0;
+	__get_cpu_var(mipsr2emustats).hilo    = 0;
+	__get_cpu_var(mipsr2bdemustats).hilo  = 0;
+	__get_cpu_var(mipsr2emustats).muls    = 0;
+	__get_cpu_var(mipsr2bdemustats).muls  = 0;
+	__get_cpu_var(mipsr2emustats).divs    = 0;
+	__get_cpu_var(mipsr2bdemustats).divs  = 0;
+	__get_cpu_var(mipsr2emustats).dsps    = 0;
+	__get_cpu_var(mipsr2bdemustats).dsps  = 0;
+	__get_cpu_var(mipsr2emustats).bops    = 0;
+	__get_cpu_var(mipsr2bdemustats).bops  = 0;
+	__get_cpu_var(mipsr2emustats).traps   = 0;
+	__get_cpu_var(mipsr2bdemustats).traps = 0;
+	__get_cpu_var(mipsr2emustats).fpus    = 0;
+	__get_cpu_var(mipsr2bdemustats).fpus  = 0;
+	__get_cpu_var(mipsr2emustats).loads   = 0;
+	__get_cpu_var(mipsr2bdemustats).loads = 0;
+	__get_cpu_var(mipsr2emustats).stores  = 0;
+	__get_cpu_var(mipsr2bdemustats).stores = 0;
+	__get_cpu_var(mipsr2emustats).llsc    = 0;
+	__get_cpu_var(mipsr2bdemustats).llsc  = 0;
+	__get_cpu_var(mipsr2emustats).dsemul  = 0;
+	__get_cpu_var(mipsr2bdemustats).dsemul = 0;
+
+	__get_cpu_var(mipsr2bremustats).jrs   = 0;
+	__get_cpu_var(mipsr2bremustats).bltzl = 0;
+	__get_cpu_var(mipsr2bremustats).bgezl = 0;
+	__get_cpu_var(mipsr2bremustats).bltzll = 0;
+	__get_cpu_var(mipsr2bremustats).bgezll = 0;
+	__get_cpu_var(mipsr2bremustats).bltzal = 0;
+	__get_cpu_var(mipsr2bremustats).bgezal = 0;
+	__get_cpu_var(mipsr2bremustats).beql  = 0;
+	__get_cpu_var(mipsr2bremustats).bnel  = 0;
+	__get_cpu_var(mipsr2bremustats).blezl = 0;
+	__get_cpu_var(mipsr2bremustats).bgtzl = 0;
+
+	return 0;
+}
+
+static int mipsr2_stats_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, mipsr2_stats_show, inode->i_private);
+}
+
+static int mipsr2_stats_clear_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, mipsr2_stats_clear_show, inode->i_private);
+}
+
+static const struct file_operations mipsr2_emul_fops = {
+	.open                   = mipsr2_stats_open,
+	.read			= seq_read,
+	.llseek			= seq_lseek,
+	.release		= single_release,
+};
+
+static const struct file_operations mipsr2_clear_fops = {
+	.open                   = mipsr2_stats_clear_open,
+	.read			= seq_read,
+	.llseek			= seq_lseek,
+	.release		= single_release,
+};
+
+
+static int __init mipsr2_init_debugfs(void)
+{
+	extern struct dentry	*mips_debugfs_dir;
+	struct dentry		*mipsr2_emul;
+
+	if (!mips_debugfs_dir)
+		return -ENODEV;
+
+	mipsr2_emul = debugfs_create_file("r2_emul_stats", S_IRUGO,
+					  mips_debugfs_dir, NULL,
+					  &mipsr2_emul_fops);
+	if (!mipsr2_emul)
+		return -ENOMEM;
+
+	mipsr2_emul = debugfs_create_file("r2_emul_stats_clear", S_IRUGO,
+					  mips_debugfs_dir, NULL,
+					  &mipsr2_clear_fops);
+	if (!mipsr2_emul)
+		return -ENOMEM;
+
+	return 0;
+}
+
+device_initcall(mipsr2_init_debugfs);
+
+#endif /* CONFIG_DEBUG_FS */
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 5223f173a5db..da0836574918 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -46,6 +46,7 @@
 #include <asm/fpu.h>
 #include <asm/fpu_emulator.h>
 #include <asm/idle.h>
+#include <asm/mips-r2-to-r6-emul.h>
 #include <asm/mipsregs.h>
 #include <asm/mipsmtregs.h>
 #include <asm/module.h>
@@ -793,7 +794,7 @@ out:
 	exception_exit(prev_state);
 }
 
-static void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
+void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
 	const char *str)
 {
 	siginfo_t info;
@@ -983,7 +984,32 @@ asmlinkage void do_ri(struct pt_regs *regs)
 	unsigned int opcode = 0;
 	int status = -1;
 
+	/*
+	 * Avoid any kernel code. Just emulate the R2 instruction
+	 * as quickly as possible.
+	 */
+	if (mipsr2_emulation && cpu_has_mips_r6 &&
+	    likely(user_mode(regs))) {
+		if (likely(get_user(opcode, epc) >= 0)) {
+			status = mipsr2_decoder(regs, opcode);
+			switch (status) {
+			case 0:
+			case SIGEMT:
+				return;
+			case SIGILL:
+				goto no_r2_instr;
+			default:
+				process_fpemu_return(status,
+						     &current->thread.cp0_baduaddr);
+				return;
+			}
+		}
+	}
+
+no_r2_instr:
+
 	prev_state = exception_enter();
+
 	if (notify_die(DIE_RI, "RI Fault", regs, 0, regs_to_trapnr(regs),
 		       SIGILL) == NOTIFY_STOP)
 		goto out;
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 64/67] MIPS: Make use of the ERETNC instruction on MIPS R6
@ 2014-12-18 15:10   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:10 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

The ERETNC instruction, introduced in MIPS R5, is similar to the ERET
one, except it does not clear the LLB bit in the LLADDR register.
This feature is necessary to safely emulate R2 LL/SC instructions.
However, on context switches, we need to clear the LLAddr/LLB bit
in order to make sure that an SC instruction from the new thread
will never succeed if it happens to interrupt an LL operation on the
same address from the previous thread.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/switch_to.h   |  9 ++++++---
 arch/mips/include/asm/thread_info.h |  2 +-
 arch/mips/kernel/asm-offsets.c      |  1 +
 arch/mips/kernel/entry.S            | 18 ++++++++++++++++++
 arch/mips/kernel/traps.c            |  2 ++
 5 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/arch/mips/include/asm/switch_to.h b/arch/mips/include/asm/switch_to.h
index b928b6f898cd..e92d6c4b5ed1 100644
--- a/arch/mips/include/asm/switch_to.h
+++ b/arch/mips/include/asm/switch_to.h
@@ -75,9 +75,12 @@ do {									\
 #endif
 
 #define __clear_software_ll_bit()					\
-do {									\
-	if (!__builtin_constant_p(cpu_has_llsc) || !cpu_has_llsc)	\
-		ll_bit = 0;						\
+do {	if (cpu_has_rw_llb) {						\
+		write_c0_lladdr(0);					\
+	} else {							\
+		if (!__builtin_constant_p(cpu_has_llsc) || !cpu_has_llsc)\
+			ll_bit = 0;					\
+	}								\
 } while (0)
 
 #define switch_to(prev, next, last)					\
diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h
index 7de865805deb..ffdfb5b06e8b 100644
--- a/arch/mips/include/asm/thread_info.h
+++ b/arch/mips/include/asm/thread_info.h
@@ -28,7 +28,7 @@ struct thread_info {
 	unsigned long		tp_value;	/* thread pointer */
 	__u32			cpu;		/* current CPU */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
-
+	int			r2_emul_return; /* 1 => Returning from R2 emulator */
 	mm_segment_t		addr_limit;	/*
 						 * thread address space limit:
 						 * 0x7fffffff for user-thead
diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
index b1d84bd4efb3..7b6c11aa1cae 100644
--- a/arch/mips/kernel/asm-offsets.c
+++ b/arch/mips/kernel/asm-offsets.c
@@ -97,6 +97,7 @@ void output_thread_info_defines(void)
 	OFFSET(TI_TP_VALUE, thread_info, tp_value);
 	OFFSET(TI_CPU, thread_info, cpu);
 	OFFSET(TI_PRE_COUNT, thread_info, preempt_count);
+	OFFSET(TI_R2_EMUL_RET, thread_info, r2_emul_return);
 	OFFSET(TI_ADDR_LIMIT, thread_info, addr_limit);
 	OFFSET(TI_RESTART_BLOCK, thread_info, restart_block);
 	OFFSET(TI_REGS, thread_info, regs);
diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
index d5ab21c3fd12..af41ba6db960 100644
--- a/arch/mips/kernel/entry.S
+++ b/arch/mips/kernel/entry.S
@@ -46,6 +46,11 @@ resume_userspace:
 	local_irq_disable		# make sure we dont miss an
 					# interrupt setting need_resched
 					# between sampling and return
+#ifdef CONFIG_MIPSR2_TO_R6_EMULATOR
+	lw	k0, TI_R2_EMUL_RET($28)
+	bnez	k0, restore_all_from_r2_emul
+#endif
+
 	LONG_L	a2, TI_FLAGS($28)	# current->work
 	andi	t0, a2, _TIF_WORK_MASK	# (ignoring syscall_trace)
 	bnez	t0, work_pending
@@ -114,6 +119,19 @@ restore_partial:		# restore partial frame
 	RESTORE_SP_AND_RET
 	.set	at
 
+#ifdef CONFIG_MIPSR2_TO_R6_EMULATOR
+restore_all_from_r2_emul:			# restore full frame
+	.set	noat
+	sw	zero, TI_R2_EMUL_RET($28)	# reset it
+	RESTORE_TEMP
+	RESTORE_AT
+	RESTORE_STATIC
+	RESTORE_SOME
+	LONG_L	sp, PT_R29(sp)
+	eretnc
+	.set	at
+#endif
+
 work_pending:
 	andi	t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS
 	beqz	t0, work_notifysig
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index da0836574918..a0c4716c3c69 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -995,12 +995,14 @@ asmlinkage void do_ri(struct pt_regs *regs)
 			switch (status) {
 			case 0:
 			case SIGEMT:
+				task_thread_info(current)->r2_emul_return = 1;
 				return;
 			case SIGILL:
 				goto no_r2_instr;
 			default:
 				process_fpemu_return(status,
 						     &current->thread.cp0_baduaddr);
+				task_thread_info(current)->r2_emul_return = 1;
 				return;
 			}
 		}
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 64/67] MIPS: Make use of the ERETNC instruction on MIPS R6
@ 2014-12-18 15:10   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:10 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

The ERETNC instruction, introduced in MIPS R5, is similar to the ERET
one, except it does not clear the LLB bit in the LLADDR register.
This feature is necessary to safely emulate R2 LL/SC instructions.
However, on context switches, we need to clear the LLAddr/LLB bit
in order to make sure that an SC instruction from the new thread
will never succeed if it happens to interrupt an LL operation on the
same address from the previous thread.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/switch_to.h   |  9 ++++++---
 arch/mips/include/asm/thread_info.h |  2 +-
 arch/mips/kernel/asm-offsets.c      |  1 +
 arch/mips/kernel/entry.S            | 18 ++++++++++++++++++
 arch/mips/kernel/traps.c            |  2 ++
 5 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/arch/mips/include/asm/switch_to.h b/arch/mips/include/asm/switch_to.h
index b928b6f898cd..e92d6c4b5ed1 100644
--- a/arch/mips/include/asm/switch_to.h
+++ b/arch/mips/include/asm/switch_to.h
@@ -75,9 +75,12 @@ do {									\
 #endif
 
 #define __clear_software_ll_bit()					\
-do {									\
-	if (!__builtin_constant_p(cpu_has_llsc) || !cpu_has_llsc)	\
-		ll_bit = 0;						\
+do {	if (cpu_has_rw_llb) {						\
+		write_c0_lladdr(0);					\
+	} else {							\
+		if (!__builtin_constant_p(cpu_has_llsc) || !cpu_has_llsc)\
+			ll_bit = 0;					\
+	}								\
 } while (0)
 
 #define switch_to(prev, next, last)					\
diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h
index 7de865805deb..ffdfb5b06e8b 100644
--- a/arch/mips/include/asm/thread_info.h
+++ b/arch/mips/include/asm/thread_info.h
@@ -28,7 +28,7 @@ struct thread_info {
 	unsigned long		tp_value;	/* thread pointer */
 	__u32			cpu;		/* current CPU */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
-
+	int			r2_emul_return; /* 1 => Returning from R2 emulator */
 	mm_segment_t		addr_limit;	/*
 						 * thread address space limit:
 						 * 0x7fffffff for user-thead
diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
index b1d84bd4efb3..7b6c11aa1cae 100644
--- a/arch/mips/kernel/asm-offsets.c
+++ b/arch/mips/kernel/asm-offsets.c
@@ -97,6 +97,7 @@ void output_thread_info_defines(void)
 	OFFSET(TI_TP_VALUE, thread_info, tp_value);
 	OFFSET(TI_CPU, thread_info, cpu);
 	OFFSET(TI_PRE_COUNT, thread_info, preempt_count);
+	OFFSET(TI_R2_EMUL_RET, thread_info, r2_emul_return);
 	OFFSET(TI_ADDR_LIMIT, thread_info, addr_limit);
 	OFFSET(TI_RESTART_BLOCK, thread_info, restart_block);
 	OFFSET(TI_REGS, thread_info, regs);
diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
index d5ab21c3fd12..af41ba6db960 100644
--- a/arch/mips/kernel/entry.S
+++ b/arch/mips/kernel/entry.S
@@ -46,6 +46,11 @@ resume_userspace:
 	local_irq_disable		# make sure we dont miss an
 					# interrupt setting need_resched
 					# between sampling and return
+#ifdef CONFIG_MIPSR2_TO_R6_EMULATOR
+	lw	k0, TI_R2_EMUL_RET($28)
+	bnez	k0, restore_all_from_r2_emul
+#endif
+
 	LONG_L	a2, TI_FLAGS($28)	# current->work
 	andi	t0, a2, _TIF_WORK_MASK	# (ignoring syscall_trace)
 	bnez	t0, work_pending
@@ -114,6 +119,19 @@ restore_partial:		# restore partial frame
 	RESTORE_SP_AND_RET
 	.set	at
 
+#ifdef CONFIG_MIPSR2_TO_R6_EMULATOR
+restore_all_from_r2_emul:			# restore full frame
+	.set	noat
+	sw	zero, TI_R2_EMUL_RET($28)	# reset it
+	RESTORE_TEMP
+	RESTORE_AT
+	RESTORE_STATIC
+	RESTORE_SOME
+	LONG_L	sp, PT_R29(sp)
+	eretnc
+	.set	at
+#endif
+
 work_pending:
 	andi	t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS
 	beqz	t0, work_notifysig
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index da0836574918..a0c4716c3c69 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -995,12 +995,14 @@ asmlinkage void do_ri(struct pt_regs *regs)
 			switch (status) {
 			case 0:
 			case SIGEMT:
+				task_thread_info(current)->r2_emul_return = 1;
 				return;
 			case SIGILL:
 				goto no_r2_instr;
 			default:
 				process_fpemu_return(status,
 						     &current->thread.cp0_baduaddr);
+				task_thread_info(current)->r2_emul_return = 1;
 				return;
 			}
 		}
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 65/67] MIPS: Malta: malta-int: Set correct asm ISA level
@ 2014-12-18 15:10   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:10 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 changed the opcode for the clz instruction so we need
to properly instruct the assembler when using inline asm.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/mti-malta/malta-int.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c
index e4f43baa8f67..eada9eb0d44e 100644
--- a/arch/mips/mti-malta/malta-int.c
+++ b/arch/mips/mti-malta/malta-int.c
@@ -207,7 +207,7 @@ static inline int clz(unsigned long x)
 {
 	__asm__(
 	"	.set	push					\n"
-	"	.set	mips32					\n"
+	"	.set	"MIPS_ISA_LEVEL"			\n"
 	"	clz	%0, %1					\n"
 	"	.set	pop					\n"
 	: "=r" (x)
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 65/67] MIPS: Malta: malta-int: Set correct asm ISA level
@ 2014-12-18 15:10   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:10 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 changed the opcode for the clz instruction so we need
to properly instruct the assembler when using inline asm.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/mti-malta/malta-int.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c
index e4f43baa8f67..eada9eb0d44e 100644
--- a/arch/mips/mti-malta/malta-int.c
+++ b/arch/mips/mti-malta/malta-int.c
@@ -207,7 +207,7 @@ static inline int clz(unsigned long x)
 {
 	__asm__(
 	"	.set	push					\n"
-	"	.set	mips32					\n"
+	"	.set	"MIPS_ISA_LEVEL"			\n"
 	"	clz	%0, %1					\n"
 	"	.set	pop					\n"
 	: "=r" (x)
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 66/67] MIPS: Malta: Add support for building MIPS R6 kernel
@ 2014-12-18 15:10   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:10 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

The Malta platform supports MIPS R6 (via QEMU or real bitstreams)
so add support for it.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/Kconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 3fe856572d2e..0e1106c775a5 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -332,8 +332,10 @@ config MIPS_MALTA
 	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_HAS_CPU_MIPS32_R2
 	select SYS_HAS_CPU_MIPS32_R3_5
+	select SYS_HAS_CPU_MIPS32_R6
 	select SYS_HAS_CPU_MIPS64_R1
 	select SYS_HAS_CPU_MIPS64_R2
+	select SYS_HAS_CPU_MIPS64_R6
 	select SYS_HAS_CPU_NEVADA
 	select SYS_HAS_CPU_RM7000
 	select SYS_SUPPORTS_32BIT_KERNEL
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 66/67] MIPS: Malta: Add support for building MIPS R6 kernel
@ 2014-12-18 15:10   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:10 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

The Malta platform supports MIPS R6 (via QEMU or real bitstreams)
so add support for it.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/Kconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 3fe856572d2e..0e1106c775a5 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -332,8 +332,10 @@ config MIPS_MALTA
 	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_HAS_CPU_MIPS32_R2
 	select SYS_HAS_CPU_MIPS32_R3_5
+	select SYS_HAS_CPU_MIPS32_R6
 	select SYS_HAS_CPU_MIPS64_R1
 	select SYS_HAS_CPU_MIPS64_R2
+	select SYS_HAS_CPU_MIPS64_R6
 	select SYS_HAS_CPU_NEVADA
 	select SYS_HAS_CPU_RM7000
 	select SYS_SUPPORTS_32BIT_KERNEL
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 67/67] MIPS: Add Malta QEMU 32R6 defconfig
@ 2014-12-18 15:10   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:10 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

Add a Malta defconfig for the 32-bit MIPS R6 core as emulated
by QEMU.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/configs/malta_qemu_32r6_defconfig | 193 ++++++++++++++++++++++++++++
 1 file changed, 193 insertions(+)
 create mode 100644 arch/mips/configs/malta_qemu_32r6_defconfig

diff --git a/arch/mips/configs/malta_qemu_32r6_defconfig b/arch/mips/configs/malta_qemu_32r6_defconfig
new file mode 100644
index 000000000000..4bce1f8ebe98
--- /dev/null
+++ b/arch/mips/configs/malta_qemu_32r6_defconfig
@@ -0,0 +1,193 @@
+CONFIG_MIPS_MALTA=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_CPU_MIPS32_R6=y
+CONFIG_PAGE_SIZE_16KB=y
+CONFIG_HZ_100=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_AUDIT=y
+CONFIG_NO_HZ=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=15
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_EMBEDDED=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PCI=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_NET_IPIP=m
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+# CONFIG_INET_LRO is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_INGRESS=m
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=y
+CONFIG_NET_CLS_IND=y
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_IDE=y
+# CONFIG_IDE_PROC_FS is not set
+# CONFIG_IDEPCI_PCIBUS_ORDER is not set
+CONFIG_BLK_DEV_GENERIC=y
+CONFIG_BLK_DEV_PIIX=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_ADAPTEC is not set
+# CONFIG_NET_VENDOR_ALTEON is not set
+CONFIG_PCNET32=y
+# CONFIG_NET_VENDOR_ATHEROS is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_BROCADE is not set
+# CONFIG_NET_VENDOR_CHELSIO is not set
+# CONFIG_NET_VENDOR_CISCO is not set
+# CONFIG_NET_VENDOR_DEC is not set
+# CONFIG_NET_VENDOR_DLINK is not set
+# CONFIG_NET_VENDOR_EMULEX is not set
+# CONFIG_NET_VENDOR_EXAR is not set
+# CONFIG_NET_VENDOR_HP is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MELLANOX is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MYRI is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NVIDIA is not set
+# CONFIG_NET_VENDOR_OKI is not set
+# CONFIG_NET_PACKET_ENGINE is not set
+# CONFIG_NET_VENDOR_QLOGIC is not set
+# CONFIG_NET_VENDOR_REALTEK is not set
+# CONFIG_NET_VENDOR_RDC is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SILAN is not set
+# CONFIG_NET_VENDOR_SIS is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SUN is not set
+# CONFIG_NET_VENDOR_TEHUTI is not set
+# CONFIG_NET_VENDOR_TI is not set
+# CONFIG_NET_VENDOR_TOSHIBA is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+# CONFIG_WLAN is not set
+# CONFIG_VT is not set
+CONFIG_LEGACY_PTY_COUNT=4
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_HW_RANDOM=y
+# CONFIG_HWMON is not set
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+CONFIG_FB_MATROX=y
+CONFIG_FB_MATROX_G=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_UHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_CMOS=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_XFS_FS=y
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_POSIX_ACL=y
+CONFIG_QUOTA=y
+CONFIG_QFMT_V2=y
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_CIFS=m
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_FTRACE is not set
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* [PATCH RFC 67/67] MIPS: Add Malta QEMU 32R6 defconfig
@ 2014-12-18 15:10   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-18 15:10 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

Add a Malta defconfig for the 32-bit MIPS R6 core as emulated
by QEMU.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/configs/malta_qemu_32r6_defconfig | 193 ++++++++++++++++++++++++++++
 1 file changed, 193 insertions(+)
 create mode 100644 arch/mips/configs/malta_qemu_32r6_defconfig

diff --git a/arch/mips/configs/malta_qemu_32r6_defconfig b/arch/mips/configs/malta_qemu_32r6_defconfig
new file mode 100644
index 000000000000..4bce1f8ebe98
--- /dev/null
+++ b/arch/mips/configs/malta_qemu_32r6_defconfig
@@ -0,0 +1,193 @@
+CONFIG_MIPS_MALTA=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_CPU_MIPS32_R6=y
+CONFIG_PAGE_SIZE_16KB=y
+CONFIG_HZ_100=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_AUDIT=y
+CONFIG_NO_HZ=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=15
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_EMBEDDED=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PCI=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_NET_IPIP=m
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+# CONFIG_INET_LRO is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_INGRESS=m
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=y
+CONFIG_NET_CLS_IND=y
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_IDE=y
+# CONFIG_IDE_PROC_FS is not set
+# CONFIG_IDEPCI_PCIBUS_ORDER is not set
+CONFIG_BLK_DEV_GENERIC=y
+CONFIG_BLK_DEV_PIIX=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_ADAPTEC is not set
+# CONFIG_NET_VENDOR_ALTEON is not set
+CONFIG_PCNET32=y
+# CONFIG_NET_VENDOR_ATHEROS is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_BROCADE is not set
+# CONFIG_NET_VENDOR_CHELSIO is not set
+# CONFIG_NET_VENDOR_CISCO is not set
+# CONFIG_NET_VENDOR_DEC is not set
+# CONFIG_NET_VENDOR_DLINK is not set
+# CONFIG_NET_VENDOR_EMULEX is not set
+# CONFIG_NET_VENDOR_EXAR is not set
+# CONFIG_NET_VENDOR_HP is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MELLANOX is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MYRI is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NVIDIA is not set
+# CONFIG_NET_VENDOR_OKI is not set
+# CONFIG_NET_PACKET_ENGINE is not set
+# CONFIG_NET_VENDOR_QLOGIC is not set
+# CONFIG_NET_VENDOR_REALTEK is not set
+# CONFIG_NET_VENDOR_RDC is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SILAN is not set
+# CONFIG_NET_VENDOR_SIS is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SUN is not set
+# CONFIG_NET_VENDOR_TEHUTI is not set
+# CONFIG_NET_VENDOR_TI is not set
+# CONFIG_NET_VENDOR_TOSHIBA is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+# CONFIG_WLAN is not set
+# CONFIG_VT is not set
+CONFIG_LEGACY_PTY_COUNT=4
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_HW_RANDOM=y
+# CONFIG_HWMON is not set
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+CONFIG_FB_MATROX=y
+CONFIG_FB_MATROX_G=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_UHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_CMOS=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_XFS_FS=y
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_POSIX_ACL=y
+CONFIG_QUOTA=y
+CONFIG_QFMT_V2=y
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_CIFS=m
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_FTRACE is not set
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 19/67] MIPS: asm: atomic: Update asm and ISA constrains for MIPS R6 support
  2014-12-18 15:09   ` Markos Chandras
  (?)
@ 2014-12-18 18:50   ` David Daney
  2014-12-18 18:59     ` Måns Rullgård
                       ` (2 more replies)
  -1 siblings, 3 replies; 187+ messages in thread
From: David Daney @ 2014-12-18 18:50 UTC (permalink / raw)
  To: Markos Chandras; +Cc: linux-mips, Matthew Fortune

On 12/18/2014 07:09 AM, Markos Chandras wrote:
> MIPS R6 changed the opcodes for LL/SC instructions and reduced the
> offset field to 9-bits. This has some undesired effects with the "m"
> constrain since it implies a 16-bit immediate. As a result of which,
> add a register ("r") constrain as well to make sure the entire address
> is loaded to a register before the LL/SC operations. Also use macro
> to set the appropriate ISA for the asm blocks
>

Has support for MIPS R6 been added to GCC?

If so, that should include a proper constraint to be used with the new 
offset restrictions.  We should probably use that, instead of forcing to 
a "r" constraint.


> Cc: Matthew Fortune <Matthew.Fortune@imgtec.com>
> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
> ---
>   arch/mips/include/asm/atomic.h | 50 +++++++++++++++++++++---------------------
>   1 file changed, 25 insertions(+), 25 deletions(-)
>
> diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h
> index 6dd6bfc607e9..8669e0ec97e3 100644
> --- a/arch/mips/include/asm/atomic.h
> +++ b/arch/mips/include/asm/atomic.h
> @@ -60,13 +60,13 @@ static __inline__ void atomic_##op(int i, atomic_t * v)				\
>   										\
>   		do {								\
>   			__asm__ __volatile__(					\
> -			"	.set	arch=r4000			\n"	\
> -			"	ll	%0, %1		# atomic_" #op "\n"	\
> +			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"	\
> +			"	ll	%0, 0(%3)	# atomic_" #op "\n"	\
>   			"	" #asm_op " %0, %2			\n"	\
> -			"	sc	%0, %1				\n"	\
> +			"	sc	%0, 0(%3)			\n"	\
>   			"	.set	mips0				\n"	\
>   			: "=&r" (temp), "+m" (v->counter)			\
> -			: "Ir" (i));						\
> +			: "Ir" (i), "r" (&v->counter));				\

You lost the "m" constraint, but are still modifying memory.  There is 
no "memory" clobber here, so we are no longer correctly describing what 
is happening.

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 24/67] MIPS: asm: spinlock: Replace sub instruction with addiu
  2014-12-18 15:09   ` Markos Chandras
  (?)
@ 2014-12-18 18:53   ` David Daney
  2014-12-18 19:06     ` Ralf Baechle
  2014-12-19  8:51       ` Markos Chandras
  -1 siblings, 2 replies; 187+ messages in thread
From: David Daney @ 2014-12-18 18:53 UTC (permalink / raw)
  To: Markos Chandras; +Cc: linux-mips

On 12/18/2014 07:09 AM, Markos Chandras wrote:
> sub $reg, imm is not a real MIPS instruction. The assembler replaces
> that with 'addi $reg, -imm'.

That is a bug right there.  We cannot have faulting instructions like 
this in the kernel.

> However, addi has been removed from R6,
> so we replace the 'sub' instruction with 'addiu' instead.
>
> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
> ---
>   arch/mips/include/asm/spinlock.h | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/mips/include/asm/spinlock.h b/arch/mips/include/asm/spinlock.h
> index f63b3543c1a4..c82fc0eefbec 100644
> --- a/arch/mips/include/asm/spinlock.h
> +++ b/arch/mips/include/asm/spinlock.h
> @@ -277,7 +277,7 @@ static inline void arch_read_unlock(arch_rwlock_t *rw)
>   		do {
>   			__asm__ __volatile__(
>   			"1:	ll	%1, 0(%2)# arch_read_unlock	\n"
> -			"	sub	%1, 1				\n"
> +			"	addiu	%1, -1				\n"

Instead, how about fixing the real bug by s/sub/subu/.

Would that work for R6 too?  If so, just do that.

>   			"	sc	%1, 0(%2)			\n"
>   			: "+m" (rw->lock), "=&r" (tmp)
>   			: "r" (&rw->lock)
>

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 12/67] MIPS: asm: asmmacro: Replace add instructions with "addui"
  2014-12-18 15:09   ` Markos Chandras
  (?)
@ 2014-12-18 18:56   ` David Daney
  2014-12-19  9:01       ` Markos Chandras
  -1 siblings, 1 reply; 187+ messages in thread
From: David Daney @ 2014-12-18 18:56 UTC (permalink / raw)
  To: Markos Chandras, Ralf Baechle; +Cc: linux-mips

On 12/18/2014 07:09 AM, Markos Chandras wrote:
> The use of "add" instruction for immediate operations is wrong and
> relies to gas being smart enough to notice that and replace it with
> either addi or addui. However, MIPS R6 removed the addi instruction
> so, fix this problem properly by using the correct instruction
> directly.
>

This is another case of the use of "add" being a real bug.  We should 
never have faulting instructions like this in the kernel.

Can you send all patches in this set that fix this bug as a separate 
patch?  Since they are obviously correct, and really should be used by 
all non-R6 processors, we can get them in sooner that the entire R6 thing.

Thanks,
David Daney

> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
> ---
>   arch/mips/include/asm/asmmacro.h | 4 ++--
>   1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h
> index fe08084f5adb..55c07c40c199 100644
> --- a/arch/mips/include/asm/asmmacro.h
> +++ b/arch/mips/include/asm/asmmacro.h
> @@ -304,7 +304,7 @@
>   	.set	push
>   	.set	noat
>   	SET_HARDFLOAT
> -	add	$1, \base, \off
> +	addiu	$1, \base, \off
>   	.word	LDD_MSA_INSN | (\wd << 6)
>   	.set	pop
>   	.endm
> @@ -313,7 +313,7 @@
>   	.set	push
>   	.set	noat
>   	SET_HARDFLOAT
> -	add	$1, \base, \off
> +	addiu	$1, \base, \off
>   	.word	STD_MSA_INSN | (\wd << 6)
>   	.set	pop
>   	.endm
>

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 19/67] MIPS: asm: atomic: Update asm and ISA constrains for MIPS R6 support
  2014-12-18 18:50   ` David Daney
@ 2014-12-18 18:59     ` Måns Rullgård
  2014-12-18 19:01     ` Ralf Baechle
  2014-12-19 10:01       ` Markos Chandras
  2 siblings, 0 replies; 187+ messages in thread
From: Måns Rullgård @ 2014-12-18 18:59 UTC (permalink / raw)
  To: David Daney; +Cc: Markos Chandras, linux-mips, Matthew Fortune

David Daney <ddaney.cavm@gmail.com> writes:

> On 12/18/2014 07:09 AM, Markos Chandras wrote:
>> MIPS R6 changed the opcodes for LL/SC instructions and reduced the
>> offset field to 9-bits. This has some undesired effects with the "m"
>> constrain since it implies a 16-bit immediate. As a result of which,
>> add a register ("r") constrain as well to make sure the entire address
>> is loaded to a register before the LL/SC operations. Also use macro
>> to set the appropriate ISA for the asm blocks
>>
>
> Has support for MIPS R6 been added to GCC?
>
> If so, that should include a proper constraint to be used with the new
> offset restrictions.  We should probably use that, instead of forcing
> to a "r" constraint.
>
>> Cc: Matthew Fortune <Matthew.Fortune@imgtec.com>
>> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
>> ---
>>   arch/mips/include/asm/atomic.h | 50 +++++++++++++++++++++---------------------
>>   1 file changed, 25 insertions(+), 25 deletions(-)
>>
>> diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h
>> index 6dd6bfc607e9..8669e0ec97e3 100644
>> --- a/arch/mips/include/asm/atomic.h
>> +++ b/arch/mips/include/asm/atomic.h
>> @@ -60,13 +60,13 @@ static __inline__ void atomic_##op(int i, atomic_t * v)				\
>>   										\
>>   		do {								\
>>   			__asm__ __volatile__(					\
>> -			"	.set	arch=r4000			\n"	\
>> -			"	ll	%0, %1		# atomic_" #op "\n"	\
>> +			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"	\
>> +			"	ll	%0, 0(%3)	# atomic_" #op "\n"	\
>>   			"	" #asm_op " %0, %2			\n"	\
>> -			"	sc	%0, %1				\n"	\
>> +			"	sc	%0, 0(%3)			\n"	\
>>   			"	.set	mips0				\n"	\
>>   			: "=&r" (temp), "+m" (v->counter)			\
>> -			: "Ir" (i));						\
>> +			: "Ir" (i), "r" (&v->counter));				\
>
> You lost the "m" constraint, but are still modifying memory.  There is
> no "memory" clobber here, so we are no longer correctly describing
> what is happening.

Rather than add a blanket "memory" clobber, it's better to keep the old
memory operand even if it is never used.  GCC will still assume it has
been modified.

-- 
Måns Rullgård
mans@mansr.com

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 19/67] MIPS: asm: atomic: Update asm and ISA constrains for MIPS R6 support
  2014-12-18 18:50   ` David Daney
  2014-12-18 18:59     ` Måns Rullgård
@ 2014-12-18 19:01     ` Ralf Baechle
  2014-12-18 21:04         ` Matthew Fortune
  2014-12-19 10:01       ` Markos Chandras
  2 siblings, 1 reply; 187+ messages in thread
From: Ralf Baechle @ 2014-12-18 19:01 UTC (permalink / raw)
  To: David Daney; +Cc: Markos Chandras, linux-mips, Matthew Fortune

On Thu, Dec 18, 2014 at 10:50:27AM -0800, David Daney wrote:

> On 12/18/2014 07:09 AM, Markos Chandras wrote:
> >MIPS R6 changed the opcodes for LL/SC instructions and reduced the
> >offset field to 9-bits. This has some undesired effects with the "m"
> >constrain since it implies a 16-bit immediate. As a result of which,
> >add a register ("r") constrain as well to make sure the entire address
> >is loaded to a register before the LL/SC operations. Also use macro
> >to set the appropriate ISA for the asm blocks
> >
> 
> Has support for MIPS R6 been added to GCC?
> 
> If so, that should include a proper constraint to be used with the new
> offset restrictions.  We should probably use that, instead of forcing to a
> "r" constraint.

In a non-public earlier discussion I've requested the same but somehow
that was ignored.

We need suitable constraints or the alternatives will be very, very ugly.

  Ralf

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 40/67] MIPS: mm: tlbex: Add MIPS R6 case for the EHB instruction
  2014-12-18 15:09   ` Markos Chandras
  (?)
@ 2014-12-18 19:05   ` David Daney
  -1 siblings, 0 replies; 187+ messages in thread
From: David Daney @ 2014-12-18 19:05 UTC (permalink / raw)
  To: Markos Chandras; +Cc: linux-mips, Leonid Yegoshin, Ralf Baechle

On 12/18/2014 07:09 AM, Markos Chandras wrote:
> From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
>
> The EHB instruction is supported by MIPS R6 so add the relevant
> option.

NAK.

In cpu-features.h we have the symbol cpu_has_mips_r2_exec_hazard.  Use 
that instead.

We need to move all those exceptions for different CPU revisions to the 
CPU probing code so that cpu_has_mips_r2_exec_hazard reports the right 
thing, and then always use cpu_has_mips_r2_exec_hazard.

Also you missed other EHB sites in tlbex.c, so this patch may not 
correct even as is.

David Daney

>
> Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
> ---
>   arch/mips/mm/tlbex.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
> index 14e5fae71a06..8a8a86a8942f 100644
> --- a/arch/mips/mm/tlbex.c
> +++ b/arch/mips/mm/tlbex.c
> @@ -501,7 +501,7 @@ static void build_tlb_write_entry(u32 **p, struct uasm_label **l,
>   	case tlb_indexed: tlbw = uasm_i_tlbwi; break;
>   	}
>
> -	if (cpu_has_mips_r2) {
> +	if (cpu_has_mips_r2 || cpu_has_mips_r6) {
>   		/*
>   		 * The architecture spec says an ehb is required here,
>   		 * but a number of cores do not have the hazard and
>

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 24/67] MIPS: asm: spinlock: Replace sub instruction with addiu
  2014-12-18 18:53   ` David Daney
@ 2014-12-18 19:06     ` Ralf Baechle
  2014-12-19  8:51       ` Markos Chandras
  1 sibling, 0 replies; 187+ messages in thread
From: Ralf Baechle @ 2014-12-18 19:06 UTC (permalink / raw)
  To: David Daney; +Cc: Markos Chandras, linux-mips

On Thu, Dec 18, 2014 at 10:53:05AM -0800, David Daney wrote:

> On 12/18/2014 07:09 AM, Markos Chandras wrote:
> >sub $reg, imm is not a real MIPS instruction. The assembler replaces
> >that with 'addi $reg, -imm'.
> 
> That is a bug right there.  We cannot have faulting instructions like this
> in the kernel.

The instruction is meant to kill the kernel if a readlock gets unlocked
more often than it was taken.  Think of it as an efficient method of
implementing a BUG_ON() for this condition.

I've only seen that overflow exception once and honestly, the primary
reason was my desparate search for a rarely used CPU feature.  So if
this ADDI is repaced by an ADDIU I won't be sad.

  Ralf

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 56/67] MIPS: kernel: branch: Emulate the BOVC, BEQC and BEQZALC R6 instructions
  2014-12-18 15:10   ` Markos Chandras
  (?)
@ 2014-12-18 19:07   ` David Daney
  2014-12-19  8:52       ` Markos Chandras
  -1 siblings, 1 reply; 187+ messages in thread
From: David Daney @ 2014-12-18 19:07 UTC (permalink / raw)
  To: Markos Chandras; +Cc: linux-mips

On 12/18/2014 07:10 AM, Markos Chandras wrote:
> MIPS R6 uses the <R6 ADDI opcode for the new BOVC, BEQC and
> BEQZALC instructions.
>
> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
> ---
>   arch/mips/include/uapi/asm/inst.h | 2 +-
>   arch/mips/kernel/branch.c         | 6 ++++++
>   2 files changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h
> index 648addfe1e1c..b95363e0551f 100644
> --- a/arch/mips/include/uapi/asm/inst.h
> +++ b/arch/mips/include/uapi/asm/inst.h
> @@ -21,7 +21,7 @@
>   enum major_op {
>   	spec_op, bcond_op, j_op, jal_op,
>   	beq_op, bne_op, blez_op, bgtz_op,
> -	addi_op, addiu_op, slti_op, sltiu_op,
> +	addi_or_cbcond0_op, addiu_op, slti_op, sltiu_op,

NAK.

This is a kernel ABI document, you cannot remove symbols.

>   	andi_op, ori_op, xori_op, lui_op,
>   	cop0_op, cop1_op, cop2_op, cop1x_op,
>   	beql_op, bnel_op, blezl_op, bgtzl_op,
> diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
> index d9e3a0d72a64..cf390c76ba95 100644
> --- a/arch/mips/kernel/branch.c
> +++ b/arch/mips/kernel/branch.c
> @@ -788,6 +788,12 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
>   	case lwc2_or_bc_op:
>   		regs->cp0_epc += 8;
>   		break;
> +	case addi_or_cbcond0_op:
> +		/* Compact branches: bovc, beqc, beqzalc */
> +		if (insn.i_format.rt && !insn.i_format.rs)
> +			regs->regs[31] = epc + 4;
> +		regs->cp0_epc += 8;
> +		break;
>   #endif
>   	}
>
>

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 57/67] MIPS: kernel: branch: Emulate the BNVC, BNEC and BNEZLAC R6 instructions
  2014-12-18 15:10   ` Markos Chandras
  (?)
@ 2014-12-18 19:08   ` David Daney
  -1 siblings, 0 replies; 187+ messages in thread
From: David Daney @ 2014-12-18 19:08 UTC (permalink / raw)
  To: Markos Chandras; +Cc: linux-mips

On 12/18/2014 07:10 AM, Markos Chandras wrote:
> MIPS R6 uses the <R6 DADDI opcode for the new BNVC, BNEC and
> BNEZLAC instructions.
>
> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
> ---
>   arch/mips/include/uapi/asm/inst.h | 2 +-
>   arch/mips/kernel/branch.c         | 2 ++
>   2 files changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h
> index b95363e0551f..096f32153ce2 100644
> --- a/arch/mips/include/uapi/asm/inst.h
> +++ b/arch/mips/include/uapi/asm/inst.h
> @@ -25,7 +25,7 @@ enum major_op {
>   	andi_op, ori_op, xori_op, lui_op,
>   	cop0_op, cop1_op, cop2_op, cop1x_op,
>   	beql_op, bnel_op, blezl_op, bgtzl_op,
> -	daddi_op, daddiu_op, ldl_op, ldr_op,
> +	daddi_or_cbcond1_op, daddiu_op, ldl_op, ldr_op,

NAK.

Same as the other one.

This is a kernel ABI document, you cannot remove symbols.



>   	spec2_op, jalx_op, mdmx_op, spec3_op,
>   	lb_op, lh_op, lwl_op, lw_op,
>   	lbu_op, lhu_op, lwr_op, lwu_op,
> diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
> index cf390c76ba95..4cc9070682e1 100644
> --- a/arch/mips/kernel/branch.c
> +++ b/arch/mips/kernel/branch.c
> @@ -790,6 +790,8 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
>   		break;
>   	case addi_or_cbcond0_op:
>   		/* Compact branches: bovc, beqc, beqzalc */
> +	case daddi_or_cbcond1_op:
> +		/* Compact branches: bnvc, bnec, bnezlac */
>   		if (insn.i_format.rt && !insn.i_format.rs)
>   			regs->regs[31] = epc + 4;
>   		regs->cp0_epc += 8;
>

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 01/67] MIPS: Add generic QEMU R6 PRid and cpu type identifiers
  2014-12-18 15:09   ` Markos Chandras
  (?)
@ 2014-12-18 19:10   ` David Daney
  2014-12-19  8:49       ` Markos Chandras
  -1 siblings, 1 reply; 187+ messages in thread
From: David Daney @ 2014-12-18 19:10 UTC (permalink / raw)
  To: Markos Chandras; +Cc: linux-mips, Leonid Yegoshin

On 12/18/2014 07:09 AM, Markos Chandras wrote:
> From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
>
> Latest versions of QEMU added support for mips32r6-generic and
> mips64r6-generic cpu types so add related definitions in preparation
> of MIPS R6 support.
>
> Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
> ---
>   arch/mips/include/asm/cpu.h | 3 +++
>   1 file changed, 3 insertions(+)
>
> diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
> index dfdc77ed1839..23a5dbc0ee06 100644
> --- a/arch/mips/include/asm/cpu.h
> +++ b/arch/mips/include/asm/cpu.h
> @@ -93,6 +93,7 @@
>    * These are the PRID's for when 23:16 == PRID_COMP_MIPS
>    */
>
> +#define PRID_IMP_QEMUR6		0x0000

Why not have a value for a real R6 CPU, and then have QEMU emulate that?


>   #define PRID_IMP_4KC		0x8000
>   #define PRID_IMP_5KC		0x8100
>   #define PRID_IMP_20KC		0x8200
> @@ -311,6 +312,8 @@ enum cpu_type_enum {
>   	CPU_LOONGSON3, CPU_CAVIUM_OCTEON, CPU_CAVIUM_OCTEON_PLUS,
>   	CPU_CAVIUM_OCTEON2, CPU_CAVIUM_OCTEON3, CPU_XLR, CPU_XLP,
>
> +	CPU_QEMUR6,
> +
>   	CPU_LAST
>   };
>
>

^ permalink raw reply	[flat|nested] 187+ messages in thread

* RE: [PATCH RFC 19/67] MIPS: asm: atomic: Update asm and ISA constrains for MIPS R6 support
@ 2014-12-18 21:04         ` Matthew Fortune
  0 siblings, 0 replies; 187+ messages in thread
From: Matthew Fortune @ 2014-12-18 21:04 UTC (permalink / raw)
  To: Ralf Baechle, David Daney; +Cc: Markos Chandras, linux-mips

> On Thu, Dec 18, 2014 at 10:50:27AM -0800, David Daney wrote:
> 
> > On 12/18/2014 07:09 AM, Markos Chandras wrote:
> > >MIPS R6 changed the opcodes for LL/SC instructions and reduced the
> > >offset field to 9-bits. This has some undesired effects with the "m"
> > >constrain since it implies a 16-bit immediate. As a result of which,
> > >add a register ("r") constrain as well to make sure the entire
> > >address is loaded to a register before the LL/SC operations. Also use
> > >macro to set the appropriate ISA for the asm blocks
> > >
> >
> > Has support for MIPS R6 been added to GCC?
> >
> > If so, that should include a proper constraint to be used with the new
> > offset restrictions.  We should probably use that, instead of forcing
> > to a "r" constraint.
> 
> In a non-public earlier discussion I've requested the same but somehow
> that was ignored.

I must have missed that comment or not been on the thread.

> We need suitable constraints or the alternatives will be very, very
> ugly.

We can certainly discuss and investigate such things but there is a
general problem of a growing list of different size displacement fields
in load/store instructions. Obviously you could just opt to keep things
the way they are for uMIPS today and leave the assembler to expand the
instruction but my opinion is that magic expanding assembler macros
are infuriating. We have however had to put support in binutils for many
of them, simply to keep enough software building to ease the transition.

So, all this patch does is highlight that magic assembler macros have
been hiding this issue since micromips was added.

From your experiences will people invest the effort to look at the
size of a displacement field for all the memory operations in an inline
asm block and then choose an appropriate memory constraint?

I'm obviously wary of putting things into GCC that are either only used
in a handful of places (or not at all). The alternative to constraints
is of course to try and reduce the need for inline asm and offer builtins
for specific instructions or more complex operations.

Thanks,
Matthew

^ permalink raw reply	[flat|nested] 187+ messages in thread

* RE: [PATCH RFC 19/67] MIPS: asm: atomic: Update asm and ISA constrains for MIPS R6 support
@ 2014-12-18 21:04         ` Matthew Fortune
  0 siblings, 0 replies; 187+ messages in thread
From: Matthew Fortune @ 2014-12-18 21:04 UTC (permalink / raw)
  To: Ralf Baechle, David Daney; +Cc: Markos Chandras, linux-mips

> On Thu, Dec 18, 2014 at 10:50:27AM -0800, David Daney wrote:
> 
> > On 12/18/2014 07:09 AM, Markos Chandras wrote:
> > >MIPS R6 changed the opcodes for LL/SC instructions and reduced the
> > >offset field to 9-bits. This has some undesired effects with the "m"
> > >constrain since it implies a 16-bit immediate. As a result of which,
> > >add a register ("r") constrain as well to make sure the entire
> > >address is loaded to a register before the LL/SC operations. Also use
> > >macro to set the appropriate ISA for the asm blocks
> > >
> >
> > Has support for MIPS R6 been added to GCC?
> >
> > If so, that should include a proper constraint to be used with the new
> > offset restrictions.  We should probably use that, instead of forcing
> > to a "r" constraint.
> 
> In a non-public earlier discussion I've requested the same but somehow
> that was ignored.

I must have missed that comment or not been on the thread.

> We need suitable constraints or the alternatives will be very, very
> ugly.

We can certainly discuss and investigate such things but there is a
general problem of a growing list of different size displacement fields
in load/store instructions. Obviously you could just opt to keep things
the way they are for uMIPS today and leave the assembler to expand the
instruction but my opinion is that magic expanding assembler macros
are infuriating. We have however had to put support in binutils for many
of them, simply to keep enough software building to ease the transition.

So, all this patch does is highlight that magic assembler macros have
been hiding this issue since micromips was added.

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 19/67] MIPS: asm: atomic: Update asm and ISA constrains for MIPS R6 support
@ 2014-12-18 22:18           ` Måns Rullgård
  0 siblings, 0 replies; 187+ messages in thread
From: Måns Rullgård @ 2014-12-18 22:18 UTC (permalink / raw)
  To: Matthew Fortune; +Cc: Ralf Baechle, David Daney, Markos Chandras, linux-mips

Matthew Fortune <Matthew.Fortune@imgtec.com> writes:

>> On Thu, Dec 18, 2014 at 10:50:27AM -0800, David Daney wrote:
>> 
>> > On 12/18/2014 07:09 AM, Markos Chandras wrote:
>> > >MIPS R6 changed the opcodes for LL/SC instructions and reduced the
>> > >offset field to 9-bits. This has some undesired effects with the "m"
>> > >constrain since it implies a 16-bit immediate. As a result of which,
>> > >add a register ("r") constrain as well to make sure the entire
>> > >address is loaded to a register before the LL/SC operations. Also use
>> > >macro to set the appropriate ISA for the asm blocks
>> > >
>> >
>> > Has support for MIPS R6 been added to GCC?
>> >
>> > If so, that should include a proper constraint to be used with the new
>> > offset restrictions.  We should probably use that, instead of forcing
>> > to a "r" constraint.
>> 
>> In a non-public earlier discussion I've requested the same but somehow
>> that was ignored.
>
> I must have missed that comment or not been on the thread.
>
>> We need suitable constraints or the alternatives will be very, very
>> ugly.
>
> We can certainly discuss and investigate such things but there is a
> general problem of a growing list of different size displacement fields
> in load/store instructions.

IMO, there should at least be a constraint sufficient for the smallest
displacement supported by any instruction (in addition to the "r"
constraint which of course always works).  If there is an instruction
limited to, say, 10 bits of displacement, it will work with a constraint
enforcing 9 bits, if not ideally, and it will almost always be better
than resorting to "r".

> Obviously you could just opt to keep things the way they are for uMIPS
> today and leave the assembler to expand the instruction but my opinion
> is that magic expanding assembler macros are infuriating. We have
> however had to put support in binutils for many of them, simply to
> keep enough software building to ease the transition.

I too find magic assemblers do more harm than good.

> So, all this patch does is highlight that magic assembler macros have
> been hiding this issue since micromips was added.
>
> From your experiences will people invest the effort to look at the
> size of a displacement field for all the memory operations in an inline
> asm block and then choose an appropriate memory constraint?

I can't speak for others, but when I use inline asm, I always try to
pick the best possible constraint.

> I'm obviously wary of putting things into GCC that are either only used
> in a handful of places (or not at all). The alternative to constraints
> is of course to try and reduce the need for inline asm and offer builtins
> for specific instructions or more complex operations.

If gcc is to implement the __atomic_* operations properly, it will need
suitable constraints for internal use.  I see no reason not to document
these for others as well.

-- 
Måns Rullgård
mans@mansr.com

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 19/67] MIPS: asm: atomic: Update asm and ISA constrains for MIPS R6 support
@ 2014-12-18 22:18           ` Måns Rullgård
  0 siblings, 0 replies; 187+ messages in thread
From: Måns Rullgård @ 2014-12-18 22:18 UTC (permalink / raw)
  To: Matthew Fortune; +Cc: Ralf Baechle, David Daney, Markos Chandras, linux-mips

Matthew Fortune <Matthew.Fortune@imgtec.com> writes:

>> On Thu, Dec 18, 2014 at 10:50:27AM -0800, David Daney wrote:
>> 
>> > On 12/18/2014 07:09 AM, Markos Chandras wrote:
>> > >MIPS R6 changed the opcodes for LL/SC instructions and reduced the
>> > >offset field to 9-bits. This has some undesired effects with the "m"
>> > >constrain since it implies a 16-bit immediate. As a result of which,
>> > >add a register ("r") constrain as well to make sure the entire
>> > >address is loaded to a register before the LL/SC operations. Also use
>> > >macro to set the appropriate ISA for the asm blocks
>> > >
>> >
>> > Has support for MIPS R6 been added to GCC?
>> >
>> > If so, that should include a proper constraint to be used with the new
>> > offset restrictions.  We should probably use that, instead of forcing
>> > to a "r" constraint.
>> 
>> In a non-public earlier discussion I've requested the same but somehow
>> that was ignored.
>
> I must have missed that comment or not been on the thread.
>
>> We need suitable constraints or the alternatives will be very, very
>> ugly.
>
> We can certainly discuss and investigate such things but there is a
> general problem of a growing list of different size displacement fields
> in load/store instructions.

IMO, there should at least be a constraint sufficient for the smallest
displacement supported by any instruction (in addition to the "r"
constraint which of course always works).  If there is an instruction
limited to, say, 10 bits of displacement, it will work with a constraint
enforcing 9 bits, if not ideally, and it will almost always be better
than resorting to "r".

> Obviously you could just opt to keep things the way they are for uMIPS
> today and leave the assembler to expand the instruction but my opinion
> is that magic expanding assembler macros are infuriating. We have
> however had to put support in binutils for many of them, simply to
> keep enough software building to ease the transition.

I too find magic assemblers do more harm than good.

> So, all this patch does is highlight that magic assembler macros have
> been hiding this issue since micromips was added.
>
> From your experiences will people invest the effort to look at the
> size of a displacement field for all the memory operations in an inline
> asm block and then choose an appropriate memory constraint?

I can't speak for others, but when I use inline asm, I always try to
pick the best possible constraint.

> I'm obviously wary of putting things into GCC that are either only used
> in a handful of places (or not at all). The alternative to constraints
> is of course to try and reduce the need for inline asm and offer builtins
> for specific instructions or more complex operations.

If gcc is to implement the __atomic_* operations properly, it will need
suitable constraints for internal use.  I see no reason not to document
these for others as well.

-- 
Måns Rullgård
mans@mansr.com

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 19/67] MIPS: asm: atomic: Update asm and ISA constrains for MIPS R6 support
  2014-12-18 21:04         ` Matthew Fortune
  (?)
  (?)
@ 2014-12-18 22:19         ` David Daney
  2014-12-18 22:58           ` Matthew Fortune
  -1 siblings, 1 reply; 187+ messages in thread
From: David Daney @ 2014-12-18 22:19 UTC (permalink / raw)
  To: Matthew Fortune; +Cc: Ralf Baechle, Markos Chandras, linux-mips

On 12/18/2014 01:04 PM, Matthew Fortune wrote:
>> On Thu, Dec 18, 2014 at 10:50:27AM -0800, David Daney wrote:
>>
>>> On 12/18/2014 07:09 AM, Markos Chandras wrote:
>>>> MIPS R6 changed the opcodes for LL/SC instructions and reduced the
>>>> offset field to 9-bits. This has some undesired effects with the "m"
>>>> constrain since it implies a 16-bit immediate. As a result of which,
>>>> add a register ("r") constrain as well to make sure the entire
>>>> address is loaded to a register before the LL/SC operations. Also use
>>>> macro to set the appropriate ISA for the asm blocks
>>>>
>>>
>>> Has support for MIPS R6 been added to GCC?
>>>
>>> If so, that should include a proper constraint to be used with the new
>>> offset restrictions.  We should probably use that, instead of forcing
>>> to a "r" constraint.
>>
>> In a non-public earlier discussion I've requested the same but somehow
>> that was ignored.
>
> I must have missed that comment or not been on the thread.
>
>> We need suitable constraints or the alternatives will be very, very
>> ugly.
>
> We can certainly discuss and investigate such things but there is a
> general problem of a growing list of different size displacement fields
> in load/store instructions. Obviously you could just opt to keep things
> the way they are for uMIPS today and leave the assembler to expand the
> instruction but my opinion is that magic expanding assembler macros
> are infuriating. We have however had to put support in binutils for many
> of them, simply to keep enough software building to ease the transition.
>
> So, all this patch does is highlight that magic assembler macros have
> been hiding this issue since micromips was added.
>
>>From your experiences will people invest the effort to look at the
> size of a displacement field for all the memory operations in an inline
> asm block and then choose an appropriate memory constraint?
>
> I'm obviously wary of putting things into GCC that are either only used
> in a handful of places (or not at all). The alternative to constraints
> is of course to try and reduce the need for inline asm and offer builtins
> for specific instructions or more complex operations.
>

Well, GCC directly emits LL/SC as part of its built-in support for 
atomic operations, so the knowledge of the constraints for the 
instructions must be present there.  Since the constraints must be 
present in GCC, using them in the kernel shouldn't be a problem.

David Daney

^ permalink raw reply	[flat|nested] 187+ messages in thread

* RE: [PATCH RFC 19/67] MIPS: asm: atomic: Update asm and ISA constrains for MIPS R6 support
  2014-12-18 22:19         ` David Daney
@ 2014-12-18 22:58           ` Matthew Fortune
  2014-12-18 23:43               ` Måns Rullgård
                               ` (2 more replies)
  0 siblings, 3 replies; 187+ messages in thread
From: Matthew Fortune @ 2014-12-18 22:58 UTC (permalink / raw)
  To: David Daney; +Cc: Ralf Baechle, Markos Chandras, linux-mips

David Daney <ddaney.cavm@gmail.com> writes:
> On 12/18/2014 01:04 PM, Matthew Fortune wrote:
> >> On Thu, Dec 18, 2014 at 10:50:27AM -0800, David Daney wrote:
> >>
> >>> On 12/18/2014 07:09 AM, Markos Chandras wrote:
> >>>> MIPS R6 changed the opcodes for LL/SC instructions and reduced the
> >>>> offset field to 9-bits. This has some undesired effects with the
> "m"
> >>>> constrain since it implies a 16-bit immediate. As a result of
> >>>> which, add a register ("r") constrain as well to make sure the
> >>>> entire address is loaded to a register before the LL/SC operations.
> >>>> Also use macro to set the appropriate ISA for the asm blocks
> >>>>
> >>>
> >>> Has support for MIPS R6 been added to GCC?
> >>>
> >>> If so, that should include a proper constraint to be used with the
> >>> new offset restrictions.  We should probably use that, instead of
> >>> forcing to a "r" constraint.
> >>
> >> In a non-public earlier discussion I've requested the same but
> >> somehow that was ignored.
> >
> > I must have missed that comment or not been on the thread.
> >
> >> We need suitable constraints or the alternatives will be very, very
> >> ugly.
> >
> > We can certainly discuss and investigate such things but there is a
> > general problem of a growing list of different size displacement
> > fields in load/store instructions. Obviously you could just opt to
> > keep things the way they are for uMIPS today and leave the assembler
> > to expand the instruction but my opinion is that magic expanding
> > assembler macros are infuriating. We have however had to put support
> > in binutils for many of them, simply to keep enough software building
> to ease the transition.
> >
> > So, all this patch does is highlight that magic assembler macros have
> > been hiding this issue since micromips was added.
> >
> >>From your experiences will people invest the effort to look at the
> > size of a displacement field for all the memory operations in an
> > inline asm block and then choose an appropriate memory constraint?
> >
> > I'm obviously wary of putting things into GCC that are either only
> > used in a handful of places (or not at all). The alternative to
> > constraints is of course to try and reduce the need for inline asm and
> > offer builtins for specific instructions or more complex operations.
> >
> 
> Well, GCC directly emits LL/SC as part of its built-in support for
> atomic operations, so the knowledge of the constraints for the
> instructions must be present there.  Since the constraints must be
> present in GCC, using them in the kernel shouldn't be a problem.

Yes you are right I thought this particular case only had constraints
for the immediate and not the whole memory operand, I'm suffering from
too many tasks and too little time. Several of the memory constraints are
marked as internal and I'm not sure if that means they are unsafe to use
from inline asm or just not deemed important.

The memory constraint that LL and SC need is 'ZC'. I don't believe this
is documented so you will have to trust that its meaning will not change
but I can give some assurance of that since I will review all MIPS GCC
changes.

Obviously to use anything other than the 'm' constraint you are going
to need to know when any given constraint was added to GCC.
'ZC' was only added to GCC in March 2013 r196828 which I believe it is a
GCC 4.9 feature so you will have to use it conditionally if you use it at
all.

BTW thanks for the thread, it seems I missed updating 'ZC' for MIPSR6.
Bug fixed!

Thanks,
Matthew

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 19/67] MIPS: asm: atomic: Update asm and ISA constrains for MIPS R6 support
@ 2014-12-18 23:43               ` Måns Rullgård
  0 siblings, 0 replies; 187+ messages in thread
From: Måns Rullgård @ 2014-12-18 23:43 UTC (permalink / raw)
  To: Matthew Fortune; +Cc: David Daney, Ralf Baechle, Markos Chandras, linux-mips

Matthew Fortune <Matthew.Fortune@imgtec.com> writes:

> David Daney <ddaney.cavm@gmail.com> writes:
>> On 12/18/2014 01:04 PM, Matthew Fortune wrote:
>> >> On Thu, Dec 18, 2014 at 10:50:27AM -0800, David Daney wrote:
>> >>
>> >>> On 12/18/2014 07:09 AM, Markos Chandras wrote:
>> >>>> MIPS R6 changed the opcodes for LL/SC instructions and reduced the
>> >>>> offset field to 9-bits. This has some undesired effects with the
>> "m"
>> >>>> constrain since it implies a 16-bit immediate. As a result of
>> >>>> which, add a register ("r") constrain as well to make sure the
>> >>>> entire address is loaded to a register before the LL/SC operations.
>> >>>> Also use macro to set the appropriate ISA for the asm blocks
>> >>>>
>> >>>
>> >>> Has support for MIPS R6 been added to GCC?
>> >>>
>> >>> If so, that should include a proper constraint to be used with the
>> >>> new offset restrictions.  We should probably use that, instead of
>> >>> forcing to a "r" constraint.
>> >>
>> >> In a non-public earlier discussion I've requested the same but
>> >> somehow that was ignored.
>> >
>> > I must have missed that comment or not been on the thread.
>> >
>> >> We need suitable constraints or the alternatives will be very, very
>> >> ugly.
>> >
>> > We can certainly discuss and investigate such things but there is a
>> > general problem of a growing list of different size displacement
>> > fields in load/store instructions. Obviously you could just opt to
>> > keep things the way they are for uMIPS today and leave the assembler
>> > to expand the instruction but my opinion is that magic expanding
>> > assembler macros are infuriating. We have however had to put support
>> > in binutils for many of them, simply to keep enough software building
>> to ease the transition.
>> >
>> > So, all this patch does is highlight that magic assembler macros have
>> > been hiding this issue since micromips was added.
>> >
>> >>From your experiences will people invest the effort to look at the
>> > size of a displacement field for all the memory operations in an
>> > inline asm block and then choose an appropriate memory constraint?
>> >
>> > I'm obviously wary of putting things into GCC that are either only
>> > used in a handful of places (or not at all). The alternative to
>> > constraints is of course to try and reduce the need for inline asm and
>> > offer builtins for specific instructions or more complex operations.
>> >
>> 
>> Well, GCC directly emits LL/SC as part of its built-in support for
>> atomic operations, so the knowledge of the constraints for the
>> instructions must be present there.  Since the constraints must be
>> present in GCC, using them in the kernel shouldn't be a problem.
>
> Yes you are right I thought this particular case only had constraints
> for the immediate and not the whole memory operand, I'm suffering from
> too many tasks and too little time. Several of the memory constraints are
> marked as internal and I'm not sure if that means they are unsafe to use
> from inline asm or just not deemed important.
>
> The memory constraint that LL and SC need is 'ZC'. I don't believe this
> is documented so you will have to trust that its meaning will not change
> but I can give some assurance of that since I will review all MIPS GCC
> changes.
>
> Obviously to use anything other than the 'm' constraint you are going
> to need to know when any given constraint was added to GCC.
> 'ZC' was only added to GCC in March 2013 r196828 which I believe it is a
> GCC 4.9 feature so you will have to use it conditionally if you use it at
> all.

The ZC constraint is documented, so it should be safe to use.  A bunch
of other Z* constraints are marked internal though.

-- 
Måns Rullgård
mans@mansr.com

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 19/67] MIPS: asm: atomic: Update asm and ISA constrains for MIPS R6 support
@ 2014-12-18 23:43               ` Måns Rullgård
  0 siblings, 0 replies; 187+ messages in thread
From: Måns Rullgård @ 2014-12-18 23:43 UTC (permalink / raw)
  To: Matthew Fortune; +Cc: David Daney, Ralf Baechle, Markos Chandras, linux-mips

Matthew Fortune <Matthew.Fortune@imgtec.com> writes:

> David Daney <ddaney.cavm@gmail.com> writes:
>> On 12/18/2014 01:04 PM, Matthew Fortune wrote:
>> >> On Thu, Dec 18, 2014 at 10:50:27AM -0800, David Daney wrote:
>> >>
>> >>> On 12/18/2014 07:09 AM, Markos Chandras wrote:
>> >>>> MIPS R6 changed the opcodes for LL/SC instructions and reduced the
>> >>>> offset field to 9-bits. This has some undesired effects with the
>> "m"
>> >>>> constrain since it implies a 16-bit immediate. As a result of
>> >>>> which, add a register ("r") constrain as well to make sure the
>> >>>> entire address is loaded to a register before the LL/SC operations.
>> >>>> Also use macro to set the appropriate ISA for the asm blocks
>> >>>>
>> >>>
>> >>> Has support for MIPS R6 been added to GCC?
>> >>>
>> >>> If so, that should include a proper constraint to be used with the
>> >>> new offset restrictions.  We should probably use that, instead of
>> >>> forcing to a "r" constraint.
>> >>
>> >> In a non-public earlier discussion I've requested the same but
>> >> somehow that was ignored.
>> >
>> > I must have missed that comment or not been on the thread.
>> >
>> >> We need suitable constraints or the alternatives will be very, very
>> >> ugly.
>> >
>> > We can certainly discuss and investigate such things but there is a
>> > general problem of a growing list of different size displacement
>> > fields in load/store instructions. Obviously you could just opt to
>> > keep things the way they are for uMIPS today and leave the assembler
>> > to expand the instruction but my opinion is that magic expanding
>> > assembler macros are infuriating. We have however had to put support
>> > in binutils for many of them, simply to keep enough software building
>> to ease the transition.
>> >
>> > So, all this patch does is highlight that magic assembler macros have
>> > been hiding this issue since micromips was added.
>> >
>> >>From your experiences will people invest the effort to look at the
>> > size of a displacement field for all the memory operations in an
>> > inline asm block and then choose an appropriate memory constraint?
>> >
>> > I'm obviously wary of putting things into GCC that are either only
>> > used in a handful of places (or not at all). The alternative to
>> > constraints is of course to try and reduce the need for inline asm and
>> > offer builtins for specific instructions or more complex operations.
>> >
>> 
>> Well, GCC directly emits LL/SC as part of its built-in support for
>> atomic operations, so the knowledge of the constraints for the
>> instructions must be present there.  Since the constraints must be
>> present in GCC, using them in the kernel shouldn't be a problem.
>
> Yes you are right I thought this particular case only had constraints
> for the immediate and not the whole memory operand, I'm suffering from
> too many tasks and too little time. Several of the memory constraints are
> marked as internal and I'm not sure if that means they are unsafe to use
> from inline asm or just not deemed important.
>
> The memory constraint that LL and SC need is 'ZC'. I don't believe this
> is documented so you will have to trust that its meaning will not change
> but I can give some assurance of that since I will review all MIPS GCC
> changes.
>
> Obviously to use anything other than the 'm' constraint you are going
> to need to know when any given constraint was added to GCC.
> 'ZC' was only added to GCC in March 2013 r196828 which I believe it is a
> GCC 4.9 feature so you will have to use it conditionally if you use it at
> all.

The ZC constraint is documented, so it should be safe to use.  A bunch
of other Z* constraints are marked internal though.

-- 
Måns Rullgård
mans@mansr.com

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 47/67] MIPS: kernel: branch: Prevent BEQL emulation for MIPS R6
  2014-12-18 15:09   ` Markos Chandras
  (?)
@ 2014-12-18 23:56   ` Joshua Kinard
  2014-12-19  8:54       ` Markos Chandras
  -1 siblings, 1 reply; 187+ messages in thread
From: Joshua Kinard @ 2014-12-18 23:56 UTC (permalink / raw)
  To: Markos Chandras, linux-mips

On 12/18/2014 10:09, Markos Chandras wrote:
> MIPS R6 removed the BEQL instruction so do not try to emulate it
> if the R2-to-R6 emulator is not present.

How does this affect code for the old ISAs, MIPS-II to MIPS-IV?  I.e., the SGIs
and the R10K CPUs that have to worry about the R10000_LLSC_WAR workaround and
use branch-likely insns?

--J


> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
> ---
>  arch/mips/kernel/branch.c | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
> index 5f2a168c37fd..539d059ba4fb 100644
> --- a/arch/mips/kernel/branch.c
> +++ b/arch/mips/kernel/branch.c
> @@ -572,6 +572,10 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
>  	 */
>  	case beq_op:
>  	case beql_op:
> +		if (NO_R6EMU && insn.i_format.opcode == beql_op) {
> +			ret = -SIGILL;
> +			break;
> +		}
>  		if (regs->regs[insn.i_format.rs] ==
>  		    regs->regs[insn.i_format.rt]) {
>  			epc = epc + 4 + (insn.i_format.simmediate << 2);
> 

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 01/67] MIPS: Add generic QEMU R6 PRid and cpu type identifiers
@ 2014-12-19  8:49       ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-19  8:49 UTC (permalink / raw)
  To: David Daney; +Cc: linux-mips, Leonid Yegoshin

On 12/18/2014 07:10 PM, David Daney wrote:
> On 12/18/2014 07:09 AM, Markos Chandras wrote:
>> From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
>>
>> Latest versions of QEMU added support for mips32r6-generic and
>> mips64r6-generic cpu types so add related definitions in preparation
>> of MIPS R6 support.
>>
>> Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
>> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
>> ---
>>   arch/mips/include/asm/cpu.h | 3 +++
>>   1 file changed, 3 insertions(+)
>>
>> diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
>> index dfdc77ed1839..23a5dbc0ee06 100644
>> --- a/arch/mips/include/asm/cpu.h
>> +++ b/arch/mips/include/asm/cpu.h
>> @@ -93,6 +93,7 @@
>>    * These are the PRID's for when 23:16 == PRID_COMP_MIPS
>>    */
>>
>> +#define PRID_IMP_QEMUR6        0x0000
> 
> Why not have a value for a real R6 CPU, and then have QEMU emulate that?

because qemu does not implement real r6 cores at the moment. It uses
mips{32,64}r6-generic in order to get a minimal r6 core and that cpu
uses IMP=0. so that's the only thing we can use at the moment.

-- 
markos

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 01/67] MIPS: Add generic QEMU R6 PRid and cpu type identifiers
@ 2014-12-19  8:49       ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-19  8:49 UTC (permalink / raw)
  To: David Daney; +Cc: linux-mips, Leonid Yegoshin

On 12/18/2014 07:10 PM, David Daney wrote:
> On 12/18/2014 07:09 AM, Markos Chandras wrote:
>> From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
>>
>> Latest versions of QEMU added support for mips32r6-generic and
>> mips64r6-generic cpu types so add related definitions in preparation
>> of MIPS R6 support.
>>
>> Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
>> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
>> ---
>>   arch/mips/include/asm/cpu.h | 3 +++
>>   1 file changed, 3 insertions(+)
>>
>> diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
>> index dfdc77ed1839..23a5dbc0ee06 100644
>> --- a/arch/mips/include/asm/cpu.h
>> +++ b/arch/mips/include/asm/cpu.h
>> @@ -93,6 +93,7 @@
>>    * These are the PRID's for when 23:16 == PRID_COMP_MIPS
>>    */
>>
>> +#define PRID_IMP_QEMUR6        0x0000
> 
> Why not have a value for a real R6 CPU, and then have QEMU emulate that?

because qemu does not implement real r6 cores at the moment. It uses
mips{32,64}r6-generic in order to get a minimal r6 core and that cpu
uses IMP=0. so that's the only thing we can use at the moment.

-- 
markos

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 24/67] MIPS: asm: spinlock: Replace sub instruction with addiu
@ 2014-12-19  8:51       ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-19  8:51 UTC (permalink / raw)
  To: David Daney; +Cc: linux-mips

On 12/18/2014 06:53 PM, David Daney wrote:
> On 12/18/2014 07:09 AM, Markos Chandras wrote:
>> sub $reg, imm is not a real MIPS instruction. The assembler replaces
>> that with 'addi $reg, -imm'.
> 
> That is a bug right there.  We cannot have faulting instructions like
> this in the kernel.
> 
>> However, addi has been removed from R6,
>> so we replace the 'sub' instruction with 'addiu' instead.
>>
>> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
>> ---
>>   arch/mips/include/asm/spinlock.h | 2 +-
>>   1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/arch/mips/include/asm/spinlock.h
>> b/arch/mips/include/asm/spinlock.h
>> index f63b3543c1a4..c82fc0eefbec 100644
>> --- a/arch/mips/include/asm/spinlock.h
>> +++ b/arch/mips/include/asm/spinlock.h
>> @@ -277,7 +277,7 @@ static inline void arch_read_unlock(arch_rwlock_t
>> *rw)
>>           do {
>>               __asm__ __volatile__(
>>               "1:    ll    %1, 0(%2)# arch_read_unlock    \n"
>> -            "    sub    %1, 1                \n"
>> +            "    addiu    %1, -1                \n"
> 
> Instead, how about fixing the real bug by s/sub/subu/.
> 
> Would that work for R6 too?  If so, just do that.

subu is supported by R6 but i am not sure what the assembler will do in
case of "subu $reg, #imm". It will probably replace that with addiu

-- 
markos

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 24/67] MIPS: asm: spinlock: Replace sub instruction with addiu
@ 2014-12-19  8:51       ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-19  8:51 UTC (permalink / raw)
  To: David Daney; +Cc: linux-mips

On 12/18/2014 06:53 PM, David Daney wrote:
> On 12/18/2014 07:09 AM, Markos Chandras wrote:
>> sub $reg, imm is not a real MIPS instruction. The assembler replaces
>> that with 'addi $reg, -imm'.
> 
> That is a bug right there.  We cannot have faulting instructions like
> this in the kernel.
> 
>> However, addi has been removed from R6,
>> so we replace the 'sub' instruction with 'addiu' instead.
>>
>> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
>> ---
>>   arch/mips/include/asm/spinlock.h | 2 +-
>>   1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/arch/mips/include/asm/spinlock.h
>> b/arch/mips/include/asm/spinlock.h
>> index f63b3543c1a4..c82fc0eefbec 100644
>> --- a/arch/mips/include/asm/spinlock.h
>> +++ b/arch/mips/include/asm/spinlock.h
>> @@ -277,7 +277,7 @@ static inline void arch_read_unlock(arch_rwlock_t
>> *rw)
>>           do {
>>               __asm__ __volatile__(
>>               "1:    ll    %1, 0(%2)# arch_read_unlock    \n"
>> -            "    sub    %1, 1                \n"
>> +            "    addiu    %1, -1                \n"
> 
> Instead, how about fixing the real bug by s/sub/subu/.
> 
> Would that work for R6 too?  If so, just do that.

subu is supported by R6 but i am not sure what the assembler will do in
case of "subu $reg, #imm". It will probably replace that with addiu

-- 
markos

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 56/67] MIPS: kernel: branch: Emulate the BOVC, BEQC and BEQZALC R6 instructions
@ 2014-12-19  8:52       ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-19  8:52 UTC (permalink / raw)
  To: David Daney; +Cc: linux-mips

On 12/18/2014 07:07 PM, David Daney wrote:
> On 12/18/2014 07:10 AM, Markos Chandras wrote:
>> MIPS R6 uses the <R6 ADDI opcode for the new BOVC, BEQC and
>> BEQZALC instructions.
>>
>> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
>> ---
>>   arch/mips/include/uapi/asm/inst.h | 2 +-
>>   arch/mips/kernel/branch.c         | 6 ++++++
>>   2 files changed, 7 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/mips/include/uapi/asm/inst.h
>> b/arch/mips/include/uapi/asm/inst.h
>> index 648addfe1e1c..b95363e0551f 100644
>> --- a/arch/mips/include/uapi/asm/inst.h
>> +++ b/arch/mips/include/uapi/asm/inst.h
>> @@ -21,7 +21,7 @@
>>   enum major_op {
>>       spec_op, bcond_op, j_op, jal_op,
>>       beq_op, bne_op, blez_op, bgtz_op,
>> -    addi_op, addiu_op, slti_op, sltiu_op,
>> +    addi_or_cbcond0_op, addiu_op, slti_op, sltiu_op,
> 
> NAK.
> 
> This is a kernel ABI document, you cannot remove symbols.
ok i will find another way to workaround this. thanks

-- 
markos

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 56/67] MIPS: kernel: branch: Emulate the BOVC, BEQC and BEQZALC R6 instructions
@ 2014-12-19  8:52       ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-19  8:52 UTC (permalink / raw)
  To: David Daney; +Cc: linux-mips

On 12/18/2014 07:07 PM, David Daney wrote:
> On 12/18/2014 07:10 AM, Markos Chandras wrote:
>> MIPS R6 uses the <R6 ADDI opcode for the new BOVC, BEQC and
>> BEQZALC instructions.
>>
>> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
>> ---
>>   arch/mips/include/uapi/asm/inst.h | 2 +-
>>   arch/mips/kernel/branch.c         | 6 ++++++
>>   2 files changed, 7 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/mips/include/uapi/asm/inst.h
>> b/arch/mips/include/uapi/asm/inst.h
>> index 648addfe1e1c..b95363e0551f 100644
>> --- a/arch/mips/include/uapi/asm/inst.h
>> +++ b/arch/mips/include/uapi/asm/inst.h
>> @@ -21,7 +21,7 @@
>>   enum major_op {
>>       spec_op, bcond_op, j_op, jal_op,
>>       beq_op, bne_op, blez_op, bgtz_op,
>> -    addi_op, addiu_op, slti_op, sltiu_op,
>> +    addi_or_cbcond0_op, addiu_op, slti_op, sltiu_op,
> 
> NAK.
> 
> This is a kernel ABI document, you cannot remove symbols.
ok i will find another way to workaround this. thanks

-- 
markos

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 47/67] MIPS: kernel: branch: Prevent BEQL emulation for MIPS R6
@ 2014-12-19  8:54       ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-19  8:54 UTC (permalink / raw)
  To: Joshua Kinard, linux-mips

On 12/18/2014 11:56 PM, Joshua Kinard wrote:
> On 12/18/2014 10:09, Markos Chandras wrote:
>> MIPS R6 removed the BEQL instruction so do not try to emulate it
>> if the R2-to-R6 emulator is not present.
> 
> How does this affect code for the old ISAs, MIPS-II to MIPS-IV?  I.e., the SGIs
> and the R10K CPUs that have to worry about the R10000_LLSC_WAR workaround and
> use branch-likely insns?
> 
> --J
> 

it does not affect them (or should not affect them). In case of *any*
non-R6 core, the NO_R6EMU macro is false, so all the conditionals here
are evaluated to false and the branch emulation will do the right thing.

-- 
markos

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 47/67] MIPS: kernel: branch: Prevent BEQL emulation for MIPS R6
@ 2014-12-19  8:54       ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-19  8:54 UTC (permalink / raw)
  To: Joshua Kinard, linux-mips

On 12/18/2014 11:56 PM, Joshua Kinard wrote:
> On 12/18/2014 10:09, Markos Chandras wrote:
>> MIPS R6 removed the BEQL instruction so do not try to emulate it
>> if the R2-to-R6 emulator is not present.
> 
> How does this affect code for the old ISAs, MIPS-II to MIPS-IV?  I.e., the SGIs
> and the R10K CPUs that have to worry about the R10000_LLSC_WAR workaround and
> use branch-likely insns?
> 
> --J
> 

it does not affect them (or should not affect them). In case of *any*
non-R6 core, the NO_R6EMU macro is false, so all the conditionals here
are evaluated to false and the branch emulation will do the right thing.

-- 
markos

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 12/67] MIPS: asm: asmmacro: Replace add instructions with "addui"
@ 2014-12-19  9:01       ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-19  9:01 UTC (permalink / raw)
  To: David Daney, Ralf Baechle; +Cc: linux-mips

On 12/18/2014 06:56 PM, David Daney wrote:
> On 12/18/2014 07:09 AM, Markos Chandras wrote:
>> The use of "add" instruction for immediate operations is wrong and
>> relies to gas being smart enough to notice that and replace it with
>> either addi or addui. However, MIPS R6 removed the addi instruction
>> so, fix this problem properly by using the correct instruction
>> directly.
>>
> 
> This is another case of the use of "add" being a real bug.  We should
> never have faulting instructions like this in the kernel.
> 
> Can you send all patches in this set that fix this bug as a separate
> patch?  Since they are obviously correct, and really should be used by
> all non-R6 processors, we can get them in sooner that the entire R6 thing.
> 
> Thanks,
> David Daney

sure i will move these patches away from R6 and post them separately.

-- 
markos

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 12/67] MIPS: asm: asmmacro: Replace add instructions with "addui"
@ 2014-12-19  9:01       ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-19  9:01 UTC (permalink / raw)
  To: David Daney, Ralf Baechle; +Cc: linux-mips

On 12/18/2014 06:56 PM, David Daney wrote:
> On 12/18/2014 07:09 AM, Markos Chandras wrote:
>> The use of "add" instruction for immediate operations is wrong and
>> relies to gas being smart enough to notice that and replace it with
>> either addi or addui. However, MIPS R6 removed the addi instruction
>> so, fix this problem properly by using the correct instruction
>> directly.
>>
> 
> This is another case of the use of "add" being a real bug.  We should
> never have faulting instructions like this in the kernel.
> 
> Can you send all patches in this set that fix this bug as a separate
> patch?  Since they are obviously correct, and really should be used by
> all non-R6 processors, we can get them in sooner that the entire R6 thing.
> 
> Thanks,
> David Daney

sure i will move these patches away from R6 and post them separately.

-- 
markos

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 19/67] MIPS: asm: atomic: Update asm and ISA constrains for MIPS R6 support
@ 2014-12-19 10:01       ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-19 10:01 UTC (permalink / raw)
  To: David Daney; +Cc: linux-mips, Matthew Fortune

On 12/18/2014 06:50 PM, David Daney wrote:
> On 12/18/2014 07:09 AM, Markos Chandras wrote:
>> MIPS R6 changed the opcodes for LL/SC instructions and reduced the
>> offset field to 9-bits. This has some undesired effects with the "m"
>> constrain since it implies a 16-bit immediate. As a result of which,
>> add a register ("r") constrain as well to make sure the entire address
>> is loaded to a register before the LL/SC operations. Also use macro
>> to set the appropriate ISA for the asm blocks
>>
> 
> Has support for MIPS R6 been added to GCC?
> 
> If so, that should include a proper constraint to be used with the new
> offset restrictions.  We should probably use that, instead of forcing to
> a "r" constraint.
> 
> 
>> Cc: Matthew Fortune <Matthew.Fortune@imgtec.com>
>> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
>> ---
>>   arch/mips/include/asm/atomic.h | 50
>> +++++++++++++++++++++---------------------
>>   1 file changed, 25 insertions(+), 25 deletions(-)
>>
>> diff --git a/arch/mips/include/asm/atomic.h
>> b/arch/mips/include/asm/atomic.h
>> index 6dd6bfc607e9..8669e0ec97e3 100644
>> --- a/arch/mips/include/asm/atomic.h
>> +++ b/arch/mips/include/asm/atomic.h
>> @@ -60,13 +60,13 @@ static __inline__ void atomic_##op(int i, atomic_t
>> * v)                \
>>                                           \
>>           do {                                \
>>               __asm__ __volatile__(                    \
>> -            "    .set    arch=r4000            \n"    \
>> -            "    ll    %0, %1        # atomic_" #op "\n"    \
>> +            "    .set    "MIPS_ISA_ARCH_LEVEL"        \n"    \
>> +            "    ll    %0, 0(%3)    # atomic_" #op "\n"    \
>>               "    " #asm_op " %0, %2            \n"    \
>> -            "    sc    %0, %1                \n"    \
>> +            "    sc    %0, 0(%3)            \n"    \
>>               "    .set    mips0                \n"    \
>>               : "=&r" (temp), "+m" (v->counter)            \
>> -            : "Ir" (i));                        \
>> +            : "Ir" (i), "r" (&v->counter));                \
> 
> You lost the "m" constraint, but are still modifying memory.  There is
> no "memory" clobber here, so we are no longer correctly describing what
> is happening.
> 
> 

Sorry I don't understand what you mean by  "you lost the "m"
constraint". +m (v->counter) is still there to denote that v->counter
memory is being modified no?

-- 
markos

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 19/67] MIPS: asm: atomic: Update asm and ISA constrains for MIPS R6 support
@ 2014-12-19 10:01       ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-19 10:01 UTC (permalink / raw)
  To: David Daney; +Cc: linux-mips, Matthew Fortune

On 12/18/2014 06:50 PM, David Daney wrote:
> On 12/18/2014 07:09 AM, Markos Chandras wrote:
>> MIPS R6 changed the opcodes for LL/SC instructions and reduced the
>> offset field to 9-bits. This has some undesired effects with the "m"
>> constrain since it implies a 16-bit immediate. As a result of which,
>> add a register ("r") constrain as well to make sure the entire address
>> is loaded to a register before the LL/SC operations. Also use macro
>> to set the appropriate ISA for the asm blocks
>>
> 
> Has support for MIPS R6 been added to GCC?
> 
> If so, that should include a proper constraint to be used with the new
> offset restrictions.  We should probably use that, instead of forcing to
> a "r" constraint.
> 
> 
>> Cc: Matthew Fortune <Matthew.Fortune@imgtec.com>
>> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
>> ---
>>   arch/mips/include/asm/atomic.h | 50
>> +++++++++++++++++++++---------------------
>>   1 file changed, 25 insertions(+), 25 deletions(-)
>>
>> diff --git a/arch/mips/include/asm/atomic.h
>> b/arch/mips/include/asm/atomic.h
>> index 6dd6bfc607e9..8669e0ec97e3 100644
>> --- a/arch/mips/include/asm/atomic.h
>> +++ b/arch/mips/include/asm/atomic.h
>> @@ -60,13 +60,13 @@ static __inline__ void atomic_##op(int i, atomic_t
>> * v)                \
>>                                           \
>>           do {                                \
>>               __asm__ __volatile__(                    \
>> -            "    .set    arch=r4000            \n"    \
>> -            "    ll    %0, %1        # atomic_" #op "\n"    \
>> +            "    .set    "MIPS_ISA_ARCH_LEVEL"        \n"    \
>> +            "    ll    %0, 0(%3)    # atomic_" #op "\n"    \
>>               "    " #asm_op " %0, %2            \n"    \
>> -            "    sc    %0, %1                \n"    \
>> +            "    sc    %0, 0(%3)            \n"    \
>>               "    .set    mips0                \n"    \
>>               : "=&r" (temp), "+m" (v->counter)            \
>> -            : "Ir" (i));                        \
>> +            : "Ir" (i), "r" (&v->counter));                \
> 
> You lost the "m" constraint, but are still modifying memory.  There is
> no "memory" clobber here, so we are no longer correctly describing what
> is happening.
> 
> 

Sorry I don't understand what you mean by  "you lost the "m"
constraint". +m (v->counter) is still there to denote that v->counter
memory is being modified no?

-- 
markos

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 19/67] MIPS: asm: atomic: Update asm and ISA constrains for MIPS R6 support
  2014-12-18 22:58           ` Matthew Fortune
  2014-12-18 23:43               ` Måns Rullgård
@ 2014-12-19 10:20             ` Markos Chandras
  2014-12-19 12:39               ` Markos Chandras
  2015-01-11 23:51               ` Maciej W. Rozycki
  2014-12-19 12:29             ` Ralf Baechle
  2 siblings, 2 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-19 10:20 UTC (permalink / raw)
  To: Matthew Fortune, David Daney; +Cc: Ralf Baechle, linux-mips

On 12/18/2014 10:58 PM, Matthew Fortune wrote:
> David Daney <ddaney.cavm@gmail.com> writes:
>> On 12/18/2014 01:04 PM, Matthew Fortune wrote:
>>>> On Thu, Dec 18, 2014 at 10:50:27AM -0800, David Daney wrote:
>>>>
>>>>> On 12/18/2014 07:09 AM, Markos Chandras wrote:
>>>>>> MIPS R6 changed the opcodes for LL/SC instructions and reduced the
>>>>>> offset field to 9-bits. This has some undesired effects with the
>> "m"
>>>>>> constrain since it implies a 16-bit immediate. As a result of
>>>>>> which, add a register ("r") constrain as well to make sure the
>>>>>> entire address is loaded to a register before the LL/SC operations.
>>>>>> Also use macro to set the appropriate ISA for the asm blocks
>>>>>>
>>>>>
>>>>> Has support for MIPS R6 been added to GCC?
>>>>>
>>>>> If so, that should include a proper constraint to be used with the
>>>>> new offset restrictions.  We should probably use that, instead of
>>>>> forcing to a "r" constraint.
>>>>
>>>> In a non-public earlier discussion I've requested the same but
>>>> somehow that was ignored.
>>>
>>> I must have missed that comment or not been on the thread.
>>>
>>>> We need suitable constraints or the alternatives will be very, very
>>>> ugly.
>>>
>>> We can certainly discuss and investigate such things but there is a
>>> general problem of a growing list of different size displacement
>>> fields in load/store instructions. Obviously you could just opt to
>>> keep things the way they are for uMIPS today and leave the assembler
>>> to expand the instruction but my opinion is that magic expanding
>>> assembler macros are infuriating. We have however had to put support
>>> in binutils for many of them, simply to keep enough software building
>> to ease the transition.
>>>
>>> So, all this patch does is highlight that magic assembler macros have
>>> been hiding this issue since micromips was added.
>>>
>>> >From your experiences will people invest the effort to look at the
>>> size of a displacement field for all the memory operations in an
>>> inline asm block and then choose an appropriate memory constraint?
>>>
>>> I'm obviously wary of putting things into GCC that are either only
>>> used in a handful of places (or not at all). The alternative to
>>> constraints is of course to try and reduce the need for inline asm and
>>> offer builtins for specific instructions or more complex operations.
>>>
>>
>> Well, GCC directly emits LL/SC as part of its built-in support for
>> atomic operations, so the knowledge of the constraints for the
>> instructions must be present there.  Since the constraints must be
>> present in GCC, using them in the kernel shouldn't be a problem.
> 
> Yes you are right I thought this particular case only had constraints
> for the immediate and not the whole memory operand, I'm suffering from
> too many tasks and too little time. Several of the memory constraints are
> marked as internal and I'm not sure if that means they are unsafe to use
> from inline asm or just not deemed important.
> 
> The memory constraint that LL and SC need is 'ZC'. I don't believe this
> is documented so you will have to trust that its meaning will not change
> but I can give some assurance of that since I will review all MIPS GCC
> changes.
> 
> Obviously to use anything other than the 'm' constraint you are going
> to need to know when any given constraint was added to GCC.
> 'ZC' was only added to GCC in March 2013 r196828 which I believe it is a
> GCC 4.9 feature so you will have to use it conditionally if you use it at
> all.
> 

is this something desirable? check the gcc version, initialize a macro
and then use that macro as a constrain? i haven't thought this through,
but it could be a bit messy.

-- 
markos

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 29/67] MIPS: kernel: proc: Add MIPS R6 support to /proc/cpuinfo
  2014-12-18 15:09   ` Markos Chandras
  (?)
@ 2014-12-19 11:32   ` Sergei Shtylyov
  -1 siblings, 0 replies; 187+ messages in thread
From: Sergei Shtylyov @ 2014-12-19 11:32 UTC (permalink / raw)
  To: Markos Chandras, linux-mips

Hello.

On 12/18/2014 6:09 PM, Markos Chandras wrote:

> Print 'mips64r6' and/or 'mips32r6' if the kernel is running on
> a MIPS R6 core.

> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
> ---
>   arch/mips/kernel/proc.c | 9 ++++++++-
>   1 file changed, 8 insertions(+), 1 deletion(-)

> diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
> index 097fc8d14e42..b2194770878d 100644
> --- a/arch/mips/kernel/proc.c
> +++ b/arch/mips/kernel/proc.c
> @@ -82,7 +82,10 @@ static int show_cpuinfo(struct seq_file *m, void *v)
>   		seq_printf(m, "]\n");
>   	}
>
> -	seq_printf(m, "isa\t\t\t: mips1");
> +	if (!cpu_has_mips_r6)
> +		seq_printf(m, "isa\t\t\t: mips1");
> +	else
> +		seq_printf(m, "isa\t\t\t:");

    The following seems shorter.

	seq_printf(m, "isa\t\t\t:");
	if (!cpu_has_mips_r6)
		seq_printf(m, " mips1");

[...]

WBR, Sergei

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 53/67] MIPS: kernel: branch: Add new MIPS R6 B{L,G}ΕZ{AL,}C emulation
  2014-12-18 15:10   ` Markos Chandras
  (?)
@ 2014-12-19 11:59   ` Sergei Shtylyov
  -1 siblings, 0 replies; 187+ messages in thread
From: Sergei Shtylyov @ 2014-12-19 11:59 UTC (permalink / raw)
  To: Markos Chandras, linux-mips

Hello.

On 12/18/2014 6:10 PM, Markos Chandras wrote:

> MIPS R6 added the following four instructions which share the
> BLEZ and BLEZL opcodes:

> BLEZALC: Compact branch-and-link if GPR rt is <= to zero
> BGEZALC: Compact branch-and-link if GPR rt is >= to zero
> BLEZC: Compact branch if GPR rt is < to zero

    Not <=?

> BGEZC: Compact branch if GPR rt is > to zero

    Not >=?

> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
> ---
>   arch/mips/kernel/branch.c | 22 ++++++++++++++++++++++
>   1 file changed, 22 insertions(+)

> diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
> index e6d78ab52aa7..7bc2df026b51 100644
> --- a/arch/mips/kernel/branch.c
> +++ b/arch/mips/kernel/branch.c
> @@ -402,6 +402,16 @@ int __MIPS16e_compute_return_epc(struct pt_regs *regs)
>    * @returns:	-EFAULT on error and forces SIGBUS, and on success
>    *		returns 0 or BRANCH_LIKELY_TAKEN as appropriate after
>    *		evaluating the branch.
> + *
> + * MIPS R6 Compact branches and forbidden slots:
> + *	Compact branches do not throw exceptions because they do
> + *	not have delay slots. The forbidden slot instruction ($PC+4)
> + *	is only executed if the branch was not taken. Otherwise the
> + *	forbidden slot is skipped entirely. This means that they

    s/they/the/?

[...]
> @@ -609,6 +619,18 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
>   			ret = -SIGILL;
>   			break;
>   		}
> +		/* blezalc, bgezalc, blezc, bgezc */
> +		if (cpu_has_mips_r6) {
> +			if (insn.i_format.rt) {

     Perhaps those *if* statements can be collapsed to save on indentation?

> +				if (insn.i_format.opcode == blez_op)
> +					if ((insn.i_format.rs ==
> +					     insn.i_format.rt) ||
> +					    !insn.i_format.rs)
> +						regs->regs[31] = epc + 4;

    And these also?

> +				regs->cp0_epc += 8;
> +				break;
> +			}
> +		}
[...]

WBR, Sergei

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 54/67] MIPS: kernel: branch: Add new MIPS R6 B{L,G}TZ{AL,}C emulation
  2014-12-18 15:10   ` Markos Chandras
  (?)
@ 2014-12-19 12:02   ` Sergei Shtylyov
  -1 siblings, 0 replies; 187+ messages in thread
From: Sergei Shtylyov @ 2014-12-19 12:02 UTC (permalink / raw)
  To: Markos Chandras, linux-mips

On 12/18/2014 6:10 PM, Markos Chandras wrote:

> MIPS R6 added the following four instructions which share the
> BGTZ and BGTZL opcode:

> BLTZALC: Compact branch-and-link if GPR rt is < to zero
> BGEZALC: Compact branch-and-link if GPR rt is > to zero

    Not BGTZALC?

> BGTZL: Compact branch if GPR rt is < to zero

    Not BLTZC?

> BGEZL: Compact branch if GPR rt is > to zero

    Not BGTZC?

> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
> ---
>   arch/mips/kernel/branch.c | 13 +++++++++++++
>   1 file changed, 13 insertions(+)

> diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
> index 7bc2df026b51..ca102557fa3c 100644
> --- a/arch/mips/kernel/branch.c
> +++ b/arch/mips/kernel/branch.c
> @@ -648,6 +648,19 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
>   			ret = -SIGILL;
>   			break;
>   		}
> +		/* bgtzalc, bltzalc, bgtzc, bltzc */
> +		if (cpu_has_mips_r6) {
> +			if (insn.i_format.rt) {
> +				if (insn.i_format.opcode == blez_op)
> +					if (insn.i_format.rs ==
> +					    insn.i_format.rt ||
> +					    !insn.i_format.rs)
> +						regs->regs[31] = epc + 4;
> +				regs->cp0_epc += 8;
> +				break;

   Why not collapse the *if* statements here as well?

> +			}
> +		}
> +
[...]

WBR, Sergei

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 58/67] MIPS: kernel: branch: Emulate the BALC R6 instruction
  2014-12-18 15:10   ` Markos Chandras
  (?)
@ 2014-12-19 12:06   ` Sergei Shtylyov
  -1 siblings, 0 replies; 187+ messages in thread
From: Sergei Shtylyov @ 2014-12-19 12:06 UTC (permalink / raw)
  To: Markos Chandras, linux-mips

On 12/18/2014 6:10 PM, Markos Chandras wrote:

> MIPS R6 uses the <R6 swc2 opcode for the new BALC instructions.

> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
> ---
>   arch/mips/kernel/branch.c | 6 ++++++
>   1 file changed, 6 insertions(+)

> diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
> index 4cc9070682e1..426f876403d0 100644
> --- a/arch/mips/kernel/branch.c
> +++ b/arch/mips/kernel/branch.c
> @@ -796,6 +796,12 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
>   			regs->regs[31] = epc + 4;
>   		regs->cp0_epc += 8;
>   		break;
> +	case swc2_or_balc_op:
> +		/* Compact branch: BALC */
> +		regs->regs[31] = epc + 4;
> +		epc = epc + 4 + (insn.i_format.simmediate << 2);

		epc += 4 + (insn.i_format.simmediate << 2);

> +		regs->cp0_epc = epc;
> +		break;

WBR, Sergei

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 59/67] MIPS: kernel: branch: Emulate the BEQZC and JIC instructions
  2014-12-18 15:10   ` Markos Chandras
  (?)
@ 2014-12-19 12:08   ` Sergei Shtylyov
  -1 siblings, 0 replies; 187+ messages in thread
From: Sergei Shtylyov @ 2014-12-19 12:08 UTC (permalink / raw)
  To: Markos Chandras, linux-mips

On 12/18/2014 6:10 PM, Markos Chandras wrote:

> MIPS R6 uses the <R6 ldc2 opcode for the new BEQZC and JIC instructions

> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
> ---
>   arch/mips/kernel/branch.c | 9 +++++++++
>   1 file changed, 9 insertions(+)

> diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
> index 426f876403d0..4473c23cacf2 100644
> --- a/arch/mips/kernel/branch.c
> +++ b/arch/mips/kernel/branch.c
> @@ -802,6 +802,15 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
>   		epc = epc + 4 + (insn.i_format.simmediate << 2);
>   		regs->cp0_epc = epc;
>   		break;
> +	case ldc2_or_bzcjic_op:
> +		/* Compact branch: BEQZC || JIC */
> +		if (insn.i_format.rs) /* BEQZC */
> +			epc = epc + 8;

			epc += 8;

[...]

WBR, Sergei

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 60/67] MIPS: math-emu: cp1emu: Move the fpucondbit struct to a header
  2014-12-18 15:10   ` Markos Chandras
  (?)
@ 2014-12-19 12:10   ` Sergei Shtylyov
  -1 siblings, 0 replies; 187+ messages in thread
From: Sergei Shtylyov @ 2014-12-19 12:10 UTC (permalink / raw)
  To: Markos Chandras, linux-mips

On 12/18/2014 6:10 PM, Markos Chandras wrote:

> The fpucondbit struct will be used later on by the MIPS R2 instruction

    It's not *struct*.

> emulator, so in order to access it, we need to move it to a header.

> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
> ---
>   arch/mips/include/asm/fpu_emulator.h | 12 ++++++++++++
>   arch/mips/math-emu/cp1emu.c          | 12 ------------
>   2 files changed, 12 insertions(+), 12 deletions(-)

> diff --git a/arch/mips/include/asm/fpu_emulator.h b/arch/mips/include/asm/fpu_emulator.h
> index 3ee347713307..d7670bd80855 100644
> --- a/arch/mips/include/asm/fpu_emulator.h
> +++ b/arch/mips/include/asm/fpu_emulator.h
> @@ -30,6 +30,18 @@
>   #include <asm/local.h>
>   #include <asm/processor.h>
>
> +/* convert condition code register number to csr bit */
> +static const unsigned int fpucondbit[8] = {

    Why not *extern* declaration instead? We don't define data in the header 
files.

> +	FPU_CSR_COND0,
> +	FPU_CSR_COND1,
> +	FPU_CSR_COND2,
> +	FPU_CSR_COND3,
> +	FPU_CSR_COND4,
> +	FPU_CSR_COND5,
> +	FPU_CSR_COND6,
> +	FPU_CSR_COND7
> +};
> +
[...]

WBR, Sergei

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 19/67] MIPS: asm: atomic: Update asm and ISA constrains for MIPS R6 support
  2014-12-18 22:58           ` Matthew Fortune
  2014-12-18 23:43               ` Måns Rullgård
  2014-12-19 10:20             ` Markos Chandras
@ 2014-12-19 12:29             ` Ralf Baechle
  2 siblings, 0 replies; 187+ messages in thread
From: Ralf Baechle @ 2014-12-19 12:29 UTC (permalink / raw)
  To: Matthew Fortune; +Cc: David Daney, Markos Chandras, linux-mips

On Thu, Dec 18, 2014 at 10:58:02PM +0000, Matthew Fortune wrote:

> Yes you are right I thought this particular case only had constraints
> for the immediate and not the whole memory operand, I'm suffering from
> too many tasks and too little time. Several of the memory constraints are
> marked as internal and I'm not sure if that means they are unsafe to use
> from inline asm or just not deemed important.
> 
> The memory constraint that LL and SC need is 'ZC'. I don't believe this
> is documented so you will have to trust that its meaning will not change
> but I can give some assurance of that since I will review all MIPS GCC
> changes.
> 
> Obviously to use anything other than the 'm' constraint you are going
> to need to know when any given constraint was added to GCC.
> 'ZC' was only added to GCC in March 2013 r196828 which I believe it is a
> GCC 4.9 feature so you will have to use it conditionally if you use it at
> all.
> 
> BTW thanks for the thread, it seems I missed updating 'ZC' for MIPSR6.
> Bug fixed!

How about the "o" constraint?  The kernel uses it only in a few places
and not currently with LL/SC though that might allow for some extra
optimization(?).  Is the a suitable "o"-like constraint for use with
LL/SC on R6?

  Ralf

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 19/67] MIPS: asm: atomic: Update asm and ISA constrains for MIPS R6 support
  2014-12-19 10:20             ` Markos Chandras
@ 2014-12-19 12:39               ` Markos Chandras
  2014-12-19 13:53                 ` Matthew Fortune
  2015-01-11 23:51               ` Maciej W. Rozycki
  1 sibling, 1 reply; 187+ messages in thread
From: Markos Chandras @ 2014-12-19 12:39 UTC (permalink / raw)
  To: Matthew Fortune, David Daney; +Cc: Ralf Baechle, linux-mips

On 12/19/2014 10:20 AM, Markos Chandras wrote:
> On 12/18/2014 10:58 PM, Matthew Fortune wrote:
>> David Daney <ddaney.cavm@gmail.com> writes:
>>> On 12/18/2014 01:04 PM, Matthew Fortune wrote:
>>>>> On Thu, Dec 18, 2014 at 10:50:27AM -0800, David Daney wrote:
>>>>>
>>>>>> On 12/18/2014 07:09 AM, Markos Chandras wrote:
>>>>>>> MIPS R6 changed the opcodes for LL/SC instructions and reduced the
>>>>>>> offset field to 9-bits. This has some undesired effects with the
>>> "m"
>>>>>>> constrain since it implies a 16-bit immediate. As a result of
>>>>>>> which, add a register ("r") constrain as well to make sure the
>>>>>>> entire address is loaded to a register before the LL/SC operations.
>>>>>>> Also use macro to set the appropriate ISA for the asm blocks
>>>>>>>
>>>>>>
>>>>>> Has support for MIPS R6 been added to GCC?
>>>>>>
>>>>>> If so, that should include a proper constraint to be used with the
>>>>>> new offset restrictions.  We should probably use that, instead of
>>>>>> forcing to a "r" constraint.
>>>>>
>>>>> In a non-public earlier discussion I've requested the same but
>>>>> somehow that was ignored.
>>>>
>>>> I must have missed that comment or not been on the thread.
>>>>
>>>>> We need suitable constraints or the alternatives will be very, very
>>>>> ugly.
>>>>
>>>> We can certainly discuss and investigate such things but there is a
>>>> general problem of a growing list of different size displacement
>>>> fields in load/store instructions. Obviously you could just opt to
>>>> keep things the way they are for uMIPS today and leave the assembler
>>>> to expand the instruction but my opinion is that magic expanding
>>>> assembler macros are infuriating. We have however had to put support
>>>> in binutils for many of them, simply to keep enough software building
>>> to ease the transition.
>>>>
>>>> So, all this patch does is highlight that magic assembler macros have
>>>> been hiding this issue since micromips was added.
>>>>
>>>> >From your experiences will people invest the effort to look at the
>>>> size of a displacement field for all the memory operations in an
>>>> inline asm block and then choose an appropriate memory constraint?
>>>>
>>>> I'm obviously wary of putting things into GCC that are either only
>>>> used in a handful of places (or not at all). The alternative to
>>>> constraints is of course to try and reduce the need for inline asm and
>>>> offer builtins for specific instructions or more complex operations.
>>>>
>>>
>>> Well, GCC directly emits LL/SC as part of its built-in support for
>>> atomic operations, so the knowledge of the constraints for the
>>> instructions must be present there.  Since the constraints must be
>>> present in GCC, using them in the kernel shouldn't be a problem.
>>
>> Yes you are right I thought this particular case only had constraints
>> for the immediate and not the whole memory operand, I'm suffering from
>> too many tasks and too little time. Several of the memory constraints are
>> marked as internal and I'm not sure if that means they are unsafe to use
>> from inline asm or just not deemed important.
>>
>> The memory constraint that LL and SC need is 'ZC'. I don't believe this
>> is documented so you will have to trust that its meaning will not change
>> but I can give some assurance of that since I will review all MIPS GCC
>> changes.
>>
>> Obviously to use anything other than the 'm' constraint you are going
>> to need to know when any given constraint was added to GCC.
>> 'ZC' was only added to GCC in March 2013 r196828 which I believe it is a
>> GCC 4.9 feature so you will have to use it conditionally if you use it at
>> all.
>>
> 
> is this something desirable? check the gcc version, initialize a macro
> and then use that macro as a constrain? i haven't thought this through,
> but it could be a bit messy.
> 
btw i tried a quick test to replace +m with +ZC but i have build
failures since the immediates do not fit.

{standard input}: Assembler messages:
{standard input}:436: Error: operand 2 must be constant `ll
$3,%lo(irq_err_count)($2)'
{standard input}:438: Error: operand 2 must be constant `sc
$3,%lo(irq_err_count)($2)'

Could you provide an example of how you would use the ZC constrain in
these asm blocks? i could be doing something wrong on my end.

-- 
markos

^ permalink raw reply	[flat|nested] 187+ messages in thread

* RE: [PATCH RFC 19/67] MIPS: asm: atomic: Update asm and ISA constrains for MIPS R6 support
  2014-12-19 12:39               ` Markos Chandras
@ 2014-12-19 13:53                 ` Matthew Fortune
  2014-12-19 13:55                   ` Markos Chandras
  0 siblings, 1 reply; 187+ messages in thread
From: Matthew Fortune @ 2014-12-19 13:53 UTC (permalink / raw)
  To: Markos Chandras, David Daney; +Cc: Ralf Baechle, linux-mips

Markos Chandras <Markos.Chandras@imgtec.com> writes:
> On 12/19/2014 10:20 AM, Markos Chandras wrote:
> > On 12/18/2014 10:58 PM, Matthew Fortune wrote:
> >> David Daney <ddaney.cavm@gmail.com> writes:
> >>> On 12/18/2014 01:04 PM, Matthew Fortune wrote:
> >>>>> On Thu, Dec 18, 2014 at 10:50:27AM -0800, David Daney wrote:
> >>>>>
> >>>>>> On 12/18/2014 07:09 AM, Markos Chandras wrote:
> >>>>>>> MIPS R6 changed the opcodes for LL/SC instructions and reduced the
> >>>>>>> offset field to 9-bits. This has some undesired effects with the
> >>> "m"
> >>>>>>> constrain since it implies a 16-bit immediate. As a result of
> >>>>>>> which, add a register ("r") constrain as well to make sure the
> >>>>>>> entire address is loaded to a register before the LL/SC
> operations.
> >>>>>>> Also use macro to set the appropriate ISA for the asm blocks
> >>>>>>>
> >>>>>>
> >>>>>> Has support for MIPS R6 been added to GCC?
> >>>>>>
> >>>>>> If so, that should include a proper constraint to be used with the
> >>>>>> new offset restrictions.  We should probably use that, instead of
> >>>>>> forcing to a "r" constraint.
> >>>>>
> >>>>> In a non-public earlier discussion I've requested the same but
> >>>>> somehow that was ignored.
> >>>>
> >>>> I must have missed that comment or not been on the thread.
> >>>>
> >>>>> We need suitable constraints or the alternatives will be very, very
> >>>>> ugly.
> >>>>
> >>>> We can certainly discuss and investigate such things but there is a
> >>>> general problem of a growing list of different size displacement
> >>>> fields in load/store instructions. Obviously you could just opt to
> >>>> keep things the way they are for uMIPS today and leave the assembler
> >>>> to expand the instruction but my opinion is that magic expanding
> >>>> assembler macros are infuriating. We have however had to put support
> >>>> in binutils for many of them, simply to keep enough software building
> >>> to ease the transition.
> >>>>
> >>>> So, all this patch does is highlight that magic assembler macros have
> >>>> been hiding this issue since micromips was added.
> >>>>
> >>>> >From your experiences will people invest the effort to look at the
> >>>> size of a displacement field for all the memory operations in an
> >>>> inline asm block and then choose an appropriate memory constraint?
> >>>>
> >>>> I'm obviously wary of putting things into GCC that are either only
> >>>> used in a handful of places (or not at all). The alternative to
> >>>> constraints is of course to try and reduce the need for inline asm
> and
> >>>> offer builtins for specific instructions or more complex operations.
> >>>>
> >>>
> >>> Well, GCC directly emits LL/SC as part of its built-in support for
> >>> atomic operations, so the knowledge of the constraints for the
> >>> instructions must be present there.  Since the constraints must be
> >>> present in GCC, using them in the kernel shouldn't be a problem.
> >>
> >> Yes you are right I thought this particular case only had constraints
> >> for the immediate and not the whole memory operand, I'm suffering from
> >> too many tasks and too little time. Several of the memory constraints
> are
> >> marked as internal and I'm not sure if that means they are unsafe to
> use
> >> from inline asm or just not deemed important.
> >>
> >> The memory constraint that LL and SC need is 'ZC'. I don't believe this
> >> is documented so you will have to trust that its meaning will not
> change
> >> but I can give some assurance of that since I will review all MIPS GCC
> >> changes.
> >>
> >> Obviously to use anything other than the 'm' constraint you are going
> >> to need to know when any given constraint was added to GCC.
> >> 'ZC' was only added to GCC in March 2013 r196828 which I believe it is
> a
> >> GCC 4.9 feature so you will have to use it conditionally if you use it
> at
> >> all.
> >>
> >
> > is this something desirable? check the gcc version, initialize a macro
> > and then use that macro as a constrain? i haven't thought this through,
> > but it could be a bit messy.
> >
> btw i tried a quick test to replace +m with +ZC but i have build
> failures since the immediates do not fit.
> 
> {standard input}: Assembler messages:
> {standard input}:436: Error: operand 2 must be constant `ll
> $3,%lo(irq_err_count)($2)'
> {standard input}:438: Error: operand 2 must be constant `sc
> $3,%lo(irq_err_count)($2)'
> 
> Could you provide an example of how you would use the ZC constrain in
> these asm blocks? i could be doing something wrong on my end.

In a follow up post I mentioned that you have essentially found something
missing from the R6 GCC implementation. We have just fixed this in our
internal builds so we will have to provide you with an updated compiler to
use ZC. This will be fixed in Imaginations 2015-01 Codescape SDK and will
be posted to GCC following R6 commit (that is a matter of hours away as it
happens).

The reason this was missed from the R6 implementation in GCC is that the
atomic sync patterns in the compiler actually only allow base registers with
no offset (reason unknown) so we will be fixing that too.

Thanks,
Matthew

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 19/67] MIPS: asm: atomic: Update asm and ISA constrains for MIPS R6 support
  2014-12-19 13:53                 ` Matthew Fortune
@ 2014-12-19 13:55                   ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2014-12-19 13:55 UTC (permalink / raw)
  To: Matthew Fortune, David Daney; +Cc: Ralf Baechle, linux-mips

On 12/19/2014 01:53 PM, Matthew Fortune wrote:
> Markos Chandras <Markos.Chandras@imgtec.com> writes:
>> On 12/19/2014 10:20 AM, Markos Chandras wrote:
>>> On 12/18/2014 10:58 PM, Matthew Fortune wrote:
>>>> David Daney <ddaney.cavm@gmail.com> writes:
>>>>> On 12/18/2014 01:04 PM, Matthew Fortune wrote:
>>>>>>> On Thu, Dec 18, 2014 at 10:50:27AM -0800, David Daney wrote:
>>>>>>>
>>>>>>>> On 12/18/2014 07:09 AM, Markos Chandras wrote:
>>>>>>>>> MIPS R6 changed the opcodes for LL/SC instructions and reduced the
>>>>>>>>> offset field to 9-bits. This has some undesired effects with the
>>>>> "m"
>>>>>>>>> constrain since it implies a 16-bit immediate. As a result of
>>>>>>>>> which, add a register ("r") constrain as well to make sure the
>>>>>>>>> entire address is loaded to a register before the LL/SC
>> operations.
>>>>>>>>> Also use macro to set the appropriate ISA for the asm blocks
>>>>>>>>>
>>>>>>>>
>>>>>>>> Has support for MIPS R6 been added to GCC?
>>>>>>>>
>>>>>>>> If so, that should include a proper constraint to be used with the
>>>>>>>> new offset restrictions.  We should probably use that, instead of
>>>>>>>> forcing to a "r" constraint.
>>>>>>>
>>>>>>> In a non-public earlier discussion I've requested the same but
>>>>>>> somehow that was ignored.
>>>>>>
>>>>>> I must have missed that comment or not been on the thread.
>>>>>>
>>>>>>> We need suitable constraints or the alternatives will be very, very
>>>>>>> ugly.
>>>>>>
>>>>>> We can certainly discuss and investigate such things but there is a
>>>>>> general problem of a growing list of different size displacement
>>>>>> fields in load/store instructions. Obviously you could just opt to
>>>>>> keep things the way they are for uMIPS today and leave the assembler
>>>>>> to expand the instruction but my opinion is that magic expanding
>>>>>> assembler macros are infuriating. We have however had to put support
>>>>>> in binutils for many of them, simply to keep enough software building
>>>>> to ease the transition.
>>>>>>
>>>>>> So, all this patch does is highlight that magic assembler macros have
>>>>>> been hiding this issue since micromips was added.
>>>>>>
>>>>>> >From your experiences will people invest the effort to look at the
>>>>>> size of a displacement field for all the memory operations in an
>>>>>> inline asm block and then choose an appropriate memory constraint?
>>>>>>
>>>>>> I'm obviously wary of putting things into GCC that are either only
>>>>>> used in a handful of places (or not at all). The alternative to
>>>>>> constraints is of course to try and reduce the need for inline asm
>> and
>>>>>> offer builtins for specific instructions or more complex operations.
>>>>>>
>>>>>
>>>>> Well, GCC directly emits LL/SC as part of its built-in support for
>>>>> atomic operations, so the knowledge of the constraints for the
>>>>> instructions must be present there.  Since the constraints must be
>>>>> present in GCC, using them in the kernel shouldn't be a problem.
>>>>
>>>> Yes you are right I thought this particular case only had constraints
>>>> for the immediate and not the whole memory operand, I'm suffering from
>>>> too many tasks and too little time. Several of the memory constraints
>> are
>>>> marked as internal and I'm not sure if that means they are unsafe to
>> use
>>>> from inline asm or just not deemed important.
>>>>
>>>> The memory constraint that LL and SC need is 'ZC'. I don't believe this
>>>> is documented so you will have to trust that its meaning will not
>> change
>>>> but I can give some assurance of that since I will review all MIPS GCC
>>>> changes.
>>>>
>>>> Obviously to use anything other than the 'm' constraint you are going
>>>> to need to know when any given constraint was added to GCC.
>>>> 'ZC' was only added to GCC in March 2013 r196828 which I believe it is
>> a
>>>> GCC 4.9 feature so you will have to use it conditionally if you use it
>> at
>>>> all.
>>>>
>>>
>>> is this something desirable? check the gcc version, initialize a macro
>>> and then use that macro as a constrain? i haven't thought this through,
>>> but it could be a bit messy.
>>>
>> btw i tried a quick test to replace +m with +ZC but i have build
>> failures since the immediates do not fit.
>>
>> {standard input}: Assembler messages:
>> {standard input}:436: Error: operand 2 must be constant `ll
>> $3,%lo(irq_err_count)($2)'
>> {standard input}:438: Error: operand 2 must be constant `sc
>> $3,%lo(irq_err_count)($2)'
>>
>> Could you provide an example of how you would use the ZC constrain in
>> these asm blocks? i could be doing something wrong on my end.
> 
> In a follow up post I mentioned that you have essentially found something
> missing from the R6 GCC implementation. We have just fixed this in our
> internal builds so we will have to provide you with an updated compiler to
> use ZC. This will be fixed in Imaginations 2015-01 Codescape SDK and will
> be posted to GCC following R6 commit (that is a matter of hours away as it
> happens).

Ah sorry I misunderstood you. I thought you meant that "R6 lacks the ZC
documentation"

Thanks

> 
> The reason this was missed from the R6 implementation in GCC is that the
> atomic sync patterns in the compiler actually only allow base registers with
> no offset (reason unknown) so we will be fixing that too.

Ok thanks a lot

-- 
markos

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 19/67] MIPS: asm: atomic: Update asm and ISA constrains for MIPS R6 support
  2014-12-19 10:01       ` Markos Chandras
  (?)
@ 2014-12-19 16:38       ` David Daney
  -1 siblings, 0 replies; 187+ messages in thread
From: David Daney @ 2014-12-19 16:38 UTC (permalink / raw)
  To: Markos Chandras; +Cc: linux-mips, Matthew Fortune

On 12/19/2014 02:01 AM, Markos Chandras wrote:
> On 12/18/2014 06:50 PM, David Daney wrote:
>> On 12/18/2014 07:09 AM, Markos Chandras wrote:
>>> MIPS R6 changed the opcodes for LL/SC instructions and reduced the
>>> offset field to 9-bits. This has some undesired effects with the "m"
>>> constrain since it implies a 16-bit immediate. As a result of which,
>>> add a register ("r") constrain as well to make sure the entire address
>>> is loaded to a register before the LL/SC operations. Also use macro
>>> to set the appropriate ISA for the asm blocks
>>>
>>
>> Has support for MIPS R6 been added to GCC?
>>
>> If so, that should include a proper constraint to be used with the new
>> offset restrictions.  We should probably use that, instead of forcing to
>> a "r" constraint.
>>
>>
>>> Cc: Matthew Fortune <Matthew.Fortune@imgtec.com>
>>> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
>>> ---
>>>    arch/mips/include/asm/atomic.h | 50
>>> +++++++++++++++++++++---------------------
>>>    1 file changed, 25 insertions(+), 25 deletions(-)
>>>
>>> diff --git a/arch/mips/include/asm/atomic.h
>>> b/arch/mips/include/asm/atomic.h
>>> index 6dd6bfc607e9..8669e0ec97e3 100644
>>> --- a/arch/mips/include/asm/atomic.h
>>> +++ b/arch/mips/include/asm/atomic.h
>>> @@ -60,13 +60,13 @@ static __inline__ void atomic_##op(int i, atomic_t
>>> * v)                \
>>>                                            \
>>>            do {                                \
>>>                __asm__ __volatile__(                    \
>>> -            "    .set    arch=r4000            \n"    \
>>> -            "    ll    %0, %1        # atomic_" #op "\n"    \
>>> +            "    .set    "MIPS_ISA_ARCH_LEVEL"        \n"    \
>>> +            "    ll    %0, 0(%3)    # atomic_" #op "\n"    \
>>>                "    " #asm_op " %0, %2            \n"    \
>>> -            "    sc    %0, %1                \n"    \
>>> +            "    sc    %0, 0(%3)            \n"    \
>>>                "    .set    mips0                \n"    \
>>>                : "=&r" (temp), "+m" (v->counter)            \
>>> -            : "Ir" (i));                        \
>>> +            : "Ir" (i), "r" (&v->counter));                \
>>
>> You lost the "m" constraint, but are still modifying memory.  There is
>> no "memory" clobber here, so we are no longer correctly describing what
>> is happening.
>>
>>
>
> Sorry I don't understand what you mean by  "you lost the "m"
> constraint". +m (v->counter) is still there to denote that v->counter
> memory is being modified no?
>

It looks like I misread the patch.  On closer inspection, it seems that 
the "m" constraint remains, so let's disregard my comment.

David Daney

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 12/67] MIPS: asm: asmmacro: Replace add instructions with "addui"
  2014-12-19  9:01       ` Markos Chandras
  (?)
@ 2015-01-11 23:34       ` Maciej W. Rozycki
  2015-01-13 13:13           ` Markos Chandras
  -1 siblings, 1 reply; 187+ messages in thread
From: Maciej W. Rozycki @ 2015-01-11 23:34 UTC (permalink / raw)
  To: Markos Chandras; +Cc: David Daney, Ralf Baechle, linux-mips

On Fri, 19 Dec 2014, Markos Chandras wrote:

> >> The use of "add" instruction for immediate operations is wrong and
> >> relies to gas being smart enough to notice that and replace it with
> >> either addi or addui. However, MIPS R6 removed the addi instruction
> >> so, fix this problem properly by using the correct instruction
> >> directly.

 Not true, depending on the arguments the ADD assembly macro expands to 
either of the ADD and the ADDI hardware instructions; where an immediate 
outside the 16-bit signed range is used it also expands to a longer 
sequence involving LUI and the actual operation is ADD.  It never expands 
to ADDIU (which I gather you meant).

> > This is another case of the use of "add" being a real bug.  We should
> > never have faulting instructions like this in the kernel.
> > 
> > Can you send all patches in this set that fix this bug as a separate
> > patch?  Since they are obviously correct, and really should be used by
> > all non-R6 processors, we can get them in sooner that the entire R6 thing.
> > 
> > Thanks,
> > David Daney
> 
> sure i will move these patches away from R6 and post them separately.

 I think using the ADDU macro is preferred here as it allows arbitrary 
32-bit values for `off', just like with memory references in MIPS assembly 
instructions.

  Maciej

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 19/67] MIPS: asm: atomic: Update asm and ISA constrains for MIPS R6 support
  2014-12-19 10:20             ` Markos Chandras
  2014-12-19 12:39               ` Markos Chandras
@ 2015-01-11 23:51               ` Maciej W. Rozycki
  1 sibling, 0 replies; 187+ messages in thread
From: Maciej W. Rozycki @ 2015-01-11 23:51 UTC (permalink / raw)
  To: Markos Chandras; +Cc: Matthew Fortune, David Daney, Ralf Baechle, linux-mips

On Fri, 19 Dec 2014, Markos Chandras wrote:

> > Obviously to use anything other than the 'm' constraint you are going
> > to need to know when any given constraint was added to GCC.
> > 'ZC' was only added to GCC in March 2013 r196828 which I believe it is a
> > GCC 4.9 feature so you will have to use it conditionally if you use it at
> > all.
> > 
> 
> is this something desirable? check the gcc version, initialize a macro
> and then use that macro as a constrain? i haven't thought this through,
> but it could be a bit messy.

 There is prior art for this, see arch/mips/include/asm/compiler.h and 
then grep the tree for uses.

  Maciej

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 12/67] MIPS: asm: asmmacro: Replace add instructions with "addui"
@ 2015-01-13 13:13           ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2015-01-13 13:13 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: David Daney, Ralf Baechle, linux-mips

On 01/11/2015 11:34 PM, Maciej W. Rozycki wrote:
> On Fri, 19 Dec 2014, Markos Chandras wrote:
> 
>>>> The use of "add" instruction for immediate operations is wrong and
>>>> relies to gas being smart enough to notice that and replace it with
>>>> either addi or addui. However, MIPS R6 removed the addi instruction
>>>> so, fix this problem properly by using the correct instruction
>>>> directly.
> 
>  Not true, depending on the arguments the ADD assembly macro expands to 
> either of the ADD and the ADDI hardware instructions; where an immediate 
> outside the 16-bit signed range is used it also expands to a longer 
> sequence involving LUI and the actual operation is ADD.  It never expands 
> to ADDIU (which I gather you meant).
> 
>>> This is another case of the use of "add" being a real bug.  We should
>>> never have faulting instructions like this in the kernel.
>>>
>>> Can you send all patches in this set that fix this bug as a separate
>>> patch?  Since they are obviously correct, and really should be used by
>>> all non-R6 processors, we can get them in sooner that the entire R6 thing.
>>>
>>> Thanks,
>>> David Daney
>>
>> sure i will move these patches away from R6 and post them separately.
> 
>  I think using the ADDU macro is preferred here as it allows arbitrary 
> 32-bit values for `off', just like with memory references in MIPS assembly 
> instructions.
> 
>   Maciej
> 
Hi,

What ADDU macro?

-- 
markos

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 12/67] MIPS: asm: asmmacro: Replace add instructions with "addui"
@ 2015-01-13 13:13           ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2015-01-13 13:13 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: David Daney, Ralf Baechle, linux-mips

On 01/11/2015 11:34 PM, Maciej W. Rozycki wrote:
> On Fri, 19 Dec 2014, Markos Chandras wrote:
> 
>>>> The use of "add" instruction for immediate operations is wrong and
>>>> relies to gas being smart enough to notice that and replace it with
>>>> either addi or addui. However, MIPS R6 removed the addi instruction
>>>> so, fix this problem properly by using the correct instruction
>>>> directly.
> 
>  Not true, depending on the arguments the ADD assembly macro expands to 
> either of the ADD and the ADDI hardware instructions; where an immediate 
> outside the 16-bit signed range is used it also expands to a longer 
> sequence involving LUI and the actual operation is ADD.  It never expands 
> to ADDIU (which I gather you meant).
> 
>>> This is another case of the use of "add" being a real bug.  We should
>>> never have faulting instructions like this in the kernel.
>>>
>>> Can you send all patches in this set that fix this bug as a separate
>>> patch?  Since they are obviously correct, and really should be used by
>>> all non-R6 processors, we can get them in sooner that the entire R6 thing.
>>>
>>> Thanks,
>>> David Daney
>>
>> sure i will move these patches away from R6 and post them separately.
> 
>  I think using the ADDU macro is preferred here as it allows arbitrary 
> 32-bit values for `off', just like with memory references in MIPS assembly 
> instructions.
> 
>   Maciej
> 
Hi,

What ADDU macro?

-- 
markos

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 12/67] MIPS: asm: asmmacro: Replace add instructions with "addui"
  2015-01-13 13:13           ` Markos Chandras
  (?)
@ 2015-01-13 14:58           ` Maciej W. Rozycki
  2015-01-13 15:04               ` Markos Chandras
  -1 siblings, 1 reply; 187+ messages in thread
From: Maciej W. Rozycki @ 2015-01-13 14:58 UTC (permalink / raw)
  To: Markos Chandras; +Cc: David Daney, Ralf Baechle, linux-mips

On Tue, 13 Jan 2015, Markos Chandras wrote:

> >  I think using the ADDU macro is preferred here as it allows arbitrary 
> > 32-bit values for `off', just like with memory references in MIPS assembly 
> > instructions.
> 
> What ADDU macro?

 This:

{"addu",		"t,r,I",	0,    (int) M_ADDU_I,	INSN_MACRO,		0,		I1,		0,	0 },

(from opcodes/mips-opc.c).

  Maciej

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 12/67] MIPS: asm: asmmacro: Replace add instructions with "addui"
@ 2015-01-13 15:04               ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2015-01-13 15:04 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: David Daney, Ralf Baechle, linux-mips

On 01/13/2015 02:58 PM, Maciej W. Rozycki wrote:
> On Tue, 13 Jan 2015, Markos Chandras wrote:
> 
>>>  I think using the ADDU macro is preferred here as it allows arbitrary 
>>> 32-bit values for `off', just like with memory references in MIPS assembly 
>>> instructions.
>>
>> What ADDU macro?
> 
>  This:
> 
> {"addu",		"t,r,I",	0,    (int) M_ADDU_I,	INSN_MACRO,		0,		I1,		0,	0 },
> 
> (from opcodes/mips-opc.c).
> 
>   Maciej
> 
I see your point about having 32-bit offsets supported here but it's not
obvious that addu would simply accept this format without looking at the
binutils sources.

in any case, it does not make a difference in this particular example,
so I will fix it. Thanks

-- 
markos

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 12/67] MIPS: asm: asmmacro: Replace add instructions with "addui"
@ 2015-01-13 15:04               ` Markos Chandras
  0 siblings, 0 replies; 187+ messages in thread
From: Markos Chandras @ 2015-01-13 15:04 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: David Daney, Ralf Baechle, linux-mips

On 01/13/2015 02:58 PM, Maciej W. Rozycki wrote:
> On Tue, 13 Jan 2015, Markos Chandras wrote:
> 
>>>  I think using the ADDU macro is preferred here as it allows arbitrary 
>>> 32-bit values for `off', just like with memory references in MIPS assembly 
>>> instructions.
>>
>> What ADDU macro?
> 
>  This:
> 
> {"addu",		"t,r,I",	0,    (int) M_ADDU_I,	INSN_MACRO,		0,		I1,		0,	0 },
> 
> (from opcodes/mips-opc.c).
> 
>   Maciej
> 
I see your point about having 32-bit offsets supported here but it's not
obvious that addu would simply accept this format without looking at the
binutils sources.

in any case, it does not make a difference in this particular example,
so I will fix it. Thanks

-- 
markos

^ permalink raw reply	[flat|nested] 187+ messages in thread

* Re: [PATCH RFC 12/67] MIPS: asm: asmmacro: Replace add instructions with "addui"
  2015-01-13 15:04               ` Markos Chandras
  (?)
@ 2015-01-13 15:24               ` Maciej W. Rozycki
  -1 siblings, 0 replies; 187+ messages in thread
From: Maciej W. Rozycki @ 2015-01-13 15:24 UTC (permalink / raw)
  To: Markos Chandras; +Cc: David Daney, Ralf Baechle, linux-mips

On Tue, 13 Jan 2015, Markos Chandras wrote:

> >> What ADDU macro?
> > 
> >  This:
> > 
> > {"addu",		"t,r,I",	0,    (int) M_ADDU_I,	INSN_MACRO,		0,		I1,		0,	0 },
> > 
> > (from opcodes/mips-opc.c).
> 
> I see your point about having 32-bit offsets supported here but it's not
> obvious that addu would simply accept this format without looking at the
> binutils sources.

 All MIPS assemblers support it AFAIK, including SGI's MIPSpro and the 
original MIPS Co. assembler.

 You will have it documented in any reasonable MIPS assembly language 
manual, and other books on the MIPS architecture will have it too.  All 
MIPS ALU operations have a corresponding macro that handles an arbitrary 
third argument, including 32-bit immediates, e.g. AND, NOR, SUBU, etc.  
Some branches and other operations are macros too.

 If you have been unaware of this fact, then I suggest you that you have a 
look at a MIPS assembly book, e.g. the book I started with had all the 
macros and what they actually expand to listed, in addition to true 
hardware instructions up to MIPS IV.

  Maciej

^ permalink raw reply	[flat|nested] 187+ messages in thread

end of thread, other threads:[~2015-01-13 15:24 UTC | newest]

Thread overview: 187+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-12-18 15:09 [PATCH RFC 00/67] Add MIPS R6 support Markos Chandras
2014-12-18 15:09 ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 01/67] MIPS: Add generic QEMU R6 PRid and cpu type identifiers Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 19:10   ` David Daney
2014-12-19  8:49     ` Markos Chandras
2014-12-19  8:49       ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 02/67] MIPS: Add cases for CPU_QEMUR6 Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 03/67] MIPS: Add MIPS QEMUR6 probe support Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 04/67] MIPS: Add build support for the MIPS R6 ISA Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 05/67] MIPS: mm: uasm: Add signed 9-bit immediate related macros Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 06/67] MIPS: mm: Add MIPS R6 instruction encodings Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 07/67] MIPS: asm: asm: Add new macros to set ISA and arch asm annotations Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 08/67] MIPS: asm: module: define MODULE_PROC_FAMILY for MIPS R6 Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 09/67] MIPS: asm: stackframe: Do not preserve the HI/LO registers on " Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 10/67] MIPS: asm: asmmacro: Drop unused 'reg' argument on MIPSR2 Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 11/67] MIPS: asm: asmmacro: Add MIPS R6 support to the simple EI/DI variants Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 12/67] MIPS: asm: asmmacro: Replace add instructions with "addui" Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 18:56   ` David Daney
2014-12-19  9:01     ` Markos Chandras
2014-12-19  9:01       ` Markos Chandras
2015-01-11 23:34       ` Maciej W. Rozycki
2015-01-13 13:13         ` Markos Chandras
2015-01-13 13:13           ` Markos Chandras
2015-01-13 14:58           ` Maciej W. Rozycki
2015-01-13 15:04             ` Markos Chandras
2015-01-13 15:04               ` Markos Chandras
2015-01-13 15:24               ` Maciej W. Rozycki
2014-12-18 15:09 ` [PATCH RFC 13/67] MIPS: Use generic checksum functions for MIPS R6 Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 14/67] MIPS: asm: cpu: Add MIPSR6 ISA definitions Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 15/67] MIPS: asm: hazards: Add MIPSR6 definitions Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 16/67] MIPS: asm: irqflags: Add MIPS R6 related definitions Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 17/67] MIPS: asm: r4kcache: Add MIPS R6 cache unroll functions Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 18/67] MIPS: asm: spram: Add MIPS R6 related definitions Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 19/67] MIPS: asm: atomic: Update asm and ISA constrains for MIPS R6 support Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 18:50   ` David Daney
2014-12-18 18:59     ` Måns Rullgård
2014-12-18 19:01     ` Ralf Baechle
2014-12-18 21:04       ` Matthew Fortune
2014-12-18 21:04         ` Matthew Fortune
2014-12-18 22:18         ` Måns Rullgård
2014-12-18 22:18           ` Måns Rullgård
2014-12-18 22:19         ` David Daney
2014-12-18 22:58           ` Matthew Fortune
2014-12-18 23:43             ` Måns Rullgård
2014-12-18 23:43               ` Måns Rullgård
2014-12-19 10:20             ` Markos Chandras
2014-12-19 12:39               ` Markos Chandras
2014-12-19 13:53                 ` Matthew Fortune
2014-12-19 13:55                   ` Markos Chandras
2015-01-11 23:51               ` Maciej W. Rozycki
2014-12-19 12:29             ` Ralf Baechle
2014-12-19 10:01     ` Markos Chandras
2014-12-19 10:01       ` Markos Chandras
2014-12-19 16:38       ` David Daney
2014-12-18 15:09 ` [PATCH RFC 20/67] MIPS: asm: cmpxchg: " Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 21/67] MIPS: asm: bitops: " Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 22/67] MIPS: asm: futex: " Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 23/67] MIPS: asm: spinlock: Update asm " Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 24/67] MIPS: asm: spinlock: Replace sub instruction with addiu Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 18:53   ` David Daney
2014-12-18 19:06     ` Ralf Baechle
2014-12-19  8:51     ` Markos Chandras
2014-12-19  8:51       ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 25/67] MIPS: kernel: cpu-bugs64: Do not check R6 cores for existing 64-bit bugs Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 26/67] MIPS: kernel: cevt-r4k: Add MIPS R6 to the c0_compare_interrupt handler Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 27/67] MIPS: kernel: cpu-probe.c: Add support for MIPS R6 Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 28/67] MIPS: kernel: entry.S: Add MIPS R6 related definitions Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 29/67] MIPS: kernel: proc: Add MIPS R6 support to /proc/cpuinfo Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-19 11:32   ` Sergei Shtylyov
2014-12-18 15:09 ` [PATCH RFC 30/67] MIPS: kernel: traps: Add MIPS R6 related definitions Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 31/67] MIPS: kernel: r4k_switch: Add support for MIPS R6 Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 32/67] MIPS: kernel: r4k_fpu: " Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 33/67] MIPS: kernel: genex: Set correct ISA level Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 34/67] MIPS: kernel: cps-vec: Replace addi with addiu Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 35/67] MIPS: uapi: inst: Add new opcodes for COP2 instructions Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 36/67] MIPS: kernel: unaligned: Add support for the MIPS R6 Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 37/67] MIPS: lib: memcpy: Add MIPS R6 support Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 38/67] MIPS: lib: memset: " Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 39/67] MIPS: mm: page: " Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 40/67] MIPS: mm: tlbex: Add MIPS R6 case for the EHB instruction Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 19:05   ` David Daney
2014-12-18 15:09 ` [PATCH RFC 41/67] MIPS: mm: c-r4k: Set the correct ISA level Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 42/67] MIPS: kernel: branch: Prepare the JR instruction for emulation on MIPS R6 Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 43/67] MIPS: kernel: branch: Prevent BLTZL emulation for " Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 44/67] MIPS: kernel: branch: Prevent BGEZL " Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 45/67] MIPS: kernel: branch: Prevent BLTZAL " Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 46/67] MIPS: kernel: branch: Prevent BGEZAL " Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 47/67] MIPS: kernel: branch: Prevent BEQL " Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 23:56   ` Joshua Kinard
2014-12-19  8:54     ` Markos Chandras
2014-12-19  8:54       ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 48/67] MIPS: kernel: branch: Prevent BNEL " Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 49/67] MIPS: kernel: branch: Prevent BLEZL " Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:09 ` [PATCH RFC 50/67] MIPS: kernel: branch: Prevent BGTZL " Markos Chandras
2014-12-18 15:09   ` Markos Chandras
2014-12-18 15:10 ` [PATCH RFC 51/67] MIPS: uapi: inst: Add new BC1EQZ and BC1NEZ MIPS R6 opcodes Markos Chandras
2014-12-18 15:10   ` Markos Chandras
2014-12-18 15:10 ` [PATCH RFC 52/67] MIPS: kernel: branch: Add support for the BC1{EQ,NE}Z FPU branches Markos Chandras
2014-12-18 15:10   ` Markos Chandras
2014-12-18 15:10 ` [PATCH RFC 53/67] MIPS: kernel: branch: Add new MIPS R6 B{L,G}ΕZ{AL,}C emulation Markos Chandras
2014-12-18 15:10   ` Markos Chandras
2014-12-19 11:59   ` Sergei Shtylyov
2014-12-18 15:10 ` [PATCH RFC 54/67] MIPS: kernel: branch: Add new MIPS R6 B{L,G}TZ{AL,}C emulation Markos Chandras
2014-12-18 15:10   ` Markos Chandras
2014-12-19 12:02   ` Sergei Shtylyov
2014-12-18 15:10 ` [PATCH RFC 55/67] MIPS: kernel: branch: Emulate the branch compact (BC) on MIPS R6 Markos Chandras
2014-12-18 15:10   ` Markos Chandras
2014-12-18 15:10 ` [PATCH RFC 56/67] MIPS: kernel: branch: Emulate the BOVC, BEQC and BEQZALC R6 instructions Markos Chandras
2014-12-18 15:10   ` Markos Chandras
2014-12-18 19:07   ` David Daney
2014-12-19  8:52     ` Markos Chandras
2014-12-19  8:52       ` Markos Chandras
2014-12-18 15:10 ` [PATCH RFC 57/67] MIPS: kernel: branch: Emulate the BNVC, BNEC and BNEZLAC " Markos Chandras
2014-12-18 15:10   ` Markos Chandras
2014-12-18 19:08   ` David Daney
2014-12-18 15:10 ` [PATCH RFC 58/67] MIPS: kernel: branch: Emulate the BALC R6 instruction Markos Chandras
2014-12-18 15:10   ` Markos Chandras
2014-12-19 12:06   ` Sergei Shtylyov
2014-12-18 15:10 ` [PATCH RFC 59/67] MIPS: kernel: branch: Emulate the BEQZC and JIC instructions Markos Chandras
2014-12-18 15:10   ` Markos Chandras
2014-12-19 12:08   ` Sergei Shtylyov
2014-12-18 15:10 ` [PATCH RFC 60/67] MIPS: math-emu: cp1emu: Move the fpucondbit struct to a header Markos Chandras
2014-12-18 15:10   ` Markos Chandras
2014-12-19 12:10   ` Sergei Shtylyov
2014-12-18 15:10 ` [PATCH RFC 61/67] MIPS: Add LLB bit and related feature for the Config 5 CP0 register Markos Chandras
2014-12-18 15:10   ` Markos Chandras
2014-12-18 15:10 ` [PATCH RFC 62/67] MIPS: asm: mipsregs: Add support for the LLADDR register Markos Chandras
2014-12-18 15:10   ` Markos Chandras
2014-12-18 15:10 ` [PATCH RFC 63/67] MIPS: kernel: mips-r2-to-r6-emul: Add R2 emulator for MIPS R6 Markos Chandras
2014-12-18 15:10   ` Markos Chandras
2014-12-18 15:10 ` [PATCH RFC 64/67] MIPS: Make use of the ERETNC instruction on " Markos Chandras
2014-12-18 15:10   ` Markos Chandras
2014-12-18 15:10 ` [PATCH RFC 65/67] MIPS: Malta: malta-int: Set correct asm ISA level Markos Chandras
2014-12-18 15:10   ` Markos Chandras
2014-12-18 15:10 ` [PATCH RFC 66/67] MIPS: Malta: Add support for building MIPS R6 kernel Markos Chandras
2014-12-18 15:10   ` Markos Chandras
2014-12-18 15:10 ` [PATCH RFC 67/67] MIPS: Add Malta QEMU 32R6 defconfig Markos Chandras
2014-12-18 15:10   ` Markos Chandras

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.