diff mbox series

[1/2] MIPS: Loongson64: Guard against future cores without CPUCFG

Message ID 20200529171000.8905-2-git@xen0n.name (mailing list archive)
State Superseded
Headers show
Series CPUCFG emulation future-proofing & HWCAP addition | expand

Commit Message

WANG Xuerui May 29, 2020, 5:09 p.m. UTC
Previously it was thought that all future Loongson cores would come with
native CPUCFG. From new information shared by Huacai this is definitely
not true (maybe some future 2K cores, for example), so collisions at
PRID_REV level are inevitable. The CPU model matching needs to take
PRID_IMP into consideration.

The emulation logic needs to be disabled for those future cores as well,
as we cannot possibly encode their non-discoverable features right now.

Reported-by: Huacai Chen <chenhc@lemote.com>
Cc: Jiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: WANG Xuerui <git@xen0n.name>
---
 .../include/asm/mach-loongson64/cpucfg-emul.h | 11 ++++++
 arch/mips/kernel/traps.c                      |  4 ++
 arch/mips/loongson64/cpucfg-emul.c            | 37 ++++++++++---------
 3 files changed, 35 insertions(+), 17 deletions(-)

Comments

Huacai Chen May 30, 2020, 4:26 a.m. UTC | #1
Hi, Xuerui,

