All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] CPUCFG emulation on older Loongson64 cores
@ 2020-05-02 13:38 WANG Xuerui
  2020-05-02 13:38 ` [PATCH 1/4] MIPS: Loongson64: fix typos in loongson_regs.h WANG Xuerui
                   ` (8 more replies)
  0 siblings, 9 replies; 25+ messages in thread
From: WANG Xuerui @ 2020-05-02 13:38 UTC (permalink / raw)
  To: linux-mips; +Cc: WANG Xuerui

This patch series brings the CPUCFG instruction to older Loongson64
cores, enabling a unified way to query processor characteristics on
Loongson64 systems. A detailed explanation may be found in the last
commit.

One unresolved point is how to best introduce machtype-specific bits
into the generic MIPS code, namely the cpu probing and trap handler
parts. I have been struggling over whether to lift this logic into
arch/mips/kernel, but the instruction's encoding (reusing LWC2 opcode)
might be too invasive to be useful to other MIPS platforms. What do
people think is the best way forward?

WANG Xuerui (4):
  MIPS: Loongson64: fix typos in loongson_regs.h
  MIPS: Loongson64: define offsets and known revisions for some CPUCFG
    features
  MIPS: define more Loongson CP0.Config6 and CP0.Diag feature bits
  MIPS: emulate CPUCFG instruction on older Loongson64 cores

 arch/mips/Kconfig                             |  11 ++
 arch/mips/include/asm/cpu-info.h              |   9 ++
 .../include/asm/mach-loongson64/cpucfg-emul.h |  67 +++++++++
 .../asm/mach-loongson64/loongson_regs.h       |  27 +++-
 arch/mips/include/asm/mipsregs.h              |   6 +
 arch/mips/kernel/cpu-probe.c                  | 129 ++++++++++++++++++
 arch/mips/kernel/traps.c                      |  57 ++++++++
 arch/mips/loongson64/Makefile                 |   1 +
 arch/mips/loongson64/cpucfg-emul.c            |  80 +++++++++++
 9 files changed, 383 insertions(+), 4 deletions(-)
 create mode 100644 arch/mips/include/asm/mach-loongson64/cpucfg-emul.h
 create mode 100644 arch/mips/loongson64/cpucfg-emul.c

-- 
2.21.0


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

* [PATCH 1/4] MIPS: Loongson64: fix typos in loongson_regs.h
  2020-05-02 13:38 [PATCH 0/4] CPUCFG emulation on older Loongson64 cores WANG Xuerui
@ 2020-05-02 13:38 ` WANG Xuerui
  2020-05-02 13:38 ` [PATCH 2/4] MIPS: Loongson64: define offsets and known revisions for some CPUCFG features WANG Xuerui
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 25+ messages in thread
From: WANG Xuerui @ 2020-05-02 13:38 UTC (permalink / raw)
  To: linux-mips; +Cc: WANG Xuerui, Huacai Chen, Jiaxun Yang

Fix some symbol names to align with Loongson's User Manual wording. Also
correct the comment in csr_readq() suggesting the wrong instruction in
use.

Fixes: 6a6f9b7dafd50efc ("MIPS: Loongson: Add CFUCFG&CSR support")
Signed-off-by: WANG Xuerui <git@xen0n.name>
Cc: Huacai Chen <chenhc@lemote.com>
Cc: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 arch/mips/include/asm/mach-loongson64/loongson_regs.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/mips/include/asm/mach-loongson64/loongson_regs.h b/arch/mips/include/asm/mach-loongson64/loongson_regs.h
index 363a47a5d26e..3fa94c6ec3b9 100644
--- a/arch/mips/include/asm/mach-loongson64/loongson_regs.h
+++ b/arch/mips/include/asm/mach-loongson64/loongson_regs.h
@@ -77,12 +77,12 @@ static inline u32 read_cpucfg(u32 reg)
 #define LOONGSON_CFG2_LBT3	BIT(6)
 #define LOONGSON_CFG2_LBTMMU	BIT(7)
 #define LOONGSON_CFG2_LPMP	BIT(8)
-#define LOONGSON_CFG2_LPMPREV	GENMASK(11, 9)
+#define LOONGSON_CFG2_LPMREV	GENMASK(11, 9)
 #define LOONGSON_CFG2_LAMO	BIT(12)
 #define LOONGSON_CFG2_LPIXU	BIT(13)
 #define LOONGSON_CFG2_LPIXUN	BIT(14)
-#define LOONGSON_CFG2_LZVP	BIT(15)
-#define LOONGSON_CFG2_LZVREV	GENMASK(18, 16)
+#define LOONGSON_CFG2_LVZP	BIT(15)
+#define LOONGSON_CFG2_LVZREV	GENMASK(18, 16)
 #define LOONGSON_CFG2_LGFTP	BIT(19)
 #define LOONGSON_CFG2_LGFTPREV	GENMASK(22, 20)
 #define LOONGSON_CFG2_LLFTP	BIT(23)
@@ -139,7 +139,7 @@ static inline u64 csr_readq(u32 reg)
 {
 	u64 __res;
 
-	/* DWRCSR reg, val */
+	/* DRDCSR reg, val */
 	__asm__ __volatile__(
 		"parse_r __res,%0\n\t"
 		"parse_r reg,%1\n\t"
-- 
2.21.0


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

* [PATCH 2/4] MIPS: Loongson64: define offsets and known revisions for some CPUCFG features
  2020-05-02 13:38 [PATCH 0/4] CPUCFG emulation on older Loongson64 cores WANG Xuerui
  2020-05-02 13:38 ` [PATCH 1/4] MIPS: Loongson64: fix typos in loongson_regs.h WANG Xuerui
@ 2020-05-02 13:38 ` WANG Xuerui
  2020-05-02 13:38 ` [PATCH 3/4] MIPS: define more Loongson CP0.Config6 and CP0.Diag feature bits WANG Xuerui
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 25+ messages in thread
From: WANG Xuerui @ 2020-05-02 13:38 UTC (permalink / raw)
  To: linux-mips; +Cc: WANG Xuerui, Huacai Chen, Jiaxun Yang

Add the constants for easier and maintainable composition of CPUCFG
values.

Signed-off-by: WANG Xuerui <git@xen0n.name>
Cc: Huacai Chen <chenhc@lemote.com>
Cc: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 .../asm/mach-loongson64/loongson_regs.h       | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/arch/mips/include/asm/mach-loongson64/loongson_regs.h b/arch/mips/include/asm/mach-loongson64/loongson_regs.h
index 3fa94c6ec3b9..8508afffdfd1 100644
--- a/arch/mips/include/asm/mach-loongson64/loongson_regs.h
+++ b/arch/mips/include/asm/mach-loongson64/loongson_regs.h
@@ -67,6 +67,8 @@ static inline u32 read_cpucfg(u32 reg)
 #define LOONGSON_CFG1_SFBP	BIT(29)
 #define LOONGSON_CFG1_CDMAP	BIT(30)
 
+#define LOONGSON_CFG1_FPREV_OFFSET	1
+
 #define LOONGSON_CFG2 0x2
 #define LOONGSON_CFG2_LEXT1	BIT(0)
 #define LOONGSON_CFG2_LEXT2	BIT(1)
@@ -90,6 +92,13 @@ static inline u32 read_cpucfg(u32 reg)
 #define LOONGSON_CFG2_LCSRP	BIT(27)
 #define LOONGSON_CFG2_LDISBLIKELY	BIT(28)
 
+#define LOONGSON_CFG2_LPMREV_OFFSET	9
+#define LOONGSON_CFG2_LPM_REV1		(1 << LOONGSON_CFG2_LPMREV_OFFSET)
+#define LOONGSON_CFG2_LPM_REV2		(2 << LOONGSON_CFG2_LPMREV_OFFSET)
+#define LOONGSON_CFG2_LVZREV_OFFSET	16
+#define LOONGSON_CFG2_LVZ_REV1		(1 << LOONGSON_CFG2_LVZREV_OFFSET)
+#define LOONGSON_CFG2_LVZ_REV2		(2 << LOONGSON_CFG2_LVZREV_OFFSET)
+
 #define LOONGSON_CFG3 0x3
 #define LOONGSON_CFG3_LCAMP	BIT(0)
 #define LOONGSON_CFG3_LCAMREV	GENMASK(3, 1)
@@ -97,6 +106,16 @@ static inline u32 read_cpucfg(u32 reg)
 #define LOONGSON_CFG3_LCAMKW	GENMASK(19, 12)
 #define LOONGSON_CFG3_LCAMVW	GENMASK(27, 20)
 
+#define LOONGSON_CFG3_LCAMREV_OFFSET	1
+#define LOONGSON_CFG3_LCAM_REV1		(1 << LOONGSON_CFG3_LCAMREV_OFFSET)
+#define LOONGSON_CFG3_LCAM_REV2		(2 << LOONGSON_CFG3_LCAMREV_OFFSET)
+#define LOONGSON_CFG3_LCAMNUM_OFFSET	4
+#define LOONGSON_CFG3_LCAMNUM_REV1	(0x3f << LOONGSON_CFG3_LCAMNUM_OFFSET)
+#define LOONGSON_CFG3_LCAMKW_OFFSET	12
+#define LOONGSON_CFG3_LCAMKW_REV1	(0x27 << LOONGSON_CFG3_LCAMKW_OFFSET)
+#define LOONGSON_CFG3_LCAMVW_OFFSET	20
+#define LOONGSON_CFG3_LCAMVW_REV1	(0x3f << LOONGSON_CFG3_LCAMVW_OFFSET)
+
 #define LOONGSON_CFG4 0x4
 #define LOONGSON_CFG4_CCFREQ	GENMASK(31, 0)
 
-- 
2.21.0


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

* [PATCH 3/4] MIPS: define more Loongson CP0.Config6 and CP0.Diag feature bits
  2020-05-02 13:38 [PATCH 0/4] CPUCFG emulation on older Loongson64 cores WANG Xuerui
  2020-05-02 13:38 ` [PATCH 1/4] MIPS: Loongson64: fix typos in loongson_regs.h WANG Xuerui
  2020-05-02 13:38 ` [PATCH 2/4] MIPS: Loongson64: define offsets and known revisions for some CPUCFG features WANG Xuerui
@ 2020-05-02 13:38 ` WANG Xuerui
  2020-05-02 13:38 ` [PATCH 4/4] MIPS: emulate CPUCFG instruction on older Loongson64 cores WANG Xuerui
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 25+ messages in thread
From: WANG Xuerui @ 2020-05-02 13:38 UTC (permalink / raw)
  To: linux-mips; +Cc: WANG Xuerui, Huacai Chen, Jiaxun Yang

These are exposed to userland alternatively via the new CPUCFG
instruction on Loongson-3A R4 and above. Add definitions for readback
on older cores.

Signed-off-by: WANG Xuerui <git@xen0n.name>
Cc: Huacai Chen <chenhc@lemote.com>
Cc: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 arch/mips/include/asm/mipsregs.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index 796fe47cfd17..90f843c72774 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -681,6 +681,10 @@
 #define MIPS_CONF6_FTLBDIS	(_ULCAST_(1) << 22)
 /* FTLB probability bits */
 #define MIPS_CONF6_FTLBP_SHIFT	(16)
+/* Loongson-3 feature bits */
+#define MIPS_CONF6_LOONGSON_SCRAND	(_ULCAST_(1) << 17)
+#define MIPS_CONF6_LOONGSON_LLEXC	(_ULCAST_(1) << 16)
+#define MIPS_CONF6_LOONGSON_STFILL	(_ULCAST_(1) << 8)
 
 #define MIPS_CONF7_WII		(_ULCAST_(1) << 31)
 
@@ -997,6 +1001,8 @@
 #define LOONGSON_DIAG_ITLB	(_ULCAST_(1) << 2)
 /* Flush DTLB */
 #define LOONGSON_DIAG_DTLB	(_ULCAST_(1) << 3)
+/* Allow some CACHE instructions (CACHE0, 1, 3, 21 and 23) in user mode */
+#define LOONGSON_DIAG_UCAC	(_ULCAST_(1) << 8)
 /* Flush VTLB */
 #define LOONGSON_DIAG_VTLB	(_ULCAST_(1) << 12)
 /* Flush FTLB */
-- 
2.21.0


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

* [PATCH 4/4] MIPS: emulate CPUCFG instruction on older Loongson64 cores
  2020-05-02 13:38 [PATCH 0/4] CPUCFG emulation on older Loongson64 cores WANG Xuerui
                   ` (2 preceding siblings ...)
  2020-05-02 13:38 ` [PATCH 3/4] MIPS: define more Loongson CP0.Config6 and CP0.Diag feature bits WANG Xuerui
@ 2020-05-02 13:38 ` WANG Xuerui
  2020-05-02 13:59   ` Jiaxun Yang
  2020-05-03  6:31   ` Huacai Chen
  2020-05-03 10:33 ` [PATCH v2 0/4] CPUCFG emulation " WANG Xuerui
                   ` (4 subsequent siblings)
  8 siblings, 2 replies; 25+ messages in thread
From: WANG Xuerui @ 2020-05-02 13:38 UTC (permalink / raw)
  To: linux-mips; +Cc: WANG Xuerui, Huacai Chen, Jiaxun Yang, Tiezhu Yang

CPUCFG is the instruction for querying processor characteristics on
newer Loongson processors, much like CPUID of x86. Since the instruction
is supposedly designed to provide a unified way to do feature detection
(without having to, for example, parse /proc/cpuinfo which is too
heavyweight), it is important to provide compatibility for older cores
without native support. Fortunately, most of the fields can be
synthesized without changes to semantics. Performance is not really big
a concern, because feature detection logic is not expected to be
invoked very often in typical userland applications.

The instruction can't be emulated on LOONGSON_2EF cores, according to
FlyGoat's experiments. Because the LWC2 opcode is assigned to other
valid instructions on 2E and 2F, no RI exception is raised for us to
intercept. So compatibility is only extended back furthest to
Loongson-3A1000. Loongson-2K is covered too, as it is basically a remix
of various blocks from the 3A/3B models from a kernel perspective.

This is lightly based on Loongson's work on their Linux 3.10 fork, for
being the authority on the right feature flags to fill in, where things
aren't otherwise discoverable.

Signed-off-by: WANG Xuerui <git@xen0n.name>
Cc: Huacai Chen <chenhc@lemote.com>
Cc: Jiaxun Yang <jiaxun.yang@flygoat.com>
Cc: Tiezhu Yang <yangtiezhu@loongson.cn>
---
 arch/mips/Kconfig                             |  11 ++
 arch/mips/include/asm/cpu-info.h              |   9 ++
 .../include/asm/mach-loongson64/cpucfg-emul.h |  67 +++++++++
 arch/mips/kernel/cpu-probe.c                  | 129 ++++++++++++++++++
 arch/mips/kernel/traps.c                      |  57 ++++++++
 arch/mips/loongson64/Makefile                 |   1 +
 arch/mips/loongson64/cpucfg-emul.c            |  80 +++++++++++
 7 files changed, 354 insertions(+)
 create mode 100644 arch/mips/include/asm/mach-loongson64/cpucfg-emul.h
 create mode 100644 arch/mips/loongson64/cpucfg-emul.c

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 9f15539a6342..2ab189001917 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1508,6 +1508,17 @@ config CPU_LOONGSON3_WORKAROUNDS
 
 	  If unsure, please say Y.
 
+config CPU_LOONGSON3_CPUCFG_EMULATION
+	bool "Emulate the CPUCFG instruction on older cores"
+	default y
+	depends on CPU_LOONGSON64
+	help
+	  Loongson-3A R4 and newer have the CPUCFG instruction available for
+	  userland to query CPU capabilities, much like CPUID on x86. This
+	  option provides emulation of the instruction on older cores.
+
+	  If unsure, please say Y.
+
 config CPU_LOONGSON2E
 	bool "Loongson 2E"
 	depends on SYS_HAS_CPU_LOONGSON2E
diff --git a/arch/mips/include/asm/cpu-info.h b/arch/mips/include/asm/cpu-info.h
index ed7ffe4e63a3..43c238567a80 100644
--- a/arch/mips/include/asm/cpu-info.h
+++ b/arch/mips/include/asm/cpu-info.h
@@ -105,6 +105,15 @@ struct cpuinfo_mips {
 	unsigned int		gtoffset_mask;
 	unsigned int		guestid_mask;
 	unsigned int		guestid_cache;
+
+#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
+	/* CPUCFG data for this CPU, synthesized at probe time.
+	 *
+	 * CPUCFG select 0 is PRId, others are unimplemented for now. So the
+	 * only stored values are for CPUCFG selects 1-3 inclusive.
+	 */
+	u32 loongson3_cpucfg_data[3];
+#endif
 } __attribute__((aligned(SMP_CACHE_BYTES)));
 
 extern struct cpuinfo_mips cpu_data[];
diff --git a/arch/mips/include/asm/mach-loongson64/cpucfg-emul.h b/arch/mips/include/asm/mach-loongson64/cpucfg-emul.h
new file mode 100644
index 000000000000..b9f6b2aa98f9
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson64/cpucfg-emul.h
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_MACH_LOONGSON64_CPUCFG_EMUL_H_
+#define _ASM_MACH_LOONGSON64_CPUCFG_EMUL_H_
+
+#include <asm/cpu-info.h>
+
+#include <loongson_regs.h>
+
+#define LOONGSON_FPREV_MASK 0x7
+
+#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
+
+/* Finalize synthesis of CPUCFG data by patching the partially filled data
+ * with dynamically detected CPU characteristics. This keeps the amount of
+ * hard-coded logic at a minimum.
+ */
+void loongson3_cpucfg_finish_synthesis(struct cpuinfo_mips *c);
+
+static inline u32 loongson3_cpucfg_read_synthesized(
+	struct cpuinfo_mips *c,
+	__u64 sel)
+{
+	switch (sel) {
+	case LOONGSON_CFG0:
+		return c->processor_id;
+	case LOONGSON_CFG1:
+	case LOONGSON_CFG2:
+	case LOONGSON_CFG3:
+		return c->loongson3_cpucfg_data[sel - 1];
+	case LOONGSON_CFG4:
+	case LOONGSON_CFG5:
+		/* CPUCFG selects 4 and 5 are related to the processor clock.
+		 * Unimplemented for now.
+		 */
+		return 0;
+	case LOONGSON_CFG6:
+		/* CPUCFG select 6 is for the undocumented Safe Extension. */
+		return 0;
+	case LOONGSON_CFG7:
+		/* CPUCFG select 7 is for the virtualization extension.
+		 * We don't know if the two currently known features are
+		 * supported on older cores according to the public
+		 * documentation, so leave this at zero.
+		 */
+		return 0;
+	}
+
+	/*
+	 * Return 0 for unrecognized CPUCFG selects, which is real hardware
+	 * behavior observed on Loongson 3A R4.
+	 */
+	return 0;
+}
+#else
+static void loongson3_cpucfg_finish_synthesis(struct cpuinfo_mips *c)
+{
+}
+
+static inline u32 loongson3_cpucfg_read_synthesized(
+	struct cpuinfo_mips *c,
+	__u64 sel)
+{
+	return 0;
+}
+#endif
+
+#endif /* _ASM_MACH_LOONGSON64_CPUCFG_EMUL_H_ */
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index ca2e6f1af4fe..907e31ff562f 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -28,6 +28,8 @@
 #include <asm/spram.h>
 #include <linux/uaccess.h>
 
+#include <asm/mach-loongson64/cpucfg-emul.h>
+
 /* Hardware capabilities */
 unsigned int elf_hwcap __read_mostly;
 EXPORT_SYMBOL_GPL(elf_hwcap);
@@ -1580,6 +1582,24 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
 			set_isa(c, MIPS_CPU_ISA_M64R1);
 			c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_CAM |
 				MIPS_ASE_LOONGSON_EXT);
+#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
+			/* Add CPUCFG features non-discoverable otherwise. */
+			c->loongson3_cpucfg_data[0] |= (LOONGSON_CFG1_LSLDR0 |
+				LOONGSON_CFG1_LSSYNCI | LOONGSON_CFG1_LSUCA |
+				LOONGSON_CFG1_LLSYNC | LOONGSON_CFG1_TGTSYNC);
+			c->loongson3_cpucfg_data[1] |= (LOONGSON_CFG2_LBT1 |
+				LOONGSON_CFG2_LPMP | LOONGSON_CFG2_LPM_REV1);
+			c->loongson3_cpucfg_data[2] |= (
+				LOONGSON_CFG3_LCAM_REV1 |
+				LOONGSON_CFG3_LCAMNUM_REV1 |
+				LOONGSON_CFG3_LCAMKW_REV1 |
+				LOONGSON_CFG3_LCAMVW_REV1);
+
+			/* This feature is set by firmware, but all known
+			 * Loongson-3A Legacy systems are configured this way.
+			 */
+			c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_CDMAP;
+#endif
 			break;
 		case PRID_REV_LOONGSON3B_R1:
 		case PRID_REV_LOONGSON3B_R2:
@@ -1589,6 +1609,24 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
 			set_isa(c, MIPS_CPU_ISA_M64R1);
 			c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_CAM |
 				MIPS_ASE_LOONGSON_EXT);
