MIPS: Add defs & probing of BadInstr[P] registers
authorJames Hogan <james.hogan@imgtec.com>
Wed, 11 May 2016 12:50:51 +0000 (13:50 +0100)
committerRalf Baechle <ralf@linux-mips.org>
Fri, 13 May 2016 13:30:25 +0000 (15:30 +0200)
The optional CP0_BadInstr and CP0_BadInstrP registers are written with
the encoding of the instruction that caused a synchronous exception to
occur, and the prior branch instruction if in a delay slot.

These will be useful for instruction emulation in KVM, and especially
for VZ support where reading guest virtual memory is a bit more awkward.

Add CPU option numbers and cpu_has_* definitions to indicate the
presence of each registers, and add code to probe for them using bits in
the CP0_Config3 register.

[ralf@linux-mips.org: resolve merge conflict.]

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/13224/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
arch/mips/include/asm/cpu-features.h
arch/mips/include/asm/cpu.h
arch/mips/include/asm/mipsregs.h
arch/mips/kernel/cpu-probe.c

index 676a37b9c37ec8280906260e272df9f397076d88..5d82b01ef8b50f0c5b66f1b902079684c819ad21 100644 (file)
 # define cpu_has_ebase_wg      (cpu_data[0].options & MIPS_CPU_EBASE_WG)
 #endif
 
+#ifndef cpu_has_badinstr
+# define cpu_has_badinstr      (cpu_data[0].options & MIPS_CPU_BADINSTR)
+#endif
+
+#ifndef cpu_has_badinstrp
+# define cpu_has_badinstrp     (cpu_data[0].options & MIPS_CPU_BADINSTRP)
+#endif
+
 #endif /* __ASM_CPU_FEATURES_H */
index 3108d9b35bf1d3cea9a2973e364aa7668219f44a..0cf90d67c1af7ce1d6cc0757b1b70a32b7f785a9 100644 (file)
@@ -405,6 +405,8 @@ enum cpu_type_enum {
 #define MIPS_CPU_LDPTE         MBIT_ULL(41)    /* CPU has ldpte/lddir instructions */
 #define MIPS_CPU_MVH           MBIT_ULL(42)    /* CPU supports MFHC0/MTHC0 */
 #define MIPS_CPU_EBASE_WG      MBIT_ULL(43)    /* CPU has EBase.WG */
+#define MIPS_CPU_BADINSTR      MBIT_ULL(44)    /* CPU has BadInstr register */
+#define MIPS_CPU_BADINSTRP     MBIT_ULL(45)    /* CPU has BadInstrP register */
 
 /*
  * CPU ASE encodings
index 4e8ad9d6038a680459747a8918f1bc999467537d..b1f8f8436fd1850e09bc9320c0ecbe1797a89794 100644 (file)
@@ -1248,6 +1248,9 @@ do {                                                                      \
 #define read_c0_badvaddr()     __read_ulong_c0_register($8, 0)
 #define write_c0_badvaddr(val) __write_ulong_c0_register($8, 0, val)
 
+#define read_c0_badinstr()     __read_32bit_c0_register($8, 1)
+#define read_c0_badinstrp()    __read_32bit_c0_register($8, 2)
+
 #define read_c0_count()                __read_32bit_c0_register($9, 0)
 #define write_c0_count(val)    __write_32bit_c0_register($9, 0, val)
 
index 6a1a7da4b2d2a4cd2baaf4473961a1f6e33abe09..8e54d51c14bc471a92ea7d6857bf01deca2e0c15 100644 (file)
@@ -714,6 +714,10 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c)
                c->ases |= MIPS_ASE_VZ;
        if (config3 & MIPS_CONF3_SC)
                c->options |= MIPS_CPU_SEGMENTS;
+       if (config3 & MIPS_CONF3_BI)
+               c->options |= MIPS_CPU_BADINSTR;
+       if (config3 & MIPS_CONF3_BP)
+               c->options |= MIPS_CPU_BADINSTRP;
        if (config3 & MIPS_CONF3_MSA)
                c->ases |= MIPS_ASE_MSA;
        if (config3 & MIPS_CONF3_PW) {