All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH RFC v2 00/70] Add MIPS R6 support
@ 2015-01-16 10:48 ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Matthew Fortune

Hi,

This is the v2 of the MIPS R6 patchset I posted a month ago[1].
I have addressed most of the issues. Most notably:

* Rebased onto v3.19-rc4
* Use the "ZC" constraints for the R6 LL/ZC atomics introduced in GCC 4.9
* Code simplifications as suggested by Sergei Shtylyov and David Daney
* Add FP ABI improvement necessary for R6 userland to work with the latest
  tools.
* Code fixes.
* A couple of unrelated commits are included as well (ie s/addi/addiu/, FP fixes,
etc. I will talk to Ralf and see if we need to merge them separately or not.

A couple of things haven't been addressed on purpose:

* The QEMU patches are still needed. The PRPL QEMU has changed since then
to use the I6400[2] PRID for mips64r6[3] but mips32r6 remains the same.
This means that for mips64r6 to boot, you need to modify your PRPL tree to use
the old PRID definition even for the I6400 cpu until there is proper support in
the kernel. The generic QEMU PRID is also used by QEMU R2-generic cpu
implementations as well.

The new patches are available in my git tree[4].

[1]: http://www.linux-mips.org/archives/linux-mips/2014-12/msg00222.html
[2]: http://www.imgtec.com/mips/warrior/iclass.asp
[3]: https://github.com/prplfoundation/qemu/commit/4473b4492ddc9c90be85d11db7029fc9bbfd805a
[4]: git://git.linux-mips.org/pub/scm/mchandras/linux.git 3.19-r6-rfc-1


Leonid Yegoshin (21):
  MIPS: Add generic QEMU PRid and cpu type identifiers
  MIPS: Add cases for CPU_QEMU_GENERIC
  MIPS: Add MIPS generic QEMU 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: kernel: unaligned: Add support for the MIPS R6
  MIPS: lib: memcpy: Add MIPS R6 support
  MIPS: lib: memset: Add MIPS R6 support
  MIPS: mm: tlbex: Use cpu_has_mips_r2_exec_hazard for the EHB
    instruction
  MIPS: kernel: mips-r2-to-r6-emul: Add R2 emulator for MIPS R6

Markos Chandras (49):
  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: Use the new "ZC" constraint for MIPS R6
  MIPS: asm: cmpxchg: Update ISA constraints for MIPS R6 support
  MIPS: asm: atomic: Update ISA constraints for MIPS R6 support
  MIPS: asm: bitops: Update ISA constraints for MIPS R6 support
  MIPS: asm: futex: Set the appropriate ISA level for MIPS R6
  MIPS: asm: spinlock: Replace sub instruction with addiu
  MIPS: asm: local: Set the appropriate ISA level for MIPS R6
  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: kernel: syscall: Set the appropriate ISA level for MIPS R6
  MIPS: mm: page: Add MIPS R6 support
  MIPS: mm: c-r4k: Set the correct ISA level
  MIPS: mm: scache: Add secondary cache support for MIPS R6 cores
  MIPS: kernel: 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: Emulate the BC1{EQ,NE}Z FPU instructions
  MIPS: Emulate the new MIPS R6 B{L,G}Ε{Z,}{AL,}C instructions
  MIPS: Emulate the new MIPS R6 B{L,G}T{Z,}{AL,}C instructions
  MIPS: Emulate the new MIPS R6 branch compact (BC) instruction
  MIPS: Emulate the new MIPS R6 BOVC, BEQC and BEQZALC instructions
  MIPS: Emulate the new MIPS R6 BNVC, BNEC and BNEZLAC instructions
  MIPS: Emulate the new MIPS R6 BALC instruction
  MIPS: Emulate the new MIPS R6 BEQZC and JIC instructions
  MIPS: Emulate the new MIPS R6 BNEZC and JIALC instructions
  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: Handle MIPS IV, V and R2 FPU instructions on MIPS R6 as well
  MIPS: kernel: process: Do not allow FR=0 on MIPS R6
  MIPS: kernel: elf: Improve the overall ABI and FPU mode checks
  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              |   13 +-
 arch/mips/include/asm/bitops.h              |   31 +-
 arch/mips/include/asm/checksum.h            |    6 +
 arch/mips/include/asm/cmpxchg.h             |   11 +-
 arch/mips/include/asm/compiler.h            |   10 +-
 arch/mips/include/asm/cpu-features.h        |   22 +-
 arch/mips/include/asm/cpu-type.h            |    7 +
 arch/mips/include/asm/cpu.h                 |   11 +-
 arch/mips/include/asm/elf.h                 |   10 +-
 arch/mips/include/asm/fpu.h                 |    3 +-
 arch/mips/include/asm/futex.h               |    8 +-
 arch/mips/include/asm/hazards.h             |    9 +-
 arch/mips/include/asm/irqflags.h            |    6 +-
 arch/mips/include/asm/local.h               |    4 +-
 arch/mips/include/asm/mips-r2-to-r6-emul.h  |   96 ++
 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            |    2 +-
 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           |   24 +-
 arch/mips/kernel/Makefile                   |    2 +
 arch/mips/kernel/asm-offsets.c              |    1 +
 arch/mips/kernel/branch.c                   |  283 +++-
 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                |   27 +-
 arch/mips/kernel/elf.c                      |  284 ++--
 arch/mips/kernel/entry.S                    |   23 +-
 arch/mips/kernel/genex.S                    |    2 +-
 arch/mips/kernel/idle.c                     |    1 +
 arch/mips/kernel/mips-r2-to-r6-emul.c       | 2378 +++++++++++++++++++++++++++
 arch/mips/kernel/mips_ksyms.c               |    2 +
 arch/mips/kernel/proc.c                     |    8 +-
 arch/mips/kernel/process.c                  |    4 +
 arch/mips/kernel/r4k_fpu.S                  |   12 +-
 arch/mips/kernel/r4k_switch.S               |   14 +-
 arch/mips/kernel/spram.c                    |    1 +
 arch/mips/kernel/syscall.c                  |    2 +-
 arch/mips/kernel/traps.c                    |   41 +-
 arch/mips/kernel/unaligned.c                |  390 ++++-
 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                 |  158 +-
 arch/mips/mm/c-r4k.c                        |    6 +-
 arch/mips/mm/page.c                         |   20 +-
 arch/mips/mm/sc-mips.c                      |    4 +-
 arch/mips/mm/tlbex.c                        |    7 +-
 arch/mips/mm/uasm-mips.c                    |   32 +
 arch/mips/mm/uasm.c                         |   13 +-
 62 files changed, 4281 insertions(+), 287 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.1

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

* [PATCH RFC v2 00/70] Add MIPS R6 support
@ 2015-01-16 10:48 ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Matthew Fortune

Hi,

This is the v2 of the MIPS R6 patchset I posted a month ago[1].
I have addressed most of the issues. Most notably:

* Rebased onto v3.19-rc4
* Use the "ZC" constraints for the R6 LL/ZC atomics introduced in GCC 4.9
* Code simplifications as suggested by Sergei Shtylyov and David Daney
* Add FP ABI improvement necessary for R6 userland to work with the latest
  tools.
* Code fixes.
* A couple of unrelated commits are included as well (ie s/addi/addiu/, FP fixes,
etc. I will talk to Ralf and see if we need to merge them separately or not.

A couple of things haven't been addressed on purpose:

* The QEMU patches are still needed. The PRPL QEMU has changed since then
to use the I6400[2] PRID for mips64r6[3] but mips32r6 remains the same.
This means that for mips64r6 to boot, you need to modify your PRPL tree to use
the old PRID definition even for the I6400 cpu until there is proper support in
the kernel. The generic QEMU PRID is also used by QEMU R2-generic cpu
implementations as well.

The new patches are available in my git tree[4].

[1]: http://www.linux-mips.org/archives/linux-mips/2014-12/msg00222.html
[2]: http://www.imgtec.com/mips/warrior/iclass.asp
[3]: https://github.com/prplfoundation/qemu/commit/4473b4492ddc9c90be85d11db7029fc9bbfd805a
[4]: git://git.linux-mips.org/pub/scm/mchandras/linux.git 3.19-r6-rfc-1


Leonid Yegoshin (21):
  MIPS: Add generic QEMU PRid and cpu type identifiers
  MIPS: Add cases for CPU_QEMU_GENERIC
  MIPS: Add MIPS generic QEMU 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: kernel: unaligned: Add support for the MIPS R6
  MIPS: lib: memcpy: Add MIPS R6 support
  MIPS: lib: memset: Add MIPS R6 support
  MIPS: mm: tlbex: Use cpu_has_mips_r2_exec_hazard for the EHB
    instruction
  MIPS: kernel: mips-r2-to-r6-emul: Add R2 emulator for MIPS R6

Markos Chandras (49):
  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: Use the new "ZC" constraint for MIPS R6
  MIPS: asm: cmpxchg: Update ISA constraints for MIPS R6 support
  MIPS: asm: atomic: Update ISA constraints for MIPS R6 support
  MIPS: asm: bitops: Update ISA constraints for MIPS R6 support
  MIPS: asm: futex: Set the appropriate ISA level for MIPS R6
  MIPS: asm: spinlock: Replace sub instruction with addiu
  MIPS: asm: local: Set the appropriate ISA level for MIPS R6
  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: kernel: syscall: Set the appropriate ISA level for MIPS R6
  MIPS: mm: page: Add MIPS R6 support
  MIPS: mm: c-r4k: Set the correct ISA level
  MIPS: mm: scache: Add secondary cache support for MIPS R6 cores
  MIPS: kernel: 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: Emulate the BC1{EQ,NE}Z FPU instructions
  MIPS: Emulate the new MIPS R6 B{L,G}Ε{Z,}{AL,}C instructions
  MIPS: Emulate the new MIPS R6 B{L,G}T{Z,}{AL,}C instructions
  MIPS: Emulate the new MIPS R6 branch compact (BC) instruction
  MIPS: Emulate the new MIPS R6 BOVC, BEQC and BEQZALC instructions
  MIPS: Emulate the new MIPS R6 BNVC, BNEC and BNEZLAC instructions
  MIPS: Emulate the new MIPS R6 BALC instruction
  MIPS: Emulate the new MIPS R6 BEQZC and JIC instructions
  MIPS: Emulate the new MIPS R6 BNEZC and JIALC instructions
  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: Handle MIPS IV, V and R2 FPU instructions on MIPS R6 as well
  MIPS: kernel: process: Do not allow FR=0 on MIPS R6
  MIPS: kernel: elf: Improve the overall ABI and FPU mode checks
  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              |   13 +-
 arch/mips/include/asm/bitops.h              |   31 +-
 arch/mips/include/asm/checksum.h            |    6 +
 arch/mips/include/asm/cmpxchg.h             |   11 +-
 arch/mips/include/asm/compiler.h            |   10 +-
 arch/mips/include/asm/cpu-features.h        |   22 +-
 arch/mips/include/asm/cpu-type.h            |    7 +
 arch/mips/include/asm/cpu.h                 |   11 +-
 arch/mips/include/asm/elf.h                 |   10 +-
 arch/mips/include/asm/fpu.h                 |    3 +-
 arch/mips/include/asm/futex.h               |    8 +-
 arch/mips/include/asm/hazards.h             |    9 +-
 arch/mips/include/asm/irqflags.h            |    6 +-
 arch/mips/include/asm/local.h               |    4 +-
 arch/mips/include/asm/mips-r2-to-r6-emul.h  |   96 ++
 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            |    2 +-
 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           |   24 +-
 arch/mips/kernel/Makefile                   |    2 +
 arch/mips/kernel/asm-offsets.c              |    1 +
 arch/mips/kernel/branch.c                   |  283 +++-
 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                |   27 +-
 arch/mips/kernel/elf.c                      |  284 ++--
 arch/mips/kernel/entry.S                    |   23 +-
 arch/mips/kernel/genex.S                    |    2 +-
 arch/mips/kernel/idle.c                     |    1 +
 arch/mips/kernel/mips-r2-to-r6-emul.c       | 2378 +++++++++++++++++++++++++++
 arch/mips/kernel/mips_ksyms.c               |    2 +
 arch/mips/kernel/proc.c                     |    8 +-
 arch/mips/kernel/process.c                  |    4 +
 arch/mips/kernel/r4k_fpu.S                  |   12 +-
 arch/mips/kernel/r4k_switch.S               |   14 +-
 arch/mips/kernel/spram.c                    |    1 +
 arch/mips/kernel/syscall.c                  |    2 +-
 arch/mips/kernel/traps.c                    |   41 +-
 arch/mips/kernel/unaligned.c                |  390 ++++-
 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                 |  158 +-
 arch/mips/mm/c-r4k.c                        |    6 +-
 arch/mips/mm/page.c                         |   20 +-
 arch/mips/mm/sc-mips.c                      |    4 +-
 arch/mips/mm/tlbex.c                        |    7 +-
 arch/mips/mm/uasm-mips.c                    |   32 +
 arch/mips/mm/uasm.c                         |   13 +-
 62 files changed, 4281 insertions(+), 287 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.1

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

* [PATCH RFC v2 01/70] MIPS: Add generic QEMU PRid and cpu type identifiers
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 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. This is also used for QEMU R2 generic cpus.

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 33866fce4d63..0b74bbf976e4 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_QEMU_GENERIC	0x0000
 #define PRID_IMP_4KC		0x8000
 #define PRID_IMP_5KC		0x8100
 #define PRID_IMP_20KC		0x8200
@@ -312,6 +313,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_QEMU_GENERIC,
+
 	CPU_LAST
 };
 
-- 
2.2.1

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

* [PATCH RFC v2 01/70] MIPS: Add generic QEMU PRid and cpu type identifiers
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 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. This is also used for QEMU R2 generic cpus.

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 33866fce4d63..0b74bbf976e4 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_QEMU_GENERIC	0x0000
 #define PRID_IMP_4KC		0x8000
 #define PRID_IMP_5KC		0x8100
 #define PRID_IMP_20KC		0x8200
@@ -312,6 +313,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_QEMU_GENERIC,
+
 	CPU_LAST
 };
 
-- 
2.2.1

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

* [PATCH RFC v2 02/70] MIPS: Add cases for CPU_QEMU_GENERIC
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

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

Add a CPU_QEMU_GENERIC 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 | 7 +++++++
 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, 13 insertions(+)

diff --git a/arch/mips/include/asm/cpu-type.h b/arch/mips/include/asm/cpu-type.h
index b4e2bd87df50..8245875f8b33 100644
--- a/arch/mips/include/asm/cpu-type.h
+++ b/arch/mips/include/asm/cpu-type.h
@@ -54,6 +54,13 @@ static inline int __pure __get_cpu_type(const int cpu_type)
 	case CPU_M5150:
 #endif
 
+#if defined(CONFIG_SYS_HAS_CPU_MIPS32_R2) || \
+    defined(CONFIG_SYS_HAS_CPU_MIPS32_R6) || \
+    defined(CONFIG_SYS_HAS_CPU_MIPS64_R2) || \
+    defined(CONFIG_SYS_HAS_CPU_MIPS64_R6)
+	case CPU_QEMU_GENERIC:
+#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..368c88b7eb6c 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_QEMU_GENERIC:
 		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..d1168d7c31e8 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_QEMU_GENERIC:
 		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 d5fbfb51b9da..461653ea28c8 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1559,6 +1559,7 @@ static inline void parity_protection_init(void)
 	case CPU_INTERAPTIV:
 	case CPU_PROAPTIV:
 	case CPU_P5600:
+	case CPU_QEMU_GENERIC:
 		{
 #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 dd261df005c2..b806deb29e63 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -1255,6 +1255,7 @@ static void probe_pcache(void)
 	case CPU_P5600:
 	case CPU_PROAPTIV:
 	case CPU_M5150:
+	case CPU_QEMU_GENERIC:
 		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..fd9b5d45e91b 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_QEMU_GENERIC:
 		if (config2 & (1 << 12))
 			return 0;
 	}
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 3978a3d81366..ff8d99ce3b9b 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_QEMU_GENERIC:
 			break;
 
 		default:
-- 
2.2.1

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

* [PATCH RFC v2 02/70] MIPS: Add cases for CPU_QEMU_GENERIC
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

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

Add a CPU_QEMU_GENERIC 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 | 7 +++++++
 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, 13 insertions(+)

diff --git a/arch/mips/include/asm/cpu-type.h b/arch/mips/include/asm/cpu-type.h
index b4e2bd87df50..8245875f8b33 100644
--- a/arch/mips/include/asm/cpu-type.h
+++ b/arch/mips/include/asm/cpu-type.h
@@ -54,6 +54,13 @@ static inline int __pure __get_cpu_type(const int cpu_type)
 	case CPU_M5150:
 #endif
 
+#if defined(CONFIG_SYS_HAS_CPU_MIPS32_R2) || \
+    defined(CONFIG_SYS_HAS_CPU_MIPS32_R6) || \
+    defined(CONFIG_SYS_HAS_CPU_MIPS64_R2) || \
+    defined(CONFIG_SYS_HAS_CPU_MIPS64_R6)
+	case CPU_QEMU_GENERIC:
+#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..368c88b7eb6c 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_QEMU_GENERIC:
 		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..d1168d7c31e8 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_QEMU_GENERIC:
 		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 d5fbfb51b9da..461653ea28c8 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1559,6 +1559,7 @@ static inline void parity_protection_init(void)
 	case CPU_INTERAPTIV:
 	case CPU_PROAPTIV:
 	case CPU_P5600:
+	case CPU_QEMU_GENERIC:
 		{
 #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 dd261df005c2..b806deb29e63 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -1255,6 +1255,7 @@ static void probe_pcache(void)
 	case CPU_P5600:
 	case CPU_PROAPTIV:
 	case CPU_M5150:
+	case CPU_QEMU_GENERIC:
 		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..fd9b5d45e91b 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_QEMU_GENERIC:
 		if (config2 & (1 << 12))
 			return 0;
 	}
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 3978a3d81366..ff8d99ce3b9b 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_QEMU_GENERIC:
 			break;
 
 		default:
-- 
2.2.1

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

* [PATCH RFC v2 03/70] MIPS: Add MIPS generic QEMU probe support
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 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 generic QEMU 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 5342674842f5..cc77fdaca0eb 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -896,6 +896,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_QEMU_GENERIC:
+		c->writecombine = _CACHE_UNCACHED;
+		c->cputype = CPU_QEMU_GENERIC;
+		__cpu_name[cpu] = "MIPS GENERIC QEMU";
+		break;
 	case PRID_IMP_4KC:
 		c->cputype = CPU_4KC;
 		c->writecombine = _CACHE_UNCACHED;
-- 
2.2.1

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

* [PATCH RFC v2 03/70] MIPS: Add MIPS generic QEMU probe support
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 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 generic QEMU 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 5342674842f5..cc77fdaca0eb 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -896,6 +896,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_QEMU_GENERIC:
+		c->writecombine = _CACHE_UNCACHED;
+		c->cputype = CPU_QEMU_GENERIC;
+		__cpu_name[cpu] = "MIPS GENERIC QEMU";
+		break;
 	case PRID_IMP_4KC:
 		c->cputype = CPU_4KC;
 		c->writecombine = _CACHE_UNCACHED;
-- 
2.2.1

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

* [PATCH RFC v2 04/70] MIPS: Add build support for the MIPS R6 ISA
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 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 3289969ee423..72156ea62a69 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1304,6 +1304,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
@@ -1339,6 +1353,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
@@ -1539,7 +1567,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
@@ -1659,12 +1687,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
 
@@ -1764,11 +1798,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
@@ -1781,6 +1815,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
 
@@ -2148,7 +2186,7 @@ config CPU_HAS_SMARTMIPS
 	  here.
 
 config CPU_MICROMIPS
-	depends on 32BIT && SYS_SUPPORTS_MICROMIPS
+	depends on 32BIT && 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 2563a088d3b8..b54d5a14b9f0 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.1

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

* [PATCH RFC v2 04/70] MIPS: Add build support for the MIPS R6 ISA
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 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 3289969ee423..72156ea62a69 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1304,6 +1304,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
@@ -1339,6 +1353,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
@@ -1539,7 +1567,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
@@ -1659,12 +1687,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
 
@@ -1764,11 +1798,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
@@ -1781,6 +1815,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
 
@@ -2148,7 +2186,7 @@ config CPU_HAS_SMARTMIPS
 	  here.
 
 config CPU_MICROMIPS
-	depends on 32BIT && SYS_SUPPORTS_MICROMIPS
+	depends on 32BIT && 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 2563a088d3b8..b54d5a14b9f0 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.1

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

* [PATCH RFC v2 05/70] MIPS: mm: uasm: Add signed 9-bit immediate related macros
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 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 4adf30284813..6596b6898637 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.1

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

* [PATCH RFC v2 05/70] MIPS: mm: uasm: Add signed 9-bit immediate related macros
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 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 4adf30284813..6596b6898637 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.1

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

* [PATCH RFC v2 06/70] MIPS: mm: Add MIPS R6 instruction encodings
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 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 89c22433b1c6..5c9e14a903af 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 8e02291cfc0c..7bb0d4ce2de8 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 },
@@ -104,11 +125,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 },
@@ -198,6 +228,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.1

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

* [PATCH RFC v2 06/70] MIPS: mm: Add MIPS R6 instruction encodings
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 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 89c22433b1c6..5c9e14a903af 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 8e02291cfc0c..7bb0d4ce2de8 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 },
@@ -104,11 +125,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 },
@@ -198,6 +228,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.1

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

* [PATCH RFC v2 07/70] MIPS: asm: asm: Add new macros to set ISA and arch asm annotations
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 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.1

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

* [PATCH RFC v2 07/70] MIPS: asm: asm: Add new macros to set ISA and arch asm annotations
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 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.1

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

* [PATCH RFC v2 08/70] MIPS: asm: module: define MODULE_PROC_FAMILY for MIPS R6
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 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.1

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

* [PATCH RFC v2 08/70] MIPS: asm: module: define MODULE_PROC_FAMILY for MIPS R6
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 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.1

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

* [PATCH RFC v2 09/70] MIPS: asm: stackframe: Do not preserve the HI/LO registers on MIPS R6
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 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.1

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

* [PATCH RFC v2 09/70] MIPS: asm: stackframe: Do not preserve the HI/LO registers on MIPS R6
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 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.1

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

* [PATCH RFC v2 10/70] MIPS: asm: asmmacro: Drop unused 'reg' argument on MIPSR2
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 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.1

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

* [PATCH RFC v2 10/70] MIPS: asm: asmmacro: Drop unused 'reg' argument on MIPSR2
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 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.1

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

* [PATCH RFC v2 11/70] MIPS: asm: asmmacro: Add MIPS R6 support to the simple EI/DI variants
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 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.1

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

* [PATCH RFC v2 11/70] MIPS: asm: asmmacro: Add MIPS R6 support to the simple EI/DI variants
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 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.1

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

* [PATCH RFC v2 12/70] MIPS: asm: asmmacro: Replace add instructions with "addui"
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Maciej W. Rozycki

The use of "add" instruction for immediate operations can result to
build failures for MIPS R6. This is because, the 'add' is a macro in
binutils and depending on the size of the immediate it can expand to
an 'addi' instruction which has been removed from MIPS R6.
Thus, we will be using the 'addu' macro instead, which also
accepts immediate operands.

Link: http://www.linux-mips.org/archives/linux-mips/2015-01/msg00121.html
Cc: Maciej W. Rozycki <macro@linux-mips.org>
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..42b90c9fd756 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
+	addu	$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
+	addu	$1, \base, \off
 	.word	STD_MSA_INSN | (\wd << 6)
 	.set	pop
 	.endm
-- 
2.2.1

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

* [PATCH RFC v2 12/70] MIPS: asm: asmmacro: Replace add instructions with "addui"
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Maciej W. Rozycki

The use of "add" instruction for immediate operations can result to
build failures for MIPS R6. This is because, the 'add' is a macro in
binutils and depending on the size of the immediate it can expand to
an 'addi' instruction which has been removed from MIPS R6.
Thus, we will be using the 'addu' macro instead, which also
accepts immediate operands.

Link: http://www.linux-mips.org/archives/linux-mips/2015-01/msg00121.html
Cc: Maciej W. Rozycki <macro@linux-mips.org>
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..42b90c9fd756 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
+	addu	$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
+	addu	$1, \base, \off
 	.word	STD_MSA_INSN | (\wd << 6)
 	.set	pop
 	.endm
-- 
2.2.1

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

* [PATCH RFC v2 13/70] MIPS: Use generic checksum functions for MIPS R6
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 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 72156ea62a69..3feabcb541c6 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1033,6 +1033,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
@@ -1311,6 +1314,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
@@ -1361,6 +1365,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 200efeac4181..526539cbc99f 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 17eaf0cf760c..ac66c30c8cd6 100644
--- a/arch/mips/kernel/mips_ksyms.c
+++ b/arch/mips/kernel/mips_ksyms.c
@@ -67,11 +67,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.1

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

* [PATCH RFC v2 13/70] MIPS: Use generic checksum functions for MIPS R6
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 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 72156ea62a69..3feabcb541c6 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1033,6 +1033,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
@@ -1311,6 +1314,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
@@ -1361,6 +1365,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 200efeac4181..526539cbc99f 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 17eaf0cf760c..ac66c30c8cd6 100644
--- a/arch/mips/kernel/mips_ksyms.c
+++ b/arch/mips/kernel/mips_ksyms.c
@@ -67,11 +67,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.1

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

* [PATCH RFC v2 14/70] MIPS: asm: cpu: Add MIPSR6 ISA definitions
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 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 | 16 ++++++++++++----
 arch/mips/include/asm/cpu.h          |  7 +++++--
 2 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h
index 2897cfafcaf0..aa2819526c42 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_mips64	(cpu_has_mips64r1 | cpu_has_mips64r2)
+#define cpu_has_mips32	(cpu_has_mips32r1 | cpu_has_mips32r2 | cpu_has_mips32r6)
+#define cpu_has_mips64	(cpu_has_mips64r1 | cpu_has_mips64r2 | cpu_has_mips64r6)
 #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 0b74bbf976e4..f604523aec3d 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -332,11 +332,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.1

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

* [PATCH RFC v2 14/70] MIPS: asm: cpu: Add MIPSR6 ISA definitions
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 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 | 16 ++++++++++++----
 arch/mips/include/asm/cpu.h          |  7 +++++--
 2 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h
index 2897cfafcaf0..aa2819526c42 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_mips64	(cpu_has_mips64r1 | cpu_has_mips64r2)
+#define cpu_has_mips32	(cpu_has_mips32r1 | cpu_has_mips32r2 | cpu_has_mips32r6)
+#define cpu_has_mips64	(cpu_has_mips64r1 | cpu_has_mips64r2 | cpu_has_mips64r6)
 #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 0b74bbf976e4..f604523aec3d 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -332,11 +332,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.1

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

* [PATCH RFC v2 15/70] MIPS: asm: hazards: Add MIPSR6 definitions
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 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 | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/arch/mips/include/asm/hazards.h b/arch/mips/include/asm/hazards.h
index e3ee92d4dbe7..0b1b7faf8e15 100644
--- a/arch/mips/include/asm/hazards.h
+++ b/arch/mips/include/asm/hazards.h
@@ -11,6 +11,7 @@
 #define _ASM_HAZARDS_H
 
 #include <linux/stringify.h>
+#include <asm/asm.h>
 
 #define ___ssnop							\
 	sll	$0, $0, 1
@@ -21,7 +22,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 +59,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 +133,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 +241,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.1

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

* [PATCH RFC v2 15/70] MIPS: asm: hazards: Add MIPSR6 definitions
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 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 | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/arch/mips/include/asm/hazards.h b/arch/mips/include/asm/hazards.h
index e3ee92d4dbe7..0b1b7faf8e15 100644
--- a/arch/mips/include/asm/hazards.h
+++ b/arch/mips/include/asm/hazards.h
@@ -11,6 +11,7 @@
 #define _ASM_HAZARDS_H
 
 #include <linux/stringify.h>
+#include <asm/asm.h>
 
 #define ___ssnop							\
 	sll	$0, $0, 1
@@ -21,7 +22,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 +59,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 +133,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 +241,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.1

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

* [PATCH RFC v2 16/70] MIPS: asm: irqflags: Add MIPS R6 related definitions
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 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 be777d9a3f85..272af8ac2425 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.1

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

* [PATCH RFC v2 16/70] MIPS: asm: irqflags: Add MIPS R6 related definitions
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 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 be777d9a3f85..272af8ac2425 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.1

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

* [PATCH RFC v2 17/70] MIPS: asm: r4kcache: Add MIPS R6 cache unroll functions
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 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 e293a8d89a6d..025b63540f5e 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"	\
 	:								\
@@ -147,7 +147,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"		\
@@ -218,6 +218,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"	\
@@ -322,6 +323,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.1

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

* [PATCH RFC v2 17/70] MIPS: asm: r4kcache: Add MIPS R6 cache unroll functions
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 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 e293a8d89a6d..025b63540f5e 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"	\
 	:								\
@@ -147,7 +147,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"		\
@@ -218,6 +218,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"	\
@@ -322,6 +323,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.1

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

* [PATCH RFC v2 18/70] MIPS: asm: spram: Add MIPS R6 related definitions
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 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 92987d1bbe5f..0862ae781339 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -53,6 +53,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.1

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

* [PATCH RFC v2 18/70] MIPS: asm: spram: Add MIPS R6 related definitions
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 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 92987d1bbe5f..0862ae781339 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -53,6 +53,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.1

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

* [PATCH RFC v2 19/70] MIPS: Use the new "ZC" constraint for MIPS R6
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Matthew Fortune

GCC versions supporting MIPS R6 use the ZC constraint to enforce a
9-bit offset for MIPS R6. We will use that for all MIPS R6 LL/SC
instructions.

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

diff --git a/arch/mips/include/asm/compiler.h b/arch/mips/include/asm/compiler.h
index c73815e0123a..8f8ed0245a09 100644
--- a/arch/mips/include/asm/compiler.h
+++ b/arch/mips/include/asm/compiler.h
@@ -16,12 +16,20 @@
 #define GCC_REG_ACCUM "accum"
 #endif
 
+#ifdef CONFIG_CPU_MIPSR6
+/*
+ * GCC uses ZC for MIPS R6 to indicate a 9-bit offset although
+ * the macro name is a bit misleading
+ */
+#define GCC_OFF12_ASM() "ZC"
+#else
 #ifndef CONFIG_CPU_MICROMIPS
 #define GCC_OFF12_ASM() "R"
 #elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
 #define GCC_OFF12_ASM() "ZC"
 #else
 #error "microMIPS compilation unsupported with GCC older than 4.9"
-#endif
+#endif /* CONFIG_CPU_MICROMIPS */
+#endif /* CONFIG_CPU_MIPSR6 */
 
 #endif /* _ASM_COMPILER_H */
-- 
2.2.1

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

* [PATCH RFC v2 19/70] MIPS: Use the new "ZC" constraint for MIPS R6
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Matthew Fortune

GCC versions supporting MIPS R6 use the ZC constraint to enforce a
9-bit offset for MIPS R6. We will use that for all MIPS R6 LL/SC
instructions.

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

diff --git a/arch/mips/include/asm/compiler.h b/arch/mips/include/asm/compiler.h
index c73815e0123a..8f8ed0245a09 100644
--- a/arch/mips/include/asm/compiler.h
+++ b/arch/mips/include/asm/compiler.h
@@ -16,12 +16,20 @@
 #define GCC_REG_ACCUM "accum"
 #endif
 
+#ifdef CONFIG_CPU_MIPSR6
+/*
+ * GCC uses ZC for MIPS R6 to indicate a 9-bit offset although
+ * the macro name is a bit misleading
+ */
+#define GCC_OFF12_ASM() "ZC"
+#else
 #ifndef CONFIG_CPU_MICROMIPS
 #define GCC_OFF12_ASM() "R"
 #elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
 #define GCC_OFF12_ASM() "ZC"
 #else
 #error "microMIPS compilation unsupported with GCC older than 4.9"
-#endif
+#endif /* CONFIG_CPU_MICROMIPS */
+#endif /* CONFIG_CPU_MIPSR6 */
 
 #endif /* _ASM_COMPILER_H */
-- 
2.2.1

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

* [PATCH RFC v2 20/70] MIPS: asm: cmpxchg: Update ISA constraints for MIPS R6 support
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Matthew Fortune

MIPS R6 changed the opcodes for LL/SC instructions so we need to set
the correct ISA.

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

diff --git a/arch/mips/include/asm/cmpxchg.h b/arch/mips/include/asm/cmpxchg.h
index 28b1edf19501..1ff5e5da8c8e 100644
--- a/arch/mips/include/asm/cmpxchg.h
+++ b/arch/mips/include/asm/cmpxchg.h
@@ -11,6 +11,7 @@
 #include <linux/bug.h>
 #include <linux/irqflags.h>
 #include <asm/compiler.h>
+#include <asm/asm.h>
 #include <asm/war.h>
 
 static inline unsigned long __xchg_u32(volatile int * m, unsigned int val)
@@ -39,11 +40,11 @@ static inline unsigned long __xchg_u32(volatile int * m, unsigned int val)
 
 		do {
 			__asm__ __volatile__(
-			"	.set	arch=r4000			\n"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
 			"	ll	%0, %3		# xchg_u32	\n"
 			"	.set	mips0				\n"
 			"	move	%2, %z4				\n"
-			"	.set	arch=r4000			\n"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
 			"	sc	%2, %1				\n"
 			"	.set	mips0				\n"
 			: "=&r" (retval), "=" GCC_OFF12_ASM() (*m),
@@ -90,7 +91,7 @@ static inline __u64 __xchg_u64(volatile __u64 * m, __u64 val)
 
 		do {
 			__asm__ __volatile__(
-			"	.set	arch=r4000			\n"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
 			"	lld	%0, %3		# xchg_u64	\n"
 			"	move	%2, %z4				\n"
 			"	scd	%2, %1				\n"
@@ -165,12 +166,12 @@ 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"	\
+		"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"	\
 		"1:	" ld "	%0, %2		# __cmpxchg_asm \n"	\
 		"	bne	%0, %z3, 2f			\n"	\
 		"	.set	mips0				\n"	\
 		"	move	$1, %z4				\n"	\
-		"	.set	arch=r4000			\n"	\
+		"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"	\
 		"	" st "	$1, %1				\n"	\
 		"	beqz	$1, 1b				\n"	\
 		"	.set	pop				\n"	\
-- 
2.2.1

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

* [PATCH RFC v2 20/70] MIPS: asm: cmpxchg: Update ISA constraints for MIPS R6 support
@ 2015-01-16 10:48   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:48 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Matthew Fortune

MIPS R6 changed the opcodes for LL/SC instructions so we need to set
the correct ISA.

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

diff --git a/arch/mips/include/asm/cmpxchg.h b/arch/mips/include/asm/cmpxchg.h
index 28b1edf19501..1ff5e5da8c8e 100644
--- a/arch/mips/include/asm/cmpxchg.h
+++ b/arch/mips/include/asm/cmpxchg.h
@@ -11,6 +11,7 @@
 #include <linux/bug.h>
 #include <linux/irqflags.h>
 #include <asm/compiler.h>
+#include <asm/asm.h>
 #include <asm/war.h>
 
 static inline unsigned long __xchg_u32(volatile int * m, unsigned int val)
@@ -39,11 +40,11 @@ static inline unsigned long __xchg_u32(volatile int * m, unsigned int val)
 
 		do {
 			__asm__ __volatile__(
-			"	.set	arch=r4000			\n"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
 			"	ll	%0, %3		# xchg_u32	\n"
 			"	.set	mips0				\n"
 			"	move	%2, %z4				\n"
-			"	.set	arch=r4000			\n"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
 			"	sc	%2, %1				\n"
 			"	.set	mips0				\n"
 			: "=&r" (retval), "=" GCC_OFF12_ASM() (*m),
@@ -90,7 +91,7 @@ static inline __u64 __xchg_u64(volatile __u64 * m, __u64 val)
 
 		do {
 			__asm__ __volatile__(
-			"	.set	arch=r4000			\n"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
 			"	lld	%0, %3		# xchg_u64	\n"
 			"	move	%2, %z4				\n"
 			"	scd	%2, %1				\n"
@@ -165,12 +166,12 @@ 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"	\
+		"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"	\
 		"1:	" ld "	%0, %2		# __cmpxchg_asm \n"	\
 		"	bne	%0, %z3, 2f			\n"	\
 		"	.set	mips0				\n"	\
 		"	move	$1, %z4				\n"	\
-		"	.set	arch=r4000			\n"	\
+		"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"	\
 		"	" st "	$1, %1				\n"	\
 		"	beqz	$1, 1b				\n"	\
 		"	.set	pop				\n"	\
-- 
2.2.1

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

* [PATCH RFC v2 21/70] MIPS: asm: atomic: Update ISA constraints for MIPS R6 support
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Matthew Fortune

MIPS R6 changed the opcodes for LL/SC instructions so we need to
set the correct ISA level.

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

diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h
index 857da84cfc92..be86ec65b573 100644
--- a/arch/mips/include/asm/atomic.h
+++ b/arch/mips/include/asm/atomic.h
@@ -16,6 +16,7 @@
 
 #include <linux/irqflags.h>
 #include <linux/types.h>
+#include <asm/asm.h>
 #include <asm/barrier.h>
 #include <asm/compiler.h>
 #include <asm/cpu-features.h>
@@ -61,7 +62,7 @@ static __inline__ void atomic_##op(int i, atomic_t * v)			      \
 									      \
 		do {							      \
 			__asm__ __volatile__(				      \
-			"	.set	arch=r4000			\n"   \
+			"	.set	"MIPS_ISA_LEVEL"		\n"   \
 			"	ll	%0, %1		# atomic_" #op "\n"   \
 			"	" #asm_op " %0, %2			\n"   \
 			"	sc	%0, %1				\n"   \
@@ -104,7 +105,7 @@ static __inline__ int atomic_##op##_return(int i, atomic_t * v)		      \
 									      \
 		do {							      \
 			__asm__ __volatile__(				      \
-			"	.set	arch=r4000			\n"   \
+			"	.set	"MIPS_ISA_LEVEL"		\n"   \
 			"	ll	%1, %2	# atomic_" #op "_return	\n"   \
 			"	" #asm_op " %0, %1, %3			\n"   \
 			"	sc	%0, %2				\n"   \
@@ -178,7 +179,7 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
 		int temp;
 
 		__asm__ __volatile__(
-		"	.set	arch=r4000				\n"
+		"	.set	"MIPS_ISA_LEVEL"			\n"
 		"1:	ll	%1, %2		# atomic_sub_if_positive\n"
 		"	subu	%0, %1, %3				\n"
 		"	bltz	%0, 1f					\n"
@@ -340,7 +341,7 @@ static __inline__ void atomic64_##op(long i, atomic64_t * v)		      \
 									      \
 		do {							      \
 			__asm__ __volatile__(				      \
-			"	.set	arch=r4000			\n"   \
+			"	.set	"MIPS_ISA_LEVEL"		\n"   \
 			"	lld	%0, %1		# atomic64_" #op "\n" \
 			"	" #asm_op " %0, %2			\n"   \
 			"	scd	%0, %1				\n"   \
@@ -383,7 +384,7 @@ static __inline__ long atomic64_##op##_return(long i, atomic64_t * v)	      \
 									      \
 		do {							      \
 			__asm__ __volatile__(				      \
-			"	.set	arch=r4000			\n"   \
+			"	.set	"MIPS_ISA_LEVEL"		\n"   \
 			"	lld	%1, %2	# atomic64_" #op "_return\n"  \
 			"	" #asm_op " %0, %1, %3			\n"   \
 			"	scd	%0, %2				\n"   \
@@ -459,7 +460,7 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
 		long temp;
 
 		__asm__ __volatile__(
-		"	.set	arch=r4000				\n"
+		"	.set	"MIPS_ISA_LEVEL"			\n"
 		"1:	lld	%1, %2		# atomic64_sub_if_positive\n"
 		"	dsubu	%0, %1, %3				\n"
 		"	bltz	%0, 1f					\n"
-- 
2.2.1

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

* [PATCH RFC v2 21/70] MIPS: asm: atomic: Update ISA constraints for MIPS R6 support
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Matthew Fortune

MIPS R6 changed the opcodes for LL/SC instructions so we need to
set the correct ISA level.

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

diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h
index 857da84cfc92..be86ec65b573 100644
--- a/arch/mips/include/asm/atomic.h
+++ b/arch/mips/include/asm/atomic.h
@@ -16,6 +16,7 @@
 
 #include <linux/irqflags.h>
 #include <linux/types.h>
+#include <asm/asm.h>
 #include <asm/barrier.h>
 #include <asm/compiler.h>
 #include <asm/cpu-features.h>
@@ -61,7 +62,7 @@ static __inline__ void atomic_##op(int i, atomic_t * v)			      \
 									      \
 		do {							      \
 			__asm__ __volatile__(				      \
-			"	.set	arch=r4000			\n"   \
+			"	.set	"MIPS_ISA_LEVEL"		\n"   \
 			"	ll	%0, %1		# atomic_" #op "\n"   \
 			"	" #asm_op " %0, %2			\n"   \
 			"	sc	%0, %1				\n"   \
@@ -104,7 +105,7 @@ static __inline__ int atomic_##op##_return(int i, atomic_t * v)		      \
 									      \
 		do {							      \
 			__asm__ __volatile__(				      \
-			"	.set	arch=r4000			\n"   \
+			"	.set	"MIPS_ISA_LEVEL"		\n"   \
 			"	ll	%1, %2	# atomic_" #op "_return	\n"   \
 			"	" #asm_op " %0, %1, %3			\n"   \
 			"	sc	%0, %2				\n"   \
@@ -178,7 +179,7 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
 		int temp;
 
 		__asm__ __volatile__(
-		"	.set	arch=r4000				\n"
+		"	.set	"MIPS_ISA_LEVEL"			\n"
 		"1:	ll	%1, %2		# atomic_sub_if_positive\n"
 		"	subu	%0, %1, %3				\n"
 		"	bltz	%0, 1f					\n"
@@ -340,7 +341,7 @@ static __inline__ void atomic64_##op(long i, atomic64_t * v)		      \
 									      \
 		do {							      \
 			__asm__ __volatile__(				      \
-			"	.set	arch=r4000			\n"   \
+			"	.set	"MIPS_ISA_LEVEL"		\n"   \
 			"	lld	%0, %1		# atomic64_" #op "\n" \
 			"	" #asm_op " %0, %2			\n"   \
 			"	scd	%0, %1				\n"   \
@@ -383,7 +384,7 @@ static __inline__ long atomic64_##op##_return(long i, atomic64_t * v)	      \
 									      \
 		do {							      \
 			__asm__ __volatile__(				      \
-			"	.set	arch=r4000			\n"   \
+			"	.set	"MIPS_ISA_LEVEL"		\n"   \
 			"	lld	%1, %2	# atomic64_" #op "_return\n"  \
 			"	" #asm_op " %0, %1, %3			\n"   \
 			"	scd	%0, %2				\n"   \
@@ -459,7 +460,7 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
 		long temp;
 
 		__asm__ __volatile__(
-		"	.set	arch=r4000				\n"
+		"	.set	"MIPS_ISA_LEVEL"			\n"
 		"1:	lld	%1, %2		# atomic64_sub_if_positive\n"
 		"	dsubu	%0, %1, %3				\n"
 		"	bltz	%0, 1f					\n"
-- 
2.2.1

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

* [PATCH RFC v2 22/70] MIPS: asm: bitops: Update ISA constraints for MIPS R6 support
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Matthew Fortune

MIPS R6 changed the opcodes for LL/SC instructions so we need to set
the correct ISA level.

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

diff --git a/arch/mips/include/asm/bitops.h b/arch/mips/include/asm/bitops.h
index 6663bcca9d0c..cc73fdccbff3 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/compiler.h>
@@ -81,7 +82,7 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
 		"	.set	mips0					\n"
 		: "=&r" (temp), "=" GCC_OFF12_ASM() (*m)
 		: "ir" (1UL << bit), GCC_OFF12_ASM() (*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__(
@@ -91,11 +92,11 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
 			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
 			: "ir" (bit), "r" (~0));
 		} 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"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
 			"	" __LL "%0, %1		# set_bit	\n"
 			"	or	%0, %2				\n"
 			"	" __SC	"%0, %1				\n"
@@ -133,7 +134,7 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
 		"	.set	mips0					\n"
 		: "=&r" (temp), "+" GCC_OFF12_ASM() (*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__(
@@ -143,11 +144,11 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
 			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
 			: "ir" (bit));
 		} 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"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
 			"	" __LL "%0, %1		# clear_bit	\n"
 			"	and	%0, %2				\n"
 			"	" __SC "%0, %1				\n"
@@ -205,7 +206,7 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
 
 		do {
 			__asm__ __volatile__(
-			"	.set	arch=r4000			\n"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
 			"	" __LL "%0, %1		# change_bit	\n"
 			"	xor	%0, %2				\n"
 			"	" __SC	"%0, %1				\n"
@@ -254,7 +255,7 @@ static inline int test_and_set_bit(unsigned long nr,
 
 		do {
 			__asm__ __volatile__(
-			"	.set	arch=r4000			\n"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
 			"	" __LL "%0, %1	# test_and_set_bit	\n"
 			"	or	%2, %0, %3			\n"
 			"	" __SC	"%2, %1				\n"
@@ -308,7 +309,7 @@ static inline int test_and_set_bit_lock(unsigned long nr,
 
 		do {
 			__asm__ __volatile__(
-			"	.set	arch=r4000			\n"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
 			"	" __LL "%0, %1	# test_and_set_bit	\n"
 			"	or	%2, %0, %3			\n"
 			"	" __SC	"%2, %1				\n"
@@ -358,7 +359,7 @@ static inline int test_and_clear_bit(unsigned long nr,
 		: "=&r" (temp), "+" GCC_OFF12_ASM() (*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;
@@ -380,7 +381,7 @@ static inline int test_and_clear_bit(unsigned long nr,
 
 		do {
 			__asm__ __volatile__(
-			"	.set	arch=r4000			\n"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
 			"	" __LL	"%0, %1 # test_and_clear_bit	\n"
 			"	or	%2, %0, %3			\n"
 			"	xor	%2, %3				\n"
@@ -437,7 +438,7 @@ static inline int test_and_change_bit(unsigned long nr,
 
 		do {
 			__asm__ __volatile__(
-			"	.set	arch=r4000			\n"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
 			"	" __LL	"%0, %1 # test_and_change_bit	\n"
 			"	xor	%2, %0, %3			\n"
 			"	" __SC	"\t%2, %1			\n"
@@ -485,7 +486,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)
@@ -498,7 +499,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)
@@ -562,7 +563,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.1

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

* [PATCH RFC v2 22/70] MIPS: asm: bitops: Update ISA constraints for MIPS R6 support
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Matthew Fortune

MIPS R6 changed the opcodes for LL/SC instructions so we need to set
the correct ISA level.

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

diff --git a/arch/mips/include/asm/bitops.h b/arch/mips/include/asm/bitops.h
index 6663bcca9d0c..cc73fdccbff3 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/compiler.h>
@@ -81,7 +82,7 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
 		"	.set	mips0					\n"
 		: "=&r" (temp), "=" GCC_OFF12_ASM() (*m)
 		: "ir" (1UL << bit), GCC_OFF12_ASM() (*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__(
@@ -91,11 +92,11 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
 			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
 			: "ir" (bit), "r" (~0));
 		} 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"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
 			"	" __LL "%0, %1		# set_bit	\n"
 			"	or	%0, %2				\n"
 			"	" __SC	"%0, %1				\n"
@@ -133,7 +134,7 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
 		"	.set	mips0					\n"
 		: "=&r" (temp), "+" GCC_OFF12_ASM() (*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__(
@@ -143,11 +144,11 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
 			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
 			: "ir" (bit));
 		} 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"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
 			"	" __LL "%0, %1		# clear_bit	\n"
 			"	and	%0, %2				\n"
 			"	" __SC "%0, %1				\n"
@@ -205,7 +206,7 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
 
 		do {
 			__asm__ __volatile__(
-			"	.set	arch=r4000			\n"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
 			"	" __LL "%0, %1		# change_bit	\n"
 			"	xor	%0, %2				\n"
 			"	" __SC	"%0, %1				\n"
@@ -254,7 +255,7 @@ static inline int test_and_set_bit(unsigned long nr,
 
 		do {
 			__asm__ __volatile__(
-			"	.set	arch=r4000			\n"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
 			"	" __LL "%0, %1	# test_and_set_bit	\n"
 			"	or	%2, %0, %3			\n"
 			"	" __SC	"%2, %1				\n"
@@ -308,7 +309,7 @@ static inline int test_and_set_bit_lock(unsigned long nr,
 
 		do {
 			__asm__ __volatile__(
-			"	.set	arch=r4000			\n"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
 			"	" __LL "%0, %1	# test_and_set_bit	\n"
 			"	or	%2, %0, %3			\n"
 			"	" __SC	"%2, %1				\n"
@@ -358,7 +359,7 @@ static inline int test_and_clear_bit(unsigned long nr,
 		: "=&r" (temp), "+" GCC_OFF12_ASM() (*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;
@@ -380,7 +381,7 @@ static inline int test_and_clear_bit(unsigned long nr,
 
 		do {
 			__asm__ __volatile__(
-			"	.set	arch=r4000			\n"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
 			"	" __LL	"%0, %1 # test_and_clear_bit	\n"
 			"	or	%2, %0, %3			\n"
 			"	xor	%2, %3				\n"
@@ -437,7 +438,7 @@ static inline int test_and_change_bit(unsigned long nr,
 
 		do {
 			__asm__ __volatile__(
-			"	.set	arch=r4000			\n"
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
 			"	" __LL	"%0, %1 # test_and_change_bit	\n"
 			"	xor	%2, %0, %3			\n"
 			"	" __SC	"\t%2, %1			\n"
@@ -485,7 +486,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)
@@ -498,7 +499,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)
@@ -562,7 +563,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.1

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

* [PATCH RFC v2 23/70] MIPS: asm: futex: Set the appropriate ISA level for MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Matthew Fortune

MIPS R6 changed the opcodes for LL/SC instructions so we need to set
the appropriate ISA level.

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

diff --git a/arch/mips/include/asm/futex.h b/arch/mips/include/asm/futex.h
index ef9987a61d88..9d06d266c22b 100644
--- a/arch/mips/include/asm/futex.h
+++ b/arch/mips/include/asm/futex.h
@@ -53,11 +53,11 @@
 		__asm__ __volatile__(					\
 		"	.set	push				\n"	\
 		"	.set	noat				\n"	\
-		"	.set	arch=r4000			\n"	\
+		"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"	\
 		"1:	"user_ll("%1", "%4")" # __futex_atomic_op\n"	\
 		"	.set	mips0				\n"	\
 		"	" insn	"				\n"	\
-		"	.set	arch=r4000			\n"	\
+		"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"	\
 		"2:	"user_sc("$1", "%2")"			\n"	\
 		"	beqz	$1, 1b				\n"	\
 		__WEAK_LLSC_MB						\
@@ -183,12 +183,12 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
 		"# futex_atomic_cmpxchg_inatomic			\n"
 		"	.set	push					\n"
 		"	.set	noat					\n"
-		"	.set	arch=r4000				\n"
+		"	.set	"MIPS_ISA_ARCH_LEVEL"			\n"
 		"1:	"user_ll("%1", "%3")"				\n"
 		"	bne	%1, %z4, 3f				\n"
 		"	.set	mips0					\n"
 		"	move	$1, %z5					\n"
-		"	.set	arch=r4000				\n"
+		"	.set	"MIPS_ISA_ARCH_LEVEL"			\n"
 		"2:	"user_sc("$1", "%2")"				\n"
 		"	beqz	$1, 1b					\n"
 		__WEAK_LLSC_MB
-- 
2.2.1

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

* [PATCH RFC v2 23/70] MIPS: asm: futex: Set the appropriate ISA level for MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Matthew Fortune

MIPS R6 changed the opcodes for LL/SC instructions so we need to set
the appropriate ISA level.

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

diff --git a/arch/mips/include/asm/futex.h b/arch/mips/include/asm/futex.h
index ef9987a61d88..9d06d266c22b 100644
--- a/arch/mips/include/asm/futex.h
+++ b/arch/mips/include/asm/futex.h
@@ -53,11 +53,11 @@
 		__asm__ __volatile__(					\
 		"	.set	push				\n"	\
 		"	.set	noat				\n"	\
-		"	.set	arch=r4000			\n"	\
+		"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"	\
 		"1:	"user_ll("%1", "%4")" # __futex_atomic_op\n"	\
 		"	.set	mips0				\n"	\
 		"	" insn	"				\n"	\
-		"	.set	arch=r4000			\n"	\
+		"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"	\
 		"2:	"user_sc("$1", "%2")"			\n"	\
 		"	beqz	$1, 1b				\n"	\
 		__WEAK_LLSC_MB						\
@@ -183,12 +183,12 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
 		"# futex_atomic_cmpxchg_inatomic			\n"
 		"	.set	push					\n"
 		"	.set	noat					\n"
-		"	.set	arch=r4000				\n"
+		"	.set	"MIPS_ISA_ARCH_LEVEL"			\n"
 		"1:	"user_ll("%1", "%3")"				\n"
 		"	bne	%1, %z4, 3f				\n"
 		"	.set	mips0					\n"
 		"	move	$1, %z5					\n"
-		"	.set	arch=r4000				\n"
+		"	.set	"MIPS_ISA_ARCH_LEVEL"			\n"
 		"2:	"user_sc("$1", "%2")"				\n"
 		"	beqz	$1, 1b					\n"
 		__WEAK_LLSC_MB
-- 
2.2.1

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

* [PATCH RFC v2 24/70] MIPS: asm: spinlock: Replace sub instruction with addiu
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 c6d06d383ef9..500050d3bda6 100644
--- a/arch/mips/include/asm/spinlock.h
+++ b/arch/mips/include/asm/spinlock.h
@@ -276,7 +276,7 @@ static inline void arch_read_unlock(arch_rwlock_t *rw)
 		do {
 			__asm__ __volatile__(
 			"1:	ll	%1, %2	# arch_read_unlock	\n"
-			"	sub	%1, 1				\n"
+			"	addiu	%1, -1				\n"
 			"	sc	%1, %0				\n"
 			: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
 			: GCC_OFF12_ASM() (rw->lock)
-- 
2.2.1

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

* [PATCH RFC v2 24/70] MIPS: asm: spinlock: Replace sub instruction with addiu
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 c6d06d383ef9..500050d3bda6 100644
--- a/arch/mips/include/asm/spinlock.h
+++ b/arch/mips/include/asm/spinlock.h
@@ -276,7 +276,7 @@ static inline void arch_read_unlock(arch_rwlock_t *rw)
 		do {
 			__asm__ __volatile__(
 			"1:	ll	%1, %2	# arch_read_unlock	\n"
-			"	sub	%1, 1				\n"
+			"	addiu	%1, -1				\n"
 			"	sc	%1, %0				\n"
 			: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
 			: GCC_OFF12_ASM() (rw->lock)
-- 
2.2.1

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

* [PATCH RFC v2 25/70] MIPS: asm: local: Set the appropriate ISA level for MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Matthew Fortune

MIPS R6 changed the opcodes for LL/SC instructions so we need to set
the appropriate ISA level.

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

diff --git a/arch/mips/include/asm/local.h b/arch/mips/include/asm/local.h
index 46dfc3c1fd49..ff8c94837995 100644
--- a/arch/mips/include/asm/local.h
+++ b/arch/mips/include/asm/local.h
@@ -47,7 +47,7 @@ static __inline__ long local_add_return(long i, local_t * l)
 		unsigned long temp;
 
 		__asm__ __volatile__(
-		"	.set	arch=r4000				\n"
+		"	.set	"MIPS_ISA_ARCH_LEVEL"			\n"
 		"1:"	__LL	"%1, %2		# local_add_return	\n"
 		"	addu	%0, %1, %3				\n"
 			__SC	"%0, %2					\n"
@@ -92,7 +92,7 @@ static __inline__ long local_sub_return(long i, local_t * l)
 		unsigned long temp;
 
 		__asm__ __volatile__(
-		"	.set	arch=r4000				\n"
+		"	.set	"MIPS_ISA_ARCH_LEVEL"			\n"
 		"1:"	__LL	"%1, %2		# local_sub_return	\n"
 		"	subu	%0, %1, %3				\n"
 			__SC	"%0, %2					\n"
-- 
2.2.1

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

* [PATCH RFC v2 25/70] MIPS: asm: local: Set the appropriate ISA level for MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Matthew Fortune

MIPS R6 changed the opcodes for LL/SC instructions so we need to set
the appropriate ISA level.

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

diff --git a/arch/mips/include/asm/local.h b/arch/mips/include/asm/local.h
index 46dfc3c1fd49..ff8c94837995 100644
--- a/arch/mips/include/asm/local.h
+++ b/arch/mips/include/asm/local.h
@@ -47,7 +47,7 @@ static __inline__ long local_add_return(long i, local_t * l)
 		unsigned long temp;
 
 		__asm__ __volatile__(
-		"	.set	arch=r4000				\n"
+		"	.set	"MIPS_ISA_ARCH_LEVEL"			\n"
 		"1:"	__LL	"%1, %2		# local_add_return	\n"
 		"	addu	%0, %1, %3				\n"
 			__SC	"%0, %2					\n"
@@ -92,7 +92,7 @@ static __inline__ long local_sub_return(long i, local_t * l)
 		unsigned long temp;
 
 		__asm__ __volatile__(
-		"	.set	arch=r4000				\n"
+		"	.set	"MIPS_ISA_ARCH_LEVEL"			\n"
 		"1:"	__LL	"%1, %2		# local_sub_return	\n"
 		"	subu	%0, %1, %3				\n"
 			__SC	"%0, %2					\n"
-- 
2.2.1

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

* [PATCH RFC v2 26/70] MIPS: kernel: cpu-bugs64: Do not check R6 cores for existing 64-bit bugs
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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.1

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

* [PATCH RFC v2 26/70] MIPS: kernel: cpu-bugs64: Do not check R6 cores for existing 64-bit bugs
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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.1

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

* [PATCH RFC v2 27/70] MIPS: kernel: cevt-r4k: Add MIPS R6 to the c0_compare_interrupt handler
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 6acaad0480af..6684b042a29a 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.1

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

* [PATCH RFC v2 27/70] MIPS: kernel: cevt-r4k: Add MIPS R6 to the c0_compare_interrupt handler
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 6acaad0480af..6684b042a29a 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.1

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

* [PATCH RFC v2 28/70] MIPS: kernel: cpu-probe.c: Add support for MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index cc77fdaca0eb..328b61f63430 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -237,6 +237,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:
@@ -326,6 +333,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;
 		}
@@ -338,6 +348,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;
 		}
@@ -541,7 +554,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;
@@ -1351,7 +1364,8 @@ void cpu_probe(void)
 		c->fpu_id = cpu_get_fpu_id();
 
 		if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M32R2 |
-				    MIPS_CPU_ISA_M64R1 | MIPS_CPU_ISA_M64R2)) {
+				    MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R1 |
+				    MIPS_CPU_ISA_M64R2 | MIPS_CPU_ISA_M64R6)) {
 			if (c->fpu_id & MIPS_FPIR_3D)
 				c->ases |= MIPS_ASE_MIPS3D;
 			if (c->fpu_id & MIPS_FPIR_FREP)
@@ -1359,7 +1373,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.1

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

* [PATCH RFC v2 28/70] MIPS: kernel: cpu-probe.c: Add support for MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index cc77fdaca0eb..328b61f63430 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -237,6 +237,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:
@@ -326,6 +333,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;
 		}
@@ -338,6 +348,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;
 		}
@@ -541,7 +554,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;
@@ -1351,7 +1364,8 @@ void cpu_probe(void)
 		c->fpu_id = cpu_get_fpu_id();
 
 		if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M32R2 |
-				    MIPS_CPU_ISA_M64R1 | MIPS_CPU_ISA_M64R2)) {
+				    MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R1 |
+				    MIPS_CPU_ISA_M64R2 | MIPS_CPU_ISA_M64R6)) {
 			if (c->fpu_id & MIPS_FPIR_3D)
 				c->ases |= MIPS_ASE_MIPS3D;
 			if (c->fpu_id & MIPS_FPIR_FREP)
@@ -1359,7 +1373,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.1

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

* [PATCH RFC v2 29/70] MIPS: kernel: entry.S: Add MIPS R6 related definitions
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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.1

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

* [PATCH RFC v2 29/70] MIPS: kernel: entry.S: Add MIPS R6 related definitions
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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.1

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

* [PATCH RFC v2 30/70] MIPS: kernel: proc: Add MIPS R6 support to /proc/cpuinfo
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
index 097fc8d14e42..a8fdf9685cad 100644
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -82,7 +82,9 @@ static int show_cpuinfo(struct seq_file *m, void *v)
 		seq_printf(m, "]\n");
 	}
 
-	seq_printf(m, "isa\t\t\t: mips1");
+	seq_printf(m, "isa\t\t\t:"); 
+	if (!cpu_has_mips_r6)
+		seq_printf(m, " mips1");
 	if (cpu_has_mips_2)
 		seq_printf(m, "%s", " mips2");
 	if (cpu_has_mips_3)
@@ -95,10 +97,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.1

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

* [PATCH RFC v2 30/70] MIPS: kernel: proc: Add MIPS R6 support to /proc/cpuinfo
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
index 097fc8d14e42..a8fdf9685cad 100644
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -82,7 +82,9 @@ static int show_cpuinfo(struct seq_file *m, void *v)
 		seq_printf(m, "]\n");
 	}
 
-	seq_printf(m, "isa\t\t\t: mips1");
+	seq_printf(m, "isa\t\t\t:"); 
+	if (!cpu_has_mips_r6)
+		seq_printf(m, " mips1");
 	if (cpu_has_mips_2)
 		seq_printf(m, "%s", " mips2");
 	if (cpu_has_mips_3)
@@ -95,10 +97,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.1

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

* [PATCH RFC v2 31/70] MIPS: kernel: traps: Add MIPS R6 related definitions
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 461653ea28c8..81cface72bb0 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1649,7 +1649,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 " : "",
@@ -1689,7 +1689,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());
@@ -1978,7 +1978,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)
@@ -2022,7 +2022,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;
@@ -2113,7 +2113,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.1

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

* [PATCH RFC v2 31/70] MIPS: kernel: traps: Add MIPS R6 related definitions
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 461653ea28c8..81cface72bb0 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1649,7 +1649,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 " : "",
@@ -1689,7 +1689,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());
@@ -1978,7 +1978,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)
@@ -2022,7 +2022,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;
@@ -2113,7 +2113,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.1

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

* [PATCH RFC v2 32/70] MIPS: kernel: r4k_switch: Add support for MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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    | 14 ++++++++------
 2 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h
index 42b90c9fd756..628a6fbd5e20 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..3b1a36f13a7d 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,9 +242,9 @@ 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    MIPS_ISA_LEVEL_RAW
 	.set	fp=64
 	sll     t0, t0, 5			# is Status.FR set?
 	bgez    t0, 1f				# no: skip setting upper 32b
@@ -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.1

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

* [PATCH RFC v2 32/70] MIPS: kernel: r4k_switch: Add support for MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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    | 14 ++++++++------
 2 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h
index 42b90c9fd756..628a6fbd5e20 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..3b1a36f13a7d 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,9 +242,9 @@ 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    MIPS_ISA_LEVEL_RAW
 	.set	fp=64
 	sll     t0, t0, 5			# is Status.FR set?
 	bgez    t0, 1f				# no: skip setting upper 32b
@@ -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.1

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

* [PATCH RFC v2 33/70] MIPS: kernel: r4k_fpu: Add support for MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/arch/mips/kernel/r4k_fpu.S b/arch/mips/kernel/r4k_fpu.S
index 6c160c67984c..676c5030a953 100644
--- a/arch/mips/kernel/r4k_fpu.S
+++ b/arch/mips/kernel/r4k_fpu.S
@@ -34,7 +34,7 @@
 	.endm
 
 	.set	noreorder
-	.set	arch=r4000
+	.set	MIPS_ISA_ARCH_LEVEL_RAW
 
 LEAF(_save_fp_context)
 	.set	push
@@ -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.1

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

* [PATCH RFC v2 33/70] MIPS: kernel: r4k_fpu: Add support for MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/arch/mips/kernel/r4k_fpu.S b/arch/mips/kernel/r4k_fpu.S
index 6c160c67984c..676c5030a953 100644
--- a/arch/mips/kernel/r4k_fpu.S
+++ b/arch/mips/kernel/r4k_fpu.S
@@ -34,7 +34,7 @@
 	.endm
 
 	.set	noreorder
-	.set	arch=r4000
+	.set	MIPS_ISA_ARCH_LEVEL_RAW
 
 LEAF(_save_fp_context)
 	.set	push
@@ -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.1

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

* [PATCH RFC v2 34/70] MIPS: kernel: genex: Set correct ISA level
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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.1

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

* [PATCH RFC v2 34/70] MIPS: kernel: genex: Set correct ISA level
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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.1

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

* [PATCH RFC v2 35/70] MIPS: kernel: cps-vec: Replace addi with addiu
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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.1

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

* [PATCH RFC v2 35/70] MIPS: kernel: cps-vec: Replace addi with addiu
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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.1

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

* [PATCH RFC v2 36/70] MIPS: kernel: unaligned: Add support for the MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

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

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: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
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 e11906dff885..c580b8c12f6f 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_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_op:
 		cu2_notifier_call_chain(CU2_SDC2_OP, regs);
 		break;
-
+#endif
 	default:
 		/*
 		 * Pheeee...  We encountered an yet unknown instruction or
-- 
2.2.1

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

* [PATCH RFC v2 36/70] MIPS: kernel: unaligned: Add support for the MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

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

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: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
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 e11906dff885..c580b8c12f6f 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_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_op:
 		cu2_notifier_call_chain(CU2_SDC2_OP, regs);
 		break;
-
+#endif
 	default:
 		/*
 		 * Pheeee...  We encountered an yet unknown instruction or
-- 
2.2.1

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

* [PATCH RFC v2 37/70] MIPS: kernel: syscall: Set the appropriate ISA level for MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Matthew Fortune

MIPS R6 changed the opcodes for LL/SC instructions so we need to set
the appropriate ISA level.

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

diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
index 604b558809c4..53a7ef9a8f32 100644
--- a/arch/mips/kernel/syscall.c
+++ b/arch/mips/kernel/syscall.c
@@ -136,7 +136,7 @@ static inline int mips_atomic_set(unsigned long addr, unsigned long new)
 		: "memory");
 	} else if (cpu_has_llsc) {
 		__asm__ __volatile__ (
-		"	.set	arch=r4000				\n"
+		"	.set	"MIPS_ISA_ARCH_LEVEL"			\n"
 		"	li	%[err], 0				\n"
 		"1:	ll	%[old], (%[addr])			\n"
 		"	move	%[tmp], %[new]				\n"
-- 
2.2.1

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

* [PATCH RFC v2 37/70] MIPS: kernel: syscall: Set the appropriate ISA level for MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Matthew Fortune

MIPS R6 changed the opcodes for LL/SC instructions so we need to set
the appropriate ISA level.

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

diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
index 604b558809c4..53a7ef9a8f32 100644
--- a/arch/mips/kernel/syscall.c
+++ b/arch/mips/kernel/syscall.c
@@ -136,7 +136,7 @@ static inline int mips_atomic_set(unsigned long addr, unsigned long new)
 		: "memory");
 	} else if (cpu_has_llsc) {
 		__asm__ __volatile__ (
-		"	.set	arch=r4000				\n"
+		"	.set	"MIPS_ISA_ARCH_LEVEL"			\n"
 		"	li	%[err], 0				\n"
 		"1:	ll	%[old], (%[addr])			\n"
 		"	move	%[tmp], %[new]				\n"
-- 
2.2.1

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

* [PATCH RFC v2 38/70] MIPS: lib: memcpy: Add MIPS R6 support
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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.1

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

* [PATCH RFC v2 38/70] MIPS: lib: memcpy: Add MIPS R6 support
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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.1

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

* [PATCH RFC v2 39/70] MIPS: lib: memset: Add MIPS R6 support
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 c8fe6b1968fb..d542650d4fb7 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 */
@@ -120,6 +121,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 */
@@ -159,6 +184,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__
@@ -166,6 +192,22 @@
 #else
 	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
 
@@ -186,6 +228,11 @@
 	.hidden __memset
 	.endif
 
+.Lbyte_fixup\@:
+	PTR_SUBU	a2, $0, t0
+	jr		ra
+	 PTR_ADDIU	a2, 1
+
 .Lfirst_fixup\@:
 	jr	ra
 	nop
-- 
2.2.1

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

* [PATCH RFC v2 39/70] MIPS: lib: memset: Add MIPS R6 support
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 c8fe6b1968fb..d542650d4fb7 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 */
@@ -120,6 +121,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 */
@@ -159,6 +184,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__
@@ -166,6 +192,22 @@
 #else
 	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
 
@@ -186,6 +228,11 @@
 	.hidden __memset
 	.endif
 
+.Lbyte_fixup\@:
+	PTR_SUBU	a2, $0, t0
+	jr		ra
+	 PTR_ADDIU	a2, 1
+
 .Lfirst_fixup\@:
 	jr	ra
 	nop
-- 
2.2.1

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

* [PATCH RFC v2 40/70] MIPS: mm: page: Add MIPS R6 support
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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..b84e0b2ce140 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 < -0x100))	\
+		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.1

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

* [PATCH RFC v2 40/70] MIPS: mm: page: Add MIPS R6 support
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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..b84e0b2ce140 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 < -0x100))	\
+		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.1

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

* [PATCH RFC v2 41/70] MIPS: mm: tlbex: Use cpu_has_mips_r2_exec_hazard for the EHB instruction
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

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

MIPS uses the cpu_has_mips_r2_exec_hazard macro to determine whether the
EHB instruction is available or not. This is necessary for MIPS R6
which also supports the EHB instruction.

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

diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index ff8d99ce3b9b..d75ff73a2012 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_exec_hazard) {
 		/*
 		 * The architecture spec says an ehb is required here,
 		 * but a number of cores do not have the hazard and
@@ -1953,7 +1953,7 @@ static void build_r4000_tlb_load_handler(void)
 
 		switch (current_cpu_type()) {
 		default:
-			if (cpu_has_mips_r2) {
+			if (cpu_has_mips_r2_exec_hazard) {
 				uasm_i_ehb(&p);
 
 		case CPU_CAVIUM_OCTEON:
@@ -2020,7 +2020,7 @@ static void build_r4000_tlb_load_handler(void)
 
 		switch (current_cpu_type()) {
 		default:
-			if (cpu_has_mips_r2) {
+			if (cpu_has_mips_r2_exec_hazard) {
 				uasm_i_ehb(&p);
 
 		case CPU_CAVIUM_OCTEON:
-- 
2.2.1

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

* [PATCH RFC v2 41/70] MIPS: mm: tlbex: Use cpu_has_mips_r2_exec_hazard for the EHB instruction
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 UTC (permalink / raw)
  To: linux-mips; +Cc: Leonid Yegoshin, Markos Chandras

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

MIPS uses the cpu_has_mips_r2_exec_hazard macro to determine whether the
EHB instruction is available or not. This is necessary for MIPS R6
which also supports the EHB instruction.

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

diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index ff8d99ce3b9b..d75ff73a2012 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_exec_hazard) {
 		/*
 		 * The architecture spec says an ehb is required here,
 		 * but a number of cores do not have the hazard and
@@ -1953,7 +1953,7 @@ static void build_r4000_tlb_load_handler(void)
 
 		switch (current_cpu_type()) {
 		default:
-			if (cpu_has_mips_r2) {
+			if (cpu_has_mips_r2_exec_hazard) {
 				uasm_i_ehb(&p);
 
 		case CPU_CAVIUM_OCTEON:
@@ -2020,7 +2020,7 @@ static void build_r4000_tlb_load_handler(void)
 
 		switch (current_cpu_type()) {
 		default:
-			if (cpu_has_mips_r2) {
+			if (cpu_has_mips_r2_exec_hazard) {
 				uasm_i_ehb(&p);
 
 		case CPU_CAVIUM_OCTEON:
-- 
2.2.1

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

* [PATCH RFC v2 42/70] MIPS: mm: c-r4k: Set the correct ISA level
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 b806deb29e63..7ecee761ae2d 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.1

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

* [PATCH RFC v2 42/70] MIPS: mm: c-r4k: Set the correct ISA level
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 b806deb29e63..7ecee761ae2d 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.1

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

* [PATCH RFC v2 43/70] MIPS: mm: scache: Add secondary cache support for MIPS R6 cores
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

The secondary cache initialization and configuration code is processor
specific so we need to handle MIPS R6 cores as well.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/mm/c-r4k.c   | 3 ++-
 arch/mips/mm/sc-mips.c | 3 ++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index 7ecee761ae2d..3f8059602765 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -1473,7 +1473,8 @@ static void setup_scache(void)
 
 	default:
 		if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M32R2 |
-				    MIPS_CPU_ISA_M64R1 | MIPS_CPU_ISA_M64R2)) {
+				    MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R1 |
+				    MIPS_CPU_ISA_M64R2 | MIPS_CPU_ISA_M64R6)) {
 #ifdef CONFIG_MIPS_CPU_SCACHE
 			if (mips_sc_init ()) {
 				scache_size = c->scache.ways * c->scache.sets * c->scache.linesz;
diff --git a/arch/mips/mm/sc-mips.c b/arch/mips/mm/sc-mips.c
index fd9b5d45e91b..4ceafd13870c 100644
--- a/arch/mips/mm/sc-mips.c
+++ b/arch/mips/mm/sc-mips.c
@@ -105,7 +105,8 @@ static inline int __init mips_sc_probe(void)
 
 	/* Ignore anything but MIPSxx processors */
 	if (!(c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M32R2 |
-			      MIPS_CPU_ISA_M64R1 | MIPS_CPU_ISA_M64R2)))
+			      MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R1 |
+			      MIPS_CPU_ISA_M64R2 | MIPS_CPU_ISA_M64R6)))
 		return 0;
 
 	/* Does this MIPS32/MIPS64 CPU have a config2 register? */
-- 
2.2.1

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

* [PATCH RFC v2 43/70] MIPS: mm: scache: Add secondary cache support for MIPS R6 cores
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

The secondary cache initialization and configuration code is processor
specific so we need to handle MIPS R6 cores as well.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/mm/c-r4k.c   | 3 ++-
 arch/mips/mm/sc-mips.c | 3 ++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index 7ecee761ae2d..3f8059602765 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -1473,7 +1473,8 @@ static void setup_scache(void)
 
 	default:
 		if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M32R2 |
-				    MIPS_CPU_ISA_M64R1 | MIPS_CPU_ISA_M64R2)) {
+				    MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R1 |
+				    MIPS_CPU_ISA_M64R2 | MIPS_CPU_ISA_M64R6)) {
 #ifdef CONFIG_MIPS_CPU_SCACHE
 			if (mips_sc_init ()) {
 				scache_size = c->scache.ways * c->scache.sets * c->scache.linesz;
diff --git a/arch/mips/mm/sc-mips.c b/arch/mips/mm/sc-mips.c
index fd9b5d45e91b..4ceafd13870c 100644
--- a/arch/mips/mm/sc-mips.c
+++ b/arch/mips/mm/sc-mips.c
@@ -105,7 +105,8 @@ static inline int __init mips_sc_probe(void)
 
 	/* Ignore anything but MIPSxx processors */
 	if (!(c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M32R2 |
-			      MIPS_CPU_ISA_M64R1 | MIPS_CPU_ISA_M64R2)))
+			      MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R1 |
+			      MIPS_CPU_ISA_M64R2 | MIPS_CPU_ISA_M64R6)))
 		return 0;
 
 	/* Does this MIPS32/MIPS64 CPU have a config2 register? */
-- 
2.2.1

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

* [PATCH RFC v2 44/70] MIPS: kernel: Prepare the JR instruction for emulation on MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

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

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/branch.h | 3 +++
 arch/mips/kernel/branch.c      | 5 +++++
 arch/mips/math-emu/cp1emu.c    | 3 +++
 3 files changed, 11 insertions(+)

diff --git a/arch/mips/include/asm/branch.h b/arch/mips/include/asm/branch.h
index de781cf54bc7..2894ea58454d 100644
--- a/arch/mips/include/asm/branch.h
+++ b/arch/mips/include/asm/branch.h
@@ -13,6 +13,9 @@
 #include <asm/ptrace.h>
 #include <asm/inst.h>
 
+static int mipsr2_emulation = 0;
+#define NO_R6EMU	(cpu_has_mips_r6 && !mipsr2_emulation)
+
 extern int __isa_exception_epc(struct pt_regs *regs);
 extern int __compute_return_epc(struct pt_regs *regs);
 extern int __compute_return_epc_for_insn(struct pt_regs *regs,
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 4d7d99d601cc..9b622ca391d8 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -417,6 +417,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;
 		}
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 9dfcd7fc1bc3..9707af43913f 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -448,6 +448,9 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 				dec_insn.next_pc_inc;
 			/* Fall through */
 		case jr_op:
+			/* For R6, JR already emulated in jalr_op */
+			if (NO_R6EMU && (insn.r_format.opcode == jr_op))
+				break;
 			*contpc = regs->regs[insn.r_format.rs];
 			return 1;
 		}
-- 
2.2.1

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

* [PATCH RFC v2 44/70] MIPS: kernel: Prepare the JR instruction for emulation on MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

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

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/branch.h | 3 +++
 arch/mips/kernel/branch.c      | 5 +++++
 arch/mips/math-emu/cp1emu.c    | 3 +++
 3 files changed, 11 insertions(+)

diff --git a/arch/mips/include/asm/branch.h b/arch/mips/include/asm/branch.h
index de781cf54bc7..2894ea58454d 100644
--- a/arch/mips/include/asm/branch.h
+++ b/arch/mips/include/asm/branch.h
@@ -13,6 +13,9 @@
 #include <asm/ptrace.h>
 #include <asm/inst.h>
 
+static int mipsr2_emulation = 0;
+#define NO_R6EMU	(cpu_has_mips_r6 && !mipsr2_emulation)
+
 extern int __isa_exception_epc(struct pt_regs *regs);
 extern int __compute_return_epc(struct pt_regs *regs);
 extern int __compute_return_epc_for_insn(struct pt_regs *regs,
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 4d7d99d601cc..9b622ca391d8 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -417,6 +417,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;
 		}
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 9dfcd7fc1bc3..9707af43913f 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -448,6 +448,9 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 				dec_insn.next_pc_inc;
 			/* Fall through */
 		case jr_op:
+			/* For R6, JR already emulated in jalr_op */
+			if (NO_R6EMU && (insn.r_format.opcode == jr_op))
+				break;
 			*contpc = regs->regs[insn.r_format.rs];
 			return 1;
 		}
-- 
2.2.1

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

* [PATCH RFC v2 45/70] MIPS: kernel: branch: Prevent BLTZL emulation for MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 +++++
 arch/mips/math-emu/cp1emu.c | 2 ++
 2 files changed, 7 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 9b622ca391d8..502bf2aeb834 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -436,6 +436,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)
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 9707af43913f..e70513d552f6 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -465,6 +465,8 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 			/* Fall through */
 		case bltz_op:
 		case bltzl_op:
+			if (NO_R6EMU && (insn.i_format.rt == bltzl_op))
+				break;
 			if ((long)regs->regs[insn.i_format.rs] < 0)
 				*contpc = regs->cp0_epc +
 					dec_insn.pc_inc +
-- 
2.2.1

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

* [PATCH RFC v2 45/70] MIPS: kernel: branch: Prevent BLTZL emulation for MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 +++++
 arch/mips/math-emu/cp1emu.c | 2 ++
 2 files changed, 7 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 9b622ca391d8..502bf2aeb834 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -436,6 +436,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)
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 9707af43913f..e70513d552f6 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -465,6 +465,8 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 			/* Fall through */
 		case bltz_op:
 		case bltzl_op:
+			if (NO_R6EMU && (insn.i_format.rt == bltzl_op))
+				break;
 			if ((long)regs->regs[insn.i_format.rs] < 0)
 				*contpc = regs->cp0_epc +
 					dec_insn.pc_inc +
-- 
2.2.1

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

* [PATCH RFC v2 46/70] MIPS: kernel: branch: Prevent BGEZL emulation for MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 +++++
 arch/mips/math-emu/cp1emu.c | 2 ++
 2 files changed, 7 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 502bf2aeb834..b8cc0a2e20a4 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -452,6 +452,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)
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index e70513d552f6..4028d536cd1c 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -484,6 +484,8 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 			/* Fall through */
 		case bgez_op:
 		case bgezl_op:
+			if (NO_R6EMU && (insn.i_format.rt == bgezl_op))
+				break;
 			if ((long)regs->regs[insn.i_format.rs] >= 0)
 				*contpc = regs->cp0_epc +
 					dec_insn.pc_inc +
-- 
2.2.1

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

* [PATCH RFC v2 46/70] MIPS: kernel: branch: Prevent BGEZL emulation for MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 +++++
 arch/mips/math-emu/cp1emu.c | 2 ++
 2 files changed, 7 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 502bf2aeb834..b8cc0a2e20a4 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -452,6 +452,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)
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index e70513d552f6..4028d536cd1c 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -484,6 +484,8 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 			/* Fall through */
 		case bgez_op:
 		case bgezl_op:
+			if (NO_R6EMU && (insn.i_format.rt == bgezl_op))
+				break;
 			if ((long)regs->regs[insn.i_format.rs] >= 0)
 				*contpc = regs->cp0_epc +
 					dec_insn.pc_inc +
-- 
2.2.1

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

* [PATCH RFC v2 47/70] MIPS: kernel: branch: Prevent BLTZAL emulation for MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 ++++++++++++++++++++++
 arch/mips/math-emu/cp1emu.c |  4 ++++
 2 files changed, 26 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index b8cc0a2e20a4..311a2223da59 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -468,7 +468,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)
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 4028d536cd1c..5429efe24d5a 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -459,6 +459,10 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 		switch (insn.i_format.rt) {
 		case bltzal_op:
 		case bltzall_op:
+			if (NO_R6EMU && (insn.i_format.rs ||
+			    insn.i_format.rt == bltzall_op))
+				break;
+
 			regs->regs[31] = regs->cp0_epc +
 				dec_insn.pc_inc +
 				dec_insn.next_pc_inc;
-- 
2.2.1

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

* [PATCH RFC v2 47/70] MIPS: kernel: branch: Prevent BLTZAL emulation for MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 ++++++++++++++++++++++
 arch/mips/math-emu/cp1emu.c |  4 ++++
 2 files changed, 26 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index b8cc0a2e20a4..311a2223da59 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -468,7 +468,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)
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 4028d536cd1c..5429efe24d5a 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -459,6 +459,10 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 		switch (insn.i_format.rt) {
 		case bltzal_op:
 		case bltzall_op:
+			if (NO_R6EMU && (insn.i_format.rs ||
+			    insn.i_format.rt == bltzall_op))
+				break;
+
 			regs->regs[31] = regs->cp0_epc +
 				dec_insn.pc_inc +
 				dec_insn.next_pc_inc;
-- 
2.2.1

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

* [PATCH RFC v2 48/70] MIPS: kernel: branch: Prevent BGEZAL emulation for MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 ++++++++++++++++++++++
 arch/mips/math-emu/cp1emu.c |  4 ++++
 2 files changed, 26 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 311a2223da59..2273307f7c51 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -502,7 +502,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)
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 5429efe24d5a..8aa6a451104b 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -482,6 +482,10 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 			return 1;
 		case bgezal_op:
 		case bgezall_op:
+			if (NO_R6EMU && (insn.i_format.rs ||
+			    insn.i_format.rt == bgezall_op))
+				break;
+
 			regs->regs[31] = regs->cp0_epc +
 				dec_insn.pc_inc +
 				dec_insn.next_pc_inc;
-- 
2.2.1

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

* [PATCH RFC v2 48/70] MIPS: kernel: branch: Prevent BGEZAL emulation for MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 ++++++++++++++++++++++
 arch/mips/math-emu/cp1emu.c |  4 ++++
 2 files changed, 26 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 311a2223da59..2273307f7c51 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -502,7 +502,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)
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 5429efe24d5a..8aa6a451104b 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -482,6 +482,10 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 			return 1;
 		case bgezal_op:
 		case bgezall_op:
+			if (NO_R6EMU && (insn.i_format.rs ||
+			    insn.i_format.rt == bgezall_op))
+				break;
+
 			regs->regs[31] = regs->cp0_epc +
 				dec_insn.pc_inc +
 				dec_insn.next_pc_inc;
-- 
2.2.1

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

* [PATCH RFC v2 49/70] MIPS: kernel: branch: Prevent BEQL emulation for MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 ++++
 arch/mips/math-emu/cp1emu.c | 3 +++
 2 files changed, 7 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 2273307f7c51..a21bbda1ea9e 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -569,6 +569,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);
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 8aa6a451104b..c8ab23e96310 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -522,6 +522,9 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 		return 1;
 	case beq_op:
 	case beql_op:
+		if (NO_R6EMU && (insn.i_format.opcode == beql_op))
+			break;
+
 		if (regs->regs[insn.i_format.rs] ==
 		    regs->regs[insn.i_format.rt])
 			*contpc = regs->cp0_epc +
-- 
2.2.1

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

* [PATCH RFC v2 49/70] MIPS: kernel: branch: Prevent BEQL emulation for MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 ++++
 arch/mips/math-emu/cp1emu.c | 3 +++
 2 files changed, 7 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 2273307f7c51..a21bbda1ea9e 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -569,6 +569,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);
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 8aa6a451104b..c8ab23e96310 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -522,6 +522,9 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 		return 1;
 	case beq_op:
 	case beql_op:
+		if (NO_R6EMU && (insn.i_format.opcode == beql_op))
+			break;
+
 		if (regs->regs[insn.i_format.rs] ==
 		    regs->regs[insn.i_format.rt])
 			*contpc = regs->cp0_epc +
-- 
2.2.1

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

* [PATCH RFC v2 50/70] MIPS: kernel: branch: Prevent BNEL emulation for MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 ++++
 arch/mips/math-emu/cp1emu.c | 3 +++
 2 files changed, 7 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index a21bbda1ea9e..b71eff60543d 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -585,6 +585,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);
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index c8ab23e96310..05982b631d7c 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -537,6 +537,9 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 		return 1;
 	case bne_op:
 	case bnel_op:
+		if (NO_R6EMU && (insn.i_format.opcode == bnel_op))
+			break;
+
 		if (regs->regs[insn.i_format.rs] !=
 		    regs->regs[insn.i_format.rt])
 			*contpc = regs->cp0_epc +
-- 
2.2.1

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

* [PATCH RFC v2 50/70] MIPS: kernel: branch: Prevent BNEL emulation for MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 ++++
 arch/mips/math-emu/cp1emu.c | 3 +++
 2 files changed, 7 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index a21bbda1ea9e..b71eff60543d 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -585,6 +585,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);
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index c8ab23e96310..05982b631d7c 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -537,6 +537,9 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 		return 1;
 	case bne_op:
 	case bnel_op:
+		if (NO_R6EMU && (insn.i_format.opcode == bnel_op))
+			break;
+
 		if (regs->regs[insn.i_format.rs] !=
 		    regs->regs[insn.i_format.rt])
 			*contpc = regs->cp0_epc +
-- 
2.2.1

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

* [PATCH RFC v2 51/70] MIPS: kernel: branch: Prevent BLEZL emulation for MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 +++++
 arch/mips/math-emu/cp1emu.c | 3 +++
 2 files changed, 8 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index b71eff60543d..bf5754ac9c14 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -601,6 +601,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);
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 05982b631d7c..41516e2f08c7 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -552,6 +552,9 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 		return 1;
 	case blez_op:
 	case blezl_op:
+		if (NO_R6EMU && (insn.i_format.opcode == blezl_op))
+			break;
+
 		if ((long)regs->regs[insn.i_format.rs] <= 0)
 			*contpc = regs->cp0_epc +
 				dec_insn.pc_inc +
-- 
2.2.1

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

* [PATCH RFC v2 51/70] MIPS: kernel: branch: Prevent BLEZL emulation for MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 +++++
 arch/mips/math-emu/cp1emu.c | 3 +++
 2 files changed, 8 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index b71eff60543d..bf5754ac9c14 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -601,6 +601,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);
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 05982b631d7c..41516e2f08c7 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -552,6 +552,9 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 		return 1;
 	case blez_op:
 	case blezl_op:
+		if (NO_R6EMU && (insn.i_format.opcode == blezl_op))
+			break;
+
 		if ((long)regs->regs[insn.i_format.rs] <= 0)
 			*contpc = regs->cp0_epc +
 				dec_insn.pc_inc +
-- 
2.2.1

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

* [PATCH RFC v2 52/70] MIPS: kernel: branch: Prevent BGTZL emulation for MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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   | 5 +++++
 arch/mips/math-emu/cp1emu.c | 3 +++
 2 files changed, 8 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index bf5754ac9c14..fdc6316877c7 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -618,6 +618,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)) {
+			/* 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);
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 41516e2f08c7..472acb1dc3dd 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -566,6 +566,9 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 		return 1;
 	case bgtz_op:
 	case bgtzl_op:
+		if (NO_R6EMU && (insn.i_format.opcode == bgtzl_op))
+			break;
+
 		if ((long)regs->regs[insn.i_format.rs] > 0)
 			*contpc = regs->cp0_epc +
 				dec_insn.pc_inc +
-- 
2.2.1

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

* [PATCH RFC v2 52/70] MIPS: kernel: branch: Prevent BGTZL emulation for MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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   | 5 +++++
 arch/mips/math-emu/cp1emu.c | 3 +++
 2 files changed, 8 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index bf5754ac9c14..fdc6316877c7 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -618,6 +618,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)) {
+			/* 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);
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 41516e2f08c7..472acb1dc3dd 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -566,6 +566,9 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 		return 1;
 	case bgtz_op:
 	case bgtzl_op:
+		if (NO_R6EMU && (insn.i_format.opcode == bgtzl_op))
+			break;
+
 		if ((long)regs->regs[insn.i_format.rs] > 0)
 			*contpc = regs->cp0_epc +
 				dec_insn.pc_inc +
-- 
2.2.1

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

* [PATCH RFC v2 53/70] MIPS: Emulate the BC1{EQ,NE}Z FPU instructions
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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/include/uapi/asm/inst.h |   3 +-
 arch/mips/kernel/branch.c         | 101 +++++++++++++++++++++++++++-----------
 arch/mips/math-emu/cp1emu.c       |  27 ++++++++++
 3 files changed, 101 insertions(+), 30 deletions(-)

diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h
index 5c9e14a903af..19d3bc1e6510 100644
--- a/arch/mips/include/uapi/asm/inst.h
+++ b/arch/mips/include/uapi/asm/inst.h
@@ -115,7 +115,8 @@ enum cop_op {
 	mfhc_op       = 0x03, mtc_op	    = 0x04,
 	dmtc_op	      = 0x05, ctc_op	    = 0x06,
 	mthc0_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 fdc6316877c7..41dcf5a45ec2 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -403,7 +403,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;
 
@@ -637,40 +637,83 @@ 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 (cpu_has_mips_r6 &&
+		    ((insn.i_format.rs == bc1eqz_op) ||
+		     (insn.i_format.rs == bc1nez_op))) {
+			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_op: /* This is bbit0 on Octeon */
 		if ((regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt))
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 472acb1dc3dd..433e9ebdc35a 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -606,6 +606,33 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 #endif
 	case cop0_op:
 	case cop1_op:
+		/* Need to check for R6 bc1nez and bc1eqz branches */
+		if (cpu_has_mips_r6 &&
+		    ((insn.i_format.rs == bc1eqz_op) ||
+		     (insn.i_format.rs == bc1nez_op))) {
+			bit = 0;
+			switch (insn.i_format.rs) {
+			case bc1eqz_op:
+				if (get_fpr32(&current->thread.fpu.fpr[insn.i_format.rt], 0) & 0x1)
+				    bit = 1;
+				break;
+			case bc1nez_op:
+				if (!(get_fpr32(&current->thread.fpu.fpr[insn.i_format.rt], 0) & 0x1))
+				    bit = 1;
+				break;
+			}
+			if (bit)
+				*contpc = regs->cp0_epc +
+					dec_insn.pc_inc +
+					(insn.i_format.simmediate << 2);
+			else
+				*contpc = regs->cp0_epc +
+					dec_insn.pc_inc +
+					dec_insn.next_pc_inc;
+
+			return 1;
+		}
+		/* R2/R6 compatible cop1 instruction. Fall through */
 	case cop2_op:
 	case cop1x_op:
 		if (insn.i_format.rs == bc_op) {
-- 
2.2.1

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

* [PATCH RFC v2 53/70] MIPS: Emulate the BC1{EQ,NE}Z FPU instructions
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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/include/uapi/asm/inst.h |   3 +-
 arch/mips/kernel/branch.c         | 101 +++++++++++++++++++++++++++-----------
 arch/mips/math-emu/cp1emu.c       |  27 ++++++++++
 3 files changed, 101 insertions(+), 30 deletions(-)

diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h
index 5c9e14a903af..19d3bc1e6510 100644
--- a/arch/mips/include/uapi/asm/inst.h
+++ b/arch/mips/include/uapi/asm/inst.h
@@ -115,7 +115,8 @@ enum cop_op {
 	mfhc_op       = 0x03, mtc_op	    = 0x04,
 	dmtc_op	      = 0x05, ctc_op	    = 0x06,
 	mthc0_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 fdc6316877c7..41dcf5a45ec2 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -403,7 +403,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;
 
@@ -637,40 +637,83 @@ 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 (cpu_has_mips_r6 &&
+		    ((insn.i_format.rs == bc1eqz_op) ||
+		     (insn.i_format.rs == bc1nez_op))) {
+			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_op: /* This is bbit0 on Octeon */
 		if ((regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt))
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 472acb1dc3dd..433e9ebdc35a 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -606,6 +606,33 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 #endif
 	case cop0_op:
 	case cop1_op:
+		/* Need to check for R6 bc1nez and bc1eqz branches */
+		if (cpu_has_mips_r6 &&
+		    ((insn.i_format.rs == bc1eqz_op) ||
+		     (insn.i_format.rs == bc1nez_op))) {
+			bit = 0;
+			switch (insn.i_format.rs) {
+			case bc1eqz_op:
+				if (get_fpr32(&current->thread.fpu.fpr[insn.i_format.rt], 0) & 0x1)
+				    bit = 1;
+				break;
+			case bc1nez_op:
+				if (!(get_fpr32(&current->thread.fpu.fpr[insn.i_format.rt], 0) & 0x1))
+				    bit = 1;
+				break;
+			}
+			if (bit)
+				*contpc = regs->cp0_epc +
+					dec_insn.pc_inc +
+					(insn.i_format.simmediate << 2);
+			else
+				*contpc = regs->cp0_epc +
+					dec_insn.pc_inc +
+					dec_insn.next_pc_inc;
+
+			return 1;
+		}
+		/* R2/R6 compatible cop1 instruction. Fall through */
 	case cop2_op:
 	case cop1x_op:
 		if (insn.i_format.rs == bc_op) {
-- 
2.2.1

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

* [PATCH RFC v2 54/70] MIPS: Emulate the new MIPS R6 B{L,G}Ε{Z,}{AL,}C instructions
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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
BGEC   : Compact branch if GPR rs is less than or equal to GPR rt
BGEUC  : Similar to BGEC but unsigned.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/branch.c   | 31 +++++++++++++++++++++++++++++++
 arch/mips/math-emu/cp1emu.c | 23 +++++++++++++++++++++++
 2 files changed, 54 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 41dcf5a45ec2..174d2f74f28c 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -399,6 +399,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 the
+ *	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)
@@ -606,6 +616,27 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 			ret = -SIGILL;
 			break;
 		}
+		/*
+		 * Compact branches for R6 for the
+		 * blez and blezl opcodes.
+		 * BLEZ  | rs = 0 | rt != 0  == BLEZALC
+		 * BLEZ  | rs = rt != 0      == BGEZALC
+		 * BLEZ  | rs != 0 | rt != 0 == BGEUC
+		 * BLEZL | rs = 0 | rt != 0  == BLEZC
+		 * BLEZL | rs = rt != 0      == BGEZC
+		 * BLEZL | rs != 0 | rt != 0 == BGEC
+		 *
+		 * For real BLEZ{,L}, rt is always 0.
+		 */
+
+		if (cpu_has_mips_r6 && insn.i_format.rt) {
+			if ((insn.i_format.opcode == blez_op) &&
+			    ((!insn.i_format.rs && insn.i_format.rt) ||
+			     (insn.i_format.rs == insn.i_format.rt)))
+				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);
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 433e9ebdc35a..0697bab067c0 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -555,6 +555,29 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 		if (NO_R6EMU && (insn.i_format.opcode == blezl_op))
 			break;
 
+		/*
+		 * Compact branches for R6 for the
+		 * blez and blezl opcodes.
+		 * BLEZ  | rs = 0 | rt != 0  == BLEZALC
+		 * BLEZ  | rs = rt != 0      == BGEZALC
+		 * BLEZ  | rs != 0 | rt != 0 == BGEUC
+		 * BLEZL | rs = 0 | rt != 0  == BLEZC
+		 * BLEZL | rs = rt != 0      == BGEZC
+		 * BLEZL | rs != 0 | rt != 0 == BGEC
+		 *
+		 * For real BLEZ{,L}, rt is always 0.
+		 */
+		if (cpu_has_mips_r6 && insn.i_format.rt) {
+			if ((insn.i_format.opcode == blez_op) &&
+			    ((!insn.i_format.rs && insn.i_format.rt) ||
+			     (insn.i_format.rs == insn.i_format.rt)))
+				regs->regs[31] = regs->cp0_epc +
+					dec_insn.pc_inc;
+			*contpc = regs->cp0_epc + dec_insn.pc_inc +
+				dec_insn.next_pc_inc;
+
+			return 1;
+		}
 		if ((long)regs->regs[insn.i_format.rs] <= 0)
 			*contpc = regs->cp0_epc +
 				dec_insn.pc_inc +
-- 
2.2.1

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

* [PATCH RFC v2 54/70] MIPS: Emulate the new MIPS R6 B{L,G}Ε{Z,}{AL,}C instructions
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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
BGEC   : Compact branch if GPR rs is less than or equal to GPR rt
BGEUC  : Similar to BGEC but unsigned.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/branch.c   | 31 +++++++++++++++++++++++++++++++
 arch/mips/math-emu/cp1emu.c | 23 +++++++++++++++++++++++
 2 files changed, 54 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 41dcf5a45ec2..174d2f74f28c 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -399,6 +399,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 the
+ *	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)
@@ -606,6 +616,27 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 			ret = -SIGILL;
 			break;
 		}
+		/*
+		 * Compact branches for R6 for the
+		 * blez and blezl opcodes.
+		 * BLEZ  | rs = 0 | rt != 0  == BLEZALC
+		 * BLEZ  | rs = rt != 0      == BGEZALC
+		 * BLEZ  | rs != 0 | rt != 0 == BGEUC
+		 * BLEZL | rs = 0 | rt != 0  == BLEZC
+		 * BLEZL | rs = rt != 0      == BGEZC
+		 * BLEZL | rs != 0 | rt != 0 == BGEC
+		 *
+		 * For real BLEZ{,L}, rt is always 0.
+		 */
+
+		if (cpu_has_mips_r6 && insn.i_format.rt) {
+			if ((insn.i_format.opcode == blez_op) &&
+			    ((!insn.i_format.rs && insn.i_format.rt) ||
+			     (insn.i_format.rs == insn.i_format.rt)))
+				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);
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 433e9ebdc35a..0697bab067c0 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -555,6 +555,29 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 		if (NO_R6EMU && (insn.i_format.opcode == blezl_op))
 			break;
 
+		/*
+		 * Compact branches for R6 for the
+		 * blez and blezl opcodes.
+		 * BLEZ  | rs = 0 | rt != 0  == BLEZALC
+		 * BLEZ  | rs = rt != 0      == BGEZALC
+		 * BLEZ  | rs != 0 | rt != 0 == BGEUC
+		 * BLEZL | rs = 0 | rt != 0  == BLEZC
+		 * BLEZL | rs = rt != 0      == BGEZC
+		 * BLEZL | rs != 0 | rt != 0 == BGEC
+		 *
+		 * For real BLEZ{,L}, rt is always 0.
+		 */
+		if (cpu_has_mips_r6 && insn.i_format.rt) {
+			if ((insn.i_format.opcode == blez_op) &&
+			    ((!insn.i_format.rs && insn.i_format.rt) ||
+			     (insn.i_format.rs == insn.i_format.rt)))
+				regs->regs[31] = regs->cp0_epc +
+					dec_insn.pc_inc;
+			*contpc = regs->cp0_epc + dec_insn.pc_inc +
+				dec_insn.next_pc_inc;
+
+			return 1;
+		}
 		if ((long)regs->regs[insn.i_format.rs] <= 0)
 			*contpc = regs->cp0_epc +
 				dec_insn.pc_inc +
-- 
2.2.1

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

* [PATCH RFC v2 55/70] MIPS: Emulate the new MIPS R6 B{L,G}T{Z,}{AL,}C instructions
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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
BGTZALC: Compact branch-and-link if GPR rt is > to zero
BLTZL  : Compact branch if GPR rt is < to zero
BGTZL  : Compact branch if GPR rt is > to zero
BLTC   : Compact branch if GPR rs is less than GPR rt
BLTUC  : Similar to BLTC but unsigned

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/branch.c   | 22 ++++++++++++++++++++++
 arch/mips/math-emu/cp1emu.c | 24 ++++++++++++++++++++++++
 2 files changed, 46 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 174d2f74f28c..713d72561f97 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -654,6 +654,28 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 			ret = -SIGILL;
 			break;
 		}
+		/*
+		 * Compact branches for R6 for the
+		 * bgtz and bgtzl opcodes.
+		 * BGTZ  | rs = 0 | rt != 0  == BGTZALC
+		 * BGTZ  | rs = rt != 0      == BLTZALC
+		 * BGTZ  | rs != 0 | rt != 0 == BLTUC
+		 * BGTZL | rs = 0 | rt != 0  == BGTZC
+		 * BGTZL | rs = rt != 0      == BLTZC
+		 * BGTZL | rs != 0 | rt != 0 == BLTC
+		 *
+		 * *ZALC varint for BGTZ &&& rt != 0
+		 * For real GTZ{,L}, rt is always 0.
+		 */
+		if (cpu_has_mips_r6 && insn.i_format.rt) {
+			if ((insn.i_format.opcode == blez_op) &&
+			    ((!insn.i_format.rs && insn.i_format.rt) ||
+			    (insn.i_format.rs == insn.i_format.rt)))
+				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);
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 0697bab067c0..29d1621bdefd 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -591,6 +591,30 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 	case bgtzl_op:
 		if (NO_R6EMU && (insn.i_format.opcode == bgtzl_op))
 			break;
+		/*
+		 * Compact branches for R6 for the
+		 * bgtz and bgtzl opcodes.
+		 * BGTZ  | rs = 0 | rt != 0  == BGTZALC
+		 * BGTZ  | rs = rt != 0      == BLTZALC
+		 * BGTZ  | rs != 0 | rt != 0 == BLTUC
+		 * BGTZL | rs = 0 | rt != 0  == BGTZC
+		 * BGTZL | rs = rt != 0      == BLTZC
+		 * BGTZL | rs != 0 | rt != 0 == BLTC
+		 *
+		 * *ZALC varint for BGTZ &&& rt != 0
+		 * For real GTZ{,L}, rt is always 0.
+		 */
+		if (cpu_has_mips_r6 && insn.i_format.rt) {
+			if ((insn.i_format.opcode == blez_op) &&
+			    ((!insn.i_format.rs && insn.i_format.rt) ||
+			     (insn.i_format.rs == insn.i_format.rt)))
+				regs->regs[31] = regs->cp0_epc +
+					dec_insn.pc_inc;
+			*contpc = regs->cp0_epc + dec_insn.pc_inc +
+				dec_insn.next_pc_inc;
+
+			return 1;
+		}
 
 		if ((long)regs->regs[insn.i_format.rs] > 0)
 			*contpc = regs->cp0_epc +
-- 
2.2.1

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

* [PATCH RFC v2 55/70] MIPS: Emulate the new MIPS R6 B{L,G}T{Z,}{AL,}C instructions
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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
BGTZALC: Compact branch-and-link if GPR rt is > to zero
BLTZL  : Compact branch if GPR rt is < to zero
BGTZL  : Compact branch if GPR rt is > to zero
BLTC   : Compact branch if GPR rs is less than GPR rt
BLTUC  : Similar to BLTC but unsigned

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/branch.c   | 22 ++++++++++++++++++++++
 arch/mips/math-emu/cp1emu.c | 24 ++++++++++++++++++++++++
 2 files changed, 46 insertions(+)

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 174d2f74f28c..713d72561f97 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -654,6 +654,28 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 			ret = -SIGILL;
 			break;
 		}
+		/*
+		 * Compact branches for R6 for the
+		 * bgtz and bgtzl opcodes.
+		 * BGTZ  | rs = 0 | rt != 0  == BGTZALC
+		 * BGTZ  | rs = rt != 0      == BLTZALC
+		 * BGTZ  | rs != 0 | rt != 0 == BLTUC
+		 * BGTZL | rs = 0 | rt != 0  == BGTZC
+		 * BGTZL | rs = rt != 0      == BLTZC
+		 * BGTZL | rs != 0 | rt != 0 == BLTC
+		 *
+		 * *ZALC varint for BGTZ &&& rt != 0
+		 * For real GTZ{,L}, rt is always 0.
+		 */
+		if (cpu_has_mips_r6 && insn.i_format.rt) {
+			if ((insn.i_format.opcode == blez_op) &&
+			    ((!insn.i_format.rs && insn.i_format.rt) ||
+			    (insn.i_format.rs == insn.i_format.rt)))
+				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);
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 0697bab067c0..29d1621bdefd 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -591,6 +591,30 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 	case bgtzl_op:
 		if (NO_R6EMU && (insn.i_format.opcode == bgtzl_op))
 			break;
+		/*
+		 * Compact branches for R6 for the
+		 * bgtz and bgtzl opcodes.
+		 * BGTZ  | rs = 0 | rt != 0  == BGTZALC
+		 * BGTZ  | rs = rt != 0      == BLTZALC
+		 * BGTZ  | rs != 0 | rt != 0 == BLTUC
+		 * BGTZL | rs = 0 | rt != 0  == BGTZC
+		 * BGTZL | rs = rt != 0      == BLTZC
+		 * BGTZL | rs != 0 | rt != 0 == BLTC
+		 *
+		 * *ZALC varint for BGTZ &&& rt != 0
+		 * For real GTZ{,L}, rt is always 0.
+		 */
+		if (cpu_has_mips_r6 && insn.i_format.rt) {
+			if ((insn.i_format.opcode == blez_op) &&
+			    ((!insn.i_format.rs && insn.i_format.rt) ||
+			     (insn.i_format.rs == insn.i_format.rt)))
+				regs->regs[31] = regs->cp0_epc +
+					dec_insn.pc_inc;
+			*contpc = regs->cp0_epc + dec_insn.pc_inc +
+				dec_insn.next_pc_inc;
+
+			return 1;
+		}
 
 		if ((long)regs->regs[insn.i_format.rs] > 0)
 			*contpc = regs->cp0_epc +
-- 
2.2.1

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

* [PATCH RFC v2 56/70] MIPS: Emulate the new MIPS R6 branch compact (BC) instruction
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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/include/uapi/asm/inst.h |  2 +-
 arch/mips/kernel/branch.c         |  8 ++++++++
 arch/mips/math-emu/cp1emu.c       | 12 ++++++++++++
 3 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h
index 19d3bc1e6510..9ce5e34b9c64 100644
--- a/arch/mips/include/uapi/asm/inst.h
+++ b/arch/mips/include/uapi/asm/inst.h
@@ -31,7 +31,7 @@ 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,
+	ll_op, lwc1_op, lwc2_op, bc6_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
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 713d72561f97..bf82ec302cff 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -800,6 +800,14 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 		regs->cp0_epc = epc;
 		break;
 #endif
+	case bc6_op:
+		/* Only valid for MIPS R6 */
+		if (!cpu_has_mips_r6) {
+			ret = -SIGILL;
+			break;
+		}
+		regs->cp0_epc += 8;
+		break;
 	}
 
 	return ret;
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 29d1621bdefd..ccdd424f2f1d 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -625,6 +625,18 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 				dec_insn.pc_inc +
 				dec_insn.next_pc_inc;
 		return 1;
+	case bc6_op:
+		/*
+		 * Only valid for MIPS R6 but we can still end up
+		 * here from a broken userland so just tell emulator
+		 * this is not a branch and let it break later on.
+		 */
+		if  (!cpu_has_mips_r6)
+			break;
+		*contpc = regs->cp0_epc + dec_insn.pc_inc +
+			dec_insn.next_pc_inc;
+
+		return 1;
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
 	case lwc2_op: /* This is bbit0 on Octeon */
 		if ((regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt)) == 0)
-- 
2.2.1

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

* [PATCH RFC v2 56/70] MIPS: Emulate the new MIPS R6 branch compact (BC) instruction
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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/include/uapi/asm/inst.h |  2 +-
 arch/mips/kernel/branch.c         |  8 ++++++++
 arch/mips/math-emu/cp1emu.c       | 12 ++++++++++++
 3 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h
index 19d3bc1e6510..9ce5e34b9c64 100644
--- a/arch/mips/include/uapi/asm/inst.h
+++ b/arch/mips/include/uapi/asm/inst.h
@@ -31,7 +31,7 @@ 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,
+	ll_op, lwc1_op, lwc2_op, bc6_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
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 713d72561f97..bf82ec302cff 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -800,6 +800,14 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 		regs->cp0_epc = epc;
 		break;
 #endif
+	case bc6_op:
+		/* Only valid for MIPS R6 */
+		if (!cpu_has_mips_r6) {
+			ret = -SIGILL;
+			break;
+		}
+		regs->cp0_epc += 8;
+		break;
 	}
 
 	return ret;
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 29d1621bdefd..ccdd424f2f1d 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -625,6 +625,18 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 				dec_insn.pc_inc +
 				dec_insn.next_pc_inc;
 		return 1;
+	case bc6_op:
+		/*
+		 * Only valid for MIPS R6 but we can still end up
+		 * here from a broken userland so just tell emulator
+		 * this is not a branch and let it break later on.
+		 */
+		if  (!cpu_has_mips_r6)
+			break;
+		*contpc = regs->cp0_epc + dec_insn.pc_inc +
+			dec_insn.next_pc_inc;
+
+		return 1;
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
 	case lwc2_op: /* This is bbit0 on Octeon */
 		if ((regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt)) == 0)
-- 
2.2.1

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

* [PATCH RFC v2 57/70] MIPS: Emulate the new MIPS R6 BOVC, BEQC and BEQZALC instructions
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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         | 11 +++++++++++
 arch/mips/math-emu/cp1emu.c       | 10 ++++++++++
 3 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h
index 9ce5e34b9c64..782af0f83421 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_op, cbcond0_op = addi_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 bf82ec302cff..c084b38e727b 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -808,6 +808,17 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 		}
 		regs->cp0_epc += 8;
 		break;
+	case cbcond0_op:
+		/* Only valid for MIPS R6 */
+		if (!cpu_has_mips_r6) {
+			ret = -SIGILL;
+			break;
+		}
+		/* Compact branches: bovc, beqc, beqzalc */
+		if (insn.i_format.rt && !insn.i_format.rs)
+			regs->regs[31] = epc + 4;
+		regs->cp0_epc += 8;
+		break;
 	}
 
 	return ret;
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index ccdd424f2f1d..cafeb54b7cf1 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -637,6 +637,16 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 			dec_insn.next_pc_inc;
 
 		return 1;
+	case cbcond0_op:
+		if (!cpu_has_mips_r6)
+			break;
+		if (insn.i_format.rt && !insn.i_format.rs)
+			regs->regs[31] = regs->cp0_epc + 4;
+		*contpc = regs->cp0_epc + dec_insn.pc_inc +
+			dec_insn.next_pc_inc;
+
+		return 1;
+
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
 	case lwc2_op: /* This is bbit0 on Octeon */
 		if ((regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt)) == 0)
-- 
2.2.1

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

* [PATCH RFC v2 57/70] MIPS: Emulate the new MIPS R6 BOVC, BEQC and BEQZALC instructions
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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         | 11 +++++++++++
 arch/mips/math-emu/cp1emu.c       | 10 ++++++++++
 3 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h
index 9ce5e34b9c64..782af0f83421 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_op, cbcond0_op = addi_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 bf82ec302cff..c084b38e727b 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -808,6 +808,17 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 		}
 		regs->cp0_epc += 8;
 		break;
+	case cbcond0_op:
+		/* Only valid for MIPS R6 */
+		if (!cpu_has_mips_r6) {
+			ret = -SIGILL;
+			break;
+		}
+		/* Compact branches: bovc, beqc, beqzalc */
+		if (insn.i_format.rt && !insn.i_format.rs)
+			regs->regs[31] = epc + 4;
+		regs->cp0_epc += 8;
+		break;
 	}
 
 	return ret;
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index ccdd424f2f1d..cafeb54b7cf1 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -637,6 +637,16 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 			dec_insn.next_pc_inc;
 
 		return 1;
+	case cbcond0_op:
+		if (!cpu_has_mips_r6)
+			break;
+		if (insn.i_format.rt && !insn.i_format.rs)
+			regs->regs[31] = regs->cp0_epc + 4;
+		*contpc = regs->cp0_epc + dec_insn.pc_inc +
+			dec_insn.next_pc_inc;
+
+		return 1;
+
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
 	case lwc2_op: /* This is bbit0 on Octeon */
 		if ((regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt)) == 0)
-- 
2.2.1

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

* [PATCH RFC v2 58/70] MIPS: Emulate the new MIPS R6 BNVC, BNEC and BNEZLAC instructions
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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         | 6 +++++-
 arch/mips/math-emu/cp1emu.c       | 1 +
 3 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h
index 782af0f83421..78335414b18a 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_op, cbcond1_op = daddi_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 c084b38e727b..fa780ac87863 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -809,12 +809,16 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 		regs->cp0_epc += 8;
 		break;
 	case cbcond0_op:
+	case cbcond1_op:
 		/* Only valid for MIPS R6 */
 		if (!cpu_has_mips_r6) {
 			ret = -SIGILL;
 			break;
 		}
-		/* Compact branches: bovc, beqc, beqzalc */
+		/*
+		 * Compact branches:
+		 * bovc, beqc, beqzalc, bnvc, bnec, bnezlac
+		 */
 		if (insn.i_format.rt && !insn.i_format.rs)
 			regs->regs[31] = epc + 4;
 		regs->cp0_epc += 8;
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index cafeb54b7cf1..a9c19441795b 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -638,6 +638,7 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 
 		return 1;
 	case cbcond0_op:
+	case cbcond1_op:
 		if (!cpu_has_mips_r6)
 			break;
 		if (insn.i_format.rt && !insn.i_format.rs)
-- 
2.2.1

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

* [PATCH RFC v2 58/70] MIPS: Emulate the new MIPS R6 BNVC, BNEC and BNEZLAC instructions
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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         | 6 +++++-
 arch/mips/math-emu/cp1emu.c       | 1 +
 3 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h
index 782af0f83421..78335414b18a 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_op, cbcond1_op = daddi_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 c084b38e727b..fa780ac87863 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -809,12 +809,16 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 		regs->cp0_epc += 8;
 		break;
 	case cbcond0_op:
+	case cbcond1_op:
 		/* Only valid for MIPS R6 */
 		if (!cpu_has_mips_r6) {
 			ret = -SIGILL;
 			break;
 		}
-		/* Compact branches: bovc, beqc, beqzalc */
+		/*
+		 * Compact branches:
+		 * bovc, beqc, beqzalc, bnvc, bnec, bnezlac
+		 */
 		if (insn.i_format.rt && !insn.i_format.rs)
 			regs->regs[31] = epc + 4;
 		regs->cp0_epc += 8;
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index cafeb54b7cf1..a9c19441795b 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -638,6 +638,7 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 
 		return 1;
 	case cbcond0_op:
+	case cbcond1_op:
 		if (!cpu_has_mips_r6)
 			break;
 		if (insn.i_format.rt && !insn.i_format.rs)
-- 
2.2.1

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

* [PATCH RFC v2 59/70] MIPS: Emulate the new MIPS R6 BALC instruction
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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/include/uapi/asm/inst.h |  2 +-
 arch/mips/kernel/branch.c         | 10 ++++++++++
 arch/mips/math-emu/cp1emu.c       |  7 +++++++
 3 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h
index 78335414b18a..32063c52f24b 100644
--- a/arch/mips/include/uapi/asm/inst.h
+++ b/arch/mips/include/uapi/asm/inst.h
@@ -33,7 +33,7 @@ enum major_op {
 	sdl_op, sdr_op, swr_op, cache_op,
 	ll_op, lwc1_op, lwc2_op, bc6_op = lwc2_op, pref_op,
 	lld_op, ldc1_op, ldc2_op, ld_op,
-	sc_op, swc1_op, swc2_op, major_3b_op,
+	sc_op, swc1_op, swc2_op, balc6_op = swc2_op, major_3b_op,
 	scd_op, sdc1_op, sdc2_op, sd_op
 };
 
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index fa780ac87863..93e90c27a0cd 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -823,6 +823,16 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 			regs->regs[31] = epc + 4;
 		regs->cp0_epc += 8;
 		break;
+	case balc6_op:
+		if (!cpu_has_mips_r6) {
+			ret = -SIGILL;
+			break;
+		}
+		/* Compact branch: BALC */
+		regs->regs[31] = epc + 4;
+		epc += 4 + (insn.i_format.simmediate << 2);
+		regs->cp0_epc = epc;
+		break;
 	}
 
 	return ret;
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index a9c19441795b..b66d77ad5504 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -647,7 +647,14 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 			dec_insn.next_pc_inc;
 
 		return 1;
+	case balc6_op:
+		if (!cpu_has_mips_r6)
+			break;
+		regs->regs[31] = regs->cp0_epc + 4;
+		*contpc = regs->cp0_epc + dec_insn.pc_inc +
+			dec_insn.next_pc_inc;
 
+		return 1;
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
 	case lwc2_op: /* This is bbit0 on Octeon */
 		if ((regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt)) == 0)
-- 
2.2.1

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

* [PATCH RFC v2 59/70] MIPS: Emulate the new MIPS R6 BALC instruction
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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/include/uapi/asm/inst.h |  2 +-
 arch/mips/kernel/branch.c         | 10 ++++++++++
 arch/mips/math-emu/cp1emu.c       |  7 +++++++
 3 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h
index 78335414b18a..32063c52f24b 100644
--- a/arch/mips/include/uapi/asm/inst.h
+++ b/arch/mips/include/uapi/asm/inst.h
@@ -33,7 +33,7 @@ enum major_op {
 	sdl_op, sdr_op, swr_op, cache_op,
 	ll_op, lwc1_op, lwc2_op, bc6_op = lwc2_op, pref_op,
 	lld_op, ldc1_op, ldc2_op, ld_op,
-	sc_op, swc1_op, swc2_op, major_3b_op,
+	sc_op, swc1_op, swc2_op, balc6_op = swc2_op, major_3b_op,
 	scd_op, sdc1_op, sdc2_op, sd_op
 };
 
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index fa780ac87863..93e90c27a0cd 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -823,6 +823,16 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 			regs->regs[31] = epc + 4;
 		regs->cp0_epc += 8;
 		break;
+	case balc6_op:
+		if (!cpu_has_mips_r6) {
+			ret = -SIGILL;
+			break;
+		}
+		/* Compact branch: BALC */
+		regs->regs[31] = epc + 4;
+		epc += 4 + (insn.i_format.simmediate << 2);
+		regs->cp0_epc = epc;
+		break;
 	}
 
 	return ret;
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index a9c19441795b..b66d77ad5504 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -647,7 +647,14 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 			dec_insn.next_pc_inc;
 
 		return 1;
+	case balc6_op:
+		if (!cpu_has_mips_r6)
+			break;
+		regs->regs[31] = regs->cp0_epc + 4;
+		*contpc = regs->cp0_epc + dec_insn.pc_inc +
+			dec_insn.next_pc_inc;
 
+		return 1;
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
 	case lwc2_op: /* This is bbit0 on Octeon */
 		if ((regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt)) == 0)
-- 
2.2.1

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

* [PATCH RFC v2 60/70] MIPS: Emulate the new MIPS R6 BEQZC and JIC instructions
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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/include/uapi/asm/inst.h | 2 +-
 arch/mips/kernel/branch.c         | 8 ++++++++
 arch/mips/math-emu/cp1emu.c       | 7 +++++++
 3 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h
index 32063c52f24b..721f8fe705a4 100644
--- a/arch/mips/include/uapi/asm/inst.h
+++ b/arch/mips/include/uapi/asm/inst.h
@@ -32,7 +32,7 @@ enum major_op {
 	sb_op, sh_op, swl_op, sw_op,
 	sdl_op, sdr_op, swr_op, cache_op,
 	ll_op, lwc1_op, lwc2_op, bc6_op = lwc2_op, pref_op,
-	lld_op, ldc1_op, ldc2_op, ld_op,
+	lld_op, ldc1_op, ldc2_op, beqzcjic_op = ldc2_op, ld_op,
 	sc_op, swc1_op, swc2_op, balc6_op = swc2_op, major_3b_op,
 	scd_op, sdc1_op, sdc2_op, sd_op
 };
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 93e90c27a0cd..c29ceaeaa96e 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -833,6 +833,14 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 		epc += 4 + (insn.i_format.simmediate << 2);
 		regs->cp0_epc = epc;
 		break;
+	case beqzcjic_op:
+		if (!cpu_has_mips_r6) {
+			ret = -SIGILL;
+			break;
+		}
+		/* Compact branch: BEQZC || JIC */
+		regs->cp0_epc += 8;
+		break;
 	}
 
 	return ret;
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index b66d77ad5504..2b53036d5f09 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -655,6 +655,13 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 			dec_insn.next_pc_inc;
 
 		return 1;
+	case beqzcjic_op:
+		if (!cpu_has_mips_r6)
+			break;
+		*contpc = regs->cp0_epc + dec_insn.pc_inc +
+			dec_insn.next_pc_inc;
+
+		return 1;
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
 	case lwc2_op: /* This is bbit0 on Octeon */
 		if ((regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt)) == 0)
-- 
2.2.1

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

* [PATCH RFC v2 60/70] MIPS: Emulate the new MIPS R6 BEQZC and JIC instructions
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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/include/uapi/asm/inst.h | 2 +-
 arch/mips/kernel/branch.c         | 8 ++++++++
 arch/mips/math-emu/cp1emu.c       | 7 +++++++
 3 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h
index 32063c52f24b..721f8fe705a4 100644
--- a/arch/mips/include/uapi/asm/inst.h
+++ b/arch/mips/include/uapi/asm/inst.h
@@ -32,7 +32,7 @@ enum major_op {
 	sb_op, sh_op, swl_op, sw_op,
 	sdl_op, sdr_op, swr_op, cache_op,
 	ll_op, lwc1_op, lwc2_op, bc6_op = lwc2_op, pref_op,
-	lld_op, ldc1_op, ldc2_op, ld_op,
+	lld_op, ldc1_op, ldc2_op, beqzcjic_op = ldc2_op, ld_op,
 	sc_op, swc1_op, swc2_op, balc6_op = swc2_op, major_3b_op,
 	scd_op, sdc1_op, sdc2_op, sd_op
 };
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 93e90c27a0cd..c29ceaeaa96e 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -833,6 +833,14 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 		epc += 4 + (insn.i_format.simmediate << 2);
 		regs->cp0_epc = epc;
 		break;
+	case beqzcjic_op:
+		if (!cpu_has_mips_r6) {
+			ret = -SIGILL;
+			break;
+		}
+		/* Compact branch: BEQZC || JIC */
+		regs->cp0_epc += 8;
+		break;
 	}
 
 	return ret;
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index b66d77ad5504..2b53036d5f09 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -655,6 +655,13 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 			dec_insn.next_pc_inc;
 
 		return 1;
+	case beqzcjic_op:
+		if (!cpu_has_mips_r6)
+			break;
+		*contpc = regs->cp0_epc + dec_insn.pc_inc +
+			dec_insn.next_pc_inc;
+
+		return 1;
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
 	case lwc2_op: /* This is bbit0 on Octeon */
 		if ((regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt)) == 0)
-- 
2.2.1

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

* [PATCH RFC v2 61/70] MIPS: Emulate the new MIPS R6 BNEZC and JIALC instructions
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 uses the <R6 sdc2 opcode for the new BNEZC and JIALC instructions

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

diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h
index 721f8fe705a4..fc0cf5ac0cf7 100644
--- a/arch/mips/include/uapi/asm/inst.h
+++ b/arch/mips/include/uapi/asm/inst.h
@@ -34,7 +34,7 @@ enum major_op {
 	ll_op, lwc1_op, lwc2_op, bc6_op = lwc2_op, pref_op,
 	lld_op, ldc1_op, ldc2_op, beqzcjic_op = ldc2_op, ld_op,
 	sc_op, swc1_op, swc2_op, balc6_op = swc2_op, major_3b_op,
-	scd_op, sdc1_op, sdc2_op, sd_op
+	scd_op, sdc1_op, sdc2_op, bnezcjialc_op = sdc2_op, sd_op
 };
 
 /*
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index c29ceaeaa96e..02d6032e91ab 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -841,6 +841,16 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 		/* Compact branch: BEQZC || JIC */
 		regs->cp0_epc += 8;
 		break;
+	case bnezcjialc_op:
+		if (!cpu_has_mips_r6) {
+			ret = -SIGILL;
+			break;
+		}
+		/* Compact branch: BNEZC || JIALC */
+		if (insn.i_format.rs)
+			regs->regs[31] = epc + 4;
+		regs->cp0_epc += 8;
+		break;
 	}
 
 	return ret;
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 2b53036d5f09..bf4ccb15c541 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -662,6 +662,15 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 			dec_insn.next_pc_inc;
 
 		return 1;
+	case bnezcjialc_op:
+		if (!cpu_has_mips_r6)
+			break;
+		if (!insn.i_format.rs)
+			regs->regs[31] = regs->cp0_epc + 4;
+		*contpc = regs->cp0_epc + dec_insn.pc_inc +
+			dec_insn.next_pc_inc;
+
+		return 1;
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
 	case lwc2_op: /* This is bbit0 on Octeon */
 		if ((regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt)) == 0)
-- 
2.2.1

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

* [PATCH RFC v2 61/70] MIPS: Emulate the new MIPS R6 BNEZC and JIALC instructions
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R6 uses the <R6 sdc2 opcode for the new BNEZC and JIALC instructions

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

diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h
index 721f8fe705a4..fc0cf5ac0cf7 100644
--- a/arch/mips/include/uapi/asm/inst.h
+++ b/arch/mips/include/uapi/asm/inst.h
@@ -34,7 +34,7 @@ enum major_op {
 	ll_op, lwc1_op, lwc2_op, bc6_op = lwc2_op, pref_op,
 	lld_op, ldc1_op, ldc2_op, beqzcjic_op = ldc2_op, ld_op,
 	sc_op, swc1_op, swc2_op, balc6_op = swc2_op, major_3b_op,
-	scd_op, sdc1_op, sdc2_op, sd_op
+	scd_op, sdc1_op, sdc2_op, bnezcjialc_op = sdc2_op, sd_op
 };
 
 /*
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index c29ceaeaa96e..02d6032e91ab 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -841,6 +841,16 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 		/* Compact branch: BEQZC || JIC */
 		regs->cp0_epc += 8;
 		break;
+	case bnezcjialc_op:
+		if (!cpu_has_mips_r6) {
+			ret = -SIGILL;
+			break;
+		}
+		/* Compact branch: BNEZC || JIALC */
+		if (insn.i_format.rs)
+			regs->regs[31] = epc + 4;
+		regs->cp0_epc += 8;
+		break;
 	}
 
 	return ret;
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 2b53036d5f09..bf4ccb15c541 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -662,6 +662,15 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 			dec_insn.next_pc_inc;
 
 		return 1;
+	case bnezcjialc_op:
+		if (!cpu_has_mips_r6)
+			break;
+		if (!insn.i_format.rs)
+			regs->regs[31] = regs->cp0_epc + 4;
+		*contpc = regs->cp0_epc + dec_insn.pc_inc +
+			dec_insn.next_pc_inc;
+
+		return 1;
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
 	case lwc2_op: /* This is bbit0 on Octeon */
 		if ((regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt)) == 0)
-- 
2.2.1

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

* [PATCH RFC v2 62/70] MIPS: Add LLB bit and related feature for the Config 5 CP0 register
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 aa2819526c42..904dd1ca5cf4 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 f604523aec3d..15687234d70a 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -376,6 +376,7 @@ enum cpu_type_enum {
 #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_FRE		0x800000000ull /* FRE & UFE bits implemented */
+#define MIPS_CPU_RW_LLB		0x1000000000ull /* 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 5e4aef304b02..093cd70e56ec 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_MVH		(_ULCAST_(1) << 5)
 #define MIPS_CONF5_FRE		(_ULCAST_(1) << 8)
 #define MIPS_CONF5_UFE		(_ULCAST_(1) << 9)
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 328b61f63430..aefe404742a3 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -512,6 +512,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.1

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

* [PATCH RFC v2 62/70] MIPS: Add LLB bit and related feature for the Config 5 CP0 register
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 aa2819526c42..904dd1ca5cf4 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 f604523aec3d..15687234d70a 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -376,6 +376,7 @@ enum cpu_type_enum {
 #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_FRE		0x800000000ull /* FRE & UFE bits implemented */
+#define MIPS_CPU_RW_LLB		0x1000000000ull /* 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 5e4aef304b02..093cd70e56ec 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_MVH		(_ULCAST_(1) << 5)
 #define MIPS_CONF5_FRE		(_ULCAST_(1) << 8)
 #define MIPS_CONF5_UFE		(_ULCAST_(1) << 9)
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 328b61f63430..aefe404742a3 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -512,6 +512,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.1

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

* [PATCH RFC v2 63/70] MIPS: asm: mipsregs: Add support for the LLADDR register
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 093cd70e56ec..06346001ee4d 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -1128,6 +1128,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.1

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

* [PATCH RFC v2 63/70] MIPS: asm: mipsregs: Add support for the LLADDR register
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 093cd70e56ec..06346001ee4d 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -1128,6 +1128,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.1

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

* [PATCH RFC v2 64/70] MIPS: kernel: mips-r2-to-r6-emul: Add R2 emulator for MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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/branch.h             |    3 -
 arch/mips/include/asm/mips-r2-to-r6-emul.h |   96 ++
 arch/mips/kernel/Makefile                  |    1 +
 arch/mips/kernel/branch.c                  |    1 +
 arch/mips/kernel/mips-r2-to-r6-emul.c      | 2378 ++++++++++++++++++++++++++++
 arch/mips/kernel/traps.c                   |   28 +-
 arch/mips/math-emu/cp1emu.c                |    3 +-
 8 files changed, 2518 insertions(+), 5 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 3feabcb541c6..bfc817770e74 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -2056,6 +2056,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/branch.h b/arch/mips/include/asm/branch.h
index 2894ea58454d..de781cf54bc7 100644
--- a/arch/mips/include/asm/branch.h
+++ b/arch/mips/include/asm/branch.h
@@ -13,9 +13,6 @@
 #include <asm/ptrace.h>
 #include <asm/inst.h>
 
-static int mipsr2_emulation = 0;
-#define NO_R6EMU	(cpu_has_mips_r6 && !mipsr2_emulation)
-
 extern int __isa_exception_epc(struct pt_regs *regs);
 extern int __compute_return_epc(struct pt_regs *regs);
 extern int __compute_return_epc_for_insn(struct pt_regs *regs,
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..f66938ef80f0
--- /dev/null
+++ b/arch/mips/include/asm/mips-r2-to-r6-emul.h
@@ -0,0 +1,96 @@
+/*
+ * 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();						\
+	__this_cpu_inc(mipsr2emustats.M);				\
+	err = __get_user(nir, (u32 __user *)regs->cp0_epc);		\
+	if (!err) {							\
+		if (nir == BREAK_MATH)					\
+			__this_cpu_inc(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();					\
+	__this_cpu_inc(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 */
+
+#define NO_R6EMU	(cpu_has_mips_r6 && !mipsr2_emulation)
+
+#endif /* __ASM_MIPS_R2_TO_R6_EMUL_H */
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 0862ae781339..913a8ce41e9d 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -91,6 +91,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 02d6032e91ab..768680756b06 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -16,6 +16,7 @@
 #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>
 
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..64d17e41093b
--- /dev/null
+++ b/arch/mips/kernel/mips-r2-to-r6-emul.c
@@ -0,0 +1,2378 @@
+/*
+ * 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);
+
+extern const unsigned int fpucondbit[8];
+
+#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)__this_cpu_read(mipsr2emustats.movs),
+		   (unsigned long)__this_cpu_read(mipsr2bdemustats.movs));
+	seq_printf(s, "hilo\t\t%ld\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2emustats.hilo),
+		   (unsigned long)__this_cpu_read(mipsr2bdemustats.hilo));
+	seq_printf(s, "muls\t\t%ld\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2emustats.muls),
+		   (unsigned long)__this_cpu_read(mipsr2bdemustats.muls));
+	seq_printf(s, "divs\t\t%ld\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2emustats.divs),
+		   (unsigned long)__this_cpu_read(mipsr2bdemustats.divs));
+	seq_printf(s, "dsps\t\t%ld\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2emustats.dsps),
+		   (unsigned long)__this_cpu_read(mipsr2bdemustats.dsps));
+	seq_printf(s, "bops\t\t%ld\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2emustats.bops),
+		   (unsigned long)__this_cpu_read(mipsr2bdemustats.bops));
+	seq_printf(s, "traps\t\t%ld\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2emustats.traps),
+		   (unsigned long)__this_cpu_read(mipsr2bdemustats.traps));
+	seq_printf(s, "fpus\t\t%ld\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2emustats.fpus),
+		   (unsigned long)__this_cpu_read(mipsr2bdemustats.fpus));
+	seq_printf(s, "loads\t\t%ld\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2emustats.loads),
+		   (unsigned long)__this_cpu_read(mipsr2bdemustats.loads));
+	seq_printf(s, "stores\t\t%ld\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2emustats.stores),
+		   (unsigned long)__this_cpu_read(mipsr2bdemustats.stores));
+	seq_printf(s, "llsc\t\t%ld\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2emustats.llsc),
+		   (unsigned long)__this_cpu_read(mipsr2bdemustats.llsc));
+	seq_printf(s, "dsemul\t\t%ld\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2emustats.dsemul),
+		   (unsigned long)__this_cpu_read(mipsr2bdemustats.dsemul));
+	seq_printf(s, "jr\t\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2bremustats.jrs));
+	seq_printf(s, "bltzl\t\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2bremustats.bltzl));
+	seq_printf(s, "bgezl\t\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2bremustats.bgezl));
+	seq_printf(s, "bltzll\t\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2bremustats.bltzll));
+	seq_printf(s, "bgezll\t\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2bremustats.bgezll));
+	seq_printf(s, "bltzal\t\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2bremustats.bltzal));
+	seq_printf(s, "bgezal\t\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2bremustats.bgezal));
+	seq_printf(s, "beql\t\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2bremustats.beql));
+	seq_printf(s, "bnel\t\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2bremustats.bnel));
+	seq_printf(s, "blezl\t\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2bremustats.blezl));
+	seq_printf(s, "bgtzl\t\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2bremustats.bgtzl));
+
+	return 0;
+}
+
+static int mipsr2_stats_clear_show(struct seq_file *s, void *unused)
+{
+	mipsr2_stats_show(s, unused);
+
+	__this_cpu_write((mipsr2emustats).movs, 0);
+	__this_cpu_write((mipsr2bdemustats).movs, 0);
+	__this_cpu_write((mipsr2emustats).hilo, 0);
+	__this_cpu_write((mipsr2bdemustats).hilo, 0);
+	__this_cpu_write((mipsr2emustats).muls, 0);
+	__this_cpu_write((mipsr2bdemustats).muls, 0);
+	__this_cpu_write((mipsr2emustats).divs, 0);
+	__this_cpu_write((mipsr2bdemustats).divs, 0);
+	__this_cpu_write((mipsr2emustats).dsps, 0);
+	__this_cpu_write((mipsr2bdemustats).dsps, 0);
+	__this_cpu_write((mipsr2emustats).bops, 0);
+	__this_cpu_write((mipsr2bdemustats).bops, 0);
+	__this_cpu_write((mipsr2emustats).traps, 0);
+	__this_cpu_write((mipsr2bdemustats).traps, 0);
+	__this_cpu_write((mipsr2emustats).fpus, 0);
+	__this_cpu_write((mipsr2bdemustats).fpus, 0);
+	__this_cpu_write((mipsr2emustats).loads, 0);
+	__this_cpu_write((mipsr2bdemustats).loads, 0);
+	__this_cpu_write((mipsr2emustats).stores, 0);
+	__this_cpu_write((mipsr2bdemustats).stores, 0);
+	__this_cpu_write((mipsr2emustats).llsc, 0);
+	__this_cpu_write((mipsr2bdemustats).llsc, 0);
+	__this_cpu_write((mipsr2emustats).dsemul, 0);
+	__this_cpu_write((mipsr2bdemustats).dsemul, 0);
+	__this_cpu_write((mipsr2bremustats).jrs, 0);
+	__this_cpu_write((mipsr2bremustats).bltzl, 0);
+	__this_cpu_write((mipsr2bremustats).bgezl, 0);
+	__this_cpu_write((mipsr2bremustats).bltzll, 0);
+	__this_cpu_write((mipsr2bremustats).bgezll, 0);
+	__this_cpu_write((mipsr2bremustats).bltzal, 0);
+	__this_cpu_write((mipsr2bremustats).bgezal, 0);
+	__this_cpu_write((mipsr2bremustats).beql, 0);
+	__this_cpu_write((mipsr2bremustats).bnel, 0);
+	__this_cpu_write((mipsr2bremustats).blezl, 0);
+	__this_cpu_write((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 81cface72bb0..ada73d288d0b 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>
@@ -837,7 +838,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;
@@ -1027,7 +1028,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;
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index bf4ccb15c541..4d32033e8081 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -48,6 +48,7 @@
 #include <asm/processor.h>
 #include <asm/fpu_emulator.h>
 #include <asm/fpu.h>
+#include <asm/mips-r2-to-r6-emul.h>
 
 #include "ieee754.h"
 
@@ -68,7 +69,7 @@ static int fpux_emu(struct pt_regs *,
 #define modeindex(v) ((v) & FPU_CSR_RM)
 
 /* convert condition code register number to csr bit */
-static const unsigned int fpucondbit[8] = {
+const unsigned int fpucondbit[8] = {
 	FPU_CSR_COND0,
 	FPU_CSR_COND1,
 	FPU_CSR_COND2,
-- 
2.2.1

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

* [PATCH RFC v2 64/70] MIPS: kernel: mips-r2-to-r6-emul: Add R2 emulator for MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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/branch.h             |    3 -
 arch/mips/include/asm/mips-r2-to-r6-emul.h |   96 ++
 arch/mips/kernel/Makefile                  |    1 +
 arch/mips/kernel/branch.c                  |    1 +
 arch/mips/kernel/mips-r2-to-r6-emul.c      | 2378 ++++++++++++++++++++++++++++
 arch/mips/kernel/traps.c                   |   28 +-
 arch/mips/math-emu/cp1emu.c                |    3 +-
 8 files changed, 2518 insertions(+), 5 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 3feabcb541c6..bfc817770e74 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -2056,6 +2056,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/branch.h b/arch/mips/include/asm/branch.h
index 2894ea58454d..de781cf54bc7 100644
--- a/arch/mips/include/asm/branch.h
+++ b/arch/mips/include/asm/branch.h
@@ -13,9 +13,6 @@
 #include <asm/ptrace.h>
 #include <asm/inst.h>
 
-static int mipsr2_emulation = 0;
-#define NO_R6EMU	(cpu_has_mips_r6 && !mipsr2_emulation)
-
 extern int __isa_exception_epc(struct pt_regs *regs);
 extern int __compute_return_epc(struct pt_regs *regs);
 extern int __compute_return_epc_for_insn(struct pt_regs *regs,
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..f66938ef80f0
--- /dev/null
+++ b/arch/mips/include/asm/mips-r2-to-r6-emul.h
@@ -0,0 +1,96 @@
+/*
+ * 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();						\
+	__this_cpu_inc(mipsr2emustats.M);				\
+	err = __get_user(nir, (u32 __user *)regs->cp0_epc);		\
+	if (!err) {							\
+		if (nir == BREAK_MATH)					\
+			__this_cpu_inc(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();					\
+	__this_cpu_inc(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 */
+
+#define NO_R6EMU	(cpu_has_mips_r6 && !mipsr2_emulation)
+
+#endif /* __ASM_MIPS_R2_TO_R6_EMUL_H */
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 0862ae781339..913a8ce41e9d 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -91,6 +91,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 02d6032e91ab..768680756b06 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -16,6 +16,7 @@
 #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>
 
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..64d17e41093b
--- /dev/null
+++ b/arch/mips/kernel/mips-r2-to-r6-emul.c
@@ -0,0 +1,2378 @@
+/*
+ * 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);
+
+extern const unsigned int fpucondbit[8];
+
+#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)__this_cpu_read(mipsr2emustats.movs),
+		   (unsigned long)__this_cpu_read(mipsr2bdemustats.movs));
+	seq_printf(s, "hilo\t\t%ld\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2emustats.hilo),
+		   (unsigned long)__this_cpu_read(mipsr2bdemustats.hilo));
+	seq_printf(s, "muls\t\t%ld\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2emustats.muls),
+		   (unsigned long)__this_cpu_read(mipsr2bdemustats.muls));
+	seq_printf(s, "divs\t\t%ld\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2emustats.divs),
+		   (unsigned long)__this_cpu_read(mipsr2bdemustats.divs));
+	seq_printf(s, "dsps\t\t%ld\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2emustats.dsps),
+		   (unsigned long)__this_cpu_read(mipsr2bdemustats.dsps));
+	seq_printf(s, "bops\t\t%ld\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2emustats.bops),
+		   (unsigned long)__this_cpu_read(mipsr2bdemustats.bops));
+	seq_printf(s, "traps\t\t%ld\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2emustats.traps),
+		   (unsigned long)__this_cpu_read(mipsr2bdemustats.traps));
+	seq_printf(s, "fpus\t\t%ld\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2emustats.fpus),
+		   (unsigned long)__this_cpu_read(mipsr2bdemustats.fpus));
+	seq_printf(s, "loads\t\t%ld\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2emustats.loads),
+		   (unsigned long)__this_cpu_read(mipsr2bdemustats.loads));
+	seq_printf(s, "stores\t\t%ld\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2emustats.stores),
+		   (unsigned long)__this_cpu_read(mipsr2bdemustats.stores));
+	seq_printf(s, "llsc\t\t%ld\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2emustats.llsc),
+		   (unsigned long)__this_cpu_read(mipsr2bdemustats.llsc));
+	seq_printf(s, "dsemul\t\t%ld\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2emustats.dsemul),
+		   (unsigned long)__this_cpu_read(mipsr2bdemustats.dsemul));
+	seq_printf(s, "jr\t\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2bremustats.jrs));
+	seq_printf(s, "bltzl\t\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2bremustats.bltzl));
+	seq_printf(s, "bgezl\t\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2bremustats.bgezl));
+	seq_printf(s, "bltzll\t\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2bremustats.bltzll));
+	seq_printf(s, "bgezll\t\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2bremustats.bgezll));
+	seq_printf(s, "bltzal\t\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2bremustats.bltzal));
+	seq_printf(s, "bgezal\t\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2bremustats.bgezal));
+	seq_printf(s, "beql\t\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2bremustats.beql));
+	seq_printf(s, "bnel\t\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2bremustats.bnel));
+	seq_printf(s, "blezl\t\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2bremustats.blezl));
+	seq_printf(s, "bgtzl\t\t%ld\n",
+		   (unsigned long)__this_cpu_read(mipsr2bremustats.bgtzl));
+
+	return 0;
+}
+
+static int mipsr2_stats_clear_show(struct seq_file *s, void *unused)
+{
+	mipsr2_stats_show(s, unused);
+
+	__this_cpu_write((mipsr2emustats).movs, 0);
+	__this_cpu_write((mipsr2bdemustats).movs, 0);
+	__this_cpu_write((mipsr2emustats).hilo, 0);
+	__this_cpu_write((mipsr2bdemustats).hilo, 0);
+	__this_cpu_write((mipsr2emustats).muls, 0);
+	__this_cpu_write((mipsr2bdemustats).muls, 0);
+	__this_cpu_write((mipsr2emustats).divs, 0);
+	__this_cpu_write((mipsr2bdemustats).divs, 0);
+	__this_cpu_write((mipsr2emustats).dsps, 0);
+	__this_cpu_write((mipsr2bdemustats).dsps, 0);
+	__this_cpu_write((mipsr2emustats).bops, 0);
+	__this_cpu_write((mipsr2bdemustats).bops, 0);
+	__this_cpu_write((mipsr2emustats).traps, 0);
+	__this_cpu_write((mipsr2bdemustats).traps, 0);
+	__this_cpu_write((mipsr2emustats).fpus, 0);
+	__this_cpu_write((mipsr2bdemustats).fpus, 0);
+	__this_cpu_write((mipsr2emustats).loads, 0);
+	__this_cpu_write((mipsr2bdemustats).loads, 0);
+	__this_cpu_write((mipsr2emustats).stores, 0);
+	__this_cpu_write((mipsr2bdemustats).stores, 0);
+	__this_cpu_write((mipsr2emustats).llsc, 0);
+	__this_cpu_write((mipsr2bdemustats).llsc, 0);
+	__this_cpu_write((mipsr2emustats).dsemul, 0);
+	__this_cpu_write((mipsr2bdemustats).dsemul, 0);
+	__this_cpu_write((mipsr2bremustats).jrs, 0);
+	__this_cpu_write((mipsr2bremustats).bltzl, 0);
+	__this_cpu_write((mipsr2bremustats).bgezl, 0);
+	__this_cpu_write((mipsr2bremustats).bltzll, 0);
+	__this_cpu_write((mipsr2bremustats).bgezll, 0);
+	__this_cpu_write((mipsr2bremustats).bltzal, 0);
+	__this_cpu_write((mipsr2bremustats).bgezal, 0);
+	__this_cpu_write((mipsr2bremustats).beql, 0);
+	__this_cpu_write((mipsr2bremustats).bnel, 0);
+	__this_cpu_write((mipsr2bremustats).blezl, 0);
+	__this_cpu_write((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 81cface72bb0..ada73d288d0b 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>
@@ -837,7 +838,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;
@@ -1027,7 +1028,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;
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index bf4ccb15c541..4d32033e8081 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -48,6 +48,7 @@
 #include <asm/processor.h>
 #include <asm/fpu_emulator.h>
 #include <asm/fpu.h>
+#include <asm/mips-r2-to-r6-emul.h>
 
 #include "ieee754.h"
 
@@ -68,7 +69,7 @@ static int fpux_emu(struct pt_regs *,
 #define modeindex(v) ((v) & FPU_CSR_RM)
 
 /* convert condition code register number to csr bit */
-static const unsigned int fpucondbit[8] = {
+const unsigned int fpucondbit[8] = {
 	FPU_CSR_COND0,
 	FPU_CSR_COND1,
 	FPU_CSR_COND2,
-- 
2.2.1

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

* [PATCH RFC v2 65/70] MIPS: Make use of the ERETNC instruction on MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 99eea59604e9..fb68fd2714fb 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 ada73d288d0b..e7ac32f3b80a 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1039,12 +1039,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.1

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

* [PATCH RFC v2 65/70] MIPS: Make use of the ERETNC instruction on MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 99eea59604e9..fb68fd2714fb 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 ada73d288d0b..e7ac32f3b80a 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1039,12 +1039,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.1

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

* [PATCH RFC v2 66/70] MIPS: Handle MIPS IV, V and R2 FPU instructions on MIPS R6 as well
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R2 FPU instructions are also present in MIPS R6 so amend the
preprocessor definitions to take MIPS R6 into consideration.

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

diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h
index 904dd1ca5cf4..3274065de231 100644
--- a/arch/mips/include/asm/cpu-features.h
+++ b/arch/mips/include/asm/cpu-features.h
@@ -217,7 +217,8 @@
 #define cpu_has_mips_4_5_r	(cpu_has_mips_4 | cpu_has_mips_5_r)
 #define cpu_has_mips_5_r	(cpu_has_mips_5 | cpu_has_mips_r)
 
-#define cpu_has_mips_4_5_r2	(cpu_has_mips_4_5 | cpu_has_mips_r2)
+#define cpu_has_mips_4_5_r2_r6	(cpu_has_mips_4_5 | cpu_has_mips_r2 | \
+				 cpu_has_mips_r6)
 
 #define cpu_has_mips32	(cpu_has_mips32r1 | cpu_has_mips32r2 | cpu_has_mips32r6)
 #define cpu_has_mips64	(cpu_has_mips64r1 | cpu_has_mips64r2 | cpu_has_mips64r6)
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 4d32033e8081..eef958edc4c7 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -1562,14 +1562,14 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 		 * achieve full IEEE-754 accuracy - however this emulator does.
 		 */
 		case frsqrt_op:
-			if (!cpu_has_mips_4_5_r2)
+			if (!cpu_has_mips_4_5_r2_r6)
 				return SIGILL;
 
 			handler.u = fpemu_sp_rsqrt;
 			goto scopuop;
 
 		case frecip_op:
-			if (!cpu_has_mips_4_5_r2)
+			if (!cpu_has_mips_4_5_r2_r6)
 				return SIGILL;
 
 			handler.u = fpemu_sp_recip;
@@ -1764,13 +1764,13 @@ copcsr:
 		 * achieve full IEEE-754 accuracy - however this emulator does.
 		 */
 		case frsqrt_op:
-			if (!cpu_has_mips_4_5_r2)
+			if (!cpu_has_mips_4_5_r2_r6)
 				return SIGILL;
 
 			handler.u = fpemu_dp_rsqrt;
 			goto dcopuop;
 		case frecip_op:
-			if (!cpu_has_mips_4_5_r2)
+			if (!cpu_has_mips_4_5_r2_r6)
 				return SIGILL;
 
 			handler.u = fpemu_dp_recip;
-- 
2.2.1

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

* [PATCH RFC v2 66/70] MIPS: Handle MIPS IV, V and R2 FPU instructions on MIPS R6 as well
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

MIPS R2 FPU instructions are also present in MIPS R6 so amend the
preprocessor definitions to take MIPS R6 into consideration.

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

diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h
index 904dd1ca5cf4..3274065de231 100644
--- a/arch/mips/include/asm/cpu-features.h
+++ b/arch/mips/include/asm/cpu-features.h
@@ -217,7 +217,8 @@
 #define cpu_has_mips_4_5_r	(cpu_has_mips_4 | cpu_has_mips_5_r)
 #define cpu_has_mips_5_r	(cpu_has_mips_5 | cpu_has_mips_r)
 
-#define cpu_has_mips_4_5_r2	(cpu_has_mips_4_5 | cpu_has_mips_r2)
+#define cpu_has_mips_4_5_r2_r6	(cpu_has_mips_4_5 | cpu_has_mips_r2 | \
+				 cpu_has_mips_r6)
 
 #define cpu_has_mips32	(cpu_has_mips32r1 | cpu_has_mips32r2 | cpu_has_mips32r6)
 #define cpu_has_mips64	(cpu_has_mips64r1 | cpu_has_mips64r2 | cpu_has_mips64r6)
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 4d32033e8081..eef958edc4c7 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -1562,14 +1562,14 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 		 * achieve full IEEE-754 accuracy - however this emulator does.
 		 */
 		case frsqrt_op:
-			if (!cpu_has_mips_4_5_r2)
+			if (!cpu_has_mips_4_5_r2_r6)
 				return SIGILL;
 
 			handler.u = fpemu_sp_rsqrt;
 			goto scopuop;
 
 		case frecip_op:
-			if (!cpu_has_mips_4_5_r2)
+			if (!cpu_has_mips_4_5_r2_r6)
 				return SIGILL;
 
 			handler.u = fpemu_sp_recip;
@@ -1764,13 +1764,13 @@ copcsr:
 		 * achieve full IEEE-754 accuracy - however this emulator does.
 		 */
 		case frsqrt_op:
-			if (!cpu_has_mips_4_5_r2)
+			if (!cpu_has_mips_4_5_r2_r6)
 				return SIGILL;
 
 			handler.u = fpemu_dp_rsqrt;
 			goto dcopuop;
 		case frecip_op:
-			if (!cpu_has_mips_4_5_r2)
+			if (!cpu_has_mips_4_5_r2_r6)
 				return SIGILL;
 
 			handler.u = fpemu_dp_recip;
-- 
2.2.1

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

* [PATCH RFC v2 67/70] MIPS: kernel: process: Do not allow FR=0 on MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Paul Burton, Matthew Fortune

A prctl() call to set FR=0 for MIPS R6 should not be allowed
since FR=1 is the only option for R6 cores.

Cc: Paul Burton <paul.burton@imgtec.com>
Cc: Matthew Fortune <matthew.fortune@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/fpu.h | 3 ++-
 arch/mips/kernel/process.c  | 4 ++++
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/arch/mips/include/asm/fpu.h b/arch/mips/include/asm/fpu.h
index 994d21939676..b96d9d327626 100644
--- a/arch/mips/include/asm/fpu.h
+++ b/arch/mips/include/asm/fpu.h
@@ -68,7 +68,8 @@ static inline int __enable_fpu(enum fpu_mode mode)
 		goto fr_common;
 
 	case FPU_64BIT:
-#if !(defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_64BIT))
+#if !(defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_CPU_MIPS32_R6) \
+      || defined(CONFIG_64BIT))
 		/* we only have a 32-bit FPU */
 		return SIGFPE;
 #endif
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index b732c0ce2e56..41ebd5d0ac30 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -581,6 +581,10 @@ int mips_set_process_fp_mode(struct task_struct *task, unsigned int value)
 	if ((value & PR_FP_MODE_FRE) && !cpu_has_fre)
 		return -EOPNOTSUPP;
 
+	/* FR = 0 not supported in MIPS R6 */
+	if (!(value & PR_FP_MODE_FR) && cpu_has_fpu && cpu_has_mips_r6)
+		return -EOPNOTSUPP;
+
 	/* Save FP & vector context, then disable FPU & MSA */
 	if (task->signal == current->signal)
 		lose_fpu(1);
-- 
2.2.1

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

* [PATCH RFC v2 67/70] MIPS: kernel: process: Do not allow FR=0 on MIPS R6
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Paul Burton, Matthew Fortune

A prctl() call to set FR=0 for MIPS R6 should not be allowed
since FR=1 is the only option for R6 cores.

Cc: Paul Burton <paul.burton@imgtec.com>
Cc: Matthew Fortune <matthew.fortune@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/fpu.h | 3 ++-
 arch/mips/kernel/process.c  | 4 ++++
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/arch/mips/include/asm/fpu.h b/arch/mips/include/asm/fpu.h
index 994d21939676..b96d9d327626 100644
--- a/arch/mips/include/asm/fpu.h
+++ b/arch/mips/include/asm/fpu.h
@@ -68,7 +68,8 @@ static inline int __enable_fpu(enum fpu_mode mode)
 		goto fr_common;
 
 	case FPU_64BIT:
-#if !(defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_64BIT))
+#if !(defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_CPU_MIPS32_R6) \
+      || defined(CONFIG_64BIT))
 		/* we only have a 32-bit FPU */
 		return SIGFPE;
 #endif
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index b732c0ce2e56..41ebd5d0ac30 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -581,6 +581,10 @@ int mips_set_process_fp_mode(struct task_struct *task, unsigned int value)
 	if ((value & PR_FP_MODE_FRE) && !cpu_has_fre)
 		return -EOPNOTSUPP;
 
+	/* FR = 0 not supported in MIPS R6 */
+	if (!(value & PR_FP_MODE_FR) && cpu_has_fpu && cpu_has_mips_r6)
+		return -EOPNOTSUPP;
+
 	/* Save FP & vector context, then disable FPU & MSA */
 	if (task->signal == current->signal)
 		lose_fpu(1);
-- 
2.2.1

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

* [PATCH RFC v2 68/70] MIPS: kernel: elf: Improve the overall ABI and FPU mode checks
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Matthew Fortune, Paul Burton

The previous implementation did not cover all possible FPU combinations
and it silently allowed ABI incompatible objects to be loaded with the
wrong ABI. For example, the previous logic would set the FP_64 ABI as
the matching ABI for an FP_XX object combined with an FP_64A object.
This was wrong, and the matching ABI should have been FP_64A.
The previous logic is now replaced with a new one which determines
the appropriate FPU mode to be used rather than the FP ABI. This has
the advantage that the entire logic is much simpler since it is the FPU
mode we are interested in rather than the FP ABI resulting to code
simplifications.

Cc: Matthew Fortune <Matthew.Fortune@imgtec.com>
Cc: Paul Burton <paul.burton@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/elf.h |  10 +-
 arch/mips/kernel/elf.c      | 284 ++++++++++++++++++++++++++------------------
 2 files changed, 177 insertions(+), 117 deletions(-)

diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h
index eb4d95de619c..ee5e6d250487 100644
--- a/arch/mips/include/asm/elf.h
+++ b/arch/mips/include/asm/elf.h
@@ -192,6 +192,8 @@ struct mips_elf_abiflags_v0 {
 	uint32_t flags2;
 };
 
+#define MIPS_ABI_FP_UNKNOWN	(-1)	/* Unknown FP ABI (kernel internal) */
+
 #define MIPS_ABI_FP_ANY		0	/* FP ABI doesn't matter */
 #define MIPS_ABI_FP_DOUBLE	1	/* -mdouble-float */
 #define MIPS_ABI_FP_SINGLE	2	/* -msingle-float */
@@ -417,13 +419,13 @@ extern unsigned long arch_randomize_brk(struct mm_struct *mm);
 struct arch_elf_state {
 	int fp_abi;
 	int interp_fp_abi;
-	int overall_abi;
+	int overall_fp_mode;
 };
 
 #define INIT_ARCH_ELF_STATE {			\
-	.fp_abi = -1,				\
-	.interp_fp_abi = -1,			\
-	.overall_abi = -1,			\
+	.fp_abi = MIPS_ABI_FP_UNKNOWN,		\
+	.interp_fp_abi = MIPS_ABI_FP_UNKNOWN,	\
+	.overall_fp_mode = -1,			\
 }
 
 extern int arch_elf_pt_proc(void *ehdr, void *phdr, struct file *elf,
diff --git a/arch/mips/kernel/elf.c b/arch/mips/kernel/elf.c
index c92b15df6893..2ac33d2375ca 100644
--- a/arch/mips/kernel/elf.c
+++ b/arch/mips/kernel/elf.c
@@ -11,29 +11,102 @@
 #include <linux/elf.h>
 #include <linux/sched.h>
 
+/* FPU modes */
 enum {
-	FP_ERROR = -1,
-	FP_DOUBLE_64A = -2,
+	FP_FRE,
+	FP_FR0,
+	FP_FR1,
 };
 
+/**
+ * struct mode_req - ABI FPU mode requirements
+ * @single:	The program being loaded needs an FPU but it will only issue
+ *		single precision instructions meaning that it can execute in
+ *		either FR0 or FR1.
+ * @soft:	The soft(-float) requirement means that the program being
+ *		loaded needs has no FPU dependency at all (i.e. it has no
+ *		FPU instructions).
+ * @fr1:	The program being loaded depends on FPU being in FR=1 mode.
+ * @frdefault:	The program being loaded depends on the default FPU mode.
+ *		That is FR0 for O32 and FR1 for N32/N64.
+ * @fre:	The program being loaded depends on FPU with FRE=1. This mode is
+ *		a bridge which uses FR=1 whilst still being able to maintain
+ *		full compatibility with pre-existing code using the O32 FP32
+ *		ABI.
+ *
+ * More information about the FP ABIs can be found here:
+ *
+ * https://dmz-portal.mips.com/wiki/MIPS_O32_ABI_-_FR0_and_FR1_Interlinking#10.4.1._Basic_mode_set-up
+ *
+ */
+
+struct mode_req {
+	bool single;
+	bool soft;
+	bool fr1;
+	bool frdefault;
+	bool fre;
+};
+
+static const struct mode_req fpu_reqs[] = {
+	[MIPS_ABI_FP_ANY]    = { true,  true,  true,  true,  true  },
+	[MIPS_ABI_FP_DOUBLE] = { false, false, false, true,  true  },
+	[MIPS_ABI_FP_SINGLE] = { true,  false, false, false, false },
+	[MIPS_ABI_FP_SOFT]   = { false, true,  false, false, false },
+	[MIPS_ABI_FP_OLD_64] = { false, false, false, false, false },
+	[MIPS_ABI_FP_XX]     = { false, false, true,  true,  true  },
+	[MIPS_ABI_FP_64]     = { false, false, true,  false, false },
+	[MIPS_ABI_FP_64A]    = { false, false, true,  false, true  }
+};
+
+/*
+ * Mode requirements when .MIPS.abiflags is not present in the ELF.
+ * Not present means that everything is acceptable except FR1.
+ */
+static struct mode_req none_req = { true, true, false, true, true };
+
 int arch_elf_pt_proc(void *_ehdr, void *_phdr, struct file *elf,
 		     bool is_interp, struct arch_elf_state *state)
 {
-	struct elfhdr *ehdr = _ehdr;
-	struct elf_phdr *phdr = _phdr;
+	struct elf32_hdr *ehdr32 = _ehdr;
+	struct elf32_phdr *phdr32 = _phdr;
+	struct elf64_phdr *phdr64 = _phdr;
 	struct mips_elf_abiflags_v0 abiflags;
 	int ret;
 
-	if (config_enabled(CONFIG_64BIT) &&
-	    (ehdr->e_ident[EI_CLASS] != ELFCLASS32))
-		return 0;
-	if (phdr->p_type != PT_MIPS_ABIFLAGS)
-		return 0;
-	if (phdr->p_filesz < sizeof(abiflags))
-		return -EINVAL;
+	/* Lets see if this is an O32 ELF */
+	if (ehdr32->e_ident[EI_CLASS] == ELFCLASS32) {
+		/* FR = 1 for N32 */
+		if (ehdr32->e_flags & EF_MIPS_ABI2)
+			state->overall_fp_mode = FP_FR1;
+		else
+			/* Set a good default FPU mode for O32*/
+			state->overall_fp_mode = cpu_has_mips_r6 ?
+				FP_FRE : FP_FR0;
+
+		if (phdr32->p_type != PT_MIPS_ABIFLAGS)
+			return 0;
+
+		if (phdr32->p_filesz < sizeof(abiflags))
+			return -EINVAL;
+
+		ret = kernel_read(elf, phdr32->p_offset,
+				  (char *)&abiflags,
+				  sizeof(abiflags));
+	} else {
+		/* FR=1 is really the only option for 64-bit */
+		state->overall_fp_mode = FP_FR1;
+
+		if (phdr64->p_type != PT_MIPS_ABIFLAGS)
+			return 0;
+		if (phdr64->p_filesz < sizeof(abiflags))
+			return -EINVAL;
+
+		ret = kernel_read(elf, phdr64->p_offset,
+				  (char *)&abiflags,
+				  sizeof(abiflags));
+	}
 
-	ret = kernel_read(elf, phdr->p_offset, (char *)&abiflags,
-			  sizeof(abiflags));
 	if (ret < 0)
 		return ret;
 	if (ret != sizeof(abiflags))
@@ -48,30 +121,26 @@ int arch_elf_pt_proc(void *_ehdr, void *_phdr, struct file *elf,
 	return 0;
 }
 
-static inline unsigned get_fp_abi(struct elfhdr *ehdr, int in_abi)
+static inline unsigned get_fp_abi(struct elf32_hdr *ehdr, int in_abi)
 {
 	/* If the ABI requirement is provided, simply return that */
-	if (in_abi != -1)
+	if (in_abi != MIPS_ABI_FP_UNKNOWN)
 		return in_abi;
 
 	/* If the EF_MIPS_FP64 flag was set, return MIPS_ABI_FP_64 */
 	if (ehdr->e_flags & EF_MIPS_FP64)
-		return MIPS_ABI_FP_64;
+		return MIPS_ABI_FP_OLD_64;
 
-	/* Default to MIPS_ABI_FP_DOUBLE */
-	return MIPS_ABI_FP_DOUBLE;
+	/* Unknown ABI */
+	return MIPS_ABI_FP_UNKNOWN;
 }
 
 int arch_check_elf(void *_ehdr, bool has_interpreter,
 		   struct arch_elf_state *state)
 {
-	struct elfhdr *ehdr = _ehdr;
-	unsigned fp_abi, interp_fp_abi, abi0, abi1;
-
-	/* Ignore non-O32 binaries */
-	if (config_enabled(CONFIG_64BIT) &&
-	    (ehdr->e_ident[EI_CLASS] != ELFCLASS32))
-		return 0;
+	struct elf32_hdr *ehdr = _ehdr;
+	struct mode_req prog_req, interp_req;
+	unsigned fp_abi, interp_fp_abi, abi0, abi1, max_abi;
 
 	fp_abi = get_fp_abi(ehdr, state->fp_abi);
 
@@ -84,108 +153,97 @@ int arch_check_elf(void *_ehdr, bool has_interpreter,
 		abi0 = abi1 = fp_abi;
 	}
 
-	state->overall_abi = FP_ERROR;
-
-	if (abi0 == abi1) {
-		state->overall_abi = abi0;
-	} else if (abi0 == MIPS_ABI_FP_ANY) {
-		state->overall_abi = abi1;
-	} else if (abi0 == MIPS_ABI_FP_DOUBLE) {
-		switch (abi1) {
-		case MIPS_ABI_FP_XX:
-			state->overall_abi = MIPS_ABI_FP_DOUBLE;
-			break;
-
-		case MIPS_ABI_FP_64A:
-			state->overall_abi = FP_DOUBLE_64A;
-			break;
-		}
-	} else if (abi0 == MIPS_ABI_FP_SINGLE ||
-		   abi0 == MIPS_ABI_FP_SOFT) {
-		/* Cannot link with other ABIs */
-	} else if (abi0 == MIPS_ABI_FP_OLD_64) {
-		switch (abi1) {
-		case MIPS_ABI_FP_XX:
-		case MIPS_ABI_FP_64:
-		case MIPS_ABI_FP_64A:
-			state->overall_abi = MIPS_ABI_FP_64;
-			break;
-		}
-	} else if (abi0 == MIPS_ABI_FP_XX ||
-		   abi0 == MIPS_ABI_FP_64 ||
-		   abi0 == MIPS_ABI_FP_64A) {
-		state->overall_abi = MIPS_ABI_FP_64;
-	}
+	/* ABI limits. O32 = FP_64A, N32/N64 = FP_SOFT */
+	max_abi = ((ehdr->e_ident[EI_CLASS] == ELFCLASS32) &&
+		   (!(ehdr->e_flags & EF_MIPS_ABI2))) ?
+		MIPS_ABI_FP_64A : MIPS_ABI_FP_SOFT;
 
-	switch (state->overall_abi) {
-	case MIPS_ABI_FP_64:
-	case MIPS_ABI_FP_64A:
-	case FP_DOUBLE_64A:
-		if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
-			return -ELIBBAD;
-		break;
+	if ((abi0 > max_abi && abi0 != MIPS_ABI_FP_UNKNOWN) ||
+	    (abi1 > max_abi && abi1 != MIPS_ABI_FP_UNKNOWN))
+		return -ELIBBAD;
 
-	case FP_ERROR:
+	/* It's time to determine the FPU mode requirements */
+	prog_req = (abi0 == MIPS_ABI_FP_UNKNOWN) ? none_req : fpu_reqs[abi0];
+	interp_req = (abi1 == MIPS_ABI_FP_UNKNOWN) ? none_req : fpu_reqs[abi1];
+
+	/*
+	 * Check whether the program's and interp's ABIs have a matching FPU
+	 * mode requirement.
+	 */
+	prog_req.single = interp_req.single && prog_req.single;
+	prog_req.soft = interp_req.soft && prog_req.soft;
+	prog_req.fr1 = interp_req.fr1 && prog_req.fr1;
+	prog_req.frdefault = interp_req.frdefault && prog_req.frdefault;
+	prog_req.fre = interp_req.fre && prog_req.fre;
+
+	/*
+	 * Determine the desired FPU mode
+	 *
+	 * Decision making:
+	 *
+	 * - We want FR_FRE if FR=1 and FR=0 are both false. This means
+	 *   that we don't have a single matching FR mode to satisfy
+	 *   the requirements so our only solution is to use the emulated
+	 *   mode
+	 * - If FR1 and FRDEFAULT is true, that means we hit the any-abi or
+	 *   fpxx case. This is because, in any-ABI (or no-ABI) we have no FPU
+	 *   instructions so we don't care about the mode. We will simply use
+	 *   the one preferred by the hardware. In fpxx case, that ABI can
+	 *   handle both FR=1 and FR=0, so, again, we simply choose the one
+	 *   preferred by the hardware. Next, if we only use single-precision
+	 *   FPU instructions, and the default ABI FPU mode is not good
+	 *   (ie single + any ABI combination), we set again the FPU mode to the
+	 *   one is preferred by the hardware.
+	 * - We want FP_FR1 if that's the only matching mode and the default one
+	 *   is not good.
+	 * - Return with -ELIBADD if we can't find a matching FPU mode.
+	 */
+	if (prog_req.fre && !prog_req.frdefault && !prog_req.fr1)
+		state->overall_fp_mode = FP_FRE;
+	else if ((prog_req.fr1 && prog_req.frdefault) ||
+		 (prog_req.single && !prog_req.frdefault))
+		/* Make sure 64-bit MIPS III/IV will not pick FR1 */
+		state->overall_fp_mode = ((current_cpu_data.fpu_id & MIPS_FPIR_F64) &&
+					  (cpu_has_mips_r2 || cpu_has_mips_r6)) ?
+					  FP_FR1 : FP_FR0;
+	else if (prog_req.fr1)
+		state->overall_fp_mode = FP_FR1;
+	else  if (!prog_req.fre && !prog_req.frdefault &&
+		  !prog_req.fr1 && !prog_req.single && !prog_req.soft)
 		return -ELIBBAD;
-	}
 
 	return 0;
 }
 
-void mips_set_personality_fp(struct arch_elf_state *state)
+static inline void set_thread_fp_mode(int hybrid, int regs32)
 {
-	if (config_enabled(CONFIG_FP32XX_HYBRID_FPRS)) {
-		/*
-		 * Use hybrid FPRs for all code which can correctly execute
-		 * with that mode.
-		 */
-		switch (state->overall_abi) {
-		case MIPS_ABI_FP_DOUBLE:
-		case MIPS_ABI_FP_SINGLE:
-		case MIPS_ABI_FP_SOFT:
-		case MIPS_ABI_FP_XX:
-		case MIPS_ABI_FP_ANY:
-			/* FR=1, FRE=1 */
-			clear_thread_flag(TIF_32BIT_FPREGS);
-			set_thread_flag(TIF_HYBRID_FPREGS);
-			return;
-		}
-	}
-
-	switch (state->overall_abi) {
-	case MIPS_ABI_FP_DOUBLE:
-	case MIPS_ABI_FP_SINGLE:
-	case MIPS_ABI_FP_SOFT:
-		/* FR=0 */
-		set_thread_flag(TIF_32BIT_FPREGS);
+	if (hybrid)
+		set_thread_flag(TIF_HYBRID_FPREGS);
+	else
 		clear_thread_flag(TIF_HYBRID_FPREGS);
-		break;
-
-	case FP_DOUBLE_64A:
-		/* FR=1, FRE=1 */
+	if (regs32)
+		set_thread_flag(TIF_32BIT_FPREGS);
+	else
 		clear_thread_flag(TIF_32BIT_FPREGS);
-		set_thread_flag(TIF_HYBRID_FPREGS);
-		break;
+}
 
-	case MIPS_ABI_FP_64:
-	case MIPS_ABI_FP_64A:
-		/* FR=1, FRE=0 */
-		clear_thread_flag(TIF_32BIT_FPREGS);
-		clear_thread_flag(TIF_HYBRID_FPREGS);
+void mips_set_personality_fp(struct arch_elf_state *state)
+{
+	/*
+	 * This function is only ever called for O32 ELFs so we should
+	 * not be worried about N32/N64 binaries.
+	 */
+	switch (state->overall_fp_mode) {
+	case FP_FRE:
+		set_thread_fp_mode(1, 0);
 		break;
-
-	case MIPS_ABI_FP_XX:
-	case MIPS_ABI_FP_ANY:
-		if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
-			set_thread_flag(TIF_32BIT_FPREGS);
-		else
-			clear_thread_flag(TIF_32BIT_FPREGS);
-
-		clear_thread_flag(TIF_HYBRID_FPREGS);
+	case FP_FR0:
+		set_thread_fp_mode(0, 1);
+		break;
+	case FP_FR1:
+		set_thread_fp_mode(0, 0);
 		break;
-
 	default:
-	case FP_ERROR:
 		BUG();
 	}
 }
-- 
2.2.1

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

* [PATCH RFC v2 68/70] MIPS: kernel: elf: Improve the overall ABI and FPU mode checks
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Matthew Fortune, Paul Burton

The previous implementation did not cover all possible FPU combinations
and it silently allowed ABI incompatible objects to be loaded with the
wrong ABI. For example, the previous logic would set the FP_64 ABI as
the matching ABI for an FP_XX object combined with an FP_64A object.
This was wrong, and the matching ABI should have been FP_64A.
The previous logic is now replaced with a new one which determines
the appropriate FPU mode to be used rather than the FP ABI. This has
the advantage that the entire logic is much simpler since it is the FPU
mode we are interested in rather than the FP ABI resulting to code
simplifications.

Cc: Matthew Fortune <Matthew.Fortune@imgtec.com>
Cc: Paul Burton <paul.burton@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/elf.h |  10 +-
 arch/mips/kernel/elf.c      | 284 ++++++++++++++++++++++++++------------------
 2 files changed, 177 insertions(+), 117 deletions(-)

diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h
index eb4d95de619c..ee5e6d250487 100644
--- a/arch/mips/include/asm/elf.h
+++ b/arch/mips/include/asm/elf.h
@@ -192,6 +192,8 @@ struct mips_elf_abiflags_v0 {
 	uint32_t flags2;
 };
 
+#define MIPS_ABI_FP_UNKNOWN	(-1)	/* Unknown FP ABI (kernel internal) */
+
 #define MIPS_ABI_FP_ANY		0	/* FP ABI doesn't matter */
 #define MIPS_ABI_FP_DOUBLE	1	/* -mdouble-float */
 #define MIPS_ABI_FP_SINGLE	2	/* -msingle-float */
@@ -417,13 +419,13 @@ extern unsigned long arch_randomize_brk(struct mm_struct *mm);
 struct arch_elf_state {
 	int fp_abi;
 	int interp_fp_abi;
-	int overall_abi;
+	int overall_fp_mode;
 };
 
 #define INIT_ARCH_ELF_STATE {			\
-	.fp_abi = -1,				\
-	.interp_fp_abi = -1,			\
-	.overall_abi = -1,			\
+	.fp_abi = MIPS_ABI_FP_UNKNOWN,		\
+	.interp_fp_abi = MIPS_ABI_FP_UNKNOWN,	\
+	.overall_fp_mode = -1,			\
 }
 
 extern int arch_elf_pt_proc(void *ehdr, void *phdr, struct file *elf,
diff --git a/arch/mips/kernel/elf.c b/arch/mips/kernel/elf.c
index c92b15df6893..2ac33d2375ca 100644
--- a/arch/mips/kernel/elf.c
+++ b/arch/mips/kernel/elf.c
@@ -11,29 +11,102 @@
 #include <linux/elf.h>
 #include <linux/sched.h>
 
+/* FPU modes */
 enum {
-	FP_ERROR = -1,
-	FP_DOUBLE_64A = -2,
+	FP_FRE,
+	FP_FR0,
+	FP_FR1,
 };
 
+/**
+ * struct mode_req - ABI FPU mode requirements
+ * @single:	The program being loaded needs an FPU but it will only issue
+ *		single precision instructions meaning that it can execute in
+ *		either FR0 or FR1.
+ * @soft:	The soft(-float) requirement means that the program being
+ *		loaded needs has no FPU dependency at all (i.e. it has no
+ *		FPU instructions).
+ * @fr1:	The program being loaded depends on FPU being in FR=1 mode.
+ * @frdefault:	The program being loaded depends on the default FPU mode.
+ *		That is FR0 for O32 and FR1 for N32/N64.
+ * @fre:	The program being loaded depends on FPU with FRE=1. This mode is
+ *		a bridge which uses FR=1 whilst still being able to maintain
+ *		full compatibility with pre-existing code using the O32 FP32
+ *		ABI.
+ *
+ * More information about the FP ABIs can be found here:
+ *
+ * https://dmz-portal.mips.com/wiki/MIPS_O32_ABI_-_FR0_and_FR1_Interlinking#10.4.1._Basic_mode_set-up
+ *
+ */
+
+struct mode_req {
+	bool single;
+	bool soft;
+	bool fr1;
+	bool frdefault;
+	bool fre;
+};
+
+static const struct mode_req fpu_reqs[] = {
+	[MIPS_ABI_FP_ANY]    = { true,  true,  true,  true,  true  },
+	[MIPS_ABI_FP_DOUBLE] = { false, false, false, true,  true  },
+	[MIPS_ABI_FP_SINGLE] = { true,  false, false, false, false },
+	[MIPS_ABI_FP_SOFT]   = { false, true,  false, false, false },
+	[MIPS_ABI_FP_OLD_64] = { false, false, false, false, false },
+	[MIPS_ABI_FP_XX]     = { false, false, true,  true,  true  },
+	[MIPS_ABI_FP_64]     = { false, false, true,  false, false },
+	[MIPS_ABI_FP_64A]    = { false, false, true,  false, true  }
+};
+
+/*
+ * Mode requirements when .MIPS.abiflags is not present in the ELF.
+ * Not present means that everything is acceptable except FR1.
+ */
+static struct mode_req none_req = { true, true, false, true, true };
+
 int arch_elf_pt_proc(void *_ehdr, void *_phdr, struct file *elf,
 		     bool is_interp, struct arch_elf_state *state)
 {
-	struct elfhdr *ehdr = _ehdr;
-	struct elf_phdr *phdr = _phdr;
+	struct elf32_hdr *ehdr32 = _ehdr;
+	struct elf32_phdr *phdr32 = _phdr;
+	struct elf64_phdr *phdr64 = _phdr;
 	struct mips_elf_abiflags_v0 abiflags;
 	int ret;
 
-	if (config_enabled(CONFIG_64BIT) &&
-	    (ehdr->e_ident[EI_CLASS] != ELFCLASS32))
-		return 0;
-	if (phdr->p_type != PT_MIPS_ABIFLAGS)
-		return 0;
-	if (phdr->p_filesz < sizeof(abiflags))
-		return -EINVAL;
+	/* Lets see if this is an O32 ELF */
+	if (ehdr32->e_ident[EI_CLASS] == ELFCLASS32) {
+		/* FR = 1 for N32 */
+		if (ehdr32->e_flags & EF_MIPS_ABI2)
+			state->overall_fp_mode = FP_FR1;
+		else
+			/* Set a good default FPU mode for O32*/
+			state->overall_fp_mode = cpu_has_mips_r6 ?
+				FP_FRE : FP_FR0;
+
+		if (phdr32->p_type != PT_MIPS_ABIFLAGS)
+			return 0;
+
+		if (phdr32->p_filesz < sizeof(abiflags))
+			return -EINVAL;
+
+		ret = kernel_read(elf, phdr32->p_offset,
+				  (char *)&abiflags,
+				  sizeof(abiflags));
+	} else {
+		/* FR=1 is really the only option for 64-bit */
+		state->overall_fp_mode = FP_FR1;
+
+		if (phdr64->p_type != PT_MIPS_ABIFLAGS)
+			return 0;
+		if (phdr64->p_filesz < sizeof(abiflags))
+			return -EINVAL;
+
+		ret = kernel_read(elf, phdr64->p_offset,
+				  (char *)&abiflags,
+				  sizeof(abiflags));
+	}
 
-	ret = kernel_read(elf, phdr->p_offset, (char *)&abiflags,
-			  sizeof(abiflags));
 	if (ret < 0)
 		return ret;
 	if (ret != sizeof(abiflags))
@@ -48,30 +121,26 @@ int arch_elf_pt_proc(void *_ehdr, void *_phdr, struct file *elf,
 	return 0;
 }
 
-static inline unsigned get_fp_abi(struct elfhdr *ehdr, int in_abi)
+static inline unsigned get_fp_abi(struct elf32_hdr *ehdr, int in_abi)
 {
 	/* If the ABI requirement is provided, simply return that */
-	if (in_abi != -1)
+	if (in_abi != MIPS_ABI_FP_UNKNOWN)
 		return in_abi;
 
 	/* If the EF_MIPS_FP64 flag was set, return MIPS_ABI_FP_64 */
 	if (ehdr->e_flags & EF_MIPS_FP64)
-		return MIPS_ABI_FP_64;
+		return MIPS_ABI_FP_OLD_64;
 
-	/* Default to MIPS_ABI_FP_DOUBLE */
-	return MIPS_ABI_FP_DOUBLE;
+	/* Unknown ABI */
+	return MIPS_ABI_FP_UNKNOWN;
 }
 
 int arch_check_elf(void *_ehdr, bool has_interpreter,
 		   struct arch_elf_state *state)
 {
-	struct elfhdr *ehdr = _ehdr;
-	unsigned fp_abi, interp_fp_abi, abi0, abi1;
-
-	/* Ignore non-O32 binaries */
-	if (config_enabled(CONFIG_64BIT) &&
-	    (ehdr->e_ident[EI_CLASS] != ELFCLASS32))
-		return 0;
+	struct elf32_hdr *ehdr = _ehdr;
+	struct mode_req prog_req, interp_req;
+	unsigned fp_abi, interp_fp_abi, abi0, abi1, max_abi;
 
 	fp_abi = get_fp_abi(ehdr, state->fp_abi);
 
@@ -84,108 +153,97 @@ int arch_check_elf(void *_ehdr, bool has_interpreter,
 		abi0 = abi1 = fp_abi;
 	}
 
-	state->overall_abi = FP_ERROR;
-
-	if (abi0 == abi1) {
-		state->overall_abi = abi0;
-	} else if (abi0 == MIPS_ABI_FP_ANY) {
-		state->overall_abi = abi1;
-	} else if (abi0 == MIPS_ABI_FP_DOUBLE) {
-		switch (abi1) {
-		case MIPS_ABI_FP_XX:
-			state->overall_abi = MIPS_ABI_FP_DOUBLE;
-			break;
-
-		case MIPS_ABI_FP_64A:
-			state->overall_abi = FP_DOUBLE_64A;
-			break;
-		}
-	} else if (abi0 == MIPS_ABI_FP_SINGLE ||
-		   abi0 == MIPS_ABI_FP_SOFT) {
-		/* Cannot link with other ABIs */
-	} else if (abi0 == MIPS_ABI_FP_OLD_64) {
-		switch (abi1) {
-		case MIPS_ABI_FP_XX:
-		case MIPS_ABI_FP_64:
-		case MIPS_ABI_FP_64A:
-			state->overall_abi = MIPS_ABI_FP_64;
-			break;
-		}
-	} else if (abi0 == MIPS_ABI_FP_XX ||
-		   abi0 == MIPS_ABI_FP_64 ||
-		   abi0 == MIPS_ABI_FP_64A) {
-		state->overall_abi = MIPS_ABI_FP_64;
-	}
+	/* ABI limits. O32 = FP_64A, N32/N64 = FP_SOFT */
+	max_abi = ((ehdr->e_ident[EI_CLASS] == ELFCLASS32) &&
+		   (!(ehdr->e_flags & EF_MIPS_ABI2))) ?
+		MIPS_ABI_FP_64A : MIPS_ABI_FP_SOFT;
 
-	switch (state->overall_abi) {
-	case MIPS_ABI_FP_64:
-	case MIPS_ABI_FP_64A:
-	case FP_DOUBLE_64A:
-		if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
-			return -ELIBBAD;
-		break;
+	if ((abi0 > max_abi && abi0 != MIPS_ABI_FP_UNKNOWN) ||
+	    (abi1 > max_abi && abi1 != MIPS_ABI_FP_UNKNOWN))
+		return -ELIBBAD;
 
-	case FP_ERROR:
+	/* It's time to determine the FPU mode requirements */
+	prog_req = (abi0 == MIPS_ABI_FP_UNKNOWN) ? none_req : fpu_reqs[abi0];
+	interp_req = (abi1 == MIPS_ABI_FP_UNKNOWN) ? none_req : fpu_reqs[abi1];
+
+	/*
+	 * Check whether the program's and interp's ABIs have a matching FPU
+	 * mode requirement.
+	 */
+	prog_req.single = interp_req.single && prog_req.single;
+	prog_req.soft = interp_req.soft && prog_req.soft;
+	prog_req.fr1 = interp_req.fr1 && prog_req.fr1;
+	prog_req.frdefault = interp_req.frdefault && prog_req.frdefault;
+	prog_req.fre = interp_req.fre && prog_req.fre;
+
+	/*
+	 * Determine the desired FPU mode
+	 *
+	 * Decision making:
+	 *
+	 * - We want FR_FRE if FR=1 and FR=0 are both false. This means
+	 *   that we don't have a single matching FR mode to satisfy
+	 *   the requirements so our only solution is to use the emulated
+	 *   mode
+	 * - If FR1 and FRDEFAULT is true, that means we hit the any-abi or
+	 *   fpxx case. This is because, in any-ABI (or no-ABI) we have no FPU
+	 *   instructions so we don't care about the mode. We will simply use
+	 *   the one preferred by the hardware. In fpxx case, that ABI can
+	 *   handle both FR=1 and FR=0, so, again, we simply choose the one
+	 *   preferred by the hardware. Next, if we only use single-precision
+	 *   FPU instructions, and the default ABI FPU mode is not good
+	 *   (ie single + any ABI combination), we set again the FPU mode to the
+	 *   one is preferred by the hardware.
+	 * - We want FP_FR1 if that's the only matching mode and the default one
+	 *   is not good.
+	 * - Return with -ELIBADD if we can't find a matching FPU mode.
+	 */
+	if (prog_req.fre && !prog_req.frdefault && !prog_req.fr1)
+		state->overall_fp_mode = FP_FRE;
+	else if ((prog_req.fr1 && prog_req.frdefault) ||
+		 (prog_req.single && !prog_req.frdefault))
+		/* Make sure 64-bit MIPS III/IV will not pick FR1 */
+		state->overall_fp_mode = ((current_cpu_data.fpu_id & MIPS_FPIR_F64) &&
+					  (cpu_has_mips_r2 || cpu_has_mips_r6)) ?
+					  FP_FR1 : FP_FR0;
+	else if (prog_req.fr1)
+		state->overall_fp_mode = FP_FR1;
+	else  if (!prog_req.fre && !prog_req.frdefault &&
+		  !prog_req.fr1 && !prog_req.single && !prog_req.soft)
 		return -ELIBBAD;
-	}
 
 	return 0;
 }
 
-void mips_set_personality_fp(struct arch_elf_state *state)
+static inline void set_thread_fp_mode(int hybrid, int regs32)
 {
-	if (config_enabled(CONFIG_FP32XX_HYBRID_FPRS)) {
-		/*
-		 * Use hybrid FPRs for all code which can correctly execute
-		 * with that mode.
-		 */
-		switch (state->overall_abi) {
-		case MIPS_ABI_FP_DOUBLE:
-		case MIPS_ABI_FP_SINGLE:
-		case MIPS_ABI_FP_SOFT:
-		case MIPS_ABI_FP_XX:
-		case MIPS_ABI_FP_ANY:
-			/* FR=1, FRE=1 */
-			clear_thread_flag(TIF_32BIT_FPREGS);
-			set_thread_flag(TIF_HYBRID_FPREGS);
-			return;
-		}
-	}
-
-	switch (state->overall_abi) {
-	case MIPS_ABI_FP_DOUBLE:
-	case MIPS_ABI_FP_SINGLE:
-	case MIPS_ABI_FP_SOFT:
-		/* FR=0 */
-		set_thread_flag(TIF_32BIT_FPREGS);
+	if (hybrid)
+		set_thread_flag(TIF_HYBRID_FPREGS);
+	else
 		clear_thread_flag(TIF_HYBRID_FPREGS);
-		break;
-
-	case FP_DOUBLE_64A:
-		/* FR=1, FRE=1 */
+	if (regs32)
+		set_thread_flag(TIF_32BIT_FPREGS);
+	else
 		clear_thread_flag(TIF_32BIT_FPREGS);
-		set_thread_flag(TIF_HYBRID_FPREGS);
-		break;
+}
 
-	case MIPS_ABI_FP_64:
-	case MIPS_ABI_FP_64A:
-		/* FR=1, FRE=0 */
-		clear_thread_flag(TIF_32BIT_FPREGS);
-		clear_thread_flag(TIF_HYBRID_FPREGS);
+void mips_set_personality_fp(struct arch_elf_state *state)
+{
+	/*
+	 * This function is only ever called for O32 ELFs so we should
+	 * not be worried about N32/N64 binaries.
+	 */
+	switch (state->overall_fp_mode) {
+	case FP_FRE:
+		set_thread_fp_mode(1, 0);
 		break;
-
-	case MIPS_ABI_FP_XX:
-	case MIPS_ABI_FP_ANY:
-		if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
-			set_thread_flag(TIF_32BIT_FPREGS);
-		else
-			clear_thread_flag(TIF_32BIT_FPREGS);
-
-		clear_thread_flag(TIF_HYBRID_FPREGS);
+	case FP_FR0:
+		set_thread_fp_mode(0, 1);
+		break;
+	case FP_FR1:
+		set_thread_fp_mode(0, 0);
 		break;
-
 	default:
-	case FP_ERROR:
 		BUG();
 	}
 }
-- 
2.2.1

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

* [PATCH RFC v2 69/70] MIPS: Malta: Add support for building MIPS R6 kernel
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 bfc817770e74..be42028e11a6 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -376,8 +376,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.1

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

* [PATCH RFC v2 69/70] MIPS: Malta: Add support for building MIPS R6 kernel
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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 bfc817770e74..be42028e11a6 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -376,8 +376,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.1

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

* [PATCH RFC v2 70/70] MIPS: Add Malta QEMU 32R6 defconfig
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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.1

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

* [PATCH RFC v2 70/70] MIPS: Add Malta QEMU 32R6 defconfig
@ 2015-01-16 10:49   ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 10:49 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.1

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

* Re: [PATCH RFC v2 05/70] MIPS: mm: uasm: Add signed 9-bit immediate related macros
  2015-01-16 10:48   ` Markos Chandras
  (?)
@ 2015-01-16 11:29   ` Sergei Shtylyov
  2015-01-19 12:35       ` Markos Chandras
  -1 siblings, 1 reply; 262+ messages in thread
From: Sergei Shtylyov @ 2015-01-16 11:29 UTC (permalink / raw)
  To: Markos Chandras, linux-mips; +Cc: Leonid Yegoshin

Hello.

On 1/16/2015 1:48 PM, Markos Chandras wrote:

> 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 4adf30284813..6596b6898637 100644
> --- a/arch/mips/mm/uasm.c
> +++ b/arch/mips/mm/uasm.c
[...]
> @@ -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),

    Not 0xFF and -0x100? The values above don't fit into 9 bits...

> +	       KERN_WARNING "Micro-assembler field overflow\n");
> +
> +	return (arg & SIMM9_MASK) << SIMM9_SH;
> +}
> +
[...]

WBR, Sergei

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

* RE: [PATCH RFC v2 67/70] MIPS: kernel: process: Do not allow FR=0 on MIPS R6
  2015-01-16 10:49   ` Markos Chandras
  (?)
@ 2015-01-16 11:54   ` Matthew Fortune
  2015-01-16 15:33     ` Markos Chandras
  -1 siblings, 1 reply; 262+ messages in thread
From: Matthew Fortune @ 2015-01-16 11:54 UTC (permalink / raw)
  To: Markos Chandras, linux-mips; +Cc: Paul Burton

Markos Chandras <Markos.Chandras@imgtec.com> writes:
> diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
> index b732c0ce2e56..41ebd5d0ac30 100644
> --- a/arch/mips/kernel/process.c
> +++ b/arch/mips/kernel/process.c
> @@ -581,6 +581,10 @@ int mips_set_process_fp_mode(struct task_struct
> *task, unsigned int value)
>  	if ((value & PR_FP_MODE_FRE) && !cpu_has_fre)
>  		return -EOPNOTSUPP;

There is an inconsistency here in that the kernel will not support
emulating FRE mode when there is no FPU but will emulate FR1 or FR0
when there is no FPU.

For consistency I think we should do this for FRE:

 	if ((value & PR_FP_MODE_FRE) && cpu_has_fpu && !cpu_has_fre)
 		return -EOPNOTSUPP;

thanks,
Matthew

> 
> +	/* FR = 0 not supported in MIPS R6 */
> +	if (!(value & PR_FP_MODE_FR) && cpu_has_fpu && cpu_has_mips_r6)
> +		return -EOPNOTSUPP;
> +
>  	/* Save FP & vector context, then disable FPU & MSA */
>  	if (task->signal == current->signal)
>  		lose_fpu(1);
> --
> 2.2.1

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

* RE: [PATCH RFC v2 68/70] MIPS: kernel: elf: Improve the overall ABI and FPU mode checks
  2015-01-16 10:49   ` Markos Chandras
  (?)
@ 2015-01-16 12:28   ` Matthew Fortune
  -1 siblings, 0 replies; 262+ messages in thread
From: Matthew Fortune @ 2015-01-16 12:28 UTC (permalink / raw)
  To: Markos Chandras, linux-mips; +Cc: Paul Burton

> The previous implementation did not cover all possible FPU combinations
> and it silently allowed ABI incompatible objects to be loaded with the
> wrong ABI. For example, the previous logic would set the FP_64 ABI as
> the matching ABI for an FP_XX object combined with an FP_64A object.
> This was wrong, and the matching ABI should have been FP_64A.
> The previous logic is now replaced with a new one which determines the
> appropriate FPU mode to be used rather than the FP ABI. This has the
> advantage that the entire logic is much simpler since it is the FPU mode
> we are interested in rather than the FP ABI resulting to code
> simplifications.
> 

For the record this code has been tested against the GLIBC implementation
.MIPS.abiflags dynamic linker logic and a comprehensive ABI compatibility
testsuite posted here:

http://sourceware.org/ml/libc-alpha/2014-12/msg00852.html

> +	/* Lets see if this is an O32 ELF */
> +	if (ehdr32->e_ident[EI_CLASS] == ELFCLASS32) {
> +		/* FR = 1 for N32 */
> +		if (ehdr32->e_flags & EF_MIPS_ABI2)
> +			state->overall_fp_mode = FP_FR1;
> +		else
> +			/* Set a good default FPU mode for O32*/

Nit: spacing at the end of the comment.

>  	/* If the EF_MIPS_FP64 flag was set, return MIPS_ABI_FP_64 */

Should say return MIPS_ABI_FP_OLD_64 in the comment.

>  	if (ehdr->e_flags & EF_MIPS_FP64)
> -		return MIPS_ABI_FP_64;
> +		return MIPS_ABI_FP_OLD_64;
> 

A couple of suggestions for rewording the mode selection comments:

> +	 * - We want FR_FRE if FR=1 and FR=0 are both false. This means
> +	 *   that we don't have a single matching FR mode to satisfy
> +	 *   the requirements so our only solution is to use the emulated
> +	 *   mode

We want FR_FRE if FRE=1 is true but both FR=1 and FR=0 are false.
This means that we have a combination of program and interpreter
that inherently require the hybrid FP mode.

> +	 * - If FR1 and FRDEFAULT is true, that means we hit the any-abi or
> +	 *   fpxx case. This is because, in any-ABI (or no-ABI) we have no
> FPU
> +	 *   instructions so we don't care about the mode. We will simply
> use
> +	 *   the one preferred by the hardware. In fpxx case, that ABI can
> +	 *   handle both FR=1 and FR=0, so, again, we simply choose the one
> +	 *   preferred by the hardware. Next, if we only use single-
> precision
> +	 *   FPU instructions, and the default ABI FPU mode is not good
> +	 *   (ie single + any ABI combination), we set again the FPU mode
> to the
> +	 *   one is preferred by the hardware.

Next, if we know that the code will only use single-precision instructions,
shown by single being true but frdefault being false, then we again set
the FPU mode to the one that is preferred by the hardware.

> +	 * - We want FP_FR1 if that's the only matching mode and the
> default one
> +	 *   is not good.
> +	 * - Return with -ELIBADD if we can't find a matching FPU mode.
> +	 */
> +	if (prog_req.fre && !prog_req.frdefault && !prog_req.fr1)
> +		state->overall_fp_mode = FP_FRE;
> +	else if ((prog_req.fr1 && prog_req.frdefault) ||
> +		 (prog_req.single && !prog_req.frdefault))
> +		/* Make sure 64-bit MIPS III/IV will not pick FR1 */

This is 64-bit MIPS III/IV and MIPS64(R1)

> +		state->overall_fp_mode = ((current_cpu_data.fpu_id &
> MIPS_FPIR_F64) &&
> +					  (cpu_has_mips_r2 || cpu_has_mips_r6)) ?
> +					  FP_FR1 : FP_FR0;
> +	else if (prog_req.fr1)
> +		state->overall_fp_mode = FP_FR1;
> +	else  if (!prog_req.fre && !prog_req.frdefault &&
> +		  !prog_req.fr1 && !prog_req.single && !prog_req.soft)
>  		return -ELIBBAD;
> -	}
> 
>  	return 0;
>  }

Thanks,
Matthew

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

* Re: [PATCH RFC v2 67/70] MIPS: kernel: process: Do not allow FR=0 on MIPS R6
  2015-01-16 11:54   ` Matthew Fortune
@ 2015-01-16 15:33     ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-16 15:33 UTC (permalink / raw)
  To: Matthew Fortune, linux-mips; +Cc: Paul Burton

On 01/16/2015 11:54 AM, Matthew Fortune wrote:
> Markos Chandras <Markos.Chandras@imgtec.com> writes:
>> diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
>> index b732c0ce2e56..41ebd5d0ac30 100644
>> --- a/arch/mips/kernel/process.c
>> +++ b/arch/mips/kernel/process.c
>> @@ -581,6 +581,10 @@ int mips_set_process_fp_mode(struct task_struct
>> *task, unsigned int value)
>>  	if ((value & PR_FP_MODE_FRE) && !cpu_has_fre)
>>  		return -EOPNOTSUPP;
> 
> There is an inconsistency here in that the kernel will not support
> emulating FRE mode when there is no FPU but will emulate FR1 or FR0
> when there is no FPU.
> 
> For consistency I think we should do this for FRE:
> 
>  	if ((value & PR_FP_MODE_FRE) && cpu_has_fpu && !cpu_has_fre)
>  		return -EOPNOTSUPP;
> 
Ok I will create a separate patch for this one.

-- 
markos

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

* Re: [PATCH RFC v2 06/70] MIPS: mm: Add MIPS R6 instruction encodings
  2015-01-16 10:48   ` Markos Chandras
  (?)
@ 2015-01-16 19:15   ` David Daney
  -1 siblings, 0 replies; 262+ messages in thread
From: David Daney @ 2015-01-16 19:15 UTC (permalink / raw)
  To: Markos Chandras; +Cc: linux-mips, Leonid Yegoshin

On 01/16/2015 02:48 AM, Markos Chandras wrote:
> 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 ++++++---

We should probably split changes to uapi/asm/inst.h in to a separate 
patch from the patches to the kernel proper.

The fact that it changes (extends) a userspace ABI, makes it a candidate 
for being a standalone patch.

David Daney

>   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 89c22433b1c6..5c9e14a903af 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 8e02291cfc0c..7bb0d4ce2de8 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 },
> @@ -104,11 +125,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 },
> @@ -198,6 +228,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;
>

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

* Re: [PATCH RFC v2 40/70] MIPS: mm: page: Add MIPS R6 support
  2015-01-16 10:49   ` Markos Chandras
  (?)
@ 2015-01-17 11:58   ` Sergei Shtylyov
  2015-01-19 12:33       ` Markos Chandras
  -1 siblings, 1 reply; 262+ messages in thread
From: Sergei Shtylyov @ 2015-01-17 11:58 UTC (permalink / raw)
  To: Markos Chandras, linux-mips

Hello.

On 1/16/2015 1:49 PM, Markos Chandras wrote:

> 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..b84e0b2ce140 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 < -0x100))	\

    Please indent with tabs only. Inner () not necessary. And it looks like 
you've reversed the conditions.

> +		uasm_i_pref(a, b, c, d);	\
> +	} else {				\
> +		uasm_i_pref(a, b, c, d);	\
> +	}					\
> +} while(0)
> +
[...]

WBR, Sergei

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

* Re: [PATCH RFC v2 57/70] MIPS: Emulate the new MIPS R6 BOVC, BEQC and BEQZALC instructions
  2015-01-16 10:49   ` Markos Chandras
  (?)
@ 2015-01-17 13:24   ` Sergei Shtylyov
  2015-01-19  9:48       ` Markos Chandras
  -1 siblings, 1 reply; 262+ messages in thread
From: Sergei Shtylyov @ 2015-01-17 13:24 UTC (permalink / raw)
  To: Markos Chandras, linux-mips

Hello.

On 1/16/2015 1:49 PM, 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>

[...]

> diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
> index bf82ec302cff..c084b38e727b 100644
> --- a/arch/mips/kernel/branch.c
> +++ b/arch/mips/kernel/branch.c
> @@ -808,6 +808,17 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
>   		}
>   		regs->cp0_epc += 8;
>   		break;
> +	case cbcond0_op:
> +		/* Only valid for MIPS R6 */
> +		if (!cpu_has_mips_r6) {
> +			ret = -SIGILL;
> +			break;
> +		}
> +		/* Compact branches: bovc, beqc, beqzalc */
> +		if (insn.i_format.rt && !insn.i_format.rs)
> +			regs->regs[31] = epc + 4;

    Hm, so this instruction doesn't have delay slot?

> +		regs->cp0_epc += 8;

    Then why 8 here?

WBR, Sergei

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

* RE: [PATCH RFC v2 68/70] MIPS: kernel: elf: Improve the overall ABI and FPU mode checks
  2015-01-16 10:49   ` Markos Chandras
  (?)
  (?)
@ 2015-01-19  9:29   ` Matthew Fortune
  2015-01-19 12:17     ` Markos Chandras
  2015-02-03 12:41     ` Maciej W. Rozycki
  -1 siblings, 2 replies; 262+ messages in thread
From: Matthew Fortune @ 2015-01-19  9:29 UTC (permalink / raw)
  To: Markos Chandras, linux-mips
  Cc: Paul Burton, Maciej W. Rozycki (macro@linux-mips.org)

> The previous implementation did not cover all possible FPU combinations
> and it silently allowed ABI incompatible objects to be loaded with the
> wrong ABI. For example, the previous logic would set the FP_64 ABI as
> the matching ABI for an FP_XX object combined with an FP_64A object.
> This was wrong, and the matching ABI should have been FP_64A.
> The previous logic is now replaced with a new one which determines
> the appropriate FPU mode to be used rather than the FP ABI. This has
> the advantage that the entire logic is much simpler since it is the FPU
> mode we are interested in rather than the FP ABI resulting to code
> simplifications.

Markos,

Can you confirm that the o32 abiflags testsuite has been run on a 64-bit
kernel? I know that the o32 testsuite has run on a 32-bit kernel and the
n64 testsuite has run on a 64-bit kernel. It is certainly worth checking
given the fixes that are being made to 3.19.

Is it worth updating the CONFIG_MIPS_O32_FP64_SUPPORT option to no longer
be experimental and also default on? This option could then guard the new
logic from this patch as a safety measure. Once the code has been proven
I'd suggest removing the option and making the code unconditional.

Maciej: The comments you made here http://patchwork.linux-mips.org/patch/8932/
should be addressed by this patch. 

Thanks,
Matthew

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

* Re: [PATCH RFC v2 57/70] MIPS: Emulate the new MIPS R6 BOVC, BEQC and BEQZALC instructions
@ 2015-01-19  9:48       ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-19  9:48 UTC (permalink / raw)
  To: Sergei Shtylyov, linux-mips

On 01/17/2015 01:24 PM, Sergei Shtylyov wrote:
> Hello.
> 
> On 1/16/2015 1:49 PM, 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>
> 
> [...]
> 
>> diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
>> index bf82ec302cff..c084b38e727b 100644
>> --- a/arch/mips/kernel/branch.c
>> +++ b/arch/mips/kernel/branch.c
>> @@ -808,6 +808,17 @@ int __compute_return_epc_for_insn(struct pt_regs
>> *regs,
>>           }
>>           regs->cp0_epc += 8;
>>           break;
>> +    case cbcond0_op:
>> +        /* Only valid for MIPS R6 */
>> +        if (!cpu_has_mips_r6) {
>> +            ret = -SIGILL;
>> +            break;
>> +        }
>> +        /* Compact branches: bovc, beqc, beqzalc */
>> +        if (insn.i_format.rt && !insn.i_format.rs)
>> +            regs->regs[31] = epc + 4;
> 
>    Hm, so this instruction doesn't have delay slot?

All 3 of them have a forbidden slot. An instruction in a forbidden slot
is only executed if the branch *is not taken*.

The "if" condition above is aimed to handle the BEQZALC instruction. The
BEQZALC instruction will store the return address to the 31 register.

According to the R6 ISA this is what happens in that instruction:

GPR[31] <- PC+4
target_offset <- ...
BLTZALC: cond <- GPR[rt] < 0
if cond then
PC <- ( PC+4+ sign_extend( target_offset ) )
endif

So GPR[31] will contain the address for the forbidden slot instruction.
So in this type of branches (where the link register is used), the
forbidden slot will be executed after the branch.

However, the only way for us to be emulating a branch, is an instruction
in a forbidden slot or delay slot to have caused an exception. In case
of compact branches, when the instruction in a forbidden slot is
executed, we know we are done with the branch, because in any case, the
branch was already executed. An exception in the forbidden slot sets the
EPC back to the branch itself. So we simply handle the forbidden slot
exception, and then we do PC+8 so go past the forbidden slot instruction
that we already handled.

See

http://git.linux-mips.org/cgit/mchandras/linux.git/tree/arch/mips/kernel/branch.c?h=3.19-r6-rfc-1#n404

does that make sense?

-- 
markos

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

* Re: [PATCH RFC v2 57/70] MIPS: Emulate the new MIPS R6 BOVC, BEQC and BEQZALC instructions
@ 2015-01-19  9:48       ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-19  9:48 UTC (permalink / raw)
  To: Sergei Shtylyov, linux-mips

On 01/17/2015 01:24 PM, Sergei Shtylyov wrote:
> Hello.
> 
> On 1/16/2015 1:49 PM, 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>
> 
> [...]
> 
>> diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
>> index bf82ec302cff..c084b38e727b 100644
>> --- a/arch/mips/kernel/branch.c
>> +++ b/arch/mips/kernel/branch.c
>> @@ -808,6 +808,17 @@ int __compute_return_epc_for_insn(struct pt_regs
>> *regs,
>>           }
>>           regs->cp0_epc += 8;
>>           break;
>> +    case cbcond0_op:
>> +        /* Only valid for MIPS R6 */
>> +        if (!cpu_has_mips_r6) {
>> +            ret = -SIGILL;
>> +            break;
>> +        }
>> +        /* Compact branches: bovc, beqc, beqzalc */
>> +        if (insn.i_format.rt && !insn.i_format.rs)
>> +            regs->regs[31] = epc + 4;
> 
>    Hm, so this instruction doesn't have delay slot?

All 3 of them have a forbidden slot. An instruction in a forbidden slot
is only executed if the branch *is not taken*.

The "if" condition above is aimed to handle the BEQZALC instruction. The
BEQZALC instruction will store the return address to the 31 register.

According to the R6 ISA this is what happens in that instruction:

GPR[31] <- PC+4
target_offset <- ...
BLTZALC: cond <- GPR[rt] < 0
if cond then
PC <- ( PC+4+ sign_extend( target_offset ) )
endif

So GPR[31] will contain the address for the forbidden slot instruction.
So in this type of branches (where the link register is used), the
forbidden slot will be executed after the branch.

However, the only way for us to be emulating a branch, is an instruction
in a forbidden slot or delay slot to have caused an exception. In case
of compact branches, when the instruction in a forbidden slot is
executed, we know we are done with the branch, because in any case, the
branch was already executed. An exception in the forbidden slot sets the
EPC back to the branch itself. So we simply handle the forbidden slot
exception, and then we do PC+8 so go past the forbidden slot instruction
that we already handled.

See

http://git.linux-mips.org/cgit/mchandras/linux.git/tree/arch/mips/kernel/branch.c?h=3.19-r6-rfc-1#n404

does that make sense?

-- 
markos

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

* Re: [PATCH RFC v2 68/70] MIPS: kernel: elf: Improve the overall ABI and FPU mode checks
  2015-01-19  9:29   ` Matthew Fortune
@ 2015-01-19 12:17     ` Markos Chandras
  2015-01-29 23:22       ` Paul Burton
  2015-02-03 12:41     ` Maciej W. Rozycki
  1 sibling, 1 reply; 262+ messages in thread
From: Markos Chandras @ 2015-01-19 12:17 UTC (permalink / raw)
  To: Matthew Fortune, linux-mips
  Cc: Paul Burton, Maciej W. Rozycki (macro@linux-mips.org)

On 01/19/2015 09:29 AM, Matthew Fortune wrote:
>> The previous implementation did not cover all possible FPU combinations
>> and it silently allowed ABI incompatible objects to be loaded with the
>> wrong ABI. For example, the previous logic would set the FP_64 ABI as
>> the matching ABI for an FP_XX object combined with an FP_64A object.
>> This was wrong, and the matching ABI should have been FP_64A.
>> The previous logic is now replaced with a new one which determines
>> the appropriate FPU mode to be used rather than the FP ABI. This has
>> the advantage that the entire logic is much simpler since it is the FPU
>> mode we are interested in rather than the FP ABI resulting to code
>> simplifications.
> 
> Markos,
> 
> Can you confirm that the o32 abiflags testsuite has been run on a 64-bit
> kernel? I know that the o32 testsuite has run on a 32-bit kernel and the
> n64 testsuite has run on a 64-bit kernel. It is certainly worth checking
> given the fixes that are being made to 3.19.


They all pass with my R6 64-bit kernel + R6 userland + R2 O32 testsuite.

> 
> Is it worth updating the CONFIG_MIPS_O32_FP64_SUPPORT option to no longer
> be experimental and also default on? This option could then guard the new
> logic from this patch as a safety measure. Once the code has been proven
> I'd suggest removing the option and making the code unconditional.

Paul?

Initially thought of having 32-bit R6 select this symbol but then I
dropped it. But maybe it make sense now?

-- 
markos

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

* [PATCH RFC v3 40/70] MIPS: mm: page: Add MIPS R6 support
@ 2015-01-19 12:33       ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-19 12:33 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

The MIPS R6 pref instruction only has 9 bits for the immediate
field so skip the micro-assembler PREF instruction if the offset
does not fit in 9 bits. Moreover, bit 30 (Pref_PrepareForStore) is
no longer valid in MIPS R6, so we change the default for all MIPS R6
processors to bit 5 (Pref_StoreStreamed).

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

diff --git a/arch/mips/mm/page.c b/arch/mips/mm/page.c
index b611102e23b5..152b5d300f0c 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 <= 0x1ff && d >= -0x200)	\
+			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;
@@ -178,7 +192,15 @@ static void set_prefetch_parameters(void)
 			pref_bias_copy_load = 256;
 			pref_bias_copy_store = 128;
 			pref_src_mode = Pref_LoadStreamed;
-			pref_dst_mode = Pref_PrepareForStore;
+			if (cpu_has_mips_r6)
+				/*
+				 * Bit 30 (Pref_PrepareForStore) has been
+				 * removed from MIPS R6. Use bit 5
+				 * (Pref_StoreStreamed).
+				 */
+				pref_dst_mode = Pref_StoreStreamed;
+			else
+				pref_dst_mode = Pref_PrepareForStore;
 			break;
 		}
 	} else {
@@ -214,7 +236,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 +379,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 +388,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.1

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

* [PATCH RFC v3 40/70] MIPS: mm: page: Add MIPS R6 support
@ 2015-01-19 12:33       ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-19 12:33 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

The MIPS R6 pref instruction only has 9 bits for the immediate
field so skip the micro-assembler PREF instruction if the offset
does not fit in 9 bits. Moreover, bit 30 (Pref_PrepareForStore) is
no longer valid in MIPS R6, so we change the default for all MIPS R6
processors to bit 5 (Pref_StoreStreamed).

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

diff --git a/arch/mips/mm/page.c b/arch/mips/mm/page.c
index b611102e23b5..152b5d300f0c 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 <= 0x1ff && d >= -0x200)	\
+			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;
@@ -178,7 +192,15 @@ static void set_prefetch_parameters(void)
 			pref_bias_copy_load = 256;
 			pref_bias_copy_store = 128;
 			pref_src_mode = Pref_LoadStreamed;
-			pref_dst_mode = Pref_PrepareForStore;
+			if (cpu_has_mips_r6)
+				/*
+				 * Bit 30 (Pref_PrepareForStore) has been
+				 * removed from MIPS R6. Use bit 5
+				 * (Pref_StoreStreamed).
+				 */
+				pref_dst_mode = Pref_StoreStreamed;
+			else
+				pref_dst_mode = Pref_PrepareForStore;
 			break;
 		}
 	} else {
@@ -214,7 +236,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 +379,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 +388,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.1

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

* Re: [PATCH RFC v2 05/70] MIPS: mm: uasm: Add signed 9-bit immediate related macros
@ 2015-01-19 12:35       ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-19 12:35 UTC (permalink / raw)
  To: Sergei Shtylyov, linux-mips; +Cc: Leonid Yegoshin

On 01/16/2015 11:29 AM, Sergei Shtylyov wrote:
> Hello.
> 
> On 1/16/2015 1:48 PM, Markos Chandras wrote:
> 
>> 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 4adf30284813..6596b6898637 100644
>> --- a/arch/mips/mm/uasm.c
>> +++ b/arch/mips/mm/uasm.c
> [...]
>> @@ -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),
> 
>    Not 0xFF and -0x100? The values above don't fit into 9 bits...

Hi,

I think 0x1ff and -0x200 fit into 9-bits. Why do you think they don't?

-- 
markos

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

* Re: [PATCH RFC v2 05/70] MIPS: mm: uasm: Add signed 9-bit immediate related macros
@ 2015-01-19 12:35       ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-19 12:35 UTC (permalink / raw)
  To: Sergei Shtylyov, linux-mips; +Cc: Leonid Yegoshin

On 01/16/2015 11:29 AM, Sergei Shtylyov wrote:
> Hello.
> 
> On 1/16/2015 1:48 PM, Markos Chandras wrote:
> 
>> 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 4adf30284813..6596b6898637 100644
>> --- a/arch/mips/mm/uasm.c
>> +++ b/arch/mips/mm/uasm.c
> [...]
>> @@ -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),
> 
>    Not 0xFF and -0x100? The values above don't fit into 9 bits...

Hi,

I think 0x1ff and -0x200 fit into 9-bits. Why do you think they don't?

-- 
markos

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

* Re: [PATCH RFC v2 05/70] MIPS: mm: uasm: Add signed 9-bit immediate related macros
@ 2015-01-19 12:45         ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-19 12:45 UTC (permalink / raw)
  To: Sergei Shtylyov, linux-mips; +Cc: Leonid Yegoshin

On 01/19/2015 12:35 PM, Markos Chandras wrote:
> On 01/16/2015 11:29 AM, Sergei Shtylyov wrote:
>> Hello.
>>
>> On 1/16/2015 1:48 PM, Markos Chandras wrote:
>>
>>> 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 4adf30284813..6596b6898637 100644
>>> --- a/arch/mips/mm/uasm.c
>>> +++ b/arch/mips/mm/uasm.c
>> [...]
>>> @@ -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),
>>
>>    Not 0xFF and -0x100? The values above don't fit into 9 bits...
> 
> Hi,
> 
> I think 0x1ff and -0x200 fit into 9-bits. Why do you think they don't?
> 
I think you are right. I will fix that and the 40/70 patch as well.

-- 
markos

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

* Re: [PATCH RFC v2 05/70] MIPS: mm: uasm: Add signed 9-bit immediate related macros
@ 2015-01-19 12:45         ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-19 12:45 UTC (permalink / raw)
  To: Sergei Shtylyov, linux-mips; +Cc: Leonid Yegoshin

On 01/19/2015 12:35 PM, Markos Chandras wrote:
> On 01/16/2015 11:29 AM, Sergei Shtylyov wrote:
>> Hello.
>>
>> On 1/16/2015 1:48 PM, Markos Chandras wrote:
>>
>>> 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 4adf30284813..6596b6898637 100644
>>> --- a/arch/mips/mm/uasm.c
>>> +++ b/arch/mips/mm/uasm.c
>> [...]
>>> @@ -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),
>>
>>    Not 0xFF and -0x100? The values above don't fit into 9 bits...
> 
> Hi,
> 
> I think 0x1ff and -0x200 fit into 9-bits. Why do you think they don't?
> 
I think you are right. I will fix that and the 40/70 patch as well.

-- 
markos

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

* Re: [PATCH RFC v2 05/70] MIPS: mm: uasm: Add signed 9-bit immediate related macros
  2015-01-19 12:35       ` Markos Chandras
  (?)
  (?)
@ 2015-01-19 12:50       ` Sergei Shtylyov
  -1 siblings, 0 replies; 262+ messages in thread
From: Sergei Shtylyov @ 2015-01-19 12:50 UTC (permalink / raw)
  To: Markos Chandras, linux-mips; +Cc: Leonid Yegoshin

Hello.

On 1/19/2015 3:35 PM, Markos Chandras wrote:

>>> 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 4adf30284813..6596b6898637 100644
>>> --- a/arch/mips/mm/uasm.c
>>> +++ b/arch/mips/mm/uasm.c
>> [...]
>>> @@ -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),

>>     Not 0xFF and -0x100? The values above don't fit into 9 bits...

> Hi,

> I think 0x1ff and -0x200 fit into 9-bits. Why do you think they don't?

    Because 0x1ff occupies 9 bits already and -0x200 (~0x200 + 1) occupies at 
least 10 bits. I thought that was pretty obvious...

WBR, Sergei

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

* Re: [PATCH RFC v2 12/70] MIPS: asm: asmmacro: Replace add instructions with "addui"
  2015-01-16 10:48   ` Markos Chandras
  (?)
@ 2015-01-19 15:59   ` Maciej W. Rozycki
  2015-01-19 16:39       ` Markos Chandras
  -1 siblings, 1 reply; 262+ messages in thread
From: Maciej W. Rozycki @ 2015-01-19 15:59 UTC (permalink / raw)
  To: Markos Chandras; +Cc: linux-mips

On Fri, 16 Jan 2015, Markos Chandras wrote:

> The use of "add" instruction for immediate operations can result to
> build failures for MIPS R6. This is because, the 'add' is a macro in
> binutils and depending on the size of the immediate it can expand to
> an 'addi' instruction which has been removed from MIPS R6.
> Thus, we will be using the 'addu' macro instead, which also
> accepts immediate operands.
> 
> Link: http://www.linux-mips.org/archives/linux-mips/2015-01/msg00121.html
> Cc: Maciej W. Rozycki <macro@linux-mips.org>
> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
> ---

 This needs a title fix: s/addui/addu/; I'd suggest making the use of 
quotation marks consistent too on this occasion, e.g.:

MIPS: asm: asmmacro: Replace "add" instructions with "addu"

You might take the opportunity to decide on single or double quotes 
throughout the description too; right now it looks a bit messy to me.

 Other than that -- this is self-contained and an actual bug fix, 
irrelevant to R6.  I think it can and really should go in right away 
regardless of the outcome of the discussion on the other changes in this 
series.  Also to any stable branches where applicable; the change is so 
obvious that it cannot do any harm.

 So please resend this change with the title fix (and any description 
updates), and I'll give you my review acceptance tag to speed up 
processing.

 NB it looks to me like a followup change is needed to ensure the correct 
operation of these macros in 64-bit kernels, where a doubleword addition 
must be used instead for address calculation.  One way would be by using 
the PTR_ADDU preprocessor macro, but there are other possibilities as 
well.  This is not a requirement for this change to be accepted as far as 
I am concerned though.

 Thanks,

  Maciej

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

* Re: [PATCH RFC v2 12/70] MIPS: asm: asmmacro: Replace add instructions with "addui"
@ 2015-01-19 16:39       ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-19 16:39 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: linux-mips

On 01/19/2015 03:59 PM, Maciej W. Rozycki wrote:
> On Fri, 16 Jan 2015, Markos Chandras wrote:
> 
>> The use of "add" instruction for immediate operations can result to
>> build failures for MIPS R6. This is because, the 'add' is a macro in
>> binutils and depending on the size of the immediate it can expand to
>> an 'addi' instruction which has been removed from MIPS R6.
>> Thus, we will be using the 'addu' macro instead, which also
>> accepts immediate operands.
>>
>> Link: http://www.linux-mips.org/archives/linux-mips/2015-01/msg00121.html
>> Cc: Maciej W. Rozycki <macro@linux-mips.org>
>> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
>> ---
> 
>  This needs a title fix: s/addui/addu/; I'd suggest making the use of 
> quotation marks consistent too on this occasion, e.g.:
> 
> MIPS: asm: asmmacro: Replace "add" instructions with "addu"
> 
> You might take the opportunity to decide on single or double quotes 
> throughout the description too; right now it looks a bit messy to me.
> 
>  Other than that -- this is self-contained and an actual bug fix, 
> irrelevant to R6.  I think it can and really should go in right away 
> regardless of the outcome of the discussion on the other changes in this 
> series.  Also to any stable branches where applicable; the change is so 
> obvious that it cannot do any harm.
> 
>  So please resend this change with the title fix (and any description 
> updates), and I'll give you my review acceptance tag to speed up 
> processing.
> 
>  NB it looks to me like a followup change is needed to ensure the correct 
> operation of these macros in 64-bit kernels, where a doubleword addition 
> must be used instead for address calculation.  One way would be by using 
> the PTR_ADDU preprocessor macro, but there are other possibilities as 
> well.  This is not a requirement for this change to be accepted as far as 
> I am concerned though.
> 
>  Thanks,
> 
>   Maciej
> 
sorry i might be missing something but why do you think this is an
important bug fix that should go into 3.19? the way i read the code it
seems that it can't go wrong at the moment.

-- 
markos

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

* Re: [PATCH RFC v2 12/70] MIPS: asm: asmmacro: Replace add instructions with "addui"
@ 2015-01-19 16:39       ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-19 16:39 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: linux-mips

On 01/19/2015 03:59 PM, Maciej W. Rozycki wrote:
> On Fri, 16 Jan 2015, Markos Chandras wrote:
> 
>> The use of "add" instruction for immediate operations can result to
>> build failures for MIPS R6. This is because, the 'add' is a macro in
>> binutils and depending on the size of the immediate it can expand to
>> an 'addi' instruction which has been removed from MIPS R6.
>> Thus, we will be using the 'addu' macro instead, which also
>> accepts immediate operands.
>>
>> Link: http://www.linux-mips.org/archives/linux-mips/2015-01/msg00121.html
>> Cc: Maciej W. Rozycki <macro@linux-mips.org>
>> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
>> ---
> 
>  This needs a title fix: s/addui/addu/; I'd suggest making the use of 
> quotation marks consistent too on this occasion, e.g.:
> 
> MIPS: asm: asmmacro: Replace "add" instructions with "addu"
> 
> You might take the opportunity to decide on single or double quotes 
> throughout the description too; right now it looks a bit messy to me.
> 
>  Other than that -- this is self-contained and an actual bug fix, 
> irrelevant to R6.  I think it can and really should go in right away 
> regardless of the outcome of the discussion on the other changes in this 
> series.  Also to any stable branches where applicable; the change is so 
> obvious that it cannot do any harm.
> 
>  So please resend this change with the title fix (and any description 
> updates), and I'll give you my review acceptance tag to speed up 
> processing.
> 
>  NB it looks to me like a followup change is needed to ensure the correct 
> operation of these macros in 64-bit kernels, where a doubleword addition 
> must be used instead for address calculation.  One way would be by using 
> the PTR_ADDU preprocessor macro, but there are other possibilities as 
> well.  This is not a requirement for this change to be accepted as far as 
> I am concerned though.
> 
>  Thanks,
> 
>   Maciej
> 
sorry i might be missing something but why do you think this is an
important bug fix that should go into 3.19? the way i read the code it
seems that it can't go wrong at the moment.

-- 
markos

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

* Re: [PATCH RFC v2 12/70] MIPS: asm: asmmacro: Replace add instructions with "addui"
  2015-01-19 16:39       ` Markos Chandras
  (?)
@ 2015-01-19 19:07       ` Maciej W. Rozycki
  2015-01-19 19:25         ` Maciej W. Rozycki
  -1 siblings, 1 reply; 262+ messages in thread
From: Maciej W. Rozycki @ 2015-01-19 19:07 UTC (permalink / raw)
  To: Markos Chandras; +Cc: linux-mips

On Mon, 19 Jan 2015, Markos Chandras wrote:

> sorry i might be missing something but why do you think this is an
> important bug fix that should go into 3.19? the way i read the code it
> seems that it can't go wrong at the moment.

 We shouldn't be using trapping instructions for address calculation.  
These macros have been wrong since the beginning, the MSA instructions 
they correspond to do not trigger an exception on an integer overflow in 
address calculation (none of the MIPS instruction does).

  Maciej

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

* Re: [PATCH RFC v2 12/70] MIPS: asm: asmmacro: Replace add instructions with "addui"
  2015-01-19 19:07       ` Maciej W. Rozycki
@ 2015-01-19 19:25         ` Maciej W. Rozycki
  2015-01-20  9:52             ` Markos Chandras
  0 siblings, 1 reply; 262+ messages in thread
From: Maciej W. Rozycki @ 2015-01-19 19:25 UTC (permalink / raw)
  To: Markos Chandras; +Cc: linux-mips

On Mon, 19 Jan 2015, Maciej W. Rozycki wrote:

> > sorry i might be missing something but why do you think this is an
> > important bug fix that should go into 3.19? the way i read the code it
> > seems that it can't go wrong at the moment.
> 
>  We shouldn't be using trapping instructions for address calculation.  
> These macros have been wrong since the beginning, the MSA instructions 
> they correspond to do not trigger an exception on an integer overflow in 
> address calculation (none of the MIPS instruction does).

 And BTW, it is a bug in GAS too, that it does not accept ADDI for R6 -- 
it should treat the instruction as a macro and expand it to an equivalent 
LI + ADD sequence (using $at or `rd', if available, as a temporary to 
store the immediate).  Similarly to how microMIPS DADDI is handled for 
example (where the hardware instruction has an unusually limited range of 
the immediate argument, however GAS accepts any 16-bit).

  Maciej

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

* Re: [PATCH RFC v2 04/70] MIPS: Add build support for the MIPS R6 ISA
  2015-01-16 10:48   ` Markos Chandras
  (?)
@ 2015-01-19 23:56   ` Maciej W. Rozycki
  -1 siblings, 0 replies; 262+ messages in thread
From: Maciej W. Rozycki @ 2015-01-19 23:56 UTC (permalink / raw)
  To: Markos Chandras; +Cc: linux-mips, Leonid Yegoshin

On Fri, 16 Jan 2015, Markos Chandras wrote:

> diff --git a/arch/mips/Makefile b/arch/mips/Makefile
> index 2563a088d3b8..b54d5a14b9f0 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

 I think there is no sense to carry on this GCC 3.2/3.3 compatibility 
cruft for R6, there's no chance for this to work with those ancient 
compilers that these hacks have been intended for.  These arrangements 
come from 9200c0b2:

commit 9200c0b2a07c430bd98c546fc44b94f50e67ac62
Author: Ralf Baechle <ralf@linux-mips.org>
Date:   Thu Apr 6 00:44:25 2006 +0100

    [MIPS] Fix Makefile bugs for MIPS32/MIPS64 R1 and R2.

    This fixes kernel builds with gcc 3.2 (not 64-bit, that is looking like
    it is beyond recovery) and 3.3.  With these bugs fixed we now also can
    get undo 3b4c4996a0c24da9e6f8be764e3950b756b18cc0 and similar bits for
    SMTC that were added in 79cc8007b93838a670b164b8a55ab3e735a12a8b.

(where the arrangement switched from older yet a fallback that used flags 
like `-mips2 -mtune=r4600 -Wa,-mips32' to support GCC 2.95.x or suchlike) 
-- so please just make them plain:

cflags-$(CONFIG_CPU_MIPS32_R6)	+= -march=mips32r6 -Wa,--trap
cflags-$(CONFIG_CPU_MIPS64_R6)	+= -march=mips64r6 -Wa,--trap

Any compiler that supports R6 (and `-mips64r6' for that matter) will 
support `-march=mips64r6' and will pass this option down to GAS.

 I can take blame for some of this stuff BTW, with 2c6e7315:

commit 2c6e7315369ff6195c816d804b1e89d206aed06a
Author: Maciej W. Rozycki <macro@linux-mips.org>
Date:   Mon Dec 22 16:59:09 2003 +0000

    Support for newer gcc/gas options.

-- so I roughly know what is going on here and I think you can trust me 
that you don't want to go down the complicated path.

  Maciej

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

* Re: [PATCH RFC v2 10/70] MIPS: asm: asmmacro: Drop unused 'reg' argument on MIPSR2
  2015-01-16 10:48   ` Markos Chandras
  (?)
@ 2015-01-20  0:04   ` Maciej W. Rozycki
  2015-01-20  9:49       ` Markos Chandras
  -1 siblings, 1 reply; 262+ messages in thread
From: Maciej W. Rozycki @ 2015-01-20  0:04 UTC (permalink / raw)
  To: Markos Chandras; +Cc: linux-mips

On Fri, 16 Jan 2015, Markos Chandras wrote:

> 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

 Their !CONFIG_CPU_MIPSR2 counterparts do however.  Have you checked with 
GAS that it is acceptable to pass an extra argument to a macro that 
doesn't expect one?

  Maciej

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

* Re: [PATCH RFC v2 18/70] MIPS: asm: spram: Add MIPS R6 related definitions
  2015-01-16 10:48   ` Markos Chandras
  (?)
@ 2015-01-20  0:13   ` Maciej W. Rozycki
  2015-01-21 12:16       ` Markos Chandras
  -1 siblings, 1 reply; 262+ messages in thread
From: Maciej W. Rozycki @ 2015-01-20  0:13 UTC (permalink / raw)
  To: Markos Chandras; +Cc: linux-mips

On Fri, 16 Jan 2015, Markos Chandras wrote:

> 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 92987d1bbe5f..0862ae781339 100644
> --- a/arch/mips/kernel/Makefile
> +++ b/arch/mips/kernel/Makefile
> @@ -53,6 +53,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

 It looks to me like this should be a separate CONFIG_MIPS_SPRAM option 
selected by CPU_MIPSR2 and CPU_MIPSR6.  This will avoid the need to list 
`spram.o' twice which may be asking for troubles.  Also this will keep 
simple the `#ifdef' condition above.

  Maciej

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

* Re: [PATCH RFC v2 19/70] MIPS: Use the new "ZC" constraint for MIPS R6
  2015-01-16 10:48   ` Markos Chandras
  (?)
@ 2015-01-20  0:27   ` Maciej W. Rozycki
  2015-01-20  9:11     ` Matthew Fortune
  -1 siblings, 1 reply; 262+ messages in thread
From: Maciej W. Rozycki @ 2015-01-20  0:27 UTC (permalink / raw)
  To: Markos Chandras; +Cc: linux-mips, Matthew Fortune

On Fri, 16 Jan 2015, Markos Chandras wrote:

> GCC versions supporting MIPS R6 use the ZC constraint to enforce a
> 9-bit offset for MIPS R6. We will use that for all MIPS R6 LL/SC
> instructions.
> 
> Cc: Matthew Fortune <Matthew.Fortune@imgtec.com>
> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
> ---
>  arch/mips/include/asm/compiler.h | 10 +++++++++-
>  1 file changed, 9 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/mips/include/asm/compiler.h b/arch/mips/include/asm/compiler.h
> index c73815e0123a..8f8ed0245a09 100644
> --- a/arch/mips/include/asm/compiler.h
> +++ b/arch/mips/include/asm/compiler.h
> @@ -16,12 +16,20 @@
>  #define GCC_REG_ACCUM "accum"
>  #endif
>  
> +#ifdef CONFIG_CPU_MIPSR6
> +/*
> + * GCC uses ZC for MIPS R6 to indicate a 9-bit offset although
> + * the macro name is a bit misleading
> + */
> +#define GCC_OFF12_ASM() "ZC"
> +#else
>  #ifndef CONFIG_CPU_MICROMIPS
>  #define GCC_OFF12_ASM() "R"
>  #elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
>  #define GCC_OFF12_ASM() "ZC"
>  #else
>  #error "microMIPS compilation unsupported with GCC older than 4.9"
> -#endif
> +#endif /* CONFIG_CPU_MICROMIPS */
> +#endif /* CONFIG_CPU_MIPSR6 */
>  
>  #endif /* _ASM_COMPILER_H */

 I'd prefer to have a GCC version trap here just like with the microMIPS 
constraint.  What is the first upstream version to support R6?  5.0?

 Also rather than stating that the name of the macro has now become a 
misnomer I think it should actually be renamed to something more general, 
like `GCC_OFF_SMALL_ASM' (any better suggestions are welcome).  That'd 
have to be a separate patch though, to be applied first, preferably.

  Maciej

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

* Re: [PATCH RFC v2 24/70] MIPS: asm: spinlock: Replace sub instruction with addiu
  2015-01-16 10:49   ` Markos Chandras
  (?)
@ 2015-01-20  1:04   ` Maciej W. Rozycki
  2015-01-20 11:29       ` Markos Chandras
  -1 siblings, 1 reply; 262+ messages in thread
From: Maciej W. Rozycki @ 2015-01-20  1:04 UTC (permalink / raw)
  To: Markos Chandras; +Cc: linux-mips

On Fri, 16 Jan 2015, Markos Chandras wrote:

> 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 c6d06d383ef9..500050d3bda6 100644
> --- a/arch/mips/include/asm/spinlock.h
> +++ b/arch/mips/include/asm/spinlock.h
> @@ -276,7 +276,7 @@ static inline void arch_read_unlock(arch_rwlock_t *rw)
>  		do {
>  			__asm__ __volatile__(
>  			"1:	ll	%1, %2	# arch_read_unlock	\n"
> -			"	sub	%1, 1				\n"
> +			"	addiu	%1, -1				\n"
>  			"	sc	%1, %0				\n"
>  			: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
>  			: GCC_OFF12_ASM() (rw->lock)

 This integer overflow trap is deliberate here -- have you seen the note 
just above:

/* Note the use of sub, not subu which will make the kernel die with an
   overflow exception if we ever try to unlock an rwlock that is already
   unlocked or is being held by a writer.  */

?

 What this shows really is a GAS bug fix for the SUB macro is needed 
similar to what I suggested in 12/70 for ADDI (from the situation I infer 
there is some real work to do in GAS in this area; adding Matthew as a 
recipient to raise his awareness) so that it does not expand to ADDI where 
the architecture or processor selected do not support it.  Instead a 
longer sequence involving SUB has to be produced.

 However, regardless, I suggest code like:

/* There's no R6 ADDI instruction so use the ADD register version instead. */
#ifdef CONFIG_CPU_MIPSR6
#define GCC_ADDI_ASM() "r"
#else
#define GCC_ADDI_ASM() "I"
#endif

			__asm__ __volatile__(
			"1:	ll	%1, %2	# arch_read_unlock	\n"
			"	sub	%1, %3				\n"
			"	sc	%1, %0				\n"
			: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
			: GCC_OFF12_ASM() (rw->lock), GCC_ADDI_ASM() (1)
			: "memory");

(untested, but should work) so that there's still a single instruction 
only in the LL/SC loop and consequently no increased lock contention risk.

 As a side note, this could be cleaned up to use a "+" input/output 
constraint; such a clean-up will be welcome -- although to be complete, a 
review of all the asms will be required (this may bump up the GCC version 
requirement though, ISTR bugs in this area).

  Maciej

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

* Re: [PATCH RFC v2 26/70] MIPS: kernel: cpu-bugs64: Do not check R6 cores for existing 64-bit bugs
  2015-01-16 10:49   ` Markos Chandras
  (?)
@ 2015-01-20  1:07   ` Maciej W. Rozycki
  -1 siblings, 0 replies; 262+ messages in thread
From: Maciej W. Rozycki @ 2015-01-20  1:07 UTC (permalink / raw)
  To: Markos Chandras; +Cc: linux-mips, Leonid Yegoshin

On Fri, 16 Jan 2015, Markos Chandras wrote:

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

Reviewed-by: Maciej W. Rozycki <macro@linux-mips.org>

We might even want to limit these errata checks further, to reduce code 
size for people who won't ever care.  No need to rush doing that though.

  Maciej

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

* Re: [PATCH RFC v2 27/70] MIPS: kernel: cevt-r4k: Add MIPS R6 to the c0_compare_interrupt handler
  2015-01-16 10:49   ` Markos Chandras
  (?)
@ 2015-01-20  1:22   ` Maciej W. Rozycki
  2015-01-20  9:14       ` James Hogan
  -1 siblings, 1 reply; 262+ messages in thread
From: Maciej W. Rozycki @ 2015-01-20  1:22 UTC (permalink / raw)
  To: Markos Chandras; +Cc: James Hogan, linux-mips, Leonid Yegoshin

On Fri, 16 Jan 2015, Markos Chandras wrote:

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

 While a preexisting bug, this is simply not true, there's CP0.Cause.TI to 
examine for a timer interrupt pending.  Please fix your change to use 
`c0_compare_int_pending' instead and synchronise with stuff posted by 
James (cc-ed) at <http://patchwork.linux-mips.org/patch/8900/>.

  Maciej

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

* RE: [PATCH RFC v2 19/70] MIPS: Use the new "ZC" constraint for MIPS R6
  2015-01-20  0:27   ` Maciej W. Rozycki
@ 2015-01-20  9:11     ` Matthew Fortune
  2015-01-20  9:35       ` Markos Chandras
  0 siblings, 1 reply; 262+ messages in thread
From: Matthew Fortune @ 2015-01-20  9:11 UTC (permalink / raw)
  To: Maciej W. Rozycki, Markos Chandras; +Cc: linux-mips

Maciej W. Rozycki <macro@linux-mips.org> writes:
> On Fri, 16 Jan 2015, Markos Chandras wrote:
> 
> > GCC versions supporting MIPS R6 use the ZC constraint to enforce a
> > 9-bit offset for MIPS R6. We will use that for all MIPS R6 LL/SC
> > instructions.
> >
> > Cc: Matthew Fortune <Matthew.Fortune@imgtec.com>
> > Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
> > ---
> >  arch/mips/include/asm/compiler.h | 10 +++++++++-
> >  1 file changed, 9 insertions(+), 1 deletion(-)
> >
> > diff --git a/arch/mips/include/asm/compiler.h
> b/arch/mips/include/asm/compiler.h
> > index c73815e0123a..8f8ed0245a09 100644
> > --- a/arch/mips/include/asm/compiler.h
> > +++ b/arch/mips/include/asm/compiler.h
> > @@ -16,12 +16,20 @@
> >  #define GCC_REG_ACCUM "accum"
> >  #endif
> >
> > +#ifdef CONFIG_CPU_MIPSR6
> > +/*
> > + * GCC uses ZC for MIPS R6 to indicate a 9-bit offset although
> > + * the macro name is a bit misleading
> > + */
> > +#define GCC_OFF12_ASM() "ZC"
> > +#else
> >  #ifndef CONFIG_CPU_MICROMIPS
> >  #define GCC_OFF12_ASM() "R"
> >  #elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
> >  #define GCC_OFF12_ASM() "ZC"
> >  #else
> >  #error "microMIPS compilation unsupported with GCC older than 4.9"
> > -#endif
> > +#endif /* CONFIG_CPU_MICROMIPS */
> > +#endif /* CONFIG_CPU_MIPSR6 */
> >
> >  #endif /* _ASM_COMPILER_H */
> 
>  I'd prefer to have a GCC version trap here just like with the microMIPS
> constraint.  What is the first upstream version to support R6?  5.0?

Correct.
 
>  Also rather than stating that the name of the macro has now become a
> misnomer I think it should actually be renamed to something more general,
> like `GCC_OFF_SMALL_ASM' (any better suggestions are welcome).  That'd
> have to be a separate patch though, to be applied first, preferably.

The ZC constraint is suitable for use in LL/SC/PREF/CACHE for all ISAs. I
believe this is the smallest width displacement for a memory operation in
all ISAs. The only other reduced displacement in Release 6 is for copro 2
load/stores which are 11-bit rather than 9-bit.

Matthew

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

* Re: [PATCH RFC v2 27/70] MIPS: kernel: cevt-r4k: Add MIPS R6 to the c0_compare_interrupt handler
@ 2015-01-20  9:14       ` James Hogan
  0 siblings, 0 replies; 262+ messages in thread
From: James Hogan @ 2015-01-20  9:14 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: Markos Chandras, linux-mips, Leonid Yegoshin

[-- Attachment #1: Type: text/plain, Size: 981 bytes --]

Hi Maciej,

On Tue, Jan 20, 2015 at 01:22:24AM +0000, Maciej W. Rozycki wrote:
> On Fri, 16 Jan 2015, Markos Chandras wrote:
> 
> > 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>
> > ---
> 
>  While a preexisting bug, this is simply not true, there's CP0.Cause.TI to 
> examine for a timer interrupt pending.  Please fix your change to use 
> `c0_compare_int_pending' instead and synchronise with stuff posted by 
> James (cc-ed) at <http://patchwork.linux-mips.org/patch/8900/>.

I'm not sure I follow what you mean. This change makes it treat r6 like
it treats r2 (i.e. there is still a Cause.TI bit), which sounds correct
to me. I'm guessing cpu_has_mips_r6 doesn't imply cpu_has_mips_r2.

Cheers
James

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [PATCH RFC v2 27/70] MIPS: kernel: cevt-r4k: Add MIPS R6 to the c0_compare_interrupt handler
@ 2015-01-20  9:14       ` James Hogan
  0 siblings, 0 replies; 262+ messages in thread
From: James Hogan @ 2015-01-20  9:14 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: Markos Chandras, linux-mips, Leonid Yegoshin

[-- Attachment #1: Type: text/plain, Size: 981 bytes --]

Hi Maciej,

On Tue, Jan 20, 2015 at 01:22:24AM +0000, Maciej W. Rozycki wrote:
> On Fri, 16 Jan 2015, Markos Chandras wrote:
> 
> > 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>
> > ---
> 
>  While a preexisting bug, this is simply not true, there's CP0.Cause.TI to 
> examine for a timer interrupt pending.  Please fix your change to use 
> `c0_compare_int_pending' instead and synchronise with stuff posted by 
> James (cc-ed) at <http://patchwork.linux-mips.org/patch/8900/>.

I'm not sure I follow what you mean. This change makes it treat r6 like
it treats r2 (i.e. there is still a Cause.TI bit), which sounds correct
to me. I'm guessing cpu_has_mips_r6 doesn't imply cpu_has_mips_r2.

Cheers
James

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [PATCH RFC v2 19/70] MIPS: Use the new "ZC" constraint for MIPS R6
  2015-01-20  9:11     ` Matthew Fortune
@ 2015-01-20  9:35       ` Markos Chandras
  2015-01-20 10:08           ` Matthew Fortune
  0 siblings, 1 reply; 262+ messages in thread
From: Markos Chandras @ 2015-01-20  9:35 UTC (permalink / raw)
  To: Matthew Fortune, Maciej W. Rozycki; +Cc: linux-mips

On 01/20/2015 09:11 AM, Matthew Fortune wrote:
> Maciej W. Rozycki <macro@linux-mips.org> writes:
>> On Fri, 16 Jan 2015, Markos Chandras wrote:
>>
>>> GCC versions supporting MIPS R6 use the ZC constraint to enforce a
>>> 9-bit offset for MIPS R6. We will use that for all MIPS R6 LL/SC
>>> instructions.
>>>
>>> Cc: Matthew Fortune <Matthew.Fortune@imgtec.com>
>>> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
>>> ---
>>>  arch/mips/include/asm/compiler.h | 10 +++++++++-
>>>  1 file changed, 9 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/arch/mips/include/asm/compiler.h
>> b/arch/mips/include/asm/compiler.h
>>> index c73815e0123a..8f8ed0245a09 100644
>>> --- a/arch/mips/include/asm/compiler.h
>>> +++ b/arch/mips/include/asm/compiler.h
>>> @@ -16,12 +16,20 @@
>>>  #define GCC_REG_ACCUM "accum"
>>>  #endif
>>>
>>> +#ifdef CONFIG_CPU_MIPSR6
>>> +/*
>>> + * GCC uses ZC for MIPS R6 to indicate a 9-bit offset although
>>> + * the macro name is a bit misleading
>>> + */
>>> +#define GCC_OFF12_ASM() "ZC"
>>> +#else
>>>  #ifndef CONFIG_CPU_MICROMIPS
>>>  #define GCC_OFF12_ASM() "R"
>>>  #elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
>>>  #define GCC_OFF12_ASM() "ZC"
>>>  #else
>>>  #error "microMIPS compilation unsupported with GCC older than 4.9"
>>> -#endif
>>> +#endif /* CONFIG_CPU_MICROMIPS */
>>> +#endif /* CONFIG_CPU_MIPSR6 */
>>>
>>>  #endif /* _ASM_COMPILER_H */
>>
>>  I'd prefer to have a GCC version trap here just like with the microMIPS
>> constraint.  What is the first upstream version to support R6?  5.0?
> 
> Correct.

We have tools out there based on 4.9. If we make gcc < 5.0 to fail with
R6, then nobody will be able to build it until 5.0 is released.
Perhaps it makes sense to add some checks in arch/mips/Makefile, see if
our gcc supports -mips32r6 or something and then decide what to do.

-- 
markos

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

* Re: [PATCH RFC v2 10/70] MIPS: asm: asmmacro: Drop unused 'reg' argument on MIPSR2
@ 2015-01-20  9:49       ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-20  9:49 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: linux-mips

On 01/20/2015 12:04 AM, Maciej W. Rozycki wrote:
> On Fri, 16 Jan 2015, Markos Chandras wrote:
> 
>> 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
> 
>  Their !CONFIG_CPU_MIPSR2 counterparts do however.

I know but ...

  Have you checked with
> GAS that it is acceptable to pass an extra argument to a macro that 
> doesn't expect one?

none of the calls in arch/mips/* to local_irq_enable or _disable pass
any argument to the macro.

To me it seems like it's ok to drop the reg argument even on
!CONFIG_CPU_MIPSR2 and simply use $t0 directly.

-- 
markos

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

* Re: [PATCH RFC v2 10/70] MIPS: asm: asmmacro: Drop unused 'reg' argument on MIPSR2
@ 2015-01-20  9:49       ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-20  9:49 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: linux-mips

On 01/20/2015 12:04 AM, Maciej W. Rozycki wrote:
> On Fri, 16 Jan 2015, Markos Chandras wrote:
> 
>> 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
> 
>  Their !CONFIG_CPU_MIPSR2 counterparts do however.

I know but ...

  Have you checked with
> GAS that it is acceptable to pass an extra argument to a macro that 
> doesn't expect one?

none of the calls in arch/mips/* to local_irq_enable or _disable pass
any argument to the macro.

To me it seems like it's ok to drop the reg argument even on
!CONFIG_CPU_MIPSR2 and simply use $t0 directly.

-- 
markos

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

* Re: [PATCH RFC v2 12/70] MIPS: asm: asmmacro: Replace add instructions with "addui"
@ 2015-01-20  9:52             ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-20  9:52 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: linux-mips, Matthew Fortune

On 01/19/2015 07:25 PM, Maciej W. Rozycki wrote:
> On Mon, 19 Jan 2015, Maciej W. Rozycki wrote:
> 
>>> sorry i might be missing something but why do you think this is an
>>> important bug fix that should go into 3.19? the way i read the code it
>>> seems that it can't go wrong at the moment.
>>
>>  We shouldn't be using trapping instructions for address calculation.  
>> These macros have been wrong since the beginning, the MSA instructions 
>> they correspond to do not trigger an exception on an integer overflow in 
>> address calculation (none of the MIPS instruction does).
> 
>  And BTW, it is a bug in GAS too, that it does not accept ADDI for R6 -- 
> it should treat the instruction as a macro and expand it to an equivalent 
> LI + ADD sequence (using $at or `rd', if available, as a temporary to 
> store the immediate).  Similarly to how microMIPS DADDI is handled for 
> example (where the hardware instruction has an unusually limited range of 
> the immediate argument, however GAS accepts any 16-bit).
> 
>   Maciej
> 
CC'ing Matthew

-- 
markos

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

* Re: [PATCH RFC v2 12/70] MIPS: asm: asmmacro: Replace add instructions with "addui"
@ 2015-01-20  9:52             ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-20  9:52 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: linux-mips, Matthew Fortune

On 01/19/2015 07:25 PM, Maciej W. Rozycki wrote:
> On Mon, 19 Jan 2015, Maciej W. Rozycki wrote:
> 
>>> sorry i might be missing something but why do you think this is an
>>> important bug fix that should go into 3.19? the way i read the code it
>>> seems that it can't go wrong at the moment.
>>
>>  We shouldn't be using trapping instructions for address calculation.  
>> These macros have been wrong since the beginning, the MSA instructions 
>> they correspond to do not trigger an exception on an integer overflow in 
>> address calculation (none of the MIPS instruction does).
> 
>  And BTW, it is a bug in GAS too, that it does not accept ADDI for R6 -- 
> it should treat the instruction as a macro and expand it to an equivalent 
> LI + ADD sequence (using $at or `rd', if available, as a temporary to 
> store the immediate).  Similarly to how microMIPS DADDI is handled for 
> example (where the hardware instruction has an unusually limited range of 
> the immediate argument, however GAS accepts any 16-bit).
> 
>   Maciej
> 
CC'ing Matthew

-- 
markos

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

* RE: [PATCH RFC v2 19/70] MIPS: Use the new "ZC" constraint for MIPS R6
@ 2015-01-20 10:08           ` Matthew Fortune
  0 siblings, 0 replies; 262+ messages in thread
From: Matthew Fortune @ 2015-01-20 10:08 UTC (permalink / raw)
  To: Markos Chandras, Maciej W. Rozycki; +Cc: linux-mips

Markos Chandras <Markos.Chandras@imgtec.com> writes:
> On 01/20/2015 09:11 AM, Matthew Fortune wrote:
> > Maciej W. Rozycki <macro@linux-mips.org> writes:
> >> On Fri, 16 Jan 2015, Markos Chandras wrote:
> >>
> >>> GCC versions supporting MIPS R6 use the ZC constraint to enforce a
> >>> 9-bit offset for MIPS R6. We will use that for all MIPS R6 LL/SC
> >>> instructions.
> >>>
> >>> Cc: Matthew Fortune <Matthew.Fortune@imgtec.com>
> >>> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
> >>> ---
> >>>  arch/mips/include/asm/compiler.h | 10 +++++++++-
> >>>  1 file changed, 9 insertions(+), 1 deletion(-)
> >>>
> >>> diff --git a/arch/mips/include/asm/compiler.h
> >> b/arch/mips/include/asm/compiler.h
> >>> index c73815e0123a..8f8ed0245a09 100644
> >>> --- a/arch/mips/include/asm/compiler.h
> >>> +++ b/arch/mips/include/asm/compiler.h
> >>> @@ -16,12 +16,20 @@
> >>>  #define GCC_REG_ACCUM "accum"
> >>>  #endif
> >>>
> >>> +#ifdef CONFIG_CPU_MIPSR6
> >>> +/*
> >>> + * GCC uses ZC for MIPS R6 to indicate a 9-bit offset although
> >>> + * the macro name is a bit misleading
> >>> + */
> >>> +#define GCC_OFF12_ASM() "ZC"
> >>> +#else
> >>>  #ifndef CONFIG_CPU_MICROMIPS
> >>>  #define GCC_OFF12_ASM() "R"
> >>>  #elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
> >>>  #define GCC_OFF12_ASM() "ZC"
> >>>  #else
> >>>  #error "microMIPS compilation unsupported with GCC older than 4.9"
> >>> -#endif
> >>> +#endif /* CONFIG_CPU_MICROMIPS */
> >>> +#endif /* CONFIG_CPU_MIPSR6 */
> >>>
> >>>  #endif /* _ASM_COMPILER_H */
> >>
> >>  I'd prefer to have a GCC version trap here just like with the
> microMIPS
> >> constraint.  What is the first upstream version to support R6?  5.0?
> >
> > Correct.
> 
> We have tools out there based on 4.9. If we make gcc < 5.0 to fail with
> R6, then nobody will be able to build it until 5.0 is released.
> Perhaps it makes sense to add some checks in arch/mips/Makefile, see if
> our gcc supports -mips32r6 or something and then decide what to do.

Indeed, I think it is worthwhile supporting the use of tools which have R6
backported to them owing to long lead times for new versions of GCC to be
released.

I think you could actually just switch the check around and remove the
check for micromips entirely, putting the GCC 4.9 check first:

#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
#define GCC_OFF12_ASM() "ZC"
#else
#define GCC_OFF12_ASM() "R"
#endif

From what I can see this is safe. It was presumably written with a micromips
check out of caution to not change older non-micromips code-gen but that
doesn't seem particularly important. It is an improvement to older code if
anything.

Matthew

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

* RE: [PATCH RFC v2 19/70] MIPS: Use the new "ZC" constraint for MIPS R6
@ 2015-01-20 10:08           ` Matthew Fortune
  0 siblings, 0 replies; 262+ messages in thread
From: Matthew Fortune @ 2015-01-20 10:08 UTC (permalink / raw)
  To: Markos Chandras, Maciej W. Rozycki; +Cc: linux-mips

Markos Chandras <Markos.Chandras@imgtec.com> writes:
> On 01/20/2015 09:11 AM, Matthew Fortune wrote:
> > Maciej W. Rozycki <macro@linux-mips.org> writes:
> >> On Fri, 16 Jan 2015, Markos Chandras wrote:
> >>
> >>> GCC versions supporting MIPS R6 use the ZC constraint to enforce a
> >>> 9-bit offset for MIPS R6. We will use that for all MIPS R6 LL/SC
> >>> instructions.
> >>>
> >>> Cc: Matthew Fortune <Matthew.Fortune@imgtec.com>
> >>> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
> >>> ---
> >>>  arch/mips/include/asm/compiler.h | 10 +++++++++-
> >>>  1 file changed, 9 insertions(+), 1 deletion(-)
> >>>
> >>> diff --git a/arch/mips/include/asm/compiler.h
> >> b/arch/mips/include/asm/compiler.h
> >>> index c73815e0123a..8f8ed0245a09 100644
> >>> --- a/arch/mips/include/asm/compiler.h
> >>> +++ b/arch/mips/include/asm/compiler.h
> >>> @@ -16,12 +16,20 @@
> >>>  #define GCC_REG_ACCUM "accum"
> >>>  #endif
> >>>
> >>> +#ifdef CONFIG_CPU_MIPSR6
> >>> +/*
> >>> + * GCC uses ZC for MIPS R6 to indicate a 9-bit offset although
> >>> + * the macro name is a bit misleading
> >>> + */
> >>> +#define GCC_OFF12_ASM() "ZC"
> >>> +#else
> >>>  #ifndef CONFIG_CPU_MICROMIPS
> >>>  #define GCC_OFF12_ASM() "R"
> >>>  #elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
> >>>  #define GCC_OFF12_ASM() "ZC"
> >>>  #else
> >>>  #error "microMIPS compilation unsupported with GCC older than 4.9"
> >>> -#endif
> >>> +#endif /* CONFIG_CPU_MICROMIPS */
> >>> +#endif /* CONFIG_CPU_MIPSR6 */
> >>>
> >>>  #endif /* _ASM_COMPILER_H */
> >>
> >>  I'd prefer to have a GCC version trap here just like with the
> microMIPS
> >> constraint.  What is the first upstream version to support R6?  5.0?
> >
> > Correct.
> 
> We have tools out there based on 4.9. If we make gcc < 5.0 to fail with
> R6, then nobody will be able to build it until 5.0 is released.
> Perhaps it makes sense to add some checks in arch/mips/Makefile, see if
> our gcc supports -mips32r6 or something and then decide what to do.

Indeed, I think it is worthwhile supporting the use of tools which have R6
backported to them owing to long lead times for new versions of GCC to be
released.

I think you could actually just switch the check around and remove the
check for micromips entirely, putting the GCC 4.9 check first:

#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
#define GCC_OFF12_ASM() "ZC"
#else
#define GCC_OFF12_ASM() "R"
#endif

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

* Re: [PATCH RFC v2 19/70] MIPS: Use the new "ZC" constraint for MIPS R6
  2015-01-20 10:08           ` Matthew Fortune
  (?)
@ 2015-01-20 10:12           ` Markos Chandras
  2015-01-20 14:37             ` Maciej W. Rozycki
  -1 siblings, 1 reply; 262+ messages in thread
From: Markos Chandras @ 2015-01-20 10:12 UTC (permalink / raw)
  To: Matthew Fortune, Maciej W. Rozycki; +Cc: linux-mips

On 01/20/2015 10:08 AM, Matthew Fortune wrote:
> Markos Chandras <Markos.Chandras@imgtec.com> writes:
>> On 01/20/2015 09:11 AM, Matthew Fortune wrote:
>>> Maciej W. Rozycki <macro@linux-mips.org> writes:
>>>> On Fri, 16 Jan 2015, Markos Chandras wrote:
>>>>
>>>>> GCC versions supporting MIPS R6 use the ZC constraint to enforce a
>>>>> 9-bit offset for MIPS R6. We will use that for all MIPS R6 LL/SC
>>>>> instructions.
>>>>>
>>>>> Cc: Matthew Fortune <Matthew.Fortune@imgtec.com>
>>>>> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
>>>>> ---
>>>>>  arch/mips/include/asm/compiler.h | 10 +++++++++-
>>>>>  1 file changed, 9 insertions(+), 1 deletion(-)
>>>>>
>>>>> diff --git a/arch/mips/include/asm/compiler.h
>>>> b/arch/mips/include/asm/compiler.h
>>>>> index c73815e0123a..8f8ed0245a09 100644
>>>>> --- a/arch/mips/include/asm/compiler.h
>>>>> +++ b/arch/mips/include/asm/compiler.h
>>>>> @@ -16,12 +16,20 @@
>>>>>  #define GCC_REG_ACCUM "accum"
>>>>>  #endif
>>>>>
>>>>> +#ifdef CONFIG_CPU_MIPSR6
>>>>> +/*
>>>>> + * GCC uses ZC for MIPS R6 to indicate a 9-bit offset although
>>>>> + * the macro name is a bit misleading
>>>>> + */
>>>>> +#define GCC_OFF12_ASM() "ZC"
>>>>> +#else
>>>>>  #ifndef CONFIG_CPU_MICROMIPS
>>>>>  #define GCC_OFF12_ASM() "R"
>>>>>  #elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
>>>>>  #define GCC_OFF12_ASM() "ZC"
>>>>>  #else
>>>>>  #error "microMIPS compilation unsupported with GCC older than 4.9"
>>>>> -#endif
>>>>> +#endif /* CONFIG_CPU_MICROMIPS */
>>>>> +#endif /* CONFIG_CPU_MIPSR6 */
>>>>>
>>>>>  #endif /* _ASM_COMPILER_H */
>>>>
>>>>  I'd prefer to have a GCC version trap here just like with the
>> microMIPS
>>>> constraint.  What is the first upstream version to support R6?  5.0?
>>>
>>> Correct.
>>
>> We have tools out there based on 4.9. If we make gcc < 5.0 to fail with
>> R6, then nobody will be able to build it until 5.0 is released.
>> Perhaps it makes sense to add some checks in arch/mips/Makefile, see if
>> our gcc supports -mips32r6 or something and then decide what to do.
> 
> Indeed, I think it is worthwhile supporting the use of tools which have R6
> backported to them owing to long lead times for new versions of GCC to be
> released.
> 
> I think you could actually just switch the check around and remove the
> check for micromips entirely, putting the GCC 4.9 check first:
> 
> #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
> #define GCC_OFF12_ASM() "ZC"
> #else
> #define GCC_OFF12_ASM() "R"
> #endif
> 
> From what I can see this is safe. It was presumably written with a micromips
> check out of caution to not change older non-micromips code-gen but that
> doesn't seem particularly important. It is an improvement to older code if
> anything.
> 
> Matthew
> 

For non-micromips kernel, this will start using "ZC" instead of "R",
whereas before, it only used "ZC" for micromips and "R" for everything
else. Is that safe? Maciej was the one committed this code, so if that's
still safe, then I will change it as requested.

-- 
markos

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

* Re: [PATCH RFC v2 24/70] MIPS: asm: spinlock: Replace sub instruction with addiu
@ 2015-01-20 11:29       ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-20 11:29 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: linux-mips, Matthew Fortune

On 01/20/2015 01:04 AM, Maciej W. Rozycki wrote:
> On Fri, 16 Jan 2015, Markos Chandras wrote:
> 
>> 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 c6d06d383ef9..500050d3bda6 100644
>> --- a/arch/mips/include/asm/spinlock.h
>> +++ b/arch/mips/include/asm/spinlock.h
>> @@ -276,7 +276,7 @@ static inline void arch_read_unlock(arch_rwlock_t *rw)
>>  		do {
>>  			__asm__ __volatile__(
>>  			"1:	ll	%1, %2	# arch_read_unlock	\n"
>> -			"	sub	%1, 1				\n"
>> +			"	addiu	%1, -1				\n"
>>  			"	sc	%1, %0				\n"
>>  			: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
>>  			: GCC_OFF12_ASM() (rw->lock)
> 
>  This integer overflow trap is deliberate here -- have you seen the note 
> just above:
> 
> /* Note the use of sub, not subu which will make the kernel die with an
>    overflow exception if we ever try to unlock an rwlock that is already
>    unlocked or is being held by a writer.  */
> 
> ?
> 
>  What this shows really is a GAS bug fix for the SUB macro is needed 
> similar to what I suggested in 12/70 for ADDI (from the situation I infer 
> there is some real work to do in GAS in this area; adding Matthew as a 
> recipient to raise his awareness) so that it does not expand to ADDI where 
> the architecture or processor selected do not support it.  Instead a 
> longer sequence involving SUB has to be produced.
> 
>  However, regardless, I suggest code like:
> 
> /* There's no R6 ADDI instruction so use the ADD register version instead. */
> #ifdef CONFIG_CPU_MIPSR6
> #define GCC_ADDI_ASM() "r"
> #else
> #define GCC_ADDI_ASM() "I"
> #endif
> 
> 			__asm__ __volatile__(
> 			"1:	ll	%1, %2	# arch_read_unlock	\n"
> 			"	sub	%1, %3				\n"
> 			"	sc	%1, %0				\n"
> 			: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
> 			: GCC_OFF12_ASM() (rw->lock), GCC_ADDI_ASM() (1)
> 			: "memory");
> 
> (untested, but should work) so that there's still a single instruction 
> only in the LL/SC loop and consequently no increased lock contention risk.
> 
>  As a side note, this could be cleaned up to use a "+" input/output 
> constraint; such a clean-up will be welcome -- although to be complete, a 
> review of all the asms will be required (this may bump up the GCC version 
> requirement though, ISTR bugs in this area).
> 
>   Maciej
> 
CC'ing Matthew again for the GAS suggestions

-- 
markos

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

* Re: [PATCH RFC v2 24/70] MIPS: asm: spinlock: Replace sub instruction with addiu
@ 2015-01-20 11:29       ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-20 11:29 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: linux-mips, Matthew Fortune

On 01/20/2015 01:04 AM, Maciej W. Rozycki wrote:
> On Fri, 16 Jan 2015, Markos Chandras wrote:
> 
>> 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 c6d06d383ef9..500050d3bda6 100644
>> --- a/arch/mips/include/asm/spinlock.h
>> +++ b/arch/mips/include/asm/spinlock.h
>> @@ -276,7 +276,7 @@ static inline void arch_read_unlock(arch_rwlock_t *rw)
>>  		do {
>>  			__asm__ __volatile__(
>>  			"1:	ll	%1, %2	# arch_read_unlock	\n"
>> -			"	sub	%1, 1				\n"
>> +			"	addiu	%1, -1				\n"
>>  			"	sc	%1, %0				\n"
>>  			: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
>>  			: GCC_OFF12_ASM() (rw->lock)
> 
>  This integer overflow trap is deliberate here -- have you seen the note 
> just above:
> 
> /* Note the use of sub, not subu which will make the kernel die with an
>    overflow exception if we ever try to unlock an rwlock that is already
>    unlocked or is being held by a writer.  */
> 
> ?
> 
>  What this shows really is a GAS bug fix for the SUB macro is needed 
> similar to what I suggested in 12/70 for ADDI (from the situation I infer 
> there is some real work to do in GAS in this area; adding Matthew as a 
> recipient to raise his awareness) so that it does not expand to ADDI where 
> the architecture or processor selected do not support it.  Instead a 
> longer sequence involving SUB has to be produced.
> 
>  However, regardless, I suggest code like:
> 
> /* There's no R6 ADDI instruction so use the ADD register version instead. */
> #ifdef CONFIG_CPU_MIPSR6
> #define GCC_ADDI_ASM() "r"
> #else
> #define GCC_ADDI_ASM() "I"
> #endif
> 
> 			__asm__ __volatile__(
> 			"1:	ll	%1, %2	# arch_read_unlock	\n"
> 			"	sub	%1, %3				\n"
> 			"	sc	%1, %0				\n"
> 			: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
> 			: GCC_OFF12_ASM() (rw->lock), GCC_ADDI_ASM() (1)
> 			: "memory");
> 
> (untested, but should work) so that there's still a single instruction 
> only in the LL/SC loop and consequently no increased lock contention risk.
> 
>  As a side note, this could be cleaned up to use a "+" input/output 
> constraint; such a clean-up will be welcome -- although to be complete, a 
> review of all the asms will be required (this may bump up the GCC version 
> requirement though, ISTR bugs in this area).
> 
>   Maciej
> 
CC'ing Matthew again for the GAS suggestions

-- 
markos

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

* RE: [PATCH RFC v2 24/70] MIPS: asm: spinlock: Replace sub instruction with addiu
  2015-01-20 11:29       ` Markos Chandras
  (?)
@ 2015-01-20 11:47       ` Matthew Fortune
  2015-02-10 16:17         ` Maciej W. Rozycki
  -1 siblings, 1 reply; 262+ messages in thread
From: Matthew Fortune @ 2015-01-20 11:47 UTC (permalink / raw)
  To: Markos Chandras, Maciej W. Rozycki; +Cc: linux-mips

Markos Chandras <Markos.Chandras@imgtec.com> writes:
> On 01/20/2015 01:04 AM, Maciej W. Rozycki wrote:
> > On Fri, 16 Jan 2015, Markos Chandras wrote:
> >
> >> 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 c6d06d383ef9..500050d3bda6 100644
> >> --- a/arch/mips/include/asm/spinlock.h
> >> +++ b/arch/mips/include/asm/spinlock.h
> >> @@ -276,7 +276,7 @@ static inline void arch_read_unlock(arch_rwlock_t
> *rw)
> >>  		do {
> >>  			__asm__ __volatile__(
> >>  			"1:	ll	%1, %2	# arch_read_unlock	\n"
> >> -			"	sub	%1, 1				\n"
> >> +			"	addiu	%1, -1				\n"
> >>  			"	sc	%1, %0				\n"
> >>  			: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
> >>  			: GCC_OFF12_ASM() (rw->lock)
> >
> >  This integer overflow trap is deliberate here -- have you seen the note
> > just above:
> >
> > /* Note the use of sub, not subu which will make the kernel die with an
> >    overflow exception if we ever try to unlock an rwlock that is already
> >    unlocked or is being held by a writer.  */
> >
> > ?
> >
> >  What this shows really is a GAS bug fix for the SUB macro is needed
> > similar to what I suggested in 12/70 for ADDI (from the situation I
> infer
> > there is some real work to do in GAS in this area; adding Matthew as a
> > recipient to raise his awareness) so that it does not expand to ADDI
> where
> > the architecture or processor selected do not support it.  Instead a
> > longer sequence involving SUB has to be produced.

The assembler is at least consistent at the moment as the 'sub' macro is
disabled for R6. I am very keen to stop carrying around historic baggage
where it is not necessary. R6 is one place we can do that and deal with
any code changes that are required.

> >  However, regardless, I suggest code like:
> >
> > /* There's no R6 ADDI instruction so use the ADD register version
> instead. */
> > #ifdef CONFIG_CPU_MIPSR6
> > #define GCC_ADDI_ASM() "r"
> > #else
> > #define GCC_ADDI_ASM() "I"
> > #endif
> >
> > 			__asm__ __volatile__(
> > 			"1:	ll	%1, %2	# arch_read_unlock	\n"
> > 			"	sub	%1, %3				\n"
> > 			"	sc	%1, %0				\n"
> > 			: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
> > 			: GCC_OFF12_ASM() (rw->lock), GCC_ADDI_ASM() (1)
> > 			: "memory");
> >
> > (untested, but should work) so that there's still a single instruction
> > only in the LL/SC loop and consequently no increased lock contention
> risk.

I'm afraid I don't like this. The obfuscation of the underlying ISA is
very confusing. In this case it is 100% clear that the asm instruction
is going to get an immediate operand so the instruction is 'addi' with
a negated immediate. However, it costs nothing (in the loop) to use
'add' and an 'r' constraint in all cases. Yes, there will be an extra
setup instruction and register used but the assembly code is clear and
maps 1:1 to real instructions for all ISAs.

(Note this asm block does not appear to need to clobber memory either as
the effects on memory are correctly stated in the constraints).

> >  As a side note, this could be cleaned up to use a "+" input/output
> > constraint; such a clean-up will be welcome -- although to be complete,
> a
> > review of all the asms will be required (this may bump up the GCC
> version
> > requirement though, ISTR bugs in this area).

I believe some of these asm blocks using ll/sc already have '+' in the
constraints for the memory location so perhaps that is either already
a problem or not an issue.

Matthew

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

* Re: [PATCH RFC v2 27/70] MIPS: kernel: cevt-r4k: Add MIPS R6 to the c0_compare_interrupt handler
  2015-01-20  9:14       ` James Hogan
  (?)
@ 2015-01-20 14:33       ` Maciej W. Rozycki
  2015-01-21  9:34           ` Markos Chandras
  -1 siblings, 1 reply; 262+ messages in thread
From: Maciej W. Rozycki @ 2015-01-20 14:33 UTC (permalink / raw)
  To: James Hogan; +Cc: Markos Chandras, linux-mips, Leonid Yegoshin

On Tue, 20 Jan 2015, James Hogan wrote:

> >  While a preexisting bug, this is simply not true, there's CP0.Cause.TI to 
> > examine for a timer interrupt pending.  Please fix your change to use 
> > `c0_compare_int_pending' instead and synchronise with stuff posted by 
> > James (cc-ed) at <http://patchwork.linux-mips.org/patch/8900/>.
> 
> I'm not sure I follow what you mean. This change makes it treat r6 like
> it treats r2 (i.e. there is still a Cause.TI bit), which sounds correct
> to me. I'm guessing cpu_has_mips_r6 doesn't imply cpu_has_mips_r2.

 Correct, R6 is not backwards compatible with R2 so it doesn't set the R2 
flag and consequently any compatibility that does exist has to be handled 
explicitly; see 28/70 for the details of the flag setup.

  Maciej

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

* RE: [PATCH RFC v2 12/70] MIPS: asm: asmmacro: Replace add instructions with "addui"
  2015-01-20  9:52             ` Markos Chandras
  (?)
@ 2015-01-20 14:33             ` Matthew Fortune
  -1 siblings, 0 replies; 262+ messages in thread
From: Matthew Fortune @ 2015-01-20 14:33 UTC (permalink / raw)
  To: Markos Chandras, Maciej W. Rozycki; +Cc: linux-mips

Markos Chandras <Markos.Chandras@imgtec.com> writes:
> On 01/19/2015 07:25 PM, Maciej W. Rozycki wrote:
> > On Mon, 19 Jan 2015, Maciej W. Rozycki wrote:
> >
> >>> sorry i might be missing something but why do you think this is an
> >>> important bug fix that should go into 3.19? the way i read the code it
> >>> seems that it can't go wrong at the moment.
> >>
> >>  We shouldn't be using trapping instructions for address calculation.
> >> These macros have been wrong since the beginning, the MSA instructions
> >> they correspond to do not trigger an exception on an integer overflow
> in
> >> address calculation (none of the MIPS instruction does).
> >
> >  And BTW, it is a bug in GAS too, that it does not accept ADDI for R6 --
> > it should treat the instruction as a macro and expand it to an
> equivalent
> > LI + ADD sequence (using $at or `rd', if available, as a temporary to
> > store the immediate).  Similarly to how microMIPS DADDI is handled for
> > example (where the hardware instruction has an unusually limited range
> of
> > the immediate argument, however GAS accepts any 16-bit).

I suspect this is a discussion best moved to binutils but I have differing
opinions on the value of macros that simply hide the true code that will
be generated. I agree with everything relating to the kernel patch, there
is definitely a 64-bit addressing issue here.

Thanks,
Matthew

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

* Re: [PATCH RFC v2 19/70] MIPS: Use the new "ZC" constraint for MIPS R6
  2015-01-20 10:12           ` Markos Chandras
@ 2015-01-20 14:37             ` Maciej W. Rozycki
  2015-01-20 14:46               ` Maciej W. Rozycki
  2015-01-21  9:06               ` Markos Chandras
  0 siblings, 2 replies; 262+ messages in thread
From: Maciej W. Rozycki @ 2015-01-20 14:37 UTC (permalink / raw)
  To: Markos Chandras; +Cc: Matthew Fortune, linux-mips

On Tue, 20 Jan 2015, Markos Chandras wrote:

> >> We have tools out there based on 4.9. If we make gcc < 5.0 to fail with
> >> R6, then nobody will be able to build it until 5.0 is released.
> >> Perhaps it makes sense to add some checks in arch/mips/Makefile, see if
> >> our gcc supports -mips32r6 or something and then decide what to do.
> > 
> > Indeed, I think it is worthwhile supporting the use of tools which have R6
> > backported to them owing to long lead times for new versions of GCC to be
> > released.
> > 
> > I think you could actually just switch the check around and remove the
> > check for micromips entirely, putting the GCC 4.9 check first:
> > 
> > #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
> > #define GCC_OFF12_ASM() "ZC"
> > #else
> > #define GCC_OFF12_ASM() "R"
> > #endif
> > 
> > From what I can see this is safe. It was presumably written with a micromips
> > check out of caution to not change older non-micromips code-gen but that
> > doesn't seem particularly important. It is an improvement to older code if
> > anything.
> 
> For non-micromips kernel, this will start using "ZC" instead of "R",
> whereas before, it only used "ZC" for micromips and "R" for everything
> else. Is that safe? Maciej was the one committed this code, so if that's
> still safe, then I will change it as requested.

 I'm fine with this proposal; a separate Makefile check for 
`-march=mips32r6' support would be good too.

  Maciej

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

* Re: [PATCH RFC v2 19/70] MIPS: Use the new "ZC" constraint for MIPS R6
  2015-01-20 14:37             ` Maciej W. Rozycki
@ 2015-01-20 14:46               ` Maciej W. Rozycki
  2015-01-21  9:06               ` Markos Chandras
  1 sibling, 0 replies; 262+ messages in thread
From: Maciej W. Rozycki @ 2015-01-20 14:46 UTC (permalink / raw)
  To: Markos Chandras; +Cc: Matthew Fortune, linux-mips

On Tue, 20 Jan 2015, Maciej W. Rozycki wrote:

> > >> We have tools out there based on 4.9. If we make gcc < 5.0 to fail with
> > >> R6, then nobody will be able to build it until 5.0 is released.
> > >> Perhaps it makes sense to add some checks in arch/mips/Makefile, see if
> > >> our gcc supports -mips32r6 or something and then decide what to do.
> > > 
> > > Indeed, I think it is worthwhile supporting the use of tools which have R6
> > > backported to them owing to long lead times for new versions of GCC to be
> > > released.
> > > 
> > > I think you could actually just switch the check around and remove the
> > > check for micromips entirely, putting the GCC 4.9 check first:
> > > 
> > > #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
> > > #define GCC_OFF12_ASM() "ZC"
> > > #else
> > > #define GCC_OFF12_ASM() "R"
> > > #endif
> > > 
> > > From what I can see this is safe. It was presumably written with a micromips
> > > check out of caution to not change older non-micromips code-gen but that
> > > doesn't seem particularly important. It is an improvement to older code if
> > > anything.
> > 
> > For non-micromips kernel, this will start using "ZC" instead of "R",
> > whereas before, it only used "ZC" for micromips and "R" for everything
> > else. Is that safe? Maciej was the one committed this code, so if that's
> > still safe, then I will change it as requested.
> 
>  I'm fine with this proposal; a separate Makefile check for 
> `-march=mips32r6' support would be good too.

 With such an arrangement there is potential however that it'll break 
non-microMIPS builds for someone using a 4.9 prerelease that didn't yet 
have `ZC'.  This is why I arranged the macros like I did in the first 
place.  So if you are able to keep such an arrangement without 
complicating the structure too much, then it would be great.

  Maciej

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

* Re: [PATCH RFC v2 24/70] MIPS: asm: spinlock: Replace sub instruction with addiu
  2015-01-20 11:29       ` Markos Chandras
  (?)
  (?)
@ 2015-01-20 17:17       ` David Daney
  2015-01-20 22:20         ` Ralf Baechle
  -1 siblings, 1 reply; 262+ messages in thread
From: David Daney @ 2015-01-20 17:17 UTC (permalink / raw)
  To: Markos Chandras
  Cc: Maciej W. Rozycki, linux-mips, Matthew Fortune, Ralf Baechle

On 01/20/2015 03:29 AM, Markos Chandras wrote:
> On 01/20/2015 01:04 AM, Maciej W. Rozycki wrote:
>> On Fri, 16 Jan 2015, Markos Chandras wrote:
>>
>>> 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 c6d06d383ef9..500050d3bda6 100644
>>> --- a/arch/mips/include/asm/spinlock.h
>>> +++ b/arch/mips/include/asm/spinlock.h
>>> @@ -276,7 +276,7 @@ static inline void arch_read_unlock(arch_rwlock_t *rw)
>>>   		do {
>>>   			__asm__ __volatile__(
>>>   			"1:	ll	%1, %2	# arch_read_unlock	\n"
>>> -			"	sub	%1, 1				\n"
>>> +			"	addiu	%1, -1				\n"
>>>   			"	sc	%1, %0				\n"
>>>   			: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
>>>   			: GCC_OFF12_ASM() (rw->lock)
>>
>>   This integer overflow trap is deliberate here -- have you seen the note
>> just above:
>>
>> /* Note the use of sub, not subu which will make the kernel die with an
>>     overflow exception if we ever try to unlock an rwlock that is already
>>     unlocked or is being held by a writer.  */
>>

According to a comment on another thread from Ralf, this has been 
observed in the wild only once.  We can simplify the code and remove 
that comment.  Why not just use the ADDIU and be done with it?

There are many locking and atomic primitives that don't have any such 
error checking.  What makes the read lock so special that it needs this 
extra protection?

David Daney

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

* Re: [PATCH RFC v2 24/70] MIPS: asm: spinlock: Replace sub instruction with addiu
  2015-01-20 17:17       ` David Daney
@ 2015-01-20 22:20         ` Ralf Baechle
  2015-01-21  0:58           ` Maciej W. Rozycki
  0 siblings, 1 reply; 262+ messages in thread
From: Ralf Baechle @ 2015-01-20 22:20 UTC (permalink / raw)
  To: David Daney
  Cc: Markos Chandras, Maciej W. Rozycki, linux-mips, Matthew Fortune

On Tue, Jan 20, 2015 at 09:17:59AM -0800, David Daney wrote:

> >>>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 c6d06d383ef9..500050d3bda6 100644
> >>>--- a/arch/mips/include/asm/spinlock.h
> >>>+++ b/arch/mips/include/asm/spinlock.h
> >>>@@ -276,7 +276,7 @@ static inline void arch_read_unlock(arch_rwlock_t *rw)
> >>>  		do {
> >>>  			__asm__ __volatile__(
> >>>  			"1:	ll	%1, %2	# arch_read_unlock	\n"
> >>>-			"	sub	%1, 1				\n"
> >>>+			"	addiu	%1, -1				\n"
> >>>  			"	sc	%1, %0				\n"
> >>>  			: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
> >>>  			: GCC_OFF12_ASM() (rw->lock)
> >>
> >>  This integer overflow trap is deliberate here -- have you seen the note
> >>just above:
> >>
> >>/* Note the use of sub, not subu which will make the kernel die with an
> >>    overflow exception if we ever try to unlock an rwlock that is already
> >>    unlocked or is being held by a writer.  */
> >>
> 
> According to a comment on another thread from Ralf, this has been observed
> in the wild only once.  We can simplify the code and remove that comment.
> Why not just use the ADDIU and be done with it?
> 
> There are many locking and atomic primitives that don't have any such error
> checking.  What makes the read lock so special that it needs this extra
> protection?

Because I was desparate to find a use for the signed add ;-)

Honestly, it's nice to have such a safeguard if it's available at no
runtime overhead at all but these days are such nice lock debugging tools
that the loss won't be missed.  So (cut'n'paste):

Why not just use the ADDIU and be done with it?

  Ralf

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

* Re: [PATCH RFC v2 28/70] MIPS: kernel: cpu-probe.c: Add support for MIPS R6
  2015-01-16 10:49   ` Markos Chandras
  (?)
@ 2015-01-20 23:32   ` Maciej W. Rozycki
  2015-01-21 11:22       ` Markos Chandras
  2015-01-21 11:40       ` James Hogan
  -1 siblings, 2 replies; 262+ messages in thread
From: Maciej W. Rozycki @ 2015-01-20 23:32 UTC (permalink / raw)
  To: Markos Chandras; +Cc: linux-mips, Leonid Yegoshin

On Fri, 16 Jan 2015, Markos Chandras wrote:

> diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
> index cc77fdaca0eb..328b61f63430 100644
> --- a/arch/mips/kernel/cpu-probe.c
> +++ b/arch/mips/kernel/cpu-probe.c
> @@ -237,6 +237,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 */

 Typos here: s/incopatible/incompatible/

> @@ -541,7 +554,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) {

 Hmm, maybe define a macro:

#define cpu_has_mips_r2_r6 (cpu_has_mips_r2 | cpu_has_mips_r6)

(bitwise OR used to follow our preexisting convention, it often produces 
shorter and faster code)?  To have it centrally controlled and to shorten 
source code.  We have precedents already, see the `Shortcuts' section in 
<asm/cpu-features.h>.

> @@ -1351,7 +1364,8 @@ void cpu_probe(void)
>  		c->fpu_id = cpu_get_fpu_id();
>  
>  		if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M32R2 |
> -				    MIPS_CPU_ISA_M64R1 | MIPS_CPU_ISA_M64R2)) {
> +				    MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R1 |
> +				    MIPS_CPU_ISA_M64R2 | MIPS_CPU_ISA_M64R6)) {

 Likewise, this could have used `cpu_has_mips_r' as it stands; with the
R6 update it can be `cpu_has_mips_r1_r2_r6'.

 This uses `c->isa_level' rather than `cpu_data[0].isa_level' that 
`cpu_has_*' macros use, but that's not a problem as we do not support 
mixed ISA levels anyway and standardising on these macros makes 
maintenance easier, e.g. if we decided to actually use 
`current_cpu_data.isa_level' or suchlike in these macros instead.

 As a side note I can see that as from a96102be, ISA flags are inclusive, 
so the macros in <asm/cpu-features.h> can and I think should be rearranged 
and simplified.  E.g. (indentation adjusted, we can afford it now):

#define cpu_has_mips_2_3_4_5	cpu_has_mips_2
#define cpu_has_mips_3_4_5	cpu_has_mips_3

#define cpu_has_mips_2_3_4_5_r	cpu_has_mips_2

#define cpu_has_mips32		cpu_has_mips32r1
#define cpu_has_mips64		cpu_has_mips64r1

#define cpu_has_mips_r		cpu_has_mips32r1

etc.  With R6 in the picture I think the `*_r' macros need to go, to avoid 
confusion; I suggest renaming them to `*_r1_r2' to follow the existing 
convention.  Then the above macros will look like:

#define cpu_has_mips_2_3_4_5		cpu_has_mips_2
#define cpu_has_mips_3_4_5		cpu_has_mips_3

#define cpu_has_mips_2_3_4_5_r1_r2	cpu_has_mips_2

#define cpu_has_mips32			(cpu_has_mips32r1 | cpu_has_mips32r6)
#define cpu_has_mips64			(cpu_has_mips64r1 | cpu_has_mips64r6)

#define cpu_has_mips_r1_r2		cpu_has_mips32r1

etc., plus new ones:

#define cpu_has_mips_r1_r2_r6		(cpu_has_mips32r1 | cpu_has_mips32r6)
#define cpu_has_mips_r2_r6		(cpu_has_mips32r2 | cpu_has_mips32r6)
#define cpu_has_mips_r6			cpu_has_mips32r6

etc.

 Thoughts?

  Maciej

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

* Re: [PATCH RFC v2 30/70] MIPS: kernel: proc: Add MIPS R6 support to /proc/cpuinfo
  2015-01-16 10:49   ` Markos Chandras
  (?)
@ 2015-01-20 23:42   ` Maciej W. Rozycki
  2015-01-21  9:25       ` Markos Chandras
  -1 siblings, 1 reply; 262+ messages in thread
From: Maciej W. Rozycki @ 2015-01-20 23:42 UTC (permalink / raw)
  To: Markos Chandras; +Cc: linux-mips

On Fri, 16 Jan 2015, 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 | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
> index 097fc8d14e42..a8fdf9685cad 100644
> --- a/arch/mips/kernel/proc.c
> +++ b/arch/mips/kernel/proc.c
> @@ -82,7 +82,9 @@ static int show_cpuinfo(struct seq_file *m, void *v)
>  		seq_printf(m, "]\n");
>  	}
>  
> -	seq_printf(m, "isa\t\t\t: mips1");
> +	seq_printf(m, "isa\t\t\t:"); 
> +	if (!cpu_has_mips_r6)
> +		seq_printf(m, " mips1");

 I think define `cpu_has_mips_r1' instead and use it here.  It may turn 
out needed elsewhere too.  We probably don't need a new `MIPS_CPU_ISA_I' 
bit at this stage so this could be:

#define cpu_has_mips_r1		(!cpu_has_mips_r6)

for now, and we can determine later on if the new bit is indeed required.

  Maciej

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

* Re: [PATCH RFC v2 31/70] MIPS: kernel: traps: Add MIPS R6 related definitions
  2015-01-16 10:49   ` Markos Chandras
  (?)
@ 2015-01-20 23:49   ` Maciej W. Rozycki
  -1 siblings, 0 replies; 262+ messages in thread
From: Maciej W. Rozycki @ 2015-01-20 23:49 UTC (permalink / raw)
  To: Markos Chandras; +Cc: linux-mips, Leonid Yegoshin

On Fri, 16 Jan 2015, Markos Chandras wrote:

> diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
> index 461653ea28c8..81cface72bb0 100644
> --- a/arch/mips/kernel/traps.c
> +++ b/arch/mips/kernel/traps.c
> @@ -1649,7 +1649,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) &&

 Same observation about the `cpu_has_mips_r2_r6' macro as in the other 
e-mail.  Likewise throughout this patch.  I won't repeat it for any 
further occurences in the remaining patches, please assume this 
automatically and revise the changes yourself.

>  	    ((current_cpu_data.processor_id & 0xff0000) == PRID_COMP_MIPS)) {

 Hmm, this could and should use `PRID_COMP_MASK' rather than hardcoded 
0xff0000.  Similarly elsewhere down this patch.  That'd be a separate 
cleanup.

  Maciej

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

* Re: [PATCH RFC v2 35/70] MIPS: kernel: cps-vec: Replace addi with addiu
  2015-01-16 10:49   ` Markos Chandras
  (?)
@ 2015-01-21  0:02   ` Maciej W. Rozycki
  -1 siblings, 0 replies; 262+ messages in thread
From: Maciej W. Rozycki @ 2015-01-21  0:02 UTC (permalink / raw)
  To: Markos Chandras; +Cc: linux-mips, Paul Burton

On Fri, 16 Jan 2015, Markos Chandras wrote:

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

 This looks like another case of an unrelated ADDIU vs ADDI bug, there's 
nothing in this code apparent to me that would make it want trap on 
integer overflows.  This should go in separately IMHO, not as a part of R6 
changes, and right away, including all the relevant release branches.

 Of course an updated description would do, I'll mark such an update as 
reviewed by me to speed up processing.

  Maciej

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

* Re: [PATCH RFC v2 24/70] MIPS: asm: spinlock: Replace sub instruction with addiu
  2015-01-20 22:20         ` Ralf Baechle
@ 2015-01-21  0:58           ` Maciej W. Rozycki
  0 siblings, 0 replies; 262+ messages in thread
From: Maciej W. Rozycki @ 2015-01-21  0:58 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: David Daney, Markos Chandras, linux-mips, Matthew Fortune

Ralf,

> > According to a comment on another thread from Ralf, this has been observed
> > in the wild only once.  We can simplify the code and remove that comment.
> > Why not just use the ADDIU and be done with it?
> > 
> > There are many locking and atomic primitives that don't have any such error
> > checking.  What makes the read lock so special that it needs this extra
> > protection?
> 
> Because I was desparate to find a use for the signed add ;-)
> 
> Honestly, it's nice to have such a safeguard if it's available at no
> runtime overhead at all but these days are such nice lock debugging tools
> that the loss won't be missed.  So (cut'n'paste):
> 
> Why not just use the ADDIU and be done with it?

 Given David's comment I meant to defer to you on this as the originator 
of this bit, but since you have spoken, I think we've come to a conclusion 
now. :)

  Maciej

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

* Re: [PATCH RFC v2 45/70] MIPS: kernel: branch: Prevent BLTZL emulation for MIPS R6
@ 2015-01-21  1:59     ` Maciej W. Rozycki
  0 siblings, 0 replies; 262+ messages in thread
From: Maciej W. Rozycki @ 2015-01-21  1:59 UTC (permalink / raw)
  To: Markos Chandras; +Cc: linux-mips

On Fri, 16 Jan 2015, Markos Chandras wrote:

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

 I appreciate your effort in splitting 45-52/70 into separate patches, but 
frankly I think removing individual branch instructions one by one seems 
an overkill to me, and actually makes a review more difficult.  They 
comprise a single functional entity and can really be treated as one 
feature and splitting it into pieces makes it easy to miss the big 
picture.

> diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
> index 9b622ca391d8..502bf2aeb834 100644
> --- a/arch/mips/kernel/branch.c
> +++ b/arch/mips/kernel/branch.c
> @@ -436,6 +436,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)

 For example here it is obvious that there is no need to repeat the 
condition and:

		switch (insn.i_format.rt) {
		case bltzl_op:
			if (NO_R6EMU) {
				ret = -SIGILL;
				/* not emulating the branch likely for R6 */
				break;
			}
			/* Fall through */
		case bltz_op:

will do.

 However the way how the return value is set and the error return path 
handled here is inconsistent with how BPOSGE32 does these things here.  
From how `__compute_return_epc' and `evaluate_branch_instruction' handle 
error returns it looks to me it's BPOSGE32 that is right.  So you do need 
to return -EFAULT instead and send a signal, probably SIGILL.

 So it looks to me you want to use `goto' instead, to a similar exit path 
(a poor man's plain C exception handler) like BPOSGE32 uses, with a 
similar message produced to the kernel log and SIGILL thrown, maybe 
calling them `sigill_dsp' and `sigill_r6' respectively.  Why BPOSGE32 uses 
SIGBUS instead escapes me, perhaps someone just copied and pasted the 
`unaligned' case from `__compute_return_epc' without thinking much.  I 
think it should be fixed too, or otherwise an explanatory comment added.

> diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
> index 9707af43913f..e70513d552f6 100644
> --- a/arch/mips/math-emu/cp1emu.c
> +++ b/arch/mips/math-emu/cp1emu.c
> @@ -465,6 +465,8 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
>  			/* Fall through */
>  		case bltz_op:
>  		case bltzl_op:
> +			if (NO_R6EMU && (insn.i_format.rt == bltzl_op))
> +				break;
>  			if ((long)regs->regs[insn.i_format.rs] < 0)
>  				*contpc = regs->cp0_epc +
>  					dec_insn.pc_inc +

 Then here it is not obvious at all what to do.  There is a fall-through 
already, so without seeing 47/70 that pokes at `bltzall_op' immediately 
above it is difficult to decide whether your proposal is suitable or not.

 And last but not least all these 8 changes follow the same pattern, so it 
does not appear to me like one could be accepted as just fine and another 
one rejected to be rewritten as fundamentally broken.

  Maciej

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

* Re: [PATCH RFC v2 45/70] MIPS: kernel: branch: Prevent BLTZL emulation for MIPS R6
@ 2015-01-21  1:59     ` Maciej W. Rozycki
  0 siblings, 0 replies; 262+ messages in thread
From: Maciej W. Rozycki @ 2015-01-21  1:59 UTC (permalink / raw)
  To: Markos Chandras; +Cc: linux-mips

On Fri, 16 Jan 2015, Markos Chandras wrote:

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

 I appreciate your effort in splitting 45-52/70 into separate patches, but 
frankly I think removing individual branch instructions one by one seems 
an overkill to me, and actually makes a review more difficult.  They 
comprise a single functional entity and can really be treated as one 
feature and splitting it into pieces makes it easy to miss the big 
picture.

> diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
> index 9b622ca391d8..502bf2aeb834 100644
> --- a/arch/mips/kernel/branch.c
> +++ b/arch/mips/kernel/branch.c
> @@ -436,6 +436,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)

 For example here it is obvious that there is no need to repeat the 
condition and:

		switch (insn.i_format.rt) {
		case bltzl_op:
			if (NO_R6EMU) {
				ret = -SIGILL;
				/* not emulating the branch likely for R6 */
				break;
			}
			/* Fall through */
		case bltz_op:

will do.

 However the way how the return value is set and the error return path 
handled here is inconsistent with how BPOSGE32 does these things here.  

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

* Re: [PATCH RFC v2 19/70] MIPS: Use the new "ZC" constraint for MIPS R6
  2015-01-20 14:37             ` Maciej W. Rozycki
  2015-01-20 14:46               ` Maciej W. Rozycki
@ 2015-01-21  9:06               ` Markos Chandras
  1 sibling, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-21  9:06 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: Matthew Fortune, linux-mips

On 01/20/2015 02:37 PM, Maciej W. Rozycki wrote:
> On Tue, 20 Jan 2015, Markos Chandras wrote:
> 
>>>> We have tools out there based on 4.9. If we make gcc < 5.0 to fail with
>>>> R6, then nobody will be able to build it until 5.0 is released.
>>>> Perhaps it makes sense to add some checks in arch/mips/Makefile, see if
>>>> our gcc supports -mips32r6 or something and then decide what to do.
>>>
>>> Indeed, I think it is worthwhile supporting the use of tools which have R6
>>> backported to them owing to long lead times for new versions of GCC to be
>>> released.
>>>
>>> I think you could actually just switch the check around and remove the
>>> check for micromips entirely, putting the GCC 4.9 check first:
>>>
>>> #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
>>> #define GCC_OFF12_ASM() "ZC"
>>> #else
>>> #define GCC_OFF12_ASM() "R"
>>> #endif
>>>
>>> From what I can see this is safe. It was presumably written with a micromips
>>> check out of caution to not change older non-micromips code-gen but that
>>> doesn't seem particularly important. It is an improvement to older code if
>>> anything.
>>
>> For non-micromips kernel, this will start using "ZC" instead of "R",
>> whereas before, it only used "ZC" for micromips and "R" for everything
>> else. Is that safe? Maciej was the one committed this code, so if that's
>> still safe, then I will change it as requested.
> 
>  I'm fine with this proposal; a separate Makefile check for 
> `-march=mips32r6' support would be good too.
> 
>   Maciej
> 
I think we are over engineering this. In patch 04/70 you suggested

cflags-$(CONFIG_CPU_MIPS32_R6)	+= -march=mips32r6 -Wa,--trap
cflags-$(CONFIG_CPU_MIPS64_R6)	+= -march=mips64r6 -Wa,--trap

that means that you will pass march=mips32r6 if _R6 is selected without
checking if the toolchain support.

We know that every toolchain that has r6 support will have ZC support as
well. So my question is, why is the original patch wrong. Do you really
need to trap here for r6? Like I said, ever R6 toolchain will support
ZC. If you are trying to build R6 with a non-r6 toolchain you surely
have broken the build earlier on.

Having said that. I believe the original patch is fine.

-- 
markos

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

* Re: [PATCH RFC v2 30/70] MIPS: kernel: proc: Add MIPS R6 support to /proc/cpuinfo
@ 2015-01-21  9:25       ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-21  9:25 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: linux-mips

On 01/20/2015 11:42 PM, Maciej W. Rozycki wrote:
> On Fri, 16 Jan 2015, 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 | 8 +++++++-
>>  1 file changed, 7 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
>> index 097fc8d14e42..a8fdf9685cad 100644
>> --- a/arch/mips/kernel/proc.c
>> +++ b/arch/mips/kernel/proc.c
>> @@ -82,7 +82,9 @@ static int show_cpuinfo(struct seq_file *m, void *v)
>>  		seq_printf(m, "]\n");
>>  	}
>>  
>> -	seq_printf(m, "isa\t\t\t: mips1");
>> +	seq_printf(m, "isa\t\t\t:"); 
>> +	if (!cpu_has_mips_r6)
>> +		seq_printf(m, " mips1");
> 
>  I think define `cpu_has_mips_r1' instead and use it here.  It may turn 
> out needed elsewhere too.  We probably don't need a new `MIPS_CPU_ISA_I' 
> bit at this stage so this could be:

the change is simple enough and I see no reason to define the
cpu_has_mips_r1 at the moment. If we ever need to explicitly handle r1,
we can reconsider that.

-- 
markos

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

* Re: [PATCH RFC v2 30/70] MIPS: kernel: proc: Add MIPS R6 support to /proc/cpuinfo
@ 2015-01-21  9:25       ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-21  9:25 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: linux-mips

On 01/20/2015 11:42 PM, Maciej W. Rozycki wrote:
> On Fri, 16 Jan 2015, 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 | 8 +++++++-
>>  1 file changed, 7 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
>> index 097fc8d14e42..a8fdf9685cad 100644
>> --- a/arch/mips/kernel/proc.c
>> +++ b/arch/mips/kernel/proc.c
>> @@ -82,7 +82,9 @@ static int show_cpuinfo(struct seq_file *m, void *v)
>>  		seq_printf(m, "]\n");
>>  	}
>>  
>> -	seq_printf(m, "isa\t\t\t: mips1");
>> +	seq_printf(m, "isa\t\t\t:"); 
>> +	if (!cpu_has_mips_r6)
>> +		seq_printf(m, " mips1");
> 
>  I think define `cpu_has_mips_r1' instead and use it here.  It may turn 
> out needed elsewhere too.  We probably don't need a new `MIPS_CPU_ISA_I' 
> bit at this stage so this could be:

the change is simple enough and I see no reason to define the
cpu_has_mips_r1 at the moment. If we ever need to explicitly handle r1,
we can reconsider that.

-- 
markos

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

* Re: [PATCH RFC v2 27/70] MIPS: kernel: cevt-r4k: Add MIPS R6 to the c0_compare_interrupt handler
@ 2015-01-21  9:34           ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-21  9:34 UTC (permalink / raw)
  To: Maciej W. Rozycki, James Hogan; +Cc: linux-mips, Leonid Yegoshin

On 01/20/2015 02:33 PM, Maciej W. Rozycki wrote:
> On Tue, 20 Jan 2015, James Hogan wrote:
> 
>>>  While a preexisting bug, this is simply not true, there's CP0.Cause.TI to 
>>> examine for a timer interrupt pending.  Please fix your change to use 
>>> `c0_compare_int_pending' instead and synchronise with stuff posted by 
>>> James (cc-ed) at <http://patchwork.linux-mips.org/patch/8900/>.
>>
>> I'm not sure I follow what you mean. This change makes it treat r6 like
>> it treats r2 (i.e. there is still a Cause.TI bit), which sounds correct
>> to me. I'm guessing cpu_has_mips_r6 doesn't imply cpu_has_mips_r2.
> 
>  Correct, R6 is not backwards compatible with R2 so it doesn't set the R2 
> flag and consequently any compatibility that does exist has to be handled 
> explicitly; see 28/70 for the details of the flag setup.
> 
>   Maciej
> 
So i guess the original patch is fine then? otherwise, like James said,
I am not sure what's wrong with it (apart from the fact that it will
conflict with what James posted on
http://patchwork.linux-mips.org/patch/8900/). Such conflicts will be
taken care of when Ralf is ready to merge R6.

-- 
markos

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

* Re: [PATCH RFC v2 27/70] MIPS: kernel: cevt-r4k: Add MIPS R6 to the c0_compare_interrupt handler
@ 2015-01-21  9:34           ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-21  9:34 UTC (permalink / raw)
  To: Maciej W. Rozycki, James Hogan; +Cc: linux-mips, Leonid Yegoshin

On 01/20/2015 02:33 PM, Maciej W. Rozycki wrote:
> On Tue, 20 Jan 2015, James Hogan wrote:
> 
>>>  While a preexisting bug, this is simply not true, there's CP0.Cause.TI to 
>>> examine for a timer interrupt pending.  Please fix your change to use 
>>> `c0_compare_int_pending' instead and synchronise with stuff posted by 
>>> James (cc-ed) at <http://patchwork.linux-mips.org/patch/8900/>.
>>
>> I'm not sure I follow what you mean. This change makes it treat r6 like
>> it treats r2 (i.e. there is still a Cause.TI bit), which sounds correct
>> to me. I'm guessing cpu_has_mips_r6 doesn't imply cpu_has_mips_r2.
> 
>  Correct, R6 is not backwards compatible with R2 so it doesn't set the R2 
> flag and consequently any compatibility that does exist has to be handled 
> explicitly; see 28/70 for the details of the flag setup.
> 
>   Maciej
> 
So i guess the original patch is fine then? otherwise, like James said,
I am not sure what's wrong with it (apart from the fact that it will
conflict with what James posted on
http://patchwork.linux-mips.org/patch/8900/). Such conflicts will be
taken care of when Ralf is ready to merge R6.

-- 
markos

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

* Re: [PATCH RFC v2 45/70] MIPS: kernel: branch: Prevent BLTZL emulation for MIPS R6
@ 2015-01-21 10:43       ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-21 10:43 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: linux-mips

On 01/21/2015 01:59 AM, Maciej W. Rozycki wrote:
> On Fri, 16 Jan 2015, Markos Chandras wrote:
> 
>> 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>
>> ---
> 
>  I appreciate your effort in splitting 45-52/70 into separate patches, but 
> frankly I think removing individual branch instructions one by one seems 
> an overkill to me, and actually makes a review more difficult.  They 
> comprise a single functional entity and can really be treated as one 
> feature and splitting it into pieces makes it easy to miss the big 
> picture.
> 

Ok will do

>> diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
>> index 9b622ca391d8..502bf2aeb834 100644
>> --- a/arch/mips/kernel/branch.c
>> +++ b/arch/mips/kernel/branch.c
>> @@ -436,6 +436,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)
> 
>  For example here it is obvious that there is no need to repeat the 
> condition and:
> 
> 		switch (insn.i_format.rt) {
> 		case bltzl_op:
> 			if (NO_R6EMU) {
> 				ret = -SIGILL;
> 				/* not emulating the branch likely for R6 */
> 				break;
> 			}
> 			/* Fall through */
> 		case bltz_op:
> 
> will do.
> 
yes but i was trying to avoid touching more things than necessary. I
don't think the current code is unreadable, but I will change it as
suggested.

>  However the way how the return value is set and the error return path 
> handled here is inconsistent with how BPOSGE32 does these things here.  
> From how `__compute_return_epc' and `evaluate_branch_instruction' handle 
> error returns it looks to me it's BPOSGE32 that is right.  So you do need 
> to return -EFAULT instead and send a signal, probably SIGILL.
> 
>  So it looks to me you want to use `goto' instead, to a similar exit path 
> (a poor man's plain C exception handler) like BPOSGE32 uses, with a 
> similar message produced to the kernel log and SIGILL thrown, maybe 
> calling them `sigill_dsp' and `sigill_r6' respectively.  Why BPOSGE32 uses 
> SIGBUS instead escapes me, perhaps someone just copied and pasted the 
> `unaligned' case from `__compute_return_epc' without thinking much.  I 
> think it should be fixed too, or otherwise an explanatory comment added.
>

Ok I will do that.

-- 
markos

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

* Re: [PATCH RFC v2 45/70] MIPS: kernel: branch: Prevent BLTZL emulation for MIPS R6
@ 2015-01-21 10:43       ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-21 10:43 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: linux-mips

On 01/21/2015 01:59 AM, Maciej W. Rozycki wrote:
> On Fri, 16 Jan 2015, Markos Chandras wrote:
> 
>> 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>
>> ---
> 
>  I appreciate your effort in splitting 45-52/70 into separate patches, but 
> frankly I think removing individual branch instructions one by one seems 
> an overkill to me, and actually makes a review more difficult.  They 
> comprise a single functional entity and can really be treated as one 
> feature and splitting it into pieces makes it easy to miss the big 
> picture.
> 

Ok will do

>> diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
>> index 9b622ca391d8..502bf2aeb834 100644
>> --- a/arch/mips/kernel/branch.c
>> +++ b/arch/mips/kernel/branch.c
>> @@ -436,6 +436,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)
> 
>  For example here it is obvious that there is no need to repeat the 
> condition and:
> 
> 		switch (insn.i_format.rt) {
> 		case bltzl_op:
> 			if (NO_R6EMU) {
> 				ret = -SIGILL;
> 				/* not emulating the branch likely for R6 */
> 				break;
> 			}
> 			/* Fall through */
> 		case bltz_op:
> 
> will do.
> 
yes but i was trying to avoid touching more things than necessary. I
don't think the current code is unreadable, but I will change it as
suggested.

>  However the way how the return value is set and the error return path 
> handled here is inconsistent with how BPOSGE32 does these things here.  
> From how `__compute_return_epc' and `evaluate_branch_instruction' handle 
> error returns it looks to me it's BPOSGE32 that is right.  So you do need 
> to return -EFAULT instead and send a signal, probably SIGILL.
> 
>  So it looks to me you want to use `goto' instead, to a similar exit path 
> (a poor man's plain C exception handler) like BPOSGE32 uses, with a 
> similar message produced to the kernel log and SIGILL thrown, maybe 
> calling them `sigill_dsp' and `sigill_r6' respectively.  Why BPOSGE32 uses 
> SIGBUS instead escapes me, perhaps someone just copied and pasted the 
> `unaligned' case from `__compute_return_epc' without thinking much.  I 
> think it should be fixed too, or otherwise an explanatory comment added.
>

Ok I will do that.

-- 
markos

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

* Re: [PATCH RFC v2 28/70] MIPS: kernel: cpu-probe.c: Add support for MIPS R6
@ 2015-01-21 11:22       ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-21 11:22 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: linux-mips, Leonid Yegoshin

On 01/20/2015 11:32 PM, Maciej W. Rozycki wrote:
> On Fri, 16 Jan 2015, Markos Chandras wrote:
> 
>> diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
>> index cc77fdaca0eb..328b61f63430 100644
>> --- a/arch/mips/kernel/cpu-probe.c
>> +++ b/arch/mips/kernel/cpu-probe.c
>> @@ -237,6 +237,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 */
> 
>  Typos here: s/incopatible/incompatible/

Ok thanks

> 
>> @@ -541,7 +554,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) {
> 
>  Hmm, maybe define a macro:
> 
> #define cpu_has_mips_r2_r6 (cpu_has_mips_r2 | cpu_has_mips_r6)

Yes will do

> 
> (bitwise OR used to follow our preexisting convention, it often produces 
> shorter and faster code)?  To have it centrally controlled and to shorten 
> source code.  We have precedents already, see the `Shortcuts' section in 
> <asm/cpu-features.h>.
> 
>> @@ -1351,7 +1364,8 @@ void cpu_probe(void)
>>  		c->fpu_id = cpu_get_fpu_id();
>>  
>>  		if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M32R2 |
>> -				    MIPS_CPU_ISA_M64R1 | MIPS_CPU_ISA_M64R2)) {
>> +				    MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R1 |
>> +				    MIPS_CPU_ISA_M64R2 | MIPS_CPU_ISA_M64R6)) {
> 
>  Likewise, this could have used `cpu_has_mips_r' as it stands; with the
> R6 update it can be `cpu_has_mips_r1_r2_r6'.

cpu_has_mips_r should be fine thanks.

> 
>  This uses `c->isa_level' rather than `cpu_data[0].isa_level' that 
> `cpu_has_*' macros use, but that's not a problem as we do not support 
> mixed ISA levels anyway and standardising on these macros makes 
> maintenance easier, e.g. if we decided to actually use 
> `current_cpu_data.isa_level' or suchlike in these macros instead.
> 
>  As a side note I can see that as from a96102be, ISA flags are inclusive, 
> so the macros in <asm/cpu-features.h> can and I think should be rearranged 
> and simplified.  E.g. (indentation adjusted, we can afford it now):
> 
> #define cpu_has_mips_2_3_4_5	cpu_has_mips_2
> #define cpu_has_mips_3_4_5	cpu_has_mips_3
> 
> #define cpu_has_mips_2_3_4_5_r	cpu_has_mips_2
> 
> #define cpu_has_mips32		cpu_has_mips32r1
> #define cpu_has_mips64		cpu_has_mips64r1
> 
> #define cpu_has_mips_r		cpu_has_mips32r1
> 
> etc.  With R6 in the picture I think the `*_r' macros need to go, to avoid 
> confusion; I suggest renaming them to `*_r1_r2' to follow the existing 
> convention.  Then the above macros will look like:
> 
> #define cpu_has_mips_2_3_4_5		cpu_has_mips_2
> #define cpu_has_mips_3_4_5		cpu_has_mips_3
> 
> #define cpu_has_mips_2_3_4_5_r1_r2	cpu_has_mips_2
> 
> #define cpu_has_mips32			(cpu_has_mips32r1 | cpu_has_mips32r6)
> #define cpu_has_mips64			(cpu_has_mips64r1 | cpu_has_mips64r6)
> 
> #define cpu_has_mips_r1_r2		cpu_has_mips32r1
> 
> etc., plus new ones:
> 
> #define cpu_has_mips_r1_r2_r6		(cpu_has_mips32r1 | cpu_has_mips32r6)
> #define cpu_has_mips_r2_r6		(cpu_has_mips32r2 | cpu_has_mips32r6)
> #define cpu_has_mips_r6			cpu_has_mips32r6
> 
> etc.
> 
>  Thoughts?
> 
>   Maciej
> 

I like the suggestion but I'd rather do that post-r6 as a separate clean up.

-- 
markos

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

* Re: [PATCH RFC v2 28/70] MIPS: kernel: cpu-probe.c: Add support for MIPS R6
@ 2015-01-21 11:22       ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-21 11:22 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: linux-mips, Leonid Yegoshin

On 01/20/2015 11:32 PM, Maciej W. Rozycki wrote:
> On Fri, 16 Jan 2015, Markos Chandras wrote:
> 
>> diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
>> index cc77fdaca0eb..328b61f63430 100644
>> --- a/arch/mips/kernel/cpu-probe.c
>> +++ b/arch/mips/kernel/cpu-probe.c
>> @@ -237,6 +237,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 */
> 
>  Typos here: s/incopatible/incompatible/

Ok thanks

> 
>> @@ -541,7 +554,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) {
> 
>  Hmm, maybe define a macro:
> 
> #define cpu_has_mips_r2_r6 (cpu_has_mips_r2 | cpu_has_mips_r6)

Yes will do

> 
> (bitwise OR used to follow our preexisting convention, it often produces 
> shorter and faster code)?  To have it centrally controlled and to shorten 
> source code.  We have precedents already, see the `Shortcuts' section in 
> <asm/cpu-features.h>.
> 
>> @@ -1351,7 +1364,8 @@ void cpu_probe(void)
>>  		c->fpu_id = cpu_get_fpu_id();
>>  
>>  		if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M32R2 |
>> -				    MIPS_CPU_ISA_M64R1 | MIPS_CPU_ISA_M64R2)) {
>> +				    MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R1 |
>> +				    MIPS_CPU_ISA_M64R2 | MIPS_CPU_ISA_M64R6)) {
> 
>  Likewise, this could have used `cpu_has_mips_r' as it stands; with the
> R6 update it can be `cpu_has_mips_r1_r2_r6'.

cpu_has_mips_r should be fine thanks.

> 
>  This uses `c->isa_level' rather than `cpu_data[0].isa_level' that 
> `cpu_has_*' macros use, but that's not a problem as we do not support 
> mixed ISA levels anyway and standardising on these macros makes 
> maintenance easier, e.g. if we decided to actually use 
> `current_cpu_data.isa_level' or suchlike in these macros instead.
> 
>  As a side note I can see that as from a96102be, ISA flags are inclusive, 
> so the macros in <asm/cpu-features.h> can and I think should be rearranged 
> and simplified.  E.g. (indentation adjusted, we can afford it now):
> 
> #define cpu_has_mips_2_3_4_5	cpu_has_mips_2
> #define cpu_has_mips_3_4_5	cpu_has_mips_3
> 
> #define cpu_has_mips_2_3_4_5_r	cpu_has_mips_2
> 
> #define cpu_has_mips32		cpu_has_mips32r1
> #define cpu_has_mips64		cpu_has_mips64r1
> 
> #define cpu_has_mips_r		cpu_has_mips32r1
> 
> etc.  With R6 in the picture I think the `*_r' macros need to go, to avoid 
> confusion; I suggest renaming them to `*_r1_r2' to follow the existing 
> convention.  Then the above macros will look like:
> 
> #define cpu_has_mips_2_3_4_5		cpu_has_mips_2
> #define cpu_has_mips_3_4_5		cpu_has_mips_3
> 
> #define cpu_has_mips_2_3_4_5_r1_r2	cpu_has_mips_2
> 
> #define cpu_has_mips32			(cpu_has_mips32r1 | cpu_has_mips32r6)
> #define cpu_has_mips64			(cpu_has_mips64r1 | cpu_has_mips64r6)
> 
> #define cpu_has_mips_r1_r2		cpu_has_mips32r1
> 
> etc., plus new ones:
> 
> #define cpu_has_mips_r1_r2_r6		(cpu_has_mips32r1 | cpu_has_mips32r6)
> #define cpu_has_mips_r2_r6		(cpu_has_mips32r2 | cpu_has_mips32r6)
> #define cpu_has_mips_r6			cpu_has_mips32r6
> 
> etc.
> 
>  Thoughts?
> 
>   Maciej
> 

I like the suggestion but I'd rather do that post-r6 as a separate clean up.

-- 
markos

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

* Re: [PATCH RFC v2 28/70] MIPS: kernel: cpu-probe.c: Add support for MIPS R6
@ 2015-01-21 11:40       ` James Hogan
  0 siblings, 0 replies; 262+ messages in thread
From: James Hogan @ 2015-01-21 11:40 UTC (permalink / raw)
  To: Maciej W. Rozycki, Markos Chandras
  Cc: linux-mips, Leonid Yegoshin, David Daney (Cavium)

[-- Attachment #1: Type: text/plain, Size: 935 bytes --]

Hi Maciej,

On 20/01/15 23:32, Maciej W. Rozycki wrote:
>  As a side note I can see that as from a96102be, ISA flags are inclusive, 
> so the macros in <asm/cpu-features.h> can and I think should be rearranged 
> and simplified.  E.g. (indentation adjusted, we can afford it now):
> 
> #define cpu_has_mips_2_3_4_5	cpu_has_mips_2
> #define cpu_has_mips_3_4_5	cpu_has_mips_3
> 
> #define cpu_has_mips_2_3_4_5_r	cpu_has_mips_2
> 
> #define cpu_has_mips32		cpu_has_mips32r1
> #define cpu_has_mips64		cpu_has_mips64r1
> 
> #define cpu_has_mips_r		cpu_has_mips32r1

this isn't always the case. Although set_isa will do the right thing,
some platforms override these in exclusive ways, e.g.:

https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h#n49

David on Cc in case he'd like to justify that. IMO it seems wrong.

Cheers
James


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [PATCH RFC v2 28/70] MIPS: kernel: cpu-probe.c: Add support for MIPS R6
@ 2015-01-21 11:40       ` James Hogan
  0 siblings, 0 replies; 262+ messages in thread
From: James Hogan @ 2015-01-21 11:40 UTC (permalink / raw)
  To: Maciej W. Rozycki, Markos Chandras
  Cc: linux-mips, Leonid Yegoshin, David Daney (Cavium)

[-- Attachment #1: Type: text/plain, Size: 935 bytes --]

Hi Maciej,

On 20/01/15 23:32, Maciej W. Rozycki wrote:
>  As a side note I can see that as from a96102be, ISA flags are inclusive, 
> so the macros in <asm/cpu-features.h> can and I think should be rearranged 
> and simplified.  E.g. (indentation adjusted, we can afford it now):
> 
> #define cpu_has_mips_2_3_4_5	cpu_has_mips_2
> #define cpu_has_mips_3_4_5	cpu_has_mips_3
> 
> #define cpu_has_mips_2_3_4_5_r	cpu_has_mips_2
> 
> #define cpu_has_mips32		cpu_has_mips32r1
> #define cpu_has_mips64		cpu_has_mips64r1
> 
> #define cpu_has_mips_r		cpu_has_mips32r1

this isn't always the case. Although set_isa will do the right thing,
some platforms override these in exclusive ways, e.g.:

https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h#n49

David on Cc in case he'd like to justify that. IMO it seems wrong.

Cheers
James


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [PATCH RFC v2 18/70] MIPS: asm: spram: Add MIPS R6 related definitions
@ 2015-01-21 12:16       ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-21 12:16 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: linux-mips

On 01/20/2015 12:13 AM, Maciej W. Rozycki wrote:
> On Fri, 16 Jan 2015, Markos Chandras wrote:
> 
>> 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 92987d1bbe5f..0862ae781339 100644
>> --- a/arch/mips/kernel/Makefile
>> +++ b/arch/mips/kernel/Makefile
>> @@ -53,6 +53,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
> 
>  It looks to me like this should be a separate CONFIG_MIPS_SPRAM option 
> selected by CPU_MIPSR2 and CPU_MIPSR6.  This will avoid the need to list 
> `spram.o' twice which may be asking for troubles.  Also this will keep 
> simple the `#ifdef' condition above.
> 
>   Maciej
> 
ok i will do that instead. thanks

-- 
markos

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

* Re: [PATCH RFC v2 18/70] MIPS: asm: spram: Add MIPS R6 related definitions
@ 2015-01-21 12:16       ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-21 12:16 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: linux-mips

On 01/20/2015 12:13 AM, Maciej W. Rozycki wrote:
> On Fri, 16 Jan 2015, Markos Chandras wrote:
> 
>> 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 92987d1bbe5f..0862ae781339 100644
>> --- a/arch/mips/kernel/Makefile
>> +++ b/arch/mips/kernel/Makefile
>> @@ -53,6 +53,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
> 
>  It looks to me like this should be a separate CONFIG_MIPS_SPRAM option 
> selected by CPU_MIPSR2 and CPU_MIPSR6.  This will avoid the need to list 
> `spram.o' twice which may be asking for troubles.  Also this will keep 
> simple the `#ifdef' condition above.
> 
>   Maciej
> 
ok i will do that instead. thanks

-- 
markos

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

* Re: [PATCH RFC v2 30/70] MIPS: kernel: proc: Add MIPS R6 support to /proc/cpuinfo
  2015-01-21  9:25       ` Markos Chandras
  (?)
@ 2015-01-22 14:08       ` Maciej W. Rozycki
  2015-01-22 14:43           ` Markos Chandras
  -1 siblings, 1 reply; 262+ messages in thread
From: Maciej W. Rozycki @ 2015-01-22 14:08 UTC (permalink / raw)
  To: Markos Chandras; +Cc: linux-mips

On Wed, 21 Jan 2015, Markos Chandras wrote:

> >> diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
> >> index 097fc8d14e42..a8fdf9685cad 100644
> >> --- a/arch/mips/kernel/proc.c
> >> +++ b/arch/mips/kernel/proc.c
> >> @@ -82,7 +82,9 @@ static int show_cpuinfo(struct seq_file *m, void *v)
> >>  		seq_printf(m, "]\n");
> >>  	}
> >>  
> >> -	seq_printf(m, "isa\t\t\t: mips1");
> >> +	seq_printf(m, "isa\t\t\t:"); 
> >> +	if (!cpu_has_mips_r6)
> >> +		seq_printf(m, " mips1");
> > 
> >  I think define `cpu_has_mips_r1' instead and use it here.  It may turn 
> > out needed elsewhere too.  We probably don't need a new `MIPS_CPU_ISA_I' 
> > bit at this stage so this could be:

 Typo here, I meant `cpu_has_mips_1' actually, sorry about that.

> the change is simple enough and I see no reason to define the
> cpu_has_mips_r1 at the moment. If we ever need to explicitly handle r1,
> we can reconsider that.

 It's a matter of code clarity, good code is self-explanatory.  Here the 
intent is to print `mips1' if it is supported.  By avoiding the extra 
definition you're detaching the intent from what code says.  Someone 
reading this code (who may not necessarily know the architecture documents 
by heart) has to scratch their head thinking: "why isn't `mips1' printed 
for R6, what the former has to do with the latter, and why is this case 
different to `mips2' and other ones that follow?"

 Whereas the intent is clear with this:

#define cpu_has_mips_1 (!cpu_has_mips_r6) // Aha, `mips1' is there if no R6!

	if (cpu_has_mips_1)
		seq_printf(m, " mips1");  // Well, this is obvious...

Do you see what I mean?  Do you agree now?

  Maciej

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

* Re: [PATCH RFC v2 30/70] MIPS: kernel: proc: Add MIPS R6 support to /proc/cpuinfo
@ 2015-01-22 14:43           ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-22 14:43 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: linux-mips

On 01/22/2015 02:08 PM, Maciej W. Rozycki wrote:
> On Wed, 21 Jan 2015, Markos Chandras wrote:
> 
>>>> diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
>>>> index 097fc8d14e42..a8fdf9685cad 100644
>>>> --- a/arch/mips/kernel/proc.c
>>>> +++ b/arch/mips/kernel/proc.c
>>>> @@ -82,7 +82,9 @@ static int show_cpuinfo(struct seq_file *m, void *v)
>>>>  		seq_printf(m, "]\n");
>>>>  	}
>>>>  
>>>> -	seq_printf(m, "isa\t\t\t: mips1");
>>>> +	seq_printf(m, "isa\t\t\t:"); 
>>>> +	if (!cpu_has_mips_r6)
>>>> +		seq_printf(m, " mips1");
>>>
>>>  I think define `cpu_has_mips_r1' instead and use it here.  It may turn 
>>> out needed elsewhere too.  We probably don't need a new `MIPS_CPU_ISA_I' 
>>> bit at this stage so this could be:
> 
>  Typo here, I meant `cpu_has_mips_1' actually, sorry about that.
> 
>> the change is simple enough and I see no reason to define the
>> cpu_has_mips_r1 at the moment. If we ever need to explicitly handle r1,
>> we can reconsider that.
> 
>  It's a matter of code clarity, good code is self-explanatory.  Here the 
> intent is to print `mips1' if it is supported.  By avoiding the extra 
> definition you're detaching the intent from what code says.  Someone 
> reading this code (who may not necessarily know the architecture documents 
> by heart) has to scratch their head thinking: "why isn't `mips1' printed 
> for R6, what the former has to do with the latter, and why is this case 
> different to `mips2' and other ones that follow?"
> 
>  Whereas the intent is clear with this:
> 
> #define cpu_has_mips_1 (!cpu_has_mips_r6) // Aha, `mips1' is there if no R6!
> 
> 	if (cpu_has_mips_1)
> 		seq_printf(m, " mips1");  // Well, this is obvious...

however, someone may wonder then why not have

if (cpu_has_mips_1)
print mips1
if (cpu_has_mips_2)
print mips2
if (cpu_has_mips_3)
print mips3

and only care about mips1.

> 
> Do you see what I mean?  Do you agree now?

the

if (!cpu_has_mips_r6)
    seq_printf(m, " mips1");

means exactly the same thing with

#define cpu_has_mips_1 (!cpu_has_mips_r6) // Aha, `mips1' is there if no R6!

especially since this is the only place that is being used.

I don't see how the differ.

In any case, i don't want such details to block the patchset, so I will
change it.

-- 
markos

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

* Re: [PATCH RFC v2 30/70] MIPS: kernel: proc: Add MIPS R6 support to /proc/cpuinfo
@ 2015-01-22 14:43           ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-22 14:43 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: linux-mips

On 01/22/2015 02:08 PM, Maciej W. Rozycki wrote:
> On Wed, 21 Jan 2015, Markos Chandras wrote:
> 
>>>> diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
>>>> index 097fc8d14e42..a8fdf9685cad 100644
>>>> --- a/arch/mips/kernel/proc.c
>>>> +++ b/arch/mips/kernel/proc.c
>>>> @@ -82,7 +82,9 @@ static int show_cpuinfo(struct seq_file *m, void *v)
>>>>  		seq_printf(m, "]\n");
>>>>  	}
>>>>  
>>>> -	seq_printf(m, "isa\t\t\t: mips1");
>>>> +	seq_printf(m, "isa\t\t\t:"); 
>>>> +	if (!cpu_has_mips_r6)
>>>> +		seq_printf(m, " mips1");
>>>
>>>  I think define `cpu_has_mips_r1' instead and use it here.  It may turn 
>>> out needed elsewhere too.  We probably don't need a new `MIPS_CPU_ISA_I' 
>>> bit at this stage so this could be:
> 
>  Typo here, I meant `cpu_has_mips_1' actually, sorry about that.
> 
>> the change is simple enough and I see no reason to define the
>> cpu_has_mips_r1 at the moment. If we ever need to explicitly handle r1,
>> we can reconsider that.
> 
>  It's a matter of code clarity, good code is self-explanatory.  Here the 
> intent is to print `mips1' if it is supported.  By avoiding the extra 
> definition you're detaching the intent from what code says.  Someone 
> reading this code (who may not necessarily know the architecture documents 
> by heart) has to scratch their head thinking: "why isn't `mips1' printed 
> for R6, what the former has to do with the latter, and why is this case 
> different to `mips2' and other ones that follow?"
> 
>  Whereas the intent is clear with this:
> 
> #define cpu_has_mips_1 (!cpu_has_mips_r6) // Aha, `mips1' is there if no R6!
> 
> 	if (cpu_has_mips_1)
> 		seq_printf(m, " mips1");  // Well, this is obvious...

however, someone may wonder then why not have

if (cpu_has_mips_1)
print mips1
if (cpu_has_mips_2)
print mips2
if (cpu_has_mips_3)
print mips3

and only care about mips1.

> 
> Do you see what I mean?  Do you agree now?

the

if (!cpu_has_mips_r6)
    seq_printf(m, " mips1");

means exactly the same thing with

#define cpu_has_mips_1 (!cpu_has_mips_r6) // Aha, `mips1' is there if no R6!

especially since this is the only place that is being used.

I don't see how the differ.

In any case, i don't want such details to block the patchset, so I will
change it.

-- 
markos

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

* Re: [PATCH RFC v2 30/70] MIPS: kernel: proc: Add MIPS R6 support to /proc/cpuinfo
@ 2015-01-22 15:03             ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-22 15:03 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: linux-mips

On 01/22/2015 02:43 PM, Markos Chandras wrote:
> On 01/22/2015 02:08 PM, Maciej W. Rozycki wrote:
>> On Wed, 21 Jan 2015, Markos Chandras wrote:
>>
>>>>> diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
>>>>> index 097fc8d14e42..a8fdf9685cad 100644
>>>>> --- a/arch/mips/kernel/proc.c
>>>>> +++ b/arch/mips/kernel/proc.c
>>>>> @@ -82,7 +82,9 @@ static int show_cpuinfo(struct seq_file *m, void *v)
>>>>>  		seq_printf(m, "]\n");
>>>>>  	}
>>>>>  
>>>>> -	seq_printf(m, "isa\t\t\t: mips1");
>>>>> +	seq_printf(m, "isa\t\t\t:"); 
>>>>> +	if (!cpu_has_mips_r6)
>>>>> +		seq_printf(m, " mips1");
>>>>
>>>>  I think define `cpu_has_mips_r1' instead and use it here.  It may turn 
>>>> out needed elsewhere too.  We probably don't need a new `MIPS_CPU_ISA_I' 
>>>> bit at this stage so this could be:
>>
>>  Typo here, I meant `cpu_has_mips_1' actually, sorry about that.
>>
>>> the change is simple enough and I see no reason to define the
>>> cpu_has_mips_r1 at the moment. If we ever need to explicitly handle r1,
>>> we can reconsider that.
>>
>>  It's a matter of code clarity, good code is self-explanatory.  Here the 
>> intent is to print `mips1' if it is supported.  By avoiding the extra 
>> definition you're detaching the intent from what code says.  Someone 
>> reading this code (who may not necessarily know the architecture documents 
>> by heart) has to scratch their head thinking: "why isn't `mips1' printed 
>> for R6, what the former has to do with the latter, and why is this case 
>> different to `mips2' and other ones that follow?"
>>
>>  Whereas the intent is clear with this:
>>
>> #define cpu_has_mips_1 (!cpu_has_mips_r6) // Aha, `mips1' is there if no R6!
>>
>> 	if (cpu_has_mips_1)
>> 		seq_printf(m, " mips1");  // Well, this is obvious...
> 
> however, someone may wonder then why not have
> 
> if (cpu_has_mips_1)
> print mips1
> if (cpu_has_mips_2)
> print mips2
> if (cpu_has_mips_3)
> print mips3
> 
> and only care about mips1.
oops that's already there. Then I guess your proposal makes the whole
thing consistent indeed.

-- 
markos

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

* Re: [PATCH RFC v2 30/70] MIPS: kernel: proc: Add MIPS R6 support to /proc/cpuinfo
@ 2015-01-22 15:03             ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-22 15:03 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: linux-mips

On 01/22/2015 02:43 PM, Markos Chandras wrote:
> On 01/22/2015 02:08 PM, Maciej W. Rozycki wrote:
>> On Wed, 21 Jan 2015, Markos Chandras wrote:
>>
>>>>> diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
>>>>> index 097fc8d14e42..a8fdf9685cad 100644
>>>>> --- a/arch/mips/kernel/proc.c
>>>>> +++ b/arch/mips/kernel/proc.c
>>>>> @@ -82,7 +82,9 @@ static int show_cpuinfo(struct seq_file *m, void *v)
>>>>>  		seq_printf(m, "]\n");
>>>>>  	}
>>>>>  
>>>>> -	seq_printf(m, "isa\t\t\t: mips1");
>>>>> +	seq_printf(m, "isa\t\t\t:"); 
>>>>> +	if (!cpu_has_mips_r6)
>>>>> +		seq_printf(m, " mips1");
>>>>
>>>>  I think define `cpu_has_mips_r1' instead and use it here.  It may turn 
>>>> out needed elsewhere too.  We probably don't need a new `MIPS_CPU_ISA_I' 
>>>> bit at this stage so this could be:
>>
>>  Typo here, I meant `cpu_has_mips_1' actually, sorry about that.
>>
>>> the change is simple enough and I see no reason to define the
>>> cpu_has_mips_r1 at the moment. If we ever need to explicitly handle r1,
>>> we can reconsider that.
>>
>>  It's a matter of code clarity, good code is self-explanatory.  Here the 
>> intent is to print `mips1' if it is supported.  By avoiding the extra 
>> definition you're detaching the intent from what code says.  Someone 
>> reading this code (who may not necessarily know the architecture documents 
>> by heart) has to scratch their head thinking: "why isn't `mips1' printed 
>> for R6, what the former has to do with the latter, and why is this case 
>> different to `mips2' and other ones that follow?"
>>
>>  Whereas the intent is clear with this:
>>
>> #define cpu_has_mips_1 (!cpu_has_mips_r6) // Aha, `mips1' is there if no R6!
>>
>> 	if (cpu_has_mips_1)
>> 		seq_printf(m, " mips1");  // Well, this is obvious...
> 
> however, someone may wonder then why not have
> 
> if (cpu_has_mips_1)
> print mips1
> if (cpu_has_mips_2)
> print mips2
> if (cpu_has_mips_3)
> print mips3
> 
> and only care about mips1.
oops that's already there. Then I guess your proposal makes the whole
thing consistent indeed.

-- 
markos

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

* [PATCH] MIPS: asm: Rename GCC_OFF12_ASM to GCC_OFF_SMALL_ASM
@ 2015-01-26 13:39     ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-26 13:39 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Maciej W. Rozycki

The GCC_OFF12_ASM macro is used for 12-bit immediate constrains
but we will also use it for 9-bit constrains on MIPS R6 so we
rename it to something more appropriate.

Cc: Maciej W. Rozycki <macro@linux-mips.org>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
This patch will be part of MIPS R6 and it will be placed before
the following one
[PATCH RFC v2 19/70] MIPS: Use the new "ZC" constraint for MIPS R6
http://www.linux-mips.org/archives/linux-mips/2015-01/msg00211.html
---
 arch/mips/include/asm/atomic.h                     | 30 +++++++-------
 arch/mips/include/asm/bitops.h                     | 34 +++++++--------
 arch/mips/include/asm/cmpxchg.h                    | 24 +++++------
 arch/mips/include/asm/compiler.h                   |  4 +-
 arch/mips/include/asm/edac.h                       |  4 +-
 arch/mips/include/asm/futex.h                      | 16 ++++----
 .../include/asm/mach-pmcs-msp71xx/msp_regops.h     | 24 +++++------
 arch/mips/include/asm/octeon/cvmx-cmd-queue.h      |  2 +-
 arch/mips/include/asm/spinlock.h                   | 48 +++++++++++-----------
 9 files changed, 93 insertions(+), 93 deletions(-)

diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h
index 857da84cfc92..3a44c2f17e53 100644
--- a/arch/mips/include/asm/atomic.h
+++ b/arch/mips/include/asm/atomic.h
@@ -54,7 +54,7 @@ static __inline__ void atomic_##op(int i, atomic_t * v)			      \
 		"	sc	%0, %1					\n"   \
 		"	beqzl	%0, 1b					\n"   \
 		"	.set	mips0					\n"   \
-		: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter)	      \
+		: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (v->counter)	      \
 		: "Ir" (i));						      \
 	} else if (kernel_uses_llsc) {					      \
 		int temp;						      \
@@ -66,7 +66,7 @@ static __inline__ void atomic_##op(int i, atomic_t * v)			      \
 			"	" #asm_op " %0, %2			\n"   \
 			"	sc	%0, %1				\n"   \
 			"	.set	mips0				\n"   \
-			: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter)      \
+			: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (v->counter)      \
 			: "Ir" (i));					      \
 		} while (unlikely(!temp));				      \
 	} else {							      \
@@ -97,7 +97,7 @@ static __inline__ int atomic_##op##_return(int i, atomic_t * v)		      \
 		"	" #asm_op " %0, %1, %3				\n"   \
 		"	.set	mips0					\n"   \
 		: "=&r" (result), "=&r" (temp),				      \
-		  "+" GCC_OFF12_ASM() (v->counter)			      \
+		  "+" GCC_OFF_SMALL_ASM() (v->counter)			      \
 		: "Ir" (i));						      \
 	} else if (kernel_uses_llsc) {					      \
 		int temp;						      \
@@ -110,7 +110,7 @@ static __inline__ int atomic_##op##_return(int i, atomic_t * v)		      \
 			"	sc	%0, %2				\n"   \
 			"	.set	mips0				\n"   \
 			: "=&r" (result), "=&r" (temp),			      \
-			  "+" GCC_OFF12_ASM() (v->counter)		      \
+			  "+" GCC_OFF_SMALL_ASM() (v->counter)		      \
 			: "Ir" (i));					      \
 		} while (unlikely(!result));				      \
 									      \
@@ -171,8 +171,8 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
 		"1:							\n"
 		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp),
-		  "+" GCC_OFF12_ASM() (v->counter)
-		: "Ir" (i), GCC_OFF12_ASM() (v->counter)
+		  "+" GCC_OFF_SMALL_ASM() (v->counter)
+		: "Ir" (i), GCC_OFF_SMALL_ASM() (v->counter)
 		: "memory");
 	} else if (kernel_uses_llsc) {
 		int temp;
@@ -190,7 +190,7 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
 		"1:							\n"
 		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp),
-		  "+" GCC_OFF12_ASM() (v->counter)
+		  "+" GCC_OFF_SMALL_ASM() (v->counter)
 		: "Ir" (i));
 	} else {
 		unsigned long flags;
@@ -333,7 +333,7 @@ static __inline__ void atomic64_##op(long i, atomic64_t * v)		      \
 		"	scd	%0, %1					\n"   \
 		"	beqzl	%0, 1b					\n"   \
 		"	.set	mips0					\n"   \
-		: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter)	      \
+		: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (v->counter)	      \
 		: "Ir" (i));						      \
 	} else if (kernel_uses_llsc) {					      \
 		long temp;						      \
@@ -345,7 +345,7 @@ static __inline__ void atomic64_##op(long i, atomic64_t * v)		      \
 			"	" #asm_op " %0, %2			\n"   \
 			"	scd	%0, %1				\n"   \
 			"	.set	mips0				\n"   \
-			: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter)      \
+			: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (v->counter)      \
 			: "Ir" (i));					      \
 		} while (unlikely(!temp));				      \
 	} else {							      \
@@ -376,7 +376,7 @@ static __inline__ long atomic64_##op##_return(long i, atomic64_t * v)	      \
 		"	" #asm_op " %0, %1, %3				\n"   \
 		"	.set	mips0					\n"   \
 		: "=&r" (result), "=&r" (temp),				      \
-		  "+" GCC_OFF12_ASM() (v->counter)			      \
+		  "+" GCC_OFF_SMALL_ASM() (v->counter)			      \
 		: "Ir" (i));						      \
 	} else if (kernel_uses_llsc) {					      \
 		long temp;						      \
@@ -389,8 +389,8 @@ static __inline__ long atomic64_##op##_return(long i, atomic64_t * v)	      \
 			"	scd	%0, %2				\n"   \
 			"	.set	mips0				\n"   \
 			: "=&r" (result), "=&r" (temp),			      \
-			  "=" GCC_OFF12_ASM() (v->counter)		      \
-			: "Ir" (i), GCC_OFF12_ASM() (v->counter)	      \
+			  "=" GCC_OFF_SMALL_ASM() (v->counter)		      \
+			: "Ir" (i), GCC_OFF_SMALL_ASM() (v->counter)	      \
 			: "memory");					      \
 		} while (unlikely(!result));				      \
 									      \
@@ -452,8 +452,8 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
 		"1:							\n"
 		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp),
-		  "=" GCC_OFF12_ASM() (v->counter)
-		: "Ir" (i), GCC_OFF12_ASM() (v->counter)
+		  "=" GCC_OFF_SMALL_ASM() (v->counter)
+		: "Ir" (i), GCC_OFF_SMALL_ASM() (v->counter)
 		: "memory");
 	} else if (kernel_uses_llsc) {
 		long temp;
@@ -471,7 +471,7 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
 		"1:							\n"
 		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp),
-		  "+" GCC_OFF12_ASM() (v->counter)
+		  "+" GCC_OFF_SMALL_ASM() (v->counter)
 		: "Ir" (i));
 	} else {
 		unsigned long flags;
diff --git a/arch/mips/include/asm/bitops.h b/arch/mips/include/asm/bitops.h
index 6663bcca9d0c..6cc1f539c79a 100644
--- a/arch/mips/include/asm/bitops.h
+++ b/arch/mips/include/asm/bitops.h
@@ -79,8 +79,8 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
 		"	" __SC	"%0, %1					\n"
 		"	beqzl	%0, 1b					\n"
 		"	.set	mips0					\n"
-		: "=&r" (temp), "=" GCC_OFF12_ASM() (*m)
-		: "ir" (1UL << bit), GCC_OFF12_ASM() (*m));
+		: "=&r" (temp), "=" GCC_OFF_SMALL_ASM() (*m)
+		: "ir" (1UL << bit), GCC_OFF_SMALL_ASM() (*m));
 #ifdef CONFIG_CPU_MIPSR2
 	} else if (kernel_uses_llsc && __builtin_constant_p(bit)) {
 		do {
@@ -88,7 +88,7 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
 			"	" __LL "%0, %1		# set_bit	\n"
 			"	" __INS "%0, %3, %2, 1			\n"
 			"	" __SC "%0, %1				\n"
-			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
+			: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m)
 			: "ir" (bit), "r" (~0));
 		} while (unlikely(!temp));
 #endif /* CONFIG_CPU_MIPSR2 */
@@ -100,7 +100,7 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
 			"	or	%0, %2				\n"
 			"	" __SC	"%0, %1				\n"
 			"	.set	mips0				\n"
-			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
+			: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m)
 			: "ir" (1UL << bit));
 		} while (unlikely(!temp));
 	} else
@@ -131,7 +131,7 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
 		"	" __SC "%0, %1					\n"
 		"	beqzl	%0, 1b					\n"
 		"	.set	mips0					\n"
-		: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
+		: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m)
 		: "ir" (~(1UL << bit)));
 #ifdef CONFIG_CPU_MIPSR2
 	} else if (kernel_uses_llsc && __builtin_constant_p(bit)) {
@@ -140,7 +140,7 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
 			"	" __LL "%0, %1		# clear_bit	\n"
 			"	" __INS "%0, $0, %2, 1			\n"
 			"	" __SC "%0, %1				\n"
-			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
+			: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m)
 			: "ir" (bit));
 		} while (unlikely(!temp));
 #endif /* CONFIG_CPU_MIPSR2 */
@@ -152,7 +152,7 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
 			"	and	%0, %2				\n"
 			"	" __SC "%0, %1				\n"
 			"	.set	mips0				\n"
-			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
+			: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m)
 			: "ir" (~(1UL << bit)));
 		} while (unlikely(!temp));
 	} else
@@ -197,7 +197,7 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
 		"	" __SC	"%0, %1				\n"
 		"	beqzl	%0, 1b				\n"
 		"	.set	mips0				\n"
-		: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
+		: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m)
 		: "ir" (1UL << bit));
 	} else if (kernel_uses_llsc) {
 		unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
@@ -210,7 +210,7 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
 			"	xor	%0, %2				\n"
 			"	" __SC	"%0, %1				\n"
 			"	.set	mips0				\n"
-			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
+			: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m)
 			: "ir" (1UL << bit));
 		} while (unlikely(!temp));
 	} else
@@ -245,7 +245,7 @@ static inline int test_and_set_bit(unsigned long nr,
 		"	beqzl	%2, 1b					\n"
 		"	and	%2, %0, %3				\n"
 		"	.set	mips0					\n"
-		: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
+		: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m), "=&r" (res)
 		: "r" (1UL << bit)
 		: "memory");
 	} else if (kernel_uses_llsc) {
@@ -259,7 +259,7 @@ static inline int test_and_set_bit(unsigned long nr,
 			"	or	%2, %0, %3			\n"
 			"	" __SC	"%2, %1				\n"
 			"	.set	mips0				\n"
-			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
+			: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m), "=&r" (res)
 			: "r" (1UL << bit)
 			: "memory");
 		} while (unlikely(!res));
@@ -313,7 +313,7 @@ static inline int test_and_set_bit_lock(unsigned long nr,
 			"	or	%2, %0, %3			\n"
 			"	" __SC	"%2, %1				\n"
 			"	.set	mips0				\n"
-			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
+			: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m), "=&r" (res)
 			: "r" (1UL << bit)
 			: "memory");
 		} while (unlikely(!res));
@@ -355,7 +355,7 @@ static inline int test_and_clear_bit(unsigned long nr,
 		"	beqzl	%2, 1b					\n"
 		"	and	%2, %0, %3				\n"
 		"	.set	mips0					\n"
-		: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
+		: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m), "=&r" (res)
 		: "r" (1UL << bit)
 		: "memory");
 #ifdef CONFIG_CPU_MIPSR2
@@ -369,7 +369,7 @@ static inline int test_and_clear_bit(unsigned long nr,
 			"	" __EXT "%2, %0, %3, 1			\n"
 			"	" __INS "%0, $0, %3, 1			\n"
 			"	" __SC	"%0, %1				\n"
-			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
+			: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m), "=&r" (res)
 			: "ir" (bit)
 			: "memory");
 		} while (unlikely(!temp));
@@ -386,7 +386,7 @@ static inline int test_and_clear_bit(unsigned long nr,
 			"	xor	%2, %3				\n"
 			"	" __SC	"%2, %1				\n"
 			"	.set	mips0				\n"
-			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
+			: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m), "=&r" (res)
 			: "r" (1UL << bit)
 			: "memory");
 		} while (unlikely(!res));
@@ -428,7 +428,7 @@ static inline int test_and_change_bit(unsigned long nr,
 		"	beqzl	%2, 1b					\n"
 		"	and	%2, %0, %3				\n"
 		"	.set	mips0					\n"
-		: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
+		: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m), "=&r" (res)
 		: "r" (1UL << bit)
 		: "memory");
 	} else if (kernel_uses_llsc) {
@@ -442,7 +442,7 @@ static inline int test_and_change_bit(unsigned long nr,
 			"	xor	%2, %0, %3			\n"
 			"	" __SC	"\t%2, %1			\n"
 			"	.set	mips0				\n"
-			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
+			: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m), "=&r" (res)
 			: "r" (1UL << bit)
 			: "memory");
 		} while (unlikely(!res));
diff --git a/arch/mips/include/asm/cmpxchg.h b/arch/mips/include/asm/cmpxchg.h
index 28b1edf19501..68baa0cf521a 100644
--- a/arch/mips/include/asm/cmpxchg.h
+++ b/arch/mips/include/asm/cmpxchg.h
@@ -31,8 +31,8 @@ static inline unsigned long __xchg_u32(volatile int * m, unsigned int val)
 		"	sc	%2, %1					\n"
 		"	beqzl	%2, 1b					\n"
 		"	.set	mips0					\n"
-		: "=&r" (retval), "=" GCC_OFF12_ASM() (*m), "=&r" (dummy)
-		: GCC_OFF12_ASM() (*m), "Jr" (val)
+		: "=&r" (retval), "=" GCC_OFF_SMALL_ASM() (*m), "=&r" (dummy)
+		: GCC_OFF_SMALL_ASM() (*m), "Jr" (val)
 		: "memory");
 	} else if (kernel_uses_llsc) {
 		unsigned long dummy;
@@ -46,9 +46,9 @@ static inline unsigned long __xchg_u32(volatile int * m, unsigned int val)
 			"	.set	arch=r4000			\n"
 			"	sc	%2, %1				\n"
 			"	.set	mips0				\n"
-			: "=&r" (retval), "=" GCC_OFF12_ASM() (*m),
+			: "=&r" (retval), "=" GCC_OFF_SMALL_ASM() (*m),
 			  "=&r" (dummy)
-			: GCC_OFF12_ASM() (*m), "Jr" (val)
+			: GCC_OFF_SMALL_ASM() (*m), "Jr" (val)
 			: "memory");
 		} while (unlikely(!dummy));
 	} else {
@@ -82,8 +82,8 @@ static inline __u64 __xchg_u64(volatile __u64 * m, __u64 val)
 		"	scd	%2, %1					\n"
 		"	beqzl	%2, 1b					\n"
 		"	.set	mips0					\n"
-		: "=&r" (retval), "=" GCC_OFF12_ASM() (*m), "=&r" (dummy)
-		: GCC_OFF12_ASM() (*m), "Jr" (val)
+		: "=&r" (retval), "=" GCC_OFF_SMALL_ASM() (*m), "=&r" (dummy)
+		: GCC_OFF_SMALL_ASM() (*m), "Jr" (val)
 		: "memory");
 	} else if (kernel_uses_llsc) {
 		unsigned long dummy;
@@ -95,9 +95,9 @@ static inline __u64 __xchg_u64(volatile __u64 * m, __u64 val)
 			"	move	%2, %z4				\n"
 			"	scd	%2, %1				\n"
 			"	.set	mips0				\n"
-			: "=&r" (retval), "=" GCC_OFF12_ASM() (*m),
+			: "=&r" (retval), "=" GCC_OFF_SMALL_ASM() (*m),
 			  "=&r" (dummy)
-			: GCC_OFF12_ASM() (*m), "Jr" (val)
+			: GCC_OFF_SMALL_ASM() (*m), "Jr" (val)
 			: "memory");
 		} while (unlikely(!dummy));
 	} else {
@@ -158,8 +158,8 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
 		"	beqzl	$1, 1b				\n"	\
 		"2:						\n"	\
 		"	.set	pop				\n"	\
-		: "=&r" (__ret), "=" GCC_OFF12_ASM() (*m)		\
-		: GCC_OFF12_ASM() (*m), "Jr" (old), "Jr" (new)		\
+		: "=&r" (__ret), "=" GCC_OFF_SMALL_ASM() (*m)		\
+		: GCC_OFF_SMALL_ASM() (*m), "Jr" (old), "Jr" (new)		\
 		: "memory");						\
 	} else if (kernel_uses_llsc) {					\
 		__asm__ __volatile__(					\
@@ -175,8 +175,8 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
 		"	beqz	$1, 1b				\n"	\
 		"	.set	pop				\n"	\
 		"2:						\n"	\
-		: "=&r" (__ret), "=" GCC_OFF12_ASM() (*m)		\
-		: GCC_OFF12_ASM() (*m), "Jr" (old), "Jr" (new)		\
+		: "=&r" (__ret), "=" GCC_OFF_SMALL_ASM() (*m)		\
+		: GCC_OFF_SMALL_ASM() (*m), "Jr" (old), "Jr" (new)		\
 		: "memory");						\
 	} else {							\
 		unsigned long __flags;					\
diff --git a/arch/mips/include/asm/compiler.h b/arch/mips/include/asm/compiler.h
index c73815e0123a..90a317a08bd7 100644
--- a/arch/mips/include/asm/compiler.h
+++ b/arch/mips/include/asm/compiler.h
@@ -17,9 +17,9 @@
 #endif
 
 #ifndef CONFIG_CPU_MICROMIPS
-#define GCC_OFF12_ASM() "R"
+#define GCC_OFF_SMALL_ASM() "R"
 #elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
-#define GCC_OFF12_ASM() "ZC"
+#define GCC_OFF_SMALL_ASM() "ZC"
 #else
 #error "microMIPS compilation unsupported with GCC older than 4.9"
 #endif
diff --git a/arch/mips/include/asm/edac.h b/arch/mips/include/asm/edac.h
index ae6fedcb0060..94105d3f58f4 100644
--- a/arch/mips/include/asm/edac.h
+++ b/arch/mips/include/asm/edac.h
@@ -26,8 +26,8 @@ static inline void atomic_scrub(void *va, u32 size)
 		"	sc	%0, %1					\n"
 		"	beqz	%0, 1b					\n"
 		"	.set	mips0					\n"
-		: "=&r" (temp), "=" GCC_OFF12_ASM() (*virt_addr)
-		: GCC_OFF12_ASM() (*virt_addr));
+		: "=&r" (temp), "=" GCC_OFF_SMALL_ASM() (*virt_addr)
+		: GCC_OFF_SMALL_ASM() (*virt_addr));
 
 		virt_addr++;
 	}
diff --git a/arch/mips/include/asm/futex.h b/arch/mips/include/asm/futex.h
index ef9987a61d88..f666c0608c11 100644
--- a/arch/mips/include/asm/futex.h
+++ b/arch/mips/include/asm/futex.h
@@ -45,8 +45,8 @@
 		"	"__UA_ADDR "\t2b, 4b			\n"	\
 		"	.previous				\n"	\
 		: "=r" (ret), "=&r" (oldval),				\
-		  "=" GCC_OFF12_ASM() (*uaddr)				\
-		: "0" (0), GCC_OFF12_ASM() (*uaddr), "Jr" (oparg),	\
+		  "=" GCC_OFF_SMALL_ASM() (*uaddr)				\
+		: "0" (0), GCC_OFF_SMALL_ASM() (*uaddr), "Jr" (oparg),	\
 		  "i" (-EFAULT)						\
 		: "memory");						\
 	} else if (cpu_has_llsc) {					\
@@ -74,8 +74,8 @@
 		"	"__UA_ADDR "\t2b, 4b			\n"	\
 		"	.previous				\n"	\
 		: "=r" (ret), "=&r" (oldval),				\
-		  "=" GCC_OFF12_ASM() (*uaddr)				\
-		: "0" (0), GCC_OFF12_ASM() (*uaddr), "Jr" (oparg),	\
+		  "=" GCC_OFF_SMALL_ASM() (*uaddr)				\
+		: "0" (0), GCC_OFF_SMALL_ASM() (*uaddr), "Jr" (oparg),	\
 		  "i" (-EFAULT)						\
 		: "memory");						\
 	} else								\
@@ -174,8 +174,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), "=" GCC_OFF12_ASM() (*uaddr)
-		: GCC_OFF12_ASM() (*uaddr), "Jr" (oldval), "Jr" (newval),
+		: "+r" (ret), "=&r" (val), "=" GCC_OFF_SMALL_ASM() (*uaddr)
+		: GCC_OFF_SMALL_ASM() (*uaddr), "Jr" (oldval), "Jr" (newval),
 		  "i" (-EFAULT)
 		: "memory");
 	} else if (cpu_has_llsc) {
@@ -203,8 +203,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), "=" GCC_OFF12_ASM() (*uaddr)
-		: GCC_OFF12_ASM() (*uaddr), "Jr" (oldval), "Jr" (newval),
+		: "+r" (ret), "=&r" (val), "=" GCC_OFF_SMALL_ASM() (*uaddr)
+		: GCC_OFF_SMALL_ASM() (*uaddr), "Jr" (oldval), "Jr" (newval),
 		  "i" (-EFAULT)
 		: "memory");
 	} else
diff --git a/arch/mips/include/asm/mach-pmcs-msp71xx/msp_regops.h b/arch/mips/include/asm/mach-pmcs-msp71xx/msp_regops.h
index 2e54b4bff5cf..90dbe43c8d27 100644
--- a/arch/mips/include/asm/mach-pmcs-msp71xx/msp_regops.h
+++ b/arch/mips/include/asm/mach-pmcs-msp71xx/msp_regops.h
@@ -85,8 +85,8 @@ static inline void set_value_reg32(volatile u32 *const addr,
 	"	"__beqz"%0, 1b				\n"
 	"	nop					\n"
 	"	.set	pop				\n"
-	: "=&r" (temp), "=" GCC_OFF12_ASM() (*addr)
-	: "ir" (~mask), "ir" (value), GCC_OFF12_ASM() (*addr));
+	: "=&r" (temp), "=" GCC_OFF_SMALL_ASM() (*addr)
+	: "ir" (~mask), "ir" (value), GCC_OFF_SMALL_ASM() (*addr));
 }
 
 /*
@@ -106,8 +106,8 @@ static inline void set_reg32(volatile u32 *const addr,
 	"	"__beqz"%0, 1b				\n"
 	"	nop					\n"
 	"	.set	pop				\n"
-	: "=&r" (temp), "=" GCC_OFF12_ASM() (*addr)
-	: "ir" (mask), GCC_OFF12_ASM() (*addr));
+	: "=&r" (temp), "=" GCC_OFF_SMALL_ASM() (*addr)
+	: "ir" (mask), GCC_OFF_SMALL_ASM() (*addr));
 }
 
 /*
@@ -127,8 +127,8 @@ static inline void clear_reg32(volatile u32 *const addr,
 	"	"__beqz"%0, 1b				\n"
 	"	nop					\n"
 	"	.set	pop				\n"
-	: "=&r" (temp), "=" GCC_OFF12_ASM() (*addr)
-	: "ir" (~mask), GCC_OFF12_ASM() (*addr));
+	: "=&r" (temp), "=" GCC_OFF_SMALL_ASM() (*addr)
+	: "ir" (~mask), GCC_OFF_SMALL_ASM() (*addr));
 }
 
 /*
@@ -148,8 +148,8 @@ static inline void toggle_reg32(volatile u32 *const addr,
 	"	"__beqz"%0, 1b				\n"
 	"	nop					\n"
 	"	.set	pop				\n"
-	: "=&r" (temp), "=" GCC_OFF12_ASM() (*addr)
-	: "ir" (mask), GCC_OFF12_ASM() (*addr));
+	: "=&r" (temp), "=" GCC_OFF_SMALL_ASM() (*addr)
+	: "ir" (mask), GCC_OFF_SMALL_ASM() (*addr));
 }
 
 /*
@@ -220,8 +220,8 @@ static inline u32 blocking_read_reg32(volatile u32 *const addr)
 	"	.set	arch=r4000			\n"	\
 	"1:	ll	%0, %1	#custom_read_reg32	\n"	\
 	"	.set	pop				\n"	\
-	: "=r" (tmp), "=" GCC_OFF12_ASM() (*address)		\
-	: GCC_OFF12_ASM() (*address))
+	: "=r" (tmp), "=" GCC_OFF_SMALL_ASM() (*address)		\
+	: GCC_OFF_SMALL_ASM() (*address))
 
 #define custom_write_reg32(address, tmp)			\
 	__asm__ __volatile__(					\
@@ -231,7 +231,7 @@ static inline u32 blocking_read_reg32(volatile u32 *const addr)
 	"	"__beqz"%0, 1b				\n"	\
 	"	nop					\n"	\
 	"	.set	pop				\n"	\
-	: "=&r" (tmp), "=" GCC_OFF12_ASM() (*address)		\
-	: "0" (tmp), GCC_OFF12_ASM() (*address))
+	: "=&r" (tmp), "=" GCC_OFF_SMALL_ASM() (*address)		\
+	: "0" (tmp), GCC_OFF_SMALL_ASM() (*address))
 
 #endif	/* __ASM_REGOPS_H__ */
diff --git a/arch/mips/include/asm/octeon/cvmx-cmd-queue.h b/arch/mips/include/asm/octeon/cvmx-cmd-queue.h
index 75739c83f07e..8d05d9069823 100644
--- a/arch/mips/include/asm/octeon/cvmx-cmd-queue.h
+++ b/arch/mips/include/asm/octeon/cvmx-cmd-queue.h
@@ -275,7 +275,7 @@ static inline void __cvmx_cmd_queue_lock(cvmx_cmd_queue_id_t queue_id,
 		" lbu	%[ticket], %[now_serving]\n"
 		"4:\n"
 		".set pop\n" :
-		[ticket_ptr] "=" GCC_OFF12_ASM()(__cvmx_cmd_queue_state_ptr->ticket[__cvmx_cmd_queue_get_index(queue_id)]),
+		[ticket_ptr] "=" GCC_OFF_SMALL_ASM()(__cvmx_cmd_queue_state_ptr->ticket[__cvmx_cmd_queue_get_index(queue_id)]),
 		[now_serving] "=m"(qptr->now_serving), [ticket] "=r"(tmp),
 		[my_ticket] "=r"(my_ticket)
 	    );
diff --git a/arch/mips/include/asm/spinlock.h b/arch/mips/include/asm/spinlock.h
index c6d06d383ef9..b5238404c059 100644
--- a/arch/mips/include/asm/spinlock.h
+++ b/arch/mips/include/asm/spinlock.h
@@ -89,7 +89,7 @@ static inline void arch_spin_lock(arch_spinlock_t *lock)
 		"	 subu	%[ticket], %[ticket], 1			\n"
 		"	.previous					\n"
 		"	.set pop					\n"
-		: [ticket_ptr] "+" GCC_OFF12_ASM() (lock->lock),
+		: [ticket_ptr] "+" GCC_OFF_SMALL_ASM() (lock->lock),
 		  [serving_now_ptr] "+m" (lock->h.serving_now),
 		  [ticket] "=&r" (tmp),
 		  [my_ticket] "=&r" (my_ticket)
@@ -122,7 +122,7 @@ static inline void arch_spin_lock(arch_spinlock_t *lock)
 		"	 subu	%[ticket], %[ticket], 1			\n"
 		"	.previous					\n"
 		"	.set pop					\n"
-		: [ticket_ptr] "+" GCC_OFF12_ASM() (lock->lock),
+		: [ticket_ptr] "+" GCC_OFF_SMALL_ASM() (lock->lock),
 		  [serving_now_ptr] "+m" (lock->h.serving_now),
 		  [ticket] "=&r" (tmp),
 		  [my_ticket] "=&r" (my_ticket)
@@ -164,7 +164,7 @@ static inline unsigned int arch_spin_trylock(arch_spinlock_t *lock)
 		"	 li	%[ticket], 0				\n"
 		"	.previous					\n"
 		"	.set pop					\n"
-		: [ticket_ptr] "+" GCC_OFF12_ASM() (lock->lock),
+		: [ticket_ptr] "+" GCC_OFF_SMALL_ASM() (lock->lock),
 		  [ticket] "=&r" (tmp),
 		  [my_ticket] "=&r" (tmp2),
 		  [now_serving] "=&r" (tmp3)
@@ -188,7 +188,7 @@ static inline unsigned int arch_spin_trylock(arch_spinlock_t *lock)
 		"	 li	%[ticket], 0				\n"
 		"	.previous					\n"
 		"	.set pop					\n"
-		: [ticket_ptr] "+" GCC_OFF12_ASM() (lock->lock),
+		: [ticket_ptr] "+" GCC_OFF_SMALL_ASM() (lock->lock),
 		  [ticket] "=&r" (tmp),
 		  [my_ticket] "=&r" (tmp2),
 		  [now_serving] "=&r" (tmp3)
@@ -235,8 +235,8 @@ static inline void arch_read_lock(arch_rwlock_t *rw)
 		"	beqzl	%1, 1b					\n"
 		"	 nop						\n"
 		"	.set	reorder					\n"
-		: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
-		: GCC_OFF12_ASM() (rw->lock)
+		: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp)
+		: GCC_OFF_SMALL_ASM() (rw->lock)
 		: "memory");
 	} else {
 		do {
@@ -245,8 +245,8 @@ static inline void arch_read_lock(arch_rwlock_t *rw)
 			"	bltz	%1, 1b				\n"
 			"	 addu	%1, 1				\n"
 			"2:	sc	%1, %0				\n"
-			: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
-			: GCC_OFF12_ASM() (rw->lock)
+			: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp)
+			: GCC_OFF_SMALL_ASM() (rw->lock)
 			: "memory");
 		} while (unlikely(!tmp));
 	}
@@ -269,8 +269,8 @@ static inline void arch_read_unlock(arch_rwlock_t *rw)
 		"	sub	%1, 1					\n"
 		"	sc	%1, %0					\n"
 		"	beqzl	%1, 1b					\n"
-		: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
-		: GCC_OFF12_ASM() (rw->lock)
+		: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp)
+		: GCC_OFF_SMALL_ASM() (rw->lock)
 		: "memory");
 	} else {
 		do {
@@ -278,8 +278,8 @@ static inline void arch_read_unlock(arch_rwlock_t *rw)
 			"1:	ll	%1, %2	# arch_read_unlock	\n"
 			"	sub	%1, 1				\n"
 			"	sc	%1, %0				\n"
-			: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
-			: GCC_OFF12_ASM() (rw->lock)
+			: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp)
+			: GCC_OFF_SMALL_ASM() (rw->lock)
 			: "memory");
 		} while (unlikely(!tmp));
 	}
@@ -299,8 +299,8 @@ static inline void arch_write_lock(arch_rwlock_t *rw)
 		"	beqzl	%1, 1b					\n"
 		"	 nop						\n"
 		"	.set	reorder					\n"
-		: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
-		: GCC_OFF12_ASM() (rw->lock)
+		: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp)
+		: GCC_OFF_SMALL_ASM() (rw->lock)
 		: "memory");
 	} else {
 		do {
@@ -309,8 +309,8 @@ static inline void arch_write_lock(arch_rwlock_t *rw)
 			"	bnez	%1, 1b				\n"
 			"	 lui	%1, 0x8000			\n"
 			"2:	sc	%1, %0				\n"
-			: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
-			: GCC_OFF12_ASM() (rw->lock)
+			: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp)
+			: GCC_OFF_SMALL_ASM() (rw->lock)
 			: "memory");
 		} while (unlikely(!tmp));
 	}
@@ -349,8 +349,8 @@ static inline int arch_read_trylock(arch_rwlock_t *rw)
 		__WEAK_LLSC_MB
 		"	li	%2, 1					\n"
 		"2:							\n"
-		: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp), "=&r" (ret)
-		: GCC_OFF12_ASM() (rw->lock)
+		: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp), "=&r" (ret)
+		: GCC_OFF_SMALL_ASM() (rw->lock)
 		: "memory");
 	} else {
 		__asm__ __volatile__(
@@ -366,8 +366,8 @@ static inline int arch_read_trylock(arch_rwlock_t *rw)
 		__WEAK_LLSC_MB
 		"	li	%2, 1					\n"
 		"2:							\n"
-		: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp), "=&r" (ret)
-		: GCC_OFF12_ASM() (rw->lock)
+		: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp), "=&r" (ret)
+		: GCC_OFF_SMALL_ASM() (rw->lock)
 		: "memory");
 	}
 
@@ -393,8 +393,8 @@ static inline int arch_write_trylock(arch_rwlock_t *rw)
 		"	li	%2, 1					\n"
 		"	.set	reorder					\n"
 		"2:							\n"
-		: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp), "=&r" (ret)
-		: GCC_OFF12_ASM() (rw->lock)
+		: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp), "=&r" (ret)
+		: GCC_OFF_SMALL_ASM() (rw->lock)
 		: "memory");
 	} else {
 		do {
@@ -406,9 +406,9 @@ static inline int arch_write_trylock(arch_rwlock_t *rw)
 			"	sc	%1, %0				\n"
 			"	li	%2, 1				\n"
 			"2:						\n"
-			: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp),
+			: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp),
 			  "=&r" (ret)
-			: GCC_OFF12_ASM() (rw->lock)
+			: GCC_OFF_SMALL_ASM() (rw->lock)
 			: "memory");
 		} while (unlikely(!tmp));
 
-- 
2.2.2

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

* [PATCH] MIPS: asm: Rename GCC_OFF12_ASM to GCC_OFF_SMALL_ASM
@ 2015-01-26 13:39     ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-26 13:39 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Maciej W. Rozycki

The GCC_OFF12_ASM macro is used for 12-bit immediate constrains
but we will also use it for 9-bit constrains on MIPS R6 so we
rename it to something more appropriate.

Cc: Maciej W. Rozycki <macro@linux-mips.org>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
This patch will be part of MIPS R6 and it will be placed before
the following one
[PATCH RFC v2 19/70] MIPS: Use the new "ZC" constraint for MIPS R6
http://www.linux-mips.org/archives/linux-mips/2015-01/msg00211.html
---
 arch/mips/include/asm/atomic.h                     | 30 +++++++-------
 arch/mips/include/asm/bitops.h                     | 34 +++++++--------
 arch/mips/include/asm/cmpxchg.h                    | 24 +++++------
 arch/mips/include/asm/compiler.h                   |  4 +-
 arch/mips/include/asm/edac.h                       |  4 +-
 arch/mips/include/asm/futex.h                      | 16 ++++----
 .../include/asm/mach-pmcs-msp71xx/msp_regops.h     | 24 +++++------
 arch/mips/include/asm/octeon/cvmx-cmd-queue.h      |  2 +-
 arch/mips/include/asm/spinlock.h                   | 48 +++++++++++-----------
 9 files changed, 93 insertions(+), 93 deletions(-)

diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h
index 857da84cfc92..3a44c2f17e53 100644
--- a/arch/mips/include/asm/atomic.h
+++ b/arch/mips/include/asm/atomic.h
@@ -54,7 +54,7 @@ static __inline__ void atomic_##op(int i, atomic_t * v)			      \
 		"	sc	%0, %1					\n"   \
 		"	beqzl	%0, 1b					\n"   \
 		"	.set	mips0					\n"   \
-		: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter)	      \
+		: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (v->counter)	      \
 		: "Ir" (i));						      \
 	} else if (kernel_uses_llsc) {					      \
 		int temp;						      \
@@ -66,7 +66,7 @@ static __inline__ void atomic_##op(int i, atomic_t * v)			      \
 			"	" #asm_op " %0, %2			\n"   \
 			"	sc	%0, %1				\n"   \
 			"	.set	mips0				\n"   \
-			: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter)      \
+			: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (v->counter)      \
 			: "Ir" (i));					      \
 		} while (unlikely(!temp));				      \
 	} else {							      \
@@ -97,7 +97,7 @@ static __inline__ int atomic_##op##_return(int i, atomic_t * v)		      \
 		"	" #asm_op " %0, %1, %3				\n"   \
 		"	.set	mips0					\n"   \
 		: "=&r" (result), "=&r" (temp),				      \
-		  "+" GCC_OFF12_ASM() (v->counter)			      \
+		  "+" GCC_OFF_SMALL_ASM() (v->counter)			      \
 		: "Ir" (i));						      \
 	} else if (kernel_uses_llsc) {					      \
 		int temp;						      \
@@ -110,7 +110,7 @@ static __inline__ int atomic_##op##_return(int i, atomic_t * v)		      \
 			"	sc	%0, %2				\n"   \
 			"	.set	mips0				\n"   \
 			: "=&r" (result), "=&r" (temp),			      \
-			  "+" GCC_OFF12_ASM() (v->counter)		      \
+			  "+" GCC_OFF_SMALL_ASM() (v->counter)		      \
 			: "Ir" (i));					      \
 		} while (unlikely(!result));				      \
 									      \
@@ -171,8 +171,8 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
 		"1:							\n"
 		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp),
-		  "+" GCC_OFF12_ASM() (v->counter)
-		: "Ir" (i), GCC_OFF12_ASM() (v->counter)
+		  "+" GCC_OFF_SMALL_ASM() (v->counter)
+		: "Ir" (i), GCC_OFF_SMALL_ASM() (v->counter)
 		: "memory");
 	} else if (kernel_uses_llsc) {
 		int temp;
@@ -190,7 +190,7 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
 		"1:							\n"
 		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp),
-		  "+" GCC_OFF12_ASM() (v->counter)
+		  "+" GCC_OFF_SMALL_ASM() (v->counter)
 		: "Ir" (i));
 	} else {
 		unsigned long flags;
@@ -333,7 +333,7 @@ static __inline__ void atomic64_##op(long i, atomic64_t * v)		      \
 		"	scd	%0, %1					\n"   \
 		"	beqzl	%0, 1b					\n"   \
 		"	.set	mips0					\n"   \
-		: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter)	      \
+		: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (v->counter)	      \
 		: "Ir" (i));						      \
 	} else if (kernel_uses_llsc) {					      \
 		long temp;						      \
@@ -345,7 +345,7 @@ static __inline__ void atomic64_##op(long i, atomic64_t * v)		      \
 			"	" #asm_op " %0, %2			\n"   \
 			"	scd	%0, %1				\n"   \
 			"	.set	mips0				\n"   \
-			: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter)      \
+			: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (v->counter)      \
 			: "Ir" (i));					      \
 		} while (unlikely(!temp));				      \
 	} else {							      \
@@ -376,7 +376,7 @@ static __inline__ long atomic64_##op##_return(long i, atomic64_t * v)	      \
 		"	" #asm_op " %0, %1, %3				\n"   \
 		"	.set	mips0					\n"   \
 		: "=&r" (result), "=&r" (temp),				      \
-		  "+" GCC_OFF12_ASM() (v->counter)			      \
+		  "+" GCC_OFF_SMALL_ASM() (v->counter)			      \
 		: "Ir" (i));						      \
 	} else if (kernel_uses_llsc) {					      \
 		long temp;						      \
@@ -389,8 +389,8 @@ static __inline__ long atomic64_##op##_return(long i, atomic64_t * v)	      \
 			"	scd	%0, %2				\n"   \
 			"	.set	mips0				\n"   \
 			: "=&r" (result), "=&r" (temp),			      \
-			  "=" GCC_OFF12_ASM() (v->counter)		      \
-			: "Ir" (i), GCC_OFF12_ASM() (v->counter)	      \
+			  "=" GCC_OFF_SMALL_ASM() (v->counter)		      \
+			: "Ir" (i), GCC_OFF_SMALL_ASM() (v->counter)	      \
 			: "memory");					      \
 		} while (unlikely(!result));				      \
 									      \
@@ -452,8 +452,8 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
 		"1:							\n"
 		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp),
-		  "=" GCC_OFF12_ASM() (v->counter)
-		: "Ir" (i), GCC_OFF12_ASM() (v->counter)
+		  "=" GCC_OFF_SMALL_ASM() (v->counter)
+		: "Ir" (i), GCC_OFF_SMALL_ASM() (v->counter)
 		: "memory");
 	} else if (kernel_uses_llsc) {
 		long temp;
@@ -471,7 +471,7 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
 		"1:							\n"
 		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp),
-		  "+" GCC_OFF12_ASM() (v->counter)
+		  "+" GCC_OFF_SMALL_ASM() (v->counter)
 		: "Ir" (i));
 	} else {
 		unsigned long flags;
diff --git a/arch/mips/include/asm/bitops.h b/arch/mips/include/asm/bitops.h
index 6663bcca9d0c..6cc1f539c79a 100644
--- a/arch/mips/include/asm/bitops.h
+++ b/arch/mips/include/asm/bitops.h
@@ -79,8 +79,8 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
 		"	" __SC	"%0, %1					\n"
 		"	beqzl	%0, 1b					\n"
 		"	.set	mips0					\n"
-		: "=&r" (temp), "=" GCC_OFF12_ASM() (*m)
-		: "ir" (1UL << bit), GCC_OFF12_ASM() (*m));
+		: "=&r" (temp), "=" GCC_OFF_SMALL_ASM() (*m)
+		: "ir" (1UL << bit), GCC_OFF_SMALL_ASM() (*m));
 #ifdef CONFIG_CPU_MIPSR2
 	} else if (kernel_uses_llsc && __builtin_constant_p(bit)) {
 		do {
@@ -88,7 +88,7 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
 			"	" __LL "%0, %1		# set_bit	\n"
 			"	" __INS "%0, %3, %2, 1			\n"
 			"	" __SC "%0, %1				\n"
-			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
+			: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m)
 			: "ir" (bit), "r" (~0));
 		} while (unlikely(!temp));
 #endif /* CONFIG_CPU_MIPSR2 */
@@ -100,7 +100,7 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
 			"	or	%0, %2				\n"
 			"	" __SC	"%0, %1				\n"
 			"	.set	mips0				\n"
-			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
+			: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m)
 			: "ir" (1UL << bit));
 		} while (unlikely(!temp));
 	} else
@@ -131,7 +131,7 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
 		"	" __SC "%0, %1					\n"
 		"	beqzl	%0, 1b					\n"
 		"	.set	mips0					\n"
-		: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
+		: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m)
 		: "ir" (~(1UL << bit)));
 #ifdef CONFIG_CPU_MIPSR2
 	} else if (kernel_uses_llsc && __builtin_constant_p(bit)) {
@@ -140,7 +140,7 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
 			"	" __LL "%0, %1		# clear_bit	\n"
 			"	" __INS "%0, $0, %2, 1			\n"
 			"	" __SC "%0, %1				\n"
-			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
+			: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m)
 			: "ir" (bit));
 		} while (unlikely(!temp));
 #endif /* CONFIG_CPU_MIPSR2 */
@@ -152,7 +152,7 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
 			"	and	%0, %2				\n"
 			"	" __SC "%0, %1				\n"
 			"	.set	mips0				\n"
-			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
+			: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m)
 			: "ir" (~(1UL << bit)));
 		} while (unlikely(!temp));
 	} else
@@ -197,7 +197,7 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
 		"	" __SC	"%0, %1				\n"
 		"	beqzl	%0, 1b				\n"
 		"	.set	mips0				\n"
-		: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
+		: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m)
 		: "ir" (1UL << bit));
 	} else if (kernel_uses_llsc) {
 		unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
@@ -210,7 +210,7 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
 			"	xor	%0, %2				\n"
 			"	" __SC	"%0, %1				\n"
 			"	.set	mips0				\n"
-			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
+			: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m)
 			: "ir" (1UL << bit));
 		} while (unlikely(!temp));
 	} else
@@ -245,7 +245,7 @@ static inline int test_and_set_bit(unsigned long nr,
 		"	beqzl	%2, 1b					\n"
 		"	and	%2, %0, %3				\n"
 		"	.set	mips0					\n"
-		: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
+		: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m), "=&r" (res)
 		: "r" (1UL << bit)
 		: "memory");
 	} else if (kernel_uses_llsc) {
@@ -259,7 +259,7 @@ static inline int test_and_set_bit(unsigned long nr,
 			"	or	%2, %0, %3			\n"
 			"	" __SC	"%2, %1				\n"
 			"	.set	mips0				\n"
-			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
+			: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m), "=&r" (res)
 			: "r" (1UL << bit)
 			: "memory");
 		} while (unlikely(!res));
@@ -313,7 +313,7 @@ static inline int test_and_set_bit_lock(unsigned long nr,
 			"	or	%2, %0, %3			\n"
 			"	" __SC	"%2, %1				\n"
 			"	.set	mips0				\n"
-			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
+			: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m), "=&r" (res)
 			: "r" (1UL << bit)
 			: "memory");
 		} while (unlikely(!res));
@@ -355,7 +355,7 @@ static inline int test_and_clear_bit(unsigned long nr,
 		"	beqzl	%2, 1b					\n"
 		"	and	%2, %0, %3				\n"
 		"	.set	mips0					\n"
-		: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
+		: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m), "=&r" (res)
 		: "r" (1UL << bit)
 		: "memory");
 #ifdef CONFIG_CPU_MIPSR2
@@ -369,7 +369,7 @@ static inline int test_and_clear_bit(unsigned long nr,
 			"	" __EXT "%2, %0, %3, 1			\n"
 			"	" __INS "%0, $0, %3, 1			\n"
 			"	" __SC	"%0, %1				\n"
-			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
+			: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m), "=&r" (res)
 			: "ir" (bit)
 			: "memory");
 		} while (unlikely(!temp));
@@ -386,7 +386,7 @@ static inline int test_and_clear_bit(unsigned long nr,
 			"	xor	%2, %3				\n"
 			"	" __SC	"%2, %1				\n"
 			"	.set	mips0				\n"
-			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
+			: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m), "=&r" (res)
 			: "r" (1UL << bit)
 			: "memory");
 		} while (unlikely(!res));
@@ -428,7 +428,7 @@ static inline int test_and_change_bit(unsigned long nr,
 		"	beqzl	%2, 1b					\n"
 		"	and	%2, %0, %3				\n"
 		"	.set	mips0					\n"
-		: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
+		: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m), "=&r" (res)
 		: "r" (1UL << bit)
 		: "memory");
 	} else if (kernel_uses_llsc) {
@@ -442,7 +442,7 @@ static inline int test_and_change_bit(unsigned long nr,
 			"	xor	%2, %0, %3			\n"
 			"	" __SC	"\t%2, %1			\n"
 			"	.set	mips0				\n"
-			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
+			: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m), "=&r" (res)
 			: "r" (1UL << bit)
 			: "memory");
 		} while (unlikely(!res));
diff --git a/arch/mips/include/asm/cmpxchg.h b/arch/mips/include/asm/cmpxchg.h
index 28b1edf19501..68baa0cf521a 100644
--- a/arch/mips/include/asm/cmpxchg.h
+++ b/arch/mips/include/asm/cmpxchg.h
@@ -31,8 +31,8 @@ static inline unsigned long __xchg_u32(volatile int * m, unsigned int val)
 		"	sc	%2, %1					\n"
 		"	beqzl	%2, 1b					\n"
 		"	.set	mips0					\n"
-		: "=&r" (retval), "=" GCC_OFF12_ASM() (*m), "=&r" (dummy)
-		: GCC_OFF12_ASM() (*m), "Jr" (val)
+		: "=&r" (retval), "=" GCC_OFF_SMALL_ASM() (*m), "=&r" (dummy)
+		: GCC_OFF_SMALL_ASM() (*m), "Jr" (val)
 		: "memory");
 	} else if (kernel_uses_llsc) {
 		unsigned long dummy;
@@ -46,9 +46,9 @@ static inline unsigned long __xchg_u32(volatile int * m, unsigned int val)
 			"	.set	arch=r4000			\n"
 			"	sc	%2, %1				\n"
 			"	.set	mips0				\n"
-			: "=&r" (retval), "=" GCC_OFF12_ASM() (*m),
+			: "=&r" (retval), "=" GCC_OFF_SMALL_ASM() (*m),
 			  "=&r" (dummy)
-			: GCC_OFF12_ASM() (*m), "Jr" (val)
+			: GCC_OFF_SMALL_ASM() (*m), "Jr" (val)
 			: "memory");
 		} while (unlikely(!dummy));
 	} else {
@@ -82,8 +82,8 @@ static inline __u64 __xchg_u64(volatile __u64 * m, __u64 val)
 		"	scd	%2, %1					\n"
 		"	beqzl	%2, 1b					\n"
 		"	.set	mips0					\n"
-		: "=&r" (retval), "=" GCC_OFF12_ASM() (*m), "=&r" (dummy)
-		: GCC_OFF12_ASM() (*m), "Jr" (val)
+		: "=&r" (retval), "=" GCC_OFF_SMALL_ASM() (*m), "=&r" (dummy)
+		: GCC_OFF_SMALL_ASM() (*m), "Jr" (val)
 		: "memory");
 	} else if (kernel_uses_llsc) {
 		unsigned long dummy;
@@ -95,9 +95,9 @@ static inline __u64 __xchg_u64(volatile __u64 * m, __u64 val)
 			"	move	%2, %z4				\n"
 			"	scd	%2, %1				\n"
 			"	.set	mips0				\n"
-			: "=&r" (retval), "=" GCC_OFF12_ASM() (*m),
+			: "=&r" (retval), "=" GCC_OFF_SMALL_ASM() (*m),
 			  "=&r" (dummy)
-			: GCC_OFF12_ASM() (*m), "Jr" (val)
+			: GCC_OFF_SMALL_ASM() (*m), "Jr" (val)
 			: "memory");
 		} while (unlikely(!dummy));
 	} else {
@@ -158,8 +158,8 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
 		"	beqzl	$1, 1b				\n"	\
 		"2:						\n"	\
 		"	.set	pop				\n"	\
-		: "=&r" (__ret), "=" GCC_OFF12_ASM() (*m)		\
-		: GCC_OFF12_ASM() (*m), "Jr" (old), "Jr" (new)		\
+		: "=&r" (__ret), "=" GCC_OFF_SMALL_ASM() (*m)		\
+		: GCC_OFF_SMALL_ASM() (*m), "Jr" (old), "Jr" (new)		\
 		: "memory");						\
 	} else if (kernel_uses_llsc) {					\
 		__asm__ __volatile__(					\
@@ -175,8 +175,8 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
 		"	beqz	$1, 1b				\n"	\
 		"	.set	pop				\n"	\
 		"2:						\n"	\
-		: "=&r" (__ret), "=" GCC_OFF12_ASM() (*m)		\
-		: GCC_OFF12_ASM() (*m), "Jr" (old), "Jr" (new)		\
+		: "=&r" (__ret), "=" GCC_OFF_SMALL_ASM() (*m)		\
+		: GCC_OFF_SMALL_ASM() (*m), "Jr" (old), "Jr" (new)		\
 		: "memory");						\
 	} else {							\
 		unsigned long __flags;					\
diff --git a/arch/mips/include/asm/compiler.h b/arch/mips/include/asm/compiler.h
index c73815e0123a..90a317a08bd7 100644
--- a/arch/mips/include/asm/compiler.h
+++ b/arch/mips/include/asm/compiler.h
@@ -17,9 +17,9 @@
 #endif
 
 #ifndef CONFIG_CPU_MICROMIPS
-#define GCC_OFF12_ASM() "R"
+#define GCC_OFF_SMALL_ASM() "R"
 #elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
-#define GCC_OFF12_ASM() "ZC"
+#define GCC_OFF_SMALL_ASM() "ZC"
 #else
 #error "microMIPS compilation unsupported with GCC older than 4.9"
 #endif
diff --git a/arch/mips/include/asm/edac.h b/arch/mips/include/asm/edac.h
index ae6fedcb0060..94105d3f58f4 100644
--- a/arch/mips/include/asm/edac.h
+++ b/arch/mips/include/asm/edac.h
@@ -26,8 +26,8 @@ static inline void atomic_scrub(void *va, u32 size)
 		"	sc	%0, %1					\n"
 		"	beqz	%0, 1b					\n"
 		"	.set	mips0					\n"
-		: "=&r" (temp), "=" GCC_OFF12_ASM() (*virt_addr)
-		: GCC_OFF12_ASM() (*virt_addr));
+		: "=&r" (temp), "=" GCC_OFF_SMALL_ASM() (*virt_addr)
+		: GCC_OFF_SMALL_ASM() (*virt_addr));
 
 		virt_addr++;
 	}
diff --git a/arch/mips/include/asm/futex.h b/arch/mips/include/asm/futex.h
index ef9987a61d88..f666c0608c11 100644
--- a/arch/mips/include/asm/futex.h
+++ b/arch/mips/include/asm/futex.h
@@ -45,8 +45,8 @@
 		"	"__UA_ADDR "\t2b, 4b			\n"	\
 		"	.previous				\n"	\
 		: "=r" (ret), "=&r" (oldval),				\
-		  "=" GCC_OFF12_ASM() (*uaddr)				\
-		: "0" (0), GCC_OFF12_ASM() (*uaddr), "Jr" (oparg),	\
+		  "=" GCC_OFF_SMALL_ASM() (*uaddr)				\
+		: "0" (0), GCC_OFF_SMALL_ASM() (*uaddr), "Jr" (oparg),	\
 		  "i" (-EFAULT)						\
 		: "memory");						\
 	} else if (cpu_has_llsc) {					\
@@ -74,8 +74,8 @@
 		"	"__UA_ADDR "\t2b, 4b			\n"	\
 		"	.previous				\n"	\
 		: "=r" (ret), "=&r" (oldval),				\
-		  "=" GCC_OFF12_ASM() (*uaddr)				\
-		: "0" (0), GCC_OFF12_ASM() (*uaddr), "Jr" (oparg),	\
+		  "=" GCC_OFF_SMALL_ASM() (*uaddr)				\
+		: "0" (0), GCC_OFF_SMALL_ASM() (*uaddr), "Jr" (oparg),	\
 		  "i" (-EFAULT)						\
 		: "memory");						\
 	} else								\
@@ -174,8 +174,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), "=" GCC_OFF12_ASM() (*uaddr)
-		: GCC_OFF12_ASM() (*uaddr), "Jr" (oldval), "Jr" (newval),
+		: "+r" (ret), "=&r" (val), "=" GCC_OFF_SMALL_ASM() (*uaddr)
+		: GCC_OFF_SMALL_ASM() (*uaddr), "Jr" (oldval), "Jr" (newval),
 		  "i" (-EFAULT)
 		: "memory");
 	} else if (cpu_has_llsc) {
@@ -203,8 +203,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), "=" GCC_OFF12_ASM() (*uaddr)
-		: GCC_OFF12_ASM() (*uaddr), "Jr" (oldval), "Jr" (newval),
+		: "+r" (ret), "=&r" (val), "=" GCC_OFF_SMALL_ASM() (*uaddr)
+		: GCC_OFF_SMALL_ASM() (*uaddr), "Jr" (oldval), "Jr" (newval),
 		  "i" (-EFAULT)
 		: "memory");
 	} else
diff --git a/arch/mips/include/asm/mach-pmcs-msp71xx/msp_regops.h b/arch/mips/include/asm/mach-pmcs-msp71xx/msp_regops.h
index 2e54b4bff5cf..90dbe43c8d27 100644
--- a/arch/mips/include/asm/mach-pmcs-msp71xx/msp_regops.h
+++ b/arch/mips/include/asm/mach-pmcs-msp71xx/msp_regops.h
@@ -85,8 +85,8 @@ static inline void set_value_reg32(volatile u32 *const addr,
 	"	"__beqz"%0, 1b				\n"
 	"	nop					\n"
 	"	.set	pop				\n"
-	: "=&r" (temp), "=" GCC_OFF12_ASM() (*addr)
-	: "ir" (~mask), "ir" (value), GCC_OFF12_ASM() (*addr));
+	: "=&r" (temp), "=" GCC_OFF_SMALL_ASM() (*addr)
+	: "ir" (~mask), "ir" (value), GCC_OFF_SMALL_ASM() (*addr));
 }
 
 /*
@@ -106,8 +106,8 @@ static inline void set_reg32(volatile u32 *const addr,
 	"	"__beqz"%0, 1b				\n"
 	"	nop					\n"
 	"	.set	pop				\n"
-	: "=&r" (temp), "=" GCC_OFF12_ASM() (*addr)
-	: "ir" (mask), GCC_OFF12_ASM() (*addr));
+	: "=&r" (temp), "=" GCC_OFF_SMALL_ASM() (*addr)
+	: "ir" (mask), GCC_OFF_SMALL_ASM() (*addr));
 }
 
 /*
@@ -127,8 +127,8 @@ static inline void clear_reg32(volatile u32 *const addr,
 	"	"__beqz"%0, 1b				\n"
 	"	nop					\n"
 	"	.set	pop				\n"
-	: "=&r" (temp), "=" GCC_OFF12_ASM() (*addr)
-	: "ir" (~mask), GCC_OFF12_ASM() (*addr));
+	: "=&r" (temp), "=" GCC_OFF_SMALL_ASM() (*addr)
+	: "ir" (~mask), GCC_OFF_SMALL_ASM() (*addr));
 }
 
 /*
@@ -148,8 +148,8 @@ static inline void toggle_reg32(volatile u32 *const addr,
 	"	"__beqz"%0, 1b				\n"
 	"	nop					\n"
 	"	.set	pop				\n"
-	: "=&r" (temp), "=" GCC_OFF12_ASM() (*addr)
-	: "ir" (mask), GCC_OFF12_ASM() (*addr));
+	: "=&r" (temp), "=" GCC_OFF_SMALL_ASM() (*addr)
+	: "ir" (mask), GCC_OFF_SMALL_ASM() (*addr));
 }
 
 /*
@@ -220,8 +220,8 @@ static inline u32 blocking_read_reg32(volatile u32 *const addr)
 	"	.set	arch=r4000			\n"	\
 	"1:	ll	%0, %1	#custom_read_reg32	\n"	\
 	"	.set	pop				\n"	\
-	: "=r" (tmp), "=" GCC_OFF12_ASM() (*address)		\
-	: GCC_OFF12_ASM() (*address))
+	: "=r" (tmp), "=" GCC_OFF_SMALL_ASM() (*address)		\
+	: GCC_OFF_SMALL_ASM() (*address))
 
 #define custom_write_reg32(address, tmp)			\
 	__asm__ __volatile__(					\
@@ -231,7 +231,7 @@ static inline u32 blocking_read_reg32(volatile u32 *const addr)
 	"	"__beqz"%0, 1b				\n"	\
 	"	nop					\n"	\
 	"	.set	pop				\n"	\
-	: "=&r" (tmp), "=" GCC_OFF12_ASM() (*address)		\
-	: "0" (tmp), GCC_OFF12_ASM() (*address))
+	: "=&r" (tmp), "=" GCC_OFF_SMALL_ASM() (*address)		\
+	: "0" (tmp), GCC_OFF_SMALL_ASM() (*address))
 
 #endif	/* __ASM_REGOPS_H__ */
diff --git a/arch/mips/include/asm/octeon/cvmx-cmd-queue.h b/arch/mips/include/asm/octeon/cvmx-cmd-queue.h
index 75739c83f07e..8d05d9069823 100644
--- a/arch/mips/include/asm/octeon/cvmx-cmd-queue.h
+++ b/arch/mips/include/asm/octeon/cvmx-cmd-queue.h
@@ -275,7 +275,7 @@ static inline void __cvmx_cmd_queue_lock(cvmx_cmd_queue_id_t queue_id,
 		" lbu	%[ticket], %[now_serving]\n"
 		"4:\n"
 		".set pop\n" :
-		[ticket_ptr] "=" GCC_OFF12_ASM()(__cvmx_cmd_queue_state_ptr->ticket[__cvmx_cmd_queue_get_index(queue_id)]),
+		[ticket_ptr] "=" GCC_OFF_SMALL_ASM()(__cvmx_cmd_queue_state_ptr->ticket[__cvmx_cmd_queue_get_index(queue_id)]),
 		[now_serving] "=m"(qptr->now_serving), [ticket] "=r"(tmp),
 		[my_ticket] "=r"(my_ticket)
 	    );
diff --git a/arch/mips/include/asm/spinlock.h b/arch/mips/include/asm/spinlock.h
index c6d06d383ef9..b5238404c059 100644
--- a/arch/mips/include/asm/spinlock.h
+++ b/arch/mips/include/asm/spinlock.h
@@ -89,7 +89,7 @@ static inline void arch_spin_lock(arch_spinlock_t *lock)
 		"	 subu	%[ticket], %[ticket], 1			\n"
 		"	.previous					\n"
 		"	.set pop					\n"
-		: [ticket_ptr] "+" GCC_OFF12_ASM() (lock->lock),
+		: [ticket_ptr] "+" GCC_OFF_SMALL_ASM() (lock->lock),
 		  [serving_now_ptr] "+m" (lock->h.serving_now),
 		  [ticket] "=&r" (tmp),
 		  [my_ticket] "=&r" (my_ticket)
@@ -122,7 +122,7 @@ static inline void arch_spin_lock(arch_spinlock_t *lock)
 		"	 subu	%[ticket], %[ticket], 1			\n"
 		"	.previous					\n"
 		"	.set pop					\n"
-		: [ticket_ptr] "+" GCC_OFF12_ASM() (lock->lock),
+		: [ticket_ptr] "+" GCC_OFF_SMALL_ASM() (lock->lock),
 		  [serving_now_ptr] "+m" (lock->h.serving_now),
 		  [ticket] "=&r" (tmp),
 		  [my_ticket] "=&r" (my_ticket)
@@ -164,7 +164,7 @@ static inline unsigned int arch_spin_trylock(arch_spinlock_t *lock)
 		"	 li	%[ticket], 0				\n"
 		"	.previous					\n"
 		"	.set pop					\n"
-		: [ticket_ptr] "+" GCC_OFF12_ASM() (lock->lock),
+		: [ticket_ptr] "+" GCC_OFF_SMALL_ASM() (lock->lock),
 		  [ticket] "=&r" (tmp),
 		  [my_ticket] "=&r" (tmp2),
 		  [now_serving] "=&r" (tmp3)
@@ -188,7 +188,7 @@ static inline unsigned int arch_spin_trylock(arch_spinlock_t *lock)
 		"	 li	%[ticket], 0				\n"
 		"	.previous					\n"
 		"	.set pop					\n"
-		: [ticket_ptr] "+" GCC_OFF12_ASM() (lock->lock),
+		: [ticket_ptr] "+" GCC_OFF_SMALL_ASM() (lock->lock),
 		  [ticket] "=&r" (tmp),
 		  [my_ticket] "=&r" (tmp2),
 		  [now_serving] "=&r" (tmp3)
@@ -235,8 +235,8 @@ static inline void arch_read_lock(arch_rwlock_t *rw)
 		"	beqzl	%1, 1b					\n"
 		"	 nop						\n"
 		"	.set	reorder					\n"
-		: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
-		: GCC_OFF12_ASM() (rw->lock)
+		: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp)
+		: GCC_OFF_SMALL_ASM() (rw->lock)
 		: "memory");
 	} else {
 		do {
@@ -245,8 +245,8 @@ static inline void arch_read_lock(arch_rwlock_t *rw)
 			"	bltz	%1, 1b				\n"
 			"	 addu	%1, 1				\n"
 			"2:	sc	%1, %0				\n"
-			: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
-			: GCC_OFF12_ASM() (rw->lock)
+			: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp)
+			: GCC_OFF_SMALL_ASM() (rw->lock)
 			: "memory");
 		} while (unlikely(!tmp));
 	}
@@ -269,8 +269,8 @@ static inline void arch_read_unlock(arch_rwlock_t *rw)
 		"	sub	%1, 1					\n"
 		"	sc	%1, %0					\n"
 		"	beqzl	%1, 1b					\n"
-		: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
-		: GCC_OFF12_ASM() (rw->lock)
+		: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp)
+		: GCC_OFF_SMALL_ASM() (rw->lock)
 		: "memory");
 	} else {
 		do {
@@ -278,8 +278,8 @@ static inline void arch_read_unlock(arch_rwlock_t *rw)
 			"1:	ll	%1, %2	# arch_read_unlock	\n"
 			"	sub	%1, 1				\n"
 			"	sc	%1, %0				\n"
-			: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
-			: GCC_OFF12_ASM() (rw->lock)
+			: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp)
+			: GCC_OFF_SMALL_ASM() (rw->lock)
 			: "memory");
 		} while (unlikely(!tmp));
 	}
@@ -299,8 +299,8 @@ static inline void arch_write_lock(arch_rwlock_t *rw)
 		"	beqzl	%1, 1b					\n"
 		"	 nop						\n"
 		"	.set	reorder					\n"
-		: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
-		: GCC_OFF12_ASM() (rw->lock)
+		: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp)
+		: GCC_OFF_SMALL_ASM() (rw->lock)
 		: "memory");
 	} else {
 		do {
@@ -309,8 +309,8 @@ static inline void arch_write_lock(arch_rwlock_t *rw)
 			"	bnez	%1, 1b				\n"
 			"	 lui	%1, 0x8000			\n"
 			"2:	sc	%1, %0				\n"
-			: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
-			: GCC_OFF12_ASM() (rw->lock)
+			: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp)
+			: GCC_OFF_SMALL_ASM() (rw->lock)
 			: "memory");
 		} while (unlikely(!tmp));
 	}
@@ -349,8 +349,8 @@ static inline int arch_read_trylock(arch_rwlock_t *rw)
 		__WEAK_LLSC_MB
 		"	li	%2, 1					\n"
 		"2:							\n"
-		: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp), "=&r" (ret)
-		: GCC_OFF12_ASM() (rw->lock)
+		: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp), "=&r" (ret)
+		: GCC_OFF_SMALL_ASM() (rw->lock)
 		: "memory");
 	} else {
 		__asm__ __volatile__(
@@ -366,8 +366,8 @@ static inline int arch_read_trylock(arch_rwlock_t *rw)
 		__WEAK_LLSC_MB
 		"	li	%2, 1					\n"
 		"2:							\n"
-		: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp), "=&r" (ret)
-		: GCC_OFF12_ASM() (rw->lock)
+		: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp), "=&r" (ret)
+		: GCC_OFF_SMALL_ASM() (rw->lock)
 		: "memory");
 	}
 
@@ -393,8 +393,8 @@ static inline int arch_write_trylock(arch_rwlock_t *rw)
 		"	li	%2, 1					\n"
 		"	.set	reorder					\n"
 		"2:							\n"
-		: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp), "=&r" (ret)
-		: GCC_OFF12_ASM() (rw->lock)
+		: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp), "=&r" (ret)
+		: GCC_OFF_SMALL_ASM() (rw->lock)
 		: "memory");
 	} else {
 		do {
@@ -406,9 +406,9 @@ static inline int arch_write_trylock(arch_rwlock_t *rw)
 			"	sc	%1, %0				\n"
 			"	li	%2, 1				\n"
 			"2:						\n"
-			: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp),
+			: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp),
 			  "=&r" (ret)
-			: GCC_OFF12_ASM() (rw->lock)
+			: GCC_OFF_SMALL_ASM() (rw->lock)
 			: "memory");
 		} while (unlikely(!tmp));
 
-- 
2.2.2

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

* RE: [PATCH RFC v2 68/70] MIPS: kernel: elf: Improve the overall ABI and FPU mode checks
  2015-01-16 10:49   ` Markos Chandras
                     ` (2 preceding siblings ...)
  (?)
@ 2015-01-29 21:51   ` Matthew Fortune
  2015-02-02 16:13       ` Markos Chandras
  2015-02-26 11:11       ` Markos Chandras
  -1 siblings, 2 replies; 262+ messages in thread
From: Matthew Fortune @ 2015-01-29 21:51 UTC (permalink / raw)
  To: Markos Chandras, linux-mips; +Cc: Paul Burton, Leonid Yegoshin

> +static inline unsigned get_fp_abi(struct elf32_hdr *ehdr, int in_abi)
>  {
>  	/* If the ABI requirement is provided, simply return that */
> -	if (in_abi != -1)
> +	if (in_abi != MIPS_ABI_FP_UNKNOWN)
>  		return in_abi;
> 
>  	/* If the EF_MIPS_FP64 flag was set, return MIPS_ABI_FP_64 */
>  	if (ehdr->e_flags & EF_MIPS_FP64)
> -		return MIPS_ABI_FP_64;
> +		return MIPS_ABI_FP_OLD_64;

Leonid spotting a bug here, the ehdr given to this function can be either elf32
or elf64.

I suggest finding a way to move this check for EF_MIPS_FP64 into arch_elf_pt_proc
where the elf class is known.  The fpabi can be set to MIPS_ABI_FP_OLD_64 if this
holds true and then overridden if a MIPS_ABIFLAGS segment is found so would go
as indicated below:

+	/* Lets see if this is an O32 ELF */
+	if (ehdr32->e_ident[EI_CLASS] == ELFCLASS32) {
+		/* FR = 1 for N32 */
+		if (ehdr32->e_flags & EF_MIPS_ABI2)
+			state->overall_fp_mode = FP_FR1;
+		else
+			/* Set a good default FPU mode for O32*/
+			state->overall_fp_mode = cpu_has_mips_r6 ?
+				FP_FRE : FP_FR0;

<<here>>

+		if (phdr32->p_type != PT_MIPS_ABIFLAGS)
+			return 0;

Thanks,
Matthew

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

* Re: [PATCH RFC v2 67/70] MIPS: kernel: process: Do not allow FR=0 on MIPS R6
@ 2015-01-29 23:13     ` Paul Burton
  0 siblings, 0 replies; 262+ messages in thread
From: Paul Burton @ 2015-01-29 23:13 UTC (permalink / raw)
  To: Markos Chandras; +Cc: linux-mips, Matthew Fortune

On Fri, Jan 16, 2015 at 10:49:46AM +0000, Markos Chandras wrote:
> A prctl() call to set FR=0 for MIPS R6 should not be allowed
> since FR=1 is the only option for R6 cores.
> 
> Cc: Paul Burton <paul.burton@imgtec.com>
> Cc: Matthew Fortune <matthew.fortune@imgtec.com>
> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
> ---
>  arch/mips/include/asm/fpu.h | 3 ++-
>  arch/mips/kernel/process.c  | 4 ++++
>  2 files changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/mips/include/asm/fpu.h b/arch/mips/include/asm/fpu.h
> index 994d21939676..b96d9d327626 100644
> --- a/arch/mips/include/asm/fpu.h
> +++ b/arch/mips/include/asm/fpu.h
> @@ -68,7 +68,8 @@ static inline int __enable_fpu(enum fpu_mode mode)
>  		goto fr_common;
>  
>  	case FPU_64BIT:
> -#if !(defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_64BIT))
> +#if !(defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_CPU_MIPS32_R6) \
> +      || defined(CONFIG_64BIT))

Hi Markos,

This change really seems like a separate one, since it has nothing to do
with the prctl or disallowing FR=1, but rather with allowing FR=1 on r6.

Thanks,
    Paul

>  		/* we only have a 32-bit FPU */
>  		return SIGFPE;
>  #endif
> diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
> index b732c0ce2e56..41ebd5d0ac30 100644
> --- a/arch/mips/kernel/process.c
> +++ b/arch/mips/kernel/process.c
> @@ -581,6 +581,10 @@ int mips_set_process_fp_mode(struct task_struct *task, unsigned int value)
>  	if ((value & PR_FP_MODE_FRE) && !cpu_has_fre)
>  		return -EOPNOTSUPP;
>  
> +	/* FR = 0 not supported in MIPS R6 */
> +	if (!(value & PR_FP_MODE_FR) && cpu_has_fpu && cpu_has_mips_r6)
> +		return -EOPNOTSUPP;
> +
>  	/* Save FP & vector context, then disable FPU & MSA */
>  	if (task->signal == current->signal)
>  		lose_fpu(1);
> -- 
> 2.2.1
> 

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

* Re: [PATCH RFC v2 67/70] MIPS: kernel: process: Do not allow FR=0 on MIPS R6
@ 2015-01-29 23:13     ` Paul Burton
  0 siblings, 0 replies; 262+ messages in thread
From: Paul Burton @ 2015-01-29 23:13 UTC (permalink / raw)
  To: Markos Chandras; +Cc: linux-mips, Matthew Fortune

On Fri, Jan 16, 2015 at 10:49:46AM +0000, Markos Chandras wrote:
> A prctl() call to set FR=0 for MIPS R6 should not be allowed
> since FR=1 is the only option for R6 cores.
> 
> Cc: Paul Burton <paul.burton@imgtec.com>
> Cc: Matthew Fortune <matthew.fortune@imgtec.com>
> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
> ---
>  arch/mips/include/asm/fpu.h | 3 ++-
>  arch/mips/kernel/process.c  | 4 ++++
>  2 files changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/mips/include/asm/fpu.h b/arch/mips/include/asm/fpu.h
> index 994d21939676..b96d9d327626 100644
> --- a/arch/mips/include/asm/fpu.h
> +++ b/arch/mips/include/asm/fpu.h
> @@ -68,7 +68,8 @@ static inline int __enable_fpu(enum fpu_mode mode)
>  		goto fr_common;
>  
>  	case FPU_64BIT:
> -#if !(defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_64BIT))
> +#if !(defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_CPU_MIPS32_R6) \
> +      || defined(CONFIG_64BIT))

Hi Markos,

This change really seems like a separate one, since it has nothing to do
with the prctl or disallowing FR=1, but rather with allowing FR=1 on r6.

Thanks,
    Paul

>  		/* we only have a 32-bit FPU */
>  		return SIGFPE;
>  #endif
> diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
> index b732c0ce2e56..41ebd5d0ac30 100644
> --- a/arch/mips/kernel/process.c
> +++ b/arch/mips/kernel/process.c
> @@ -581,6 +581,10 @@ int mips_set_process_fp_mode(struct task_struct *task, unsigned int value)
>  	if ((value & PR_FP_MODE_FRE) && !cpu_has_fre)
>  		return -EOPNOTSUPP;
>  
> +	/* FR = 0 not supported in MIPS R6 */
> +	if (!(value & PR_FP_MODE_FR) && cpu_has_fpu && cpu_has_mips_r6)
> +		return -EOPNOTSUPP;
> +
>  	/* Save FP & vector context, then disable FPU & MSA */
>  	if (task->signal == current->signal)
>  		lose_fpu(1);
> -- 
> 2.2.1
> 

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

* Re: [PATCH RFC v2 68/70] MIPS: kernel: elf: Improve the overall ABI and FPU mode checks
  2015-01-19 12:17     ` Markos Chandras
@ 2015-01-29 23:22       ` Paul Burton
  2015-01-30 10:23         ` Markos Chandras
  0 siblings, 1 reply; 262+ messages in thread
From: Paul Burton @ 2015-01-29 23:22 UTC (permalink / raw)
  To: Markos Chandras
  Cc: Matthew Fortune, linux-mips, Maciej W. Rozycki (macro@linux-mips.org)

On Mon, Jan 19, 2015 at 12:17:27PM +0000, Markos Chandras wrote:
> > Is it worth updating the CONFIG_MIPS_O32_FP64_SUPPORT option to no longer
> > be experimental and also default on? This option could then guard the new
> > logic from this patch as a safety measure. Once the code has been proven
> > I'd suggest removing the option and making the code unconditional.
> 
> Paul?
> 
> Initially thought of having 32-bit R6 select this symbol but then I
> dropped it. But maybe it make sense now?

Personally I'd rather leave it default to off until it gets through a
release cycle without any complaints. Perhaps having r6 select it, or
"default y if CONFIG_CPU_MIPSR6" would make sense though, given that you
won't be able to use the FPU for r6 userland without it.

Paul

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

* Re: [PATCH RFC v2 67/70] MIPS: kernel: process: Do not allow FR=0 on MIPS R6
@ 2015-01-30 10:18       ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-30 10:18 UTC (permalink / raw)
  To: Paul Burton; +Cc: linux-mips, Matthew Fortune

On 01/29/2015 11:13 PM, Paul Burton wrote:
> On Fri, Jan 16, 2015 at 10:49:46AM +0000, Markos Chandras wrote:
>> A prctl() call to set FR=0 for MIPS R6 should not be allowed
>> since FR=1 is the only option for R6 cores.
>>
>> Cc: Paul Burton <paul.burton@imgtec.com>
>> Cc: Matthew Fortune <matthew.fortune@imgtec.com>
>> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
>> ---
>>  arch/mips/include/asm/fpu.h | 3 ++-
>>  arch/mips/kernel/process.c  | 4 ++++
>>  2 files changed, 6 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/mips/include/asm/fpu.h b/arch/mips/include/asm/fpu.h
>> index 994d21939676..b96d9d327626 100644
>> --- a/arch/mips/include/asm/fpu.h
>> +++ b/arch/mips/include/asm/fpu.h
>> @@ -68,7 +68,8 @@ static inline int __enable_fpu(enum fpu_mode mode)
>>  		goto fr_common;
>>  
>>  	case FPU_64BIT:
>> -#if !(defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_64BIT))
>> +#if !(defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_CPU_MIPS32_R6) \
>> +      || defined(CONFIG_64BIT))
> 
> Hi Markos,
> 
> This change really seems like a separate one, since it has nothing to do
> with the prctl or disallowing FR=1, but rather with allowing FR=1 on r6.
> 
> Thanks,
>     Paul

Thanks I will move it to a separate patch

-- 
markos

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

* Re: [PATCH RFC v2 67/70] MIPS: kernel: process: Do not allow FR=0 on MIPS R6
@ 2015-01-30 10:18       ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-30 10:18 UTC (permalink / raw)
  To: Paul Burton; +Cc: linux-mips, Matthew Fortune

On 01/29/2015 11:13 PM, Paul Burton wrote:
> On Fri, Jan 16, 2015 at 10:49:46AM +0000, Markos Chandras wrote:
>> A prctl() call to set FR=0 for MIPS R6 should not be allowed
>> since FR=1 is the only option for R6 cores.
>>
>> Cc: Paul Burton <paul.burton@imgtec.com>
>> Cc: Matthew Fortune <matthew.fortune@imgtec.com>
>> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
>> ---
>>  arch/mips/include/asm/fpu.h | 3 ++-
>>  arch/mips/kernel/process.c  | 4 ++++
>>  2 files changed, 6 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/mips/include/asm/fpu.h b/arch/mips/include/asm/fpu.h
>> index 994d21939676..b96d9d327626 100644
>> --- a/arch/mips/include/asm/fpu.h
>> +++ b/arch/mips/include/asm/fpu.h
>> @@ -68,7 +68,8 @@ static inline int __enable_fpu(enum fpu_mode mode)
>>  		goto fr_common;
>>  
>>  	case FPU_64BIT:
>> -#if !(defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_64BIT))
>> +#if !(defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_CPU_MIPS32_R6) \
>> +      || defined(CONFIG_64BIT))
> 
> Hi Markos,
> 
> This change really seems like a separate one, since it has nothing to do
> with the prctl or disallowing FR=1, but rather with allowing FR=1 on r6.
> 
> Thanks,
>     Paul

Thanks I will move it to a separate patch

-- 
markos

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

* Re: [PATCH RFC v2 68/70] MIPS: kernel: elf: Improve the overall ABI and FPU mode checks
  2015-01-29 23:22       ` Paul Burton
@ 2015-01-30 10:23         ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-01-30 10:23 UTC (permalink / raw)
  To: Paul Burton
  Cc: Matthew Fortune, linux-mips, Maciej W. Rozycki (macro@linux-mips.org)

On 01/29/2015 11:22 PM, Paul Burton wrote:
> On Mon, Jan 19, 2015 at 12:17:27PM +0000, Markos Chandras wrote:
>>> Is it worth updating the CONFIG_MIPS_O32_FP64_SUPPORT option to no longer
>>> be experimental and also default on? This option could then guard the new
>>> logic from this patch as a safety measure. Once the code has been proven
>>> I'd suggest removing the option and making the code unconditional.
>>
>> Paul?
>>
>> Initially thought of having 32-bit R6 select this symbol but then I
>> dropped it. But maybe it make sense now?
> 
> Personally I'd rather leave it default to off until it gets through a
> release cycle without any complaints. Perhaps having r6 select it, or
> "default y if CONFIG_CPU_MIPSR6" would make sense though, given that you
> won't be able to use the FPU for r6 userland without it.
> 
> Paul
> 
Thanks I add a patch to have CPU_MIPS32_R6 select MIPS_O32_FP64_SUPPORT

-- 
markos

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

* [PATCH v3] MIPS: kernel: elf: Improve the overall ABI and FPU mode checks
@ 2015-02-02 16:13       ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-02-02 16:13 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Matthew Fortune, Paul Burton

The previous implementation did not cover all possible FPU combinations
and it silently allowed ABI incompatible objects to be loaded with the
wrong ABI. For example, the previous logic would set the FP_64 ABI as
the matching ABI for an FP_XX object combined with an FP_64A object.
This was wrong, and the matching ABI should have been FP_64A.
The previous logic is now replaced with a new one which determines
the appropriate FPU mode to be used rather than the FP ABI. This has
the advantage that the entire logic is much simpler since it is the FPU
mode we are interested in rather than the FP ABI resulting to code
simplifications.

Cc: Matthew Fortune <Matthew.Fortune@imgtec.com>
Cc: Paul Burton <paul.burton@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/elf.h |  10 +-
 arch/mips/kernel/elf.c      | 303 +++++++++++++++++++++++++++-----------------
 2 files changed, 194 insertions(+), 119 deletions(-)

diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h
index eb4d95de619c..535f196ffe02 100644
--- a/arch/mips/include/asm/elf.h
+++ b/arch/mips/include/asm/elf.h
@@ -417,13 +417,15 @@ extern unsigned long arch_randomize_brk(struct mm_struct *mm);
 struct arch_elf_state {
 	int fp_abi;
 	int interp_fp_abi;
-	int overall_abi;
+	int overall_fp_mode;
 };
 
+#define MIPS_ABI_FP_UNKNOWN	(-1)	/* Unknown FP ABI (kernel internal) */
+
 #define INIT_ARCH_ELF_STATE {			\
-	.fp_abi = -1,				\
-	.interp_fp_abi = -1,			\
-	.overall_abi = -1,			\
+	.fp_abi = MIPS_ABI_FP_UNKNOWN,		\
+	.interp_fp_abi = MIPS_ABI_FP_UNKNOWN,	\
+	.overall_fp_mode = -1,			\
 }
 
 extern int arch_elf_pt_proc(void *ehdr, void *phdr, struct file *elf,
diff --git a/arch/mips/kernel/elf.c b/arch/mips/kernel/elf.c
index c92b15df6893..d2c09f6475c5 100644
--- a/arch/mips/kernel/elf.c
+++ b/arch/mips/kernel/elf.c
@@ -11,29 +11,112 @@
 #include <linux/elf.h>
 #include <linux/sched.h>
 
+/* FPU modes */
 enum {
-	FP_ERROR = -1,
-	FP_DOUBLE_64A = -2,
+	FP_FRE,
+	FP_FR0,
+	FP_FR1,
 };
 
+/**
+ * struct mode_req - ABI FPU mode requirements
+ * @single:	The program being loaded needs an FPU but it will only issue
+ *		single precision instructions meaning that it can execute in
+ *		either FR0 or FR1.
+ * @soft:	The soft(-float) requirement means that the program being
+ *		loaded needs has no FPU dependency at all (i.e. it has no
+ *		FPU instructions).
+ * @fr1:	The program being loaded depends on FPU being in FR=1 mode.
+ * @frdefault:	The program being loaded depends on the default FPU mode.
+ *		That is FR0 for O32 and FR1 for N32/N64.
+ * @fre:	The program being loaded depends on FPU with FRE=1. This mode is
+ *		a bridge which uses FR=1 whilst still being able to maintain
+ *		full compatibility with pre-existing code using the O32 FP32
+ *		ABI.
+ *
+ * More information about the FP ABIs can be found here:
+ *
+ * https://dmz-portal.mips.com/wiki/MIPS_O32_ABI_-_FR0_and_FR1_Interlinking#10.4.1._Basic_mode_set-up
+ *
+ */
+
+struct mode_req {
+	bool single;
+	bool soft;
+	bool fr1;
+	bool frdefault;
+	bool fre;
+};
+
+static const struct mode_req fpu_reqs[] = {
+	[MIPS_ABI_FP_ANY]    = { true,  true,  true,  true,  true  },
+	[MIPS_ABI_FP_DOUBLE] = { false, false, false, true,  true  },
+	[MIPS_ABI_FP_SINGLE] = { true,  false, false, false, false },
+	[MIPS_ABI_FP_SOFT]   = { false, true,  false, false, false },
+	[MIPS_ABI_FP_OLD_64] = { false, false, false, false, false },
+	[MIPS_ABI_FP_XX]     = { false, false, true,  true,  true  },
+	[MIPS_ABI_FP_64]     = { false, false, true,  false, false },
+	[MIPS_ABI_FP_64A]    = { false, false, true,  false, true  }
+};
+
+/*
+ * Mode requirements when .MIPS.abiflags is not present in the ELF.
+ * Not present means that everything is acceptable except FR1.
+ */
+static struct mode_req none_req = { true, true, false, true, true };
+
 int arch_elf_pt_proc(void *_ehdr, void *_phdr, struct file *elf,
 		     bool is_interp, struct arch_elf_state *state)
 {
-	struct elfhdr *ehdr = _ehdr;
-	struct elf_phdr *phdr = _phdr;
+	struct elf32_hdr *ehdr32 = _ehdr;
+	struct elf32_phdr *phdr32 = _phdr;
+	struct elf64_phdr *phdr64 = _phdr;
 	struct mips_elf_abiflags_v0 abiflags;
 	int ret;
 
-	if (config_enabled(CONFIG_64BIT) &&
-	    (ehdr->e_ident[EI_CLASS] != ELFCLASS32))
-		return 0;
-	if (phdr->p_type != PT_MIPS_ABIFLAGS)
-		return 0;
-	if (phdr->p_filesz < sizeof(abiflags))
-		return -EINVAL;
+	/* Lets see if this is an O32 ELF */
+	if (ehdr32->e_ident[EI_CLASS] == ELFCLASS32) {
+		/* FR = 1 for N32 */
+		if (ehdr32->e_flags & EF_MIPS_ABI2)
+			state->overall_fp_mode = FP_FR1;
+		else
+			/* Set a good default FPU mode for O32 */
+			state->overall_fp_mode = cpu_has_mips_r6 ?
+				FP_FRE : FP_FR0;
+
+		if (ehdr32->e_flags & EF_MIPS_FP64) {
+			/*
+			 * Set MIPS_ABI_FP_OLD_64 for EF_MIPS_FP64. We will override it
+			 * later if needed
+			 */
+			if (is_interp)
+				state->interp_fp_abi = MIPS_ABI_FP_OLD_64;
+			else
+				state->fp_abi = MIPS_ABI_FP_OLD_64;
+		}
+		if (phdr32->p_type != PT_MIPS_ABIFLAGS)
+			return 0;
+
+		if (phdr32->p_filesz < sizeof(abiflags))
+			return -EINVAL;
+
+		ret = kernel_read(elf, phdr32->p_offset,
+				  (char *)&abiflags,
+				  sizeof(abiflags));
+	} else {
+		/* FR=1 is really the only option for 64-bit */
+		state->overall_fp_mode = FP_FR1;
+
+		if (phdr64->p_type != PT_MIPS_ABIFLAGS)
+			return 0;
+		if (phdr64->p_filesz < sizeof(abiflags))
+			return -EINVAL;
+
+		ret = kernel_read(elf, phdr64->p_offset,
+				  (char *)&abiflags,
+				  sizeof(abiflags));
+	}
 
-	ret = kernel_read(elf, phdr->p_offset, (char *)&abiflags,
-			  sizeof(abiflags));
 	if (ret < 0)
 		return ret;
 	if (ret != sizeof(abiflags))
@@ -48,35 +131,30 @@ int arch_elf_pt_proc(void *_ehdr, void *_phdr, struct file *elf,
 	return 0;
 }
 
-static inline unsigned get_fp_abi(struct elfhdr *ehdr, int in_abi)
+static inline unsigned get_fp_abi(int in_abi)
 {
 	/* If the ABI requirement is provided, simply return that */
-	if (in_abi != -1)
+	if (in_abi != MIPS_ABI_FP_UNKNOWN)
 		return in_abi;
 
-	/* If the EF_MIPS_FP64 flag was set, return MIPS_ABI_FP_64 */
-	if (ehdr->e_flags & EF_MIPS_FP64)
-		return MIPS_ABI_FP_64;
-
-	/* Default to MIPS_ABI_FP_DOUBLE */
-	return MIPS_ABI_FP_DOUBLE;
+	/* Unknown ABI */
+	return MIPS_ABI_FP_UNKNOWN;
 }
 
 int arch_check_elf(void *_ehdr, bool has_interpreter,
 		   struct arch_elf_state *state)
 {
-	struct elfhdr *ehdr = _ehdr;
-	unsigned fp_abi, interp_fp_abi, abi0, abi1;
+	struct elf32_hdr *ehdr = _ehdr;
+	struct mode_req prog_req, interp_req;
+	int fp_abi, interp_fp_abi, abi0, abi1, max_abi;
 
-	/* Ignore non-O32 binaries */
-	if (config_enabled(CONFIG_64BIT) &&
-	    (ehdr->e_ident[EI_CLASS] != ELFCLASS32))
+	if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
 		return 0;
 
-	fp_abi = get_fp_abi(ehdr, state->fp_abi);
+	fp_abi = get_fp_abi(state->fp_abi);
 
 	if (has_interpreter) {
-		interp_fp_abi = get_fp_abi(ehdr, state->interp_fp_abi);
+		interp_fp_abi = get_fp_abi(state->interp_fp_abi);
 
 		abi0 = min(fp_abi, interp_fp_abi);
 		abi1 = max(fp_abi, interp_fp_abi);
@@ -84,108 +162,103 @@ int arch_check_elf(void *_ehdr, bool has_interpreter,
 		abi0 = abi1 = fp_abi;
 	}
 
-	state->overall_abi = FP_ERROR;
-
-	if (abi0 == abi1) {
-		state->overall_abi = abi0;
-	} else if (abi0 == MIPS_ABI_FP_ANY) {
-		state->overall_abi = abi1;
-	} else if (abi0 == MIPS_ABI_FP_DOUBLE) {
-		switch (abi1) {
-		case MIPS_ABI_FP_XX:
-			state->overall_abi = MIPS_ABI_FP_DOUBLE;
-			break;
-
-		case MIPS_ABI_FP_64A:
-			state->overall_abi = FP_DOUBLE_64A;
-			break;
-		}
-	} else if (abi0 == MIPS_ABI_FP_SINGLE ||
-		   abi0 == MIPS_ABI_FP_SOFT) {
-		/* Cannot link with other ABIs */
-	} else if (abi0 == MIPS_ABI_FP_OLD_64) {
-		switch (abi1) {
-		case MIPS_ABI_FP_XX:
-		case MIPS_ABI_FP_64:
-		case MIPS_ABI_FP_64A:
-			state->overall_abi = MIPS_ABI_FP_64;
-			break;
-		}
-	} else if (abi0 == MIPS_ABI_FP_XX ||
-		   abi0 == MIPS_ABI_FP_64 ||
-		   abi0 == MIPS_ABI_FP_64A) {
-		state->overall_abi = MIPS_ABI_FP_64;
-	}
+	/* ABI limits. O32 = FP_64A, N32/N64 = FP_SOFT */
+	max_abi = ((ehdr->e_ident[EI_CLASS] == ELFCLASS32) &&
+		   (!(ehdr->e_flags & EF_MIPS_ABI2))) ?
+		MIPS_ABI_FP_64A : MIPS_ABI_FP_SOFT;
 
-	switch (state->overall_abi) {
-	case MIPS_ABI_FP_64:
-	case MIPS_ABI_FP_64A:
-	case FP_DOUBLE_64A:
-		if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
-			return -ELIBBAD;
-		break;
+	if ((abi0 > max_abi && abi0 != MIPS_ABI_FP_UNKNOWN) ||
+	    (abi1 > max_abi && abi1 != MIPS_ABI_FP_UNKNOWN))
+		return -ELIBBAD;
+
+	/* It's time to determine the FPU mode requirements */
+	prog_req = (abi0 == MIPS_ABI_FP_UNKNOWN) ? none_req : fpu_reqs[abi0];
+	interp_req = (abi1 == MIPS_ABI_FP_UNKNOWN) ? none_req : fpu_reqs[abi1];
 
-	case FP_ERROR:
+	/*
+	 * Check whether the program's and interp's ABIs have a matching FPU
+	 * mode requirement.
+	 */
+	prog_req.single = interp_req.single && prog_req.single;
+	prog_req.soft = interp_req.soft && prog_req.soft;
+	prog_req.fr1 = interp_req.fr1 && prog_req.fr1;
+	prog_req.frdefault = interp_req.frdefault && prog_req.frdefault;
+	prog_req.fre = interp_req.fre && prog_req.fre;
+
+	/*
+	 * Determine the desired FPU mode
+	 *
+	 * Decision making:
+	 *
+	 * - We want FR_FRE if FRE=1 and both FR=1 and FR=0 are false. This
+	 *   means that we have a combination of program and interpreter
+	 *   that inherently require the hybrid FP mode.
+	 * - If FR1 and FRDEFAULT is true, that means we hit the any-abi or
+	 *   fpxx case. This is because, in any-ABI (or no-ABI) we have no FPU
+	 *   instructions so we don't care about the mode. We will simply use
+	 *   the one preferred by the hardware. In fpxx case, that ABI can
+	 *   handle both FR=1 and FR=0, so, again, we simply choose the one
+	 *   preferred by the hardware. Next, if we only use single-precision
+	 *   FPU instructions, and the default ABI FPU mode is not good
+	 *   (ie single + any ABI combination), we set again the FPU mode to the
+	 *   one is preferred by the hardware. Next, if we know that the code
+	 *   will only use single-precision instructions, shown by single being
+	 *   true but frdefault being false, then we again set the FPU mode to
+	 *   the one that is preferred by the hardware.
+	 * - We want FP_FR1 if that's the only matching mode and the default one
+	 *   is not good.
+	 * - Return with -ELIBADD if we can't find a matching FPU mode.
+	 */
+	if (prog_req.fre && !prog_req.frdefault && !prog_req.fr1)
+		state->overall_fp_mode = FP_FRE;
+	else if ((prog_req.fr1 && prog_req.frdefault) ||
+		 (prog_req.single && !prog_req.frdefault))
+		/* Make sure 64-bit MIPS III/IV/64R1 will not pick FR1 */
+		state->overall_fp_mode = ((current_cpu_data.fpu_id & MIPS_FPIR_F64) &&
+					  cpu_has_mips_r2_r6) ?
+					  FP_FR1 : FP_FR0;
+	else if (prog_req.fr1)
+		state->overall_fp_mode = FP_FR1;
+	else  if (!prog_req.fre && !prog_req.frdefault &&
+		  !prog_req.fr1 && !prog_req.single && !prog_req.soft)
 		return -ELIBBAD;
-	}
 
 	return 0;
 }
 
-void mips_set_personality_fp(struct arch_elf_state *state)
+static inline void set_thread_fp_mode(int hybrid, int regs32)
 {
-	if (config_enabled(CONFIG_FP32XX_HYBRID_FPRS)) {
-		/*
-		 * Use hybrid FPRs for all code which can correctly execute
-		 * with that mode.
-		 */
-		switch (state->overall_abi) {
-		case MIPS_ABI_FP_DOUBLE:
-		case MIPS_ABI_FP_SINGLE:
-		case MIPS_ABI_FP_SOFT:
-		case MIPS_ABI_FP_XX:
-		case MIPS_ABI_FP_ANY:
-			/* FR=1, FRE=1 */
-			clear_thread_flag(TIF_32BIT_FPREGS);
-			set_thread_flag(TIF_HYBRID_FPREGS);
-			return;
-		}
-	}
-
-	switch (state->overall_abi) {
-	case MIPS_ABI_FP_DOUBLE:
-	case MIPS_ABI_FP_SINGLE:
-	case MIPS_ABI_FP_SOFT:
-		/* FR=0 */
-		set_thread_flag(TIF_32BIT_FPREGS);
+	if (hybrid)
+		set_thread_flag(TIF_HYBRID_FPREGS);
+	else
 		clear_thread_flag(TIF_HYBRID_FPREGS);
-		break;
-
-	case FP_DOUBLE_64A:
-		/* FR=1, FRE=1 */
+	if (regs32)
+		set_thread_flag(TIF_32BIT_FPREGS);
+	else
 		clear_thread_flag(TIF_32BIT_FPREGS);
-		set_thread_flag(TIF_HYBRID_FPREGS);
-		break;
+}
 
-	case MIPS_ABI_FP_64:
-	case MIPS_ABI_FP_64A:
-		/* FR=1, FRE=0 */
-		clear_thread_flag(TIF_32BIT_FPREGS);
-		clear_thread_flag(TIF_HYBRID_FPREGS);
-		break;
+void mips_set_personality_fp(struct arch_elf_state *state)
+{
+	/*
+	 * This function is only ever called for O32 ELFs so we should
+	 * not be worried about N32/N64 binaries.
+	 */
 
-	case MIPS_ABI_FP_XX:
-	case MIPS_ABI_FP_ANY:
-		if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
-			set_thread_flag(TIF_32BIT_FPREGS);
-		else
-			clear_thread_flag(TIF_32BIT_FPREGS);
+	if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
+		return;
 
-		clear_thread_flag(TIF_HYBRID_FPREGS);
+	switch (state->overall_fp_mode) {
+	case FP_FRE:
+		set_thread_fp_mode(1, 0);
+		break;
+	case FP_FR0:
+		set_thread_fp_mode(0, 1);
+		break;
+	case FP_FR1:
+		set_thread_fp_mode(0, 0);
 		break;
-
 	default:
-	case FP_ERROR:
 		BUG();
 	}
 }
-- 
2.2.2

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

* [PATCH v3] MIPS: kernel: elf: Improve the overall ABI and FPU mode checks
@ 2015-02-02 16:13       ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-02-02 16:13 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Matthew Fortune, Paul Burton

The previous implementation did not cover all possible FPU combinations
and it silently allowed ABI incompatible objects to be loaded with the
wrong ABI. For example, the previous logic would set the FP_64 ABI as
the matching ABI for an FP_XX object combined with an FP_64A object.
This was wrong, and the matching ABI should have been FP_64A.
The previous logic is now replaced with a new one which determines
the appropriate FPU mode to be used rather than the FP ABI. This has
the advantage that the entire logic is much simpler since it is the FPU
mode we are interested in rather than the FP ABI resulting to code
simplifications.

Cc: Matthew Fortune <Matthew.Fortune@imgtec.com>
Cc: Paul Burton <paul.burton@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/elf.h |  10 +-
 arch/mips/kernel/elf.c      | 303 +++++++++++++++++++++++++++-----------------
 2 files changed, 194 insertions(+), 119 deletions(-)

diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h
index eb4d95de619c..535f196ffe02 100644
--- a/arch/mips/include/asm/elf.h
+++ b/arch/mips/include/asm/elf.h
@@ -417,13 +417,15 @@ extern unsigned long arch_randomize_brk(struct mm_struct *mm);
 struct arch_elf_state {
 	int fp_abi;
 	int interp_fp_abi;
-	int overall_abi;
+	int overall_fp_mode;
 };
 
+#define MIPS_ABI_FP_UNKNOWN	(-1)	/* Unknown FP ABI (kernel internal) */
+
 #define INIT_ARCH_ELF_STATE {			\
-	.fp_abi = -1,				\
-	.interp_fp_abi = -1,			\
-	.overall_abi = -1,			\
+	.fp_abi = MIPS_ABI_FP_UNKNOWN,		\
+	.interp_fp_abi = MIPS_ABI_FP_UNKNOWN,	\
+	.overall_fp_mode = -1,			\
 }
 
 extern int arch_elf_pt_proc(void *ehdr, void *phdr, struct file *elf,
diff --git a/arch/mips/kernel/elf.c b/arch/mips/kernel/elf.c
index c92b15df6893..d2c09f6475c5 100644
--- a/arch/mips/kernel/elf.c
+++ b/arch/mips/kernel/elf.c
@@ -11,29 +11,112 @@
 #include <linux/elf.h>
 #include <linux/sched.h>
 
+/* FPU modes */
 enum {
-	FP_ERROR = -1,
-	FP_DOUBLE_64A = -2,
+	FP_FRE,
+	FP_FR0,
+	FP_FR1,
 };
 
+/**
+ * struct mode_req - ABI FPU mode requirements
+ * @single:	The program being loaded needs an FPU but it will only issue
+ *		single precision instructions meaning that it can execute in
+ *		either FR0 or FR1.
+ * @soft:	The soft(-float) requirement means that the program being
+ *		loaded needs has no FPU dependency at all (i.e. it has no
+ *		FPU instructions).
+ * @fr1:	The program being loaded depends on FPU being in FR=1 mode.
+ * @frdefault:	The program being loaded depends on the default FPU mode.
+ *		That is FR0 for O32 and FR1 for N32/N64.
+ * @fre:	The program being loaded depends on FPU with FRE=1. This mode is
+ *		a bridge which uses FR=1 whilst still being able to maintain
+ *		full compatibility with pre-existing code using the O32 FP32
+ *		ABI.
+ *
+ * More information about the FP ABIs can be found here:
+ *
+ * https://dmz-portal.mips.com/wiki/MIPS_O32_ABI_-_FR0_and_FR1_Interlinking#10.4.1._Basic_mode_set-up
+ *
+ */
+
+struct mode_req {
+	bool single;
+	bool soft;
+	bool fr1;
+	bool frdefault;
+	bool fre;
+};
+
+static const struct mode_req fpu_reqs[] = {
+	[MIPS_ABI_FP_ANY]    = { true,  true,  true,  true,  true  },
+	[MIPS_ABI_FP_DOUBLE] = { false, false, false, true,  true  },
+	[MIPS_ABI_FP_SINGLE] = { true,  false, false, false, false },
+	[MIPS_ABI_FP_SOFT]   = { false, true,  false, false, false },
+	[MIPS_ABI_FP_OLD_64] = { false, false, false, false, false },
+	[MIPS_ABI_FP_XX]     = { false, false, true,  true,  true  },
+	[MIPS_ABI_FP_64]     = { false, false, true,  false, false },
+	[MIPS_ABI_FP_64A]    = { false, false, true,  false, true  }
+};
+
+/*
+ * Mode requirements when .MIPS.abiflags is not present in the ELF.
+ * Not present means that everything is acceptable except FR1.
+ */
+static struct mode_req none_req = { true, true, false, true, true };
+
 int arch_elf_pt_proc(void *_ehdr, void *_phdr, struct file *elf,
 		     bool is_interp, struct arch_elf_state *state)
 {
-	struct elfhdr *ehdr = _ehdr;
-	struct elf_phdr *phdr = _phdr;
+	struct elf32_hdr *ehdr32 = _ehdr;
+	struct elf32_phdr *phdr32 = _phdr;
+	struct elf64_phdr *phdr64 = _phdr;
 	struct mips_elf_abiflags_v0 abiflags;
 	int ret;
 
-	if (config_enabled(CONFIG_64BIT) &&
-	    (ehdr->e_ident[EI_CLASS] != ELFCLASS32))
-		return 0;
-	if (phdr->p_type != PT_MIPS_ABIFLAGS)
-		return 0;
-	if (phdr->p_filesz < sizeof(abiflags))
-		return -EINVAL;
+	/* Lets see if this is an O32 ELF */
+	if (ehdr32->e_ident[EI_CLASS] == ELFCLASS32) {
+		/* FR = 1 for N32 */
+		if (ehdr32->e_flags & EF_MIPS_ABI2)
+			state->overall_fp_mode = FP_FR1;
+		else
+			/* Set a good default FPU mode for O32 */
+			state->overall_fp_mode = cpu_has_mips_r6 ?
+				FP_FRE : FP_FR0;
+
+		if (ehdr32->e_flags & EF_MIPS_FP64) {
+			/*
+			 * Set MIPS_ABI_FP_OLD_64 for EF_MIPS_FP64. We will override it
+			 * later if needed
+			 */
+			if (is_interp)
+				state->interp_fp_abi = MIPS_ABI_FP_OLD_64;
+			else
+				state->fp_abi = MIPS_ABI_FP_OLD_64;
+		}
+		if (phdr32->p_type != PT_MIPS_ABIFLAGS)
+			return 0;
+
+		if (phdr32->p_filesz < sizeof(abiflags))
+			return -EINVAL;
+
+		ret = kernel_read(elf, phdr32->p_offset,
+				  (char *)&abiflags,
+				  sizeof(abiflags));
+	} else {
+		/* FR=1 is really the only option for 64-bit */
+		state->overall_fp_mode = FP_FR1;
+
+		if (phdr64->p_type != PT_MIPS_ABIFLAGS)
+			return 0;
+		if (phdr64->p_filesz < sizeof(abiflags))
+			return -EINVAL;
+
+		ret = kernel_read(elf, phdr64->p_offset,
+				  (char *)&abiflags,
+				  sizeof(abiflags));
+	}
 
-	ret = kernel_read(elf, phdr->p_offset, (char *)&abiflags,
-			  sizeof(abiflags));
 	if (ret < 0)
 		return ret;
 	if (ret != sizeof(abiflags))
@@ -48,35 +131,30 @@ int arch_elf_pt_proc(void *_ehdr, void *_phdr, struct file *elf,
 	return 0;
 }
 
-static inline unsigned get_fp_abi(struct elfhdr *ehdr, int in_abi)
+static inline unsigned get_fp_abi(int in_abi)
 {
 	/* If the ABI requirement is provided, simply return that */
-	if (in_abi != -1)
+	if (in_abi != MIPS_ABI_FP_UNKNOWN)
 		return in_abi;
 
-	/* If the EF_MIPS_FP64 flag was set, return MIPS_ABI_FP_64 */
-	if (ehdr->e_flags & EF_MIPS_FP64)
-		return MIPS_ABI_FP_64;
-
-	/* Default to MIPS_ABI_FP_DOUBLE */
-	return MIPS_ABI_FP_DOUBLE;
+	/* Unknown ABI */
+	return MIPS_ABI_FP_UNKNOWN;
 }
 
 int arch_check_elf(void *_ehdr, bool has_interpreter,
 		   struct arch_elf_state *state)
 {
-	struct elfhdr *ehdr = _ehdr;
-	unsigned fp_abi, interp_fp_abi, abi0, abi1;
+	struct elf32_hdr *ehdr = _ehdr;
+	struct mode_req prog_req, interp_req;
+	int fp_abi, interp_fp_abi, abi0, abi1, max_abi;
 
-	/* Ignore non-O32 binaries */
-	if (config_enabled(CONFIG_64BIT) &&
-	    (ehdr->e_ident[EI_CLASS] != ELFCLASS32))
+	if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
 		return 0;
 
-	fp_abi = get_fp_abi(ehdr, state->fp_abi);
+	fp_abi = get_fp_abi(state->fp_abi);
 
 	if (has_interpreter) {
-		interp_fp_abi = get_fp_abi(ehdr, state->interp_fp_abi);
+		interp_fp_abi = get_fp_abi(state->interp_fp_abi);
 
 		abi0 = min(fp_abi, interp_fp_abi);
 		abi1 = max(fp_abi, interp_fp_abi);
@@ -84,108 +162,103 @@ int arch_check_elf(void *_ehdr, bool has_interpreter,
 		abi0 = abi1 = fp_abi;
 	}
 
-	state->overall_abi = FP_ERROR;
-
-	if (abi0 == abi1) {
-		state->overall_abi = abi0;
-	} else if (abi0 == MIPS_ABI_FP_ANY) {
-		state->overall_abi = abi1;
-	} else if (abi0 == MIPS_ABI_FP_DOUBLE) {
-		switch (abi1) {
-		case MIPS_ABI_FP_XX:
-			state->overall_abi = MIPS_ABI_FP_DOUBLE;
-			break;
-
-		case MIPS_ABI_FP_64A:
-			state->overall_abi = FP_DOUBLE_64A;
-			break;
-		}
-	} else if (abi0 == MIPS_ABI_FP_SINGLE ||
-		   abi0 == MIPS_ABI_FP_SOFT) {
-		/* Cannot link with other ABIs */
-	} else if (abi0 == MIPS_ABI_FP_OLD_64) {
-		switch (abi1) {
-		case MIPS_ABI_FP_XX:
-		case MIPS_ABI_FP_64:
-		case MIPS_ABI_FP_64A:
-			state->overall_abi = MIPS_ABI_FP_64;
-			break;
-		}
-	} else if (abi0 == MIPS_ABI_FP_XX ||
-		   abi0 == MIPS_ABI_FP_64 ||
-		   abi0 == MIPS_ABI_FP_64A) {
-		state->overall_abi = MIPS_ABI_FP_64;
-	}
+	/* ABI limits. O32 = FP_64A, N32/N64 = FP_SOFT */
+	max_abi = ((ehdr->e_ident[EI_CLASS] == ELFCLASS32) &&
+		   (!(ehdr->e_flags & EF_MIPS_ABI2))) ?
+		MIPS_ABI_FP_64A : MIPS_ABI_FP_SOFT;
 
-	switch (state->overall_abi) {
-	case MIPS_ABI_FP_64:
-	case MIPS_ABI_FP_64A:
-	case FP_DOUBLE_64A:
-		if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
-			return -ELIBBAD;
-		break;
+	if ((abi0 > max_abi && abi0 != MIPS_ABI_FP_UNKNOWN) ||
+	    (abi1 > max_abi && abi1 != MIPS_ABI_FP_UNKNOWN))
+		return -ELIBBAD;
+
+	/* It's time to determine the FPU mode requirements */
+	prog_req = (abi0 == MIPS_ABI_FP_UNKNOWN) ? none_req : fpu_reqs[abi0];
+	interp_req = (abi1 == MIPS_ABI_FP_UNKNOWN) ? none_req : fpu_reqs[abi1];
 
-	case FP_ERROR:
+	/*
+	 * Check whether the program's and interp's ABIs have a matching FPU
+	 * mode requirement.
+	 */
+	prog_req.single = interp_req.single && prog_req.single;
+	prog_req.soft = interp_req.soft && prog_req.soft;
+	prog_req.fr1 = interp_req.fr1 && prog_req.fr1;
+	prog_req.frdefault = interp_req.frdefault && prog_req.frdefault;
+	prog_req.fre = interp_req.fre && prog_req.fre;
+
+	/*
+	 * Determine the desired FPU mode
+	 *
+	 * Decision making:
+	 *
+	 * - We want FR_FRE if FRE=1 and both FR=1 and FR=0 are false. This
+	 *   means that we have a combination of program and interpreter
+	 *   that inherently require the hybrid FP mode.
+	 * - If FR1 and FRDEFAULT is true, that means we hit the any-abi or
+	 *   fpxx case. This is because, in any-ABI (or no-ABI) we have no FPU
+	 *   instructions so we don't care about the mode. We will simply use
+	 *   the one preferred by the hardware. In fpxx case, that ABI can
+	 *   handle both FR=1 and FR=0, so, again, we simply choose the one
+	 *   preferred by the hardware. Next, if we only use single-precision
+	 *   FPU instructions, and the default ABI FPU mode is not good
+	 *   (ie single + any ABI combination), we set again the FPU mode to the
+	 *   one is preferred by the hardware. Next, if we know that the code
+	 *   will only use single-precision instructions, shown by single being
+	 *   true but frdefault being false, then we again set the FPU mode to
+	 *   the one that is preferred by the hardware.
+	 * - We want FP_FR1 if that's the only matching mode and the default one
+	 *   is not good.
+	 * - Return with -ELIBADD if we can't find a matching FPU mode.
+	 */
+	if (prog_req.fre && !prog_req.frdefault && !prog_req.fr1)
+		state->overall_fp_mode = FP_FRE;
+	else if ((prog_req.fr1 && prog_req.frdefault) ||
+		 (prog_req.single && !prog_req.frdefault))
+		/* Make sure 64-bit MIPS III/IV/64R1 will not pick FR1 */
+		state->overall_fp_mode = ((current_cpu_data.fpu_id & MIPS_FPIR_F64) &&
+					  cpu_has_mips_r2_r6) ?
+					  FP_FR1 : FP_FR0;
+	else if (prog_req.fr1)
+		state->overall_fp_mode = FP_FR1;
+	else  if (!prog_req.fre && !prog_req.frdefault &&
+		  !prog_req.fr1 && !prog_req.single && !prog_req.soft)
 		return -ELIBBAD;
-	}
 
 	return 0;
 }
 
-void mips_set_personality_fp(struct arch_elf_state *state)
+static inline void set_thread_fp_mode(int hybrid, int regs32)
 {
-	if (config_enabled(CONFIG_FP32XX_HYBRID_FPRS)) {
-		/*
-		 * Use hybrid FPRs for all code which can correctly execute
-		 * with that mode.
-		 */
-		switch (state->overall_abi) {
-		case MIPS_ABI_FP_DOUBLE:
-		case MIPS_ABI_FP_SINGLE:
-		case MIPS_ABI_FP_SOFT:
-		case MIPS_ABI_FP_XX:
-		case MIPS_ABI_FP_ANY:
-			/* FR=1, FRE=1 */
-			clear_thread_flag(TIF_32BIT_FPREGS);
-			set_thread_flag(TIF_HYBRID_FPREGS);
-			return;
-		}
-	}
-
-	switch (state->overall_abi) {
-	case MIPS_ABI_FP_DOUBLE:
-	case MIPS_ABI_FP_SINGLE:
-	case MIPS_ABI_FP_SOFT:
-		/* FR=0 */
-		set_thread_flag(TIF_32BIT_FPREGS);
+	if (hybrid)
+		set_thread_flag(TIF_HYBRID_FPREGS);
+	else
 		clear_thread_flag(TIF_HYBRID_FPREGS);
-		break;
-
-	case FP_DOUBLE_64A:
-		/* FR=1, FRE=1 */
+	if (regs32)
+		set_thread_flag(TIF_32BIT_FPREGS);
+	else
 		clear_thread_flag(TIF_32BIT_FPREGS);
-		set_thread_flag(TIF_HYBRID_FPREGS);
-		break;
+}
 
-	case MIPS_ABI_FP_64:
-	case MIPS_ABI_FP_64A:
-		/* FR=1, FRE=0 */
-		clear_thread_flag(TIF_32BIT_FPREGS);
-		clear_thread_flag(TIF_HYBRID_FPREGS);
-		break;
+void mips_set_personality_fp(struct arch_elf_state *state)
+{
+	/*
+	 * This function is only ever called for O32 ELFs so we should
+	 * not be worried about N32/N64 binaries.
+	 */
 
-	case MIPS_ABI_FP_XX:
-	case MIPS_ABI_FP_ANY:
-		if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
-			set_thread_flag(TIF_32BIT_FPREGS);
-		else
-			clear_thread_flag(TIF_32BIT_FPREGS);
+	if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
+		return;
 
-		clear_thread_flag(TIF_HYBRID_FPREGS);
+	switch (state->overall_fp_mode) {
+	case FP_FRE:
+		set_thread_fp_mode(1, 0);
+		break;
+	case FP_FR0:
+		set_thread_fp_mode(0, 1);
+		break;
+	case FP_FR1:
+		set_thread_fp_mode(0, 0);
 		break;
-
 	default:
-	case FP_ERROR:
 		BUG();
 	}
 }
-- 
2.2.2

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

* Re: [PATCH RFC v2 46/70] MIPS: kernel: branch: Prevent BGEZL emulation for MIPS R6
  2015-01-16 10:49   ` Markos Chandras
  (?)
@ 2015-02-03 11:57   ` Maciej W. Rozycki
  -1 siblings, 0 replies; 262+ messages in thread
From: Maciej W. Rozycki @ 2015-02-03 11:57 UTC (permalink / raw)
  To: Markos Chandras; +Cc: linux-mips

On Fri, 16 Jan 2015, Markos Chandras wrote:

> diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
> index 502bf2aeb834..b8cc0a2e20a4 100644
> --- a/arch/mips/kernel/branch.c
> +++ b/arch/mips/kernel/branch.c
> @@ -452,6 +452,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)) {

 There is no need for parentheses around `==' here, logical operators are 
well known to have a lower precedence.  The same applies throughout this 
series.

  Maciej

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

* Re: [PATCH RFC v2 68/70] MIPS: kernel: elf: Improve the overall ABI and FPU mode checks
  2015-01-16 10:49   ` Markos Chandras
                     ` (3 preceding siblings ...)
  (?)
@ 2015-02-03 12:40   ` Maciej W. Rozycki
  -1 siblings, 0 replies; 262+ messages in thread
From: Maciej W. Rozycki @ 2015-02-03 12:40 UTC (permalink / raw)
  To: Markos Chandras; +Cc: linux-mips, Matthew Fortune, Paul Burton

On Fri, 16 Jan 2015, Markos Chandras wrote:

> diff --git a/arch/mips/kernel/elf.c b/arch/mips/kernel/elf.c
> index c92b15df6893..2ac33d2375ca 100644
> --- a/arch/mips/kernel/elf.c
> +++ b/arch/mips/kernel/elf.c
> @@ -11,29 +11,102 @@
>  #include <linux/elf.h>
>  #include <linux/sched.h>
>  
> +/* FPU modes */
>  enum {
> -	FP_ERROR = -1,
> -	FP_DOUBLE_64A = -2,
> +	FP_FRE,
> +	FP_FR0,
> +	FP_FR1,
>  };
>  
> +/**
> + * struct mode_req - ABI FPU mode requirements
> + * @single:	The program being loaded needs an FPU but it will only issue
> + *		single precision instructions meaning that it can execute in
> + *		either FR0 or FR1.
> + * @soft:	The soft(-float) requirement means that the program being
> + *		loaded needs has no FPU dependency at all (i.e. it has no
> + *		FPU instructions).
> + * @fr1:	The program being loaded depends on FPU being in FR=1 mode.
> + * @frdefault:	The program being loaded depends on the default FPU mode.
> + *		That is FR0 for O32 and FR1 for N32/N64.
> + * @fre:	The program being loaded depends on FPU with FRE=1. This mode is
> + *		a bridge which uses FR=1 whilst still being able to maintain
> + *		full compatibility with pre-existing code using the O32 FP32
> + *		ABI.
> + *
> + * More information about the FP ABIs can be found here:
> + *
> + * https://dmz-portal.mips.com/wiki/MIPS_O32_ABI_-_FR0_and_FR1_Interlinking#10.4.1._Basic_mode_set-up
> + *
> + */
> +
> +struct mode_req {
> +	bool single;
> +	bool soft;
> +	bool fr1;
> +	bool frdefault;
> +	bool fre;
> +};
> +
> +static const struct mode_req fpu_reqs[] = {
> +	[MIPS_ABI_FP_ANY]    = { true,  true,  true,  true,  true  },
> +	[MIPS_ABI_FP_DOUBLE] = { false, false, false, true,  true  },
> +	[MIPS_ABI_FP_SINGLE] = { true,  false, false, false, false },
> +	[MIPS_ABI_FP_SOFT]   = { false, true,  false, false, false },
> +	[MIPS_ABI_FP_OLD_64] = { false, false, false, false, false },
> +	[MIPS_ABI_FP_XX]     = { false, false, true,  true,  true  },
> +	[MIPS_ABI_FP_64]     = { false, false, true,  false, false },
> +	[MIPS_ABI_FP_64A]    = { false, false, true,  false, true  }
> +};
> +
> +/*
> + * Mode requirements when .MIPS.abiflags is not present in the ELF.
> + * Not present means that everything is acceptable except FR1.
> + */
> +static struct mode_req none_req = { true, true, false, true, true };
> +
>  int arch_elf_pt_proc(void *_ehdr, void *_phdr, struct file *elf,
>  		     bool is_interp, struct arch_elf_state *state)
>  {
> -	struct elfhdr *ehdr = _ehdr;
> -	struct elf_phdr *phdr = _phdr;
> +	struct elf32_hdr *ehdr32 = _ehdr;
> +	struct elf32_phdr *phdr32 = _phdr;
> +	struct elf64_phdr *phdr64 = _phdr;

 Minor nit, I won't be picking on it if you have a strong feeling against, 
but I think it would be slightly cleaner if you had used unions here -- no 
risk of people picking bad habits that would hurt if any of these 
structures were written, causing aliasing issues.

 So e.g.:

	union {
		struct elf32_hdr e32;
		struct elf64_hdr e64;
	} *ehdr = _ehdr;
	union {
		struct elf32_phdr p32;
		struct elf64_phdr p64;
	} *phdr = _phdr;

and then:

> +	/* Lets see if this is an O32 ELF */
> +	if (ehdr32->e_ident[EI_CLASS] == ELFCLASS32) {
> +		/* FR = 1 for N32 */
> +		if (ehdr32->e_flags & EF_MIPS_ABI2)
> +			state->overall_fp_mode = FP_FR1;
> +		else
> +			/* Set a good default FPU mode for O32*/
> +			state->overall_fp_mode = cpu_has_mips_r6 ?
> +				FP_FRE : FP_FR0;
> +
> +		if (phdr32->p_type != PT_MIPS_ABIFLAGS)
> +			return 0;
> +
> +		if (phdr32->p_filesz < sizeof(abiflags))
> +			return -EINVAL;
> +
> +		ret = kernel_read(elf, phdr32->p_offset,
> +				  (char *)&abiflags,
> +				  sizeof(abiflags));

	/* Lets see if this is an O32 ELF */
	if (ehdr->e32.e_ident[EI_CLASS] == ELFCLASS32) {
		/* FR = 1 for N32 */
		if (ehdr->e32.e_flags & EF_MIPS_ABI2)
			state->overall_fp_mode = FP_FR1;
		else
			/* Set a good default FPU mode for O32*/
			state->overall_fp_mode = cpu_has_mips_r6 ?
				FP_FRE : FP_FR0;

		if (phdr->p32.p_type != PT_MIPS_ABIFLAGS)
			return 0;

		if (phdr->p32.p_filesz < sizeof(abiflags))
			return -EINVAL;

		ret = kernel_read(elf, phdr->p32.p_offset,
				  (char *)&abiflags,
				  sizeof(abiflags));

-- and so on...  As you can see the result isn't even much different in 
terms of readability or source code size, while avoiding any possible 
aliasing issues.

  Maciej

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

* RE: [PATCH RFC v2 68/70] MIPS: kernel: elf: Improve the overall ABI and FPU mode checks
  2015-01-19  9:29   ` Matthew Fortune
  2015-01-19 12:17     ` Markos Chandras
@ 2015-02-03 12:41     ` Maciej W. Rozycki
  1 sibling, 0 replies; 262+ messages in thread
From: Maciej W. Rozycki @ 2015-02-03 12:41 UTC (permalink / raw)
  To: Matthew Fortune; +Cc: Markos Chandras, linux-mips, Paul Burton

On Mon, 19 Jan 2015, Matthew Fortune wrote:

> Maciej: The comments you made here http://patchwork.linux-mips.org/patch/8932/
> should be addressed by this patch. 

 Thanks for the heads-up, it looks good to me as far as this matter is 
concerned.

  Maciej

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

* RE: [PATCH RFC v2 24/70] MIPS: asm: spinlock: Replace sub instruction with addiu
  2015-01-20 11:47       ` Matthew Fortune
@ 2015-02-10 16:17         ` Maciej W. Rozycki
  0 siblings, 0 replies; 262+ messages in thread
From: Maciej W. Rozycki @ 2015-02-10 16:17 UTC (permalink / raw)
  To: Matthew Fortune; +Cc: Markos Chandras, binutils, linux-mips

On Tue, 20 Jan 2015, Matthew Fortune wrote:

> > >  What this shows really is a GAS bug fix for the SUB macro is needed
> > > similar to what I suggested in 12/70 for ADDI (from the situation I
> > infer
> > > there is some real work to do in GAS in this area; adding Matthew as a
> > > recipient to raise his awareness) so that it does not expand to ADDI
> > where
> > > the architecture or processor selected do not support it.  Instead a
> > > longer sequence involving SUB has to be produced.
> 
> The assembler is at least consistent at the moment as the 'sub' macro is
> disabled for R6. I am very keen to stop carrying around historic baggage
> where it is not necessary. R6 is one place we can do that and deal with
> any code changes that are required.

 I have yet to be convinced it is merely historic baggage.  Maybe it's a 
matter of habits I got into, but I find the presence of these macros a way 
to make the MIPS assembly language actually usable for handcoding.  There 
are several reasons for this.

 One is the limited range of immediates in machine makes it necessary to 
use different instruction sequences for different immediate input 
arguments.  Given this source code instruction:

	li	$2, foo

for different values of `foo' you'll get different machine code:

    foo		code
    0x1234	addiu $2, $0, 0x1234
    0x89ab	ori $2, $0, 0x89ab
0x89ab0000	lui $2, 0x89ab
0x89ab1234	lui $2, 0x89ab; addiu $2, $2, 0x1234

now if `foo' is some sort of an externally supplied constant (e.g. set 
with a `configure' script or whatever), then without the macros you'd have 
to pessimise code, or clutter it with #ifdef's.

 Another is to abstract ABI dependencies.  Again, given this source code 
instruction:

	lw	$2, foo

for different ABIs you'll get different code:

    ABI		code
o32/non-PIC	lui $2, %hi(foo); lw $2, %lo(foo)($2)
o32/PIC/extern	lw $2, %got(foo)($28); lw $2, 0($2)
o32/PIC/local	lw $2, %got(foo)($28); addiu $2, %lo(foo); lw $2, 0($2)
n64/non-PIC	lui $1, %highest(foo); lui $2, %hi(foo);
		addiu $1, $1, %higher(foo); dsll32 $1, $1, 0;
		daddu $1, $1, $2; lw $2, %lo(foo)($1)
n64/PIC/extern	ld $2, %got_disp(foo)($28); lw $2, 0($2)
[...]

You'd have to conditionalise it all too.

 And there are more cases macros address, e.g. to make the complete set of 
arithmetic conditions available for branches (with the use of SLT and SLTU 
instructions), extra operations (e.g. NOT as a shorthand for NOR), 
three-argument trapping MULOU, DIVU, REMU operations (especially 
interesting to note in the context of r6; why MODU wasn't consequently 
called REMU for portability escapes me), etc.

 All this makes assembly language programming easier and more like with 
CISC assembly languages, e.g. this x86 assembly-language instruction:

	addl	$foo, %eax

will do the right thing for any value of `foo' and the assembler will also 
pick the shortest instruction encoding available.  As a result when 
writing code you can focus on the problem you're trying to solve rather 
than getting distracted by ABI peculiarites or the assymetry of the 
machine instruction set.  It is also easier to follow when studying code 
written by someone else.

 Of course all this does not matter for compiler-generated code.  Which is 
also the reason why the MIPS16 assembly language has never included a 
complementing set of these macros -- it was only meant to be used in 
compiler-generated code and never for handcoding.  And for handcoded 
assembly if you are concerned about source code instructions expanding 
into multiple machine instructions, then you can always stick `.set 
nomacro' at the top of your source code.

> > > 			__asm__ __volatile__(
> > > 			"1:	ll	%1, %2	# arch_read_unlock	\n"
> > > 			"	sub	%1, %3				\n"
> > > 			"	sc	%1, %0				\n"
> > > 			: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
> > > 			: GCC_OFF12_ASM() (rw->lock), GCC_ADDI_ASM() (1)
> > > 			: "memory");
> > >
> > > (untested, but should work) so that there's still a single instruction
> > > only in the LL/SC loop and consequently no increased lock contention
> > risk.
[...]
> 
> (Note this asm block does not appear to need to clobber memory either as
> the effects on memory are correctly stated in the constraints).

 The `memory' clobber serves the purpose of an optimisation barrier here, 
it's not about the memory accesses happening within the asm itself.

> > >  As a side note, this could be cleaned up to use a "+" input/output
> > > constraint; such a clean-up will be welcome -- although to be complete,
> > a
> > > review of all the asms will be required (this may bump up the GCC
> > version
> > > requirement though, ISTR bugs in this area).
> 
> I believe some of these asm blocks using ll/sc already have '+' in the
> constraints for the memory location so perhaps that is either already
> a problem or not an issue.

 I just don't remember offhand if the use of `+' was in platform or in 
shared code.  If the latter, then let's just switch, if the former, we 
need to be careful.

 IIRC some versions of GCC complained and failed compilation if the list 
of constraints associated with `+' did not allow a register alternative, 
such by including the `r' constraint.  Which of course would be completely 
pointless here, and actually harmful.  Furthermore IIRC it had been a 
deliberate decision made by GCC maintainers who were unaware of some use 
cases for inline asms.  The decision was then discussed and GCC 
maintainers persuaded to change it; it can likely be tracked down in a 
mailing list archive somewhere.

  Maciej

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

* Re: [PATCH RFC v2 00/70] Add MIPS R6 support
@ 2015-02-12 23:12   ` David Daney
  0 siblings, 0 replies; 262+ messages in thread
From: David Daney @ 2015-02-12 23:12 UTC (permalink / raw)
  To: Markos Chandras, Ralf Baechle; +Cc: linux-mips, Matthew Fortune

[-- Attachment #1: Type: text/plain, Size: 10256 bytes --]

It looks like Ralf did a preliminary merge of this patch set to 
mips-for-linux-next.

Unfortunatly there are several patches that break compilation of 
existing code, especially OCTEON.  It would be nice if somebody fixed it 
before it gets sent upstream for real.

Basically the problem is that the opcodes chosen for many of the new 
branch instructions conflict with existing opcodes used by other 
processors (i.e. OCTEON), so there are multiple case labels with the 
same value in several places.

I attached a patch that fixes the problems for me, but you may be able 
to come up with a better approach. :-)

David Daney

On 01/16/2015 02:48 AM, Markos Chandras wrote:
> Hi,
>
> This is the v2 of the MIPS R6 patchset I posted a month ago[1].
> I have addressed most of the issues. Most notably:
>
> * Rebased onto v3.19-rc4
> * Use the "ZC" constraints for the R6 LL/ZC atomics introduced in GCC 4.9
> * Code simplifications as suggested by Sergei Shtylyov and David Daney
> * Add FP ABI improvement necessary for R6 userland to work with the latest
>    tools.
> * Code fixes.
> * A couple of unrelated commits are included as well (ie s/addi/addiu/, FP fixes,
> etc. I will talk to Ralf and see if we need to merge them separately or not.
>
> A couple of things haven't been addressed on purpose:
>
> * The QEMU patches are still needed. The PRPL QEMU has changed since then
> to use the I6400[2] PRID for mips64r6[3] but mips32r6 remains the same.
> This means that for mips64r6 to boot, you need to modify your PRPL tree to use
> the old PRID definition even for the I6400 cpu until there is proper support in
> the kernel. The generic QEMU PRID is also used by QEMU R2-generic cpu
> implementations as well.
>
> The new patches are available in my git tree[4].
>
> [1]: http://www.linux-mips.org/archives/linux-mips/2014-12/msg00222.html
> [2]: http://www.imgtec.com/mips/warrior/iclass.asp
> [3]: https://github.com/prplfoundation/qemu/commit/4473b4492ddc9c90be85d11db7029fc9bbfd805a
> [4]: git://git.linux-mips.org/pub/scm/mchandras/linux.git 3.19-r6-rfc-1
>
>
> Leonid Yegoshin (21):
>    MIPS: Add generic QEMU PRid and cpu type identifiers
>    MIPS: Add cases for CPU_QEMU_GENERIC
>    MIPS: Add MIPS generic QEMU 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: kernel: unaligned: Add support for the MIPS R6
>    MIPS: lib: memcpy: Add MIPS R6 support
>    MIPS: lib: memset: Add MIPS R6 support
>    MIPS: mm: tlbex: Use cpu_has_mips_r2_exec_hazard for the EHB
>      instruction
>    MIPS: kernel: mips-r2-to-r6-emul: Add R2 emulator for MIPS R6
>
> Markos Chandras (49):
>    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: Use the new "ZC" constraint for MIPS R6
>    MIPS: asm: cmpxchg: Update ISA constraints for MIPS R6 support
>    MIPS: asm: atomic: Update ISA constraints for MIPS R6 support
>    MIPS: asm: bitops: Update ISA constraints for MIPS R6 support
>    MIPS: asm: futex: Set the appropriate ISA level for MIPS R6
>    MIPS: asm: spinlock: Replace sub instruction with addiu
>    MIPS: asm: local: Set the appropriate ISA level for MIPS R6
>    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: kernel: syscall: Set the appropriate ISA level for MIPS R6
>    MIPS: mm: page: Add MIPS R6 support
>    MIPS: mm: c-r4k: Set the correct ISA level
>    MIPS: mm: scache: Add secondary cache support for MIPS R6 cores
>    MIPS: kernel: 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: Emulate the BC1{EQ,NE}Z FPU instructions
>    MIPS: Emulate the new MIPS R6 B{L,G}Ε{Z,}{AL,}C instructions
>    MIPS: Emulate the new MIPS R6 B{L,G}T{Z,}{AL,}C instructions
>    MIPS: Emulate the new MIPS R6 branch compact (BC) instruction
>    MIPS: Emulate the new MIPS R6 BOVC, BEQC and BEQZALC instructions
>    MIPS: Emulate the new MIPS R6 BNVC, BNEC and BNEZLAC instructions
>    MIPS: Emulate the new MIPS R6 BALC instruction
>    MIPS: Emulate the new MIPS R6 BEQZC and JIC instructions
>    MIPS: Emulate the new MIPS R6 BNEZC and JIALC instructions
>    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: Handle MIPS IV, V and R2 FPU instructions on MIPS R6 as well
>    MIPS: kernel: process: Do not allow FR=0 on MIPS R6
>    MIPS: kernel: elf: Improve the overall ABI and FPU mode checks
>    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              |   13 +-
>   arch/mips/include/asm/bitops.h              |   31 +-
>   arch/mips/include/asm/checksum.h            |    6 +
>   arch/mips/include/asm/cmpxchg.h             |   11 +-
>   arch/mips/include/asm/compiler.h            |   10 +-
>   arch/mips/include/asm/cpu-features.h        |   22 +-
>   arch/mips/include/asm/cpu-type.h            |    7 +
>   arch/mips/include/asm/cpu.h                 |   11 +-
>   arch/mips/include/asm/elf.h                 |   10 +-
>   arch/mips/include/asm/fpu.h                 |    3 +-
>   arch/mips/include/asm/futex.h               |    8 +-
>   arch/mips/include/asm/hazards.h             |    9 +-
>   arch/mips/include/asm/irqflags.h            |    6 +-
>   arch/mips/include/asm/local.h               |    4 +-
>   arch/mips/include/asm/mips-r2-to-r6-emul.h  |   96 ++
>   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            |    2 +-
>   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           |   24 +-
>   arch/mips/kernel/Makefile                   |    2 +
>   arch/mips/kernel/asm-offsets.c              |    1 +
>   arch/mips/kernel/branch.c                   |  283 +++-
>   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                |   27 +-
>   arch/mips/kernel/elf.c                      |  284 ++--
>   arch/mips/kernel/entry.S                    |   23 +-
>   arch/mips/kernel/genex.S                    |    2 +-
>   arch/mips/kernel/idle.c                     |    1 +
>   arch/mips/kernel/mips-r2-to-r6-emul.c       | 2378 +++++++++++++++++++++++++++
>   arch/mips/kernel/mips_ksyms.c               |    2 +
>   arch/mips/kernel/proc.c                     |    8 +-
>   arch/mips/kernel/process.c                  |    4 +
>   arch/mips/kernel/r4k_fpu.S                  |   12 +-
>   arch/mips/kernel/r4k_switch.S               |   14 +-
>   arch/mips/kernel/spram.c                    |    1 +
>   arch/mips/kernel/syscall.c                  |    2 +-
>   arch/mips/kernel/traps.c                    |   41 +-
>   arch/mips/kernel/unaligned.c                |  390 ++++-
>   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                 |  158 +-
>   arch/mips/mm/c-r4k.c                        |    6 +-
>   arch/mips/mm/page.c                         |   20 +-
>   arch/mips/mm/sc-mips.c                      |    4 +-
>   arch/mips/mm/tlbex.c                        |    7 +-
>   arch/mips/mm/uasm-mips.c                    |   32 +
>   arch/mips/mm/uasm.c                         |   13 +-
>   62 files changed, 4281 insertions(+), 287 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
>


[-- Attachment #2: fix-r6.patch --]
[-- Type: text/x-patch, Size: 1239 bytes --]

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 248f91b..22d4abe 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -782,6 +782,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 		regs->cp0_epc = epc;
 		break;
 #endif
+#if 0
 	case bc6_op:
 		/* Only valid for MIPS R6 */
 		if (!cpu_has_mips_r6) {
@@ -833,6 +834,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 			regs->regs[31] = epc + 4;
 		regs->cp0_epc += 8;
 		break;
+#endif
 	}
 
 	return ret;
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index acd3172..0bd9e4d 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -624,6 +624,7 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 				dec_insn.pc_inc +
 				dec_insn.next_pc_inc;
 		return 1;
+#if 0
 	case bc6_op:
 		/*
 		 * Only valid for MIPS R6 but we can still end up
@@ -670,6 +671,7 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 			dec_insn.next_pc_inc;
 
 		return 1;
+#endif
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
 	case lwc2_op: /* This is bbit0 on Octeon */
 		if ((regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt)) == 0)

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

* Re: [PATCH RFC v2 00/70] Add MIPS R6 support
@ 2015-02-12 23:12   ` David Daney
  0 siblings, 0 replies; 262+ messages in thread
From: David Daney @ 2015-02-12 23:12 UTC (permalink / raw)
  To: Markos Chandras, Ralf Baechle; +Cc: linux-mips, Matthew Fortune

[-- Attachment #1: Type: text/plain, Size: 10256 bytes --]

It looks like Ralf did a preliminary merge of this patch set to 
mips-for-linux-next.

Unfortunatly there are several patches that break compilation of 
existing code, especially OCTEON.  It would be nice if somebody fixed it 
before it gets sent upstream for real.

Basically the problem is that the opcodes chosen for many of the new 
branch instructions conflict with existing opcodes used by other 
processors (i.e. OCTEON), so there are multiple case labels with the 
same value in several places.

I attached a patch that fixes the problems for me, but you may be able 
to come up with a better approach. :-)

David Daney

On 01/16/2015 02:48 AM, Markos Chandras wrote:
> Hi,
>
> This is the v2 of the MIPS R6 patchset I posted a month ago[1].
> I have addressed most of the issues. Most notably:
>
> * Rebased onto v3.19-rc4
> * Use the "ZC" constraints for the R6 LL/ZC atomics introduced in GCC 4.9
> * Code simplifications as suggested by Sergei Shtylyov and David Daney
> * Add FP ABI improvement necessary for R6 userland to work with the latest
>    tools.
> * Code fixes.
> * A couple of unrelated commits are included as well (ie s/addi/addiu/, FP fixes,
> etc. I will talk to Ralf and see if we need to merge them separately or not.
>
> A couple of things haven't been addressed on purpose:
>
> * The QEMU patches are still needed. The PRPL QEMU has changed since then
> to use the I6400[2] PRID for mips64r6[3] but mips32r6 remains the same.
> This means that for mips64r6 to boot, you need to modify your PRPL tree to use
> the old PRID definition even for the I6400 cpu until there is proper support in
> the kernel. The generic QEMU PRID is also used by QEMU R2-generic cpu
> implementations as well.
>
> The new patches are available in my git tree[4].
>
> [1]: http://www.linux-mips.org/archives/linux-mips/2014-12/msg00222.html
> [2]: http://www.imgtec.com/mips/warrior/iclass.asp
> [3]: https://github.com/prplfoundation/qemu/commit/4473b4492ddc9c90be85d11db7029fc9bbfd805a
> [4]: git://git.linux-mips.org/pub/scm/mchandras/linux.git 3.19-r6-rfc-1
>
>
> Leonid Yegoshin (21):
>    MIPS: Add generic QEMU PRid and cpu type identifiers
>    MIPS: Add cases for CPU_QEMU_GENERIC
>    MIPS: Add MIPS generic QEMU 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: kernel: unaligned: Add support for the MIPS R6
>    MIPS: lib: memcpy: Add MIPS R6 support
>    MIPS: lib: memset: Add MIPS R6 support
>    MIPS: mm: tlbex: Use cpu_has_mips_r2_exec_hazard for the EHB
>      instruction
>    MIPS: kernel: mips-r2-to-r6-emul: Add R2 emulator for MIPS R6
>
> Markos Chandras (49):
>    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: Use the new "ZC" constraint for MIPS R6
>    MIPS: asm: cmpxchg: Update ISA constraints for MIPS R6 support
>    MIPS: asm: atomic: Update ISA constraints for MIPS R6 support
>    MIPS: asm: bitops: Update ISA constraints for MIPS R6 support
>    MIPS: asm: futex: Set the appropriate ISA level for MIPS R6
>    MIPS: asm: spinlock: Replace sub instruction with addiu
>    MIPS: asm: local: Set the appropriate ISA level for MIPS R6
>    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: kernel: syscall: Set the appropriate ISA level for MIPS R6
>    MIPS: mm: page: Add MIPS R6 support
>    MIPS: mm: c-r4k: Set the correct ISA level
>    MIPS: mm: scache: Add secondary cache support for MIPS R6 cores
>    MIPS: kernel: 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: Emulate the BC1{EQ,NE}Z FPU instructions
>    MIPS: Emulate the new MIPS R6 B{L,G}Ε{Z,}{AL,}C instructions
>    MIPS: Emulate the new MIPS R6 B{L,G}T{Z,}{AL,}C instructions
>    MIPS: Emulate the new MIPS R6 branch compact (BC) instruction
>    MIPS: Emulate the new MIPS R6 BOVC, BEQC and BEQZALC instructions
>    MIPS: Emulate the new MIPS R6 BNVC, BNEC and BNEZLAC instructions
>    MIPS: Emulate the new MIPS R6 BALC instruction
>    MIPS: Emulate the new MIPS R6 BEQZC and JIC instructions
>    MIPS: Emulate the new MIPS R6 BNEZC and JIALC instructions
>    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: Handle MIPS IV, V and R2 FPU instructions on MIPS R6 as well
>    MIPS: kernel: process: Do not allow FR=0 on MIPS R6
>    MIPS: kernel: elf: Improve the overall ABI and FPU mode checks
>    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              |   13 +-
>   arch/mips/include/asm/bitops.h              |   31 +-
>   arch/mips/include/asm/checksum.h            |    6 +
>   arch/mips/include/asm/cmpxchg.h             |   11 +-
>   arch/mips/include/asm/compiler.h            |   10 +-
>   arch/mips/include/asm/cpu-features.h        |   22 +-
>   arch/mips/include/asm/cpu-type.h            |    7 +
>   arch/mips/include/asm/cpu.h                 |   11 +-
>   arch/mips/include/asm/elf.h                 |   10 +-
>   arch/mips/include/asm/fpu.h                 |    3 +-
>   arch/mips/include/asm/futex.h               |    8 +-
>   arch/mips/include/asm/hazards.h             |    9 +-
>   arch/mips/include/asm/irqflags.h            |    6 +-
>   arch/mips/include/asm/local.h               |    4 +-
>   arch/mips/include/asm/mips-r2-to-r6-emul.h  |   96 ++
>   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            |    2 +-
>   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           |   24 +-
>   arch/mips/kernel/Makefile                   |    2 +
>   arch/mips/kernel/asm-offsets.c              |    1 +
>   arch/mips/kernel/branch.c                   |  283 +++-
>   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                |   27 +-
>   arch/mips/kernel/elf.c                      |  284 ++--
>   arch/mips/kernel/entry.S                    |   23 +-
>   arch/mips/kernel/genex.S                    |    2 +-
>   arch/mips/kernel/idle.c                     |    1 +
>   arch/mips/kernel/mips-r2-to-r6-emul.c       | 2378 +++++++++++++++++++++++++++
>   arch/mips/kernel/mips_ksyms.c               |    2 +
>   arch/mips/kernel/proc.c                     |    8 +-
>   arch/mips/kernel/process.c                  |    4 +
>   arch/mips/kernel/r4k_fpu.S                  |   12 +-
>   arch/mips/kernel/r4k_switch.S               |   14 +-
>   arch/mips/kernel/spram.c                    |    1 +
>   arch/mips/kernel/syscall.c                  |    2 +-
>   arch/mips/kernel/traps.c                    |   41 +-
>   arch/mips/kernel/unaligned.c                |  390 ++++-
>   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                 |  158 +-
>   arch/mips/mm/c-r4k.c                        |    6 +-
>   arch/mips/mm/page.c                         |   20 +-
>   arch/mips/mm/sc-mips.c                      |    4 +-
>   arch/mips/mm/tlbex.c                        |    7 +-
>   arch/mips/mm/uasm-mips.c                    |   32 +
>   arch/mips/mm/uasm.c                         |   13 +-
>   62 files changed, 4281 insertions(+), 287 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
>


[-- Attachment #2: fix-r6.patch --]
[-- Type: text/x-patch, Size: 1239 bytes --]

diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 248f91b..22d4abe 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -782,6 +782,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 		regs->cp0_epc = epc;
 		break;
 #endif
+#if 0
 	case bc6_op:
 		/* Only valid for MIPS R6 */
 		if (!cpu_has_mips_r6) {
@@ -833,6 +834,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
 			regs->regs[31] = epc + 4;
 		regs->cp0_epc += 8;
 		break;
+#endif
 	}
 
 	return ret;
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index acd3172..0bd9e4d 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -624,6 +624,7 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 				dec_insn.pc_inc +
 				dec_insn.next_pc_inc;
 		return 1;
+#if 0
 	case bc6_op:
 		/*
 		 * Only valid for MIPS R6 but we can still end up
@@ -670,6 +671,7 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 			dec_insn.next_pc_inc;
 
 		return 1;
+#endif
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
 	case lwc2_op: /* This is bbit0 on Octeon */
 		if ((regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt)) == 0)

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

* Re: [PATCH RFC v2 41/70] MIPS: mm: tlbex: Use cpu_has_mips_r2_exec_hazard for the EHB instruction
  2015-01-16 10:49   ` Markos Chandras
  (?)
@ 2015-02-23 22:03   ` David Daney
  2015-02-23 22:07     ` David Daney
  2015-02-24  0:33     ` Maciej W. Rozycki
  -1 siblings, 2 replies; 262+ messages in thread
From: David Daney @ 2015-02-23 22:03 UTC (permalink / raw)
  To: Markos Chandras, Ralf Baechle; +Cc: linux-mips, Leonid Yegoshin

On 01/16/2015 02:49 AM, Markos Chandras wrote:
> From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
>
> MIPS uses the cpu_has_mips_r2_exec_hazard macro to determine whether the
> EHB instruction is available or not. This is necessary for MIPS R6
> which also supports the EHB instruction.
>
> Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>

For the version of this patch currently in mips-for-linux-next: NACK

There are two problems:

1) It breaks OCTEON, which will now crash in early boot with:

   Kernel panic - not syncing: No TLB refill handler yet (CPU type: 80)

2) The logic is broken.

The meaning of cpu_has_mips_r2_exec_hazard is that the EHB instruction 
is required.  You change the meaning to be that EHB is part of the ISA.

Can we get this patch reverted from mips-for-linux-next?

David Daney


> ---
>   arch/mips/mm/tlbex.c | 6 +++---
>   1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
> index ff8d99ce3b9b..d75ff73a2012 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_exec_hazard) {
>   		/*
>   		 * The architecture spec says an ehb is required here,
>   		 * but a number of cores do not have the hazard and
> @@ -1953,7 +1953,7 @@ static void build_r4000_tlb_load_handler(void)
>
>   		switch (current_cpu_type()) {
>   		default:
> -			if (cpu_has_mips_r2) {
> +			if (cpu_has_mips_r2_exec_hazard) {
>   				uasm_i_ehb(&p);
>
>   		case CPU_CAVIUM_OCTEON:
> @@ -2020,7 +2020,7 @@ static void build_r4000_tlb_load_handler(void)
>
>   		switch (current_cpu_type()) {
>   		default:
> -			if (cpu_has_mips_r2) {
> +			if (cpu_has_mips_r2_exec_hazard) {
>   				uasm_i_ehb(&p);
>
>   		case CPU_CAVIUM_OCTEON:
>

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

* Re: [PATCH RFC v2 41/70] MIPS: mm: tlbex: Use cpu_has_mips_r2_exec_hazard for the EHB instruction
  2015-02-23 22:03   ` David Daney
@ 2015-02-23 22:07     ` David Daney
  2015-02-24  0:33     ` Maciej W. Rozycki
  1 sibling, 0 replies; 262+ messages in thread
From: David Daney @ 2015-02-23 22:07 UTC (permalink / raw)
  To: Markos Chandras, Ralf Baechle; +Cc: linux-mips, Leonid Yegoshin

On 02/23/2015 02:03 PM, David Daney wrote:
> On 01/16/2015 02:49 AM, Markos Chandras wrote:
>> From: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
>>
>> MIPS uses the cpu_has_mips_r2_exec_hazard macro to determine whether the
>> EHB instruction is available or not. This is necessary for MIPS R6
>> which also supports the EHB instruction.
>>
>> Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
>> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
>
> For the version of this patch currently in mips-for-linux-next: NACK
>

FYI, that would be: Commit id: 77f3ee59ee7cfe19e0ee48d9a990c7967fbfcbed

> There are two problems:
>
> 1) It breaks OCTEON, which will now crash in early boot with:
>
>    Kernel panic - not syncing: No TLB refill handler yet (CPU type: 80)
>
> 2) The logic is broken.
>
> The meaning of cpu_has_mips_r2_exec_hazard is that the EHB instruction
> is required.  You change the meaning to be that EHB is part of the ISA.
>
> Can we get this patch reverted from mips-for-linux-next?
>
> David Daney
>
>
>> ---
>>   arch/mips/mm/tlbex.c | 6 +++---
>>   1 file changed, 3 insertions(+), 3 deletions(-)
>>
>> diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
>> index ff8d99ce3b9b..d75ff73a2012 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_exec_hazard) {
>>           /*
>>            * The architecture spec says an ehb is required here,
>>            * but a number of cores do not have the hazard and
>> @@ -1953,7 +1953,7 @@ static void build_r4000_tlb_load_handler(void)
>>
>>           switch (current_cpu_type()) {
>>           default:
>> -            if (cpu_has_mips_r2) {
>> +            if (cpu_has_mips_r2_exec_hazard) {
>>                   uasm_i_ehb(&p);
>>
>>           case CPU_CAVIUM_OCTEON:
>> @@ -2020,7 +2020,7 @@ static void build_r4000_tlb_load_handler(void)
>>
>>           switch (current_cpu_type()) {
>>           default:
>> -            if (cpu_has_mips_r2) {
>> +            if (cpu_has_mips_r2_exec_hazard) {
>>                   uasm_i_ehb(&p);
>>
>>           case CPU_CAVIUM_OCTEON:
>>
>

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

* Re: [PATCH RFC v2 41/70] MIPS: mm: tlbex: Use cpu_has_mips_r2_exec_hazard for the EHB instruction
  2015-02-23 22:03   ` David Daney
  2015-02-23 22:07     ` David Daney
@ 2015-02-24  0:33     ` Maciej W. Rozycki
  2015-02-24  0:53       ` David Daney
  1 sibling, 1 reply; 262+ messages in thread
From: Maciej W. Rozycki @ 2015-02-24  0:33 UTC (permalink / raw)
  To: David Daney; +Cc: Markos Chandras, Ralf Baechle, linux-mips, Leonid Yegoshin

On Mon, 23 Feb 2015, David Daney wrote:

> For the version of this patch currently in mips-for-linux-next: NACK
> 
> There are two problems:
> 
> 1) It breaks OCTEON, which will now crash in early boot with:
> 
>   Kernel panic - not syncing: No TLB refill handler yet (CPU type: 80)
> 
> 2) The logic is broken.
> 
> The meaning of cpu_has_mips_r2_exec_hazard is that the EHB instruction is
> required.  You change the meaning to be that EHB is part of the ISA.

 Well, the macro is nowhere used I'm afraid, its last use was dropped with 
625c0a21, so it's rather difficult to assume any meaning to the macro.

 Also the intended meaning is clear from the commit message of 41f0e4d0, 
where the macro comes from, however unfortunately not from the definition 
of the macro itself.  It's a pity that along your change you did not 
include an explanatory note in arch/mips/include/asm/cpu-features.h.

 Finally, I think the change made to `build_tlb_write_entry' with 625c0a21 
may need to be reconsidered, as may perhaps the name itself of 
`cpu_has_mips_r2_exec_hazard' (why is it this place only that the macro 
was used? -- would it be better called `cpu_has_tlbw_exec_hazard' 
instead?), and then we'll need `cpu_has_ehb' or suchlike across all the 
other places.

  Maciej

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

* Re: [PATCH RFC v2 41/70] MIPS: mm: tlbex: Use cpu_has_mips_r2_exec_hazard for the EHB instruction
  2015-02-24  0:33     ` Maciej W. Rozycki
@ 2015-02-24  0:53       ` David Daney
  0 siblings, 0 replies; 262+ messages in thread
From: David Daney @ 2015-02-24  0:53 UTC (permalink / raw)
  To: Maciej W. Rozycki
  Cc: Markos Chandras, Ralf Baechle, linux-mips, Leonid Yegoshin

On 02/23/2015 04:33 PM, Maciej W. Rozycki wrote:
> On Mon, 23 Feb 2015, David Daney wrote:
>
>> For the version of this patch currently in mips-for-linux-next: NACK
>>
>> There are two problems:
>>
>> 1) It breaks OCTEON, which will now crash in early boot with:
>>
>>    Kernel panic - not syncing: No TLB refill handler yet (CPU type: 80)
>>
>> 2) The logic is broken.
>>
>> The meaning of cpu_has_mips_r2_exec_hazard is that the EHB instruction is
>> required.  You change the meaning to be that EHB is part of the ISA.
>
>   Well, the macro is nowhere used I'm afraid, its last use was dropped with
> 625c0a21, so it's rather difficult to assume any meaning to the macro.
>
>   Also the intended meaning is clear from the commit message of 41f0e4d0,
> where the macro comes from, however unfortunately not from the definition
> of the macro itself.  It's a pity that along your change you did not
> include an explanatory note in arch/mips/include/asm/cpu-features.h.
>
>   Finally, I think the change made to `build_tlb_write_entry' with 625c0a21
> may need to be reconsidered, as may perhaps the name itself of
> `cpu_has_mips_r2_exec_hazard' (why is it this place only that the macro
> was used? -- would it be better called `cpu_has_tlbw_exec_hazard'
> instead?), and then we'll need `cpu_has_ehb' or suchlike across all the
> other places.
>

I agree with all the points you make.

The parts of tlbex.c dealing with EHB are an inconsistent mess.  Since 
it is one of my favorite playgrounds I am probably as guilty as anyone.

The idea behind `cpu_has_mips_r2_exec_hazard' (although a better name 
could have been chosen, as you point out) was to get rid of the case 
statements based on CPU model in tlbex.c, and move the logic into the 
individual cpu-feature files.  I thought this would make it easier to 
add new CPUs in the future, but it turns out that now we have a random 
assortment of both :-(.

David Daney

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

* Re: [PATCH v3] MIPS: kernel: elf: Improve the overall ABI and FPU mode checks
@ 2015-02-24 13:17         ` Måns Rullgård
  0 siblings, 0 replies; 262+ messages in thread
From: Måns Rullgård @ 2015-02-24 13:17 UTC (permalink / raw)
  To: Markos Chandras; +Cc: linux-mips, Matthew Fortune, Paul Burton

Markos Chandras <markos.chandras@imgtec.com> writes:

> The previous implementation did not cover all possible FPU combinations
> and it silently allowed ABI incompatible objects to be loaded with the
> wrong ABI. For example, the previous logic would set the FP_64 ABI as
> the matching ABI for an FP_XX object combined with an FP_64A object.
> This was wrong, and the matching ABI should have been FP_64A.
> The previous logic is now replaced with a new one which determines
> the appropriate FPU mode to be used rather than the FP ABI. This has
> the advantage that the entire logic is much simpler since it is the FPU
> mode we are interested in rather than the FP ABI resulting to code
> simplifications.
>
> Cc: Matthew Fortune <Matthew.Fortune@imgtec.com>
> Cc: Paul Burton <paul.burton@imgtec.com>
> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
> ---
>  arch/mips/include/asm/elf.h |  10 +-
>  arch/mips/kernel/elf.c      | 303 +++++++++++++++++++++++++++-----------------
>  2 files changed, 194 insertions(+), 119 deletions(-)

This patch (well, the variant that made it into 4.0-rc1) breaks
MIPS_ABI_FP_DOUBLE (the gcc default) apps on MIPS32.

> +void mips_set_personality_fp(struct arch_elf_state *state)
> +{
> +	/*
> +	 * This function is only ever called for O32 ELFs so we should
> +	 * not be worried about N32/N64 binaries.
> +	 */
>
> -	case MIPS_ABI_FP_XX:
> -	case MIPS_ABI_FP_ANY:
> -		if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
> -			set_thread_flag(TIF_32BIT_FPREGS);
> -		else
> -			clear_thread_flag(TIF_32BIT_FPREGS);
> +	if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
> +		return;

The problem is here.  In a 32-bit configuration, MIPS_O32_FP64_SUPPORT
is always disabled, so the FP mode doesn't get set.  Simply deleting
those two lines makes things work again, but that's probably not the
right fix.

> -		clear_thread_flag(TIF_HYBRID_FPREGS);
> +	switch (state->overall_fp_mode) {
> +	case FP_FRE:
> +		set_thread_fp_mode(1, 0);
> +		break;
> +	case FP_FR0:
> +		set_thread_fp_mode(0, 1);
> +		break;
> +	case FP_FR1:
> +		set_thread_fp_mode(0, 0);
>  		break;
> -
>  	default:
> -	case FP_ERROR:
>  		BUG();
>  	}
>  }
> -- 
> 2.2.2
>

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

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

* Re: [PATCH v3] MIPS: kernel: elf: Improve the overall ABI and FPU mode checks
@ 2015-02-24 13:17         ` Måns Rullgård
  0 siblings, 0 replies; 262+ messages in thread
From: Måns Rullgård @ 2015-02-24 13:17 UTC (permalink / raw)
  To: Markos Chandras; +Cc: linux-mips, Matthew Fortune, Paul Burton

Markos Chandras <markos.chandras@imgtec.com> writes:

> The previous implementation did not cover all possible FPU combinations
> and it silently allowed ABI incompatible objects to be loaded with the
> wrong ABI. For example, the previous logic would set the FP_64 ABI as
> the matching ABI for an FP_XX object combined with an FP_64A object.
> This was wrong, and the matching ABI should have been FP_64A.
> The previous logic is now replaced with a new one which determines
> the appropriate FPU mode to be used rather than the FP ABI. This has
> the advantage that the entire logic is much simpler since it is the FPU
> mode we are interested in rather than the FP ABI resulting to code
> simplifications.
>
> Cc: Matthew Fortune <Matthew.Fortune@imgtec.com>
> Cc: Paul Burton <paul.burton@imgtec.com>
> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
> ---
>  arch/mips/include/asm/elf.h |  10 +-
>  arch/mips/kernel/elf.c      | 303 +++++++++++++++++++++++++++-----------------
>  2 files changed, 194 insertions(+), 119 deletions(-)

This patch (well, the variant that made it into 4.0-rc1) breaks
MIPS_ABI_FP_DOUBLE (the gcc default) apps on MIPS32.

> +void mips_set_personality_fp(struct arch_elf_state *state)
> +{
> +	/*
> +	 * This function is only ever called for O32 ELFs so we should
> +	 * not be worried about N32/N64 binaries.
> +	 */
>
> -	case MIPS_ABI_FP_XX:
> -	case MIPS_ABI_FP_ANY:
> -		if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
> -			set_thread_flag(TIF_32BIT_FPREGS);
> -		else
> -			clear_thread_flag(TIF_32BIT_FPREGS);
> +	if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
> +		return;

The problem is here.  In a 32-bit configuration, MIPS_O32_FP64_SUPPORT
is always disabled, so the FP mode doesn't get set.  Simply deleting
those two lines makes things work again, but that's probably not the
right fix.

> -		clear_thread_flag(TIF_HYBRID_FPREGS);
> +	switch (state->overall_fp_mode) {
> +	case FP_FRE:
> +		set_thread_fp_mode(1, 0);
> +		break;
> +	case FP_FR0:
> +		set_thread_fp_mode(0, 1);
> +		break;
> +	case FP_FR1:
> +		set_thread_fp_mode(0, 0);
>  		break;
> -
>  	default:
> -	case FP_ERROR:
>  		BUG();
>  	}
>  }
> -- 
> 2.2.2
>

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

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

* Re: [PATCH v3] MIPS: kernel: elf: Improve the overall ABI and FPU mode checks
@ 2015-02-24 13:52           ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-02-24 13:52 UTC (permalink / raw)
  To: Måns Rullgård; +Cc: linux-mips, Matthew Fortune, Paul Burton

Hi,

On Tue, Feb 24, 2015 at 01:17:33PM +0000, Måns Rullgård wrote:
> This patch (well, the variant that made it into 4.0-rc1) breaks
> MIPS_ABI_FP_DOUBLE (the gcc default) apps on MIPS32.
> 

Thanks for the report.

> > +void mips_set_personality_fp(struct arch_elf_state *state)
> > +{
> > +	/*
> > +	 * This function is only ever called for O32 ELFs so we should
> > +	 * not be worried about N32/N64 binaries.
> > +	 */
> >
> > -	case MIPS_ABI_FP_XX:
> > -	case MIPS_ABI_FP_ANY:
> > -		if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
> > -			set_thread_flag(TIF_32BIT_FPREGS);
> > -		else
> > -			clear_thread_flag(TIF_32BIT_FPREGS);
> > +	if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
> > +		return;
> 
> The problem is here.  In a 32-bit configuration, MIPS_O32_FP64_SUPPORT
> is always disabled, so the FP mode doesn't get set.  Simply deleting
> those two lines makes things work again, but that's probably not the
> right fix.
> 
I had the impression that the loader would have set the FP mode earlier on.
But that only may happen with the latest version of the tools.

Perhaps instead of dropping these two lines we need a similar check on the
arch_elf_pt_proc so we don't mess with the default FPI abi?

Having said that, dropping these two lines should be fine, it just means you
do a little bit of extra work when loading your ELF files to check for ABI
compatibility which shouldn't matter in your case.

Matthew what do you think?

-- 
markos

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

* Re: [PATCH v3] MIPS: kernel: elf: Improve the overall ABI and FPU mode checks
@ 2015-02-24 13:52           ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-02-24 13:52 UTC (permalink / raw)
  To: Måns Rullgård; +Cc: linux-mips, Matthew Fortune, Paul Burton

Hi,

On Tue, Feb 24, 2015 at 01:17:33PM +0000, Måns Rullgård wrote:
> This patch (well, the variant that made it into 4.0-rc1) breaks
> MIPS_ABI_FP_DOUBLE (the gcc default) apps on MIPS32.
> 

Thanks for the report.

> > +void mips_set_personality_fp(struct arch_elf_state *state)
> > +{
> > +	/*
> > +	 * This function is only ever called for O32 ELFs so we should
> > +	 * not be worried about N32/N64 binaries.
> > +	 */
> >
> > -	case MIPS_ABI_FP_XX:
> > -	case MIPS_ABI_FP_ANY:
> > -		if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
> > -			set_thread_flag(TIF_32BIT_FPREGS);
> > -		else
> > -			clear_thread_flag(TIF_32BIT_FPREGS);
> > +	if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
> > +		return;
> 
> The problem is here.  In a 32-bit configuration, MIPS_O32_FP64_SUPPORT
> is always disabled, so the FP mode doesn't get set.  Simply deleting
> those two lines makes things work again, but that's probably not the
> right fix.
> 
I had the impression that the loader would have set the FP mode earlier on.
But that only may happen with the latest version of the tools.

Perhaps instead of dropping these two lines we need a similar check on the
arch_elf_pt_proc so we don't mess with the default FPI abi?

Having said that, dropping these two lines should be fine, it just means you
do a little bit of extra work when loading your ELF files to check for ABI
compatibility which shouldn't matter in your case.

Matthew what do you think?

-- 
markos

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

* Re: [PATCH v3] MIPS: kernel: elf: Improve the overall ABI and FPU mode checks
@ 2015-02-24 14:06             ` Måns Rullgård
  0 siblings, 0 replies; 262+ messages in thread
From: Måns Rullgård @ 2015-02-24 14:06 UTC (permalink / raw)
  To: Markos Chandras; +Cc: linux-mips, Matthew Fortune, Paul Burton

Markos Chandras <markos.chandras@imgtec.com> writes:

> Hi,
>
> On Tue, Feb 24, 2015 at 01:17:33PM +0000, Måns Rullgård wrote:
>> This patch (well, the variant that made it into 4.0-rc1) breaks
>> MIPS_ABI_FP_DOUBLE (the gcc default) apps on MIPS32.
>> 
>
> Thanks for the report.
>
>> > +void mips_set_personality_fp(struct arch_elf_state *state)
>> > +{
>> > +	/*
>> > +	 * This function is only ever called for O32 ELFs so we should
>> > +	 * not be worried about N32/N64 binaries.
>> > +	 */
>> >
>> > -	case MIPS_ABI_FP_XX:
>> > -	case MIPS_ABI_FP_ANY:
>> > -		if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
>> > -			set_thread_flag(TIF_32BIT_FPREGS);
>> > -		else
>> > -			clear_thread_flag(TIF_32BIT_FPREGS);
>> > +	if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
>> > +		return;
>> 
>> The problem is here.  In a 32-bit configuration, MIPS_O32_FP64_SUPPORT
>> is always disabled, so the FP mode doesn't get set.  Simply deleting
>> those two lines makes things work again, but that's probably not the
>> right fix.
>> 
> I had the impression that the loader would have set the FP mode earlier on.
> But that only may happen with the latest version of the tools.
>
> Perhaps instead of dropping these two lines we need a similar check on the
> arch_elf_pt_proc so we don't mess with the default FPI abi?
>
> Having said that, dropping these two lines should be fine, it just means you
> do a little bit of extra work when loading your ELF files to check for ABI
> compatibility which shouldn't matter in your case.

There's another early return like this in arch_check_elf() which should
probably go as well, or everything will end up with the default mode.

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

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

* Re: [PATCH v3] MIPS: kernel: elf: Improve the overall ABI and FPU mode checks
@ 2015-02-24 14:06             ` Måns Rullgård
  0 siblings, 0 replies; 262+ messages in thread
From: Måns Rullgård @ 2015-02-24 14:06 UTC (permalink / raw)
  To: Markos Chandras; +Cc: linux-mips, Matthew Fortune, Paul Burton

Markos Chandras <markos.chandras@imgtec.com> writes:

> Hi,
>
> On Tue, Feb 24, 2015 at 01:17:33PM +0000, Måns Rullgård wrote:
>> This patch (well, the variant that made it into 4.0-rc1) breaks
>> MIPS_ABI_FP_DOUBLE (the gcc default) apps on MIPS32.
>> 
>
> Thanks for the report.
>
>> > +void mips_set_personality_fp(struct arch_elf_state *state)
>> > +{
>> > +	/*
>> > +	 * This function is only ever called for O32 ELFs so we should
>> > +	 * not be worried about N32/N64 binaries.
>> > +	 */
>> >
>> > -	case MIPS_ABI_FP_XX:
>> > -	case MIPS_ABI_FP_ANY:
>> > -		if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
>> > -			set_thread_flag(TIF_32BIT_FPREGS);
>> > -		else
>> > -			clear_thread_flag(TIF_32BIT_FPREGS);
>> > +	if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
>> > +		return;
>> 
>> The problem is here.  In a 32-bit configuration, MIPS_O32_FP64_SUPPORT
>> is always disabled, so the FP mode doesn't get set.  Simply deleting
>> those two lines makes things work again, but that's probably not the
>> right fix.
>> 
> I had the impression that the loader would have set the FP mode earlier on.
> But that only may happen with the latest version of the tools.
>
> Perhaps instead of dropping these two lines we need a similar check on the
> arch_elf_pt_proc so we don't mess with the default FPI abi?
>
> Having said that, dropping these two lines should be fine, it just means you
> do a little bit of extra work when loading your ELF files to check for ABI
> compatibility which shouldn't matter in your case.

There's another early return like this in arch_check_elf() which should
probably go as well, or everything will end up with the default mode.

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

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

* RE: [PATCH v3] MIPS: kernel: elf: Improve the overall ABI and FPU mode checks
  2015-02-24 14:06             ` Måns Rullgård
  (?)
@ 2015-02-24 14:26             ` Matthew Fortune
  2015-02-26  8:59               ` Markos Chandras
  -1 siblings, 1 reply; 262+ messages in thread
From: Matthew Fortune @ 2015-02-24 14:26 UTC (permalink / raw)
  To: Måns Rullgård, Markos Chandras; +Cc: linux-mips, Paul Burton

Måns Rullgård <mans@mansr.com> writes:
> Markos Chandras <markos.chandras@imgtec.com> writes:
> 
> > Hi,
> >
> > On Tue, Feb 24, 2015 at 01:17:33PM +0000, Måns Rullgård wrote:
> >> This patch (well, the variant that made it into 4.0-rc1) breaks
> >> MIPS_ABI_FP_DOUBLE (the gcc default) apps on MIPS32.
> >>
> >
> > Thanks for the report.
> >
> >> > +void mips_set_personality_fp(struct arch_elf_state *state) {
> >> > +	/*
> >> > +	 * This function is only ever called for O32 ELFs so we should
> >> > +	 * not be worried about N32/N64 binaries.
> >> > +	 */
> >> >
> >> > -	case MIPS_ABI_FP_XX:
> >> > -	case MIPS_ABI_FP_ANY:
> >> > -		if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
> >> > -			set_thread_flag(TIF_32BIT_FPREGS);
> >> > -		else
> >> > -			clear_thread_flag(TIF_32BIT_FPREGS);
> >> > +	if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
> >> > +		return;
> >>
> >> The problem is here.  In a 32-bit configuration,
> >> MIPS_O32_FP64_SUPPORT is always disabled, so the FP mode doesn't get
> >> set.  Simply deleting those two lines makes things work again, but
> >> that's probably not the right fix.

I don't recall the final decision on default on/off for this option but
IIRC it is going to be off for everything except R6 in the first kernel
version and then turned on by default(/option removed) when the code is
proven for the following kernel version.

> >>
> > I had the impression that the loader would have set the FP mode
> earlier on.
> > But that only may happen with the latest version of the tools.
> >
> > Perhaps instead of dropping these two lines we need a similar check on
> > the arch_elf_pt_proc so we don't mess with the default FPI abi?
> >
> > Having said that, dropping these two lines should be fine, it just
> > means you do a little bit of extra work when loading your ELF files to
> > check for ABI compatibility which shouldn't matter in your case.
> 
> There's another early return like this in arch_check_elf() which should
> probably go as well, or everything will end up with the default mode.

Ironically I discussed these changes with Markos in an attempt to make
all the new changes benign when:

!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT)

Clearly this has backfired. I will have to re-read the version of the code
in 4.0-rc1 to see what is the root cause. The intention was that without
the config option then the kernel would blindly continue to assume that
all O32 binaries would run in the original TIF_32BIT_FPREGS mode. As I
recall, the callers to mips_set_personality_fp were setting this mode
which is why the simple early return was added.

Thanks,
Matthew

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

* Re: [PATCH v3] MIPS: kernel: elf: Improve the overall ABI and FPU mode checks
  2015-02-24 14:26             ` Matthew Fortune
@ 2015-02-26  8:59               ` Markos Chandras
  2015-02-26  9:14                   ` Måns Rullgård
  0 siblings, 1 reply; 262+ messages in thread
From: Markos Chandras @ 2015-02-26  8:59 UTC (permalink / raw)
  To: Matthew Fortune; +Cc: Måns Rullgård, linux-mips, Paul Burton

On Tue, Feb 24, 2015 at 02:26:04PM +0000, Matthew Fortune wrote:
> Måns Rullgård <mans@mansr.com> writes:
> > Markos Chandras <markos.chandras@imgtec.com> writes:
> > 
> > > Hi,
> > >
> > > On Tue, Feb 24, 2015 at 01:17:33PM +0000, Måns Rullgård wrote:
> > >> This patch (well, the variant that made it into 4.0-rc1) breaks
> > >> MIPS_ABI_FP_DOUBLE (the gcc default) apps on MIPS32.
> > >>
> > >
> > > Thanks for the report.
> > >
> > >> > +void mips_set_personality_fp(struct arch_elf_state *state) {
> > >> > +	/*
> > >> > +	 * This function is only ever called for O32 ELFs so we should
> > >> > +	 * not be worried about N32/N64 binaries.
> > >> > +	 */
> > >> >
> > >> > -	case MIPS_ABI_FP_XX:
> > >> > -	case MIPS_ABI_FP_ANY:
> > >> > -		if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
> > >> > -			set_thread_flag(TIF_32BIT_FPREGS);
> > >> > -		else
> > >> > -			clear_thread_flag(TIF_32BIT_FPREGS);
> > >> > +	if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
> > >> > +		return;
> > >>
> > >> The problem is here.  In a 32-bit configuration,
> > >> MIPS_O32_FP64_SUPPORT is always disabled, so the FP mode doesn't get
> > >> set.  Simply deleting those two lines makes things work again, but
> > >> that's probably not the right fix.
> 
> I don't recall the final decision on default on/off for this option but
> IIRC it is going to be off for everything except R6 in the first kernel
> version and then turned on by default(/option removed) when the code is
> proven for the following kernel version.
> 
> > >>
> > > I had the impression that the loader would have set the FP mode
> > earlier on.
> > > But that only may happen with the latest version of the tools.
> > >
> > > Perhaps instead of dropping these two lines we need a similar check on
> > > the arch_elf_pt_proc so we don't mess with the default FPI abi?
> > >
> > > Having said that, dropping these two lines should be fine, it just
> > > means you do a little bit of extra work when loading your ELF files to
> > > check for ABI compatibility which shouldn't matter in your case.
> > 
> > There's another early return like this in arch_check_elf() which should
> > probably go as well, or everything will end up with the default mode.
> 
> Ironically I discussed these changes with Markos in an attempt to make
> all the new changes benign when:
> 
> !config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT)
> 
> Clearly this has backfired. I will have to re-read the version of the code
> in 4.0-rc1 to see what is the root cause. The intention was that without
> the config option then the kernel would blindly continue to assume that
> all O32 binaries would run in the original TIF_32BIT_FPREGS mode. As I
> recall, the callers to mips_set_personality_fp were setting this mode
> which is why the simple early return was added.
> 
> Thanks,
> Matthew

I think I can see what is going on. The problem is that
mips_set_personality_fp() (as already mentioned) is not executed for
!CONFIG_MIPS_O32_FP64_SUPPORT. The reason this is a problem
(i think this could only happen in 64-bit) is that SET_PERSONALITY2
clears all the thread flags related to 32-bit and FPU. The 32-bit flags will
be set again by the SET_PERSONALITY32_O32 but the FPU flags are not since
the entire mips_set_personality_fp() is skipped. While removing the if()
conditional in mips_set_personality_fp() will fix the problem, you rely on
state->overall_fp_mode having a good default value for you case. If not, it will
set the wrong FPU mode. Therefore, I believe the correct fix is either to drop
both CONFIG_MIPS_O32_FP64_SUPPORT or drop the one in mips_set_personality_fp()
and add another one in arch_elf_pt_proc() to set a good default ABI just for
this case and then return.

-- 
markos

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

* Re: [PATCH v3] MIPS: kernel: elf: Improve the overall ABI and FPU mode checks
@ 2015-02-26  9:14                   ` Måns Rullgård
  0 siblings, 0 replies; 262+ messages in thread
From: Måns Rullgård @ 2015-02-26  9:14 UTC (permalink / raw)
  To: Markos Chandras; +Cc: Matthew Fortune, linux-mips, Paul Burton

Markos Chandras <markos.chandras@imgtec.com> writes:

> On Tue, Feb 24, 2015 at 02:26:04PM +0000, Matthew Fortune wrote:
>> Måns Rullgård <mans@mansr.com> writes:
>> > Markos Chandras <markos.chandras@imgtec.com> writes:
>> > 
>> > > Hi,
>> > >
>> > > On Tue, Feb 24, 2015 at 01:17:33PM +0000, Måns Rullgård wrote:
>> > >> This patch (well, the variant that made it into 4.0-rc1) breaks
>> > >> MIPS_ABI_FP_DOUBLE (the gcc default) apps on MIPS32.
>> > >>
>> > >
>> > > Thanks for the report.
>> > >
>> > >> > +void mips_set_personality_fp(struct arch_elf_state *state) {
>> > >> > +	/*
>> > >> > +	 * This function is only ever called for O32 ELFs so we should
>> > >> > +	 * not be worried about N32/N64 binaries.
>> > >> > +	 */
>> > >> >
>> > >> > -	case MIPS_ABI_FP_XX:
>> > >> > -	case MIPS_ABI_FP_ANY:
>> > >> > -		if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
>> > >> > -			set_thread_flag(TIF_32BIT_FPREGS);
>> > >> > -		else
>> > >> > -			clear_thread_flag(TIF_32BIT_FPREGS);
>> > >> > +	if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
>> > >> > +		return;
>> > >>
>> > >> The problem is here.  In a 32-bit configuration,
>> > >> MIPS_O32_FP64_SUPPORT is always disabled, so the FP mode doesn't get
>> > >> set.  Simply deleting those two lines makes things work again, but
>> > >> that's probably not the right fix.
>> 
>> I don't recall the final decision on default on/off for this option but
>> IIRC it is going to be off for everything except R6 in the first kernel
>> version and then turned on by default(/option removed) when the code is
>> proven for the following kernel version.
>> 
>> > >>
>> > > I had the impression that the loader would have set the FP mode
>> > > earlier on.  But that only may happen with the latest version of
>> > > the tools.
>> > >
>> > > Perhaps instead of dropping these two lines we need a similar check on
>> > > the arch_elf_pt_proc so we don't mess with the default FPI abi?
>> > >
>> > > Having said that, dropping these two lines should be fine, it just
>> > > means you do a little bit of extra work when loading your ELF files to
>> > > check for ABI compatibility which shouldn't matter in your case.
>> > 
>> > There's another early return like this in arch_check_elf() which should
>> > probably go as well, or everything will end up with the default mode.
>> 
>> Ironically I discussed these changes with Markos in an attempt to make
>> all the new changes benign when:
>> 
>> !config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT)
>> 
>> Clearly this has backfired. I will have to re-read the version of the code
>> in 4.0-rc1 to see what is the root cause. The intention was that without
>> the config option then the kernel would blindly continue to assume that
>> all O32 binaries would run in the original TIF_32BIT_FPREGS mode. As I
>> recall, the callers to mips_set_personality_fp were setting this mode
>> which is why the simple early return was added.
>> 
>> Thanks,
>> Matthew
>
> I think I can see what is going on. The problem is that
> mips_set_personality_fp() (as already mentioned) is not executed for
> !CONFIG_MIPS_O32_FP64_SUPPORT. The reason this is a problem
> (i think this could only happen in 64-bit)

It's definitely causing problems on my 74Kf system.

> is that SET_PERSONALITY2 clears all the thread flags related to 32-bit
> and FPU. The 32-bit flags will be set again by the
> SET_PERSONALITY32_O32 but the FPU flags are not since the entire
> mips_set_personality_fp() is skipped. While removing the if()
> conditional in mips_set_personality_fp() will fix the problem, you
> rely on state->overall_fp_mode having a good default value for you
> case. If not, it will set the wrong FPU mode.

Yes, I realised this after hitting the send button earlier.

> Therefore, I believe the correct fix is either to drop both
> CONFIG_MIPS_O32_FP64_SUPPORT or drop the one in
> mips_set_personality_fp() and add another one in arch_elf_pt_proc() to
> set a good default ABI just for this case and then return.

Sounds about right.

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

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

* Re: [PATCH v3] MIPS: kernel: elf: Improve the overall ABI and FPU mode checks
@ 2015-02-26  9:14                   ` Måns Rullgård
  0 siblings, 0 replies; 262+ messages in thread
From: Måns Rullgård @ 2015-02-26  9:14 UTC (permalink / raw)
  To: Markos Chandras; +Cc: Matthew Fortune, linux-mips, Paul Burton

Markos Chandras <markos.chandras@imgtec.com> writes:

> On Tue, Feb 24, 2015 at 02:26:04PM +0000, Matthew Fortune wrote:
>> Måns Rullgård <mans@mansr.com> writes:
>> > Markos Chandras <markos.chandras@imgtec.com> writes:
>> > 
>> > > Hi,
>> > >
>> > > On Tue, Feb 24, 2015 at 01:17:33PM +0000, Måns Rullgård wrote:
>> > >> This patch (well, the variant that made it into 4.0-rc1) breaks
>> > >> MIPS_ABI_FP_DOUBLE (the gcc default) apps on MIPS32.
>> > >>
>> > >
>> > > Thanks for the report.
>> > >
>> > >> > +void mips_set_personality_fp(struct arch_elf_state *state) {
>> > >> > +	/*
>> > >> > +	 * This function is only ever called for O32 ELFs so we should
>> > >> > +	 * not be worried about N32/N64 binaries.
>> > >> > +	 */
>> > >> >
>> > >> > -	case MIPS_ABI_FP_XX:
>> > >> > -	case MIPS_ABI_FP_ANY:
>> > >> > -		if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
>> > >> > -			set_thread_flag(TIF_32BIT_FPREGS);
>> > >> > -		else
>> > >> > -			clear_thread_flag(TIF_32BIT_FPREGS);
>> > >> > +	if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
>> > >> > +		return;
>> > >>
>> > >> The problem is here.  In a 32-bit configuration,
>> > >> MIPS_O32_FP64_SUPPORT is always disabled, so the FP mode doesn't get
>> > >> set.  Simply deleting those two lines makes things work again, but
>> > >> that's probably not the right fix.
>> 
>> I don't recall the final decision on default on/off for this option but
>> IIRC it is going to be off for everything except R6 in the first kernel
>> version and then turned on by default(/option removed) when the code is
>> proven for the following kernel version.
>> 
>> > >>
>> > > I had the impression that the loader would have set the FP mode
>> > > earlier on.  But that only may happen with the latest version of
>> > > the tools.
>> > >
>> > > Perhaps instead of dropping these two lines we need a similar check on
>> > > the arch_elf_pt_proc so we don't mess with the default FPI abi?
>> > >
>> > > Having said that, dropping these two lines should be fine, it just
>> > > means you do a little bit of extra work when loading your ELF files to
>> > > check for ABI compatibility which shouldn't matter in your case.
>> > 
>> > There's another early return like this in arch_check_elf() which should
>> > probably go as well, or everything will end up with the default mode.
>> 
>> Ironically I discussed these changes with Markos in an attempt to make
>> all the new changes benign when:
>> 
>> !config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT)
>> 
>> Clearly this has backfired. I will have to re-read the version of the code
>> in 4.0-rc1 to see what is the root cause. The intention was that without
>> the config option then the kernel would blindly continue to assume that
>> all O32 binaries would run in the original TIF_32BIT_FPREGS mode. As I
>> recall, the callers to mips_set_personality_fp were setting this mode
>> which is why the simple early return was added.
>> 
>> Thanks,
>> Matthew
>
> I think I can see what is going on. The problem is that
> mips_set_personality_fp() (as already mentioned) is not executed for
> !CONFIG_MIPS_O32_FP64_SUPPORT. The reason this is a problem
> (i think this could only happen in 64-bit)

It's definitely causing problems on my 74Kf system.

> is that SET_PERSONALITY2 clears all the thread flags related to 32-bit
> and FPU. The 32-bit flags will be set again by the
> SET_PERSONALITY32_O32 but the FPU flags are not since the entire
> mips_set_personality_fp() is skipped. While removing the if()
> conditional in mips_set_personality_fp() will fix the problem, you
> rely on state->overall_fp_mode having a good default value for you
> case. If not, it will set the wrong FPU mode.

Yes, I realised this after hitting the send button earlier.

> Therefore, I believe the correct fix is either to drop both
> CONFIG_MIPS_O32_FP64_SUPPORT or drop the one in
> mips_set_personality_fp() and add another one in arch_elf_pt_proc() to
> set a good default ABI just for this case and then return.

Sounds about right.

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

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

* Re: [PATCH v3] MIPS: kernel: elf: Improve the overall ABI and FPU mode checks
  2015-02-26  9:14                   ` Måns Rullgård
  (?)
@ 2015-02-26  9:24                   ` Markos Chandras
  2015-02-26  9:31                     ` Matthew Fortune
  -1 siblings, 1 reply; 262+ messages in thread
From: Markos Chandras @ 2015-02-26  9:24 UTC (permalink / raw)
  To: Måns Rullgård; +Cc: Matthew Fortune, linux-mips, Paul Burton

On Thu, Feb 26, 2015 at 09:14:41AM +0000, Måns Rullgård wrote:
> Markos Chandras <markos.chandras@imgtec.com> writes:
> 
> > On Tue, Feb 24, 2015 at 02:26:04PM +0000, Matthew Fortune wrote:
> >> Måns Rullgård <mans@mansr.com> writes:
> >> > Markos Chandras <markos.chandras@imgtec.com> writes:
> >> > 
> >> > > Hi,
> >> > >
> >> > > On Tue, Feb 24, 2015 at 01:17:33PM +0000, Måns Rullgård wrote:
> >> > >> This patch (well, the variant that made it into 4.0-rc1) breaks
> >> > >> MIPS_ABI_FP_DOUBLE (the gcc default) apps on MIPS32.
> >> > >>
> >> > >
> >> > > Thanks for the report.
> >> > >
> >> > >> > +void mips_set_personality_fp(struct arch_elf_state *state) {
> >> > >> > +	/*
> >> > >> > +	 * This function is only ever called for O32 ELFs so we should
> >> > >> > +	 * not be worried about N32/N64 binaries.
> >> > >> > +	 */
> >> > >> >
> >> > >> > -	case MIPS_ABI_FP_XX:
> >> > >> > -	case MIPS_ABI_FP_ANY:
> >> > >> > -		if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
> >> > >> > -			set_thread_flag(TIF_32BIT_FPREGS);
> >> > >> > -		else
> >> > >> > -			clear_thread_flag(TIF_32BIT_FPREGS);
> >> > >> > +	if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
> >> > >> > +		return;
> >> > >>
> >> > >> The problem is here.  In a 32-bit configuration,
> >> > >> MIPS_O32_FP64_SUPPORT is always disabled, so the FP mode doesn't get
> >> > >> set.  Simply deleting those two lines makes things work again, but
> >> > >> that's probably not the right fix.
> >> 
> >> I don't recall the final decision on default on/off for this option but
> >> IIRC it is going to be off for everything except R6 in the first kernel
> >> version and then turned on by default(/option removed) when the code is
> >> proven for the following kernel version.
> >> 
> >> > >>
> >> > > I had the impression that the loader would have set the FP mode
> >> > > earlier on.  But that only may happen with the latest version of
> >> > > the tools.
> >> > >
> >> > > Perhaps instead of dropping these two lines we need a similar check on
> >> > > the arch_elf_pt_proc so we don't mess with the default FPI abi?
> >> > >
> >> > > Having said that, dropping these two lines should be fine, it just
> >> > > means you do a little bit of extra work when loading your ELF files to
> >> > > check for ABI compatibility which shouldn't matter in your case.
> >> > 
> >> > There's another early return like this in arch_check_elf() which should
> >> > probably go as well, or everything will end up with the default mode.
> >> 
> >> Ironically I discussed these changes with Markos in an attempt to make
> >> all the new changes benign when:
> >> 
> >> !config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT)
> >> 
> >> Clearly this has backfired. I will have to re-read the version of the code
> >> in 4.0-rc1 to see what is the root cause. The intention was that without
> >> the config option then the kernel would blindly continue to assume that
> >> all O32 binaries would run in the original TIF_32BIT_FPREGS mode. As I
> >> recall, the callers to mips_set_personality_fp were setting this mode
> >> which is why the simple early return was added.
> >> 
> >> Thanks,
> >> Matthew
> >
> > I think I can see what is going on. The problem is that
> > mips_set_personality_fp() (as already mentioned) is not executed for
> > !CONFIG_MIPS_O32_FP64_SUPPORT. The reason this is a problem
> > (i think this could only happen in 64-bit)
> 
> It's definitely causing problems on my 74Kf system.
> 
> > is that SET_PERSONALITY2 clears all the thread flags related to 32-bit
> > and FPU. The 32-bit flags will be set again by the
> > SET_PERSONALITY32_O32 but the FPU flags are not since the entire
> > mips_set_personality_fp() is skipped. While removing the if()
> > conditional in mips_set_personality_fp() will fix the problem, you
> > rely on state->overall_fp_mode having a good default value for you
> > case. If not, it will set the wrong FPU mode.
> 
> Yes, I realised this after hitting the send button earlier.
> 
> > Therefore, I believe the correct fix is either to drop both
> > CONFIG_MIPS_O32_FP64_SUPPORT or drop the one in
> > mips_set_personality_fp() and add another one in arch_elf_pt_proc() to
> > set a good default ABI just for this case and then return.
> 
> Sounds about right.
> 
> -- 
> Måns Rullgård
> mans@mansr.com
> 

actually the current default one for o32 (FR0) is fine. I think there is no need
to add a special O32_FP64_SUPPORT case here since it's very unlikely for the
default fp abi for o32 to change.

-- 
markos

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

* RE: [PATCH v3] MIPS: kernel: elf: Improve the overall ABI and FPU mode checks
  2015-02-26  9:24                   ` Markos Chandras
@ 2015-02-26  9:31                     ` Matthew Fortune
  2015-02-26  9:44                       ` Markos Chandras
  0 siblings, 1 reply; 262+ messages in thread
From: Matthew Fortune @ 2015-02-26  9:31 UTC (permalink / raw)
  To: Markos Chandras, Måns Rullgård; +Cc: linux-mips, Paul Burton

Markos Chandras <Markos.Chandras@imgtec.com>  writes:
> On Thu, Feb 26, 2015 at 09:14:41AM +0000, Måns Rullgård wrote:
> > Markos Chandras <markos.chandras@imgtec.com> writes:
> >
> > > On Tue, Feb 24, 2015 at 02:26:04PM +0000, Matthew Fortune wrote:
> > >> Måns Rullgård <mans@mansr.com> writes:
> > >> > Markos Chandras <markos.chandras@imgtec.com> writes:
> > >> >
> > >> > > Hi,
> > >> > >
> > >> > > On Tue, Feb 24, 2015 at 01:17:33PM +0000, Måns Rullgård wrote:
> > >> > >> This patch (well, the variant that made it into 4.0-rc1)
> > >> > >> breaks MIPS_ABI_FP_DOUBLE (the gcc default) apps on MIPS32.
> > >> > >>
> > >> > >
> > >> > > Thanks for the report.
> > >> > >
> > >> > >> > +void mips_set_personality_fp(struct arch_elf_state *state)
> {
> > >> > >> > +	/*
> > >> > >> > +	 * This function is only ever called for O32 ELFs so we
> should
> > >> > >> > +	 * not be worried about N32/N64 binaries.
> > >> > >> > +	 */
> > >> > >> >
> > >> > >> > -	case MIPS_ABI_FP_XX:
> > >> > >> > -	case MIPS_ABI_FP_ANY:
> > >> > >> > -		if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
> > >> > >> > -			set_thread_flag(TIF_32BIT_FPREGS);
> > >> > >> > -		else
> > >> > >> > -			clear_thread_flag(TIF_32BIT_FPREGS);
> > >> > >> > +	if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
> > >> > >> > +		return;
> > >> > >>
> > >> > >> The problem is here.  In a 32-bit configuration,
> > >> > >> MIPS_O32_FP64_SUPPORT is always disabled, so the FP mode
> > >> > >> doesn't get set.  Simply deleting those two lines makes things
> > >> > >> work again, but that's probably not the right fix.
> > >>
> > >> I don't recall the final decision on default on/off for this option
> > >> but IIRC it is going to be off for everything except R6 in the
> > >> first kernel version and then turned on by default(/option removed)
> > >> when the code is proven for the following kernel version.
> > >>
> > >> > >>
> > >> > > I had the impression that the loader would have set the FP mode
> > >> > > earlier on.  But that only may happen with the latest version
> > >> > > of the tools.
> > >> > >
> > >> > > Perhaps instead of dropping these two lines we need a similar
> > >> > > check on the arch_elf_pt_proc so we don't mess with the default
> FPI abi?
> > >> > >
> > >> > > Having said that, dropping these two lines should be fine, it
> > >> > > just means you do a little bit of extra work when loading your
> > >> > > ELF files to check for ABI compatibility which shouldn't matter
> in your case.
> > >> >
> > >> > There's another early return like this in arch_check_elf() which
> > >> > should probably go as well, or everything will end up with the
> default mode.
> > >>
> > >> Ironically I discussed these changes with Markos in an attempt to
> > >> make all the new changes benign when:
> > >>
> > >> !config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT)
> > >>
> > >> Clearly this has backfired. I will have to re-read the version of
> > >> the code in 4.0-rc1 to see what is the root cause. The intention
> > >> was that without the config option then the kernel would blindly
> > >> continue to assume that all O32 binaries would run in the original
> > >> TIF_32BIT_FPREGS mode. As I recall, the callers to
> > >> mips_set_personality_fp were setting this mode which is why the
> simple early return was added.
> > >>
> > >> Thanks,
> > >> Matthew
> > >
> > > I think I can see what is going on. The problem is that
> > > mips_set_personality_fp() (as already mentioned) is not executed for
> > > !CONFIG_MIPS_O32_FP64_SUPPORT. The reason this is a problem (i think
> > > this could only happen in 64-bit)
> >
> > It's definitely causing problems on my 74Kf system.
> >
> > > is that SET_PERSONALITY2 clears all the thread flags related to
> > > 32-bit and FPU. The 32-bit flags will be set again by the
> > > SET_PERSONALITY32_O32 but the FPU flags are not since the entire

OK, so this sounds like what differs from what I remember seeing. I thought
the various SET_PERSONALITY macros were setting up the default FPU flags
(default as in to match the default O32 FP ABI) and then this would be
updated in mips_set_personality_fp(). Iirc then mips_set_personality_fp
is only called for the O32 case so the FPU related flags must be correctly
set for n32/n64 in the macros. Why not just update the O32 macros to
set the mode?

> > > mips_set_personality_fp() is skipped. While removing the if()
> > > conditional in mips_set_personality_fp() will fix the problem, you
> > > rely on state->overall_fp_mode having a good default value for you
> > > case. If not, it will set the wrong FPU mode.
> >
> > Yes, I realised this after hitting the send button earlier.
> >
> > > Therefore, I believe the correct fix is either to drop both
> > > CONFIG_MIPS_O32_FP64_SUPPORT or drop the one in
> > > mips_set_personality_fp() and add another one in arch_elf_pt_proc()
> > > to set a good default ABI just for this case and then return.
> >
> > Sounds about right.
> >
> > --
> > Måns Rullgård
> > mans@mansr.com
> >
> 
> actually the current default one for o32 (FR0) is fine. I think there is
> no need
> to add a special O32_FP64_SUPPORT case here since it's very unlikely for
> the
> default fp abi for o32 to change.

I can guarantee that the default/original will not change.

Thanks,
Matthew

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

* Re: [PATCH v3] MIPS: kernel: elf: Improve the overall ABI and FPU mode checks
  2015-02-26  9:31                     ` Matthew Fortune
@ 2015-02-26  9:44                       ` Markos Chandras
  2015-02-26 10:31                           ` Måns Rullgård
  0 siblings, 1 reply; 262+ messages in thread
From: Markos Chandras @ 2015-02-26  9:44 UTC (permalink / raw)
  To: Matthew Fortune; +Cc: Måns Rullgård, linux-mips, Paul Burton

On Thu, Feb 26, 2015 at 09:31:36AM +0000, Matthew Fortune wrote:
> Markos Chandras <Markos.Chandras@imgtec.com>  writes:
> > On Thu, Feb 26, 2015 at 09:14:41AM +0000, Måns Rullgård wrote:
> > > Markos Chandras <markos.chandras@imgtec.com> writes:
> > >
> > > > On Tue, Feb 24, 2015 at 02:26:04PM +0000, Matthew Fortune wrote:
> > > >> Måns Rullgård <mans@mansr.com> writes:
> > > >> > Markos Chandras <markos.chandras@imgtec.com> writes:
> > > >> >
> > > >> > > Hi,
> > > >> > >
> > > >> > > On Tue, Feb 24, 2015 at 01:17:33PM +0000, Måns Rullgård wrote:
> > > >> > >> This patch (well, the variant that made it into 4.0-rc1)
> > > >> > >> breaks MIPS_ABI_FP_DOUBLE (the gcc default) apps on MIPS32.
> > > >> > >>
> > > >> > >
> > > >> > > Thanks for the report.
> > > >> > >
> > > >> > >> > +void mips_set_personality_fp(struct arch_elf_state *state)
> > {
> > > >> > >> > +	/*
> > > >> > >> > +	 * This function is only ever called for O32 ELFs so we
> > should
> > > >> > >> > +	 * not be worried about N32/N64 binaries.
> > > >> > >> > +	 */
> > > >> > >> >
> > > >> > >> > -	case MIPS_ABI_FP_XX:
> > > >> > >> > -	case MIPS_ABI_FP_ANY:
> > > >> > >> > -		if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
> > > >> > >> > -			set_thread_flag(TIF_32BIT_FPREGS);
> > > >> > >> > -		else
> > > >> > >> > -			clear_thread_flag(TIF_32BIT_FPREGS);
> > > >> > >> > +	if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
> > > >> > >> > +		return;
> > > >> > >>
> > > >> > >> The problem is here.  In a 32-bit configuration,
> > > >> > >> MIPS_O32_FP64_SUPPORT is always disabled, so the FP mode
> > > >> > >> doesn't get set.  Simply deleting those two lines makes things
> > > >> > >> work again, but that's probably not the right fix.
> > > >>
> > > >> I don't recall the final decision on default on/off for this option
> > > >> but IIRC it is going to be off for everything except R6 in the
> > > >> first kernel version and then turned on by default(/option removed)
> > > >> when the code is proven for the following kernel version.
> > > >>
> > > >> > >>
> > > >> > > I had the impression that the loader would have set the FP mode
> > > >> > > earlier on.  But that only may happen with the latest version
> > > >> > > of the tools.
> > > >> > >
> > > >> > > Perhaps instead of dropping these two lines we need a similar
> > > >> > > check on the arch_elf_pt_proc so we don't mess with the default
> > FPI abi?
> > > >> > >
> > > >> > > Having said that, dropping these two lines should be fine, it
> > > >> > > just means you do a little bit of extra work when loading your
> > > >> > > ELF files to check for ABI compatibility which shouldn't matter
> > in your case.
> > > >> >
> > > >> > There's another early return like this in arch_check_elf() which
> > > >> > should probably go as well, or everything will end up with the
> > default mode.
> > > >>
> > > >> Ironically I discussed these changes with Markos in an attempt to
> > > >> make all the new changes benign when:
> > > >>
> > > >> !config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT)
> > > >>
> > > >> Clearly this has backfired. I will have to re-read the version of
> > > >> the code in 4.0-rc1 to see what is the root cause. The intention
> > > >> was that without the config option then the kernel would blindly
> > > >> continue to assume that all O32 binaries would run in the original
> > > >> TIF_32BIT_FPREGS mode. As I recall, the callers to
> > > >> mips_set_personality_fp were setting this mode which is why the
> > simple early return was added.
> > > >>
> > > >> Thanks,
> > > >> Matthew
> > > >
> > > > I think I can see what is going on. The problem is that
> > > > mips_set_personality_fp() (as already mentioned) is not executed for
> > > > !CONFIG_MIPS_O32_FP64_SUPPORT. The reason this is a problem (i think
> > > > this could only happen in 64-bit)
> > >
> > > It's definitely causing problems on my 74Kf system.
> > >
> > > > is that SET_PERSONALITY2 clears all the thread flags related to
> > > > 32-bit and FPU. The 32-bit flags will be set again by the
> > > > SET_PERSONALITY32_O32 but the FPU flags are not since the entire
> 
> OK, so this sounds like what differs from what I remember seeing. I thought
> the various SET_PERSONALITY macros were setting up the default FPU flags
> (default as in to match the default O32 FP ABI) and then this would be
> updated in mips_set_personality_fp(). Iirc then mips_set_personality_fp
> is only called for the O32 case so the FPU related flags must be correctly
> set for n32/n64 in the macros. Why not just update the O32 macros to
> set the mode?
Yes that should be fine too.

Mans, could you try the following patch please since it seems you already have
a suitable environment ready to reproduce this problem

diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h
index 535f196ffe02..694925a26924 100644
--- a/arch/mips/include/asm/elf.h
+++ b/arch/mips/include/asm/elf.h
@@ -294,6 +294,9 @@ do {									\
 	if (personality(current->personality) != PER_LINUX)		\
 		set_personality(PER_LINUX);				\
 									\
+	clear_thread_flag(TIF_HYBRID_FPREGS);				\
+	set_thread_flag(TIF_32BIT_FPREGS);				\
+									\
 	mips_set_personality_fp(state);					\
 									\
 	current->thread.abi = &mips_abi;				\
@@ -319,6 +322,8 @@ do {									\
 	do {								\
 		set_thread_flag(TIF_32BIT_REGS);			\
 		set_thread_flag(TIF_32BIT_ADDR);			\
+		clear_thread_flag(TIF_HYBRID_FPREGS);			\
+		set_thread_flag(TIF_32BIT_FPREGS);			\
 									\
 		mips_set_personality_fp(state);				\
 									\


If that works, I will submit a format patch asap.

-- 
markos

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

* Re: [PATCH v3] MIPS: kernel: elf: Improve the overall ABI and FPU mode checks
@ 2015-02-26 10:31                           ` Måns Rullgård
  0 siblings, 0 replies; 262+ messages in thread
From: Måns Rullgård @ 2015-02-26 10:31 UTC (permalink / raw)
  To: Markos Chandras; +Cc: Matthew Fortune, linux-mips, Paul Burton

Markos Chandras <markos.chandras@imgtec.com> writes:

> On Thu, Feb 26, 2015 at 09:31:36AM +0000, Matthew Fortune wrote:
>> Markos Chandras <Markos.Chandras@imgtec.com>  writes:
>> > On Thu, Feb 26, 2015 at 09:14:41AM +0000, Måns Rullgård wrote:
>> > > Markos Chandras <markos.chandras@imgtec.com> writes:
>> > >
>> > > > On Tue, Feb 24, 2015 at 02:26:04PM +0000, Matthew Fortune wrote:
>> > > >> Måns Rullgård <mans@mansr.com> writes:
>> > > >> > Markos Chandras <markos.chandras@imgtec.com> writes:
>> > > >> >
>> > > >> > > Hi,
>> > > >> > >
>> > > >> > > On Tue, Feb 24, 2015 at 01:17:33PM +0000, Måns Rullgård wrote:
>> > > >> > >> This patch (well, the variant that made it into 4.0-rc1)
>> > > >> > >> breaks MIPS_ABI_FP_DOUBLE (the gcc default) apps on MIPS32.
>> > > >> > >>
>> > > >> > >
>> > > >> > > Thanks for the report.
>> > > >> > >
>> > > >> > >> > +void mips_set_personality_fp(struct arch_elf_state *state) {
>> > > >> > >> > +	/*
>> > > >> > >> > +	 * This function is only ever called for O32 ELFs so we should
>> > > >> > >> > +	 * not be worried about N32/N64 binaries.
>> > > >> > >> > +	 */
>> > > >> > >> >
>> > > >> > >> > -	case MIPS_ABI_FP_XX:
>> > > >> > >> > -	case MIPS_ABI_FP_ANY:
>> > > >> > >> > -		if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
>> > > >> > >> > -			set_thread_flag(TIF_32BIT_FPREGS);
>> > > >> > >> > -		else
>> > > >> > >> > -			clear_thread_flag(TIF_32BIT_FPREGS);
>> > > >> > >> > +	if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
>> > > >> > >> > +		return;
>> > > >> > >>
>> > > >> > >> The problem is here.  In a 32-bit configuration,
>> > > >> > >> MIPS_O32_FP64_SUPPORT is always disabled, so the FP mode
>> > > >> > >> doesn't get set.  Simply deleting those two lines makes things
>> > > >> > >> work again, but that's probably not the right fix.
>> > > >>
>> > > >> I don't recall the final decision on default on/off for this option
>> > > >> but IIRC it is going to be off for everything except R6 in the
>> > > >> first kernel version and then turned on by default(/option removed)
>> > > >> when the code is proven for the following kernel version.
>> > > >>
>> > > >> > >>
>> > > >> > > I had the impression that the loader would have set the FP mode
>> > > >> > > earlier on.  But that only may happen with the latest version
>> > > >> > > of the tools.
>> > > >> > >
>> > > >> > > Perhaps instead of dropping these two lines we need a
>> > > >> > > similar check on the arch_elf_pt_proc so we don't mess
>> > > >> > > with the default FPI abi?
>> > > >> > >
>> > > >> > > Having said that, dropping these two lines should be fine,
>> > > >> > > it just means you do a little bit of extra work when
>> > > >> > > loading your ELF files to check for ABI compatibility
>> > > >> > > which shouldn't matter in your case.
>> > > >> >
>> > > >> > There's another early return like this in arch_check_elf()
>> > > >> > which should probably go as well, or everything will end up
>> > > >> > with the default mode.
>> > > >>
>> > > >> Ironically I discussed these changes with Markos in an attempt to
>> > > >> make all the new changes benign when:
>> > > >>
>> > > >> !config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT)
>> > > >>
>> > > >> Clearly this has backfired. I will have to re-read the version of
>> > > >> the code in 4.0-rc1 to see what is the root cause. The intention
>> > > >> was that without the config option then the kernel would blindly
>> > > >> continue to assume that all O32 binaries would run in the original
>> > > >> TIF_32BIT_FPREGS mode. As I recall, the callers to
>> > > >> mips_set_personality_fp were setting this mode which is why the
>> > > >> simple early return was added.
>> > > >>
>> > > >> Thanks,
>> > > >> Matthew
>> > > >
>> > > > I think I can see what is going on. The problem is that
>> > > > mips_set_personality_fp() (as already mentioned) is not executed for
>> > > > !CONFIG_MIPS_O32_FP64_SUPPORT. The reason this is a problem (i think
>> > > > this could only happen in 64-bit)
>> > >
>> > > It's definitely causing problems on my 74Kf system.
>> > >
>> > > > is that SET_PERSONALITY2 clears all the thread flags related to
>> > > > 32-bit and FPU. The 32-bit flags will be set again by the
>> > > > SET_PERSONALITY32_O32 but the FPU flags are not since the entire
>> 
>> OK, so this sounds like what differs from what I remember seeing. I thought
>> the various SET_PERSONALITY macros were setting up the default FPU flags
>> (default as in to match the default O32 FP ABI) and then this would be
>> updated in mips_set_personality_fp(). Iirc then mips_set_personality_fp
>> is only called for the O32 case so the FPU related flags must be correctly
>> set for n32/n64 in the macros. Why not just update the O32 macros to
>> set the mode?
> Yes that should be fine too.
>
> Mans, could you try the following patch please since it seems you already have
> a suitable environment ready to reproduce this problem
>
> diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h
> index 535f196ffe02..694925a26924 100644
> --- a/arch/mips/include/asm/elf.h
> +++ b/arch/mips/include/asm/elf.h
> @@ -294,6 +294,9 @@ do {									\
>  	if (personality(current->personality) != PER_LINUX)		\
>  		set_personality(PER_LINUX);				\
>  									\
> +	clear_thread_flag(TIF_HYBRID_FPREGS);				\
> +	set_thread_flag(TIF_32BIT_FPREGS);				\
> +									\
>  	mips_set_personality_fp(state);					\
>  									\
>  	current->thread.abi = &mips_abi;				\
> @@ -319,6 +322,8 @@ do {									\
>  	do {								\
>  		set_thread_flag(TIF_32BIT_REGS);			\
>  		set_thread_flag(TIF_32BIT_ADDR);			\
> +		clear_thread_flag(TIF_HYBRID_FPREGS);			\
> +		set_thread_flag(TIF_32BIT_FPREGS);			\
>  									\
>  		mips_set_personality_fp(state);				\
>  									\
>
> If that works, I will submit a format patch asap.

Seems to work.

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

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

* Re: [PATCH v3] MIPS: kernel: elf: Improve the overall ABI and FPU mode checks
@ 2015-02-26 10:31                           ` Måns Rullgård
  0 siblings, 0 replies; 262+ messages in thread
From: Måns Rullgård @ 2015-02-26 10:31 UTC (permalink / raw)
  To: Markos Chandras; +Cc: Matthew Fortune, linux-mips, Paul Burton

Markos Chandras <markos.chandras@imgtec.com> writes:

> On Thu, Feb 26, 2015 at 09:31:36AM +0000, Matthew Fortune wrote:
>> Markos Chandras <Markos.Chandras@imgtec.com>  writes:
>> > On Thu, Feb 26, 2015 at 09:14:41AM +0000, Måns Rullgård wrote:
>> > > Markos Chandras <markos.chandras@imgtec.com> writes:
>> > >
>> > > > On Tue, Feb 24, 2015 at 02:26:04PM +0000, Matthew Fortune wrote:
>> > > >> Måns Rullgård <mans@mansr.com> writes:
>> > > >> > Markos Chandras <markos.chandras@imgtec.com> writes:
>> > > >> >
>> > > >> > > Hi,
>> > > >> > >
>> > > >> > > On Tue, Feb 24, 2015 at 01:17:33PM +0000, Måns Rullgård wrote:
>> > > >> > >> This patch (well, the variant that made it into 4.0-rc1)
>> > > >> > >> breaks MIPS_ABI_FP_DOUBLE (the gcc default) apps on MIPS32.
>> > > >> > >>
>> > > >> > >
>> > > >> > > Thanks for the report.
>> > > >> > >
>> > > >> > >> > +void mips_set_personality_fp(struct arch_elf_state *state) {
>> > > >> > >> > +	/*
>> > > >> > >> > +	 * This function is only ever called for O32 ELFs so we should
>> > > >> > >> > +	 * not be worried about N32/N64 binaries.
>> > > >> > >> > +	 */
>> > > >> > >> >
>> > > >> > >> > -	case MIPS_ABI_FP_XX:
>> > > >> > >> > -	case MIPS_ABI_FP_ANY:
>> > > >> > >> > -		if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
>> > > >> > >> > -			set_thread_flag(TIF_32BIT_FPREGS);
>> > > >> > >> > -		else
>> > > >> > >> > -			clear_thread_flag(TIF_32BIT_FPREGS);
>> > > >> > >> > +	if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
>> > > >> > >> > +		return;
>> > > >> > >>
>> > > >> > >> The problem is here.  In a 32-bit configuration,
>> > > >> > >> MIPS_O32_FP64_SUPPORT is always disabled, so the FP mode
>> > > >> > >> doesn't get set.  Simply deleting those two lines makes things
>> > > >> > >> work again, but that's probably not the right fix.
>> > > >>
>> > > >> I don't recall the final decision on default on/off for this option
>> > > >> but IIRC it is going to be off for everything except R6 in the
>> > > >> first kernel version and then turned on by default(/option removed)
>> > > >> when the code is proven for the following kernel version.
>> > > >>
>> > > >> > >>
>> > > >> > > I had the impression that the loader would have set the FP mode
>> > > >> > > earlier on.  But that only may happen with the latest version
>> > > >> > > of the tools.
>> > > >> > >
>> > > >> > > Perhaps instead of dropping these two lines we need a
>> > > >> > > similar check on the arch_elf_pt_proc so we don't mess
>> > > >> > > with the default FPI abi?
>> > > >> > >
>> > > >> > > Having said that, dropping these two lines should be fine,
>> > > >> > > it just means you do a little bit of extra work when
>> > > >> > > loading your ELF files to check for ABI compatibility
>> > > >> > > which shouldn't matter in your case.
>> > > >> >
>> > > >> > There's another early return like this in arch_check_elf()
>> > > >> > which should probably go as well, or everything will end up
>> > > >> > with the default mode.
>> > > >>
>> > > >> Ironically I discussed these changes with Markos in an attempt to
>> > > >> make all the new changes benign when:
>> > > >>
>> > > >> !config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT)
>> > > >>
>> > > >> Clearly this has backfired. I will have to re-read the version of
>> > > >> the code in 4.0-rc1 to see what is the root cause. The intention
>> > > >> was that without the config option then the kernel would blindly
>> > > >> continue to assume that all O32 binaries would run in the original
>> > > >> TIF_32BIT_FPREGS mode. As I recall, the callers to
>> > > >> mips_set_personality_fp were setting this mode which is why the
>> > > >> simple early return was added.
>> > > >>
>> > > >> Thanks,
>> > > >> Matthew
>> > > >
>> > > > I think I can see what is going on. The problem is that
>> > > > mips_set_personality_fp() (as already mentioned) is not executed for
>> > > > !CONFIG_MIPS_O32_FP64_SUPPORT. The reason this is a problem (i think
>> > > > this could only happen in 64-bit)
>> > >
>> > > It's definitely causing problems on my 74Kf system.
>> > >
>> > > > is that SET_PERSONALITY2 clears all the thread flags related to
>> > > > 32-bit and FPU. The 32-bit flags will be set again by the
>> > > > SET_PERSONALITY32_O32 but the FPU flags are not since the entire
>> 
>> OK, so this sounds like what differs from what I remember seeing. I thought
>> the various SET_PERSONALITY macros were setting up the default FPU flags
>> (default as in to match the default O32 FP ABI) and then this would be
>> updated in mips_set_personality_fp(). Iirc then mips_set_personality_fp
>> is only called for the O32 case so the FPU related flags must be correctly
>> set for n32/n64 in the macros. Why not just update the O32 macros to
>> set the mode?
> Yes that should be fine too.
>
> Mans, could you try the following patch please since it seems you already have
> a suitable environment ready to reproduce this problem
>
> diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h
> index 535f196ffe02..694925a26924 100644
> --- a/arch/mips/include/asm/elf.h
> +++ b/arch/mips/include/asm/elf.h
> @@ -294,6 +294,9 @@ do {									\
>  	if (personality(current->personality) != PER_LINUX)		\
>  		set_personality(PER_LINUX);				\
>  									\
> +	clear_thread_flag(TIF_HYBRID_FPREGS);				\
> +	set_thread_flag(TIF_32BIT_FPREGS);				\
> +									\
>  	mips_set_personality_fp(state);					\
>  									\
>  	current->thread.abi = &mips_abi;				\
> @@ -319,6 +322,8 @@ do {									\
>  	do {								\
>  		set_thread_flag(TIF_32BIT_REGS);			\
>  		set_thread_flag(TIF_32BIT_ADDR);			\
> +		clear_thread_flag(TIF_HYBRID_FPREGS);			\
> +		set_thread_flag(TIF_32BIT_FPREGS);			\
>  									\
>  		mips_set_personality_fp(state);				\
>  									\
>
> If that works, I will submit a format patch asap.

Seems to work.

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

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

* [PATCH] MIPS: asm: elf: Set O32 default FPU flags
@ 2015-02-26 11:11       ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-02-26 11:11 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Matthew Fortune, Paul Burton

Set good default FPU flags (FR0) for O32 binaries similar to what the
kernel does for the N64/N32 ones. This also fixes a regression
introduced in commit 46490b572544 ("MIPS: kernel: elf: Improve the
overall ABI and FPU mode checks") when MIPS_O32_FP64_SUPPORT is
disabled. In that case, the mips_set_personality_fp() did not set the
FPU mode at all because it assumed that the FPU mode was already set
properly. That led to O32 userland problems.

Cc: Matthew Fortune <Matthew.Fortune@imgtec.com>
Cc: Paul Burton <paul.burton@imgtec.com>
Reported-by: Mans Rullgard <mans@mansr.com>
Fixes: 46490b572544 ("MIPS: kernel: elf: Improve the overall ABI and FPU mode checks")
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/elf.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h
index 535f196ffe02..694925a26924 100644
--- a/arch/mips/include/asm/elf.h
+++ b/arch/mips/include/asm/elf.h
@@ -294,6 +294,9 @@ do {									\
 	if (personality(current->personality) != PER_LINUX)		\
 		set_personality(PER_LINUX);				\
 									\
+	clear_thread_flag(TIF_HYBRID_FPREGS);				\
+	set_thread_flag(TIF_32BIT_FPREGS);				\
+									\
 	mips_set_personality_fp(state);					\
 									\
 	current->thread.abi = &mips_abi;				\
@@ -319,6 +322,8 @@ do {									\
 	do {								\
 		set_thread_flag(TIF_32BIT_REGS);			\
 		set_thread_flag(TIF_32BIT_ADDR);			\
+		clear_thread_flag(TIF_HYBRID_FPREGS);			\
+		set_thread_flag(TIF_32BIT_FPREGS);			\
 									\
 		mips_set_personality_fp(state);				\
 									\
-- 
2.3.0

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

* [PATCH] MIPS: asm: elf: Set O32 default FPU flags
@ 2015-02-26 11:11       ` Markos Chandras
  0 siblings, 0 replies; 262+ messages in thread
From: Markos Chandras @ 2015-02-26 11:11 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Matthew Fortune, Paul Burton

Set good default FPU flags (FR0) for O32 binaries similar to what the
kernel does for the N64/N32 ones. This also fixes a regression
introduced in commit 46490b572544 ("MIPS: kernel: elf: Improve the
overall ABI and FPU mode checks") when MIPS_O32_FP64_SUPPORT is
disabled. In that case, the mips_set_personality_fp() did not set the
FPU mode at all because it assumed that the FPU mode was already set
properly. That led to O32 userland problems.

Cc: Matthew Fortune <Matthew.Fortune@imgtec.com>
Cc: Paul Burton <paul.burton@imgtec.com>
Reported-by: Mans Rullgard <mans@mansr.com>
Fixes: 46490b572544 ("MIPS: kernel: elf: Improve the overall ABI and FPU mode checks")
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/elf.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h
index 535f196ffe02..694925a26924 100644
--- a/arch/mips/include/asm/elf.h
+++ b/arch/mips/include/asm/elf.h
@@ -294,6 +294,9 @@ do {									\
 	if (personality(current->personality) != PER_LINUX)		\
 		set_personality(PER_LINUX);				\
 									\
+	clear_thread_flag(TIF_HYBRID_FPREGS);				\
+	set_thread_flag(TIF_32BIT_FPREGS);				\
+									\
 	mips_set_personality_fp(state);					\
 									\
 	current->thread.abi = &mips_abi;				\
@@ -319,6 +322,8 @@ do {									\
 	do {								\
 		set_thread_flag(TIF_32BIT_REGS);			\
 		set_thread_flag(TIF_32BIT_ADDR);			\
+		clear_thread_flag(TIF_HYBRID_FPREGS);			\
+		set_thread_flag(TIF_32BIT_FPREGS);			\
 									\
 		mips_set_personality_fp(state);				\
 									\
-- 
2.3.0

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

* Re: [PATCH] MIPS: asm: elf: Set O32 default FPU flags
@ 2015-02-26 11:21         ` Måns Rullgård
  0 siblings, 0 replies; 262+ messages in thread
From: Måns Rullgård @ 2015-02-26 11:21 UTC (permalink / raw)
  To: Markos Chandras; +Cc: linux-mips, Matthew Fortune, Paul Burton

Markos Chandras <markos.chandras@imgtec.com> writes:

> Set good default FPU flags (FR0) for O32 binaries similar to what the
> kernel does for the N64/N32 ones. This also fixes a regression
> introduced in commit 46490b572544 ("MIPS: kernel: elf: Improve the
> overall ABI and FPU mode checks") when MIPS_O32_FP64_SUPPORT is
> disabled. In that case, the mips_set_personality_fp() did not set the
> FPU mode at all because it assumed that the FPU mode was already set
> properly. That led to O32 userland problems.
>
> Cc: Matthew Fortune <Matthew.Fortune@imgtec.com>
> Cc: Paul Burton <paul.burton@imgtec.com>
> Reported-by: Mans Rullgard <mans@mansr.com>
> Fixes: 46490b572544 ("MIPS: kernel: elf: Improve the overall ABI and FPU mode checks")
> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>

Tested-by: Mans Rullgard <mans@mansr.com>

> ---
>  arch/mips/include/asm/elf.h | 5 +++++
>  1 file changed, 5 insertions(+)
>
> diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h
> index 535f196ffe02..694925a26924 100644
> --- a/arch/mips/include/asm/elf.h
> +++ b/arch/mips/include/asm/elf.h
> @@ -294,6 +294,9 @@ do {									\
>  	if (personality(current->personality) != PER_LINUX)		\
>  		set_personality(PER_LINUX);				\
>  									\
> +	clear_thread_flag(TIF_HYBRID_FPREGS);				\
> +	set_thread_flag(TIF_32BIT_FPREGS);				\
> +									\
>  	mips_set_personality_fp(state);					\
>  									\
>  	current->thread.abi = &mips_abi;				\
> @@ -319,6 +322,8 @@ do {									\
>  	do {								\
>  		set_thread_flag(TIF_32BIT_REGS);			\
>  		set_thread_flag(TIF_32BIT_ADDR);			\
> +		clear_thread_flag(TIF_HYBRID_FPREGS);			\
> +		set_thread_flag(TIF_32BIT_FPREGS);			\
>  									\
>  		mips_set_personality_fp(state);				\
>  									\
> -- 
> 2.3.0
>

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

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

* Re: [PATCH] MIPS: asm: elf: Set O32 default FPU flags
@ 2015-02-26 11:21         ` Måns Rullgård
  0 siblings, 0 replies; 262+ messages in thread
From: Måns Rullgård @ 2015-02-26 11:21 UTC (permalink / raw)
  To: Markos Chandras; +Cc: linux-mips, Matthew Fortune, Paul Burton

Markos Chandras <markos.chandras@imgtec.com> writes:

> Set good default FPU flags (FR0) for O32 binaries similar to what the
> kernel does for the N64/N32 ones. This also fixes a regression
> introduced in commit 46490b572544 ("MIPS: kernel: elf: Improve the
> overall ABI and FPU mode checks") when MIPS_O32_FP64_SUPPORT is
> disabled. In that case, the mips_set_personality_fp() did not set the
> FPU mode at all because it assumed that the FPU mode was already set
> properly. That led to O32 userland problems.
>
> Cc: Matthew Fortune <Matthew.Fortune@imgtec.com>
> Cc: Paul Burton <paul.burton@imgtec.com>
> Reported-by: Mans Rullgard <mans@mansr.com>
> Fixes: 46490b572544 ("MIPS: kernel: elf: Improve the overall ABI and FPU mode checks")
> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>

Tested-by: Mans Rullgard <mans@mansr.com>

> ---
>  arch/mips/include/asm/elf.h | 5 +++++
>  1 file changed, 5 insertions(+)
>
> diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h
> index 535f196ffe02..694925a26924 100644
> --- a/arch/mips/include/asm/elf.h
> +++ b/arch/mips/include/asm/elf.h
> @@ -294,6 +294,9 @@ do {									\
>  	if (personality(current->personality) != PER_LINUX)		\
>  		set_personality(PER_LINUX);				\
>  									\
> +	clear_thread_flag(TIF_HYBRID_FPREGS);				\
> +	set_thread_flag(TIF_32BIT_FPREGS);				\
> +									\
>  	mips_set_personality_fp(state);					\
>  									\
>  	current->thread.abi = &mips_abi;				\
> @@ -319,6 +322,8 @@ do {									\
>  	do {								\
>  		set_thread_flag(TIF_32BIT_REGS);			\
>  		set_thread_flag(TIF_32BIT_ADDR);			\
> +		clear_thread_flag(TIF_HYBRID_FPREGS);			\
> +		set_thread_flag(TIF_32BIT_FPREGS);			\
>  									\
>  		mips_set_personality_fp(state);				\
>  									\
> -- 
> 2.3.0
>

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

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

* Re: [PATCH] MIPS: asm: elf: Set O32 default FPU flags
  2015-02-26 11:11       ` Markos Chandras
  (?)
  (?)
@ 2015-02-27  1:28       ` Aaro Koskinen
  2015-02-27  1:46         ` Måns Rullgård
  -1 siblings, 1 reply; 262+ messages in thread
From: Aaro Koskinen @ 2015-02-27  1:28 UTC (permalink / raw)
  To: Markos Chandras; +Cc: linux-mips, Matthew Fortune, Paul Burton

Hi,

On Thu, Feb 26, 2015 at 11:11:30AM +0000, Markos Chandras wrote:
> Set good default FPU flags (FR0) for O32 binaries similar to what the
> kernel does for the N64/N32 ones. This also fixes a regression
> introduced in commit 46490b572544 ("MIPS: kernel: elf: Improve the
> overall ABI and FPU mode checks") when MIPS_O32_FP64_SUPPORT is
> disabled. In that case, the mips_set_personality_fp() did not set the
> FPU mode at all because it assumed that the FPU mode was already set
> properly. That led to O32 userland problems.
> 
> Cc: Matthew Fortune <Matthew.Fortune@imgtec.com>
> Cc: Paul Burton <paul.burton@imgtec.com>
> Reported-by: Mans Rullgard <mans@mansr.com>
> Fixes: 46490b572544 ("MIPS: kernel: elf: Improve the overall ABI and FPU mode checks")
> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>

This seems to fix some strange openssl issues on my Loongson system
(O32, hard-float) with 4.0-rc1.

Tested-by: Aaro Koskinen <aaro.koskinen@iki.fi>

A.

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

* Re: [PATCH] MIPS: asm: elf: Set O32 default FPU flags
  2015-02-27  1:28       ` Aaro Koskinen
@ 2015-02-27  1:46         ` Måns Rullgård
  0 siblings, 0 replies; 262+ messages in thread
From: Måns Rullgård @ 2015-02-27  1:46 UTC (permalink / raw)
  To: Aaro Koskinen; +Cc: Markos Chandras, linux-mips, Matthew Fortune, Paul Burton

Aaro Koskinen <aaro.koskinen@iki.fi> writes:

> Hi,
>
> On Thu, Feb 26, 2015 at 11:11:30AM +0000, Markos Chandras wrote:
>> Set good default FPU flags (FR0) for O32 binaries similar to what the
>> kernel does for the N64/N32 ones. This also fixes a regression
>> introduced in commit 46490b572544 ("MIPS: kernel: elf: Improve the
>> overall ABI and FPU mode checks") when MIPS_O32_FP64_SUPPORT is
>> disabled. In that case, the mips_set_personality_fp() did not set the
>> FPU mode at all because it assumed that the FPU mode was already set
>> properly. That led to O32 userland problems.
>> 
>> Cc: Matthew Fortune <Matthew.Fortune@imgtec.com>
>> Cc: Paul Burton <paul.burton@imgtec.com>
>> Reported-by: Mans Rullgard <mans@mansr.com>
>> Fixes: 46490b572544 ("MIPS: kernel: elf: Improve the overall ABI and FPU mode checks")
>> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
>
> This seems to fix some strange openssl issues on my Loongson system
> (O32, hard-float) with 4.0-rc1.

I have also seen openssl problems that I verified were caused by this
(it uses floating-point to measure entropy).

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

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

* Re: [PATCH] MIPS: asm: elf: Set O32 default FPU flags
  2015-02-26 11:11       ` Markos Chandras
                         ` (2 preceding siblings ...)
  (?)
@ 2015-04-07 16:36       ` Maciej W. Rozycki
  2015-04-12 23:21         ` Aaro Koskinen
  -1 siblings, 1 reply; 262+ messages in thread
From: Maciej W. Rozycki @ 2015-04-07 16:36 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: James Cowgill, Markos Chandras, linux-mips, Matthew Fortune, Paul Burton

Ralf,

On Thu, 26 Feb 2015, Markos Chandras wrote:

> Set good default FPU flags (FR0) for O32 binaries similar to what the
> kernel does for the N64/N32 ones. This also fixes a regression
> introduced in commit 46490b572544 ("MIPS: kernel: elf: Improve the
> overall ABI and FPU mode checks") when MIPS_O32_FP64_SUPPORT is
> disabled. In that case, the mips_set_personality_fp() did not set the
> FPU mode at all because it assumed that the FPU mode was already set
> properly. That led to O32 userland problems.
> 
> Cc: Matthew Fortune <Matthew.Fortune@imgtec.com>
> Cc: Paul Burton <paul.burton@imgtec.com>
> Reported-by: Mans Rullgard <mans@mansr.com>
> Fixes: 46490b572544 ("MIPS: kernel: elf: Improve the overall ABI and FPU mode checks")
> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
> ---

 Can you please backport this change to 4.0 ASAP, preferably before it 
hits the actual release?

 It fixes a 3.19->4.0 regression, likely affecting all FPU processors and 
wreaking havoc.  For example I came across a system that boots 3.19 just 
fine, but hangs in `ypbind' with 4.0.  It works again with this change 
applied.

 This is commit 5f067f5c in upstream-sfr.

 Thanks!

  Maciej

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

* Re: [PATCH] MIPS: asm: elf: Set O32 default FPU flags
  2015-04-07 16:36       ` Maciej W. Rozycki
@ 2015-04-12 23:21         ` Aaro Koskinen
  2015-04-20 11:55           ` Maciej W. Rozycki
  0 siblings, 1 reply; 262+ messages in thread
From: Aaro Koskinen @ 2015-04-12 23:21 UTC (permalink / raw)
  To: Maciej W. Rozycki, Ralf Baechle
  Cc: James Cowgill, Markos Chandras, linux-mips, Matthew Fortune, Paul Burton

Hi,

On Tue, Apr 07, 2015 at 05:36:08PM +0100, Maciej W. Rozycki wrote:
> On Thu, 26 Feb 2015, Markos Chandras wrote:
> > Set good default FPU flags (FR0) for O32 binaries similar to what the
> > kernel does for the N64/N32 ones. This also fixes a regression
> > introduced in commit 46490b572544 ("MIPS: kernel: elf: Improve the
> > overall ABI and FPU mode checks") when MIPS_O32_FP64_SUPPORT is
> > disabled. In that case, the mips_set_personality_fp() did not set the
> > FPU mode at all because it assumed that the FPU mode was already set
> > properly. That led to O32 userland problems.
> > 
> > Cc: Matthew Fortune <Matthew.Fortune@imgtec.com>
> > Cc: Paul Burton <paul.burton@imgtec.com>
> > Reported-by: Mans Rullgard <mans@mansr.com>
> > Fixes: 46490b572544 ("MIPS: kernel: elf: Improve the overall ABI and FPU mode checks")
> > Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
> > ---
> 
>  Can you please backport this change to 4.0 ASAP, preferably before it 
> hits the actual release?
> 
>  It fixes a 3.19->4.0 regression, likely affecting all FPU processors and 
> wreaking havoc.  For example I came across a system that boots 3.19 just 
> fine, but hangs in `ypbind' with 4.0.  It works again with this change 
> applied.

It seems this patch, and some other fixes for fatal regressions,
missed 4.0, although they were reported right after the -rc1 was out.

Basically 4.0 is unusable for MIPS users.

:-(

A.

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

* Re: [PATCH] MIPS: asm: elf: Set O32 default FPU flags
  2015-04-12 23:21         ` Aaro Koskinen
@ 2015-04-20 11:55           ` Maciej W. Rozycki
  0 siblings, 0 replies; 262+ messages in thread
From: Maciej W. Rozycki @ 2015-04-20 11:55 UTC (permalink / raw)
  To: Aaro Koskinen
  Cc: Ralf Baechle, James Cowgill, Markos Chandras, linux-mips,
	Matthew Fortune, Paul Burton

On Mon, 13 Apr 2015, Aaro Koskinen wrote:

> >  Can you please backport this change to 4.0 ASAP, preferably before it 
> > hits the actual release?
> > 
> >  It fixes a 3.19->4.0 regression, likely affecting all FPU processors and 
> > wreaking havoc.  For example I came across a system that boots 3.19 just 
> > fine, but hangs in `ypbind' with 4.0.  It works again with this change 
> > applied.
> 
> It seems this patch, and some other fixes for fatal regressions,
> missed 4.0, although they were reported right after the -rc1 was out.
> 
> Basically 4.0 is unusable for MIPS users.

 I've had some success with the "nofpu" kernel parameter; in fact I didn't 
notice the problem as I was testing full FPU emulation and until I enabled 
the FPU hardware.  You may try the option temporarily as a workaround.  

 Hopefully the fix makes it through to 4.0.1 or suchlike.

  Maciej

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

end of thread, other threads:[~2015-04-20 11:55 UTC | newest]

Thread overview: 262+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-16 10:48 [PATCH RFC v2 00/70] Add MIPS R6 support Markos Chandras
2015-01-16 10:48 ` Markos Chandras
2015-01-16 10:48 ` [PATCH RFC v2 01/70] MIPS: Add generic QEMU PRid and cpu type identifiers Markos Chandras
2015-01-16 10:48   ` Markos Chandras
2015-01-16 10:48 ` [PATCH RFC v2 02/70] MIPS: Add cases for CPU_QEMU_GENERIC Markos Chandras
2015-01-16 10:48   ` Markos Chandras
2015-01-16 10:48 ` [PATCH RFC v2 03/70] MIPS: Add MIPS generic QEMU probe support Markos Chandras
2015-01-16 10:48   ` Markos Chandras
2015-01-16 10:48 ` [PATCH RFC v2 04/70] MIPS: Add build support for the MIPS R6 ISA Markos Chandras
2015-01-16 10:48   ` Markos Chandras
2015-01-19 23:56   ` Maciej W. Rozycki
2015-01-16 10:48 ` [PATCH RFC v2 05/70] MIPS: mm: uasm: Add signed 9-bit immediate related macros Markos Chandras
2015-01-16 10:48   ` Markos Chandras
2015-01-16 11:29   ` Sergei Shtylyov
2015-01-19 12:35     ` Markos Chandras
2015-01-19 12:35       ` Markos Chandras
2015-01-19 12:45       ` Markos Chandras
2015-01-19 12:45         ` Markos Chandras
2015-01-19 12:50       ` Sergei Shtylyov
2015-01-16 10:48 ` [PATCH RFC v2 06/70] MIPS: mm: Add MIPS R6 instruction encodings Markos Chandras
2015-01-16 10:48   ` Markos Chandras
2015-01-16 19:15   ` David Daney
2015-01-16 10:48 ` [PATCH RFC v2 07/70] MIPS: asm: asm: Add new macros to set ISA and arch asm annotations Markos Chandras
2015-01-16 10:48   ` Markos Chandras
2015-01-16 10:48 ` [PATCH RFC v2 08/70] MIPS: asm: module: define MODULE_PROC_FAMILY for MIPS R6 Markos Chandras
2015-01-16 10:48   ` Markos Chandras
2015-01-16 10:48 ` [PATCH RFC v2 09/70] MIPS: asm: stackframe: Do not preserve the HI/LO registers on " Markos Chandras
2015-01-16 10:48   ` Markos Chandras
2015-01-16 10:48 ` [PATCH RFC v2 10/70] MIPS: asm: asmmacro: Drop unused 'reg' argument on MIPSR2 Markos Chandras
2015-01-16 10:48   ` Markos Chandras
2015-01-20  0:04   ` Maciej W. Rozycki
2015-01-20  9:49     ` Markos Chandras
2015-01-20  9:49       ` Markos Chandras
2015-01-16 10:48 ` [PATCH RFC v2 11/70] MIPS: asm: asmmacro: Add MIPS R6 support to the simple EI/DI variants Markos Chandras
2015-01-16 10:48   ` Markos Chandras
2015-01-16 10:48 ` [PATCH RFC v2 12/70] MIPS: asm: asmmacro: Replace add instructions with "addui" Markos Chandras
2015-01-16 10:48   ` Markos Chandras
2015-01-19 15:59   ` Maciej W. Rozycki
2015-01-19 16:39     ` Markos Chandras
2015-01-19 16:39       ` Markos Chandras
2015-01-19 19:07       ` Maciej W. Rozycki
2015-01-19 19:25         ` Maciej W. Rozycki
2015-01-20  9:52           ` Markos Chandras
2015-01-20  9:52             ` Markos Chandras
2015-01-20 14:33             ` Matthew Fortune
2015-01-16 10:48 ` [PATCH RFC v2 13/70] MIPS: Use generic checksum functions for MIPS R6 Markos Chandras
2015-01-16 10:48   ` Markos Chandras
2015-01-16 10:48 ` [PATCH RFC v2 14/70] MIPS: asm: cpu: Add MIPSR6 ISA definitions Markos Chandras
2015-01-16 10:48   ` Markos Chandras
2015-01-16 10:48 ` [PATCH RFC v2 15/70] MIPS: asm: hazards: Add MIPSR6 definitions Markos Chandras
2015-01-16 10:48   ` Markos Chandras
2015-01-16 10:48 ` [PATCH RFC v2 16/70] MIPS: asm: irqflags: Add MIPS R6 related definitions Markos Chandras
2015-01-16 10:48   ` Markos Chandras
2015-01-16 10:48 ` [PATCH RFC v2 17/70] MIPS: asm: r4kcache: Add MIPS R6 cache unroll functions Markos Chandras
2015-01-16 10:48   ` Markos Chandras
2015-01-16 10:48 ` [PATCH RFC v2 18/70] MIPS: asm: spram: Add MIPS R6 related definitions Markos Chandras
2015-01-16 10:48   ` Markos Chandras
2015-01-20  0:13   ` Maciej W. Rozycki
2015-01-21 12:16     ` Markos Chandras
2015-01-21 12:16       ` Markos Chandras
2015-01-16 10:48 ` [PATCH RFC v2 19/70] MIPS: Use the new "ZC" constraint for MIPS R6 Markos Chandras
2015-01-16 10:48   ` Markos Chandras
2015-01-20  0:27   ` Maciej W. Rozycki
2015-01-20  9:11     ` Matthew Fortune
2015-01-20  9:35       ` Markos Chandras
2015-01-20 10:08         ` Matthew Fortune
2015-01-20 10:08           ` Matthew Fortune
2015-01-20 10:12           ` Markos Chandras
2015-01-20 14:37             ` Maciej W. Rozycki
2015-01-20 14:46               ` Maciej W. Rozycki
2015-01-21  9:06               ` Markos Chandras
2015-01-26 13:39   ` [PATCH] MIPS: asm: Rename GCC_OFF12_ASM to GCC_OFF_SMALL_ASM Markos Chandras
2015-01-26 13:39     ` Markos Chandras
2015-01-16 10:48 ` [PATCH RFC v2 20/70] MIPS: asm: cmpxchg: Update ISA constraints for MIPS R6 support Markos Chandras
2015-01-16 10:48   ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 21/70] MIPS: asm: atomic: " Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 22/70] MIPS: asm: bitops: " Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 23/70] MIPS: asm: futex: Set the appropriate ISA level for MIPS R6 Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 24/70] MIPS: asm: spinlock: Replace sub instruction with addiu Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-20  1:04   ` Maciej W. Rozycki
2015-01-20 11:29     ` Markos Chandras
2015-01-20 11:29       ` Markos Chandras
2015-01-20 11:47       ` Matthew Fortune
2015-02-10 16:17         ` Maciej W. Rozycki
2015-01-20 17:17       ` David Daney
2015-01-20 22:20         ` Ralf Baechle
2015-01-21  0:58           ` Maciej W. Rozycki
2015-01-16 10:49 ` [PATCH RFC v2 25/70] MIPS: asm: local: Set the appropriate ISA level for MIPS R6 Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 26/70] MIPS: kernel: cpu-bugs64: Do not check R6 cores for existing 64-bit bugs Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-20  1:07   ` Maciej W. Rozycki
2015-01-16 10:49 ` [PATCH RFC v2 27/70] MIPS: kernel: cevt-r4k: Add MIPS R6 to the c0_compare_interrupt handler Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-20  1:22   ` Maciej W. Rozycki
2015-01-20  9:14     ` James Hogan
2015-01-20  9:14       ` James Hogan
2015-01-20 14:33       ` Maciej W. Rozycki
2015-01-21  9:34         ` Markos Chandras
2015-01-21  9:34           ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 28/70] MIPS: kernel: cpu-probe.c: Add support for MIPS R6 Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-20 23:32   ` Maciej W. Rozycki
2015-01-21 11:22     ` Markos Chandras
2015-01-21 11:22       ` Markos Chandras
2015-01-21 11:40     ` James Hogan
2015-01-21 11:40       ` James Hogan
2015-01-16 10:49 ` [PATCH RFC v2 29/70] MIPS: kernel: entry.S: Add MIPS R6 related definitions Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 30/70] MIPS: kernel: proc: Add MIPS R6 support to /proc/cpuinfo Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-20 23:42   ` Maciej W. Rozycki
2015-01-21  9:25     ` Markos Chandras
2015-01-21  9:25       ` Markos Chandras
2015-01-22 14:08       ` Maciej W. Rozycki
2015-01-22 14:43         ` Markos Chandras
2015-01-22 14:43           ` Markos Chandras
2015-01-22 15:03           ` Markos Chandras
2015-01-22 15:03             ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 31/70] MIPS: kernel: traps: Add MIPS R6 related definitions Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-20 23:49   ` Maciej W. Rozycki
2015-01-16 10:49 ` [PATCH RFC v2 32/70] MIPS: kernel: r4k_switch: Add support for MIPS R6 Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 33/70] MIPS: kernel: r4k_fpu: " Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 34/70] MIPS: kernel: genex: Set correct ISA level Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 35/70] MIPS: kernel: cps-vec: Replace addi with addiu Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-21  0:02   ` Maciej W. Rozycki
2015-01-16 10:49 ` [PATCH RFC v2 36/70] MIPS: kernel: unaligned: Add support for the MIPS R6 Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 37/70] MIPS: kernel: syscall: Set the appropriate ISA level for " Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 38/70] MIPS: lib: memcpy: Add MIPS R6 support Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 39/70] MIPS: lib: memset: " Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 40/70] MIPS: mm: page: " Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-17 11:58   ` Sergei Shtylyov
2015-01-19 12:33     ` [PATCH RFC v3 " Markos Chandras
2015-01-19 12:33       ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 41/70] MIPS: mm: tlbex: Use cpu_has_mips_r2_exec_hazard for the EHB instruction Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-02-23 22:03   ` David Daney
2015-02-23 22:07     ` David Daney
2015-02-24  0:33     ` Maciej W. Rozycki
2015-02-24  0:53       ` David Daney
2015-01-16 10:49 ` [PATCH RFC v2 42/70] MIPS: mm: c-r4k: Set the correct ISA level Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 43/70] MIPS: mm: scache: Add secondary cache support for MIPS R6 cores Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 44/70] MIPS: kernel: Prepare the JR instruction for emulation on MIPS R6 Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 45/70] MIPS: kernel: branch: Prevent BLTZL emulation for " Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-21  1:59   ` Maciej W. Rozycki
2015-01-21  1:59     ` Maciej W. Rozycki
2015-01-21 10:43     ` Markos Chandras
2015-01-21 10:43       ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 46/70] MIPS: kernel: branch: Prevent BGEZL " Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-02-03 11:57   ` Maciej W. Rozycki
2015-01-16 10:49 ` [PATCH RFC v2 47/70] MIPS: kernel: branch: Prevent BLTZAL " Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 48/70] MIPS: kernel: branch: Prevent BGEZAL " Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 49/70] MIPS: kernel: branch: Prevent BEQL " Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 50/70] MIPS: kernel: branch: Prevent BNEL " Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 51/70] MIPS: kernel: branch: Prevent BLEZL " Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 52/70] MIPS: kernel: branch: Prevent BGTZL " Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 53/70] MIPS: Emulate the BC1{EQ,NE}Z FPU instructions Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 54/70] MIPS: Emulate the new MIPS R6 B{L,G}Ε{Z,}{AL,}C instructions Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 55/70] MIPS: Emulate the new MIPS R6 B{L,G}T{Z,}{AL,}C instructions Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 56/70] MIPS: Emulate the new MIPS R6 branch compact (BC) instruction Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 57/70] MIPS: Emulate the new MIPS R6 BOVC, BEQC and BEQZALC instructions Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-17 13:24   ` Sergei Shtylyov
2015-01-19  9:48     ` Markos Chandras
2015-01-19  9:48       ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 58/70] MIPS: Emulate the new MIPS R6 BNVC, BNEC and BNEZLAC instructions Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 59/70] MIPS: Emulate the new MIPS R6 BALC instruction Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 60/70] MIPS: Emulate the new MIPS R6 BEQZC and JIC instructions Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 61/70] MIPS: Emulate the new MIPS R6 BNEZC and JIALC instructions Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 62/70] MIPS: Add LLB bit and related feature for the Config 5 CP0 register Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 63/70] MIPS: asm: mipsregs: Add support for the LLADDR register Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 64/70] MIPS: kernel: mips-r2-to-r6-emul: Add R2 emulator for MIPS R6 Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 65/70] MIPS: Make use of the ERETNC instruction on " Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 66/70] MIPS: Handle MIPS IV, V and R2 FPU instructions on MIPS R6 as well Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 67/70] MIPS: kernel: process: Do not allow FR=0 on MIPS R6 Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-16 11:54   ` Matthew Fortune
2015-01-16 15:33     ` Markos Chandras
2015-01-29 23:13   ` Paul Burton
2015-01-29 23:13     ` Paul Burton
2015-01-30 10:18     ` Markos Chandras
2015-01-30 10:18       ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 68/70] MIPS: kernel: elf: Improve the overall ABI and FPU mode checks Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-16 12:28   ` Matthew Fortune
2015-01-19  9:29   ` Matthew Fortune
2015-01-19 12:17     ` Markos Chandras
2015-01-29 23:22       ` Paul Burton
2015-01-30 10:23         ` Markos Chandras
2015-02-03 12:41     ` Maciej W. Rozycki
2015-01-29 21:51   ` Matthew Fortune
2015-02-02 16:13     ` [PATCH v3] " Markos Chandras
2015-02-02 16:13       ` Markos Chandras
2015-02-24 13:17       ` Måns Rullgård
2015-02-24 13:17         ` Måns Rullgård
2015-02-24 13:52         ` Markos Chandras
2015-02-24 13:52           ` Markos Chandras
2015-02-24 14:06           ` Måns Rullgård
2015-02-24 14:06             ` Måns Rullgård
2015-02-24 14:26             ` Matthew Fortune
2015-02-26  8:59               ` Markos Chandras
2015-02-26  9:14                 ` Måns Rullgård
2015-02-26  9:14                   ` Måns Rullgård
2015-02-26  9:24                   ` Markos Chandras
2015-02-26  9:31                     ` Matthew Fortune
2015-02-26  9:44                       ` Markos Chandras
2015-02-26 10:31                         ` Måns Rullgård
2015-02-26 10:31                           ` Måns Rullgård
2015-02-26 11:11     ` [PATCH] MIPS: asm: elf: Set O32 default FPU flags Markos Chandras
2015-02-26 11:11       ` Markos Chandras
2015-02-26 11:21       ` Måns Rullgård
2015-02-26 11:21         ` Måns Rullgård
2015-02-27  1:28       ` Aaro Koskinen
2015-02-27  1:46         ` Måns Rullgård
2015-04-07 16:36       ` Maciej W. Rozycki
2015-04-12 23:21         ` Aaro Koskinen
2015-04-20 11:55           ` Maciej W. Rozycki
2015-02-03 12:40   ` [PATCH RFC v2 68/70] MIPS: kernel: elf: Improve the overall ABI and FPU mode checks Maciej W. Rozycki
2015-01-16 10:49 ` [PATCH RFC v2 69/70] MIPS: Malta: Add support for building MIPS R6 kernel Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-01-16 10:49 ` [PATCH RFC v2 70/70] MIPS: Add Malta QEMU 32R6 defconfig Markos Chandras
2015-01-16 10:49   ` Markos Chandras
2015-02-12 23:12 ` [PATCH RFC v2 00/70] Add MIPS R6 support David Daney
2015-02-12 23:12   ` David Daney

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.