+#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
+			/* Add CPUCFG features non-discoverable otherwise. */
+			c->loongson3_cpucfg_data[0] |= (LOONGSON_CFG1_LSLDR0 |
+				LOONGSON_CFG1_LSSYNCI | LOONGSON_CFG1_LSUCA |
+				LOONGSON_CFG1_LLSYNC | LOONGSON_CFG1_TGTSYNC);
+			c->loongson3_cpucfg_data[1] |= (LOONGSON_CFG2_LBT1 |
+				LOONGSON_CFG2_LPMP | LOONGSON_CFG2_LPM_REV1);
+			c->loongson3_cpucfg_data[2] |= (
+				LOONGSON_CFG3_LCAM_REV1 |
+				LOONGSON_CFG3_LCAMNUM_REV1 |
+				LOONGSON_CFG3_LCAMKW_REV1 |
+				LOONGSON_CFG3_LCAMVW_REV1);
+
+			/* This feature is set by firmware, but all known
+			 * Loongson-3B Legacy systems are configured this way.
+			 */
+			c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_CDMAP;
+#endif
 			break;
 		}
 
@@ -1957,9 +1995,57 @@ static inline void decode_cpucfg(struct cpuinfo_mips *c)
 		c->ases |= MIPS_ASE_LOONGSON_CAM;
 }
 
+#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
+static inline int cpu_has_uca(void)
+{
+	u32 diag = read_c0_diag();
+	u32 new_diag;
+
+	if (diag & LOONGSON_DIAG_UCAC)
+		/* UCA is already enabled. */
+		return 1;
+
+	/* See if UCAC bit can be flipped on. This should be safe. */
+	new_diag = diag | LOONGSON_DIAG_UCAC;
+	write_c0_diag(new_diag);
+	new_diag = read_c0_diag();
+	write_c0_diag(diag);
+
+	return (new_diag & LOONGSON_DIAG_UCAC) != 0;
+}
+
+static inline void probe_uca(struct cpuinfo_mips *c)
+{
+	if (cpu_has_uca())
+		c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_LSUCA;
+}
+
+static inline void decode_loongson_config6(struct cpuinfo_mips *c)
+{
+	u32 config6 = read_c0_config6();
+
+	if (config6 & MIPS_CONF6_LOONGSON_STFILL)
+		c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_SFBP;
+	if (config6 & MIPS_CONF6_LOONGSON_LLEXC)
+		c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_LLEXC;
+	if (config6 & MIPS_CONF6_LOONGSON_SCRAND)
+		c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_SCRAND;
+}
+#else
+static inline void probe_uca(struct cpuinfo_mips *c)
+{
+}
+
+static inline void decode_loongson_config6(struct cpuinfo_mips *c)
+{
+}
+#endif /* CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION */
+
 static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)
 {
 	decode_configs(c);
+	decode_loongson_config6(c);
+	probe_uca(c);
 
 	switch (c->processor_id & PRID_IMP_MASK) {
 	case PRID_IMP_LOONGSON_64R: /* Loongson-64 Reduced */
@@ -1977,6 +2063,21 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)
 		c->writecombine = _CACHE_UNCACHED_ACCELERATED;
 		c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_EXT |
 				MIPS_ASE_LOONGSON_EXT2);
+#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
+		/* Add CPUCFG features non-discoverable otherwise. */
+		c->loongson3_cpucfg_data[0] |= (LOONGSON_CFG1_LSLDR0 |
+			LOONGSON_CFG1_LSSYNCI | LOONGSON_CFG1_LLSYNC |
+			LOONGSON_CFG1_TGTSYNC);
+		c->loongson3_cpucfg_data[1] |= (LOONGSON_CFG2_LBT1 |
+			LOONGSON_CFG2_LBT2 | LOONGSON_CFG2_LPMP |
+			LOONGSON_CFG2_LPM_REV2);
+		c->loongson3_cpucfg_data[2] = 0;
+
+		/* This feature is set by firmware, but all known Loongson-2K
+		 * systems are configured this way.
+		 */
+		c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_CDMAP;
+#endif
 		break;
 	case PRID_IMP_LOONGSON_64C:  /* Loongson-3 Classic */
 		switch (c->processor_id & PRID_REV_MASK) {
@@ -2007,6 +2108,26 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)
 		c->writecombine = _CACHE_UNCACHED_ACCELERATED;
 		c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_CAM |
 			MIPS_ASE_LOONGSON_EXT | MIPS_ASE_LOONGSON_EXT2);
+#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
+		/* Add CPUCFG features non-discoverable otherwise. */
+		c->loongson3_cpucfg_data[0] |= (LOONGSON_CFG1_CNT64 |
+			LOONGSON_CFG1_LSLDR0 | LOONGSON_CFG1_LSPREF |
+			LOONGSON_CFG1_LSPREFX | LOONGSON_CFG1_LSSYNCI |
+			LOONGSON_CFG1_LLSYNC | LOONGSON_CFG1_TGTSYNC);
+		c->loongson3_cpucfg_data[1] |= (LOONGSON_CFG2_LBT1 |
+			LOONGSON_CFG2_LBT2 | LOONGSON_CFG2_LBTMMU |
+			LOONGSON_CFG2_LPMP | LOONGSON_CFG2_LPM_REV1 |
+			LOONGSON_CFG2_LVZ_REV1);
+		c->loongson3_cpucfg_data[2] |= (LOONGSON_CFG3_LCAM_REV1 |
+			LOONGSON_CFG3_LCAMNUM_REV1 |
+			LOONGSON_CFG3_LCAMKW_REV1 |
+			LOONGSON_CFG3_LCAMVW_REV1);
+
+		/* This feature is set by firmware, but all known Loongson-3
+		 * systems are configured this way.
+		 */
+		c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_CDMAP;
+#endif
 		break;
 	case PRID_IMP_LOONGSON_64G:
 		c->cputype = CPU_LOONGSON64;
@@ -2200,6 +2321,12 @@ void cpu_probe(void)
 	c->fpu_csr31	= FPU_CSR_RN;
 	c->fpu_msk31	= FPU_CSR_RSVD | FPU_CSR_ABS2008 | FPU_CSR_NAN2008;
 
+#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
+	c->loongson3_cpucfg_data[0] = 0;
+	c->loongson3_cpucfg_data[1] = 0;
+	c->loongson3_cpucfg_data[2] = 0;
+#endif
+
 	c->processor_id = read_c0_prid();
 	switch (c->processor_id & PRID_COMP_MASK) {
 	case PRID_COMP_LEGACY:
@@ -2333,6 +2460,8 @@ void cpu_probe(void)
 	if (cpu_has_vz)
 		cpu_probe_vz(c);
 
+	loongson3_cpucfg_finish_synthesis(c);
+
 	cpu_probe_vmbits(c);
 
 #ifdef CONFIG_64BIT
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 31968cbd6464..0c77ca2f091b 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -71,6 +71,8 @@
 #include <asm/tlbex.h>
 #include <asm/uasm.h>
 
+#include <asm/mach-loongson64/cpucfg-emul.h>
+
 extern void check_wait(void);
 extern asmlinkage void rollback_handle_int(void);
 extern asmlinkage void handle_int(void);
@@ -693,6 +695,56 @@ static int simulate_sync(struct pt_regs *regs, unsigned int opcode)
 	return -1;			/* Must be something else ... */
 }
 
+/*
+ * Loongson-3 CSR instructions emulation
+ */
+
+#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
+
+#define LWC2             0xc8000000
+#define RS               BASE
+#define CSR_OPCODE2      0x00000118
+#define CSR_OPCODE2_MASK 0x000007ff
+#define CSR_FUNC_MASK    RT
+#define CSR_FUNC_CPUCFG  0x8
+
+static int simulate_loongson3_csr_cpucfg(struct pt_regs *regs,
+					unsigned int opcode)
+{
+	int rd = (opcode & RD) >> 11;
+	int rs = (opcode & RS) >> 21;
+	__u64 sel = regs->regs[rs];
+
+	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
+
+	regs->regs[rd] = loongson3_cpucfg_read_synthesized(&current_cpu_data,
+		sel);
+
+	return 0;
+}
+
+static int simulate_loongson3_csr(struct pt_regs *regs, unsigned int opcode)
+{
+	int op = opcode & OPCODE;
+	int op2 = opcode & CSR_OPCODE2_MASK;
+
+	if (op == LWC2 && op2 == CSR_OPCODE2) {
+		int csr_func = (opcode & CSR_FUNC_MASK) >> 16;
+
+		switch (csr_func) {
+		case CSR_FUNC_CPUCFG:
+			return simulate_loongson3_csr_cpucfg(regs, opcode);
+		}
+
+		/* Unrecognized Loongson-3 CSR instruction. */
+		return -1;
+	}
+
+	/* Not ours.  */
+	return -1;
+}
+#endif /* CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION */
+
 asmlinkage void do_ov(struct pt_regs *regs)
 {
 	enum ctx_state prev_state;
@@ -1166,6 +1218,11 @@ asmlinkage void do_ri(struct pt_regs *regs)
 
 		if (status < 0)
 			status = simulate_fp(regs, opcode, old_epc, old31);
+
+#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
+		if (status < 0)
+			status = simulate_loongson3_csr(regs, opcode);
+#endif
 	} else if (cpu_has_mmips) {
 		unsigned short mmop[2] = { 0 };
 
diff --git a/arch/mips/loongson64/Makefile b/arch/mips/loongson64/Makefile
index 6f3c2b47f66f..61f6add20530 100644
--- a/arch/mips/loongson64/Makefile
+++ b/arch/mips/loongson64/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_NUMA)	+= numa.o
 obj-$(CONFIG_RS780_HPET) += hpet.o
 obj-$(CONFIG_PCI) += pci.o
 obj-$(CONFIG_SUSPEND) += pm.o
+obj-$(CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION) += cpucfg-emul.o
diff --git a/arch/mips/loongson64/cpucfg-emul.c b/arch/mips/loongson64/cpucfg-emul.c
new file mode 100644
index 000000000000..a30f82b55c9e
--- /dev/null
+++ b/arch/mips/loongson64/cpucfg-emul.c
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/smp.h>
+#include <asm/cpu.h>
+#include <asm/cpu-info.h>
+
+#include <loongson_regs.h>
+#include <cpucfg-emul.h>
+
+static u32 get_loongson_fprev(struct cpuinfo_mips *c)
+{
+	return (c->fpu_id & LOONGSON_FPREV_MASK) << LOONGSON_CFG1_FPREV_OFFSET;
+}
+
+static void patch_cpucfg_sel1(struct cpuinfo_mips *c)
+{
+	u64 ases = c->ases;
+	u64 options = c->options;
+	u32 data = c->loongson3_cpucfg_data[0];
+
+	if (options & MIPS_CPU_FPU) {
+		data |= LOONGSON_CFG1_FP;
+		data |= get_loongson_fprev(c);
+	}
+	if (ases & MIPS_ASE_LOONGSON_MMI)
+		data |= LOONGSON_CFG1_MMI;
+	if (ases & MIPS_ASE_MSA)
+		data |= LOONGSON_CFG1_MSA1;
+
+	c->loongson3_cpucfg_data[0] = data;
+}
+
+static void patch_cpucfg_sel2(struct cpuinfo_mips *c)
+{
+	u64 ases = c->ases;
+	u64 options = c->options;
+	u32 data = c->loongson3_cpucfg_data[1];
+
+	if (ases & MIPS_ASE_LOONGSON_EXT)
+		data |= LOONGSON_CFG2_LEXT1;
+	if (ases & MIPS_ASE_LOONGSON_EXT2)
+		data |= LOONGSON_CFG2_LEXT2;
+	if (options & MIPS_CPU_LDPTE)
+		data |= LOONGSON_CFG2_LSPW;
+
+	if (ases & MIPS_ASE_VZ)
+		data |= LOONGSON_CFG2_LVZP;
+	else
+		data &= ~LOONGSON_CFG2_LVZREV;
+
+	c->loongson3_cpucfg_data[1] = data;
+}
+
+static void patch_cpucfg_sel3(struct cpuinfo_mips *c)
+{
+	u64 ases = c->ases;
+	u32 data = c->loongson3_cpucfg_data[2];
+
+	if (ases & MIPS_ASE_LOONGSON_CAM) {
+		data |= LOONGSON_CFG3_LCAMP;
+	} else {
+		data &= ~LOONGSON_CFG3_LCAMREV;
+		data &= ~LOONGSON_CFG3_LCAMNUM;
+		data &= ~LOONGSON_CFG3_LCAMKW;
+		data &= ~LOONGSON_CFG3_LCAMVW;
+	}
+
+	c->loongson3_cpucfg_data[2] = data;
+}
+
+void loongson3_cpucfg_finish_synthesis(struct cpuinfo_mips *c)
+{
+	/* CPUs with CPUCFG support don't need to synthesize anything. */
+	if (cpu_has_cfg())
+		return;
+
+	patch_cpucfg_sel1(c);
+	patch_cpucfg_sel2(c);
+	patch_cpucfg_sel3(c);
+}
-- 
2.21.0


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

