diff mbox series

[v2] riscv: Fix the PAUSE Opcode for MIPS P8700.

Message ID 20241227135832.188256-1-arikalo@gmail.com (mailing list archive)
State New
Headers show
Series [v2] riscv: Fix the PAUSE Opcode for MIPS P8700. | expand

Checks

Context Check Description
conchuod/vmtest-for-next-PR success PR summary
conchuod/patch-1-test-1 success .github/scripts/patches/tests/build_rv32_defconfig.sh took 102.69s
conchuod/patch-1-test-2 success .github/scripts/patches/tests/build_rv64_clang_allmodconfig.sh took 2266.73s
conchuod/patch-1-test-3 success .github/scripts/patches/tests/build_rv64_gcc_allmodconfig.sh took 2620.22s
conchuod/patch-1-test-4 success .github/scripts/patches/tests/build_rv64_nommu_k210_defconfig.sh took 15.76s
conchuod/patch-1-test-5 success .github/scripts/patches/tests/build_rv64_nommu_virt_defconfig.sh took 17.53s
conchuod/patch-1-test-6 warning .github/scripts/patches/tests/checkpatch.sh took 1.57s
conchuod/patch-1-test-7 success .github/scripts/patches/tests/dtb_warn_rv64.sh took 36.44s
conchuod/patch-1-test-8 success .github/scripts/patches/tests/header_inline.sh took 0.00s
conchuod/patch-1-test-9 success .github/scripts/patches/tests/kdoc.sh took 0.49s
conchuod/patch-1-test-10 success .github/scripts/patches/tests/module_param.sh took 0.01s
conchuod/patch-1-test-11 success .github/scripts/patches/tests/verify_fixes.sh took 0.00s
conchuod/patch-1-test-12 success .github/scripts/patches/tests/verify_signedoff.sh took 0.02s

Commit Message

Aleksandar Rikalo Dec. 27, 2024, 1:58 p.m. UTC
From: Djordje Todorovic <djordje.todorovic@htecgroup.com>

The riscv MIPS P8700 uses a different opcode for PAUSE.
It is a ‘hint’ encoding of the SLLI instruction, with rd=0, rs1=0 and
imm=5. It will behave as a NOP instruction if no additional behavior
beyond that of SLLI is implemented.

Add ERRATA_MIPS and ERRATA_MIPS_P8700_PAUSE_OPCODE configs.
Handle errata for MIPS CPUs.

Signed-off-by: Djordje Todorovic <djordje.todorovic@htecgroup.com>
Signed-off-by: Aleksandar Rikalo <arikalo@gmail.com>
Signed-off-by: Raj Vishwanathan4 <rvishwanathan@mips.com>
---
 arch/riscv/Kconfig.errata              | 22 +++++++++++++++++
 arch/riscv/errata/Makefile             |  1 +
 arch/riscv/errata/mips/Makefile        |  5 ++++
 arch/riscv/errata/mips/errata.c        | 33 ++++++++++++++++++++++++++
 arch/riscv/include/asm/alternative.h   |  3 +++
 arch/riscv/include/asm/vendorid_list.h |  1 +
 arch/riscv/kernel/alternative.c        |  5 ++++
 7 files changed, 70 insertions(+)
 create mode 100644 arch/riscv/errata/mips/Makefile
 create mode 100644 arch/riscv/errata/mips/errata.c

Comments