On Sat, May 30, 2020 at 1:11 AM WANG Xuerui <git@xen0n.name> wrote:
>
> Previously it was thought that all future Loongson cores would come with
> native CPUCFG. From new information shared by Huacai this is definitely
> not true (maybe some future 2K cores, for example), so collisions at
> PRID_REV level are inevitable. The CPU model matching needs to take
> PRID_IMP into consideration.
>
> The emulation logic needs to be disabled for those future cores as well,
> as we cannot possibly encode their non-discoverable features right now.
>
> Reported-by: Huacai Chen <chenhc@lemote.com>
> Cc: Jiaxun Yang <jiaxun.yang@flygoat.com>
> Signed-off-by: WANG Xuerui <git@xen0n.name>
> ---
>  .../include/asm/mach-loongson64/cpucfg-emul.h | 11 ++++++
>  arch/mips/kernel/traps.c                      |  4 ++
>  arch/mips/loongson64/cpucfg-emul.c            | 37 ++++++++++---------
>  3 files changed, 35 insertions(+), 17 deletions(-)
>
> diff --git a/arch/mips/include/asm/mach-loongson64/cpucfg-emul.h b/arch/mips/include/asm/mach-loongson64/cpucfg-emul.h
> index 01dc308df7b2..d64af19c210d 100644
> --- a/arch/mips/include/asm/mach-loongson64/cpucfg-emul.h
> +++ b/arch/mips/include/asm/mach-loongson64/cpucfg-emul.h
> @@ -12,6 +12,12 @@
>
>  void loongson3_cpucfg_synthesize_data(struct cpuinfo_mips *c);
>
> +static inline bool loongson3_cpucfg_emulation_enabled(struct cpuinfo_mips *c)
> +{
> +       /* All supported cores have non-zero LOONGSON_CFG1 data. */
> +       return c->loongson3_cpucfg_data[0] != 0;
> +}
> +
>  static inline u32 loongson3_cpucfg_read_synthesized(struct cpuinfo_mips *c,
>         __u64 sel)
>  {
> @@ -53,6 +59,11 @@ static inline void loongson3_cpucfg_synthesize_data(struct cpuinfo_mips *c)
>  {
>  }
>
> +static inline bool loongson3_cpucfg_emulation_enabled(struct cpuinfo_mips *c)
> +{
> +       return false;
> +}
> +
>  static inline u32 loongson3_cpucfg_read_synthesized(struct cpuinfo_mips *c,
>         __u64 sel)
>  {
> diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
> index 2d5b16daf331..caff4c921461 100644
> --- a/arch/mips/kernel/traps.c
> +++ b/arch/mips/kernel/traps.c
> @@ -720,6 +720,10 @@ static int simulate_loongson3_cpucfg(struct pt_regs *regs,
>                 int rs = (opcode & RS) >> 21;
>                 __u64 sel = regs->regs[rs];
>
> +               /* Do not emulate on unsupported core models. */
> +               if (!loongson3_cpucfg_emulation_enabled(&current_cpu_data))
> +                       return -1;
> +
>                 perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
>
>                 regs->regs[rd] = loongson3_cpucfg_read_synthesized(
> diff --git a/arch/mips/loongson64/cpucfg-emul.c b/arch/mips/loongson64/cpucfg-emul.c
> index fdd52b21c1df..c16023a13379 100644
> --- a/arch/mips/loongson64/cpucfg-emul.c
> +++ b/arch/mips/loongson64/cpucfg-emul.c
> @@ -134,13 +134,9 @@ void loongson3_cpucfg_synthesize_data(struct cpuinfo_mips *c)
>         c->loongson3_cpucfg_data[1] = 0;
>         c->loongson3_cpucfg_data[2] = 0;
>
> -       /* Add CPUCFG features non-discoverable otherwise.
> -        *
> -        * All Loongson processors covered by CPUCFG emulation have distinct
> -        * PRID_REV, so take advantage of this.
> -        */
> -       switch (c->processor_id & PRID_REV_MASK) {
> -       case PRID_REV_LOONGSON3A_R1:
> +       /* Add CPUCFG features non-discoverable otherwise. */
> +       switch (c->processor_id & (PRID_IMP_MASK | PRID_REV_MASK)) {
> +       case PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R1:
>                 c->loongson3_cpucfg_data[0] |= (LOONGSON_CFG1_LSLDR0 |
>                         LOONGSON_CFG1_LSSYNCI | LOONGSON_CFG1_LSUCA |
>                         LOONGSON_CFG1_LLSYNC | LOONGSON_CFG1_TGTSYNC);
> @@ -153,8 +149,8 @@ void loongson3_cpucfg_synthesize_data(struct cpuinfo_mips *c)
>                         LOONGSON_CFG3_LCAMVW_REV1);
>                 break;
>
> -       case PRID_REV_LOONGSON3B_R1:
> -       case PRID_REV_LOONGSON3B_R2:
> +       case PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3B_R1:
> +       case PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3B_R2:
>                 c->loongson3_cpucfg_data[0] |= (LOONGSON_CFG1_LSLDR0 |
>                         LOONGSON_CFG1_LSSYNCI | LOONGSON_CFG1_LSUCA |
>                         LOONGSON_CFG1_LLSYNC | LOONGSON_CFG1_TGTSYNC);
> @@ -167,10 +163,10 @@ void loongson3_cpucfg_synthesize_data(struct cpuinfo_mips *c)
>                         LOONGSON_CFG3_LCAMVW_REV1);
>                 break;
>
> -       case PRID_REV_LOONGSON2K_R1_0:
> -       case PRID_REV_LOONGSON2K_R1_1:
> -       case PRID_REV_LOONGSON2K_R1_2:
> -       case PRID_REV_LOONGSON2K_R1_3:
> +       case PRID_IMP_LOONGSON_64R | PRID_REV_LOONGSON2K_R1_0:
> +       case PRID_IMP_LOONGSON_64R | PRID_REV_LOONGSON2K_R1_1:
> +       case PRID_IMP_LOONGSON_64R | PRID_REV_LOONGSON2K_R1_2:
> +       case PRID_IMP_LOONGSON_64R | PRID_REV_LOONGSON2K_R1_3:
>                 decode_loongson_config6(c);
>                 probe_uca(c);
>
> @@ -183,10 +179,10 @@ void loongson3_cpucfg_synthesize_data(struct cpuinfo_mips *c)
>                 c->loongson3_cpucfg_data[2] = 0;
>                 break;
>
> -       case PRID_REV_LOONGSON3A_R2_0:
> -       case PRID_REV_LOONGSON3A_R2_1:
> -       case PRID_REV_LOONGSON3A_R3_0:
> -       case PRID_REV_LOONGSON3A_R3_1:
> +       case PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R2_0:
> +       case PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R2_1:
> +       case PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R3_0:
> +       case PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R3_1:
>                 decode_loongson_config6(c);
>                 probe_uca(c);
>
> @@ -203,6 +199,13 @@ void loongson3_cpucfg_synthesize_data(struct cpuinfo_mips *c)
>                         LOONGSON_CFG3_LCAMKW_REV1 |
>                         LOONGSON_CFG3_LCAMVW_REV1);
>                 break;
I think it is better to use alpha-betical style here, which means move
Loongson-3B after Loongson-3A (not before Loongson-2K).

> +
> +       default:
> +               /* It is possible that some future Loongson cores still do
> +                * not have CPUCFG, so do not emulate anything for these
> +                * cores.
> +                */
> +               return;
>         }
>
>         /* This feature is set by firmware, but all known Loongson-64 systems
> --
> 2.26.2
>
diff mbox series

Patch

diff --git a/arch/mips/include/asm/mach-loongson64/cpucfg-emul.h b/arch/mips/include/asm/mach-loongson64/cpucfg-emul.h
index 01dc308df7b2..d64af19c210d 100644
--- a/arch/mips/include/asm/mach-loongson64/cpucfg-emul.h
+++ b/arch/mips/include/asm/mach-loongson64/cpucfg-emul.h
@@ -12,6 +12,12 @@ 
 
 void loongson3_cpucfg_synthesize_data(struct cpuinfo_mips *c);
 
+static inline bool loongson3_cpucfg_emulation_enabled(struct cpuinfo_mips *c)
+{
+	/* All supported cores have non-zero LOONGSON_CFG1 data. */
+	return c->loongson3_cpucfg_data[0] != 0;
+}
+
 static inline u32 loongson3_cpucfg_read_synthesized(struct cpuinfo_mips *c,
 	__u64 sel)
 {
@@ -53,6 +59,11 @@  static inline void loongson3_cpucfg_synthesize_data(struct cpuinfo_mips *c)
 {
 }
 
+static inline bool loongson3_cpucfg_emulation_enabled(struct cpuinfo_mips *c)
+{
+	return false;
+}
+
 static inline u32 loongson3_cpucfg_read_synthesized(struct cpuinfo_mips *c,
 	__u64 sel)
 {
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 2d5b16daf331..caff4c921461 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -720,6 +720,10 @@  static int simulate_loongson3_cpucfg(struct pt_regs *regs,
 		int rs = (opcode & RS) >> 21;
 		__u64 sel = regs->regs[rs];
 
+		/* Do not emulate on unsupported core models. */
+		if (!loongson3_cpucfg_emulation_enabled(&current_cpu_data))
+			return -1;
+
 		perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
 
 		regs->regs[rd] = loongson3_cpucfg_read_synthesized(
diff --git a/arch/mips/loongson64/cpucfg-emul.c b/arch/mips/loongson64/cpucfg-emul.c
index fdd52b21c1df..c16023a13379 100644
--- a/arch/mips/loongson64/cpucfg-emul.c
+++ b/arch/mips/loongson64/cpucfg-emul.c
@@ -134,13 +134,9 @@  void loongson3_cpucfg_synthesize_data(struct cpuinfo_mips *c)
 	c->loongson3_cpucfg_data[1] = 0;
 	c->loongson3_cpucfg_data[2] = 0;
 
-	/* Add CPUCFG features non-discoverable otherwise.
-	 *
-	 * All Loongson processors covered by CPUCFG emulation have distinct
-	 * PRID_REV, so take advantage of this.
-	 */
-	switch (c->processor_id & PRID_REV_MASK) {
-	case PRID_REV_LOONGSON3A_R1:
+	/* Add CPUCFG features non-discoverable otherwise. */
+	switch (c->processor_id & (PRID_IMP_MASK | PRID_REV_MASK)) {
+	case PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R1:
 		c->loongson3_cpucfg_data[0] |= (LOONGSON_CFG1_LSLDR0 |
 			LOONGSON_CFG1_LSSYNCI | LOONGSON_CFG1_LSUCA |
 			LOONGSON_CFG1_LLSYNC | LOONGSON_CFG1_TGTSYNC);
@@ -153,8 +149,8 @@  void loongson3_cpucfg_synthesize_data(struct cpuinfo_mips *c)
 			LOONGSON_CFG3_LCAMVW_REV1);
 		break;
 
-	case PRID_REV_LOONGSON3B_R1:
-	case PRID_REV_LOONGSON3B_R2:
+	case PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3B_R1:
+	case PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3B_R2:
 		c->loongson3_cpucfg_data[0] |= (LOONGSON_CFG1_LSLDR0 |
 			LOONGSON_CFG1_LSSYNCI | LOONGSON_CFG1_LSUCA |
 			LOONGSON_CFG1_LLSYNC | LOONGSON_CFG1_TGTSYNC);
@@ -167,10 +163,10 @@  void loongson3_cpucfg_synthesize_data(struct cpuinfo_mips *c)
 			LOONGSON_CFG3_LCAMVW_REV1);
 		break;
 
-	case PRID_REV_LOONGSON2K_R1_0:
-	case PRID_REV_LOONGSON2K_R1_1:
-	case PRID_REV_LOONGSON2K_R1_2:
-	case PRID_REV_LOONGSON2K_R1_3:
+	case PRID_IMP_LOONGSON_64R | PRID_REV_LOONGSON2K_R1_0:
+	case PRID_IMP_LOONGSON_64R | PRID_REV_LOONGSON2K_R1_1:
+	case PRID_IMP_LOONGSON_64R | PRID_REV_LOONGSON2K_R1_2:
+	case PRID_IMP_LOONGSON_64R | PRID_REV_LOONGSON2K_R1_3:
 		decode_loongson_config6(c);
 		probe_uca(c);
 
@@ -183,10 +179,10 @@  void loongson3_cpucfg_synthesize_data(struct cpuinfo_mips *c)
 		c->loongson3_cpucfg_data[2] = 0;
 		break;
 
-	case PRID_REV_LOONGSON3A_R2_0:
-	case PRID_REV_LOONGSON3A_R2_1:
-	case PRID_REV_LOONGSON3A_R3_0:
-	case PRID_REV_LOONGSON3A_R3_1:
+	case PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R2_0:
+	case PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R2_1:
+	case PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R3_0:
+	case PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R3_1:
 		decode_loongson_config6(c);
 		probe_uca(c);
 
@@ -203,6 +199,13 @@  void loongson3_cpucfg_synthesize_data(struct cpuinfo_mips *c)
 			LOONGSON_CFG3_LCAMKW_REV1 |
 			LOONGSON_CFG3_LCAMVW_REV1);
 		break;
+
+	default:
+		/* It is possible that some future Loongson cores still do
+		 * not have CPUCFG, so do not emulate anything for these
+		 * cores.
+		 */
+		return;
 	}
 
 	/* This feature is set by firmware, but all known Loongson-64 systems