* Re: [PATCH 4/4] MIPS: emulate CPUCFG instruction on older Loongson64 cores
  2020-05-02 13:38 ` [PATCH 4/4] MIPS: emulate CPUCFG instruction on older Loongson64 cores WANG Xuerui
@ 2020-05-02 13:59   ` Jiaxun Yang
  2020-05-03  6:31   ` Huacai Chen
  1 sibling, 0 replies; 25+ messages in thread
From: Jiaxun Yang @ 2020-05-02 13:59 UTC (permalink / raw)
  To: WANG Xuerui; +Cc: linux-mips, Huacai Chen, Tiezhu Yang

On Sat,  2 May 2020 21:38:46 +0800
WANG Xuerui <git@xen0n.name> wrote:

> CPUCFG is the instruction for querying processor characteristics on
> newer Loongson processors, much like CPUID of x86. Since the
> instruction is supposedly designed to provide a unified way to do
> feature detection (without having to, for example, parse
> /proc/cpuinfo which is too heavyweight), it is important to provide
> compatibility for older cores without native support. Fortunately,
> most of the fields can be synthesized without changes to semantics.
> Performance is not really big a concern, because feature detection
> logic is not expected to be invoked very often in typical userland
> applications.
> 
> The instruction can't be emulated on LOONGSON_2EF cores, according to
> FlyGoat's experiments. Because the LWC2 opcode is assigned to other
> valid instructions on 2E and 2F, no RI exception is raised for us to
> intercept. So compatibility is only extended back furthest to
> Loongson-3A1000. Loongson-2K is covered too, as it is basically a
> remix of various blocks from the 3A/3B models from a kernel
> perspective.
> 
> This is lightly based on Loongson's work on their Linux 3.10 fork, for
> being the authority on the right feature flags to fill in, where
> things aren't otherwise discoverable.
> 
> Signed-off-by: WANG Xuerui <git@xen0n.name>
> Cc: Huacai Chen <chenhc@lemote.com>
> Cc: Jiaxun Yang <jiaxun.yang@flygoat.com>
> Cc: Tiezhu Yang <yangtiezhu@loongson.cn>

Reviewed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Tested-by: Jiaxun Yang <jiaxun.yang@flygoat.com> # Loongson-2K, 3B1500

Thanks for providing me early access of this series so I can perform
reviewing and testing before you posting to the list.

And welcome!

--
Jiaxun Yang

[...]

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

* Re: [PATCH 4/4] MIPS: emulate CPUCFG instruction on older Loongson64 cores
  2020-05-02 13:38 ` [PATCH 4/4] MIPS: emulate CPUCFG instruction on older Loongson64 cores WANG Xuerui
  2020-05-02 13:59   ` Jiaxun Yang
@ 2020-05-03  6:31   ` Huacai Chen
  2020-05-03  7:58     ` Wang Xuerui
  1 sibling, 1 reply; 25+ messages in thread
From: Huacai Chen @ 2020-05-03  6:31 UTC (permalink / raw)
  To: WANG Xuerui; +Cc: open list:MIPS, Jiaxun Yang, Tiezhu Yang

Hi, Xuerui,

On Sat, May 2, 2020 at 9:47 PM WANG Xuerui <git@xen0n.name> wrote:
>
> CPUCFG is the instruction for querying processor characteristics on
> newer Loongson processors, much like CPUID of x86. Since the instruction
> is supposedly designed to provide a unified way to do feature detection
> (without having to, for example, parse /proc/cpuinfo which is too
> heavyweight), it is important to provide compatibility for older cores
> without native support. Fortunately, most of the fields can be
> synthesized without changes to semantics. Performance is not really big
> a concern, because feature detection logic is not expected to be
> invoked very often in typical userland applications.
>
> The instruction can't be emulated on LOONGSON_2EF cores, according to
> FlyGoat's experiments. Because the LWC2 opcode is assigned to other
> valid instructions on 2E and 2F, no RI exception is raised for us to
> intercept. So compatibility is only extended back furthest to
> Loongson-3A1000. Loongson-2K is covered too, as it is basically a remix
> of various blocks from the 3A/3B models from a kernel perspective.
>
> This is lightly based on Loongson's work on their Linux 3.10 fork, for
> being the authority on the right feature flags to fill in, where things
> aren't otherwise discoverable.
>
> Signed-off-by: WANG Xuerui <git@xen0n.name>
> Cc: Huacai Chen <chenhc@lemote.com>
> Cc: Jiaxun Yang <jiaxun.yang@flygoat.com>
> Cc: Tiezhu Yang <yangtiezhu@loongson.cn>
> ---
>  arch/mips/Kconfig                             |  11 ++
>  arch/mips/include/asm/cpu-info.h              |   9 ++
>  .../include/asm/mach-loongson64/cpucfg-emul.h |  67 +++++++++
>  arch/mips/kernel/cpu-probe.c                  | 129 ++++++++++++++++++
>  arch/mips/kernel/traps.c                      |  57 ++++++++
>  arch/mips/loongson64/Makefile                 |   1 +
>  arch/mips/loongson64/cpucfg-emul.c            |  80 +++++++++++
>  7 files changed, 354 insertions(+)
>  create mode 100644 arch/mips/include/asm/mach-loongson64/cpucfg-emul.h
>  create mode 100644 arch/mips/loongson64/cpucfg-emul.c
>
> diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
> index 9f15539a6342..2ab189001917 100644
> --- a/arch/mips/Kconfig
> +++ b/arch/mips/Kconfig
> @@ -1508,6 +1508,17 @@ config CPU_LOONGSON3_WORKAROUNDS
>
>           If unsure, please say Y.
>
> +config CPU_LOONGSON3_CPUCFG_EMULATION
> +       bool "Emulate the CPUCFG instruction on older cores"
> +       default y
> +       depends on CPU_LOONGSON64
> +       help
> +         Loongson-3A R4 and newer have the CPUCFG instruction available for
> +         userland to query CPU capabilities, much like CPUID on x86. This
> +         option provides emulation of the instruction on older cores.
> +
> +         If unsure, please say Y.
> +
>  config CPU_LOONGSON2E
>         bool "Loongson 2E"
>         depends on SYS_HAS_CPU_LOONGSON2E
> diff --git a/arch/mips/include/asm/cpu-info.h b/arch/mips/include/asm/cpu-info.h
> index ed7ffe4e63a3..43c238567a80 100644
> --- a/arch/mips/include/asm/cpu-info.h
> +++ b/arch/mips/include/asm/cpu-info.h
> @@ -105,6 +105,15 @@ struct cpuinfo_mips {
>         unsigned int            gtoffset_mask;
>         unsigned int            guestid_mask;
>         unsigned int            guestid_cache;
> +
> +#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
> +       /* CPUCFG data for this CPU, synthesized at probe time.
> +        *
> +        * CPUCFG select 0 is PRId, others are unimplemented for now. So the
> +        * only stored values are for CPUCFG selects 1-3 inclusive.
> +        */
> +       u32 loongson3_cpucfg_data[3];
> +#endif
>  } __attribute__((aligned(SMP_CACHE_BYTES)));
>
>  extern struct cpuinfo_mips cpu_data[];
> diff --git a/arch/mips/include/asm/mach-loongson64/cpucfg-emul.h b/arch/mips/include/asm/mach-loongson64/cpucfg-emul.h
> new file mode 100644
> index 000000000000..b9f6b2aa98f9
> --- /dev/null
> +++ b/arch/mips/include/asm/mach-loongson64/cpucfg-emul.h
> @@ -0,0 +1,67 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef _ASM_MACH_LOONGSON64_CPUCFG_EMUL_H_
> +#define _ASM_MACH_LOONGSON64_CPUCFG_EMUL_H_
> +
> +#include <asm/cpu-info.h>
> +
> +#include <loongson_regs.h>
> +
> +#define LOONGSON_FPREV_MASK 0x7
> +
> +#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
> +
> +/* Finalize synthesis of CPUCFG data by patching the partially filled data
> + * with dynamically detected CPU characteristics. This keeps the amount of
> + * hard-coded logic at a minimum.
> + */
> +void loongson3_cpucfg_finish_synthesis(struct cpuinfo_mips *c);
> +
> +static inline u32 loongson3_cpucfg_read_synthesized(
> +       struct cpuinfo_mips *c,
> +       __u64 sel)
> +{
> +       switch (sel) {
> +       case LOONGSON_CFG0:
> +               return c->processor_id;
> +       case LOONGSON_CFG1:
> +       case LOONGSON_CFG2:
> +       case LOONGSON_CFG3:
> +               return c->loongson3_cpucfg_data[sel - 1];
> +       case LOONGSON_CFG4:
> +       case LOONGSON_CFG5:
> +               /* CPUCFG selects 4 and 5 are related to the processor clock.
> +                * Unimplemented for now.
> +                */
> +               return 0;
> +       case LOONGSON_CFG6:
> +               /* CPUCFG select 6 is for the undocumented Safe Extension. */
> +               return 0;
> +       case LOONGSON_CFG7:
> +               /* CPUCFG select 7 is for the virtualization extension.
> +                * We don't know if the two currently known features are
> +                * supported on older cores according to the public
> +                * documentation, so leave this at zero.
> +                */
> +               return 0;
> +       }
> +
> +       /*
> +        * Return 0 for unrecognized CPUCFG selects, which is real hardware
> +        * behavior observed on Loongson 3A R4.
> +        */
> +       return 0;
> +}
> +#else
> +static void loongson3_cpucfg_finish_synthesis(struct cpuinfo_mips *c)
> +{
> +}
> +
> +static inline u32 loongson3_cpucfg_read_synthesized(
> +       struct cpuinfo_mips *c,
> +       __u64 sel)
> +{
> +       return 0;
> +}
> +#endif
> +
> +#endif /* _ASM_MACH_LOONGSON64_CPUCFG_EMUL_H_ */
> diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
> index ca2e6f1af4fe..907e31ff562f 100644
> --- a/arch/mips/kernel/cpu-probe.c
> +++ b/arch/mips/kernel/cpu-probe.c
> @@ -28,6 +28,8 @@
>  #include <asm/spram.h>
>  #include <linux/uaccess.h>
>
> +#include <asm/mach-loongson64/cpucfg-emul.h>
> +
>  /* Hardware capabilities */
>  unsigned int elf_hwcap __read_mostly;
>  EXPORT_SYMBOL_GPL(elf_hwcap);
> @@ -1580,6 +1582,24 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
>                         set_isa(c, MIPS_CPU_ISA_M64R1);
>                         c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_CAM |
>                                 MIPS_ASE_LOONGSON_EXT);
> +#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
> +                       /* Add CPUCFG features non-discoverable otherwise. */
> +                       c->loongson3_cpucfg_data[0] |= (LOONGSON_CFG1_LSLDR0 |
> +                               LOONGSON_CFG1_LSSYNCI | LOONGSON_CFG1_LSUCA |
> +                               LOONGSON_CFG1_LLSYNC | LOONGSON_CFG1_TGTSYNC);
> +                       c->loongson3_cpucfg_data[1] |= (LOONGSON_CFG2_LBT1 |
> +                               LOONGSON_CFG2_LPMP | LOONGSON_CFG2_LPM_REV1);
> +                       c->loongson3_cpucfg_data[2] |= (
> +                               LOONGSON_CFG3_LCAM_REV1 |
> +                               LOONGSON_CFG3_LCAMNUM_REV1 |
> +                               LOONGSON_CFG3_LCAMKW_REV1 |
> +                               LOONGSON_CFG3_LCAMVW_REV1);
> +
> +                       /* This feature is set by firmware, but all known
> +                        * Loongson-3A Legacy systems are configured this way.
> +                        */
> +                       c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_CDMAP;
> +#endif
>                         break;
>                 case PRID_REV_LOONGSON3B_R1:
>                 case PRID_REV_LOONGSON3B_R2:
> @@ -1589,6 +1609,24 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
>                         set_isa(c, MIPS_CPU_ISA_M64R1);
>                         c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_CAM |
>                                 MIPS_ASE_LOONGSON_EXT);
> +#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
> +                       /* Add CPUCFG features non-discoverable otherwise. */
> +                       c->loongson3_cpucfg_data[0] |= (LOONGSON_CFG1_LSLDR0 |
> +                               LOONGSON_CFG1_LSSYNCI | LOONGSON_CFG1_LSUCA |
> +                               LOONGSON_CFG1_LLSYNC | LOONGSON_CFG1_TGTSYNC);
> +                       c->loongson3_cpucfg_data[1] |= (LOONGSON_CFG2_LBT1 |
> +                               LOONGSON_CFG2_LPMP | LOONGSON_CFG2_LPM_REV1);
> +                       c->loongson3_cpucfg_data[2] |= (
> +                               LOONGSON_CFG3_LCAM_REV1 |
> +                               LOONGSON_CFG3_LCAMNUM_REV1 |
> +                               LOONGSON_CFG3_LCAMKW_REV1 |
> +                               LOONGSON_CFG3_LCAMVW_REV1);
> +
> +                       /* This feature is set by firmware, but all known
> +                        * Loongson-3B Legacy systems are configured this way.
> +                        */
> +                       c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_CDMAP;
> +#endif
>                         break;
>                 }
>
> @@ -1957,9 +1995,57 @@ static inline void decode_cpucfg(struct cpuinfo_mips *c)
>                 c->ases |= MIPS_ASE_LOONGSON_CAM;
>  }
>
> +#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
> +static inline int cpu_has_uca(void)
> +{
> +       u32 diag = read_c0_diag();
> +       u32 new_diag;
> +
> +       if (diag & LOONGSON_DIAG_UCAC)
> +               /* UCA is already enabled. */
> +               return 1;
> +
> +       /* See if UCAC bit can be flipped on. This should be safe. */
> +       new_diag = diag | LOONGSON_DIAG_UCAC;
> +       write_c0_diag(new_diag);
> +       new_diag = read_c0_diag();
> +       write_c0_diag(diag);
> +
> +       return (new_diag & LOONGSON_DIAG_UCAC) != 0;
> +}
> +
> +static inline void probe_uca(struct cpuinfo_mips *c)
> +{
> +       if (cpu_has_uca())
> +               c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_LSUCA;
> +}
> +
> +static inline void decode_loongson_config6(struct cpuinfo_mips *c)
> +{
> +       u32 config6 = read_c0_config6();
> +
> +       if (config6 & MIPS_CONF6_LOONGSON_STFILL)
> +               c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_SFBP;
> +       if (config6 & MIPS_CONF6_LOONGSON_LLEXC)
> +               c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_LLEXC;
> +       if (config6 & MIPS_CONF6_LOONGSON_SCRAND)
> +               c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_SCRAND;
> +}
> +#else
> +static inline void probe_uca(struct cpuinfo_mips *c)
> +{
> +}
> +
> +static inline void decode_loongson_config6(struct cpuinfo_mips *c)
> +{
> +}
> +#endif /* CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION */
> +
>  static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)
>  {
>         decode_configs(c);
> +       decode_loongson_config6(c);
> +       probe_uca(c);
>
>         switch (c->processor_id & PRID_IMP_MASK) {
>         case PRID_IMP_LOONGSON_64R: /* Loongson-64 Reduced */
> @@ -1977,6 +2063,21 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)
>                 c->writecombine = _CACHE_UNCACHED_ACCELERATED;
>                 c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_EXT |
>                                 MIPS_ASE_LOONGSON_EXT2);
> +#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
> +               /* Add CPUCFG features non-discoverable otherwise. */
> +               c->loongson3_cpucfg_data[0] |= (LOONGSON_CFG1_LSLDR0 |
> +                       LOONGSON_CFG1_LSSYNCI | LOONGSON_CFG1_LLSYNC |
> +                       LOONGSON_CFG1_TGTSYNC);
> +               c->loongson3_cpucfg_data[1] |= (LOONGSON_CFG2_LBT1 |
> +                       LOONGSON_CFG2_LBT2 | LOONGSON_CFG2_LPMP |
> +                       LOONGSON_CFG2_LPM_REV2);
> +               c->loongson3_cpucfg_data[2] = 0;
> +
> +               /* This feature is set by firmware, but all known Loongson-2K
> +                * systems are configured this way.
> +                */
> +               c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_CDMAP;
> +#endif
>                 break;
>         case PRID_IMP_LOONGSON_64C:  /* Loongson-3 Classic */
>                 switch (c->processor_id & PRID_REV_MASK) {
> @@ -2007,6 +2108,26 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)
>                 c->writecombine = _CACHE_UNCACHED_ACCELERATED;
>                 c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_CAM |
>                         MIPS_ASE_LOONGSON_EXT | MIPS_ASE_LOONGSON_EXT2);
> +#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
> +               /* Add CPUCFG features non-discoverable otherwise. */
> +               c->loongson3_cpucfg_data[0] |= (LOONGSON_CFG1_CNT64 |
> +                       LOONGSON_CFG1_LSLDR0 | LOONGSON_CFG1_LSPREF |
> +                       LOONGSON_CFG1_LSPREFX | LOONGSON_CFG1_LSSYNCI |
> +                       LOONGSON_CFG1_LLSYNC | LOONGSON_CFG1_TGTSYNC);
> +               c->loongson3_cpucfg_data[1] |= (LOONGSON_CFG2_LBT1 |
> +                       LOONGSON_CFG2_LBT2 | LOONGSON_CFG2_LBTMMU |
> +                       LOONGSON_CFG2_LPMP | LOONGSON_CFG2_LPM_REV1 |
> +                       LOONGSON_CFG2_LVZ_REV1);
> +               c->loongson3_cpucfg_data[2] |= (LOONGSON_CFG3_LCAM_REV1 |
> +                       LOONGSON_CFG3_LCAMNUM_REV1 |
> +                       LOONGSON_CFG3_LCAMKW_REV1 |
> +                       LOONGSON_CFG3_LCAMVW_REV1);
> +
> +               /* This feature is set by firmware, but all known Loongson-3
> +                * systems are configured this way.
> +                */
> +               c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_CDMAP;
> +#endif
>                 break;
>         case PRID_IMP_LOONGSON_64G:
>                 c->cputype = CPU_LOONGSON64;
> @@ -2200,6 +2321,12 @@ void cpu_probe(void)
>         c->fpu_csr31    = FPU_CSR_RN;
>         c->fpu_msk31    = FPU_CSR_RSVD | FPU_CSR_ABS2008 | FPU_CSR_NAN2008;
>
> +#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
> +       c->loongson3_cpucfg_data[0] = 0;
> +       c->loongson3_cpucfg_data[1] = 0;
> +       c->loongson3_cpucfg_data[2] = 0;
> +#endif
> +
>         c->processor_id = read_c0_prid();
>         switch (c->processor_id & PRID_COMP_MASK) {
>         case PRID_COMP_LEGACY:
> @@ -2333,6 +2460,8 @@ void cpu_probe(void)
>         if (cpu_has_vz)
>                 cpu_probe_vz(c);
>
> +       loongson3_cpucfg_finish_synthesis(c);
> +
>         cpu_probe_vmbits(c);
>
>  #ifdef CONFIG_64BIT
> diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
> index 31968cbd6464..0c77ca2f091b 100644
> --- a/arch/mips/kernel/traps.c
> +++ b/arch/mips/kernel/traps.c
> @@ -71,6 +71,8 @@
>  #include <asm/tlbex.h>
>  #include <asm/uasm.h>
>
> +#include <asm/mach-loongson64/cpucfg-emul.h>
> +
>  extern void check_wait(void);
>  extern asmlinkage void rollback_handle_int(void);
>  extern asmlinkage void handle_int(void);
> @@ -693,6 +695,56 @@ static int simulate_sync(struct pt_regs *regs, unsigned int opcode)
>         return -1;                      /* Must be something else ... */
>  }
>
> +/*
> + * Loongson-3 CSR instructions emulation
> + */
> +
> +#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
> +
> +#define LWC2             0xc8000000
> +#define RS               BASE
> +#define CSR_OPCODE2      0x00000118
> +#define CSR_OPCODE2_MASK 0x000007ff
> +#define CSR_FUNC_MASK    RT
> +#define CSR_FUNC_CPUCFG  0x8
> +
> +static int simulate_loongson3_csr_cpucfg(struct pt_regs *regs,
> +                                       unsigned int opcode)
Maybe simulate_loongson3_cpucfg() is a better name?

> +{
> +       int rd = (opcode & RD) >> 11;
> +       int rs = (opcode & RS) >> 21;
> +       __u64 sel = regs->regs[rs];
> +
> +       perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
> +
> +       regs->regs[rd] = loongson3_cpucfg_read_synthesized(&current_cpu_data,
> +               sel);
> +
> +       return 0;
> +}
> +
> +static int simulate_loongson3_csr(struct pt_regs *regs, unsigned int opcode)
> +{
> +       int op = opcode & OPCODE;
> +       int op2 = opcode & CSR_OPCODE2_MASK;
> +
> +       if (op == LWC2 && op2 == CSR_OPCODE2) {
> +               int csr_func = (opcode & CSR_FUNC_MASK) >> 16;
> +
> +               switch (csr_func) {
> +               case CSR_FUNC_CPUCFG:
> +                       return simulate_loongson3_csr_cpucfg(regs, opcode);
> +               }
> +
> +               /* Unrecognized Loongson-3 CSR instruction. */
> +               return -1;
> +       }
> +
> +       /* Not ours.  */
> +       return -1;
> +}
> +#endif /* CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION */
> +
>  asmlinkage void do_ov(struct pt_regs *regs)
>  {
>         enum ctx_state prev_state;
> @@ -1166,6 +1218,11 @@ asmlinkage void do_ri(struct pt_regs *regs)
>
>                 if (status < 0)
>                         status = simulate_fp(regs, opcode, old_epc, old31);
> +
> +#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
> +               if (status < 0)
> +                       status = simulate_loongson3_csr(regs, opcode);
> +#endif
>         } else if (cpu_has_mmips) {
>                 unsigned short mmop[2] = { 0 };
>
> diff --git a/arch/mips/loongson64/Makefile b/arch/mips/loongson64/Makefile
> index 6f3c2b47f66f..61f6add20530 100644
> --- a/arch/mips/loongson64/Makefile
> +++ b/arch/mips/loongson64/Makefile
> @@ -10,3 +10,4 @@ obj-$(CONFIG_NUMA)    += numa.o
>  obj-$(CONFIG_RS780_HPET) += hpet.o
>  obj-$(CONFIG_PCI) += pci.o
>  obj-$(CONFIG_SUSPEND) += pm.o
> +obj-$(CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION) += cpucfg-emul.o
> diff --git a/arch/mips/loongson64/cpucfg-emul.c b/arch/mips/loongson64/cpucfg-emul.c
> new file mode 100644
> index 000000000000..a30f82b55c9e
> --- /dev/null
> +++ b/arch/mips/loongson64/cpucfg-emul.c
> @@ -0,0 +1,80 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include <linux/smp.h>
> +#include <asm/cpu.h>
> +#include <asm/cpu-info.h>
> +
> +#include <loongson_regs.h>
> +#include <cpucfg-emul.h>
> +
> +static u32 get_loongson_fprev(struct cpuinfo_mips *c)
> +{
> +       return (c->fpu_id & LOONGSON_FPREV_MASK) << LOONGSON_CFG1_FPREV_OFFSET;
> +}
> +
> +static void patch_cpucfg_sel1(struct cpuinfo_mips *c)
> +{
> +       u64 ases = c->ases;
> +       u64 options = c->options;
> +       u32 data = c->loongson3_cpucfg_data[0];
> +
> +       if (options & MIPS_CPU_FPU) {
> +               data |= LOONGSON_CFG1_FP;
> +               data |= get_loongson_fprev(c);
> +       }
> +       if (ases & MIPS_ASE_LOONGSON_MMI)
> +               data |= LOONGSON_CFG1_MMI;
> +       if (ases & MIPS_ASE_MSA)
> +               data |= LOONGSON_CFG1_MSA1;
> +
> +       c->loongson3_cpucfg_data[0] = data;
> +}
> +
> +static void patch_cpucfg_sel2(struct cpuinfo_mips *c)
> +{
> +       u64 ases = c->ases;
> +       u64 options = c->options;
> +       u32 data = c->loongson3_cpucfg_data[1];
> +
> +       if (ases & MIPS_ASE_LOONGSON_EXT)
> +               data |= LOONGSON_CFG2_LEXT1;
> +       if (ases & MIPS_ASE_LOONGSON_EXT2)
> +               data |= LOONGSON_CFG2_LEXT2;
> +       if (options & MIPS_CPU_LDPTE)
> +               data |= LOONGSON_CFG2_LSPW;
> +
> +       if (ases & MIPS_ASE_VZ)
> +               data |= LOONGSON_CFG2_LVZP;
> +       else
> +               data &= ~LOONGSON_CFG2_LVZREV;
> +
> +       c->loongson3_cpucfg_data[1] = data;
> +}
> +
> +static void patch_cpucfg_sel3(struct cpuinfo_mips *c)
> +{
> +       u64 ases = c->ases;
> +       u32 data = c->loongson3_cpucfg_data[2];
> +
> +       if (ases & MIPS_ASE_LOONGSON_CAM) {
> +               data |= LOONGSON_CFG3_LCAMP;
> +       } else {
> +               data &= ~LOONGSON_CFG3_LCAMREV;
> +               data &= ~LOONGSON_CFG3_LCAMNUM;
> +               data &= ~LOONGSON_CFG3_LCAMKW;
> +               data &= ~LOONGSON_CFG3_LCAMVW;
> +       }
> +
> +       c->loongson3_cpucfg_data[2] = data;
> +}
> +
> +void loongson3_cpucfg_finish_synthesis(struct cpuinfo_mips *c)
> +{
> +       /* CPUs with CPUCFG support don't need to synthesize anything. */
> +       if (cpu_has_cfg())
> +               return;
> +
> +       patch_cpucfg_sel1(c);
> +       patch_cpucfg_sel2(c);
> +       patch_cpucfg_sel3(c);
> +}
> --
> 2.21.0
>

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

* Re: [PATCH 4/4] MIPS: emulate CPUCFG instruction on older Loongson64 cores
  2020-05-03  6:31   ` Huacai Chen