Charlie Jenkins Dec. 28, 2024, 6:01 a.m. UTC | #1
On Fri, Dec 27, 2024 at 02:58:32PM +0100, Aleksandar Rikalo wrote:
> From: Djordje Todorovic <djordje.todorovic@htecgroup.com>
> 
> The riscv MIPS P8700 uses a different opcode for PAUSE.
> It is a ‘hint’ encoding of the SLLI instruction, with rd=0, rs1=0 and
> imm=5. It will behave as a NOP instruction if no additional behavior
> beyond that of SLLI is implemented.
> 
> Add ERRATA_MIPS and ERRATA_MIPS_P8700_PAUSE_OPCODE configs.
> Handle errata for MIPS CPUs.
> 
> Signed-off-by: Djordje Todorovic <djordje.todorovic@htecgroup.com>
> Signed-off-by: Aleksandar Rikalo <arikalo@gmail.com>
> Signed-off-by: Raj Vishwanathan4 <rvishwanathan@mips.com>
> ---
>  arch/riscv/Kconfig.errata              | 22 +++++++++++++++++
>  arch/riscv/errata/Makefile             |  1 +
>  arch/riscv/errata/mips/Makefile        |  5 ++++
>  arch/riscv/errata/mips/errata.c        | 33 ++++++++++++++++++++++++++
>  arch/riscv/include/asm/alternative.h   |  3 +++
>  arch/riscv/include/asm/vendorid_list.h |  1 +
>  arch/riscv/kernel/alternative.c        |  5 ++++
>  7 files changed, 70 insertions(+)
>  create mode 100644 arch/riscv/errata/mips/Makefile
>  create mode 100644 arch/riscv/errata/mips/errata.c
> 
> diff --git a/arch/riscv/Kconfig.errata b/arch/riscv/Kconfig.errata
> index 2acc7d876e1f..99c75fece8b9 100644
> --- a/arch/riscv/Kconfig.errata
> +++ b/arch/riscv/Kconfig.errata
> @@ -21,6 +21,28 @@ config ERRATA_ANDES_CMO
>  
>  	  If you don't know what to do here, say "Y".
>  
> +config ERRATA_MIPS
> +	bool "MIPS errata"
> +	depends on RISCV_ALTERNATIVE
> +	help
> +	  All MIPS errata Kconfig depend on this Kconfig. Disabling
> +	  this Kconfig will disable all MIPS errata. Please say "Y"
> +	  here if your platform uses MIPS CPU cores.
> +
> +	  Otherwise, please say "N" here to avoid unnecessary overhead.
> +
> +config ERRATA_MIPS_P8700_PAUSE_OPCODE
> +	bool "Fix the PAUSE Opcode for MIPS P8700"
> +	depends on ERRATA_MIPS && 64BIT
> +	help
> +	   The RISCV MIPS P8700 uses a different opcode for PAUSE.
> +	   It is a 'hint' encoding of the SLLI instruction,
> +	   with rd=0, rs1=0 and imm=5. It will behave as a NOP
> +	   instruction if no additional behavior beyond that of
> +	   SLLI is implemented.
> +
> +	   If you are not using the P8700 processor, say N.
> +
>  config ERRATA_SIFIVE
>  	bool "SiFive errata"
>  	depends on RISCV_ALTERNATIVE
> diff --git a/arch/riscv/errata/Makefile b/arch/riscv/errata/Makefile
> index f0da9d7b39c3..156cafb338c1 100644
> --- a/arch/riscv/errata/Makefile
> +++ b/arch/riscv/errata/Makefile
> @@ -9,5 +9,6 @@ endif
>  endif
>  
>  obj-$(CONFIG_ERRATA_ANDES) += andes/
> +obj-$(CONFIG_ERRATA_MIPS) += mips/
>  obj-$(CONFIG_ERRATA_SIFIVE) += sifive/
>  obj-$(CONFIG_ERRATA_THEAD) += thead/
> diff --git a/arch/riscv/errata/mips/Makefile b/arch/riscv/errata/mips/Makefile
> new file mode 100644
> index 000000000000..6278c389b801
> --- /dev/null
> +++ b/arch/riscv/errata/mips/Makefile
> @@ -0,0 +1,5 @@
> +ifdef CONFIG_RISCV_ALTERNATIVE_EARLY
> +CFLAGS_errata.o := -mcmodel=medany
> +endif
> +
> +obj-y += errata.o
> diff --git a/arch/riscv/errata/mips/errata.c b/arch/riscv/errata/mips/errata.c
> new file mode 100644
> index 000000000000..7affc590ded5
> --- /dev/null
> +++ b/arch/riscv/errata/mips/errata.c
> @@ -0,0 +1,33 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2024 MIPS.
> + */
> +
> +#include <linux/memory.h>
> +#include <linux/module.h>
> +
> +#include <asm/alternative.h>
> +#include <asm/cacheflush.h>
> +#include <asm/errata_list.h>
> +#include <asm/text-patching.h>
> +#include <asm/processor.h>
> +#include <asm/sbi.h>
> +#include <asm/vendorid_list.h>
> +#include <asm/vendor_extensions.h>
> +
> +void __init_or_module mips_errata_patch_func(struct alt_entry *begin,
> +					     struct alt_entry *end,
> +					     unsigned long archid,
> +					     unsigned long impid,
> +					     unsigned int stage)
> +{
> +	if (!IS_ENABLED(CONFIG_ERRATA_MIPS))
> +		return;
> +
> +	if (!IS_ENABLED(CONFIG_ERRATA_MIPS_P8700_PAUSE_OPCODE))
> +		return;
> +
> +	asm volatile(ALTERNATIVE(".4byte 0x1000000f", ".4byte 0x00501013",
> +				 MIPS_VENDOR_ID, 0, /* patch_id */
> +				 CONFIG_ERRATA_MIPS_P8700_PAUSE_OPCODE));

I dont think his isn't quite what you are looking for. This will end up
emitting a pause instruction when this patch function is called, instead
of replacing all pause instructions with this custom encoding. What you
want to do here is similar to what is done in
arch/riscv/include/asm/errata_list.h.

A good example of this is:

#define ALT_SFENCE_VMA_ASID(asid)					\
asm(ALTERNATIVE("sfence.vma x0, %0", "sfence.vma", SIFIVE_VENDOR_ID,	\
		ERRATA_SIFIVE_CIP_1200, CONFIG_ERRATA_SIFIVE_CIP_1200)	\
		: : "r" (asid) : "memory")

This macro is then used everywhere "sfence.vma" would normally be used.
Then in sifive_errata_patch_func() in arch/riscv/errata/sifive/errata.c iterates through all alternatives, looking for any alternatives that match SIFIVE_VENDOR_ID and then perform the replacement.

There seem to be three places where the pause instruction is used:

- cpu_relax() in arch/riscv/include/asm/vdso/processor.h
- __cmpwait() in arch/riscv/include/asm/cmpxchg.h

This one is a different because it is in tools. 
- cpu_relax() in tools/arch/riscv/include/asm/vdso/processor.h

tools is userspace code, so alternatives are not supported. Patching the
pause instruction here will require a call to hwprobe. I am hesitant
about this though because that would cause all microarchitectures to
incur the cost of calling hwprobe, not just ones produced by MIPS. I
would prefer for that to not be the default, kconfig doesn't extend to
tools so some environment variable could be set for it. I am not sure what
kind of precedent we want to set for this.

Also, Palmer is expected to merge in my vendor-specific hwprobe
framework this merge window that is included in [1].

Link
https://lore.kernel.org/linux-riscv/20241113-xtheadvector-v11-0-236c22791ef9@rivosinc.com/
[1]

> +}
> diff --git a/arch/riscv/include/asm/alternative.h b/arch/riscv/include/asm/alternative.h
> index 3c2b59b25017..bc3ada8190a9 100644
> --- a/arch/riscv/include/asm/alternative.h
> +++ b/arch/riscv/include/asm/alternative.h
> @@ -48,6 +48,9 @@ struct alt_entry {
>  void andes_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
>  			     unsigned long archid, unsigned long impid,
>  			     unsigned int stage);
> +void mips_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
> +			      unsigned long archid, unsigned long impid,
> +			      unsigned int stage);
>  void sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
>  			      unsigned long archid, unsigned long impid,
>  			      unsigned int stage);
> diff --git a/arch/riscv/include/asm/vendorid_list.h b/arch/riscv/include/asm/vendorid_list.h
> index 2f2bb0c84f9a..55d979a7a7c2 100644
> --- a/arch/riscv/include/asm/vendorid_list.h
> +++ b/arch/riscv/include/asm/vendorid_list.h
> @@ -8,5 +8,6 @@
>  #define ANDES_VENDOR_ID		0x31e
>  #define SIFIVE_VENDOR_ID	0x489
>  #define THEAD_VENDOR_ID		0x5b7
> +#define MIPS_VENDOR_ID		0x127
>  
>  #endif
> diff --git a/arch/riscv/kernel/alternative.c b/arch/riscv/kernel/alternative.c
> index 7eb3cb1215c6..7642704c7f18 100644
> --- a/arch/riscv/kernel/alternative.c
> +++ b/arch/riscv/kernel/alternative.c
> @@ -47,6 +47,11 @@ static void riscv_fill_cpu_mfr_info(struct cpu_manufacturer_info_t *cpu_mfr_info
>  		cpu_mfr_info->patch_func = andes_errata_patch_func;
>  		break;
>  #endif
> +#ifdef CONFIG_ERRATA_MIPS
> +	case MIPS_VENDOR_ID:
> +		cpu_mfr_info->patch_func = mips_errata_patch_func;
> +		break;
> +#endif
>  #ifdef CONFIG_ERRATA_SIFIVE
>  	case SIFIVE_VENDOR_ID:
>  		cpu_mfr_info->patch_func = sifive_errata_patch_func;
> -- 
> 2.25.1
> 
> 
> _______________________________________________
> linux-riscv mailing list
> linux-riscv@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv
diff mbox series

Patch

diff --git a/arch/riscv/Kconfig.errata b/arch/riscv/Kconfig.errata
index 2acc7d876e1f..99c75fece8b9 100644
--- a/arch/riscv/Kconfig.errata
+++ b/arch/riscv/Kconfig.errata
@@ -21,6 +21,28 @@  config ERRATA_ANDES_CMO
 
 	  If you don't know what to do here, say "Y".
 
+config ERRATA_MIPS
+	bool "MIPS errata"
+	depends on RISCV_ALTERNATIVE
+	help
+	  All MIPS errata Kconfig depend on this Kconfig. Disabling
+	  this Kconfig will disable all MIPS errata. Please say "Y"
+	  here if your platform uses MIPS CPU cores.
+
+	  Otherwise, please say "N" here to avoid unnecessary overhead.
+
+config ERRATA_MIPS_P8700_PAUSE_OPCODE
+	bool "Fix the PAUSE Opcode for MIPS P8700"
+	depends on ERRATA_MIPS && 64BIT
+	help
+	   The RISCV MIPS P8700 uses a different opcode for PAUSE.
+	   It is a 'hint' encoding of the SLLI instruction,
+	   with rd=0, rs1=0 and imm=5. It will behave as a NOP
+	   instruction if no additional behavior beyond that of
+	   SLLI is implemented.
+
+	   If you are not using the P8700 processor, say N.
+
 config ERRATA_SIFIVE
 	bool "SiFive errata"
 	depends on RISCV_ALTERNATIVE
diff --git a/arch/riscv/errata/Makefile b/arch/riscv/errata/Makefile
index f0da9d7b39c3..156cafb338c1 100644
--- a/arch/riscv/errata/Makefile
+++ b/arch/riscv/errata/Makefile
@@ -9,5 +9,6 @@  endif
 endif
 
 obj-$(CONFIG_ERRATA_ANDES) += andes/
+obj-$(CONFIG_ERRATA_MIPS) += mips/
 obj-$(CONFIG_ERRATA_SIFIVE) += sifive/
 obj-$(CONFIG_ERRATA_THEAD) += thead/
diff --git a/arch/riscv/errata/mips/Makefile b/arch/riscv/errata/mips/Makefile
new file mode 100644
index 000000000000..6278c389b801
--- /dev/null
+++ b/arch/riscv/errata/mips/Makefile
@@ -0,0 +1,5 @@ 
+ifdef CONFIG_RISCV_ALTERNATIVE_EARLY
+CFLAGS_errata.o := -mcmodel=medany
+endif
+
+obj-y += errata.o
diff --git a/arch/riscv/errata/mips/errata.c b/arch/riscv/errata/mips/errata.c
new file mode 100644
index 000000000000..7affc590ded5
--- /dev/null
+++ b/arch/riscv/errata/mips/errata.c
@@ -0,0 +1,33 @@ 
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2024 MIPS.
+ */
+
+#include <linux/memory.h>
+#include <linux/module.h>
+
+#include <asm/alternative.h>
+#include <asm/cacheflush.h>
+#include <asm/errata_list.h>
+#include <asm/text-patching.h>
+#include <asm/processor.h>
+#include <asm/sbi.h>
+#include <asm/vendorid_list.h>
+#include <asm/vendor_extensions.h>
+
+void __init_or_module mips_errata_patch_func(struct alt_entry *begin,
+					     struct alt_entry *end,
+					     unsigned long archid,
+					     unsigned long impid,
+					     unsigned int stage)
+{
+	if (!IS_ENABLED(CONFIG_ERRATA_MIPS))
+		return;
+
+	if (!IS_ENABLED(CONFIG_ERRATA_MIPS_P8700_PAUSE_OPCODE))
+		return;
+
+	asm volatile(ALTERNATIVE(".4byte 0x1000000f", ".4byte 0x00501013",
+				 MIPS_VENDOR_ID, 0, /* patch_id */
+				 CONFIG_ERRATA_MIPS_P8700_PAUSE_OPCODE));
+}
diff --git a/arch/riscv/include/asm/alternative.h b/arch/riscv/include/asm/alternative.h
index 3c2b59b25017..bc3ada8190a9 100644
--- a/arch/riscv/include/asm/alternative.h
+++ b/arch/riscv/include/asm/alternative.h
@@ -48,6 +48,9 @@  struct alt_entry {
 void andes_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
 			     unsigned long archid, unsigned long impid,
 			     unsigned int stage);
+void mips_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
+			      unsigned long archid, unsigned long impid,
+			      unsigned int stage);
 void sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
 			      unsigned long archid, unsigned long impid,
 			      unsigned int stage);
