* [PATCH 1/5] MIPS: clarify mips_cm_is64 documentation
2015-09-22 17:26 [PATCH 0/5] CM error report fixes Paul Burton
@ 2015-09-22 17:26 ` Paul Burton
2015-09-22 17:26 ` [PATCH 2/5] MIPS: don't read GCRs when a CM is not present Paul Burton
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Paul Burton @ 2015-09-22 17:26 UTC (permalink / raw)
To: linux-mips
Cc: Paul Burton, linux-kernel, James Hogan, Markos Chandras, Ralf Baechle
The documentation for mips_cm_is64 implied that the width of the CM GCRs
would change depending upon the CPU, which is not true. Reword the
explanation to be clearer that the GCR width is purely dependent upon
the version of the CM.
Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
arch/mips/include/asm/mips-cm.h | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h
index d75b75e..2a70b76 100644
--- a/arch/mips/include/asm/mips-cm.h
+++ b/arch/mips/include/asm/mips-cm.h
@@ -36,12 +36,12 @@ extern phys_addr_t __mips_cm_phys_base(void);
/*
* mips_cm_is64 - determine CM register width
*
- * The CM register width is processor and CM specific. A 64-bit processor
- * usually has a 64-bit CM and a 32-bit one has a 32-bit CM but a 64-bit
- * processor could come with a 32-bit CM. Moreover, accesses on 64-bit CMs
- * can be done either using regular 64-bit load/store instructions, or 32-bit
- * load/store instruction on 32-bit register pairs. We opt for using 64-bit
- * accesses on 64-bit CMs and kernels and 32-bit in any other case.
+ * The CM register width is determined by the version of the CM, with CM3
+ * introducing 64 bit GCRs and all prior CM versions having 32 bit GCRs.
+ * However we may run a kernel built for MIPS32 on a system with 64 bit GCRs,
+ * or vice-versa. This variable indicates the width of the memory accesses
+ * that the kernel will perform to GCRs, which may differ from the actual
+ * width of the GCRs.
*
* It's set to 0 for 32-bit accesses and 1 for 64-bit accesses.
*/
--
2.5.3
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH 2/5] MIPS: don't read GCRs when a CM is not present
2015-09-22 17:26 [PATCH 0/5] CM error report fixes Paul Burton
2015-09-22 17:26 ` [PATCH 1/5] MIPS: clarify mips_cm_is64 documentation Paul Burton
@ 2015-09-22 17:26 ` Paul Burton
2015-09-22 17:26 ` [PATCH 3/5] MIPS: avoid buffer overrun in mips_cm_error_report Paul Burton
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Paul Burton @ 2015-09-22 17:26 UTC (permalink / raw)
To: linux-mips; +Cc: Paul Burton, Markos Chandras, Ralf Baechle, linux-kernel
Commit 3885c2b463f6 ("MIPS: CM: Add support for reporting CM cache
errors") leads to Malta boards unconditionally reading CM GCRs upon bus
errors, regardless of whether a CM is present. This is incorrect & will
lead to further exceptions. Fix by moving the GCR reads to after the
check for whether a CM is present.
Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
arch/mips/kernel/mips-cm.c | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c
index b8ceee5..10524ce 100644
--- a/arch/mips/kernel/mips-cm.c
+++ b/arch/mips/kernel/mips-cm.c
@@ -252,7 +252,6 @@ int mips_cm_probe(void)
void mips_cm_error_report(void)
{
- unsigned long revision = mips_cm_revision();
/*
* CM3 has a 64-bit Error cause register with 0:57 containing the error
* info and 63:58 the error type. For old CMs, everything is contained
@@ -260,17 +259,21 @@ void mips_cm_error_report(void)
* though the cm_error is u64, we will simply ignore the upper word
* for CM2.
*/
- u64 cm_error = read_gcr_error_cause();
- int cm_error_cause_sft = CM_GCR_ERROR_CAUSE_ERRTYPE_SHF +
- ((revision >= CM_REV_CM3) ? 31 : 0);
- unsigned long cm_addr = read_gcr_error_addr();
- unsigned long cm_other = read_gcr_error_mult();
- int ocause, cause;
+ u64 cm_error;
+ unsigned long revision, cm_addr, cm_other;
+ int ocause, cause, cm_error_cause_sft;
char buf[256];
if (!mips_cm_present())
return;
+ revision = mips_cm_revision();
+ cm_error = read_gcr_error_cause();
+ cm_addr = read_gcr_error_addr();
+ cm_other = read_gcr_error_mult();
+
+ cm_error_cause_sft = CM_GCR_ERROR_CAUSE_ERRTYPE_SHF +
+ ((revision >= CM_REV_CM3) ? 31 : 0);
cause = cm_error >> cm_error_cause_sft;
if (!cause)
--
2.5.3
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH 3/5] MIPS: avoid buffer overrun in mips_cm_error_report
2015-09-22 17:26 [PATCH 0/5] CM error report fixes Paul Burton
2015-09-22 17:26 ` [PATCH 1/5] MIPS: clarify mips_cm_is64 documentation Paul Burton
2015-09-22 17:26 ` [PATCH 2/5] MIPS: don't read GCRs when a CM is not present Paul Burton
@ 2015-09-22 17:26 ` Paul Burton
2015-09-22 17:26 ` [PATCH 4/5] MIPS: allow read64 GCR accessors to work on MIPS32 kernels Paul Burton
2015-09-22 17:26 ` [PATCH 5/5] MIPS: always read full 64 bit CM error GCRs for CM3 Paul Burton
4 siblings, 0 replies; 6+ messages in thread
From: Paul Burton @ 2015-09-22 17:26 UTC (permalink / raw)
To: linux-mips; +Cc: Paul Burton, Markos Chandras, Ralf Baechle, linux-kernel
Commit 3885c2b463f6 ("MIPS: CM: Add support for reporting CM cache
errors") added cases for decoding errors reported by CM3, but leaves the
buf variable which is printed as a string uninitialised for cause values
other than 1, 2 or 3. Fix by ensuring the buf variable is initialised to
an empty string in such cases.
Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
arch/mips/kernel/mips-cm.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c
index 10524ce..88a8e21 100644
--- a/arch/mips/kernel/mips-cm.c
+++ b/arch/mips/kernel/mips-cm.c
@@ -366,6 +366,8 @@ void mips_cm_error_report(void)
cm3_cmd_group[cmd_group_bits],
cm3_cca_bits, 1 << mcp_bits,
cm3_tr[cm3_tr_bits], sched_bit);
+ } else {
+ buf[0] = 0;
}
pr_err("CM_ERROR=%llx %s <%s>\n", cm_error,
--
2.5.3
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH 4/5] MIPS: allow read64 GCR accessors to work on MIPS32 kernels
2015-09-22 17:26 [PATCH 0/5] CM error report fixes Paul Burton
` (2 preceding siblings ...)
2015-09-22 17:26 ` [PATCH 3/5] MIPS: avoid buffer overrun in mips_cm_error_report Paul Burton
@ 2015-09-22 17:26 ` Paul Burton
2015-09-22 17:26 ` [PATCH 5/5] MIPS: always read full 64 bit CM error GCRs for CM3 Paul Burton
4 siblings, 0 replies; 6+ messages in thread
From: Paul Burton @ 2015-09-22 17:26 UTC (permalink / raw)
To: linux-mips
Cc: Paul Burton, linux-kernel, James Hogan, Markos Chandras, Ralf Baechle
If we run a MIPS32 kernel on a system using CM3 we may still need to
access 64 bit GCRs, as will be done in later patches. Allow this by
having the read64_gcr_* accessor functions perform 2 x 32 bit reads on
those systems.
Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
arch/mips/include/asm/mips-cm.h | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h
index 2a70b76..b9df4b2 100644
--- a/arch/mips/include/asm/mips-cm.h
+++ b/arch/mips/include/asm/mips-cm.h
@@ -125,7 +125,17 @@ static inline u32 read32_gcr_##name(void) \
\
static inline u64 read64_gcr_##name(void) \
{ \
- return __raw_readq(addr_gcr_##name()); \
+ void __iomem *addr = addr_gcr_##name(); \
+ u64 ret; \
+ \
+ if (mips_cm_is64) { \
+ ret = __raw_readq(addr); \
+ } else { \
+ ret = __raw_readl(addr); \
+ ret |= (u64)__raw_readl(addr + 0x4) << 32; \
+ } \
+ \
+ return ret; \
} \
\
static inline unsigned long read_gcr_##name(void) \
--
2.5.3
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH 5/5] MIPS: always read full 64 bit CM error GCRs for CM3
2015-09-22 17:26 [PATCH 0/5] CM error report fixes Paul Burton
` (3 preceding siblings ...)
2015-09-22 17:26 ` [PATCH 4/5] MIPS: allow read64 GCR accessors to work on MIPS32 kernels Paul Burton
@ 2015-09-22 17:26 ` Paul Burton
4 siblings, 0 replies; 6+ messages in thread
From: Paul Burton @ 2015-09-22 17:26 UTC (permalink / raw)
To: linux-mips
Cc: Paul Burton, linux-kernel, James Hogan, Markos Chandras, Ralf Baechle
CM3 has 64 bit GCR_ERROR_* registers, but the code in
mips_cm_error_report was previously only reading 32 bits of it in MIPS32
kernels. Fix by splitting the reads for CM2 & CM3, and making use of the
read64_ variants of the accessor function for CM3.
Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
arch/mips/include/asm/mips-cm.h | 3 ++
arch/mips/kernel/mips-cm.c | 70 +++++++++++++++++++++--------------------
2 files changed, 39 insertions(+), 34 deletions(-)
diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h
index b9df4b2..82e7e92 100644
--- a/arch/mips/include/asm/mips-cm.h
+++ b/arch/mips/include/asm/mips-cm.h
@@ -11,6 +11,7 @@
#ifndef __MIPS_ASM_MIPS_CM_H__
#define __MIPS_ASM_MIPS_CM_H__
+#include <linux/bitops.h>
#include <linux/errno.h>
#include <linux/io.h>
#include <linux/types.h>
@@ -259,6 +260,8 @@ BUILD_CM_Cx_R_(tcid_8_priority, 0x80)
/* GCR_ERROR_CAUSE register fields */
#define CM_GCR_ERROR_CAUSE_ERRTYPE_SHF 27
#define CM_GCR_ERROR_CAUSE_ERRTYPE_MSK (_ULCAST_(0x1f) << 27)
+#define CM3_GCR_ERROR_CAUSE_ERRTYPE_SHF 58
+#define CM3_GCR_ERROR_CAUSE_ERRTYPE_MSK GENMASK_ULL(63, 58)
#define CM_GCR_ERROR_CAUSE_ERRINFO_SHF 0
#define CM_GCR_ERROR_CAUSE_ERRINGO_MSK (_ULCAST_(0x7ffffff) << 0)
diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c
index 88a8e21..02f7d7a 100644
--- a/arch/mips/kernel/mips-cm.c
+++ b/arch/mips/kernel/mips-cm.c
@@ -252,36 +252,26 @@ int mips_cm_probe(void)
void mips_cm_error_report(void)
{
- /*
- * CM3 has a 64-bit Error cause register with 0:57 containing the error
- * info and 63:58 the error type. For old CMs, everything is contained
- * in a single 32-bit register (0:26 and 31:27 respectively). Even
- * though the cm_error is u64, we will simply ignore the upper word
- * for CM2.
- */
- u64 cm_error;
- unsigned long revision, cm_addr, cm_other;
- int ocause, cause, cm_error_cause_sft;
+ u64 cm_error, cm_addr, cm_other;
+ unsigned long revision;
+ int ocause, cause;
char buf[256];
if (!mips_cm_present())
return;
revision = mips_cm_revision();
- cm_error = read_gcr_error_cause();
- cm_addr = read_gcr_error_addr();
- cm_other = read_gcr_error_mult();
- cm_error_cause_sft = CM_GCR_ERROR_CAUSE_ERRTYPE_SHF +
- ((revision >= CM_REV_CM3) ? 31 : 0);
- cause = cm_error >> cm_error_cause_sft;
+ if (revision < CM_REV_CM3) { /* CM2 */
+ cm_error = read_gcr_error_cause();
+ cm_addr = read_gcr_error_addr();
+ cm_other = read_gcr_error_mult();
+ cause = cm_error >> CM_GCR_ERROR_CAUSE_ERRTYPE_SHF;
+ ocause = cm_other >> CM_GCR_ERROR_MULT_ERR2ND_SHF;
- if (!cause)
- /* All good */
- return;
+ if (!cause)
+ return;
- ocause = cm_other >> CM_GCR_ERROR_MULT_ERR2ND_SHF;
- if (revision < CM_REV_CM3) { /* CM2 */
if (cause < 16) {
unsigned long cca_bits = (cm_error >> 15) & 7;
unsigned long tr_bits = (cm_error >> 12) & 7;
@@ -313,18 +303,30 @@ void mips_cm_error_report(void)
}
pr_err("CM_ERROR=%08llx %s <%s>\n", cm_error,
cm2_causes[cause], buf);
- pr_err("CM_ADDR =%08lx\n", cm_addr);
- pr_err("CM_OTHER=%08lx %s\n", cm_other, cm2_causes[ocause]);
+ pr_err("CM_ADDR =%08llx\n", cm_addr);
+ pr_err("CM_OTHER=%08llx %s\n", cm_other, cm2_causes[ocause]);
} else { /* CM3 */
- /* Used by cause == {1,2,3} */
- unsigned long core_id_bits = (cm_error >> 22) & 0xf;
- unsigned long vp_id_bits = (cm_error >> 18) & 0xf;
- unsigned long cmd_bits = (cm_error >> 14) & 0xf;
- unsigned long cmd_group_bits = (cm_error >> 11) & 0xf;
- unsigned long cm3_cca_bits = (cm_error >> 8) & 7;
- unsigned long mcp_bits = (cm_error >> 5) & 0xf;
- unsigned long cm3_tr_bits = (cm_error >> 1) & 0xf;
- unsigned long sched_bit = cm_error & 0x1;
+ ulong core_id_bits, vp_id_bits, cmd_bits, cmd_group_bits;
+ ulong cm3_cca_bits, mcp_bits, cm3_tr_bits, sched_bit;
+
+ cm_error = read64_gcr_error_cause();
+ cm_addr = read64_gcr_error_addr();
+ cm_other = read64_gcr_error_mult();
+ cause = cm_error >> CM3_GCR_ERROR_CAUSE_ERRTYPE_SHF;
+ ocause = cm_other >> CM_GCR_ERROR_MULT_ERR2ND_SHF;
+
+ if (!cause)
+ return;
+
+ /* Used by cause == {1,2,3} */
+ core_id_bits = (cm_error >> 22) & 0xf;
+ vp_id_bits = (cm_error >> 18) & 0xf;
+ cmd_bits = (cm_error >> 14) & 0xf;
+ cmd_group_bits = (cm_error >> 11) & 0xf;
+ cm3_cca_bits = (cm_error >> 8) & 7;
+ mcp_bits = (cm_error >> 5) & 0xf;
+ cm3_tr_bits = (cm_error >> 1) & 0xf;
+ sched_bit = cm_error & 0x1;
if (cause == 1 || cause == 3) { /* Tag ECC */
unsigned long tag_ecc = (cm_error >> 57) & 0x1;
@@ -372,8 +374,8 @@ void mips_cm_error_report(void)
pr_err("CM_ERROR=%llx %s <%s>\n", cm_error,
cm3_causes[cause], buf);
- pr_err("CM_ADDR =%lx\n", cm_addr);
- pr_err("CM_OTHER=%lx %s\n", cm_other, cm3_causes[ocause]);
+ pr_err("CM_ADDR =%llx\n", cm_addr);
+ pr_err("CM_OTHER=%llx %s\n", cm_other, cm3_causes[ocause]);
}
/* reprime cause register */
--
2.5.3
^ permalink raw reply [flat|nested] 6+ messages in thread