@ 2020-05-03  7:58     ` Wang Xuerui
  2020-05-03  8:25       ` Jiaxun Yang
  0 siblings, 1 reply; 25+ messages in thread
From: Wang Xuerui @ 2020-05-03  7:58 UTC (permalink / raw)
  To: Huacai Chen, WANG Xuerui; +Cc: open list:MIPS, Jiaxun Yang, Tiezhu Yang

On 5/3/20 2:31 PM, Huacai Chen wrote:

> Hi, Xuerui,
>
> On Sat, May 2, 2020 at 9:47 PM WANG Xuerui <git@xen0n.name> wrote:
>> +
>> +static int simulate_loongson3_csr_cpucfg(struct pt_regs *regs,
>> +                                       unsigned int opcode)
> Maybe simulate_loongson3_cpucfg() is a better name?

Fair point, I was thinking CPUCFG is a part of bigger CSR instructions, 
so kept the prefix; I don't know what other CSR instructions are 
accessible from user-space anyway. (Loongson, could you guys *please* 
release the ISA docs btw?)

Anyway, by removing the "csr" part it feels more consistent with other 
parts of the patch. I'll send v2 soon.


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

* Re: [PATCH 4/4] MIPS: emulate CPUCFG instruction on older Loongson64 cores
  2020-05-03  7:58     ` Wang Xuerui
@ 2020-05-03  8:25       ` Jiaxun Yang
  0 siblings, 0 replies; 25+ messages in thread
From: Jiaxun Yang @ 2020-05-03  8:25 UTC (permalink / raw)
  To: Wang Xuerui, Huacai Chen, WANG Xuerui; +Cc: open list:MIPS, Tiezhu Yang, hww



于 2020年5月3日 GMT+08:00 下午3:58:45, Wang Xuerui <i@xen0n.name> 写到:
>On 5/3/20 2:31 PM, Huacai Chen wrote:
>
>> Hi, Xuerui,
>>
>> On Sat, May 2, 2020 at 9:47 PM WANG Xuerui <git@xen0n.name> wrote:
>>> +
>>> +static int simulate_loongson3_csr_cpucfg(struct pt_regs *regs,
>>> +                                       unsigned int opcode)
>> Maybe simulate_loongson3_cpucfg() is a better name?
>
>Fair point, I was thinking CPUCFG is a part of bigger CSR instructions, 
>so kept the prefix; I don't know what other CSR instructions are 
>accessible from user-space anyway. (Loongson, could you guys *please* 
>release the ISA docs btw?)

Only readcfg and rdtimer family of instructions in CSR ASE
are user space instructions AFAIK.

By the way:

+ Professor Hu:

Sorry for interrupting. But documentations are really important for community development.
We've called Loongson multiple times about that buy got no positive feedback.

Also we've seen Loongson's violation of GPL/MPL on FFmpeg/GCC/Firefox recently.
That's really not a good signal.

Chinese below:

+ 尊敬的胡老师:

很抱歉打扰您,但文档对社区开发者真的非常重要。
我们向龙芯呼吁了数次,但都得不到正面反馈。

最近我们也注意到龙芯在部分开源项目中出现了违反开源协议的现象,这不是一个很好的信号。

谢谢。

Thanks.

>
>Anyway, by removing the "csr" part it feels more consistent with other 
>parts of the patch. I'll send v2 soon.
>

-- 
Jiaxun Yang

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

* [PATCH v2 0/4] CPUCFG emulation on older Loongson64 cores
  2020-05-02 13:38 [PATCH 0/4] CPUCFG emulation on older Loongson64 cores WANG Xuerui
                   ` (3 preceding siblings ...)
  2020-05-02 13:38 ` [PATCH 4/4] MIPS: emulate CPUCFG instruction on older Loongson64 cores WANG Xuerui
@ 2020-05-03 10:33 ` WANG Xuerui
  2020-05-16 11:29   ` WANG Xuerui
  2020-05-03 10:33 ` [PATCH v2 1/4] MIPS: Loongson64: fix typos in loongson_regs.h WANG Xuerui
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 25+ messages in thread
From: WANG Xuerui @ 2020-05-03 10:33 UTC (permalink / raw)
  To: linux-mips; +Cc: WANG Xuerui

This patch series brings the CPUCFG instruction to older Loongson64
cores, enabling a unified way to query processor characteristics on
Loongson64 systems. A detailed explanation may be found in the last
commit.

One unresolved point is how to best introduce machtype-specific bits
into the generic MIPS code, namely the cpu probing and trap handler
parts. I have been struggling over whether to lift this logic into
arch/mips/kernel, but the instruction's encoding (reusing LWC2 opcode)
might be too invasive to be useful to other MIPS platforms. What do
people think is the best way forward?

v2:

- Fixed one more typo in loongson_regs.h
- Merged simulate_loongson3_csr and simulate_loongson3_csr_cpucfg into
  one (simulate_loongson3_cpucfg), per Huacai's suggestion

WANG Xuerui (4):
  MIPS: Loongson64: fix typos in loongson_regs.h
  MIPS: Loongson64: define offsets and known revisions for some CPUCFG
    features
  MIPS: define more Loongson CP0.Config6 and CP0.Diag feature bits
  MIPS: emulate CPUCFG instruction on older Loongson64 cores

 arch/mips/Kconfig                             |  11 ++
 arch/mips/include/asm/cpu-info.h              |   9 ++
 .../include/asm/mach-loongson64/cpucfg-emul.h |  67 +++++++++
 .../asm/mach-loongson64/loongson_regs.h       |  29 +++-
 arch/mips/include/asm/mipsregs.h              |   6 +
 arch/mips/kernel/cpu-probe.c                  | 129 ++++++++++++++++++
 arch/mips/kernel/traps.c                      |  45 ++++++
 arch/mips/loongson64/Makefile                 |   1 +
 arch/mips/loongson64/cpucfg-emul.c            |  80 +++++++++++
 9 files changed, 372 insertions(+), 5 deletions(-)
 create mode 100644 arch/mips/include/asm/mach-loongson64/cpucfg-emul.h
 create mode 100644 arch/mips/loongson64/cpucfg-emul.c

-- 
2.21.0


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

* [PATCH v2 1/4] MIPS: Loongson64: fix typos in loongson_regs.h
  2020-05-02 13:38 [PATCH 0/4] CPUCFG emulation on older Loongson64 cores WANG Xuerui
                   ` (4 preceding siblings ...)
  2020-05-03 10:33 ` [PATCH v2 0/4] CPUCFG emulation " WANG Xuerui
@ 2020-05-03 10:33 ` WANG Xuerui
  2020-05-03 10:33 ` [PATCH v2 2/4] MIPS: Loongson64: define offsets and known revisions for some CPUCFG features WANG Xuerui
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 25+ messages in thread
From: WANG Xuerui @ 2020-05-03 10:33 UTC (permalink / raw)
  To: linux-mips; +Cc: WANG Xuerui, Huacai Chen, Jiaxun Yang

Fix some symbol names to align with Loongson's User Manual wording. Also
correct the comment in csr_readq() suggesting the wrong instruction in
use.

Fixes: 6a6f9b7dafd50efc ("MIPS: Loongson: Add CFUCFG&CSR support")
Signed-off-by: WANG Xuerui <git@xen0n.name>
Cc: Huacai Chen <chenhc@lemote.com>
Cc: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 arch/mips/include/asm/mach-loongson64/loongson_regs.h | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/arch/mips/include/asm/mach-loongson64/loongson_regs.h b/arch/mips/include/asm/mach-loongson64/loongson_regs.h
index 363a47a5d26e..07aab3c5b22c 100644
--- a/arch/mips/include/asm/mach-loongson64/loongson_regs.h
+++ b/arch/mips/include/asm/mach-loongson64/loongson_regs.h
@@ -77,12 +77,12 @@ static inline u32 read_cpucfg(u32 reg)
 #define LOONGSON_CFG2_LBT3	BIT(6)
 #define LOONGSON_CFG2_LBTMMU	BIT(7)
 #define LOONGSON_CFG2_LPMP	BIT(8)
-#define LOONGSON_CFG2_LPMPREV	GENMASK(11, 9)
+#define LOONGSON_CFG2_LPMREV	GENMASK(11, 9)
 #define LOONGSON_CFG2_LAMO	BIT(12)
 #define LOONGSON_CFG2_LPIXU	BIT(13)
-#define LOONGSON_CFG2_LPIXUN	BIT(14)
-#define LOONGSON_CFG2_LZVP	BIT(15)
-#define LOONGSON_CFG2_LZVREV	GENMASK(18, 16)
+#define LOONGSON_CFG2_LPIXNU	BIT(14)
+#define LOONGSON_CFG2_LVZP	BIT(15)
+#define LOONGSON_CFG2_LVZREV	GENMASK(18, 16)
 #define LOONGSON_CFG2_LGFTP	BIT(19)
 #define LOONGSON_CFG2_LGFTPREV	GENMASK(22, 20)
 #define LOONGSON_CFG2_LLFTP	BIT(23)
@@ -139,7 +139,7 @@ static inline u64 csr_readq(u32 reg)
 {
 	u64 __res;
 
-	/* DWRCSR reg, val */
+	/* DRDCSR reg, val */
 	__asm__ __volatile__(
 		"parse_r __res,%0\n\t"
 		"parse_r reg,%1\n\t"
-- 
2.21.0


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

* [PATCH v2 2/4] MIPS: Loongson64: define offsets and known revisions for some CPUCFG features
  2020-05-02 13:38 [PATCH 0/4] CPUCFG emulation on older Loongson64 cores WANG Xuerui
                   ` (5 preceding siblings ...)
  2020-05-03 10:33 ` [PATCH v2 1/4] MIPS: Loongson64: fix typos in loongson_regs.h WANG Xuerui
@ 2020-05-03 10:33 ` WANG Xuerui
  2020-05-03 10:33 ` [PATCH v2 3/4] MIPS: define more Loongson CP0.Config6 and CP0.Diag feature bits WANG Xuerui
  2020-05-03 10:33 ` [PATCH v2 4/4] MIPS: emulate CPUCFG instruction on older Loongson64 cores WANG Xuerui
  8 siblings, 0 replies; 25+ messages in thread
From: WANG Xuerui @ 2020-05-03 10:33 UTC (permalink / raw)
  To: linux-mips; +Cc: WANG Xuerui, Huacai Chen, Jiaxun Yang

Add the constants for easier and maintainable composition of CPUCFG
values.

Signed-off-by: WANG Xuerui <git@xen0n.name>
Cc: Huacai Chen <chenhc@lemote.com>
Cc: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 .../asm/mach-loongson64/loongson_regs.h       | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/arch/mips/include/asm/mach-loongson64/loongson_regs.h b/arch/mips/include/asm/mach-loongson64/loongson_regs.h
index 07aab3c5b22c..83dbb9fdf9c2 100644
--- a/arch/mips/include/asm/mach-loongson64/loongson_regs.h
+++ b/arch/mips/include/asm/mach-loongson64/loongson_regs.h
@@ -67,6 +67,8 @@ static inline u32 read_cpucfg(u32 reg)
 #define LOONGSON_CFG1_SFBP	BIT(29)
 #define LOONGSON_CFG1_CDMAP	BIT(30)
 
+#define LOONGSON_CFG1_FPREV_OFFSET	1
+
 #define LOONGSON_CFG2 0x2
 #define LOONGSON_CFG2_LEXT1	BIT(0)
 #define LOONGSON_CFG2_LEXT2	BIT(1)
@@ -90,6 +92,13 @@ static inline u32 read_cpucfg(u32 reg)
 #define LOONGSON_CFG2_LCSRP	BIT(27)
 #define LOONGSON_CFG2_LDISBLIKELY	BIT(28)
 