diff --git a/arch/riscv/include/asm/vendorid_list.h b/arch/riscv/include/asm/vendorid_list.h
index 2f2bb0c84f9a..55d979a7a7c2 100644
--- a/arch/riscv/include/asm/vendorid_list.h
+++ b/arch/riscv/include/asm/vendorid_list.h
@@ -8,5 +8,6 @@ 
 #define ANDES_VENDOR_ID		0x31e
 #define SIFIVE_VENDOR_ID	0x489
 #define THEAD_VENDOR_ID		0x5b7
+#define MIPS_VENDOR_ID		0x127
 
 #endif
diff --git a/arch/riscv/kernel/alternative.c b/arch/riscv/kernel/alternative.c
index 7eb3cb1215c6..7642704c7f18 100644
--- a/arch/riscv/kernel/alternative.c
+++ b/arch/riscv/kernel/alternative.c
@@ -47,6 +47,11 @@  static void riscv_fill_cpu_mfr_info(struct cpu_manufacturer_info_t *cpu_mfr_info
 		cpu_mfr_info->patch_func = andes_errata_patch_func;
 		break;
 #endif
+#ifdef CONFIG_ERRATA_MIPS
+	case MIPS_VENDOR_ID:
+		cpu_mfr_info->patch_func = mips_errata_patch_func;
+		break;
+#endif
 #ifdef CONFIG_ERRATA_SIFIVE
 	case SIFIVE_VENDOR_ID:
 		cpu_mfr_info->patch_func = sifive_errata_patch_func;