+#define LOONGSON_CFG2_LPMREV_OFFSET	9
+#define LOONGSON_CFG2_LPM_REV1		(1 << LOONGSON_CFG2_LPMREV_OFFSET)
+#define LOONGSON_CFG2_LPM_REV2		(2 << LOONGSON_CFG2_LPMREV_OFFSET)
+#define LOONGSON_CFG2_LVZREV_OFFSET	16
+#define LOONGSON_CFG2_LVZ_REV1		(1 << LOONGSON_CFG2_LVZREV_OFFSET)
+#define LOONGSON_CFG2_LVZ_REV2		(2 << LOONGSON_CFG2_LVZREV_OFFSET)
+
 #define LOONGSON_CFG3 0x3
 #define LOONGSON_CFG3_LCAMP	BIT(0)
 #define LOONGSON_CFG3_LCAMREV	GENMASK(3, 1)
@@ -97,6 +106,16 @@ static inline u32 read_cpucfg(u32 reg)
 #define LOONGSON_CFG3_LCAMKW	GENMASK(19, 12)
 #define LOONGSON_CFG3_LCAMVW	GENMASK(27, 20)
 
+#define LOONGSON_CFG3_LCAMREV_OFFSET	1
+#define LOONGSON_CFG3_LCAM_REV1		(1 << LOONGSON_CFG3_LCAMREV_OFFSET)
+#define LOONGSON_CFG3_LCAM_REV2		(2 << LOONGSON_CFG3_LCAMREV_OFFSET)
+#define LOONGSON_CFG3_LCAMNUM_OFFSET	4
+#define LOONGSON_CFG3_LCAMNUM_REV1	(0x3f << LOONGSON_CFG3_LCAMNUM_OFFSET)
+#define LOONGSON_CFG3_LCAMKW_OFFSET	12
+#define LOONGSON_CFG3_LCAMKW_REV1	(0x27 << LOONGSON_CFG3_LCAMKW_OFFSET)
+#define LOONGSON_CFG3_LCAMVW_OFFSET	20
+#define LOONGSON_CFG3_LCAMVW_REV1	(0x3f << LOONGSON_CFG3_LCAMVW_OFFSET)
+
 #define LOONGSON_CFG4 0x4
 #define LOONGSON_CFG4_CCFREQ	GENMASK(31, 0)
 
-- 
2.21.0


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

* [PATCH v2 3/4] MIPS: define more Loongson CP0.Config6 and CP0.Diag feature bits
  2020-05-02 13:38 [PATCH 0/4] CPUCFG emulation on older Loongson64 cores WANG Xuerui
                   ` (6 preceding siblings ...)
  2020-05-03 10:33 ` [PATCH v2 2/4] MIPS: Loongson64: define offsets and known revisions for some CPUCFG features WANG Xuerui
@ 2020-05-03 10:33 ` WANG Xuerui
  2020-05-03 10:33 ` [PATCH v2 4/4] MIPS: emulate CPUCFG instruction on older Loongson64 cores WANG Xuerui
  8 siblings, 0 replies; 25+ messages in thread
From: WANG Xuerui @ 2020-05-03 10:33 UTC (permalink / raw)
  To: linux-mips; +Cc: WANG Xuerui, Huacai Chen, Jiaxun Yang

These are exposed to userland alternatively via the new CPUCFG
instruction on Loongson-3A R4 and above. Add definitions for readback
on older cores.

Signed-off-by: WANG Xuerui <git@xen0n.name>
Cc: Huacai Chen <chenhc@lemote.com>
Cc: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 arch/mips/include/asm/mipsregs.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index 796fe47cfd17..90f843c72774 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -681,6 +681,10 @@
 #define MIPS_CONF6_FTLBDIS	(_ULCAST_(1) << 22)
 /* FTLB probability bits */
 #define MIPS_CONF6_FTLBP_SHIFT	(16)
+/* Loongson-3 feature bits */
+#define MIPS_CONF6_LOONGSON_SCRAND	(_ULCAST_(1) << 17)
+#define MIPS_CONF6_LOONGSON_LLEXC	(_ULCAST_(1) << 16)
+#define MIPS_CONF6_LOONGSON_STFILL	(_ULCAST_(1) << 8)
 
 #define MIPS_CONF7_WII		(_ULCAST_(1) << 31)
 
@@ -997,6 +1001,8 @@
 #define LOONGSON_DIAG_ITLB	(_ULCAST_(1) << 2)
 /* Flush DTLB */
 #define LOONGSON_DIAG_DTLB	(_ULCAST_(1) << 3)
+/* Allow some CACHE instructions (CACHE0, 1, 3, 21 and 23) in user mode */
+#define LOONGSON_DIAG_UCAC	(_ULCAST_(1) << 8)
 /* Flush VTLB */
 #define LOONGSON_DIAG_VTLB	(_ULCAST_(1) << 12)
 /* Flush FTLB */
-- 
2.21.0


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

* [PATCH v2 4/4] MIPS: emulate CPUCFG instruction on older Loongson64 cores
  2020-05-02 13:38 [PATCH 0/4] CPUCFG emulation on older Loongson64 cores WANG Xuerui
                   ` (7 preceding siblings ...)
  2020-05-03 10:33 ` [PATCH v2 3/4] MIPS: define more Loongson CP0.Config6 and CP0.Diag feature bits WANG Xuerui
@ 2020-05-03 10:33 ` WANG Xuerui
  2020-05-03 10:50   ` [PATCH v2 RESEND " WANG Xuerui
  8 siblings, 1 reply; 25+ messages in thread
From: WANG Xuerui @ 2020-05-03 10:33 UTC (permalink / raw)
  To: linux-mips; +Cc: WANG Xuerui, Huacai Chen, Jiaxun Yang, Tiezhu Yang

CPUCFG is the instruction for querying processor characteristics on
newer Loongson processors, much like CPUID of x86. Since the instruction
is supposedly designed to provide a unified way to do feature detection
(without having to, for example, parse /proc/cpuinfo which is too
heavyweight), it is important to provide compatibility for older cores
without native support. Fortunately, most of the fields can be
synthesized without changes to semantics. Performance is not really big
a concern, because feature detection logic is not expected to be
invoked very often in typical userland applications.

The instruction can't be emulated on LOONGSON_2EF cores, according to
FlyGoat's experiments. Because the LWC2 opcode is assigned to other
valid instructions on 2E and 2F, no RI exception is raised for us to
intercept. So compatibility is only extended back furthest to
Loongson-3A1000. Loongson-2K is covered too, as it is basically a remix
of various blocks from the 3A/3B models from a kernel perspective.

This is lightly based on Loongson's work on their Linux 3.10 fork, for
being the authority on the right feature flags to fill in, where things
aren't otherwise discoverable.

Signed-off-by: WANG Xuerui <git@xen0n.name>
Cc: Huacai Chen <chenhc@lemote.com>
Cc: Jiaxun Yang <jiaxun.yang@flygoat.com>
Cc: Tiezhu Yang <yangtiezhu@loongson.cn>
---
 arch/mips/Kconfig                             |  11 ++
 arch/mips/include/asm/cpu-info.h              |   9 ++
 .../include/asm/mach-loongson64/cpucfg-emul.h |  67 +++++++++
 arch/mips/kernel/cpu-probe.c                  | 129 ++++++++++++++++++
 arch/mips/kernel/traps.c                      |  45 ++++++
 arch/mips/loongson64/Makefile                 |   1 +
 arch/mips/loongson64/cpucfg-emul.c            |  80 +++++++++++
 7 files changed, 342 insertions(+)
 create mode 100644 arch/mips/include/asm/mach-loongson64/cpucfg-emul.h
 create mode 100644 arch/mips/loongson64/cpucfg-emul.c

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 9f15539a6342..2ab189001917 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1508,6 +1508,17 @@ config CPU_LOONGSON3_WORKAROUNDS
 
 	  If unsure, please say Y.
 
+config CPU_LOONGSON3_CPUCFG_EMULATION
+	bool "Emulate the CPUCFG instruction on older cores"
+	default y
+	depends on CPU_LOONGSON64
+	help
+	  Loongson-3A R4 and newer have the CPUCFG instruction available for
+	  userland to query CPU capabilities, much like CPUID on x86. This
+	  option provides emulation of the instruction on older cores.
+
+	  If unsure, please say Y.
+
 config CPU_LOONGSON2E
 	bool "Loongson 2E"
 	depends on SYS_HAS_CPU_LOONGSON2E
diff --git a/arch/mips/include/asm/cpu-info.h b/arch/mips/include/asm/cpu-info.h
index ed7ffe4e63a3..43c238567a80 100644
--- a/arch/mips/include/asm/cpu-info.h
+++ b/arch/mips/include/asm/cpu-info.h
@@ -105,6 +105,15 @@ struct cpuinfo_mips {
 	unsigned int		gtoffset_mask;
 	unsigned int		guestid_mask;
 	unsigned int		guestid_cache;
+
+#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
+	/* CPUCFG data for this CPU, synthesized at probe time.
+	 *
+	 * CPUCFG select 0 is PRId, others are unimplemented for now. So the
+	 * only stored values are for CPUCFG selects 1-3 inclusive.
+	 */
+	u32 loongson3_cpucfg_data[3];
+#endif
 } __attribute__((aligned(SMP_CACHE_BYTES)));
 
 extern struct cpuinfo_mips cpu_data[];
diff --git a/arch/mips/include/asm/mach-loongson64/cpucfg-emul.h b/arch/mips/include/asm/mach-loongson64/cpucfg-emul.h
new file mode 100644
index 000000000000..b9f6b2aa98f9
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson64/cpucfg-emul.h
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_MACH_LOONGSON64_CPUCFG_EMUL_H_
+#define _ASM_MACH_LOONGSON64_CPUCFG_EMUL_H_
+
+#include <asm/cpu-info.h>
+
+#include <loongson_regs.h>
+
+#define LOONGSON_FPREV_MASK 0x7
+
+#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
+
+/* Finalize synthesis of CPUCFG data by patching the partially filled data
+ * with dynamically detected CPU characteristics. This keeps the amount of
+ * hard-coded logic at a minimum.
+ */
+void loongson3_cpucfg_finish_synthesis(struct cpuinfo_mips *c);
+
+static inline u32 loongson3_cpucfg_read_synthesized(
+	struct cpuinfo_mips *c,
+	__u64 sel)
+{
+	switch (sel) {
+	case LOONGSON_CFG0:
+		return c->processor_id;
+	case LOONGSON_CFG1:
+	case LOONGSON_CFG2:
+	case LOONGSON_CFG3:
+		return c->loongson3_cpucfg_data[sel - 1];
+	case LOONGSON_CFG4:
+	case LOONGSON_CFG5:
+		/* CPUCFG selects 4 and 5 are related to the processor clock.
+		 * Unimplemented for now.
+		 */
+		return 0;
+	case LOONGSON_CFG6:
+		/* CPUCFG select 6 is for the undocumented Safe Extension. */
+		return 0;
+	case LOONGSON_CFG7:
+		/* CPUCFG select 7 is for the virtualization extension.
+		 * We don't know if the two currently known features are
+		 * supported on older cores according to the public
+		 * documentation, so leave this at zero.
+		 */
+		return 0;
+	}
+
+	/*
+	 * Return 0 for unrecognized CPUCFG selects, which is real hardware
+	 * behavior observed on Loongson 3A R4.
+	 */
+	return 0;
+}
+#else
+static void loongson3_cpucfg_finish_synthesis(struct cpuinfo_mips *c)
+{
+}
+
+static inline u32 loongson3_cpucfg_read_synthesized(
+	struct cpuinfo_mips *c,
+	__u64 sel)
+{
+	return 0;
+}
+#endif
+
+#endif /* _ASM_MACH_LOONGSON64_CPUCFG_EMUL_H_ */
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index ca2e6f1af4fe..907e31ff562f 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -28,6 +28,8 @@
 #include <asm/spram.h>
 #include <linux/uaccess.h>
 
+#include <asm/mach-loongson64/cpucfg-emul.h>
+
 /* Hardware capabilities */
 unsigned int elf_hwcap __read_mostly;
 EXPORT_SYMBOL_GPL(elf_hwcap);
@@ -1580,6 +1582,24 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
 			set_isa(c, MIPS_CPU_ISA_M64R1);
 			c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_CAM |
 				MIPS_ASE_LOONGSON_EXT);
+#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
+			/* Add CPUCFG features non-discoverable otherwise. */
+			c->loongson3_cpucfg_data[0] |= (LOONGSON_CFG1_LSLDR0 |
+				LOONGSON_CFG1_LSSYNCI | LOONGSON_CFG1_LSUCA |
+				LOONGSON_CFG1_LLSYNC | LOONGSON_CFG1_TGTSYNC);
+			c->loongson3_cpucfg_data[1] |= (LOONGSON_CFG2_LBT1 |
+				LOONGSON_CFG2_LPMP | LOONGSON_CFG2_LPM_REV1);
+			c->loongson3_cpucfg_data[2] |= (
+				LOONGSON_CFG3_LCAM_REV1 |
+				LOONGSON_CFG3_LCAMNUM_REV1 |
+				LOONGSON_CFG3_LCAMKW_REV1 |
+				LOONGSON_CFG3_LCAMVW_REV1);
+
+			/* This feature is set by firmware, but all known
+			 * Loongson-3A Legacy systems are configured this way.
+			 */
+			c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_CDMAP;
+#endif
 			break;
 		case PRID_REV_LOONGSON3B_R1:
 		case PRID_REV_LOONGSON3B_R2:
@@ -1589,6 +1609,24 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
 			set_isa(c, MIPS_CPU_ISA_M64R1);
 			c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_CAM |
 				MIPS_ASE_LOONGSON_EXT);
+#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
+			/* Add CPUCFG features non-discoverable otherwise. */
+			c->loongson3_cpucfg_data[0] |= (LOONGSON_CFG1_LSLDR0 |
+				LOONGSON_CFG1_LSSYNCI | LOONGSON_CFG1_LSUCA |
+				LOONGSON_CFG1_LLSYNC | LOONGSON_CFG1_TGTSYNC);
+			c->loongson3_cpucfg_data[1] |= (LOONGSON_CFG2_LBT1 |
+				LOONGSON_CFG2_LPMP | LOONGSON_CFG2_LPM_REV1);
+			c->loongson3_cpucfg_data[2] |= (
+				LOONGSON_CFG3_LCAM_REV1 |
+				LOONGSON_CFG3_LCAMNUM_REV1 |
+				LOONGSON_CFG3_LCAMKW_REV1 |
+				LOONGSON_CFG3_LCAMVW_REV1);
+
+			/* This feature is set by firmware, but all known
+			 * Loongson-3B Legacy systems are configured this way.
+			 */
+			c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_CDMAP;
+#endif
 			break;
 		}
 
@@ -1957,9 +1995,57 @@ static inline void decode_cpucfg(struct cpuinfo_mips *c)
 		c->ases |= MIPS_ASE_LOONGSON_CAM;
 }
 
+#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
+static inline int cpu_has_uca(void)
+{
+	u32 diag = read_c0_diag();
+	u32 new_diag;
+
+	if (diag & LOONGSON_DIAG_UCAC)
+		/* UCA is already enabled. */
+		return 1;
+
+	/* See if UCAC bit can be flipped on. This should be safe. */
+	new_diag = diag | LOONGSON_DIAG_UCAC;
+	write_c0_diag(new_diag);
+	new_diag = read_c0_diag();
+	write_c0_diag(diag);
+
+	return (new_diag & LOONGSON_DIAG_UCAC) != 0;
+}
+
+static inline void probe_uca(struct cpuinfo_mips *c)
+{
+	if (cpu_has_uca())
+		c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_LSUCA;
+}
+
+static inline void decode_loongson_config6(struct cpuinfo_mips *c)
+{
+	u32 config6 = read_c0_config6();
+
+	if (config6 & MIPS_CONF6_LOONGSON_STFILL)
+		c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_SFBP;
+	if (config6 & MIPS_CONF6_LOONGSON_LLEXC)
+		c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_LLEXC;
+	if (config6 & MIPS_CONF6_LOONGSON_SCRAND)
+		c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_SCRAND;
+}
+#else
+static inline void probe_uca(struct cpuinfo_mips *c)
+{
+}
+
+static inline void decode_loongson_config6(struct cpuinfo_mips *c)
+{
+}
+#endif /* CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION */
+
 static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)
 {
 	decode_configs(c);
+	decode_loongson_config6(c);
+	probe_uca(c);
 
 	switch (c->processor_id & PRID_IMP_MASK) {
 	case PRID_IMP_LOONGSON_64R: /* Loongson-64 Reduced */
@@ -1977,6 +2063,21 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)
 		c->writecombine = _CACHE_UNCACHED_ACCELERATED;
 		c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_EXT |
 				MIPS_ASE_LOONGSON_EXT2);
+#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
+		/* Add CPUCFG features non-discoverable otherwise. */
+		c->loongson3_cpucfg_data[0] |= (LOONGSON_CFG1_LSLDR0 |
+			LOONGSON_CFG1_LSSYNCI | LOONGSON_CFG1_LLSYNC |
+			LOONGSON_CFG1_TGTSYNC);
+		c->loongson3_cpucfg_data[1] |= (LOONGSON_CFG2_LBT1 |
+			LOONGSON_CFG2_LBT2 | LOONGSON_CFG2_LPMP |
+			LOONGSON_CFG2_LPM_REV2);
+		c->loongson3_cpucfg_data[2] = 0;
+
+		/* This feature is set by firmware, but all known Loongson-2K
+		 * systems are configured this way.
+		 */
+		c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_CDMAP;
+#endif
 		break;
 	case PRID_IMP_LOONGSON_64C:  /* Loongson-3 Classic */
 		switch (c->processor_id & PRID_REV_MASK) {
@@ -2007,6 +2108,26 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)
 		c->writecombine = _CACHE_UNCACHED_ACCELERATED;
 		c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_CAM |
 			MIPS_ASE_LOONGSON_EXT | MIPS_ASE_LOONGSON_EXT2);
+#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
+		/* Add CPUCFG features non-discoverable otherwise. */
+		c->loongson3_cpucfg_data[0] |= (LOONGSON_CFG1_CNT64 |
+			LOONGSON_CFG1_LSLDR0 | LOONGSON_CFG1_LSPREF |
+			LOONGSON_CFG1_LSPREFX | LOONGSON_CFG1_LSSYNCI |
+			LOONGSON_CFG1_LLSYNC | LOONGSON_CFG1_TGTSYNC);
+		c->loongson3_cpucfg_data[1] |= (LOONGSON_CFG2_LBT1 |
+			LOONGSON_CFG2_LBT2 | LOONGSON_CFG2_LBTMMU |
+			LOONGSON_CFG2_LPMP | LOONGSON_CFG2_LPM_REV1 |
+			LOONGSON_CFG2_LVZ_REV1);
+		c->loongson3_cpucfg_data[2] |= (LOONGSON_CFG3_LCAM_REV1 |
+			LOONGSON_CFG3_LCAMNUM_REV1 |
+			LOONGSON_CFG3_LCAMKW_REV1 |
+			LOONGSON_CFG3_LCAMVW_REV1);
+
+		/* This feature is set by firmware, but all known Loongson-3
+		 * systems are configured this way.
+		 */
+		c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_CDMAP;
+#endif
 		break;
 	case PRID_IMP_LOONGSON_64G:
 		c->cputype = CPU_LOONGSON64;
@@ -2200,6 +2321,12 @@ void cpu_probe(void)
 	c->fpu_csr31	= FPU_CSR_RN;
 	c->fpu_msk31	= FPU_CSR_RSVD | FPU_CSR_ABS2008 | FPU_CSR_NAN2008;
 
+#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
+	c->loongson3_cpucfg_data[0] = 0;
+	c->loongson3_cpucfg_data[1] = 0;
+	c->loongson3_cpucfg_data[2] = 0;
+#endif
+
 	c->processor_id = read_c0_prid();
 	switch (c->processor_id & PRID_COMP_MASK) {
 	case PRID_COMP_LEGACY:
@@ -2333,6 +2460,8 @@ void cpu_probe(void)
 	if (cpu_has_vz)
 		cpu_probe_vz(c);
 
+	loongson3_cpucfg_finish_synthesis(c);
+
 	cpu_probe_vmbits(c);
 
 #ifdef CONFIG_64BIT
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 31968cbd6464..768790917724 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -71,6 +71,8 @@
 #include <asm/tlbex.h>
 #include <asm/uasm.h>
 
+#include <asm/mach-loongson64/cpucfg-emul.h>
+
 extern void check_wait(void);
 extern asmlinkage void rollback_handle_int(void);
 extern asmlinkage void handle_int(void);
@@ -693,6 +695,44 @@ static int simulate_sync(struct pt_regs *regs, unsigned int opcode)
 	return -1;			/* Must be something else ... */
 }
 
+/*
+ * Loongson-3 CSR instructions emulation
+ */
+
+#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
+
+#define LWC2             0xc8000000
+#define RS               BASE
+#define CSR_OPCODE2      0x00000118
+#define CSR_OPCODE2_MASK 0x000007ff
+#define CSR_FUNC_MASK    RT
+#define CSR_FUNC_CPUCFG  0x8
+
+static int simulate_loongson3_cpucfg(struct pt_regs *regs,
+				     unsigned int opcode)
+{
+	int op = opcode & OPCODE;
+	int op2 = opcode & CSR_OPCODE2_MASK;
+	int csr_func = (opcode & CSR_FUNC_MASK) >> 16;
+
+	if (op == LWC2 && op2 == CSR_OPCODE2 && csr_func == CSR_FUNC_CPUCFG) {
+		int rd = (opcode & RD) >> 11;
+		int rs = (opcode & RS) >> 21;
+		__u64 sel = regs->regs[rs];
+
+		perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
+
+		regs->regs[rd] = loongson3_cpucfg_read_synthesized(
+			&current_cpu_data, sel);
+
+		return 0;
+	}
+
+	/* Not ours.  */
+	return -1;
+}
+#endif /* CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION */
+
 asmlinkage void do_ov(struct pt_regs *regs)
 {
 	enum ctx_state prev_state;
@@ -1166,6 +1206,11 @@ asmlinkage void do_ri(struct pt_regs *regs)
 
 		if (status < 0)
 			status = simulate_fp(regs, opcode, old_epc, old31);
+
+#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
+		if (status < 0)
+			status = simulate_loongson3_cpucfg(regs, opcode);
+#endif
 	} else if (cpu_has_mmips) {
 		unsigned short mmop[2] = { 0 };
 
diff --git a/arch/mips/loongson64/Makefile b/arch/mips/loongson64/Makefile
index 6f3c2b47f66f..61f6add20530 100644
--- a/arch/mips/loongson64/Makefile
+++ b/arch/mips/loongson64/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_NUMA)	+= numa.o
 obj-$(CONFIG_RS780_HPET) += hpet.o
 obj-$(CONFIG_PCI) += pci.o
 obj-$(CONFIG_SUSPEND) += pm.o
+obj-$(CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION) += cpucfg-emul.o
diff --git a/arch/mips/loongson64/cpucfg-emul.c b/arch/mips/loongson64/cpucfg-emul.c
new file mode 100644
index 000000000000..a30f82b55c9e
--- /dev/null
+++ b/arch/mips/loongson64/cpucfg-emul.c
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/smp.h>
+#include <asm/cpu.h>
+#include <asm/cpu-info.h>
+
+#include <loongson_regs.h>
+#include <cpucfg-emul.h>
+
+static u32 get_loongson_fprev(struct cpuinfo_mips *c)
+{
+	return (c->fpu_id & LOONGSON_FPREV_MASK) << LOONGSON_CFG1_FPREV_OFFSET;
+}
+
+static void patch_cpucfg_sel1(struct cpuinfo_mips *c)
+{
+	u64 ases = c->ases;
+	u64 options = c->options;
+	u32 data = c->loongson3_cpucfg_data[0];
+
+	if (options & MIPS_CPU_FPU) {
+		data |= LOONGSON_CFG1_FP;
+		data |= get_loongson_fprev(c);
+	}
+	if (ases & MIPS_ASE_LOONGSON_MMI)
+		data |= LOONGSON_CFG1_MMI;
+	if (ases & MIPS_ASE_MSA)
+		data |= LOONGSON_CFG1_MSA1;
+
+	c->loongson3_cpucfg_data[0] = data;
+}
+
+static void patch_cpucfg_sel2(struct cpuinfo_mips *c)
+{
+	u64 ases = c->ases;
+	u64 options = c->options;
+	u32 data = c->loongson3_cpucfg_data[1];
+
+	if (ases & MIPS_ASE_LOONGSON_EXT)
+		data |= LOONGSON_CFG2_LEXT1;
+	if (ases & MIPS_ASE_LOONGSON_EXT2)
+		data |= LOONGSON_CFG2_LEXT2;
+	if (options & MIPS_CPU_LDPTE)
+		data |= LOONGSON_CFG2_LSPW;
+
+	if (ases & MIPS_ASE_VZ)
+		data |= LOONGSON_CFG2_LVZP;
+	else
+		data &= ~LOONGSON_CFG2_LVZREV;
+
+	c->loongson3_cpucfg_data[1] = data;
+}
+
+static void patch_cpucfg_sel3(struct cpuinfo_mips *c)
+{
+	u64 ases = c->ases;
+	u32 data = c->loongson3_cpucfg_data[2];
+
+	if (ases & MIPS_ASE_LOONGSON_CAM) {
+		data |= LOONGSON_CFG3_LCAMP;
+	} else {
+		data &= ~LOONGSON_CFG3_LCAMREV;
+		data &= ~LOONGSON_CFG3_LCAMNUM;
+		data &= ~LOONGSON_CFG3_LCAMKW;
+		data &= ~LOONGSON_CFG3_LCAMVW;
+	}
+
+	c->loongson3_cpucfg_data[2] = data;
+}
+
+void loongson3_cpucfg_finish_synthesis(struct cpuinfo_mips *c)
+{
+	/* CPUs with CPUCFG support don't need to synthesize anything. */
+	if (cpu_has_cfg())
+		return;
+
+	patch_cpucfg_sel1(c);
+	patch_cpucfg_sel2(c);
+	patch_cpucfg_sel3(c);
+}
-- 
2.21.0


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

* [PATCH v2 RESEND 4/4] MIPS: emulate CPUCFG instruction on older Loongson64 cores
  2020-05-03 10:33 ` [PATCH v2 4/4] MIPS: emulate CPUCFG instruction on older Loongson64 cores WANG Xuerui
@ 2020-05-03 10:50   ` WANG Xuerui
  2020-05-03 15:50     ` Jiaxun Yang
  2020-05-17  8:37     ` Thomas Bogendoerfer
  0 siblings, 2 replies; 25+ messages in thread
From: WANG Xuerui @ 2020-05-03 10:50 UTC (permalink / raw)
  To: linux-mips; +Cc: WANG Xuerui, Jiaxun Yang, Huacai Chen, Tiezhu Yang

CPUCFG is the instruction for querying processor characteristics on
newer Loongson processors, much like CPUID of x86. Since the instruction
is supposedly designed to provide a unified way to do feature detection
(without having to, for example, parse /proc/cpuinfo which is too
heavyweight), it is important to provide compatibility for older cores
without native support. Fortunately, most of the fields can be
synthesized without changes to semantics. Performance is not really big
a concern, because feature detection logic is not expected to be
invoked very often in typical userland applications.

The instruction can't be emulated on LOONGSON_2EF cores, according to
FlyGoat's experiments. Because the LWC2 opcode is assigned to other
valid instructions on 2E and 2F, no RI exception is raised for us to
intercept. So compatibility is only extended back furthest to
Loongson-3A1000. Loongson-2K is covered too, as it is basically a remix
of various blocks from the 3A/3B models from a kernel perspective.

This is lightly based on Loongson's work on their Linux 3.10 fork, for
being the authority on the right feature flags to fill in, where things
aren't otherwise discoverable.

Signed-off-by: WANG Xuerui <git@xen0n.name>
Reviewed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Tested-by: Jiaxun Yang <jiaxun.yang@flygoat.com> # Loongson-2K, 3B1500
Cc: Huacai Chen <chenhc@lemote.com>
Cc: Jiaxun Yang <jiaxun.yang@flygoat.com>
Cc: Tiezhu Yang <yangtiezhu@loongson.cn>
---

Resend because I forgot to include Jiaxun's review tags. Sorry for the
noise.

 arch/mips/Kconfig                             |  11 ++
 arch/mips/include/asm/cpu-info.h              |   9 ++
 .../include/asm/mach-loongson64/cpucfg-emul.h |  67 +++++++++
 arch/mips/kernel/cpu-probe.c                  | 129 ++++++++++++++++++
 arch/mips/kernel/traps.c                      |  45 ++++++
 arch/mips/loongson64/Makefile                 |   1 +
 arch/mips/loongson64/cpucfg-emul.c            |  80 +++++++++++
 7 files changed, 342 insertions(+)
 create mode 100644 arch/mips/include/asm/mach-loongson64/cpucfg-emul.h
 create mode 100644 arch/mips/loongson64/cpucfg-emul.c

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 9f15539a6342..2ab189001917 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1508,6 +1508,17 @@ config CPU_LOONGSON3_WORKAROUNDS
 
 	  If unsure, please say Y.
 
+config CPU_LOONGSON3_CPUCFG_EMULATION
+	bool "Emulate the CPUCFG instruction on older cores"
+	default y
+	depends on CPU_LOONGSON64
+	help
+	  Loongson-3A R4 and newer have the CPUCFG instruction available for
+	  userland to query CPU capabilities, much like CPUID on x86. This
+	  option provides emulation of the instruction on older cores.
+
+	  If unsure, please say Y.
+
 config CPU_LOONGSON2E
 	bool "Loongson 2E"
 	depends on SYS_HAS_CPU_LOONGSON2E
diff --git a/arch/mips/include/asm/cpu-info.h b/arch/mips/include/asm/cpu-info.h
index ed7ffe4e63a3..43c238567a80 100644
--- a/arch/mips/include/asm/cpu-info.h
+++ b/arch/mips/include/asm/cpu-info.h
@@ -105,6 +105,15 @@ struct cpuinfo_mips {
 	unsigned int		gtoffset_mask;
 	unsigned int		guestid_mask;
 	unsigned int		guestid_cache;
+
+#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
+	/* CPUCFG data for this CPU, synthesized at probe time.
+	 *
+	 * CPUCFG select 0 is PRId, others are unimplemented for now. So the
+	 * only stored values are for CPUCFG selects 1-3 inclusive.
+	 */
+	u32 loongson3_cpucfg_data[3];
+#endif
 } __attribute__((aligned(SMP_CACHE_BYTES)));
 
 extern struct cpuinfo_mips cpu_data[];
diff --git a/arch/mips/include/asm/mach-loongson64/cpucfg-emul.h b/arch/mips/include/asm/mach-loongson64/cpucfg-emul.h
new file mode 100644
index 000000000000..b9f6b2aa98f9
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson64/cpucfg-emul.h
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_MACH_LOONGSON64_CPUCFG_EMUL_H_
+#define _ASM_MACH_LOONGSON64_CPUCFG_EMUL_H_
+
+#include <asm/cpu-info.h>
+
+#include <loongson_regs.h>
+
+#define LOONGSON_FPREV_MASK 0x7
+
+#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
+
+/* Finalize synthesis of CPUCFG data by patching the partially filled data
+ * with dynamically detected CPU characteristics. This keeps the amount of
+ * hard-coded logic at a minimum.
+ */
+void loongson3_cpucfg_finish_synthesis(struct cpuinfo_mips *c);
+
+static inline u32 loongson3_cpucfg_read_synthesized(
+	struct cpuinfo_mips *c,
+	__u64 sel)
+{
+	switch (sel) {
+	case LOONGSON_CFG0:
+		return c->processor_id;
+	case LOONGSON_CFG1:
+	case LOONGSON_CFG2:
+	case LOONGSON_CFG3:
+		return c->loongson3_cpucfg_data[sel - 1];
+	case LOONGSON_CFG4:
+	case LOONGSON_CFG5:
+		/* CPUCFG selects 4 and 5 are related to the processor clock.
+		 * Unimplemented for now.
+		 */
+		return 0;
+	case LOONGSON_CFG6:
+		/* CPUCFG select 6 is for the undocumented Safe Extension. */
+		return 0;
+	case LOONGSON_CFG7:
+		/* CPUCFG select 7 is for the virtualization extension.
+		 * We don't know if the two currently known features are
+		 * supported on older cores according to the public
+		 * documentation, so leave this at zero.
+		 */
+		return 0;
+	}
+
+	/*
+	 * Return 0 for unrecognized CPUCFG selects, which is real hardware
+	 * behavior observed on Loongson 3A R4.
+	 */
+	return 0;
+}
+#else
+static void loongson3_cpucfg_finish_synthesis(struct cpuinfo_mips *c)
+{
+}
+
+static inline u32 loongson3_cpucfg_read_synthesized(
+	struct cpuinfo_mips *c,
+	__u64 sel)
+{
+	return 0;
+}
+#endif
+
+#endif /* _ASM_MACH_LOONGSON64_CPUCFG_EMUL_H_ */
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index ca2e6f1af4fe..907e31ff562f 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -28,6 +28,8 @@
 #include <asm/spram.h>
 #include <linux/uaccess.h>
 
+#include <asm/mach-loongson64/cpucfg-emul.h>
+
 /* Hardware capabilities */
 unsigned int elf_hwcap __read_mostly;
 EXPORT_SYMBOL_GPL(elf_hwcap);
@@ -1580,6 +1582,24 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
 			set_isa(c, MIPS_CPU_ISA_M64R1);
 			c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_CAM |
 				MIPS_ASE_LOONGSON_EXT);
+#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
+			/* Add CPUCFG features non-discoverable otherwise. */
+			c->loongson3_cpucfg_data[0] |= (LOONGSON_CFG1_LSLDR0 |
+				LOONGSON_CFG1_LSSYNCI | LOONGSON_CFG1_LSUCA |
+				LOONGSON_CFG1_LLSYNC | LOONGSON_CFG1_TGTSYNC);
+			c->loongson3_cpucfg_data[1] |= (LOONGSON_CFG2_LBT1 |
+				LOONGSON_CFG2_LPMP | LOONGSON_CFG2_LPM_REV1);
+			c->loongson3_cpucfg_data[2] |= (
+				LOONGSON_CFG3_LCAM_REV1 |
+				LOONGSON_CFG3_LCAMNUM_REV1 |
+				LOONGSON_CFG3_LCAMKW_REV1 |
+				LOONGSON_CFG3_LCAMVW_REV1);
+
+			/* This feature is set by firmware, but all known
+			 * Loongson-3A Legacy systems are configured this way.
+			 */
+			c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_CDMAP;
+#endif
 			break;
 		case PRID_REV_LOONGSON3B_R1:
 		case PRID_REV_LOONGSON3B_R2:
@@ -1589,6 +1609,24 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
 			set_isa(c, MIPS_CPU_ISA_M64R1);
 			c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_CAM |
 				MIPS_ASE_LOONGSON_EXT);
+#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
+			/* Add CPUCFG features non-discoverable otherwise. */
+			c->loongson3_cpucfg_data[0] |= (LOONGSON_CFG1_LSLDR0 |
+				LOONGSON_CFG1_LSSYNCI | LOONGSON_CFG1_LSUCA |
+				LOONGSON_CFG1_LLSYNC | LOONGSON_CFG1_TGTSYNC);
+			c->loongson3_cpucfg_data[1] |= (LOONGSON_CFG2_LBT1 |
+				LOONGSON_CFG2_LPMP | LOONGSON_CFG2_LPM_REV1);
+			c->loongson3_cpucfg_data[2] |= (
+				LOONGSON_CFG3_LCAM_REV1 |
+				LOONGSON_CFG3_LCAMNUM_REV1 |
+				LOONGSON_CFG3_LCAMKW_REV1 |
+				LOONGSON_CFG3_LCAMVW_REV1);
+
+			/* This feature is set by firmware, but all known
+			 * Loongson-3B Legacy systems are configured this way.
+			 */
+			c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_CDMAP;
+#endif
 			break;
 		}
 
@@ -1957,9 +1995,57 @@ static inline void decode_cpucfg(struct cpuinfo_mips *c)
 		c->ases |= MIPS_ASE_LOONGSON_CAM;
 }
 
+#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
+static inline int cpu_has_uca(void)
+{
+	u32 diag = read_c0_diag();
+	u32 new_diag;
+
+	if (diag & LOONGSON_DIAG_UCAC)
+		/* UCA is already enabled. */
+		return 1;
+
+	/* See if UCAC bit can be flipped on. This should be safe. */
+	new_diag = diag | LOONGSON_DIAG_UCAC;
+	write_c0_diag(new_diag);
+	new_diag = read_c0_diag();
+	write_c0_diag(diag);
+
+	return (new_diag & LOONGSON_DIAG_UCAC) != 0;
+}
+
+static inline void probe_uca(struct cpuinfo_mips *c)
+{
+	if (cpu_has_uca())
+		c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_LSUCA;
+}
+
+static inline void decode_loongson_config6(struct cpuinfo_mips *c)
+{
+	u32 config6 = read_c0_config6();
+
+	if (config6 & MIPS_CONF6_LOONGSON_STFILL)
+		c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_SFBP;
+	if (config6 & MIPS_CONF6_LOONGSON_LLEXC)
+		c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_LLEXC;
+	if (config6 & MIPS_CONF6_LOONGSON_SCRAND)
+		c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_SCRAND;
+}
+#else
+static inline void probe_uca(struct cpuinfo_mips *c)
+{
+}
+
+static inline void decode_loongson_config6(struct cpuinfo_mips *c)
+{
+}
+#endif /* CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION */
+
 static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)
 {
 	decode_configs(c);
+	decode_loongson_config6(c);
+	probe_uca(c);
 
 	switch (c->processor_id & PRID_IMP_MASK) {
 	case PRID_IMP_LOONGSON_64R: /* Loongson-64 Reduced */
@@ -1977,6 +2063,21 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)
 		c->writecombine = _CACHE_UNCACHED_ACCELERATED;
 		c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_EXT |
 				MIPS_ASE_LOONGSON_EXT2);
+#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
+		/* Add CPUCFG features non-discoverable otherwise. */
+		c->loongson3_cpucfg_data[0] |= (LOONGSON_CFG1_LSLDR0 |
+			LOONGSON_CFG1_LSSYNCI | LOONGSON_CFG1_LLSYNC |
+			LOONGSON_CFG1_TGTSYNC);
+		c->loongson3_cpucfg_data[1] |= (LOONGSON_CFG2_LBT1 |
+			LOONGSON_CFG2_LBT2 | LOONGSON_CFG2_LPMP |
+			LOONGSON_CFG2_LPM_REV2);
+		c->loongson3_cpucfg_data[2] = 0;
+
+		/* This feature is set by firmware, but all known Loongson-2K
+		 * systems are configured this way.
+		 */
+		c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_CDMAP;
+#endif
 		break;
 	case PRID_IMP_LOONGSON_64C:  /* Loongson-3 Classic */
 		switch (c->processor_id & PRID_REV_MASK) {
@@ -2007,6 +2108,26 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)
 		c->writecombine = _CACHE_UNCACHED_ACCELERATED;
 		c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_CAM |
 			MIPS_ASE_LOONGSON_EXT | MIPS_ASE_LOONGSON_EXT2);
+#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
+		/* Add CPUCFG features non-discoverable otherwise. */
+		c->loongson3_cpucfg_data[0] |= (LOONGSON_CFG1_CNT64 |
+			LOONGSON_CFG1_LSLDR0 | LOONGSON_CFG1_LSPREF |
+			LOONGSON_CFG1_LSPREFX | LOONGSON_CFG1_LSSYNCI |
+			LOONGSON_CFG1_LLSYNC | LOONGSON_CFG1_TGTSYNC);
+		c->loongson3_cpucfg_data[1] |= (LOONGSON_CFG2_LBT1 |
+			LOONGSON_CFG2_LBT2 | LOONGSON_CFG2_LBTMMU |
+			LOONGSON_CFG2_LPMP | LOONGSON_CFG2_LPM_REV1 |
+			LOONGSON_CFG2_LVZ_REV1);
+		c->loongson3_cpucfg_data[2] |= (LOONGSON_CFG3_LCAM_REV1 |
+			LOONGSON_CFG3_LCAMNUM_REV1 |
+			LOONGSON_CFG3_LCAMKW_REV1 |
+			LOONGSON_CFG3_LCAMVW_REV1);
+
+		/* This feature is set by firmware, but all known Loongson-3
+		 * systems are configured this way.
+		 */
+		c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_CDMAP;
+#endif
 		break;
 	case PRID_IMP_LOONGSON_64G:
 		c->cputype = CPU_LOONGSON64;
@@ -2200,6 +2321,12 @@ void cpu_probe(void)
 	c->fpu_csr31	= FPU_CSR_RN;
 	c->fpu_msk31	= FPU_CSR_RSVD | FPU_CSR_ABS2008 | FPU_CSR_NAN2008;
 
+#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
+	c->loongson3_cpucfg_data[0] = 0;
+	c->loongson3_cpucfg_data[1] = 0;
+	c->loongson3_cpucfg_data[2] = 0;
+#endif
+
 	c->processor_id = read_c0_prid();
 	switch (c->processor_id & PRID_COMP_MASK) {
 	case PRID_COMP_LEGACY:
@@ -2333,6 +2460,8 @@ void cpu_probe(void)
 	if (cpu_has_vz)
 		cpu_probe_vz(c);
 
+	loongson3_cpucfg_finish_synthesis(c);
+
 	cpu_probe_vmbits(c);
 
 #ifdef CONFIG_64BIT
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 31968cbd6464..768790917724 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -71,6 +71,8 @@
 #include <asm/tlbex.h>
 #include <asm/uasm.h>
 
+#include <asm/mach-loongson64/cpucfg-emul.h>
+
 extern void check_wait(void);
 extern asmlinkage void rollback_handle_int(void);
 extern asmlinkage void handle_int(void);
@@ -693,6 +695,44 @@ static int simulate_sync(struct pt_regs *regs, unsigned int opcode)
 	return -1;			/* Must be something else ... */
 }
 
+/*
+ * Loongson-3 CSR instructions emulation
+ */
+
+#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
+
+#define LWC2             0xc8000000
+#define RS               BASE
+#define CSR_OPCODE2      0x00000118
+#define CSR_OPCODE2_MASK 0x000007ff
+#define CSR_FUNC_MASK    RT
+#define CSR_FUNC_CPUCFG  0x8
+
+static int simulate_loongson3_cpucfg(struct pt_regs *regs,
+				     unsigned int opcode)
+{
+	int op = opcode & OPCODE;
+	int op2 = opcode & CSR_OPCODE2_MASK;
+	int csr_func = (opcode & CSR_FUNC_MASK) >> 16;
+
+	if (op == LWC2 && op2 == CSR_OPCODE2 && csr_func == CSR_FUNC_CPUCFG) {
+		int rd = (opcode & RD) >> 11;
+		int rs = (opcode & RS) >> 21;
+		__u64 sel = regs->regs[rs];
+
+		perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
+
+		regs->regs[rd] = loongson3_cpucfg_read_synthesized(
+			&current_cpu_data, sel);
+
+		return 0;
+	}
+
+	/* Not ours.  */
+	return -1;
+}
+#endif /* CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION */
+
 asmlinkage void do_ov(struct pt_regs *regs)
 {
 	enum ctx_state prev_state;
@@ -1166,6 +1206,11 @@ asmlinkage void do_ri(struct pt_regs *regs)
 
 		if (status < 0)
 			status = simulate_fp(regs, opcode, old_epc, old31);
+
+#ifdef CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION
+		if (status < 0)
+			status = simulate_loongson3_cpucfg(regs, opcode);
+#endif
 	} else if (cpu_has_mmips) {
 		unsigned short mmop[2] = { 0 };
 
diff --git a/arch/mips/loongson64/Makefile b/arch/mips/loongson64/Makefile
index 6f3c2b47f66f..61f6add20530 100644
--- a/arch/mips/loongson64/Makefile
+++ b/arch/mips/loongson64/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_NUMA)	+= numa.o
 obj-$(CONFIG_RS780_HPET) += hpet.o
 obj-$(CONFIG_PCI) += pci.o
 obj-$(CONFIG_SUSPEND) += pm.o
+obj-$(CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION) += cpucfg-emul.o
diff --git a/arch/mips/loongson64/cpucfg-emul.c b/arch/mips/loongson64/cpucfg-emul.c
new file mode 100644
index 000000000000..a30f82b55c9e
--- /dev/null
+++ b/arch/mips/loongson64/cpucfg-emul.c
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/smp.h>
+#include <asm/cpu.h>
+#include <asm/cpu-info.h>
+
+#include <loongson_regs.h>
+#include <cpucfg-emul.h>
+
+static u32 get_loongson_fprev(struct cpuinfo_mips *c)
+{
+	return (c->fpu_id & LOONGSON_FPREV_MASK) << LOONGSON_CFG1_FPREV_OFFSET;
+}
+
+static void patch_cpucfg_sel1(struct cpuinfo_mips *c)
+{
+	u64 ases = c->ases;
+	u64 options = c->options;
+	u32 data = c->loongson3_cpucfg_data[0];
+
+	if (options & MIPS_CPU_FPU) {
+		data |= LOONGSON_CFG1_FP;
+		data |= get_loongson_fprev(c);
+	}
+	if (ases & MIPS_ASE_LOONGSON_MMI)
+		data |= LOONGSON_CFG1_MMI;
+	if (ases & MIPS_ASE_MSA)
+		data |= LOONGSON_CFG1_MSA1;
+
+	c->loongson3_cpucfg_data[0] = data;
+}
+
+static void patch_cpucfg_sel2(struct cpuinfo_mips *c)
+{
+	u64 ases = c->ases;
+	u64 options = c->options;
+	u32 data = c->loongson3_cpucfg_data[1];
+
+	if (ases & MIPS_ASE_LOONGSON_EXT)
+		data |= LOONGSON_CFG2_LEXT1;
+	if (ases & MIPS_ASE_LOONGSON_EXT2)
+		data |= LOONGSON_CFG2_LEXT2;
+	if (options & MIPS_CPU_LDPTE)
+		data |= LOONGSON_CFG2_LSPW;
+
+	if (ases & MIPS_ASE_VZ)
+		data |= LOONGSON_CFG2_LVZP;
+	else
+		data &= ~LOONGSON_CFG2_LVZREV;
+
+	c->loongson3_cpucfg_data[1] = data;
+}
+
+static void patch_cpucfg_sel3(struct cpuinfo_mips *c)
+{
+	u64 ases = c->ases;
+	u32 data = c->loongson3_cpucfg_data[2];
+
+	if (ases & MIPS_ASE_LOONGSON_CAM) {
+		data |= LOONGSON_CFG3_LCAMP;
+	} else {
+		data &= ~LOONGSON_CFG3_LCAMREV;
+		data &= ~LOONGSON_CFG3_LCAMNUM;
+		data &= ~LOONGSON_CFG3_LCAMKW;
+		data &= ~LOONGSON_CFG3_LCAMVW;
+	}
+
+	c->loongson3_cpucfg_data[2] = data;
+}
+
+void loongson3_cpucfg_finish_synthesis(struct cpuinfo_mips *c)
+{
+	/* CPUs with CPUCFG support don't need to synthesize anything. */
+	if (cpu_has_cfg())
+		return;
+
+	patch_cpucfg_sel1(c);
+	patch_cpucfg_sel2(c);
+	patch_cpucfg_sel3(c);
+}
-- 
2.21.0


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

* Re: [PATCH v2 RESEND 4/4] MIPS: emulate CPUCFG instruction on older Loongson64 cores
  2020-05-03 10:50   ` [PATCH v2 RESEND " WANG Xuerui
@ 2020-05-03 15:50     ` Jiaxun Yang
  2020-05-04  5:25       ` WANG Xuerui
  2020-05-17  8:37     ` Thomas Bogendoerfer
  1 sibling, 1 reply; 25+ messages in thread
From: Jiaxun Yang @ 2020-05-03 15:50 UTC (permalink / raw)
  To: WANG Xuerui, linux-mips; +Cc: Huacai Chen, Tiezhu Yang



于 2020年5月3日 GMT+08:00 下午6:50:13, WANG Xuerui <git@xen0n.name> 写到:
>CPUCFG is the instruction for querying processor characteristics on
>newer Loongson processors, much like CPUID of x86. Since the instruction
>is supposedly designed to provide a unified way to do feature detection
>(without having to, for example, parse /proc/cpuinfo which is too
>heavyweight), it is important to provide compatibility for older cores
>without native support. Fortunately, most of the fields can be
>synthesized without changes to semantics. Performance is not really big
>a concern, because feature detection logic is not expected to be
>invoked very often in typical userland applications.
>
>The instruction can't be emulated on LOONGSON_2EF cores, according to
>FlyGoat's experiments. Because the LWC2 opcode is assigned to other
>valid instructions on 2E and 2F, no RI exception is raised for us to
>intercept. So compatibility is only extended back furthest to
>Loongson-3A1000. Loongson-2K is covered too, as it is basically a remix
>of various blocks from the 3A/3B models from a kernel perspective.
>
>This is lightly based on Loongson's work on their Linux 3.10 fork, for
>being the authority on the right feature flags to fill in, where things
>aren't otherwise discoverable.
>
>Signed-off-by: WANG Xuerui <git@xen0n.name>
>Reviewed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
>Tested-by: Jiaxun Yang <jiaxun.yang@flygoat.com> # Loongson-2K, 3B1500
>Cc: Huacai Chen <chenhc@lemote.com>
>Cc: Jiaxun Yang <jiaxun.yang@flygoat.com>
>Cc: Tiezhu Yang <yangtiezhu@loongson.cn>
>---

Some random thoughts on that:

While cpucfg instruction would not be available on other MIPS
processors, and given that most distros are more willing to provide
general MIPS version instead of Loongson specified version, we'd better
provide user space programs a way to probe emulated/physical cpucfg support.

Looks like elf_hwcap would be a option? I've already added some flags about
Loongson's extension and now an extra HWCAP_LOONGSON_CPUCFG can cover everything.

>
>Resend because I forgot to include Jiaxun's review tags. Sorry for the
>noise.
>
> arch/mips/Kconfig                             |  11 ++
> arch/mips/include/asm/cpu-info.h              |   9 ++
> .../include/asm/mach-loongson64/cpucfg-emul.h |  67 +++++++++
> arch/mips/kernel/cpu-probe.c                  | 129 ++++++++++++++++++
> arch/mips/kernel/traps.c                      |  45 ++++++
> arch/mips/loongson64/Makefile                 |   1 +
> arch/mips/loongson64/cpucfg-emul.c            |  80 +++++++++++
> 7 files changed, 342 insertions(+)
> create mode 100644 arch/mips/include/asm/mach-loongson64/cpucfg-emul.h
> create mode 100644 arch/mips/loongson64/cpucfg-emul.c

-- 
Jiaxun Yang

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

* Re: [PATCH v2 RESEND 4/4] MIPS: emulate CPUCFG instruction on older Loongson64 cores
  2020-05-03 15:50     ` Jiaxun Yang
@ 2020-05-04  5:25       ` WANG Xuerui
  2020-05-04  6:58         ` Jiaxun Yang
  0 siblings, 1 reply; 25+ messages in thread
From: WANG Xuerui @ 2020-05-04  5:25 UTC (permalink / raw)
  To: jiaxun.yang, linux-mips; +Cc: Huacai Chen, Tiezhu Yang

On 5/3/20 11:50 PM, Jiaxun Yang wrote:

> Some random thoughts on that:
>
> While cpucfg instruction would not be available on other MIPS
> processors, and given that most distros are more willing to provide
> general MIPS version instead of Loongson specified version, we'd better
> provide user space programs a way to probe emulated/physical cpucfg support.
>
> Looks like elf_hwcap would be a option? I've already added some flags about
> Loongson's extension and now an extra HWCAP_LOONGSON_CPUCFG can cover everything.

All emulated outputs from the older models have the LCSRP bit clear in 
this patch. As CPUCFG is part of the Loongson CSR ASE, this is the 
reliable way to distinguish between emulated and physical CPUCFG support.

However, because detecting presence of CPUCFG itself still requires one 
to handle SIGILL, exposing an hwcap might be an option. So we'll have 
the following mapping:

- no HWCAP_LOONGSON_CPUCFG -- other MIPS or Loongson-2EF or Loongson-32
- CPUCFG.0x2.LCSRP == 0 -- older Loongson-64 models
- otherwise, Loongson-3A R4 or later

Seems some of the previously defined hwcaps will become unnecessary if 
we make this change. But they're already part of kernel ABI so we have 
to keep them, fortunately we still have plenty of bits available. At 
least future additions of Loongson features wouldn't go through hwcap.

I think the hwcap addition can be added in another follow-up series if 
the idea gets consensus; let's keep this series focused.


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

* Re: [PATCH v2 RESEND 4/4] MIPS: emulate CPUCFG instruction on older Loongson64 cores
  2020-05-04  5:25       ` WANG Xuerui
@ 2020-05-04  6:58         ` Jiaxun Yang
  0 siblings, 0 replies; 25+ messages in thread
From: Jiaxun Yang @ 2020-05-04  6:58 UTC (permalink / raw)
  To: WANG Xuerui, linux-mips; +Cc: Huacai Chen, Tiezhu Yang



于 2020年5月4日 GMT+08:00 下午1:25:00, WANG Xuerui <kernel@xen0n.name> 写到:
>On 5/3/20 11:50 PM, Jiaxun Yang wrote:
>
>> Some random thoughts on that:
>>
>> While cpucfg instruction would not be available on other MIPS
>> processors, and given that most distros are more willing to provide
>> general MIPS version instead of Loongson specified version, we'd better
>> provide user space programs a way to probe emulated/physical cpucfg support.
>>
>> Looks like elf_hwcap would be a option? I've already added some flags about
>> Loongson's extension and now an extra HWCAP_LOONGSON_CPUCFG can cover everything.
>
>All emulated outputs from the older models have the LCSRP bit clear in 
>this patch. As CPUCFG is part of the Loongson CSR ASE, this is the 
>reliable way to distinguish between emulated and physical CPUCFG support.
>
>However, because detecting presence of CPUCFG itself still requires one 
>to handle SIGILL, exposing an hwcap might be an option. So we'll have 
>the following mapping:
>
>- no HWCAP_LOONGSON_CPUCFG -- other MIPS or Loongson-2EF or Loongson-32
>- CPUCFG.0x2.LCSRP == 0 -- older Loongson-64 models
>- otherwise, Loongson-3A R4 or later
>
>Seems some of the previously defined hwcaps will become unnecessary if 
>we make this change. But they're already part of kernel ABI so we have 
>to keep them, fortunately we still have plenty of bits available. At 
>least future additions of Loongson features wouldn't go through hwcap.
>
>I think the hwcap addition can be added in another follow-up series if 
>the idea gets consensus; let's keep this series focused.

Yeah that's exactly my point.

I'm looking forward for getting these stuff merged.

Thanks.

>

-- 
Jiaxun Yang

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

* Re: [PATCH v2 0/4] CPUCFG emulation on older Loongson64 cores
  2020-05-03 10:33 ` [PATCH v2 0/4] CPUCFG emulation " WANG Xuerui
@ 2020-05-16 11:29   ` WANG Xuerui
  2020-05-17  8:38     ` Thomas Bogendoerfer
  0 siblings, 1 reply; 25+ messages in thread
From: WANG Xuerui @ 2020-05-16 11:29 UTC (permalink / raw)
  To: linux-mips

On 5/3/20 6:33 PM, WANG Xuerui wrote:

> This patch series brings the CPUCFG instruction to older Loongson64
> cores, enabling a unified way to query processor characteristics on
> Loongson64 systems. A detailed explanation may be found in the last
> commit.
>
> One unresolved point is how to best introduce machtype-specific bits
> into the generic MIPS code, namely the cpu probing and trap handler
> parts. I have been struggling over whether to lift this logic into
> arch/mips/kernel, but the instruction's encoding (reusing LWC2 opcode)
> might be too invasive to be useful to other MIPS platforms. What do
> people think is the best way forward?
>
> v2:
>
> - Fixed one more typo in loongson_regs.h
> - Merged simulate_loongson3_csr and simulate_loongson3_csr_cpucfg into
>    one (simulate_loongson3_cpucfg), per Huacai's suggestion
>
> WANG Xuerui (4):
>    MIPS: Loongson64: fix typos in loongson_regs.h
>    MIPS: Loongson64: define offsets and known revisions for some CPUCFG
>      features
>    MIPS: define more Loongson CP0.Config6 and CP0.Diag feature bits
>    MIPS: emulate CPUCFG instruction on older Loongson64 cores
>
>   arch/mips/Kconfig                             |  11 ++
>   arch/mips/include/asm/cpu-info.h              |   9 ++
>   .../include/asm/mach-loongson64/cpucfg-emul.h |  67 +++++++++
>   .../asm/mach-loongson64/loongson_regs.h       |  29 +++-
>   arch/mips/include/asm/mipsregs.h              |   6 +
>   arch/mips/kernel/cpu-probe.c                  | 129 ++++++++++++++++++
>   arch/mips/kernel/traps.c                      |  45 ++++++
>   arch/mips/loongson64/Makefile                 |   1 +
>   arch/mips/loongson64/cpucfg-emul.c            |  80 +++++++++++
>   9 files changed, 372 insertions(+), 5 deletions(-)
>   create mode 100644 arch/mips/include/asm/mach-loongson64/cpucfg-emul.h
>   create mode 100644 arch/mips/loongson64/cpucfg-emul.c
>
Just a friendly ping.

What is the status of this series? I know that I borked the threading of 
replies, I can resend if it's the only thing holding the series.

And I think the patch may well need to be reorganized, but no replies 
yet. I'm not a professional kernel developer, and any review is appreciated!


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

* Re: [PATCH v2 RESEND 4/4] MIPS: emulate CPUCFG instruction on older Loongson64 cores
  2020-05-03 10:50   ` [PATCH v2 RESEND " WANG Xuerui
  2020-05-03 15:50     ` Jiaxun Yang
@ 2020-05-17  8:37     ` Thomas Bogendoerfer
  2020-05-17 11:39       ` WANG Xuerui
  1 sibling, 1 reply; 25+ messages in thread
From: Thomas Bogendoerfer @ 2020-05-17  8:37 UTC (permalink / raw)
  To: WANG Xuerui; +Cc: linux-mips, Jiaxun Yang, Huacai Chen, Tiezhu Yang

On Sun, May 03, 2020 at 06:50:13PM +0800, WANG Xuerui wrote:
> +#endif
> +
> +#endif /* _ASM_MACH_LOONGSON64_CPUCFG_EMUL_H_ */
> diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
> index ca2e6f1af4fe..907e31ff562f 100644
> --- a/arch/mips/kernel/cpu-probe.c
> +++ b/arch/mips/kernel/cpu-probe.c
> @@ -28,6 +28,8 @@
>  #include <asm/spram.h>
>  #include <linux/uaccess.h>
>  
> +#include <asm/mach-loongson64/cpucfg-emul.h>
> +

this doesn't fly:

In file included from /local/tbogendoerfer/korg/linux/arch/mips/kernel/cpu-probe.c:31:0:
/local/tbogendoerfer/korg/linux/arch/mips/include/asm/mach-loongson64/cpucfg-emul.h:7:27: fatal error: loongson_regs.h: No such file or directory
 #include <loongson_regs.h>
                           ^
compilation terminated.

Is there a chance to put this code in a loongsoon specific file ?

Thomas.

-- 
Crap can work. Given enough thrust pigs will fly, but it's not necessarily a
good idea.                                                [ RFC1925, 2.3 ]

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

* Re: [PATCH v2 0/4] CPUCFG emulation on older Loongson64 cores
  2020-05-16 11:29   ` WANG Xuerui
@ 2020-05-17  8:38     ` Thomas Bogendoerfer
  0 siblings, 0 replies; 25+ messages in thread
From: Thomas Bogendoerfer @ 2020-05-17  8:38 UTC (permalink / raw)
  To: WANG Xuerui; +Cc: linux-mips

On Sat, May 16, 2020 at 07:29:39PM +0800, WANG Xuerui wrote:
> On 5/3/20 6:33 PM, WANG Xuerui wrote:
> What is the status of this series? I know that I borked the threading of
> replies, I can resend if it's the only thing holding the series.
> 
> And I think the patch may well need to be reorganized, but no replies yet.
> I'm not a professional kernel developer, and any review is appreciated!

I've applied patch 1-3 to mips-next. Patch 4 needs more work...

Thomas.

-- 
Crap can work. Given enough thrust pigs will fly, but it's not necessarily a
good idea.                                                [ RFC1925, 2.3 ]

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

* Re: [PATCH v2 RESEND 4/4] MIPS: emulate CPUCFG instruction on older Loongson64 cores
  2020-05-17  8:37     ` Thomas Bogendoerfer
@ 2020-05-17 11:39       ` WANG Xuerui
  2020-05-17 15:17         ` Thomas Bogendoerfer
  0 siblings, 1 reply; 25+ messages in thread
From: WANG Xuerui @ 2020-05-17 11:39 UTC (permalink / raw)
  To: Thomas Bogendoerfer; +Cc: linux-mips, Jiaxun Yang, Huacai Chen, Tiezhu Yang

On 5/17/20 4:37 PM, Thomas Bogendoerfer wrote:

> On Sun, May 03, 2020 at 06:50:13PM +0800, WANG Xuerui wrote:
>> +#endif
>> +
>> +#endif /* _ASM_MACH_LOONGSON64_CPUCFG_EMUL_H_ */
>> diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
>> index ca2e6f1af4fe..907e31ff562f 100644
>> --- a/arch/mips/kernel/cpu-probe.c
>> +++ b/arch/mips/kernel/cpu-probe.c
>> @@ -28,6 +28,8 @@
>>   #include <asm/spram.h>
>>   #include <linux/uaccess.h>
>>   
>> +#include <asm/mach-loongson64/cpucfg-emul.h>
>> +
> this doesn't fly:
>
> In file included from /local/tbogendoerfer/korg/linux/arch/mips/kernel/cpu-probe.c:31:0:
> /local/tbogendoerfer/korg/linux/arch/mips/include/asm/mach-loongson64/cpucfg-emul.h:7:27: fatal error: loongson_regs.h: No such file or directory
>   #include <loongson_regs.h>
>                             ^
> compilation terminated.
>
> Is there a chance to put this code in a loongsoon specific file ?

Oops... I'll rebase tonight to fix this. Might be caused by the build 
system changes merged in the meantime.

As for the logic separation, I'm 100% in agreement with this, but I 
don't know of any way to invoke mach-specific bits from inside 
cpu-probe. Plus all the PRId matching logic have to be duplicated if the 
code is to be moved to the loongson64/ sub-directory. I didn't find any 
other platform that does this, so I just extended the probing code.

Other way is to treat the whole CPUCFG thing just like the r2-to-r6-emul 
thing, which means moving all the logic to kernel/ sub-directory. But 
I'd rather not do this, for reasons explained in the cover letter.

>
> Thomas.
>

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

* Re: [PATCH v2 RESEND 4/4] MIPS: emulate CPUCFG instruction on older Loongson64 cores
  2020-05-17 11:39       ` WANG Xuerui
@ 2020-05-17 15:17         ` Thomas Bogendoerfer
  2020-05-18  2:44           ` WANG Xuerui
  0 siblings, 1 reply; 25+ messages in thread
From: Thomas Bogendoerfer @ 2020-05-17 15:17 UTC (permalink / raw)
  To: WANG Xuerui; +Cc: linux-mips, Jiaxun Yang, Huacai Chen, Tiezhu Yang

On Sun, May 17, 2020 at 07:39:44PM +0800, WANG Xuerui wrote:
> On 5/17/20 4:37 PM, Thomas Bogendoerfer wrote:
> 
> >On Sun, May 03, 2020 at 06:50:13PM +0800, WANG Xuerui wrote:
> >>+#endif
> >>+
> >>+#endif /* _ASM_MACH_LOONGSON64_CPUCFG_EMUL_H_ */
> >>diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
> >>index ca2e6f1af4fe..907e31ff562f 100644
> >>--- a/arch/mips/kernel/cpu-probe.c
> >>+++ b/arch/mips/kernel/cpu-probe.c
> >>@@ -28,6 +28,8 @@
> >>  #include <asm/spram.h>
> >>  #include <linux/uaccess.h>
> >>+#include <asm/mach-loongson64/cpucfg-emul.h>
> >>+
> >this doesn't fly:
> >
> >In file included from /local/tbogendoerfer/korg/linux/arch/mips/kernel/cpu-probe.c:31:0:
> >/local/tbogendoerfer/korg/linux/arch/mips/include/asm/mach-loongson64/cpucfg-emul.h:7:27: fatal error: loongson_regs.h: No such file or directory
> >  #include <loongson_regs.h>
> >                            ^
> >compilation terminated.
> >
> >Is there a chance to put this code in a loongsoon specific file ?
> 
> Oops... I'll rebase tonight to fix this. Might be caused by the build system
> changes merged in the meantime.

just to make it clear, the failing config is a RALINK config, but looking
at the failure probaly everything but loongson64 fails.

> As for the logic separation, I'm 100% in agreement with this, but I don't
> know of any way to invoke mach-specific bits from inside cpu-probe.

implement your code in a new/fitting file, provide a header file,
which has prototypes for this functions if CONFIG_xxx option is enabled
or empty stubs, if not. Then call these functions from cpu-probe.c.

Thomas.

-- 
Crap can work. Given enough thrust pigs will fly, but it's not necessarily a
good idea.                                                [ RFC1925, 2.3 ]

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

* Re: [PATCH v2 RESEND 4/4] MIPS: emulate CPUCFG instruction on older Loongson64 cores
  2020-05-17 15:17         ` Thomas Bogendoerfer
@ 2020-05-18  2:44           ` WANG Xuerui
  2020-05-19 14:33             ` WANG Xuerui
  0 siblings, 1 reply; 25+ messages in thread
From: WANG Xuerui @ 2020-05-18  2:44 UTC (permalink / raw)
  To: Thomas Bogendoerfer; +Cc: linux-mips, Jiaxun Yang, Huacai Chen, Tiezhu Yang

On 2020/5/17 23:17, Thomas Bogendoerfer wrote:

> On Sun, May 17, 2020 at 07:39:44PM +0800, WANG Xuerui wrote:
>> On 5/17/20 4:37 PM, Thomas Bogendoerfer wrote:
>>
>>> On Sun, May 03, 2020 at 06:50:13PM +0800, WANG Xuerui wrote:
>>>> +#endif
>>>> +
>>>> +#endif /* _ASM_MACH_LOONGSON64_CPUCFG_EMUL_H_ */
>>>> diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
>>>> index ca2e6f1af4fe..907e31ff562f 100644
>>>> --- a/arch/mips/kernel/cpu-probe.c
>>>> +++ b/arch/mips/kernel/cpu-probe.c
>>>> @@ -28,6 +28,8 @@
>>>>   #include <asm/spram.h>
>>>>   #include <linux/uaccess.h>
>>>> +#include <asm/mach-loongson64/cpucfg-emul.h>
>>>> +
>>> this doesn't fly:
>>>
>>> In file included from /local/tbogendoerfer/korg/linux/arch/mips/kernel/cpu-probe.c:31:0:
>>> /local/tbogendoerfer/korg/linux/arch/mips/include/asm/mach-loongson64/cpucfg-emul.h:7:27: fatal error: loongson_regs.h: No such file or directory
>>>   #include <loongson_regs.h>
>>>                             ^
>>> compilation terminated.
>>>
>>> Is there a chance to put this code in a loongsoon specific file ?
>> Oops... I'll rebase tonight to fix this. Might be caused by the build system
>> changes merged in the meantime.
> just to make it clear, the failing config is a RALINK config, but looking
> at the failure probaly everything but loongson64 fails.
Thanks for the clarification; I've found out the mistake last night. The 
include of loongson_regs.h needs to go inside the config guard to 
prevent inclusion on other platforms where the include path is not set 
up for it.
>> As for the logic separation, I'm 100% in agreement with this, but I don't
>> know of any way to invoke mach-specific bits from inside cpu-probe.
> implement your code in a new/fitting file, provide a header file,
> which has prototypes for this functions if CONFIG_xxx option is enabled
> or empty stubs, if not. Then call these functions from cpu-probe.c.

Sure. I'll move these into cpucfg-emul.c to minimize intrusion to 
cpu-probe.c.

I'll send v3 later today (in my timezone) after I go home.

And thanks for your instruction!

> Thomas.
>

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

* Re: [PATCH v2 RESEND 4/4] MIPS: emulate CPUCFG instruction on older Loongson64 cores
  2020-05-18  2:44           ` WANG Xuerui
@ 2020-05-19 14:33             ` WANG Xuerui
  0 siblings, 0 replies; 25+ messages in thread
From: WANG Xuerui @ 2020-05-19 14:33 UTC (permalink / raw)
  To: Thomas Bogendoerfer; +Cc: linux-mips, Jiaxun Yang, Huacai Chen, Tiezhu Yang

On 5/18/20 10:44 AM, WANG Xuerui wrote:

>
> Sure. I'll move these into cpucfg-emul.c to minimize intrusion to 
> cpu-probe.c.
>
> I'll send v3 later today (in my timezone) after I go home.
>
Sorry, but my development machine is experiencing some connectivity 
problems, plus this week is rather busier than normal.

v3 probably won't be ready until maybe Thursday. Will try my best to 
submit before the 5.8 merge window though...


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

end of thread, other threads:[~2020-05-19 14:33 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-02 13:38 [PATCH 0/4] CPUCFG emulation on older Loongson64 cores WANG Xuerui
2020-05-02 13:38 ` [PATCH 1/4] MIPS: Loongson64: fix typos in loongson_regs.h WANG Xuerui
2020-05-02 13:38 ` [PATCH 2/4] MIPS: Loongson64: define offsets and known revisions for some CPUCFG features WANG Xuerui
2020-05-02 13:38 ` [PATCH 3/4] MIPS: define more Loongson CP0.Config6 and CP0.Diag feature bits WANG Xuerui
2020-05-02 13:38 ` [PATCH 4/4] MIPS: emulate CPUCFG instruction on older Loongson64 cores WANG Xuerui
2020-05-02 13:59   ` Jiaxun Yang
2020-05-03  6:31   ` Huacai Chen
2020-05-03  7:58     ` Wang Xuerui
2020-05-03  8:25       ` Jiaxun Yang
2020-05-03 10:33 ` [PATCH v2 0/4] CPUCFG emulation " WANG Xuerui
2020-05-16 11:29   ` WANG Xuerui
2020-05-17  8:38     ` Thomas Bogendoerfer
2020-05-03 10:33 ` [PATCH v2 1/4] MIPS: Loongson64: fix typos in loongson_regs.h WANG Xuerui
2020-05-03 10:33 ` [PATCH v2 2/4] MIPS: Loongson64: define offsets and known revisions for some CPUCFG features WANG Xuerui
2020-05-03 10:33 ` [PATCH v2 3/4] MIPS: define more Loongson CP0.Config6 and CP0.Diag feature bits WANG Xuerui
2020-05-03 10:33 ` [PATCH v2 4/4] MIPS: emulate CPUCFG instruction on older Loongson64 cores WANG Xuerui
2020-05-03 10:50   ` [PATCH v2 RESEND " WANG Xuerui
2020-05-03 15:50     ` Jiaxun Yang
2020-05-04  5:25       ` WANG Xuerui
2020-05-04  6:58         ` Jiaxun Yang
2020-05-17  8:37     ` Thomas Bogendoerfer
2020-05-17 11:39       ` WANG Xuerui
2020-05-17 15:17         ` Thomas Bogendoerfer
2020-05-18  2:44           ` WANG Xuerui
2020-05-19 14:33             ` WANG Xuerui

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.