* [PATCH v2 01/11] platform: generic: mips: add P8700
2025-02-12 12:27 ` Anup Patel
@ 2025-02-26 0:53 ` Chao-ying Fu
2025-03-28 4:45 ` Anup Patel
2025-02-26 0:53 ` [PATCH v2 02/11] platform: generic: mips: add header files Chao-ying Fu
` (47 subsequent siblings)
48 siblings, 1 reply; 70+ messages in thread
From: Chao-ying Fu @ 2025-02-26 0:53 UTC (permalink / raw)
To: opensbi
Add a new config first.
---
platform/generic/Kconfig | 4 ++++
platform/generic/configs/defconfig | 1 +
2 files changed, 5 insertions(+)
diff --git a/platform/generic/Kconfig b/platform/generic/Kconfig
index 688da3f..a24d6ab 100644
--- a/platform/generic/Kconfig
+++ b/platform/generic/Kconfig
@@ -68,6 +68,10 @@ config PLATFORM_THEAD
select THEAD_C9XX_PMU
default n
+config PLATFORM_MIPS_P8700
+ bool "MIPS P8700 support"
+ default n
+
source "$(OPENSBI_SRC_DIR)/platform/generic/andes/Kconfig"
source "$(OPENSBI_SRC_DIR)/platform/generic/thead/Kconfig"
diff --git a/platform/generic/configs/defconfig b/platform/generic/configs/defconfig
index bb26062..ce1f1ae 100644
--- a/platform/generic/configs/defconfig
+++ b/platform/generic/configs/defconfig
@@ -6,6 +6,7 @@ CONFIG_PLATFORM_SIFIVE_FU740=y
CONFIG_PLATFORM_SOPHGO_SG2042=y
CONFIG_PLATFORM_STARFIVE_JH7110=y
CONFIG_PLATFORM_THEAD=y
+CONFIG_PLATFORM_MIPS_P8700=n
CONFIG_FDT_CPPC=y
CONFIG_FDT_CPPC_RPMI=y
CONFIG_FDT_GPIO=y
--
2.47.1
^ permalink raw reply related [flat|nested] 70+ messages in thread* Re: [PATCH v2 01/11] platform: generic: mips: add P8700
2025-02-26 0:53 ` [PATCH v2 01/11] " Chao-ying Fu
@ 2025-03-28 4:45 ` Anup Patel
0 siblings, 0 replies; 70+ messages in thread
From: Anup Patel @ 2025-03-28 4:45 UTC (permalink / raw)
To: Chao-ying Fu; +Cc: opensbi, Chao-ying Fu
On Wed, Feb 26, 2025 at 7:38 AM Chao-ying Fu <icebergfu@gmail.com> wrote:
>
> Add a new config first.
Missing Signed-off-by, otherwise looks good to me.
Reviewed-by: Anup Patel <anup@brainfault.org>
Regards,
Anup
> ---
> platform/generic/Kconfig | 4 ++++
> platform/generic/configs/defconfig | 1 +
> 2 files changed, 5 insertions(+)
>
> diff --git a/platform/generic/Kconfig b/platform/generic/Kconfig
> index 688da3f..a24d6ab 100644
> --- a/platform/generic/Kconfig
> +++ b/platform/generic/Kconfig
> @@ -68,6 +68,10 @@ config PLATFORM_THEAD
> select THEAD_C9XX_PMU
> default n
>
> +config PLATFORM_MIPS_P8700
> + bool "MIPS P8700 support"
> + default n
> +
> source "$(OPENSBI_SRC_DIR)/platform/generic/andes/Kconfig"
> source "$(OPENSBI_SRC_DIR)/platform/generic/thead/Kconfig"
>
> diff --git a/platform/generic/configs/defconfig b/platform/generic/configs/defconfig
> index bb26062..ce1f1ae 100644
> --- a/platform/generic/configs/defconfig
> +++ b/platform/generic/configs/defconfig
> @@ -6,6 +6,7 @@ CONFIG_PLATFORM_SIFIVE_FU740=y
> CONFIG_PLATFORM_SOPHGO_SG2042=y
> CONFIG_PLATFORM_STARFIVE_JH7110=y
> CONFIG_PLATFORM_THEAD=y
> +CONFIG_PLATFORM_MIPS_P8700=n
> CONFIG_FDT_CPPC=y
> CONFIG_FDT_CPPC_RPMI=y
> CONFIG_FDT_GPIO=y
> --
> 2.47.1
>
>
> --
> opensbi mailing list
> opensbi@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply [flat|nested] 70+ messages in thread
* [PATCH v2 02/11] platform: generic: mips: add header files
2025-02-12 12:27 ` Anup Patel
2025-02-26 0:53 ` [PATCH v2 01/11] " Chao-ying Fu
@ 2025-02-26 0:53 ` Chao-ying Fu
2025-03-28 4:47 ` Anup Patel
2025-02-26 0:53 ` [PATCH v2 03/11] platform: generic: mips: add mips-cm header file Chao-ying Fu
` (46 subsequent siblings)
48 siblings, 1 reply; 70+ messages in thread
From: Chao-ying Fu @ 2025-02-26 0:53 UTC (permalink / raw)
To: opensbi
Add header files to define MIPS Custom CSRs and define for the board.
---
platform/generic/include/mips/board.h | 33 +++++++
platform/generic/include/mips/p8700.h | 122 ++++++++++++++++++++++++++
2 files changed, 155 insertions(+)
create mode 100644 platform/generic/include/mips/board.h
create mode 100644 platform/generic/include/mips/p8700.h
diff --git a/platform/generic/include/mips/board.h b/platform/generic/include/mips/board.h
new file mode 100644
index 0000000..6fe7b8b
--- /dev/null
+++ b/platform/generic/include/mips/board.h
@@ -0,0 +1,33 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 MIPS
+ *
+ */
+
+#ifndef __BOARD_H__
+#define __BOARD_H__
+
+/* Please review all defines to change for your board. */
+
+/* Use in stw.S, p8700.c, p8700.h, mips-cm.h */
+#define CM_BASE 0x16100000
+
+/* Use in mips-cm.h, p8700.c */
+#define CLUSTERS_IN_PLATFORM 1
+#if CLUSTERS_IN_PLATFORM > 1
+/* Define global CM bases for cluster 0, 1, 2, and more. */
+#define GLOBAL_CM_BASE0 0
+#define GLOBAL_CM_BASE1 0
+#define GLOBAL_CM_BASE2 0
+#endif
+
+/* Use in stw.S */
+#define TIMER_ADDR (CM_BASE + 0x8050)
+
+/* Use in cps-vec.S */
+#define DRAM_ADDRESS 0x80000000
+#define DRAM_SIZE 0x80000000
+#define DRAM_PMP_ADDR ((DRAM_ADDRESS >> 2) | ((DRAM_SIZE - 1) >> 3))
+
+#endif
diff --git a/platform/generic/include/mips/p8700.h b/platform/generic/include/mips/p8700.h
new file mode 100644
index 0000000..6aa71d9
--- /dev/null
+++ b/platform/generic/include/mips/p8700.h
@@ -0,0 +1,122 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 MIPS
+ *
+ */
+
+#ifndef __P8700_H__
+#define __P8700_H__
+
+#include <mips/board.h>
+
+/* PMA */
+#define CSR_MIPSPMACFG0 0x7e0
+#define CSR_MIPSPMACFG1 0x7e1
+#define CSR_MIPSPMACFG2 0x7e2
+#define CSR_MIPSPMACFG3 0x7e3
+#define CSR_MIPSPMACFG4 0x7e4
+#define CSR_MIPSPMACFG5 0x7e5
+#define CSR_MIPSPMACFG6 0x7e6
+#define CSR_MIPSPMACFG7 0x7e7
+#define CSR_MIPSPMACFG8 0x7e8
+#define CSR_MIPSPMACFG9 0x7e9
+#define CSR_MIPSPMACFG10 0x7ea
+#define CSR_MIPSPMACFG11 0x7eb
+#define CSR_MIPSPMACFG12 0x7ec
+#define CSR_MIPSPMACFG13 0x7ed
+#define CSR_MIPSPMACFG14 0x7ee
+#define CSR_MIPSPMACFG15 0x7ef
+
+/* MIPS CCA */
+#define CCA_CACHE_ENABLE 0
+#define CCA_CACHE_DISABLE 2
+#define PMA_SPECULATION (1 << 3)
+
+/* MIPS CSR */
+#define CSR_MIPSTVEC 0x7c0
+#define CSR_MIPSCONFIG0 0x7d0
+#define CSR_MIPSCONFIG1 0x7d1
+#define CSR_MIPSCONFIG2 0x7d2
+#define CSR_MIPSCONFIG3 0x7d3
+#define CSR_MIPSCONFIG4 0x7d4
+#define CSR_MIPSCONFIG5 0x7d5
+#define CSR_MIPSCONFIG6 0x7d6
+#define CSR_MIPSCONFIG7 0x7d7
+#define CSR_MIPSCONFIG8 0x7d8
+#define CSR_MIPSCONFIG9 0x7d9
+#define CSR_MIPSCONFIG10 0x7da
+#define CSR_MIPSCONFIG11 0x7db
+
+#define MIPSCONFIG5_MTW 4
+
+#define GEN_MASK(h, l) (((1ul << ((h) + 1 - (l))) - 1) << (l))
+#define EXT(val, mask) (((val) & (mask)) >> (__builtin_ffs(mask) - 1))
+
+/*
+ * We allocate the number of bits to encode clusters, cores, and harts
+ * from the original mhartid to a new dense index.
+ */
+#define NUM_OF_BITS_FOR_CLUSTERS 4
+#define NUM_OF_BITS_FOR_CORES 12
+#define NUM_OF_BITS_FOR_HARTS 4
+
+/* mhartid field info */
+#define MHARTID_CORE_MASK 0xff
+#define MHARTID_CORE_SHIFT 4
+
+/* To get the field from new/hashed mhartid */
+#define NEW_CLUSTER_SHIFT (NUM_OF_BITS_FOR_CORES + NUM_OF_BITS_FOR_HARTS)
+#define NEW_CLUSTER_MASK ((1 << NUM_OF_BITS_FOR_CLUSTERS) - 1)
+#define NEW_CORE_SHIFT NUM_OF_BITS_FOR_HARTS
+#define NEW_CORE_MASK ((1 << NUM_OF_BITS_FOR_CORES) - 1)
+#define NEW_HART_MASK ((1 << NUM_OF_BITS_FOR_HARTS) - 1)
+#define cpu_cluster(i) (((i) >> NEW_CLUSTER_SHIFT) & NEW_CLUSTER_MASK)
+#define cpu_core(i) (((i) >> NEW_CORE_SHIFT) & NEW_CORE_MASK)
+#define cpu_hart(i) ((i) & NEW_HART_MASK)
+
+#define CPC_BASE (CM_BASE + 0x8000)
+
+#define SIZE_FOR_CPC_MTIME 0x10000 /* The size must be 2^order */
+#define AIA_BASE (CM_BASE + 0x40000)
+#define SIZE_FOR_AIA_M_MODE 0x20000 /* The size must be 2^order */
+#define P8700_ALIGN 0x10000
+
+#define CM_BASE_HART_SHIFT 3
+#define CM_BASE_CORE_SHIFT 8
+#define CM_BASE_CLUSTER_SHIFT 19
+
+/* GCR Block offsets */
+#define GCR_OFF_LOCAL 0x2000
+
+#define GCR_BASE_OFFSET 0x0008
+#define GCR_CORE_COH_EN 0x00f8
+#define GCR_CORE_COH_EN_EN (0x1 << 0)
+
+#define L2_PFT_CONTROL_OFFSET 0x0300
+#define L2_PFT_CONTROL_B_OFFSET 0x0308
+
+/* CPC Block offsets */
+#define CPC_PWRUP_CTL 0x0030
+#define CPC_CM_STAT_CONF 0x1008
+
+#define CPC_OFF_LOCAL 0x2000
+
+#define CPC_Cx_VP_STOP 0x0020
+#define CPC_Cx_VP_RUN 0x0028
+#define CPC_Cx_CMD 0x0000
+
+#define CPC_Cx_CMD_PWRUP 0x3
+#define CPC_Cx_CMD_RESET 0x4
+
+#define CPC_Cx_STAT_CONF 0x0008
+#define CPC_Cx_STAT_CONF_SEQ_STATE GEN_MASK(22, 19)
+#define CPC_Cx_STAT_CONF_SEQ_STATE_U5 6
+#define CPC_Cx_STAT_CONF_SEQ_STATE_U6 7
+
+#define INDEXED(op, reg, idx, offset, base) \
+ li idx, offset ;\
+ add idx, idx, base ;\
+ op reg, (idx)
+
+#endif
--
2.47.1
^ permalink raw reply related [flat|nested] 70+ messages in thread* Re: [PATCH v2 02/11] platform: generic: mips: add header files
2025-02-26 0:53 ` [PATCH v2 02/11] platform: generic: mips: add header files Chao-ying Fu
@ 2025-03-28 4:47 ` Anup Patel
0 siblings, 0 replies; 70+ messages in thread
From: Anup Patel @ 2025-03-28 4:47 UTC (permalink / raw)
To: Chao-ying Fu; +Cc: opensbi, Chao-ying Fu
On Wed, Feb 26, 2025 at 7:38 AM Chao-ying Fu <icebergfu@gmail.com> wrote:
>
> Add header files to define MIPS Custom CSRs and define for the board.
Missing Signed-off-by, otherwise looks good to me.
Reviewed-by: Anup Patel <anup@brainfault.org>
Regards,
Anup
> ---
> platform/generic/include/mips/board.h | 33 +++++++
> platform/generic/include/mips/p8700.h | 122 ++++++++++++++++++++++++++
> 2 files changed, 155 insertions(+)
> create mode 100644 platform/generic/include/mips/board.h
> create mode 100644 platform/generic/include/mips/p8700.h
>
> diff --git a/platform/generic/include/mips/board.h b/platform/generic/include/mips/board.h
> new file mode 100644
> index 0000000..6fe7b8b
> --- /dev/null
> +++ b/platform/generic/include/mips/board.h
> @@ -0,0 +1,33 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Copyright (c) 2025 MIPS
> + *
> + */
> +
> +#ifndef __BOARD_H__
> +#define __BOARD_H__
> +
> +/* Please review all defines to change for your board. */
> +
> +/* Use in stw.S, p8700.c, p8700.h, mips-cm.h */
> +#define CM_BASE 0x16100000
> +
> +/* Use in mips-cm.h, p8700.c */
> +#define CLUSTERS_IN_PLATFORM 1
> +#if CLUSTERS_IN_PLATFORM > 1
> +/* Define global CM bases for cluster 0, 1, 2, and more. */
> +#define GLOBAL_CM_BASE0 0
> +#define GLOBAL_CM_BASE1 0
> +#define GLOBAL_CM_BASE2 0
> +#endif
> +
> +/* Use in stw.S */
> +#define TIMER_ADDR (CM_BASE + 0x8050)
> +
> +/* Use in cps-vec.S */
> +#define DRAM_ADDRESS 0x80000000
> +#define DRAM_SIZE 0x80000000
> +#define DRAM_PMP_ADDR ((DRAM_ADDRESS >> 2) | ((DRAM_SIZE - 1) >> 3))
> +
> +#endif
> diff --git a/platform/generic/include/mips/p8700.h b/platform/generic/include/mips/p8700.h
> new file mode 100644
> index 0000000..6aa71d9
> --- /dev/null
> +++ b/platform/generic/include/mips/p8700.h
> @@ -0,0 +1,122 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Copyright (c) 2025 MIPS
> + *
> + */
> +
> +#ifndef __P8700_H__
> +#define __P8700_H__
> +
> +#include <mips/board.h>
> +
> +/* PMA */
> +#define CSR_MIPSPMACFG0 0x7e0
> +#define CSR_MIPSPMACFG1 0x7e1
> +#define CSR_MIPSPMACFG2 0x7e2
> +#define CSR_MIPSPMACFG3 0x7e3
> +#define CSR_MIPSPMACFG4 0x7e4
> +#define CSR_MIPSPMACFG5 0x7e5
> +#define CSR_MIPSPMACFG6 0x7e6
> +#define CSR_MIPSPMACFG7 0x7e7
> +#define CSR_MIPSPMACFG8 0x7e8
> +#define CSR_MIPSPMACFG9 0x7e9
> +#define CSR_MIPSPMACFG10 0x7ea
> +#define CSR_MIPSPMACFG11 0x7eb
> +#define CSR_MIPSPMACFG12 0x7ec
> +#define CSR_MIPSPMACFG13 0x7ed
> +#define CSR_MIPSPMACFG14 0x7ee
> +#define CSR_MIPSPMACFG15 0x7ef
> +
> +/* MIPS CCA */
> +#define CCA_CACHE_ENABLE 0
> +#define CCA_CACHE_DISABLE 2
> +#define PMA_SPECULATION (1 << 3)
> +
> +/* MIPS CSR */
> +#define CSR_MIPSTVEC 0x7c0
> +#define CSR_MIPSCONFIG0 0x7d0
> +#define CSR_MIPSCONFIG1 0x7d1
> +#define CSR_MIPSCONFIG2 0x7d2
> +#define CSR_MIPSCONFIG3 0x7d3
> +#define CSR_MIPSCONFIG4 0x7d4
> +#define CSR_MIPSCONFIG5 0x7d5
> +#define CSR_MIPSCONFIG6 0x7d6
> +#define CSR_MIPSCONFIG7 0x7d7
> +#define CSR_MIPSCONFIG8 0x7d8
> +#define CSR_MIPSCONFIG9 0x7d9
> +#define CSR_MIPSCONFIG10 0x7da
> +#define CSR_MIPSCONFIG11 0x7db
> +
> +#define MIPSCONFIG5_MTW 4
> +
> +#define GEN_MASK(h, l) (((1ul << ((h) + 1 - (l))) - 1) << (l))
> +#define EXT(val, mask) (((val) & (mask)) >> (__builtin_ffs(mask) - 1))
> +
> +/*
> + * We allocate the number of bits to encode clusters, cores, and harts
> + * from the original mhartid to a new dense index.
> + */
> +#define NUM_OF_BITS_FOR_CLUSTERS 4
> +#define NUM_OF_BITS_FOR_CORES 12
> +#define NUM_OF_BITS_FOR_HARTS 4
> +
> +/* mhartid field info */
> +#define MHARTID_CORE_MASK 0xff
> +#define MHARTID_CORE_SHIFT 4
> +
> +/* To get the field from new/hashed mhartid */
> +#define NEW_CLUSTER_SHIFT (NUM_OF_BITS_FOR_CORES + NUM_OF_BITS_FOR_HARTS)
> +#define NEW_CLUSTER_MASK ((1 << NUM_OF_BITS_FOR_CLUSTERS) - 1)
> +#define NEW_CORE_SHIFT NUM_OF_BITS_FOR_HARTS
> +#define NEW_CORE_MASK ((1 << NUM_OF_BITS_FOR_CORES) - 1)
> +#define NEW_HART_MASK ((1 << NUM_OF_BITS_FOR_HARTS) - 1)
> +#define cpu_cluster(i) (((i) >> NEW_CLUSTER_SHIFT) & NEW_CLUSTER_MASK)
> +#define cpu_core(i) (((i) >> NEW_CORE_SHIFT) & NEW_CORE_MASK)
> +#define cpu_hart(i) ((i) & NEW_HART_MASK)
> +
> +#define CPC_BASE (CM_BASE + 0x8000)
> +
> +#define SIZE_FOR_CPC_MTIME 0x10000 /* The size must be 2^order */
> +#define AIA_BASE (CM_BASE + 0x40000)
> +#define SIZE_FOR_AIA_M_MODE 0x20000 /* The size must be 2^order */
> +#define P8700_ALIGN 0x10000
> +
> +#define CM_BASE_HART_SHIFT 3
> +#define CM_BASE_CORE_SHIFT 8
> +#define CM_BASE_CLUSTER_SHIFT 19
> +
> +/* GCR Block offsets */
> +#define GCR_OFF_LOCAL 0x2000
> +
> +#define GCR_BASE_OFFSET 0x0008
> +#define GCR_CORE_COH_EN 0x00f8
> +#define GCR_CORE_COH_EN_EN (0x1 << 0)
> +
> +#define L2_PFT_CONTROL_OFFSET 0x0300
> +#define L2_PFT_CONTROL_B_OFFSET 0x0308
> +
> +/* CPC Block offsets */
> +#define CPC_PWRUP_CTL 0x0030
> +#define CPC_CM_STAT_CONF 0x1008
> +
> +#define CPC_OFF_LOCAL 0x2000
> +
> +#define CPC_Cx_VP_STOP 0x0020
> +#define CPC_Cx_VP_RUN 0x0028
> +#define CPC_Cx_CMD 0x0000
> +
> +#define CPC_Cx_CMD_PWRUP 0x3
> +#define CPC_Cx_CMD_RESET 0x4
> +
> +#define CPC_Cx_STAT_CONF 0x0008
> +#define CPC_Cx_STAT_CONF_SEQ_STATE GEN_MASK(22, 19)
> +#define CPC_Cx_STAT_CONF_SEQ_STATE_U5 6
> +#define CPC_Cx_STAT_CONF_SEQ_STATE_U6 7
> +
> +#define INDEXED(op, reg, idx, offset, base) \
> + li idx, offset ;\
> + add idx, idx, base ;\
> + op reg, (idx)
> +
> +#endif
> --
> 2.47.1
>
>
> --
> opensbi mailing list
> opensbi@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply [flat|nested] 70+ messages in thread
* [PATCH v2 03/11] platform: generic: mips: add mips-cm header file
2025-02-12 12:27 ` Anup Patel
2025-02-26 0:53 ` [PATCH v2 01/11] " Chao-ying Fu
2025-02-26 0:53 ` [PATCH v2 02/11] platform: generic: mips: add header files Chao-ying Fu
@ 2025-02-26 0:53 ` Chao-ying Fu
2025-03-28 4:48 ` Anup Patel
2025-02-26 0:53 ` [PATCH v2 04/11] platform: generic: mips: add custom exception handler Chao-ying Fu
` (45 subsequent siblings)
48 siblings, 1 reply; 70+ messages in thread
From: Chao-ying Fu @ 2025-02-26 0:53 UTC (permalink / raw)
To: opensbi
Add accessor functions for MIPS CM registers.
---
platform/generic/include/mips/mips-cm.h | 88 +++++++++++++++++++++++++
1 file changed, 88 insertions(+)
create mode 100644 platform/generic/include/mips/mips-cm.h
diff --git a/platform/generic/include/mips/mips-cm.h b/platform/generic/include/mips/mips-cm.h
new file mode 100644
index 0000000..19b4384
--- /dev/null
+++ b/platform/generic/include/mips/mips-cm.h
@@ -0,0 +1,88 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 MIPS
+ *
+ */
+
+#ifndef __MIPS_CM_H__
+#define __MIPS_CM_H__
+
+#include <mips/p8700.h>
+#include <sbi/sbi_console.h>
+
+/* Define 1 to print out CM read and write info */
+#define DEBUG_CM 0
+
+#if CLUSTERS_IN_PLATFORM > 1
+static long GLOBAL_CM_BASE[CLUSTERS_IN_PLATFORM] = {GLOBAL_CM_BASE0, GLOBAL_CM_BASE1, GLOBAL_CM_BASE2};
+#else
+static long GLOBAL_CM_BASE[CLUSTERS_IN_PLATFORM] = {CM_BASE};
+#endif
+
+#define CPS_ACCESSOR_R(unit, sz, base, off, name) \
+static inline u##sz read_##unit##_##name(u32 hartid, bool local_p) \
+{ \
+ u##sz value; \
+ long cmd_reg; \
+ int cl, co; \
+ cl = cpu_cluster(hartid); \
+ co = cpu_core(hartid); \
+ cmd_reg = (local_p ? (base) : ((base) - CM_BASE + GLOBAL_CM_BASE[cl])) \
+ + (co << CM_BASE_CORE_SHIFT) \
+ + off; \
+ if (DEBUG_CM) \
+ sbi_printf("CM READ%d cmd_reg=%lx\n", sz, cmd_reg); \
+ if (sz == 32) \
+ asm volatile("lw %0,0(%1)":"=r"(value):"r"(cmd_reg)); \
+ else if (sz == 64) \
+ asm volatile("ld %0,0(%1)":"=r"(value):"r"(cmd_reg)); \
+ asm volatile("fence"); \
+ return value; \
+}
+
+#define CPS_ACCESSOR_W(unit, sz, base, off, name) \
+static inline void write_##unit##_##name(u32 hartid, u##sz value, bool local_p) \
+{ \
+ long cmd_reg; \
+ int cl, co; \
+ cl = cpu_cluster(hartid); \
+ co = cpu_core(hartid); \
+ cmd_reg = (local_p ? (base) : ((base) - CM_BASE + GLOBAL_CM_BASE[cl])) \
+ + (co << CM_BASE_CORE_SHIFT) \
+ + off; \
+ if (DEBUG_CM) \
+ sbi_printf("CM WRITE%d cmd_reg=%lx value=%lx\n", sz, \
+ cmd_reg, (u64)value); \
+ if (sz == 32) \
+ asm volatile("sw %0,0(%1)"::"r"(value),"r"(cmd_reg)); \
+ else if (sz == 64) \
+ asm volatile("sd %0,0(%1)"::"r"(value),"r"(cmd_reg)); \
+ asm volatile("fence"); \
+}
+
+#define CPS_ACCESSOR_RW(unit, sz, base, off, name) \
+ CPS_ACCESSOR_R(unit, sz, base, off, name) \
+ CPS_ACCESSOR_W(unit, sz, base, off, name)
+
+#define CPC_CX_ACCESSOR_RW(sz, off, name) \
+ CPS_ACCESSOR_RW(cpc, sz, CPC_BASE, CPC_OFF_LOCAL + (off), co_##name)
+
+#define GCR_CX_ACCESSOR_RW(sz, off, name) \
+ CPS_ACCESSOR_RW(gcr, sz, CM_BASE, GCR_OFF_LOCAL + (off), co_##name)
+
+GCR_CX_ACCESSOR_RW(64, cpu_hart(hartid) << CM_BASE_HART_SHIFT, reset_base)
+GCR_CX_ACCESSOR_RW(32, GCR_CORE_COH_EN, coherence)
+
+CPC_CX_ACCESSOR_RW(32, CPC_Cx_VP_RUN, vp_run)
+CPC_CX_ACCESSOR_RW(32, CPC_Cx_VP_STOP, vp_stop)
+CPC_CX_ACCESSOR_RW(32, CPC_Cx_CMD, cmd)
+CPC_CX_ACCESSOR_RW(32, CPC_Cx_STAT_CONF, stat_conf)
+
+#define CPC_ACCESSOR_RW(sz, off, name) \
+ CPS_ACCESSOR_RW(cpc, sz, CPC_BASE, off, name)
+
+CPC_ACCESSOR_RW(32, CPC_PWRUP_CTL, pwrup_ctl)
+CPC_ACCESSOR_RW(32, CPC_CM_STAT_CONF, cm_stat_conf)
+
+#endif
--
2.47.1
^ permalink raw reply related [flat|nested] 70+ messages in thread* Re: [PATCH v2 03/11] platform: generic: mips: add mips-cm header file
2025-02-26 0:53 ` [PATCH v2 03/11] platform: generic: mips: add mips-cm header file Chao-ying Fu
@ 2025-03-28 4:48 ` Anup Patel
0 siblings, 0 replies; 70+ messages in thread
From: Anup Patel @ 2025-03-28 4:48 UTC (permalink / raw)
To: Chao-ying Fu; +Cc: opensbi, Chao-ying Fu
On Wed, Feb 26, 2025 at 7:38 AM Chao-ying Fu <icebergfu@gmail.com> wrote:
>
> Add accessor functions for MIPS CM registers.
This patch can be squashed into your PATCH2.
Regards,
Anup
> ---
> platform/generic/include/mips/mips-cm.h | 88 +++++++++++++++++++++++++
> 1 file changed, 88 insertions(+)
> create mode 100644 platform/generic/include/mips/mips-cm.h
>
> diff --git a/platform/generic/include/mips/mips-cm.h b/platform/generic/include/mips/mips-cm.h
> new file mode 100644
> index 0000000..19b4384
> --- /dev/null
> +++ b/platform/generic/include/mips/mips-cm.h
> @@ -0,0 +1,88 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Copyright (c) 2025 MIPS
> + *
> + */
> +
> +#ifndef __MIPS_CM_H__
> +#define __MIPS_CM_H__
> +
> +#include <mips/p8700.h>
> +#include <sbi/sbi_console.h>
> +
> +/* Define 1 to print out CM read and write info */
> +#define DEBUG_CM 0
> +
> +#if CLUSTERS_IN_PLATFORM > 1
> +static long GLOBAL_CM_BASE[CLUSTERS_IN_PLATFORM] = {GLOBAL_CM_BASE0, GLOBAL_CM_BASE1, GLOBAL_CM_BASE2};
> +#else
> +static long GLOBAL_CM_BASE[CLUSTERS_IN_PLATFORM] = {CM_BASE};
> +#endif
> +
> +#define CPS_ACCESSOR_R(unit, sz, base, off, name) \
> +static inline u##sz read_##unit##_##name(u32 hartid, bool local_p) \
> +{ \
> + u##sz value; \
> + long cmd_reg; \
> + int cl, co; \
> + cl = cpu_cluster(hartid); \
> + co = cpu_core(hartid); \
> + cmd_reg = (local_p ? (base) : ((base) - CM_BASE + GLOBAL_CM_BASE[cl])) \
> + + (co << CM_BASE_CORE_SHIFT) \
> + + off; \
> + if (DEBUG_CM) \
> + sbi_printf("CM READ%d cmd_reg=%lx\n", sz, cmd_reg); \
> + if (sz == 32) \
> + asm volatile("lw %0,0(%1)":"=r"(value):"r"(cmd_reg)); \
> + else if (sz == 64) \
> + asm volatile("ld %0,0(%1)":"=r"(value):"r"(cmd_reg)); \
> + asm volatile("fence"); \
> + return value; \
> +}
> +
> +#define CPS_ACCESSOR_W(unit, sz, base, off, name) \
> +static inline void write_##unit##_##name(u32 hartid, u##sz value, bool local_p) \
> +{ \
> + long cmd_reg; \
> + int cl, co; \
> + cl = cpu_cluster(hartid); \
> + co = cpu_core(hartid); \
> + cmd_reg = (local_p ? (base) : ((base) - CM_BASE + GLOBAL_CM_BASE[cl])) \
> + + (co << CM_BASE_CORE_SHIFT) \
> + + off; \
> + if (DEBUG_CM) \
> + sbi_printf("CM WRITE%d cmd_reg=%lx value=%lx\n", sz, \
> + cmd_reg, (u64)value); \
> + if (sz == 32) \
> + asm volatile("sw %0,0(%1)"::"r"(value),"r"(cmd_reg)); \
> + else if (sz == 64) \
> + asm volatile("sd %0,0(%1)"::"r"(value),"r"(cmd_reg)); \
> + asm volatile("fence"); \
> +}
> +
> +#define CPS_ACCESSOR_RW(unit, sz, base, off, name) \
> + CPS_ACCESSOR_R(unit, sz, base, off, name) \
> + CPS_ACCESSOR_W(unit, sz, base, off, name)
> +
> +#define CPC_CX_ACCESSOR_RW(sz, off, name) \
> + CPS_ACCESSOR_RW(cpc, sz, CPC_BASE, CPC_OFF_LOCAL + (off), co_##name)
> +
> +#define GCR_CX_ACCESSOR_RW(sz, off, name) \
> + CPS_ACCESSOR_RW(gcr, sz, CM_BASE, GCR_OFF_LOCAL + (off), co_##name)
> +
> +GCR_CX_ACCESSOR_RW(64, cpu_hart(hartid) << CM_BASE_HART_SHIFT, reset_base)
> +GCR_CX_ACCESSOR_RW(32, GCR_CORE_COH_EN, coherence)
> +
> +CPC_CX_ACCESSOR_RW(32, CPC_Cx_VP_RUN, vp_run)
> +CPC_CX_ACCESSOR_RW(32, CPC_Cx_VP_STOP, vp_stop)
> +CPC_CX_ACCESSOR_RW(32, CPC_Cx_CMD, cmd)
> +CPC_CX_ACCESSOR_RW(32, CPC_Cx_STAT_CONF, stat_conf)
> +
> +#define CPC_ACCESSOR_RW(sz, off, name) \
> + CPS_ACCESSOR_RW(cpc, sz, CPC_BASE, off, name)
> +
> +CPC_ACCESSOR_RW(32, CPC_PWRUP_CTL, pwrup_ctl)
> +CPC_ACCESSOR_RW(32, CPC_CM_STAT_CONF, cm_stat_conf)
> +
> +#endif
> --
> 2.47.1
>
>
> --
> opensbi mailing list
> opensbi@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply [flat|nested] 70+ messages in thread
* [PATCH v2 04/11] platform: generic: mips: add custom exception handler
2025-02-12 12:27 ` Anup Patel
` (2 preceding siblings ...)
2025-02-26 0:53 ` [PATCH v2 03/11] platform: generic: mips: add mips-cm header file Chao-ying Fu
@ 2025-02-26 0:53 ` Chao-ying Fu
2025-03-28 4:53 ` Anup Patel
2025-02-26 0:53 ` [PATCH v2 05/11] platform: generic: mips: add extra scratch space Chao-ying Fu
` (44 subsequent siblings)
48 siblings, 1 reply; 70+ messages in thread
From: Chao-ying Fu @ 2025-02-26 0:53 UTC (permalink / raw)
To: opensbi
Add the custom exception handler to implement software table walker,
rdtime emulation, and AMO instruction emulation.
---
platform/generic/include/mips/stw.h | 191 ++++++
platform/generic/mips/stw.S | 986 ++++++++++++++++++++++++++++
2 files changed, 1177 insertions(+)
create mode 100644 platform/generic/include/mips/stw.h
create mode 100644 platform/generic/mips/stw.S
diff --git a/platform/generic/include/mips/stw.h b/platform/generic/include/mips/stw.h
new file mode 100644
index 0000000..bdcacc3
--- /dev/null
+++ b/platform/generic/include/mips/stw.h
@@ -0,0 +1,191 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 MIPS
+ *
+
+Some lines of this code have been copied from
+https://github.com/riscv/riscv-tests and are used in accordance with following
+license:
+
+Copyright (c) 2012-2015, The Regents of the University of California (Regents).
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of the Regents nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
+SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
+OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
+BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
+HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
+MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+
+*/
+
+#include <sbi/sbi_scratch.h>
+#undef MSTATUS_MPRV
+#undef SATP_MODE_OFF
+#undef SATP_MODE_SV32
+#undef SATP_MODE_SV39
+#undef SATP_MODE_SV48
+#undef SATP_MODE_SV57
+#undef SATP_MODE_SV64
+#undef MSTATUS_MPV
+
+#define CAUSE_ILLEGAL_INST 2
+#define CAUSE_LOAD_ACCESS 0x5
+#define CAUSE_STORE_ACCESS 0x7
+#define CAUSE_LOAD_PAGE_FAULT 0xd
+#define CAUSE_STORE_PAGE_FAULT 0xf
+#define CAUSE_GUEST_LOAD_PAGE_FAULT 21
+#define CAUSE_GUEST_STORE_PAGE_FAULT 23
+#define CAUSE_READ_TIME 26
+#define CAUSE_GUEST_TLB_MISS 28
+#define MSTATUS_MPRV 0x00020000
+#define vsatp 0x280
+#define mtval2 0x34b
+#define hgatp 0x680
+
+#define SATP_MODE_OFF 0
+#define SATP_MODE_SV32 1
+#define SATP_MODE_SV39 8
+#define SATP_MODE_SV48 9
+#define SATP_MODE_SV57 10
+#define SATP_MODE_SV64 11
+#define mstatus_GVA_LSB 38
+#define PTE_V 0x001 /* Valid */
+#define PTE_R 0x002 /* Read */
+#define PTE_W 0x004 /* Write */
+#define PTE_X 0x008 /* Execute */
+#define PTE_U 0x010 /* User */
+#define PTE_G 0x020 /* Global */
+#define PTE_A 0x040 /* Accessed */
+#define PTE_D 0x080 /* Dirty */
+#define PTE_N 0x8000000000000000 /* Napot */
+#define PTE_RSVD 0x7fc0000000000000 /* RSVD */
+#define mstatus_MPV_MSB 39
+#define mstatus_MPV_LSB 39
+#define MSTATUS_MPV ALIGN_FIELD(-1, mstatus_MPV)
+
+/* Return value aligned at [msb:lsb]. */
+#define ALIGN(value, msb, lsb) (((value) & ((1 << (1 + msb - lsb)) - 1)) << lsb)
+
+/* Return value aligned@named field, i.e. [<field>_MSB:<field>_LSB]. */
+#define ALIGN_FIELD(value, field) ALIGN(value, field##_MSB, field##_LSB)
+
+/* rd = rs[max:min] */
+#define extract(rd, rs, max, min) ; \
+ slli rd, rs, __riscv_xlen - 1 - max ; \
+ srli rd, rd, __riscv_xlen - 1 - max + min
+
+/**
+ * GPR numbers of named gprs, for passing named gprs to instruction definitions.
+ */
+#define gpr_idx_x0 0
+#define gpr_idx_x1 1
+#define gpr_idx_sp 2
+#define gpr_idx_gp 3
+#define gpr_idx_tp 4
+#define gpr_idx_t0 5
+#define gpr_idx_t1 6
+#define gpr_idx_t2 7
+#define gpr_idx_s0 8
+#define gpr_idx_fp 8
+#define gpr_idx_s1 9
+#define gpr_idx_a0 10
+#define gpr_idx_a1 11
+#define gpr_idx_a2 12
+#define gpr_idx_a3 13
+#define gpr_idx_a4 14
+#define gpr_idx_a5 15
+#define gpr_idx_a6 16
+#define gpr_idx_a7 17
+#define gpr_idx_s2 18
+#define gpr_idx_s3 19
+#define gpr_idx_s4 20
+#define gpr_idx_s5 21
+#define gpr_idx_s6 22
+#define gpr_idx_s7 23
+#define gpr_idx_s8 24
+#define gpr_idx_s9 25
+#define gpr_idx_s10 26
+#define gpr_idx_s11 27
+#define gpr_idx_t3 28
+#define gpr_idx_t4 29
+#define gpr_idx_t5 30
+#define gpr_idx_t6 31
+
+#define GPR_IDX(rs) _GPR_IDX(rs)
+#define _GPR_IDX(rs) gpr_idx_##rs
+
+#if BIGENDIAN
+#define IWORD(x) ; \
+ .byte (x) & 0xff ; \
+ .byte (x)>>8 & 0xff ; \
+ .byte (x)>>16 & 0xff ; \
+ .byte (x)>>24 & 0xff
+#else
+ #define IWORD(x) .word x
+#endif
+
+#define MTLBWR(rs1, level) \
+ IWORD(0b11101100000000000000000001110011 | GPR_IDX(rs1)<<15 | level<<20)
+
+#define MTLBWR_HG(rs1, level) \
+ IWORD(0b11101100100000000000000001110011 | GPR_IDX(rs1)<<15 | level<<20)
+
+#define PAUSE_ZIHINTPAUSE() \
+ IWORD(0b00000001000000000000000000001111)
+
+#define PAUSE_MIPS() \
+ IWORD(0b00000000010100000001000000010011)
+
+#if ZIHINTPAUSE
+ #define PAUSE() PAUSE_ZIHINTPAUSE()
+#else
+ #define PAUSE() PAUSE_MIPS()
+#endif
+
+#define base (15 << 3) /* This should match SBI_SCRATCH_STW_TMP_OFFSET. */
+#if base != SBI_SCRATCH_STW_TMP_OFFSET
+ #error WRONG base for STW
+#endif
+#define O_tmp0 (base + (0 << 3))
+#define O_save_x1 (base + (1 << 3))
+#define O_satp_vsatp_scratch0 (base + (2 << 3))
+#define O_satp_vsatp_scratch1 (base + (3 << 3))
+#define O_satp_vsatp_scratch2 (base + (4 << 3))
+#define O_satp_vsatp_scratch3 (base + (5 << 3))
+#define O_satp_vsatp_scratch4 (base + (6 << 3))
+#define O_satp_vsatp_scratch5 (base + (7 << 3))
+#define O_satp_vsatp_scratch6 (base + (8 << 3))
+#define O_satp_vsatp_scratch7 (base + (9 << 3))
+#define O_satp_vsatp_scratch8 (base + (10 << 3))
+#define O_hgatp_scratch0 (base + (11 << 3))
+#define O_hgatp_scratch1 (base + (12 << 3))
+#define O_hgatp_scratch2 (base + (13 << 3))
+#define O_hgatp_scratch3 (base + (14 << 3))
+#define O_hgatp_scratch4 (base + (15 << 3))
+#define O_hgatp_scratch5 (base + (16 << 3))
+#define O_amo_scratch (base + (17 << 3)) /* Points to 17 dwords */
+
+#ifdef __riscv_compressed
+ #define JUMP_TABLE_SHIFT 2
+ #define JUMP_TABLE_OFFSET 4
+#else
+ #define JUMP_TABLE_SHIFT 3
+ #define JUMP_TABLE_OFFSET 8
+#endif
diff --git a/platform/generic/mips/stw.S b/platform/generic/mips/stw.S
new file mode 100644
index 0000000..e032372
--- /dev/null
+++ b/platform/generic/mips/stw.S
@@ -0,0 +1,986 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 MIPS
+ *
+ * This file implements MIPS custom exception handler for software table walker
+ * when hardware table walker is disabled or not available, rdtime emulation,
+ * and AMO instruction emulation.
+ */
+
+/* Define STW_TLB_4KB to force to use 4KB pages in every level for software table walker.
+ This is for debugging only. */
+//#define STW_TLB_4KB 1
+
+#include <mips/stw.h>
+#include <mips/board.h>
+#include <mips/p8700.h>
+
+#if defined(__riscv_zbb)
+#define ZBB_PRESENT 1
+#endif
+
+ .text
+ .align 8
+ .globl mipstvec_handler_stw
+mipstvec_handler_stw:
+ j mipstvec_handler_stw_not_vec ; .align 2 /* 0 */
+ j fail ; .align 2 /* 1 */
+ j illegal_inst_handler ; .align 2 /* 2 */
+ j fail ; .align 2 /* 3 */
+ j fail ; .align 2 /* 4 */
+ j htw_load_access_fault_handler ; .align 2 /* 5 */
+ j fail ; .align 2 /* 6 */
+ j fail ; .align 2 /* 7 */
+ j fail ; .align 2 /* 8 */
+ j fail ; .align 2 /* 9 */
+ j fail ; .align 2 /* 10 */
+ j fail ; .align 2 /* 11 */
+ j fail ; .align 2 /* 12 */
+ j fail ; .align 2 /* 13 */
+ j fail ; .align 2 /* 14 */
+ j fail ; .align 2 /* 15 */
+ j fail ; .align 2 /* 16 */
+ j fail ; .align 2 /* 17 */
+ j fail ; .align 2 /* 18 */
+ j fail ; .align 2 /* 19 */
+ j fail ; .align 2 /* 20 */
+ j htw_page_fault_handler ; .align 2 /* 21 */
+ j fail ; .align 2 /* 22 */
+ j fail ; .align 2 /* 23 */
+ j satp_refill_handler ; .align 2 /* 24 */
+ j satp_refill_handler ; .align 2 /* 25 */
+ j read_time_handler ; .align 2 /* 26 */
+ j satp_refill_handler ; .align 2 /* 27 */
+ j hgatp_refill_handler ; .align 2 /* 28 */
+ j hgatp_refill_handler ; .align 2 /* 29 */
+ j read_time_handler ; .align 2 /* 30 */
+ j hgatp_refill_handler ; .align 2 /* 31 */
+
+mipstvec_handler_stw_not_vec:
+ csrci CSR_MIPSCONFIG5, MIPSCONFIG5_MTW
+ csrrw sp, mscratch, sp // Save sp to mscratch, load mscratch to sp
+ sd x1, O_save_x1(sp) // Save x1 to memory
+ csrr x1, mcause // Read mcause
+
+#define _mipstvec_handler_dispatch(i) ; \
+ addi x1, x1, -i ; \
+ bnez x1, 10f ; \
+ ld x1, O_save_x1(sp) ; \
+ csrrw sp, mscratch, sp ; \
+ j mipstvec_handler_stw + 4 * i ; \
+10: addi x1, x1, i
+
+#define _mipstvec_handler_dispatch_mtw(i) ; \
+ addi x1, x1, -i ; \
+ bnez x1, 10f ; \
+ ld x1, O_save_x1(sp) ; \
+ csrrw sp, mscratch, sp ; \
+ csrsi CSR_MIPSCONFIG5, MIPSCONFIG5_MTW ; \
+ j mipstvec_handler_stw + 4 * i ; \
+10: addi x1, x1, i
+
+ _mipstvec_handler_dispatch(2)
+ _mipstvec_handler_dispatch(20)
+ _mipstvec_handler_dispatch(21)
+ _mipstvec_handler_dispatch(23)
+ _mipstvec_handler_dispatch(24)
+ _mipstvec_handler_dispatch(25)
+ _mipstvec_handler_dispatch(26)
+ _mipstvec_handler_dispatch(27)
+ _mipstvec_handler_dispatch_mtw(28)
+ _mipstvec_handler_dispatch_mtw(29)
+ _mipstvec_handler_dispatch_mtw(30)
+ _mipstvec_handler_dispatch_mtw(31)
+ j fail
+
+satp_refill_handler:
+vsatp_refill_handler:
+ csrrw sp, mscratch, sp /* sp = mscratch; mscratch = saved sp */
+ sd t0, O_satp_vsatp_scratch0(sp) /* save t0 */
+ csrrw t0, mscratch, sp /* t0 = saved sp; restore mscratch */
+ sd t0, O_satp_vsatp_scratch8(sp) /* save sp */
+ sd t1, O_satp_vsatp_scratch1(sp) /* save t1 */
+ sd t2, O_satp_vsatp_scratch2(sp) /* save t2 */
+ sd t3, O_satp_vsatp_scratch3(sp) /* save t3 */
+ sd s4, O_satp_vsatp_scratch4(sp) /* save s4 */
+ sd t5, O_satp_vsatp_scratch5(sp) /* save t5 */
+ sd t6, O_satp_vsatp_scratch6(sp) /* save t6 */
+ sd s7, O_satp_vsatp_scratch7(sp) /* save s7 */
+
+ /* Save mstatus, mepc (not actually needed for non-vmode refill) */
+ csrr s4, mstatus
+ csrr t5, mepc
+ csrrsi t6, CSR_MIPSCONFIG5, MIPSCONFIG5_MTW /* set MTW bit */
+
+ /* Only V can be set out of following bits for PTE to be non-leaf */
+ li s7, PTE_V | PTE_R | PTE_W | PTE_X | PTE_U | PTE_A | PTE_D | PTE_N | PTE_RSVD
+
+_read_xsatp:
+ /* t1 = vsatp if vmode exception (mstatus.GVA=1) else satp */
+ sll t3, s4, __riscv_xlen - 1 - mstatus_GVA_LSB
+ bgez t3, 1f
+ csrr t3, vsatp
+ j 2f
+1: csrr t3, satp
+2:
+
+_find_xsatp_mode:
+ slli t0, t3, 20 // t0 = satp.PPN << 20 (clear out MODE, ASID)
+ srli t0, t0, 8 // "a" = t0 = satp.PPN << 12 (i.e. * PAGESIZE)
+ li t1, 0 // Is this PTE global? (Need to track during walk).
+ csrr t2, mtval // va
+
+ // Branch according to xsatp.MODE
+ srli t3, t3, 60
+ addi t3, t3, -SATP_MODE_SV39
+ beqz t3, _xsatp_Sv39_level2 // Sv39
+ addi t3, t3, SATP_MODE_SV39 - SATP_MODE_SV48
+ beqz t3, _xsatp_Sv39_level3 // Sv48
+ j fail
+
+_xsatp_Sv39_level3:
+ extract (t3, t2, 47, 39) // t3 = VPN[2]
+ slli t3, t3, 3 // t3 = VPN[2] * PTESIZE
+ add t0, t0, t3 // t0 = a + VPN[2] * PTESIZE
+ ld t0, 0(t0) // t0 = PTE
+ and t3, t0, s7
+ xori t3, t3, PTE_V
+ bnez t3, _xsatp_level3_leaf
+ andi t3, t0, PTE_G
+ or t1, t1, t3
+ extract (t0, t0, 53, 10) // t0 = PTE[53:10]
+ slli t0, t0, 12 // "a" = t0 = PTE[53:10] * PAGESIZE
+
+_xsatp_Sv39_level2:
+ extract (t3, t2, 38, 30) // t3 = VPN[2]
+ slli t3, t3, 3 // t3 = VPN[2] * PTESIZE
+ add t0, t0, t3 // t0 = a + VPN[2] * PTESIZE
+ ld t0, 0(t0) // t0 = PTE
+ and t3, t0, s7
+ xori t3, t3, PTE_V
+ bnez t3, _xsatp_level2_leaf
+ andi t3, t0, PTE_G
+ or t1, t1, t3
+ extract (t0, t0, 53, 10) // t0 = PTE[53:10]
+ slli t0, t0, 12 // "a" = t0 = PTE[53:10] * PAGESIZE
+
+_xsatp_Sv39_level1:
+ extract (t3, t2, 29, 21) // t3 = VPN[2]
+ slli t3, t3, 3 // t3 = VPN[2] * PTESIZE
+ add t0, t0, t3 // t0 = a + VPN[2] * PTESIZE
+ ld t0, 0(t0) // t0 = PTE
+ and t3, t0, s7
+ xori t3, t3, PTE_V
+ bnez t3, _xsatp_level1_leaf
+ andi t3, t0, PTE_G
+ or t1, t1, t3
+ extract (t0, t0, 53, 10) // t0 = PTE[53:10]
+ slli t0, t0, 12 // "a" = t0 = PTE[53:10] * PAGESIZE
+
+_xsatp_Sv39_level0:
+ extract (t3, t2, 20, 13) // t3 = VPN[2] (even page)
+ slli t3, t3, 4 // t3 = VPN[2] (even page) * 2 * PTESIZE
+ add t0, t0, t3 // t0 = a + VPN[2] (even page) 2 * PTESIZE
+ ld t3, 0(t0) // t3 = even PTE
+ ld t0, 8(t0) // t0 = odd PTE
+
+_xsatp_level0_leaf:
+ or t3, t3, t1 // global if parent table is global
+ or t0, t0, t1 // global if parent table is global
+ li t1, 0x1000 // even/odd bit
+ or t2, t2, t1 // Odd page mtval
+ csrw mtval, t2
+ MTLBWR (t0, 0) // Write odd PTE to TLB
+ csrc mtval, t1 // Even page mtval
+ MTLBWR (t3, 0) // Write even PTE to TLB
+
+_xsatp_mret:
+ csrw mstatus, s4 /* Restore mstatus */
+ csrw mepc, t5 /* Restore mepc */
+ csrw CSR_MIPSCONFIG5, t6 /* Restore mipsconfig5 */
+
+ ld t0, O_satp_vsatp_scratch0(sp) /* restore t0 */
+ ld t1, O_satp_vsatp_scratch1(sp) /* restore t1 */
+ ld t2, O_satp_vsatp_scratch2(sp) /* restore t2 */
+ ld t3, O_satp_vsatp_scratch3(sp) /* restore t3 */
+ ld s4, O_satp_vsatp_scratch4(sp) /* restore s4 */
+ ld t5, O_satp_vsatp_scratch5(sp) /* restore t5 */
+ ld t6, O_satp_vsatp_scratch6(sp) /* restore t6 */
+ ld s7, O_satp_vsatp_scratch7(sp) /* restore sp */
+ ld sp, O_satp_vsatp_scratch8(sp) /* restore sp */
+
+ mret
+
+_xsatp_level1_leaf:
+ or t0, t0, t1 // global if parent table is global
+#ifdef STW_TLB_4KB
+ extract (t3, t2, 20, 12)
+ sll t3, t3, 10
+ or t0, t0, t3
+ csrw mtval, t2
+ MTLBWR (t0, 0)
+#else
+ csrw mtval, t2
+ MTLBWR (t0, 1)
+#endif
+ j _xsatp_mret
+
+_xsatp_level2_leaf:
+ or t0, t0, t1 // global if parent table is global
+#ifdef STW_TLB_4KB
+ extract (t3, t2, 29, 12)
+ sll t3, t3, 10
+ or t0, t0, t3
+ csrw mtval, t2
+ MTLBWR (t0, 0)
+#else
+ csrw mtval, t2
+ MTLBWR (t0, 2)
+#endif
+ j _xsatp_mret
+
+_xsatp_level3_leaf:
+ or t0, t0, t1 // global if parent table is global
+#ifdef STW_TLB_4KB
+ extract (t3, t2, 38, 12)
+ sll t3, t3, 10
+ or t0, t0, t3
+ csrw mtval, t2
+ MTLBWR (t0, 0)
+#else
+ csrw mtval, t2
+ MTLBWR (t0, 3)
+#endif
+ j _xsatp_mret
+
+hgatp_refill_handler:
+ csrrw sp, mscratch, sp /* sp = mscratch; mscratch = saved sp */
+ sd t0, O_hgatp_scratch0(sp) /* save t0 */
+ csrrw t0, mscratch, sp /* t0 = saved sp; restore mscratch */
+ sd t0, O_hgatp_scratch5(sp) /* save sp */
+ sd t1, O_hgatp_scratch1(sp) /* save t1 */
+ sd t2, O_hgatp_scratch2(sp) /* save t2 */
+ sd t3, O_hgatp_scratch3(sp) /* save t3 */
+ sd s4, O_hgatp_scratch4(sp) /* save s4 */
+
+ /* Only V can be set out of following bits for PTE to be non-leaf */
+ li s4, PTE_V | PTE_R | PTE_W | PTE_X | PTE_U | PTE_A | PTE_D | PTE_N | PTE_RSVD
+
+ /* set MTW=1 */
+ csrsi CSR_MIPSCONFIG5, MIPSCONFIG5_MTW
+
+_find_hgatp_mode:
+ csrr t3, hgatp
+ slli t0, t3, 20 // t0 = hgatp.PPN << 20 (clear out MODE, ASID)
+ srli t0, t0, 8 // "a" = t0 = hgatp.PPN << 12 (i.e. * PAGESIZE)
+ li t1, 0 // Is this PTE global? (Need to track during walk).
+ csrr t2, mtval // gpa
+
+ // Branch according to hgatp.MODE
+ srli t3, t3, 60
+ addi t3, t3, -SATP_MODE_SV39
+ bnez t3, 1f
+ extract (t3, t2, 38, 28) // t3 = VPN[2]
+ j _hgatp_Sv39x4_level2_got_vpn2
+1: addi t3, t3, SATP_MODE_SV39 - SATP_MODE_SV48
+ beqz t3, _hgatp_Sv39x4_level3
+ j fail
+
+_hgatp_Sv39x4_level3:
+ extract (t3, t2, 47, 37) // t3 = VPN[2]
+ slli t3, t3, 3 // t3 = VPN[2] * PTESIZE
+ add t0, t0, t3 // t0 = a + VPN[2] * PTESIZE
+ ld t0, 0(t0) // t0 = PTE
+ and t3, t0, s4
+ xori t3, t3, PTE_V
+ bnez t3, _hgatp_level3_leaf
+ andi t3, t0, PTE_G
+ or t1, t1, t3
+ extract (t0, t0, 53, 10) // t0 = PTE[53:10]
+ slli t0, t0, 12 // "a" = t0 = PTE[53:10] * PAGESIZE
+
+_hgatp_Sv39x4_level2:
+ extract (t3, t2, 36, 28) // t3 = VPN[2]
+_hgatp_Sv39x4_level2_got_vpn2:
+ slli t3, t3, 3 // t3 = VPN[2] * PTESIZE
+ add t0, t0, t3 // t0 = a + VPN[2] * PTESIZE
+ ld t0, 0(t0) // t0 = PTE
+ and t3, t0, s4
+ xori t3, t3, PTE_V
+ bnez t3, _hgatp_level2_leaf
+ andi t3, t0, PTE_G
+ or t1, t1, t3
+ extract (t0, t0, 53, 10) // t0 = PTE[53:10]
+ slli t0, t0, 12 // "a" = t0 = PTE[53:10] * PAGESIZE
+
+_hgatp_Sv39x4_level1:
+ extract (t3, t2, 27, 19) // t3 = VPN[2]
+ slli t3, t3, 3 // t3 = VPN[2] * PTESIZE
+ add t0, t0, t3 // t0 = a + VPN[2] * PTESIZE
+ ld t0, 0(t0) // t0 = PTE
+ and t3, t0, s4
+ xori t3, t3, PTE_V
+ bnez t3, _hgatp_level1_leaf
+ andi t3, t0, PTE_G
+ or t1, t1, t3
+ extract (t0, t0, 53, 10) // t0 = PTE[53:10]
+ slli t0, t0, 12 // "a" = t0 = PTE[53:10] * PAGESIZE
+
+_hgatp_Sv39x4_level0:
+ extract (t3, t2, 18, 11) // t3 = VPN[2] (even page)
+ slli t3, t3, 4 // t3 = VPN[2] (even page) * 2 * PTESIZE
+ add t0, t0, t3 // t0 = a + VPN[2] (even page) 2 * PTESIZE
+ ld t2, 0(t0) // t2 = even PTE
+ ld t3, 8(t0) // t3 = odd PTE
+
+_hgatp_level0_leaf:
+ or t2, t2, t1 // global if parent table is global
+ or t3, t3, t1 // global if parent table is global
+ li t0, 0x0400 // even/odd bit
+ csrc mtval, t0
+ MTLBWR_HG (t2, 0)
+ csrs mtval, t0
+ MTLBWR_HG (t3, 0)
+
+_hgatp_mret:
+ csrci CSR_MIPSCONFIG5, MIPSCONFIG5_MTW /* Clear MTW bit */
+
+ ld t0, O_hgatp_scratch0(sp) /* restore t0 */
+ ld t1, O_hgatp_scratch1(sp) /* restore t1 */
+ ld t2, O_hgatp_scratch2(sp) /* restore t2 */
+ ld t3, O_hgatp_scratch3(sp) /* restore t3 */
+ ld s4, O_hgatp_scratch4(sp) /* restore s4 */
+ ld sp, O_hgatp_scratch5(sp) /* restore sp */
+
+ mret
+
+_hgatp_level1_leaf:
+ or t0, t0, t1 // global if parent table is global
+#ifdef STW_TLB_4KB
+ extract (t3, t2, 20, 12)
+ sll t3, t3, 10
+ or t0, t0, t3
+ MTLBWR_HG (t0, 0)
+#else
+ MTLBWR_HG (t0, 1)
+#endif
+ j _hgatp_mret
+
+_hgatp_level2_leaf:
+ or t0, t0, t1 // global if parent table is global
+#ifdef STW_TLB_4KB
+ extract (t3, t2, 29, 12)
+ sll t3, t3, 10
+ or t0, t0, t3
+ MTLBWR_HG (t0, 0)
+#else
+ MTLBWR_HG (t0, 2)
+#endif
+ j _hgatp_mret
+
+_hgatp_level3_leaf:
+ or t0, t0, t1 // global if parent table is global
+#ifdef STW_TLB_4KB
+ extract (t3, t2, 38, 12)
+ sll t3, t3, 10
+ or t0, t0, t3
+ MTLBWR_HG (t0, 0)
+#else
+ MTLBWR_HG (t0, 3)
+#endif
+ j _hgatp_mret
+
+htw_load_access_fault_handler:
+htw_hgatp_refill_handler:
+htw_page_fault_handler:
+ j fail
+
+
+
+/********************
+ * rdtime emulation *
+ ********************/
+ .global read_time_handler
+read_time_handler:
+ csrrw sp, mscratch, sp /* sp = mscratch; mscratch = saved sp */
+ sd x1, O_satp_vsatp_scratch0(sp) /* save sp */
+ sd x3, O_satp_vsatp_scratch1(sp) /* save x3 */
+
+ /* Set x1 to address of function which will set rd to x3 */
+ csrr x1, mtval
+ srli x1, x1, 7 - JUMP_TABLE_SHIFT
+ andi x1, x1, 0x1f << JUMP_TABLE_SHIFT
+ lla x3, write_xr_rdtime
+ add x1, x1, x3
+
+ /* Read the time memory mapped register */
+ lui x3, %hi(TIMER_ADDR)
+ ld x3, %lo(TIMER_ADDR)(x3)
+
+ /* Call function which sets rd = x3 */
+ jalr x1
+
+ /* Increment mepc to skip instruction we just emulated */
+ csrr x1, mepc
+ addi x1, x1, 4
+ csrw mepc, x1
+
+ /* Restore gprs from memory */
+ ld x1, O_satp_vsatp_scratch0(sp) /* restore x1 */
+ ld x3, O_satp_vsatp_scratch1(sp) /* restore x3 */
+ csrrw sp, mscratch, sp
+
+ mret
+
+/***************************************
+ * Custom Illegal Instruction handling *
+ ***************************************/
+
+illegal_inst_handler:
+ csrrw sp, mscratch, sp /* sp = mscratch; mscratch = saved sp */
+ sd x1, (O_amo_scratch + 0 * 8)(sp)
+ csrrw x1, mscratch, sp /* x1 = saved sp; restore mscratch */
+ sd x1, (O_amo_scratch + 1 * 8)(sp) /* save sp */
+ sd x3, (O_amo_scratch + 2 * 8)(sp)
+ sd x4, (O_amo_scratch + 3 * 8)(sp)
+ sd x5, (O_amo_scratch + 4 * 8)(sp)
+ sd x6, (O_amo_scratch + 5 * 8)(sp)
+ sd x7, (O_amo_scratch + 6 * 8)(sp)
+ sd x8, (O_amo_scratch + 7 * 8)(sp)
+ sd x9, (O_amo_scratch + 8 * 8)(sp)
+ sd x10, (O_amo_scratch + 9 * 8)(sp)
+
+// Planned register use:
+// x1 - ra, temporary, result
+// x2 - sp
+// x3 - rs1 value
+// x4 - rs2 value
+// x5 - temporary (mtval, mtval_match)
+// x6 - saved mepc
+// x7 - saved mtvec
+// x8 - saved mstatus
+// x9 - saved mtval
+// x10 - temporary (fail count)
+
+ csrr x9, mtval // x9 = faulting opcode
+
+ /* x3 = rs1 value */
+ lla x7, read_xr_amo // x7 = base address of table of read_xr funcs
+ srli x6, x9, 15 - JUMP_TABLE_SHIFT // Align rs1 idx as table offset
+ andi x6, x6, 0x1f << JUMP_TABLE_SHIFT // Isolated aligned rs1
+ add x4, x6, x7 // Apply offset to jump table
+ jalr x4 // Call func to read rs1 into x4
+ move x3, x4 // x3 = rs1 value
+
+ /* x4 = rs2 value */
+ srli x6, x9, 20 - JUMP_TABLE_SHIFT // Align rs2 idx as table offset
+ andi x6, x6, 0x1f << JUMP_TABLE_SHIFT // Isolate aligned rs2
+ add x4, x6, x7 // Apply offset to jump table
+ jalr x4 // Call func to read rs1 into x4
+
+ /* x6 = saved epc */
+ csrr x6, mepc // Save mepc
+
+ /* Use a local handler for mtvec exceptions */
+ lla x1, _illegal_inst_mtvec_handler
+ csrrw x7, mtvec, x1 // x7 = saved mtvec
+
+ /*
+ * Extract the AMO opcode match bits, write that value to t5. Each AMO
+ * instruction has a single unique value for these match bits. Since
+ * every AMO has the same value for the lower 12 bits, we xor the
+ * match value with the value of those lower 12 bits. This allows us
+ * to construct the compare value for each AMO instruction using a
+ * single LUI instruction.
+ */
+ li x1, 0b11111000000000000111000001111111
+ and x5, x9, x1
+ xori x5, x5, 0b000000101111
+
+ li x1, 0b00000000000000000010000000000000
+ beq x5, x1, _illegal_inst_handler_amoadd_w
+
+ li x1, 0b00000000000000000011000000000000
+ beq x5, x1, _illegal_inst_handler_amoadd_d
+
+ li x1, 0b01100000000000000010000000000000
+ beq x5, x1, _illegal_inst_handler_amoand_w
+
+ li x1, 0b01100000000000000011000000000000
+ beq x5, x1, _illegal_inst_handler_amoand_d
+
+ li x1, 0b10100000000000000010000000000000
+ beq x5, x1, _illegal_inst_handler_amomax_w
+
+ li x1, 0b10100000000000000011000000000000
+ beq x5, x1, _illegal_inst_handler_amomax_d
+
+ li x1, 0b11100000000000000010000000000000
+ beq x5, x1, _illegal_inst_handler_amomaxu_w
+
+ li x1, 0b11100000000000000011000000000000
+ beq x5, x1, _illegal_inst_handler_amomaxu_d
+
+ li x1, 0b10000000000000000010000000000000
+ beq x5, x1, _illegal_inst_handler_amomin_w
+
+ li x1, 0b10000000000000000011000000000000
+ beq x5, x1, _illegal_inst_handler_amomin_d
+
+ li x1, 0b11000000000000000010000000000000
+ beq x5, x1, _illegal_inst_handler_amominu_w
+
+ li x1, 0b11000000000000000011000000000000
+ beq x5, x1, _illegal_inst_handler_amominu_d
+
+ li x1, 0b01000000000000000010000000000000
+ beq x5, x1, _illegal_inst_handler_amoor_w
+
+ li x1, 0b01000000000000000011000000000000
+ beq x5, x1, _illegal_inst_handler_amoor_d
+
+ li x1, 0b00001000000000000010000000000000
+ beq x5, x1, _illegal_inst_handler_amoswap_w
+
+ li x1, 0b00001000000000000011000000000000
+ beq x5, x1, _illegal_inst_handler_amoswap_d
+
+ li x1, 0b00100000000000000010000000000000
+ beq x5, x1, _illegal_inst_handler_amoxor_w
+
+ li x1, 0b00100000000000000011000000000000
+ beq x5, x1, _illegal_inst_handler_amoxor_d
+
+ j fail
+
+/**
+ * Input:
+ * x3 = rs1
+ * x4 = rs2
+ * Ouput:
+ * x5 = old memory value
+ *
+ * Try LR/SC while counting down from NUM_TRIES_WITHOUT_LOCK to 0.
+ * If counter reaches 0, acquire the global lock, then repeat LR/SC,
+ * counting down from NUM_TRIES_WITHOUT_LOCK + NUM_TRIES_WITH_LOCK to
+ * NUM_TRIES_WITHOUT_LOCK + 1
+ * If counter reaches NUM_TRIES_WITHOUT_LOCK + 1 then fail completely.
+ * On LR/SC success, if counter > NUM_TRIES_WITHOUT_LOCK then we had the lock,
+ * and need to release it.
+ *
+ * Pseudocode:
+ *
+ * # Wait until not locked.
+ * while locked:
+ * pass
+ *
+ * counter = NUM_TRIES_WITHOUT_LOCK
+ * while 1:
+ * value, fail = amo()
+ * if fail: # SC fail.
+ * counter -= NUM_TRIES_WITHOUT_LOCK + 1
+ * if counter == 0:
+ * fail
+ * counter += NUM_TRIES_WITHOUT_LOCK
+ * if counter == 0:
+ * get_lock()
+ * counter = NUM_TRIES_WITH_LOCK + NUM_TRIES_WITHOUT_LOCK
+ * else: # SC pass.
+ * counter -= NUM_TRIES_WITH_LOCK
+ * if counter > 0:
+ * free_lock()
+ * return
+ */
+
+#define NUM_TRIES_WITHOUT_LOCK 20
+#define NUM_TRIES_WITH_LOCK 10000
+//#define NO_AMO_EMULATION_LOCK 1
+
+#if NO_AMO_EMULATION_LOCK
+#define DO_AMO(SIZE, AMO_OPERATION...) ; \
+ /* Set mstatus.MPRV = 1, x8 = saved mstatus */ ; \
+25: li x8, MSTATUS_MPRV ; \
+ csrrs x8, mstatus, x8 ; \
+ ; \
+30: lr.SIZE.aq x5, (x3) ; \
+ AMO_OPERATION ; \
+ sc.SIZE.aqrl x1, x1, (x3) ; \
+ beqz x1, _illegal_inst_handler_return ; \
+ j 30b
+#else
+#define DO_AMO(SIZE, AMO_OPERATION...) ; \
+ /* Wait until lock is clear */ ; \
+ lla x10, amo_lock ; \
+10: lr.d x5, (x10) ; \
+ beqz x5, 20f ; \
+ PAUSE() ; \
+ j 10b ; \
+ ; \
+20: li x10, NUM_TRIES_WITHOUT_LOCK ; \
+ ; \
+ /* Set mstatus.MPRV = 1, x8 = saved mstatus */ ; \
+25: li x8, MSTATUS_MPRV ; \
+ csrrs x8, mstatus, x8 ; \
+ ; \
+30: lr.SIZE.aq x5, (x3) ; \
+ AMO_OPERATION ; \
+ sc.SIZE.aqrl x1, x1, (x3) ; \
+ beqz x1, _illegal_inst_handler_return ; \
+ /* SC failed */ ; \
+ addi x10, x10, -NUM_TRIES_WITHOUT_LOCK + 1 ; \
+ bnez x10, 40f ; \
+ csrw mstatus, x8 ; \
+ j fail ; \
+40: addi x10, x10, NUM_TRIES_WITHOUT_LOCK ; \
+ bnez x10, 30b ; \
+ ; \
+ /* Acquire lock */ ; \
+ csrw mstatus, x8 ; \
+ lla x10, amo_lock ; \
+50: lr.d x5, (x10) ; \
+ beqz x5, 60f ; \
+ PAUSE() ; \
+ j 50b ; \
+60: sc.d x5, sp, (x10) /* Use sp as lock value */ ; \
+ bnez x5, 50b ; \
+ ; \
+ /* Retry with lock */ ; \
+ li x10, NUM_TRIES_WITH_LOCK + NUM_TRIES_WITHOUT_LOCK ; \
+ j 25b
+#endif /* NO_AMO_EMULATION_LOCK */
+
+_illegal_inst_handler_amoadd_w:
+ DO_AMO(w, addw x1, x5, x4)
+
+_illegal_inst_handler_amoadd_d:
+ DO_AMO(d, add x1, x5, x4)
+
+_illegal_inst_handler_amoand_w:
+ DO_AMO(w, and x1, x5, x4)
+
+_illegal_inst_handler_amoand_d:
+ DO_AMO(d, and x1, x5, x4)
+
+_illegal_inst_handler_amomax_w:
+ addw x4, x4, x0
+#if ZBB_PRESENT
+ DO_AMO(w, max x1, x5, x4)
+#else
+ DO_AMO(w,
+ move x1, x5 ;
+ bge x5, x4, 5f ;
+ move x1, x4 ;
+5:
+ )
+#endif
+
+_illegal_inst_handler_amomax_d:
+#if ZBB_PRESENT
+ DO_AMO(d, max x1, x5, x4)
+#else
+ DO_AMO(d,
+ move x1, x5 ;
+ bge x5, x4, 5f ;
+ move x1, x4 ;
+5:
+ )
+#endif
+
+_illegal_inst_handler_amomaxu_w:
+ addw x4, x4, x0
+#if ZBB_PRESENT
+ DO_AMO(w, maxu x1, x5, x4)
+#else
+ DO_AMO(w,
+ move x1, x5 ;
+ bgeu x5, x4, 5f ;
+ move x1, x4 ;
+5:
+ )
+#endif
+
+_illegal_inst_handler_amomaxu_d:
+#if ZBB_PRESENT
+ DO_AMO(d, maxu x1, x5, x4)
+#else
+ DO_AMO(d,
+ move x1, x5 ;
+ bgeu x5, x4, 5f ;
+ move x1, x4 ;
+5:
+ )
+#endif
+
+_illegal_inst_handler_amomin_w:
+ addw x4, x4, x0
+#if ZBB_PRESENT
+ DO_AMO(w, min x1, x5, x4)
+#else
+ DO_AMO(w,
+ move x1, x5 ;
+ ble x5, x4, 5f ;
+ move x1, x4 ;
+5:
+ )
+#endif
+
+_illegal_inst_handler_amomin_d:
+#if ZBB_PRESENT
+ DO_AMO(d, min x1, x5, x4)
+#else
+ DO_AMO(d,
+ move x1, x5 ;
+ ble x5, x4, 5f ;
+ move x1, x4 ;
+5:
+ )
+#endif
+
+_illegal_inst_handler_amominu_w:
+ addw x4, x4, x0
+#if ZBB_PRESENT
+ DO_AMO(w, minu x1, x5, x4)
+#else
+ DO_AMO(w,
+ move x1, x5 ;
+ bleu x5, x4, 5f ;
+ move x1, x4 ;
+5:
+ )
+#endif
+
+_illegal_inst_handler_amominu_d:
+#if ZBB_PRESENT
+ DO_AMO(d, minu x1, x5, x4)
+#else
+ DO_AMO(d,
+ move x1, x5 ;
+ bleu x5, x4, 5f ;
+ move x1, x4 ;
+5:
+ )
+#endif
+
+_illegal_inst_handler_amoor_w:
+ DO_AMO(w, or x1, x5, x4)
+
+_illegal_inst_handler_amoor_d:
+ DO_AMO(d, or x1, x5, x4)
+
+_illegal_inst_handler_amoswap_w:
+ DO_AMO(w, move x1, x4)
+
+_illegal_inst_handler_amoswap_d:
+ DO_AMO(d, move x1, x4)
+
+_illegal_inst_handler_amoxor_w:
+ DO_AMO(w, xor x1, x5, x4)
+
+_illegal_inst_handler_amoxor_d:
+ DO_AMO(d, xor x1, x5, x4)
+
+_illegal_inst_handler_return:
+ csrw mstatus, x8 // Restore mstatus (undo MPRV)
+
+#if NO_AMO_EMULATION_LOCK
+#else
+ /* Clear amo_lock if we had acquired it. */
+ addi x10, x10, -NUM_TRIES_WITHOUT_LOCK
+ blez x10, 10f
+ lla x10, amo_lock
+ sd x0, (x10)
+10:
+#endif /* NO_AMO_EMULATION_LOCK */
+
+ /* write rd with value in x5 */
+ lla x4, write_xr_amo // x4 = base address of write_xr funcs
+ srli x3, x9, 7 - JUMP_TABLE_SHIFT // Align rd idx as table offset
+ andi x3, x3, 0x1f << JUMP_TABLE_SHIFT // Isolate aligned rd
+ add x1, x4, x3 // Apply offset to jump table
+ jalr x1 // Call func to write x5 to rd
+
+ addi x6, x6, 4 // Saved mepc += 4 (skip emulated instruction)
+
+_illegal_inst_handler_mret:
+ csrw mepc, x6 // Restore mepc
+ csrw mtvec, x7 // Restore mtvec
+
+ /* Restore working set of XRs */
+ ld x1, (O_amo_scratch + 0 * 8)(sp)
+ ld x3, (O_amo_scratch + 2 * 8)(sp)
+ ld x4, (O_amo_scratch + 3 * 8)(sp)
+ ld x5, (O_amo_scratch + 4 * 8)(sp)
+ ld x6, (O_amo_scratch + 5 * 8)(sp)
+ ld x7, (O_amo_scratch + 6 * 8)(sp)
+ ld x8, (O_amo_scratch + 7 * 8)(sp)
+ ld x9, (O_amo_scratch + 8 * 8)(sp)
+ ld x10, (O_amo_scratch + 9 * 8)(sp)
+ ld sp, (O_amo_scratch + 1 * 8)(sp) /* restore sp last */
+
+ mret // Return
+
+ .align 2
+_illegal_inst_mtvec_handler:
+ /*
+ * If any exception occurs on a load/store during AMO emulation,
+ * just re-execute the original faulting AMO. This will regenerate
+ * the exception (page fault, access fault) and allow it to
+ * be handled as though from the original context
+ */
+ csrw mstatus, x8 // Restore mstatus
+
+ csrr x5, mcause
+
+ li x1, CAUSE_LOAD_PAGE_FAULT
+ beq x5, x1, _illegal_inst_handler_mret
+
+ li x1, CAUSE_STORE_PAGE_FAULT
+ beq x5, x1, _illegal_inst_handler_mret
+
+ li x1, CAUSE_GUEST_LOAD_PAGE_FAULT
+ beq x5, x1, _illegal_inst_handler_mret
+
+ li x1, CAUSE_GUEST_STORE_PAGE_FAULT
+ beq x5, x1, _illegal_inst_handler_mret
+
+ li x1, CAUSE_LOAD_ACCESS
+ beq x5, x1, _illegal_inst_handler_mret
+
+ li x1, CAUSE_STORE_ACCESS
+ beq x5, x1, _illegal_inst_handler_mret
+
+ // An unexpected exception during AMO emulation is fatal.
+ j fail
+
+/**
+ * This is a table of 32 functions.
+ * Calling the function read_xr_amo + rd * JUMP_TABLE_OFFSET does
+ * x4 = XR[rd]. For xrs where the value is stored in memory by the AMO handler,
+ * do x4 = MEM[address where $rd is stored], which has the equivalent effect.
+ */
+read_xr_amo:
+ li x4, 0 ; jr ra
+ ld x4, (O_amo_scratch + 0 * 8)(sp) ; jr ra
+ ld x4, (O_amo_scratch + 1 * 8)(sp) ; jr ra
+ ld x4, (O_amo_scratch + 2 * 8)(sp) ; jr ra
+ ld x4, (O_amo_scratch + 3 * 8)(sp) ; jr ra
+ ld x4, (O_amo_scratch + 4 * 8)(sp) ; jr ra
+ ld x4, (O_amo_scratch + 5 * 8)(sp) ; jr ra
+ ld x4, (O_amo_scratch + 6 * 8)(sp) ; jr ra
+ ld x4, (O_amo_scratch + 7 * 8)(sp) ; jr ra
+ ld x4, (O_amo_scratch + 8 * 8)(sp) ; jr ra
+ ld x4, (O_amo_scratch + 9 * 8)(sp) ; jr ra
+ move x4, x11 ; jr ra
+ move x4, x12 ; jr ra
+ move x4, x13 ; jr ra
+ move x4, x14 ; jr ra
+ move x4, x15 ; jr ra
+ move x4, x16 ; jr ra
+ move x4, x17 ; jr ra
+ move x4, x18 ; jr ra
+ move x4, x19 ; jr ra
+ move x4, x20 ; jr ra
+ move x4, x21 ; jr ra
+ move x4, x22 ; jr ra
+ move x4, x23 ; jr ra
+ move x4, x24 ; jr ra
+ move x4, x25 ; jr ra
+ move x4, x26 ; jr ra
+ move x4, x27 ; jr ra
+ move x4, x28 ; jr ra
+ move x4, x29 ; jr ra
+ move x4, x30 ; jr ra
+ move x4, x31 ; jr ra
+
+/**
+ * This is a table of 32 functions.
+ * Calling the function write_xr_amo + rd * JUMP_TABLE_OFFSET does:
+ * XR[rd] = x5. For xrs which will be restored from memory at the end of
+ * the AMO handler, do MEM[address where $rd is stored] = x5.
+ */
+write_xr_amo:
+ jr ra ; jr ra
+ sd x5, (O_amo_scratch + 0 * 8)(sp) ; jr ra
+ sd x5, (O_amo_scratch + 1 * 8)(sp) ; jr ra
+ sd x5, (O_amo_scratch + 2 * 8)(sp) ; jr ra
+ sd x5, (O_amo_scratch + 3 * 8)(sp) ; jr ra
+ sd x5, (O_amo_scratch + 4 * 8)(sp) ; jr ra
+ sd x5, (O_amo_scratch + 5 * 8)(sp) ; jr ra
+ sd x5, (O_amo_scratch + 6 * 8)(sp) ; jr ra
+ sd x5, (O_amo_scratch + 7 * 8)(sp) ; jr ra
+ sd x5, (O_amo_scratch + 8 * 8)(sp) ; jr ra
+ sd x5, (O_amo_scratch + 9 * 8)(sp) ; jr ra
+ move x11, x5 ; jr ra
+ move x12, x5 ; jr ra
+ move x13, x5 ; jr ra
+ move x14, x5 ; jr ra
+ move x15, x5 ; jr ra
+ move x16, x5 ; jr ra
+ move x17, x5 ; jr ra
+ move x18, x5 ; jr ra
+ move x19, x5 ; jr ra
+ move x20, x5 ; jr ra
+ move x21, x5 ; jr ra
+ move x22, x5 ; jr ra
+ move x23, x5 ; jr ra
+ move x24, x5 ; jr ra
+ move x25, x5 ; jr ra
+ move x26, x5 ; jr ra
+ move x27, x5 ; jr ra
+ move x28, x5 ; jr ra
+ move x29, x5 ; jr ra
+ move x30, x5 ; jr ra
+ move x31, x5 ; jr ra
+
+/**
+ * This is a table of 32 functions.
+ * Calling the function write_xr_rdtime + rd * JUMP_TABLE_OFFSET does:
+ * XR[rd] = x3. For xrs which will be restored from memory@the end of
+ * the rdtime handler, do MEM[address where $rd is stored] = x3.
+ */
+write_xr_rdtime:
+ jr ra ; jr ra
+ sd x3, O_satp_vsatp_scratch0(sp) ; jr ra
+ j _write_xr_rdtime_x1 ; jr ra
+ sd x3, O_satp_vsatp_scratch1(sp) ; jr ra
+ move x4, x3 ; jr ra
+ move x5, x3 ; jr ra
+ move x6, x3 ; jr ra
+ move x7, x3 ; jr ra
+ move x8, x3 ; jr ra
+ move x9, x3 ; jr ra
+ move x10, x3 ; jr ra
+ move x11, x3 ; jr ra
+ move x12, x3 ; jr ra
+ move x13, x3 ; jr ra
+ move x14, x3 ; jr ra
+ move x15, x3 ; jr ra
+ move x16, x3 ; jr ra
+ move x17, x3 ; jr ra
+ move x18, x3 ; jr ra
+ move x19, x3 ; jr ra
+ move x20, x3 ; jr ra
+ move x21, x3 ; jr ra
+ move x22, x3 ; jr ra
+ move x23, x3 ; jr ra
+ move x24, x3 ; jr ra
+ move x25, x3 ; jr ra
+ move x26, x3 ; jr ra
+ move x27, x3 ; jr ra
+ move x28, x3 ; jr ra
+ move x29, x3 ; jr ra
+ move x30, x3 ; jr ra
+ move x31, x3 ; jr ra
+_write_xr_rdtime_x1:
+ csrw mscratch, x3 ; jr ra
+
+fail:
+ unimp
+
+ .section .sbss
+ .align 6
+ .type amo_lock, @object
+ .size amo_lock, 64
+amo_lock:
+ .zero 64
--
2.47.1
^ permalink raw reply related [flat|nested] 70+ messages in thread* Re: [PATCH v2 04/11] platform: generic: mips: add custom exception handler
2025-02-26 0:53 ` [PATCH v2 04/11] platform: generic: mips: add custom exception handler Chao-ying Fu
@ 2025-03-28 4:53 ` Anup Patel
2025-04-08 2:49 ` Chao-ying Fu
0 siblings, 1 reply; 70+ messages in thread
From: Anup Patel @ 2025-03-28 4:53 UTC (permalink / raw)
To: Chao-ying Fu; +Cc: opensbi, Chao-ying Fu
On Wed, Feb 26, 2025 at 7:38 AM Chao-ying Fu <icebergfu@gmail.com> wrote:
>
> Add the custom exception handler to implement software table walker,
> rdtime emulation, and AMO instruction emulation.
I find it hard to justify this custom MIPS specific exception handler. Looks
like the intention here is to simply dump whatever makes it work under
mips directory.
Regards,
Anup
> ---
> platform/generic/include/mips/stw.h | 191 ++++++
> platform/generic/mips/stw.S | 986 ++++++++++++++++++++++++++++
> 2 files changed, 1177 insertions(+)
> create mode 100644 platform/generic/include/mips/stw.h
> create mode 100644 platform/generic/mips/stw.S
>
> diff --git a/platform/generic/include/mips/stw.h b/platform/generic/include/mips/stw.h
> new file mode 100644
> index 0000000..bdcacc3
> --- /dev/null
> +++ b/platform/generic/include/mips/stw.h
> @@ -0,0 +1,191 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Copyright (c) 2025 MIPS
> + *
> +
> +Some lines of this code have been copied from
> +https://github.com/riscv/riscv-tests and are used in accordance with following
> +license:
> +
> +Copyright (c) 2012-2015, The Regents of the University of California (Regents).
> +All Rights Reserved.
> +
> +Redistribution and use in source and binary forms, with or without
> +modification, are permitted provided that the following conditions are met:
> +1. Redistributions of source code must retain the above copyright
> + notice, this list of conditions and the following disclaimer.
> +2. Redistributions in binary form must reproduce the above copyright
> + notice, this list of conditions and the following disclaimer in the
> + documentation and/or other materials provided with the distribution.
> +3. Neither the name of the Regents nor the
> + names of its contributors may be used to endorse or promote products
> + derived from this software without specific prior written permission.
> +
> +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
> +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
> +OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
> +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> +
> +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
> +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
> +PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
> +HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
> +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
> +
> +*/
> +
> +#include <sbi/sbi_scratch.h>
> +#undef MSTATUS_MPRV
> +#undef SATP_MODE_OFF
> +#undef SATP_MODE_SV32
> +#undef SATP_MODE_SV39
> +#undef SATP_MODE_SV48
> +#undef SATP_MODE_SV57
> +#undef SATP_MODE_SV64
> +#undef MSTATUS_MPV
> +
> +#define CAUSE_ILLEGAL_INST 2
> +#define CAUSE_LOAD_ACCESS 0x5
> +#define CAUSE_STORE_ACCESS 0x7
> +#define CAUSE_LOAD_PAGE_FAULT 0xd
> +#define CAUSE_STORE_PAGE_FAULT 0xf
> +#define CAUSE_GUEST_LOAD_PAGE_FAULT 21
> +#define CAUSE_GUEST_STORE_PAGE_FAULT 23
> +#define CAUSE_READ_TIME 26
> +#define CAUSE_GUEST_TLB_MISS 28
> +#define MSTATUS_MPRV 0x00020000
> +#define vsatp 0x280
> +#define mtval2 0x34b
> +#define hgatp 0x680
> +
> +#define SATP_MODE_OFF 0
> +#define SATP_MODE_SV32 1
> +#define SATP_MODE_SV39 8
> +#define SATP_MODE_SV48 9
> +#define SATP_MODE_SV57 10
> +#define SATP_MODE_SV64 11
> +#define mstatus_GVA_LSB 38
> +#define PTE_V 0x001 /* Valid */
> +#define PTE_R 0x002 /* Read */
> +#define PTE_W 0x004 /* Write */
> +#define PTE_X 0x008 /* Execute */
> +#define PTE_U 0x010 /* User */
> +#define PTE_G 0x020 /* Global */
> +#define PTE_A 0x040 /* Accessed */
> +#define PTE_D 0x080 /* Dirty */
> +#define PTE_N 0x8000000000000000 /* Napot */
> +#define PTE_RSVD 0x7fc0000000000000 /* RSVD */
> +#define mstatus_MPV_MSB 39
> +#define mstatus_MPV_LSB 39
> +#define MSTATUS_MPV ALIGN_FIELD(-1, mstatus_MPV)
> +
> +/* Return value aligned at [msb:lsb]. */
> +#define ALIGN(value, msb, lsb) (((value) & ((1 << (1 + msb - lsb)) - 1)) << lsb)
> +
> +/* Return value aligned at named field, i.e. [<field>_MSB:<field>_LSB]. */
> +#define ALIGN_FIELD(value, field) ALIGN(value, field##_MSB, field##_LSB)
> +
> +/* rd = rs[max:min] */
> +#define extract(rd, rs, max, min) ; \
> + slli rd, rs, __riscv_xlen - 1 - max ; \
> + srli rd, rd, __riscv_xlen - 1 - max + min
> +
> +/**
> + * GPR numbers of named gprs, for passing named gprs to instruction definitions.
> + */
> +#define gpr_idx_x0 0
> +#define gpr_idx_x1 1
> +#define gpr_idx_sp 2
> +#define gpr_idx_gp 3
> +#define gpr_idx_tp 4
> +#define gpr_idx_t0 5
> +#define gpr_idx_t1 6
> +#define gpr_idx_t2 7
> +#define gpr_idx_s0 8
> +#define gpr_idx_fp 8
> +#define gpr_idx_s1 9
> +#define gpr_idx_a0 10
> +#define gpr_idx_a1 11
> +#define gpr_idx_a2 12
> +#define gpr_idx_a3 13
> +#define gpr_idx_a4 14
> +#define gpr_idx_a5 15
> +#define gpr_idx_a6 16
> +#define gpr_idx_a7 17
> +#define gpr_idx_s2 18
> +#define gpr_idx_s3 19
> +#define gpr_idx_s4 20
> +#define gpr_idx_s5 21
> +#define gpr_idx_s6 22
> +#define gpr_idx_s7 23
> +#define gpr_idx_s8 24
> +#define gpr_idx_s9 25
> +#define gpr_idx_s10 26
> +#define gpr_idx_s11 27
> +#define gpr_idx_t3 28
> +#define gpr_idx_t4 29
> +#define gpr_idx_t5 30
> +#define gpr_idx_t6 31
> +
> +#define GPR_IDX(rs) _GPR_IDX(rs)
> +#define _GPR_IDX(rs) gpr_idx_##rs
> +
> +#if BIGENDIAN
> +#define IWORD(x) ; \
> + .byte (x) & 0xff ; \
> + .byte (x)>>8 & 0xff ; \
> + .byte (x)>>16 & 0xff ; \
> + .byte (x)>>24 & 0xff
> +#else
> + #define IWORD(x) .word x
> +#endif
> +
> +#define MTLBWR(rs1, level) \
> + IWORD(0b11101100000000000000000001110011 | GPR_IDX(rs1)<<15 | level<<20)
> +
> +#define MTLBWR_HG(rs1, level) \
> + IWORD(0b11101100100000000000000001110011 | GPR_IDX(rs1)<<15 | level<<20)
> +
> +#define PAUSE_ZIHINTPAUSE() \
> + IWORD(0b00000001000000000000000000001111)
> +
> +#define PAUSE_MIPS() \
> + IWORD(0b00000000010100000001000000010011)
> +
> +#if ZIHINTPAUSE
> + #define PAUSE() PAUSE_ZIHINTPAUSE()
> +#else
> + #define PAUSE() PAUSE_MIPS()
> +#endif
> +
> +#define base (15 << 3) /* This should match SBI_SCRATCH_STW_TMP_OFFSET. */
> +#if base != SBI_SCRATCH_STW_TMP_OFFSET
> + #error WRONG base for STW
> +#endif
> +#define O_tmp0 (base + (0 << 3))
> +#define O_save_x1 (base + (1 << 3))
> +#define O_satp_vsatp_scratch0 (base + (2 << 3))
> +#define O_satp_vsatp_scratch1 (base + (3 << 3))
> +#define O_satp_vsatp_scratch2 (base + (4 << 3))
> +#define O_satp_vsatp_scratch3 (base + (5 << 3))
> +#define O_satp_vsatp_scratch4 (base + (6 << 3))
> +#define O_satp_vsatp_scratch5 (base + (7 << 3))
> +#define O_satp_vsatp_scratch6 (base + (8 << 3))
> +#define O_satp_vsatp_scratch7 (base + (9 << 3))
> +#define O_satp_vsatp_scratch8 (base + (10 << 3))
> +#define O_hgatp_scratch0 (base + (11 << 3))
> +#define O_hgatp_scratch1 (base + (12 << 3))
> +#define O_hgatp_scratch2 (base + (13 << 3))
> +#define O_hgatp_scratch3 (base + (14 << 3))
> +#define O_hgatp_scratch4 (base + (15 << 3))
> +#define O_hgatp_scratch5 (base + (16 << 3))
> +#define O_amo_scratch (base + (17 << 3)) /* Points to 17 dwords */
> +
> +#ifdef __riscv_compressed
> + #define JUMP_TABLE_SHIFT 2
> + #define JUMP_TABLE_OFFSET 4
> +#else
> + #define JUMP_TABLE_SHIFT 3
> + #define JUMP_TABLE_OFFSET 8
> +#endif
> diff --git a/platform/generic/mips/stw.S b/platform/generic/mips/stw.S
> new file mode 100644
> index 0000000..e032372
> --- /dev/null
> +++ b/platform/generic/mips/stw.S
> @@ -0,0 +1,986 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Copyright (c) 2025 MIPS
> + *
> + * This file implements MIPS custom exception handler for software table walker
> + * when hardware table walker is disabled or not available, rdtime emulation,
> + * and AMO instruction emulation.
> + */
> +
> +/* Define STW_TLB_4KB to force to use 4KB pages in every level for software table walker.
> + This is for debugging only. */
> +//#define STW_TLB_4KB 1
> +
> +#include <mips/stw.h>
> +#include <mips/board.h>
> +#include <mips/p8700.h>
> +
> +#if defined(__riscv_zbb)
> +#define ZBB_PRESENT 1
> +#endif
> +
> + .text
> + .align 8
> + .globl mipstvec_handler_stw
> +mipstvec_handler_stw:
> + j mipstvec_handler_stw_not_vec ; .align 2 /* 0 */
> + j fail ; .align 2 /* 1 */
> + j illegal_inst_handler ; .align 2 /* 2 */
> + j fail ; .align 2 /* 3 */
> + j fail ; .align 2 /* 4 */
> + j htw_load_access_fault_handler ; .align 2 /* 5 */
> + j fail ; .align 2 /* 6 */
> + j fail ; .align 2 /* 7 */
> + j fail ; .align 2 /* 8 */
> + j fail ; .align 2 /* 9 */
> + j fail ; .align 2 /* 10 */
> + j fail ; .align 2 /* 11 */
> + j fail ; .align 2 /* 12 */
> + j fail ; .align 2 /* 13 */
> + j fail ; .align 2 /* 14 */
> + j fail ; .align 2 /* 15 */
> + j fail ; .align 2 /* 16 */
> + j fail ; .align 2 /* 17 */
> + j fail ; .align 2 /* 18 */
> + j fail ; .align 2 /* 19 */
> + j fail ; .align 2 /* 20 */
> + j htw_page_fault_handler ; .align 2 /* 21 */
> + j fail ; .align 2 /* 22 */
> + j fail ; .align 2 /* 23 */
> + j satp_refill_handler ; .align 2 /* 24 */
> + j satp_refill_handler ; .align 2 /* 25 */
> + j read_time_handler ; .align 2 /* 26 */
> + j satp_refill_handler ; .align 2 /* 27 */
> + j hgatp_refill_handler ; .align 2 /* 28 */
> + j hgatp_refill_handler ; .align 2 /* 29 */
> + j read_time_handler ; .align 2 /* 30 */
> + j hgatp_refill_handler ; .align 2 /* 31 */
> +
> +mipstvec_handler_stw_not_vec:
> + csrci CSR_MIPSCONFIG5, MIPSCONFIG5_MTW
> + csrrw sp, mscratch, sp // Save sp to mscratch, load mscratch to sp
> + sd x1, O_save_x1(sp) // Save x1 to memory
> + csrr x1, mcause // Read mcause
> +
> +#define _mipstvec_handler_dispatch(i) ; \
> + addi x1, x1, -i ; \
> + bnez x1, 10f ; \
> + ld x1, O_save_x1(sp) ; \
> + csrrw sp, mscratch, sp ; \
> + j mipstvec_handler_stw + 4 * i ; \
> +10: addi x1, x1, i
> +
> +#define _mipstvec_handler_dispatch_mtw(i) ; \
> + addi x1, x1, -i ; \
> + bnez x1, 10f ; \
> + ld x1, O_save_x1(sp) ; \
> + csrrw sp, mscratch, sp ; \
> + csrsi CSR_MIPSCONFIG5, MIPSCONFIG5_MTW ; \
> + j mipstvec_handler_stw + 4 * i ; \
> +10: addi x1, x1, i
> +
> + _mipstvec_handler_dispatch(2)
> + _mipstvec_handler_dispatch(20)
> + _mipstvec_handler_dispatch(21)
> + _mipstvec_handler_dispatch(23)
> + _mipstvec_handler_dispatch(24)
> + _mipstvec_handler_dispatch(25)
> + _mipstvec_handler_dispatch(26)
> + _mipstvec_handler_dispatch(27)
> + _mipstvec_handler_dispatch_mtw(28)
> + _mipstvec_handler_dispatch_mtw(29)
> + _mipstvec_handler_dispatch_mtw(30)
> + _mipstvec_handler_dispatch_mtw(31)
> + j fail
> +
> +satp_refill_handler:
> +vsatp_refill_handler:
> + csrrw sp, mscratch, sp /* sp = mscratch; mscratch = saved sp */
> + sd t0, O_satp_vsatp_scratch0(sp) /* save t0 */
> + csrrw t0, mscratch, sp /* t0 = saved sp; restore mscratch */
> + sd t0, O_satp_vsatp_scratch8(sp) /* save sp */
> + sd t1, O_satp_vsatp_scratch1(sp) /* save t1 */
> + sd t2, O_satp_vsatp_scratch2(sp) /* save t2 */
> + sd t3, O_satp_vsatp_scratch3(sp) /* save t3 */
> + sd s4, O_satp_vsatp_scratch4(sp) /* save s4 */
> + sd t5, O_satp_vsatp_scratch5(sp) /* save t5 */
> + sd t6, O_satp_vsatp_scratch6(sp) /* save t6 */
> + sd s7, O_satp_vsatp_scratch7(sp) /* save s7 */
> +
> + /* Save mstatus, mepc (not actually needed for non-vmode refill) */
> + csrr s4, mstatus
> + csrr t5, mepc
> + csrrsi t6, CSR_MIPSCONFIG5, MIPSCONFIG5_MTW /* set MTW bit */
> +
> + /* Only V can be set out of following bits for PTE to be non-leaf */
> + li s7, PTE_V | PTE_R | PTE_W | PTE_X | PTE_U | PTE_A | PTE_D | PTE_N | PTE_RSVD
> +
> +_read_xsatp:
> + /* t1 = vsatp if vmode exception (mstatus.GVA=1) else satp */
> + sll t3, s4, __riscv_xlen - 1 - mstatus_GVA_LSB
> + bgez t3, 1f
> + csrr t3, vsatp
> + j 2f
> +1: csrr t3, satp
> +2:
> +
> +_find_xsatp_mode:
> + slli t0, t3, 20 // t0 = satp.PPN << 20 (clear out MODE, ASID)
> + srli t0, t0, 8 // "a" = t0 = satp.PPN << 12 (i.e. * PAGESIZE)
> + li t1, 0 // Is this PTE global? (Need to track during walk).
> + csrr t2, mtval // va
> +
> + // Branch according to xsatp.MODE
> + srli t3, t3, 60
> + addi t3, t3, -SATP_MODE_SV39
> + beqz t3, _xsatp_Sv39_level2 // Sv39
> + addi t3, t3, SATP_MODE_SV39 - SATP_MODE_SV48
> + beqz t3, _xsatp_Sv39_level3 // Sv48
> + j fail
> +
> +_xsatp_Sv39_level3:
> + extract (t3, t2, 47, 39) // t3 = VPN[2]
> + slli t3, t3, 3 // t3 = VPN[2] * PTESIZE
> + add t0, t0, t3 // t0 = a + VPN[2] * PTESIZE
> + ld t0, 0(t0) // t0 = PTE
> + and t3, t0, s7
> + xori t3, t3, PTE_V
> + bnez t3, _xsatp_level3_leaf
> + andi t3, t0, PTE_G
> + or t1, t1, t3
> + extract (t0, t0, 53, 10) // t0 = PTE[53:10]
> + slli t0, t0, 12 // "a" = t0 = PTE[53:10] * PAGESIZE
> +
> +_xsatp_Sv39_level2:
> + extract (t3, t2, 38, 30) // t3 = VPN[2]
> + slli t3, t3, 3 // t3 = VPN[2] * PTESIZE
> + add t0, t0, t3 // t0 = a + VPN[2] * PTESIZE
> + ld t0, 0(t0) // t0 = PTE
> + and t3, t0, s7
> + xori t3, t3, PTE_V
> + bnez t3, _xsatp_level2_leaf
> + andi t3, t0, PTE_G
> + or t1, t1, t3
> + extract (t0, t0, 53, 10) // t0 = PTE[53:10]
> + slli t0, t0, 12 // "a" = t0 = PTE[53:10] * PAGESIZE
> +
> +_xsatp_Sv39_level1:
> + extract (t3, t2, 29, 21) // t3 = VPN[2]
> + slli t3, t3, 3 // t3 = VPN[2] * PTESIZE
> + add t0, t0, t3 // t0 = a + VPN[2] * PTESIZE
> + ld t0, 0(t0) // t0 = PTE
> + and t3, t0, s7
> + xori t3, t3, PTE_V
> + bnez t3, _xsatp_level1_leaf
> + andi t3, t0, PTE_G
> + or t1, t1, t3
> + extract (t0, t0, 53, 10) // t0 = PTE[53:10]
> + slli t0, t0, 12 // "a" = t0 = PTE[53:10] * PAGESIZE
> +
> +_xsatp_Sv39_level0:
> + extract (t3, t2, 20, 13) // t3 = VPN[2] (even page)
> + slli t3, t3, 4 // t3 = VPN[2] (even page) * 2 * PTESIZE
> + add t0, t0, t3 // t0 = a + VPN[2] (even page) 2 * PTESIZE
> + ld t3, 0(t0) // t3 = even PTE
> + ld t0, 8(t0) // t0 = odd PTE
> +
> +_xsatp_level0_leaf:
> + or t3, t3, t1 // global if parent table is global
> + or t0, t0, t1 // global if parent table is global
> + li t1, 0x1000 // even/odd bit
> + or t2, t2, t1 // Odd page mtval
> + csrw mtval, t2
> + MTLBWR (t0, 0) // Write odd PTE to TLB
> + csrc mtval, t1 // Even page mtval
> + MTLBWR (t3, 0) // Write even PTE to TLB
> +
> +_xsatp_mret:
> + csrw mstatus, s4 /* Restore mstatus */
> + csrw mepc, t5 /* Restore mepc */
> + csrw CSR_MIPSCONFIG5, t6 /* Restore mipsconfig5 */
> +
> + ld t0, O_satp_vsatp_scratch0(sp) /* restore t0 */
> + ld t1, O_satp_vsatp_scratch1(sp) /* restore t1 */
> + ld t2, O_satp_vsatp_scratch2(sp) /* restore t2 */
> + ld t3, O_satp_vsatp_scratch3(sp) /* restore t3 */
> + ld s4, O_satp_vsatp_scratch4(sp) /* restore s4 */
> + ld t5, O_satp_vsatp_scratch5(sp) /* restore t5 */
> + ld t6, O_satp_vsatp_scratch6(sp) /* restore t6 */
> + ld s7, O_satp_vsatp_scratch7(sp) /* restore sp */
> + ld sp, O_satp_vsatp_scratch8(sp) /* restore sp */
> +
> + mret
> +
> +_xsatp_level1_leaf:
> + or t0, t0, t1 // global if parent table is global
> +#ifdef STW_TLB_4KB
> + extract (t3, t2, 20, 12)
> + sll t3, t3, 10
> + or t0, t0, t3
> + csrw mtval, t2
> + MTLBWR (t0, 0)
> +#else
> + csrw mtval, t2
> + MTLBWR (t0, 1)
> +#endif
> + j _xsatp_mret
> +
> +_xsatp_level2_leaf:
> + or t0, t0, t1 // global if parent table is global
> +#ifdef STW_TLB_4KB
> + extract (t3, t2, 29, 12)
> + sll t3, t3, 10
> + or t0, t0, t3
> + csrw mtval, t2
> + MTLBWR (t0, 0)
> +#else
> + csrw mtval, t2
> + MTLBWR (t0, 2)
> +#endif
> + j _xsatp_mret
> +
> +_xsatp_level3_leaf:
> + or t0, t0, t1 // global if parent table is global
> +#ifdef STW_TLB_4KB
> + extract (t3, t2, 38, 12)
> + sll t3, t3, 10
> + or t0, t0, t3
> + csrw mtval, t2
> + MTLBWR (t0, 0)
> +#else
> + csrw mtval, t2
> + MTLBWR (t0, 3)
> +#endif
> + j _xsatp_mret
> +
> +hgatp_refill_handler:
> + csrrw sp, mscratch, sp /* sp = mscratch; mscratch = saved sp */
> + sd t0, O_hgatp_scratch0(sp) /* save t0 */
> + csrrw t0, mscratch, sp /* t0 = saved sp; restore mscratch */
> + sd t0, O_hgatp_scratch5(sp) /* save sp */
> + sd t1, O_hgatp_scratch1(sp) /* save t1 */
> + sd t2, O_hgatp_scratch2(sp) /* save t2 */
> + sd t3, O_hgatp_scratch3(sp) /* save t3 */
> + sd s4, O_hgatp_scratch4(sp) /* save s4 */
> +
> + /* Only V can be set out of following bits for PTE to be non-leaf */
> + li s4, PTE_V | PTE_R | PTE_W | PTE_X | PTE_U | PTE_A | PTE_D | PTE_N | PTE_RSVD
> +
> + /* set MTW=1 */
> + csrsi CSR_MIPSCONFIG5, MIPSCONFIG5_MTW
> +
> +_find_hgatp_mode:
> + csrr t3, hgatp
> + slli t0, t3, 20 // t0 = hgatp.PPN << 20 (clear out MODE, ASID)
> + srli t0, t0, 8 // "a" = t0 = hgatp.PPN << 12 (i.e. * PAGESIZE)
> + li t1, 0 // Is this PTE global? (Need to track during walk).
> + csrr t2, mtval // gpa
> +
> + // Branch according to hgatp.MODE
> + srli t3, t3, 60
> + addi t3, t3, -SATP_MODE_SV39
> + bnez t3, 1f
> + extract (t3, t2, 38, 28) // t3 = VPN[2]
> + j _hgatp_Sv39x4_level2_got_vpn2
> +1: addi t3, t3, SATP_MODE_SV39 - SATP_MODE_SV48
> + beqz t3, _hgatp_Sv39x4_level3
> + j fail
> +
> +_hgatp_Sv39x4_level3:
> + extract (t3, t2, 47, 37) // t3 = VPN[2]
> + slli t3, t3, 3 // t3 = VPN[2] * PTESIZE
> + add t0, t0, t3 // t0 = a + VPN[2] * PTESIZE
> + ld t0, 0(t0) // t0 = PTE
> + and t3, t0, s4
> + xori t3, t3, PTE_V
> + bnez t3, _hgatp_level3_leaf
> + andi t3, t0, PTE_G
> + or t1, t1, t3
> + extract (t0, t0, 53, 10) // t0 = PTE[53:10]
> + slli t0, t0, 12 // "a" = t0 = PTE[53:10] * PAGESIZE
> +
> +_hgatp_Sv39x4_level2:
> + extract (t3, t2, 36, 28) // t3 = VPN[2]
> +_hgatp_Sv39x4_level2_got_vpn2:
> + slli t3, t3, 3 // t3 = VPN[2] * PTESIZE
> + add t0, t0, t3 // t0 = a + VPN[2] * PTESIZE
> + ld t0, 0(t0) // t0 = PTE
> + and t3, t0, s4
> + xori t3, t3, PTE_V
> + bnez t3, _hgatp_level2_leaf
> + andi t3, t0, PTE_G
> + or t1, t1, t3
> + extract (t0, t0, 53, 10) // t0 = PTE[53:10]
> + slli t0, t0, 12 // "a" = t0 = PTE[53:10] * PAGESIZE
> +
> +_hgatp_Sv39x4_level1:
> + extract (t3, t2, 27, 19) // t3 = VPN[2]
> + slli t3, t3, 3 // t3 = VPN[2] * PTESIZE
> + add t0, t0, t3 // t0 = a + VPN[2] * PTESIZE
> + ld t0, 0(t0) // t0 = PTE
> + and t3, t0, s4
> + xori t3, t3, PTE_V
> + bnez t3, _hgatp_level1_leaf
> + andi t3, t0, PTE_G
> + or t1, t1, t3
> + extract (t0, t0, 53, 10) // t0 = PTE[53:10]
> + slli t0, t0, 12 // "a" = t0 = PTE[53:10] * PAGESIZE
> +
> +_hgatp_Sv39x4_level0:
> + extract (t3, t2, 18, 11) // t3 = VPN[2] (even page)
> + slli t3, t3, 4 // t3 = VPN[2] (even page) * 2 * PTESIZE
> + add t0, t0, t3 // t0 = a + VPN[2] (even page) 2 * PTESIZE
> + ld t2, 0(t0) // t2 = even PTE
> + ld t3, 8(t0) // t3 = odd PTE
> +
> +_hgatp_level0_leaf:
> + or t2, t2, t1 // global if parent table is global
> + or t3, t3, t1 // global if parent table is global
> + li t0, 0x0400 // even/odd bit
> + csrc mtval, t0
> + MTLBWR_HG (t2, 0)
> + csrs mtval, t0
> + MTLBWR_HG (t3, 0)
> +
> +_hgatp_mret:
> + csrci CSR_MIPSCONFIG5, MIPSCONFIG5_MTW /* Clear MTW bit */
> +
> + ld t0, O_hgatp_scratch0(sp) /* restore t0 */
> + ld t1, O_hgatp_scratch1(sp) /* restore t1 */
> + ld t2, O_hgatp_scratch2(sp) /* restore t2 */
> + ld t3, O_hgatp_scratch3(sp) /* restore t3 */
> + ld s4, O_hgatp_scratch4(sp) /* restore s4 */
> + ld sp, O_hgatp_scratch5(sp) /* restore sp */
> +
> + mret
> +
> +_hgatp_level1_leaf:
> + or t0, t0, t1 // global if parent table is global
> +#ifdef STW_TLB_4KB
> + extract (t3, t2, 20, 12)
> + sll t3, t3, 10
> + or t0, t0, t3
> + MTLBWR_HG (t0, 0)
> +#else
> + MTLBWR_HG (t0, 1)
> +#endif
> + j _hgatp_mret
> +
> +_hgatp_level2_leaf:
> + or t0, t0, t1 // global if parent table is global
> +#ifdef STW_TLB_4KB
> + extract (t3, t2, 29, 12)
> + sll t3, t3, 10
> + or t0, t0, t3
> + MTLBWR_HG (t0, 0)
> +#else
> + MTLBWR_HG (t0, 2)
> +#endif
> + j _hgatp_mret
> +
> +_hgatp_level3_leaf:
> + or t0, t0, t1 // global if parent table is global
> +#ifdef STW_TLB_4KB
> + extract (t3, t2, 38, 12)
> + sll t3, t3, 10
> + or t0, t0, t3
> + MTLBWR_HG (t0, 0)
> +#else
> + MTLBWR_HG (t0, 3)
> +#endif
> + j _hgatp_mret
> +
> +htw_load_access_fault_handler:
> +htw_hgatp_refill_handler:
> +htw_page_fault_handler:
> + j fail
> +
> +
> +
> +/********************
> + * rdtime emulation *
> + ********************/
> + .global read_time_handler
> +read_time_handler:
> + csrrw sp, mscratch, sp /* sp = mscratch; mscratch = saved sp */
> + sd x1, O_satp_vsatp_scratch0(sp) /* save sp */
> + sd x3, O_satp_vsatp_scratch1(sp) /* save x3 */
> +
> + /* Set x1 to address of function which will set rd to x3 */
> + csrr x1, mtval
> + srli x1, x1, 7 - JUMP_TABLE_SHIFT
> + andi x1, x1, 0x1f << JUMP_TABLE_SHIFT
> + lla x3, write_xr_rdtime
> + add x1, x1, x3
> +
> + /* Read the time memory mapped register */
> + lui x3, %hi(TIMER_ADDR)
> + ld x3, %lo(TIMER_ADDR)(x3)
> +
> + /* Call function which sets rd = x3 */
> + jalr x1
> +
> + /* Increment mepc to skip instruction we just emulated */
> + csrr x1, mepc
> + addi x1, x1, 4
> + csrw mepc, x1
> +
> + /* Restore gprs from memory */
> + ld x1, O_satp_vsatp_scratch0(sp) /* restore x1 */
> + ld x3, O_satp_vsatp_scratch1(sp) /* restore x3 */
> + csrrw sp, mscratch, sp
> +
> + mret
> +
> +/***************************************
> + * Custom Illegal Instruction handling *
> + ***************************************/
> +
> +illegal_inst_handler:
> + csrrw sp, mscratch, sp /* sp = mscratch; mscratch = saved sp */
> + sd x1, (O_amo_scratch + 0 * 8)(sp)
> + csrrw x1, mscratch, sp /* x1 = saved sp; restore mscratch */
> + sd x1, (O_amo_scratch + 1 * 8)(sp) /* save sp */
> + sd x3, (O_amo_scratch + 2 * 8)(sp)
> + sd x4, (O_amo_scratch + 3 * 8)(sp)
> + sd x5, (O_amo_scratch + 4 * 8)(sp)
> + sd x6, (O_amo_scratch + 5 * 8)(sp)
> + sd x7, (O_amo_scratch + 6 * 8)(sp)
> + sd x8, (O_amo_scratch + 7 * 8)(sp)
> + sd x9, (O_amo_scratch + 8 * 8)(sp)
> + sd x10, (O_amo_scratch + 9 * 8)(sp)
> +
> +// Planned register use:
> +// x1 - ra, temporary, result
> +// x2 - sp
> +// x3 - rs1 value
> +// x4 - rs2 value
> +// x5 - temporary (mtval, mtval_match)
> +// x6 - saved mepc
> +// x7 - saved mtvec
> +// x8 - saved mstatus
> +// x9 - saved mtval
> +// x10 - temporary (fail count)
> +
> + csrr x9, mtval // x9 = faulting opcode
> +
> + /* x3 = rs1 value */
> + lla x7, read_xr_amo // x7 = base address of table of read_xr funcs
> + srli x6, x9, 15 - JUMP_TABLE_SHIFT // Align rs1 idx as table offset
> + andi x6, x6, 0x1f << JUMP_TABLE_SHIFT // Isolated aligned rs1
> + add x4, x6, x7 // Apply offset to jump table
> + jalr x4 // Call func to read rs1 into x4
> + move x3, x4 // x3 = rs1 value
> +
> + /* x4 = rs2 value */
> + srli x6, x9, 20 - JUMP_TABLE_SHIFT // Align rs2 idx as table offset
> + andi x6, x6, 0x1f << JUMP_TABLE_SHIFT // Isolate aligned rs2
> + add x4, x6, x7 // Apply offset to jump table
> + jalr x4 // Call func to read rs1 into x4
> +
> + /* x6 = saved epc */
> + csrr x6, mepc // Save mepc
> +
> + /* Use a local handler for mtvec exceptions */
> + lla x1, _illegal_inst_mtvec_handler
> + csrrw x7, mtvec, x1 // x7 = saved mtvec
> +
> + /*
> + * Extract the AMO opcode match bits, write that value to t5. Each AMO
> + * instruction has a single unique value for these match bits. Since
> + * every AMO has the same value for the lower 12 bits, we xor the
> + * match value with the value of those lower 12 bits. This allows us
> + * to construct the compare value for each AMO instruction using a
> + * single LUI instruction.
> + */
> + li x1, 0b11111000000000000111000001111111
> + and x5, x9, x1
> + xori x5, x5, 0b000000101111
> +
> + li x1, 0b00000000000000000010000000000000
> + beq x5, x1, _illegal_inst_handler_amoadd_w
> +
> + li x1, 0b00000000000000000011000000000000
> + beq x5, x1, _illegal_inst_handler_amoadd_d
> +
> + li x1, 0b01100000000000000010000000000000
> + beq x5, x1, _illegal_inst_handler_amoand_w
> +
> + li x1, 0b01100000000000000011000000000000
> + beq x5, x1, _illegal_inst_handler_amoand_d
> +
> + li x1, 0b10100000000000000010000000000000
> + beq x5, x1, _illegal_inst_handler_amomax_w
> +
> + li x1, 0b10100000000000000011000000000000
> + beq x5, x1, _illegal_inst_handler_amomax_d
> +
> + li x1, 0b11100000000000000010000000000000
> + beq x5, x1, _illegal_inst_handler_amomaxu_w
> +
> + li x1, 0b11100000000000000011000000000000
> + beq x5, x1, _illegal_inst_handler_amomaxu_d
> +
> + li x1, 0b10000000000000000010000000000000
> + beq x5, x1, _illegal_inst_handler_amomin_w
> +
> + li x1, 0b10000000000000000011000000000000
> + beq x5, x1, _illegal_inst_handler_amomin_d
> +
> + li x1, 0b11000000000000000010000000000000
> + beq x5, x1, _illegal_inst_handler_amominu_w
> +
> + li x1, 0b11000000000000000011000000000000
> + beq x5, x1, _illegal_inst_handler_amominu_d
> +
> + li x1, 0b01000000000000000010000000000000
> + beq x5, x1, _illegal_inst_handler_amoor_w
> +
> + li x1, 0b01000000000000000011000000000000
> + beq x5, x1, _illegal_inst_handler_amoor_d
> +
> + li x1, 0b00001000000000000010000000000000
> + beq x5, x1, _illegal_inst_handler_amoswap_w
> +
> + li x1, 0b00001000000000000011000000000000
> + beq x5, x1, _illegal_inst_handler_amoswap_d
> +
> + li x1, 0b00100000000000000010000000000000
> + beq x5, x1, _illegal_inst_handler_amoxor_w
> +
> + li x1, 0b00100000000000000011000000000000
> + beq x5, x1, _illegal_inst_handler_amoxor_d
> +
> + j fail
> +
> +/**
> + * Input:
> + * x3 = rs1
> + * x4 = rs2
> + * Ouput:
> + * x5 = old memory value
> + *
> + * Try LR/SC while counting down from NUM_TRIES_WITHOUT_LOCK to 0.
> + * If counter reaches 0, acquire the global lock, then repeat LR/SC,
> + * counting down from NUM_TRIES_WITHOUT_LOCK + NUM_TRIES_WITH_LOCK to
> + * NUM_TRIES_WITHOUT_LOCK + 1
> + * If counter reaches NUM_TRIES_WITHOUT_LOCK + 1 then fail completely.
> + * On LR/SC success, if counter > NUM_TRIES_WITHOUT_LOCK then we had the lock,
> + * and need to release it.
> + *
> + * Pseudocode:
> + *
> + * # Wait until not locked.
> + * while locked:
> + * pass
> + *
> + * counter = NUM_TRIES_WITHOUT_LOCK
> + * while 1:
> + * value, fail = amo()
> + * if fail: # SC fail.
> + * counter -= NUM_TRIES_WITHOUT_LOCK + 1
> + * if counter == 0:
> + * fail
> + * counter += NUM_TRIES_WITHOUT_LOCK
> + * if counter == 0:
> + * get_lock()
> + * counter = NUM_TRIES_WITH_LOCK + NUM_TRIES_WITHOUT_LOCK
> + * else: # SC pass.
> + * counter -= NUM_TRIES_WITH_LOCK
> + * if counter > 0:
> + * free_lock()
> + * return
> + */
> +
> +#define NUM_TRIES_WITHOUT_LOCK 20
> +#define NUM_TRIES_WITH_LOCK 10000
> +//#define NO_AMO_EMULATION_LOCK 1
> +
> +#if NO_AMO_EMULATION_LOCK
> +#define DO_AMO(SIZE, AMO_OPERATION...) ; \
> + /* Set mstatus.MPRV = 1, x8 = saved mstatus */ ; \
> +25: li x8, MSTATUS_MPRV ; \
> + csrrs x8, mstatus, x8 ; \
> + ; \
> +30: lr.SIZE.aq x5, (x3) ; \
> + AMO_OPERATION ; \
> + sc.SIZE.aqrl x1, x1, (x3) ; \
> + beqz x1, _illegal_inst_handler_return ; \
> + j 30b
> +#else
> +#define DO_AMO(SIZE, AMO_OPERATION...) ; \
> + /* Wait until lock is clear */ ; \
> + lla x10, amo_lock ; \
> +10: lr.d x5, (x10) ; \
> + beqz x5, 20f ; \
> + PAUSE() ; \
> + j 10b ; \
> + ; \
> +20: li x10, NUM_TRIES_WITHOUT_LOCK ; \
> + ; \
> + /* Set mstatus.MPRV = 1, x8 = saved mstatus */ ; \
> +25: li x8, MSTATUS_MPRV ; \
> + csrrs x8, mstatus, x8 ; \
> + ; \
> +30: lr.SIZE.aq x5, (x3) ; \
> + AMO_OPERATION ; \
> + sc.SIZE.aqrl x1, x1, (x3) ; \
> + beqz x1, _illegal_inst_handler_return ; \
> + /* SC failed */ ; \
> + addi x10, x10, -NUM_TRIES_WITHOUT_LOCK + 1 ; \
> + bnez x10, 40f ; \
> + csrw mstatus, x8 ; \
> + j fail ; \
> +40: addi x10, x10, NUM_TRIES_WITHOUT_LOCK ; \
> + bnez x10, 30b ; \
> + ; \
> + /* Acquire lock */ ; \
> + csrw mstatus, x8 ; \
> + lla x10, amo_lock ; \
> +50: lr.d x5, (x10) ; \
> + beqz x5, 60f ; \
> + PAUSE() ; \
> + j 50b ; \
> +60: sc.d x5, sp, (x10) /* Use sp as lock value */ ; \
> + bnez x5, 50b ; \
> + ; \
> + /* Retry with lock */ ; \
> + li x10, NUM_TRIES_WITH_LOCK + NUM_TRIES_WITHOUT_LOCK ; \
> + j 25b
> +#endif /* NO_AMO_EMULATION_LOCK */
> +
> +_illegal_inst_handler_amoadd_w:
> + DO_AMO(w, addw x1, x5, x4)
> +
> +_illegal_inst_handler_amoadd_d:
> + DO_AMO(d, add x1, x5, x4)
> +
> +_illegal_inst_handler_amoand_w:
> + DO_AMO(w, and x1, x5, x4)
> +
> +_illegal_inst_handler_amoand_d:
> + DO_AMO(d, and x1, x5, x4)
> +
> +_illegal_inst_handler_amomax_w:
> + addw x4, x4, x0
> +#if ZBB_PRESENT
> + DO_AMO(w, max x1, x5, x4)
> +#else
> + DO_AMO(w,
> + move x1, x5 ;
> + bge x5, x4, 5f ;
> + move x1, x4 ;
> +5:
> + )
> +#endif
> +
> +_illegal_inst_handler_amomax_d:
> +#if ZBB_PRESENT
> + DO_AMO(d, max x1, x5, x4)
> +#else
> + DO_AMO(d,
> + move x1, x5 ;
> + bge x5, x4, 5f ;
> + move x1, x4 ;
> +5:
> + )
> +#endif
> +
> +_illegal_inst_handler_amomaxu_w:
> + addw x4, x4, x0
> +#if ZBB_PRESENT
> + DO_AMO(w, maxu x1, x5, x4)
> +#else
> + DO_AMO(w,
> + move x1, x5 ;
> + bgeu x5, x4, 5f ;
> + move x1, x4 ;
> +5:
> + )
> +#endif
> +
> +_illegal_inst_handler_amomaxu_d:
> +#if ZBB_PRESENT
> + DO_AMO(d, maxu x1, x5, x4)
> +#else
> + DO_AMO(d,
> + move x1, x5 ;
> + bgeu x5, x4, 5f ;
> + move x1, x4 ;
> +5:
> + )
> +#endif
> +
> +_illegal_inst_handler_amomin_w:
> + addw x4, x4, x0
> +#if ZBB_PRESENT
> + DO_AMO(w, min x1, x5, x4)
> +#else
> + DO_AMO(w,
> + move x1, x5 ;
> + ble x5, x4, 5f ;
> + move x1, x4 ;
> +5:
> + )
> +#endif
> +
> +_illegal_inst_handler_amomin_d:
> +#if ZBB_PRESENT
> + DO_AMO(d, min x1, x5, x4)
> +#else
> + DO_AMO(d,
> + move x1, x5 ;
> + ble x5, x4, 5f ;
> + move x1, x4 ;
> +5:
> + )
> +#endif
> +
> +_illegal_inst_handler_amominu_w:
> + addw x4, x4, x0
> +#if ZBB_PRESENT
> + DO_AMO(w, minu x1, x5, x4)
> +#else
> + DO_AMO(w,
> + move x1, x5 ;
> + bleu x5, x4, 5f ;
> + move x1, x4 ;
> +5:
> + )
> +#endif
> +
> +_illegal_inst_handler_amominu_d:
> +#if ZBB_PRESENT
> + DO_AMO(d, minu x1, x5, x4)
> +#else
> + DO_AMO(d,
> + move x1, x5 ;
> + bleu x5, x4, 5f ;
> + move x1, x4 ;
> +5:
> + )
> +#endif
> +
> +_illegal_inst_handler_amoor_w:
> + DO_AMO(w, or x1, x5, x4)
> +
> +_illegal_inst_handler_amoor_d:
> + DO_AMO(d, or x1, x5, x4)
> +
> +_illegal_inst_handler_amoswap_w:
> + DO_AMO(w, move x1, x4)
> +
> +_illegal_inst_handler_amoswap_d:
> + DO_AMO(d, move x1, x4)
> +
> +_illegal_inst_handler_amoxor_w:
> + DO_AMO(w, xor x1, x5, x4)
> +
> +_illegal_inst_handler_amoxor_d:
> + DO_AMO(d, xor x1, x5, x4)
> +
> +_illegal_inst_handler_return:
> + csrw mstatus, x8 // Restore mstatus (undo MPRV)
> +
> +#if NO_AMO_EMULATION_LOCK
> +#else
> + /* Clear amo_lock if we had acquired it. */
> + addi x10, x10, -NUM_TRIES_WITHOUT_LOCK
> + blez x10, 10f
> + lla x10, amo_lock
> + sd x0, (x10)
> +10:
> +#endif /* NO_AMO_EMULATION_LOCK */
> +
> + /* write rd with value in x5 */
> + lla x4, write_xr_amo // x4 = base address of write_xr funcs
> + srli x3, x9, 7 - JUMP_TABLE_SHIFT // Align rd idx as table offset
> + andi x3, x3, 0x1f << JUMP_TABLE_SHIFT // Isolate aligned rd
> + add x1, x4, x3 // Apply offset to jump table
> + jalr x1 // Call func to write x5 to rd
> +
> + addi x6, x6, 4 // Saved mepc += 4 (skip emulated instruction)
> +
> +_illegal_inst_handler_mret:
> + csrw mepc, x6 // Restore mepc
> + csrw mtvec, x7 // Restore mtvec
> +
> + /* Restore working set of XRs */
> + ld x1, (O_amo_scratch + 0 * 8)(sp)
> + ld x3, (O_amo_scratch + 2 * 8)(sp)
> + ld x4, (O_amo_scratch + 3 * 8)(sp)
> + ld x5, (O_amo_scratch + 4 * 8)(sp)
> + ld x6, (O_amo_scratch + 5 * 8)(sp)
> + ld x7, (O_amo_scratch + 6 * 8)(sp)
> + ld x8, (O_amo_scratch + 7 * 8)(sp)
> + ld x9, (O_amo_scratch + 8 * 8)(sp)
> + ld x10, (O_amo_scratch + 9 * 8)(sp)
> + ld sp, (O_amo_scratch + 1 * 8)(sp) /* restore sp last */
> +
> + mret // Return
> +
> + .align 2
> +_illegal_inst_mtvec_handler:
> + /*
> + * If any exception occurs on a load/store during AMO emulation,
> + * just re-execute the original faulting AMO. This will regenerate
> + * the exception (page fault, access fault) and allow it to
> + * be handled as though from the original context
> + */
> + csrw mstatus, x8 // Restore mstatus
> +
> + csrr x5, mcause
> +
> + li x1, CAUSE_LOAD_PAGE_FAULT
> + beq x5, x1, _illegal_inst_handler_mret
> +
> + li x1, CAUSE_STORE_PAGE_FAULT
> + beq x5, x1, _illegal_inst_handler_mret
> +
> + li x1, CAUSE_GUEST_LOAD_PAGE_FAULT
> + beq x5, x1, _illegal_inst_handler_mret
> +
> + li x1, CAUSE_GUEST_STORE_PAGE_FAULT
> + beq x5, x1, _illegal_inst_handler_mret
> +
> + li x1, CAUSE_LOAD_ACCESS
> + beq x5, x1, _illegal_inst_handler_mret
> +
> + li x1, CAUSE_STORE_ACCESS
> + beq x5, x1, _illegal_inst_handler_mret
> +
> + // An unexpected exception during AMO emulation is fatal.
> + j fail
> +
> +/**
> + * This is a table of 32 functions.
> + * Calling the function read_xr_amo + rd * JUMP_TABLE_OFFSET does
> + * x4 = XR[rd]. For xrs where the value is stored in memory by the AMO handler,
> + * do x4 = MEM[address where $rd is stored], which has the equivalent effect.
> + */
> +read_xr_amo:
> + li x4, 0 ; jr ra
> + ld x4, (O_amo_scratch + 0 * 8)(sp) ; jr ra
> + ld x4, (O_amo_scratch + 1 * 8)(sp) ; jr ra
> + ld x4, (O_amo_scratch + 2 * 8)(sp) ; jr ra
> + ld x4, (O_amo_scratch + 3 * 8)(sp) ; jr ra
> + ld x4, (O_amo_scratch + 4 * 8)(sp) ; jr ra
> + ld x4, (O_amo_scratch + 5 * 8)(sp) ; jr ra
> + ld x4, (O_amo_scratch + 6 * 8)(sp) ; jr ra
> + ld x4, (O_amo_scratch + 7 * 8)(sp) ; jr ra
> + ld x4, (O_amo_scratch + 8 * 8)(sp) ; jr ra
> + ld x4, (O_amo_scratch + 9 * 8)(sp) ; jr ra
> + move x4, x11 ; jr ra
> + move x4, x12 ; jr ra
> + move x4, x13 ; jr ra
> + move x4, x14 ; jr ra
> + move x4, x15 ; jr ra
> + move x4, x16 ; jr ra
> + move x4, x17 ; jr ra
> + move x4, x18 ; jr ra
> + move x4, x19 ; jr ra
> + move x4, x20 ; jr ra
> + move x4, x21 ; jr ra
> + move x4, x22 ; jr ra
> + move x4, x23 ; jr ra
> + move x4, x24 ; jr ra
> + move x4, x25 ; jr ra
> + move x4, x26 ; jr ra
> + move x4, x27 ; jr ra
> + move x4, x28 ; jr ra
> + move x4, x29 ; jr ra
> + move x4, x30 ; jr ra
> + move x4, x31 ; jr ra
> +
> +/**
> + * This is a table of 32 functions.
> + * Calling the function write_xr_amo + rd * JUMP_TABLE_OFFSET does:
> + * XR[rd] = x5. For xrs which will be restored from memory at the end of
> + * the AMO handler, do MEM[address where $rd is stored] = x5.
> + */
> +write_xr_amo:
> + jr ra ; jr ra
> + sd x5, (O_amo_scratch + 0 * 8)(sp) ; jr ra
> + sd x5, (O_amo_scratch + 1 * 8)(sp) ; jr ra
> + sd x5, (O_amo_scratch + 2 * 8)(sp) ; jr ra
> + sd x5, (O_amo_scratch + 3 * 8)(sp) ; jr ra
> + sd x5, (O_amo_scratch + 4 * 8)(sp) ; jr ra
> + sd x5, (O_amo_scratch + 5 * 8)(sp) ; jr ra
> + sd x5, (O_amo_scratch + 6 * 8)(sp) ; jr ra
> + sd x5, (O_amo_scratch + 7 * 8)(sp) ; jr ra
> + sd x5, (O_amo_scratch + 8 * 8)(sp) ; jr ra
> + sd x5, (O_amo_scratch + 9 * 8)(sp) ; jr ra
> + move x11, x5 ; jr ra
> + move x12, x5 ; jr ra
> + move x13, x5 ; jr ra
> + move x14, x5 ; jr ra
> + move x15, x5 ; jr ra
> + move x16, x5 ; jr ra
> + move x17, x5 ; jr ra
> + move x18, x5 ; jr ra
> + move x19, x5 ; jr ra
> + move x20, x5 ; jr ra
> + move x21, x5 ; jr ra
> + move x22, x5 ; jr ra
> + move x23, x5 ; jr ra
> + move x24, x5 ; jr ra
> + move x25, x5 ; jr ra
> + move x26, x5 ; jr ra
> + move x27, x5 ; jr ra
> + move x28, x5 ; jr ra
> + move x29, x5 ; jr ra
> + move x30, x5 ; jr ra
> + move x31, x5 ; jr ra
> +
> +/**
> + * This is a table of 32 functions.
> + * Calling the function write_xr_rdtime + rd * JUMP_TABLE_OFFSET does:
> + * XR[rd] = x3. For xrs which will be restored from memory at the end of
> + * the rdtime handler, do MEM[address where $rd is stored] = x3.
> + */
> +write_xr_rdtime:
> + jr ra ; jr ra
> + sd x3, O_satp_vsatp_scratch0(sp) ; jr ra
> + j _write_xr_rdtime_x1 ; jr ra
> + sd x3, O_satp_vsatp_scratch1(sp) ; jr ra
> + move x4, x3 ; jr ra
> + move x5, x3 ; jr ra
> + move x6, x3 ; jr ra
> + move x7, x3 ; jr ra
> + move x8, x3 ; jr ra
> + move x9, x3 ; jr ra
> + move x10, x3 ; jr ra
> + move x11, x3 ; jr ra
> + move x12, x3 ; jr ra
> + move x13, x3 ; jr ra
> + move x14, x3 ; jr ra
> + move x15, x3 ; jr ra
> + move x16, x3 ; jr ra
> + move x17, x3 ; jr ra
> + move x18, x3 ; jr ra
> + move x19, x3 ; jr ra
> + move x20, x3 ; jr ra
> + move x21, x3 ; jr ra
> + move x22, x3 ; jr ra
> + move x23, x3 ; jr ra
> + move x24, x3 ; jr ra
> + move x25, x3 ; jr ra
> + move x26, x3 ; jr ra
> + move x27, x3 ; jr ra
> + move x28, x3 ; jr ra
> + move x29, x3 ; jr ra
> + move x30, x3 ; jr ra
> + move x31, x3 ; jr ra
> +_write_xr_rdtime_x1:
> + csrw mscratch, x3 ; jr ra
> +
> +fail:
> + unimp
> +
> + .section .sbss
> + .align 6
> + .type amo_lock, @object
> + .size amo_lock, 64
> +amo_lock:
> + .zero 64
> --
> 2.47.1
>
>
> --
> opensbi mailing list
> opensbi@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply [flat|nested] 70+ messages in thread
* Re: [PATCH v2 04/11] platform: generic: mips: add custom exception handler
2025-03-28 4:53 ` Anup Patel
@ 2025-04-08 2:49 ` Chao-ying Fu
0 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-04-08 2:49 UTC (permalink / raw)
To: Anup Patel; +Cc: opensbi, Chao-ying Fu
On Thu, Mar 27, 2025 at 9:54 PM Anup Patel <anup@brainfault.org> wrote:
>
> On Wed, Feb 26, 2025 at 7:38 AM Chao-ying Fu <icebergfu@gmail.com> wrote:
> >
> > Add the custom exception handler to implement software table walker,
> > rdtime emulation, and AMO instruction emulation.
>
> I find it hard to justify this custom MIPS specific exception handler. Looks
> like the intention here is to simply dump whatever makes it work under
> mips directory.
The purposes are to speed up the exception handling for AMO
instructions and CSR read of the time register,
and for the software table walker functionality.
As we can change to use RISC-V illegal instruction exceptions for
AMO instructions and RDTIME and enable hardware table walker,
we will not include stw.S and stw.h and we will not use extra scratch space.
However, there are no AMO instruction handler in OpenSBI, so we will
need to add this to OpenSBI code base later.
Thanks a lot!
Regards,
Chao-ying
>
> Regards,
> Anup
>
> > ---
> > platform/generic/include/mips/stw.h | 191 ++++++
> > platform/generic/mips/stw.S | 986 ++++++++++++++++++++++++++++
> > 2 files changed, 1177 insertions(+)
> > create mode 100644 platform/generic/include/mips/stw.h
> > create mode 100644 platform/generic/mips/stw.S
> >
> > diff --git a/platform/generic/include/mips/stw.h b/platform/generic/include/mips/stw.h
> > new file mode 100644
> > index 0000000..bdcacc3
> > --- /dev/null
> > +++ b/platform/generic/include/mips/stw.h
> > @@ -0,0 +1,191 @@
> > +/*
> > + * SPDX-License-Identifier: BSD-2-Clause
> > + *
> > + * Copyright (c) 2025 MIPS
> > + *
> > +
> > +Some lines of this code have been copied from
> > +https://github.com/riscv/riscv-tests and are used in accordance with following
> > +license:
> > +
> > +Copyright (c) 2012-2015, The Regents of the University of California (Regents).
> > +All Rights Reserved.
> > +
> > +Redistribution and use in source and binary forms, with or without
> > +modification, are permitted provided that the following conditions are met:
> > +1. Redistributions of source code must retain the above copyright
> > + notice, this list of conditions and the following disclaimer.
> > +2. Redistributions in binary form must reproduce the above copyright
> > + notice, this list of conditions and the following disclaimer in the
> > + documentation and/or other materials provided with the distribution.
> > +3. Neither the name of the Regents nor the
> > + names of its contributors may be used to endorse or promote products
> > + derived from this software without specific prior written permission.
> > +
> > +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
> > +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
> > +OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
> > +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> > +
> > +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
> > +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
> > +PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
> > +HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
> > +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
> > +
> > +*/
> > +
> > +#include <sbi/sbi_scratch.h>
> > +#undef MSTATUS_MPRV
> > +#undef SATP_MODE_OFF
> > +#undef SATP_MODE_SV32
> > +#undef SATP_MODE_SV39
> > +#undef SATP_MODE_SV48
> > +#undef SATP_MODE_SV57
> > +#undef SATP_MODE_SV64
> > +#undef MSTATUS_MPV
> > +
> > +#define CAUSE_ILLEGAL_INST 2
> > +#define CAUSE_LOAD_ACCESS 0x5
> > +#define CAUSE_STORE_ACCESS 0x7
> > +#define CAUSE_LOAD_PAGE_FAULT 0xd
> > +#define CAUSE_STORE_PAGE_FAULT 0xf
> > +#define CAUSE_GUEST_LOAD_PAGE_FAULT 21
> > +#define CAUSE_GUEST_STORE_PAGE_FAULT 23
> > +#define CAUSE_READ_TIME 26
> > +#define CAUSE_GUEST_TLB_MISS 28
> > +#define MSTATUS_MPRV 0x00020000
> > +#define vsatp 0x280
> > +#define mtval2 0x34b
> > +#define hgatp 0x680
> > +
> > +#define SATP_MODE_OFF 0
> > +#define SATP_MODE_SV32 1
> > +#define SATP_MODE_SV39 8
> > +#define SATP_MODE_SV48 9
> > +#define SATP_MODE_SV57 10
> > +#define SATP_MODE_SV64 11
> > +#define mstatus_GVA_LSB 38
> > +#define PTE_V 0x001 /* Valid */
> > +#define PTE_R 0x002 /* Read */
> > +#define PTE_W 0x004 /* Write */
> > +#define PTE_X 0x008 /* Execute */
> > +#define PTE_U 0x010 /* User */
> > +#define PTE_G 0x020 /* Global */
> > +#define PTE_A 0x040 /* Accessed */
> > +#define PTE_D 0x080 /* Dirty */
> > +#define PTE_N 0x8000000000000000 /* Napot */
> > +#define PTE_RSVD 0x7fc0000000000000 /* RSVD */
> > +#define mstatus_MPV_MSB 39
> > +#define mstatus_MPV_LSB 39
> > +#define MSTATUS_MPV ALIGN_FIELD(-1, mstatus_MPV)
> > +
> > +/* Return value aligned at [msb:lsb]. */
> > +#define ALIGN(value, msb, lsb) (((value) & ((1 << (1 + msb - lsb)) - 1)) << lsb)
> > +
> > +/* Return value aligned at named field, i.e. [<field>_MSB:<field>_LSB]. */
> > +#define ALIGN_FIELD(value, field) ALIGN(value, field##_MSB, field##_LSB)
> > +
> > +/* rd = rs[max:min] */
> > +#define extract(rd, rs, max, min) ; \
> > + slli rd, rs, __riscv_xlen - 1 - max ; \
> > + srli rd, rd, __riscv_xlen - 1 - max + min
> > +
> > +/**
> > + * GPR numbers of named gprs, for passing named gprs to instruction definitions.
> > + */
> > +#define gpr_idx_x0 0
> > +#define gpr_idx_x1 1
> > +#define gpr_idx_sp 2
> > +#define gpr_idx_gp 3
> > +#define gpr_idx_tp 4
> > +#define gpr_idx_t0 5
> > +#define gpr_idx_t1 6
> > +#define gpr_idx_t2 7
> > +#define gpr_idx_s0 8
> > +#define gpr_idx_fp 8
> > +#define gpr_idx_s1 9
> > +#define gpr_idx_a0 10
> > +#define gpr_idx_a1 11
> > +#define gpr_idx_a2 12
> > +#define gpr_idx_a3 13
> > +#define gpr_idx_a4 14
> > +#define gpr_idx_a5 15
> > +#define gpr_idx_a6 16
> > +#define gpr_idx_a7 17
> > +#define gpr_idx_s2 18
> > +#define gpr_idx_s3 19
> > +#define gpr_idx_s4 20
> > +#define gpr_idx_s5 21
> > +#define gpr_idx_s6 22
> > +#define gpr_idx_s7 23
> > +#define gpr_idx_s8 24
> > +#define gpr_idx_s9 25
> > +#define gpr_idx_s10 26
> > +#define gpr_idx_s11 27
> > +#define gpr_idx_t3 28
> > +#define gpr_idx_t4 29
> > +#define gpr_idx_t5 30
> > +#define gpr_idx_t6 31
> > +
> > +#define GPR_IDX(rs) _GPR_IDX(rs)
> > +#define _GPR_IDX(rs) gpr_idx_##rs
> > +
> > +#if BIGENDIAN
> > +#define IWORD(x) ; \
> > + .byte (x) & 0xff ; \
> > + .byte (x)>>8 & 0xff ; \
> > + .byte (x)>>16 & 0xff ; \
> > + .byte (x)>>24 & 0xff
> > +#else
> > + #define IWORD(x) .word x
> > +#endif
> > +
> > +#define MTLBWR(rs1, level) \
> > + IWORD(0b11101100000000000000000001110011 | GPR_IDX(rs1)<<15 | level<<20)
> > +
> > +#define MTLBWR_HG(rs1, level) \
> > + IWORD(0b11101100100000000000000001110011 | GPR_IDX(rs1)<<15 | level<<20)
> > +
> > +#define PAUSE_ZIHINTPAUSE() \
> > + IWORD(0b00000001000000000000000000001111)
> > +
> > +#define PAUSE_MIPS() \
> > + IWORD(0b00000000010100000001000000010011)
> > +
> > +#if ZIHINTPAUSE
> > + #define PAUSE() PAUSE_ZIHINTPAUSE()
> > +#else
> > + #define PAUSE() PAUSE_MIPS()
> > +#endif
> > +
> > +#define base (15 << 3) /* This should match SBI_SCRATCH_STW_TMP_OFFSET. */
> > +#if base != SBI_SCRATCH_STW_TMP_OFFSET
> > + #error WRONG base for STW
> > +#endif
> > +#define O_tmp0 (base + (0 << 3))
> > +#define O_save_x1 (base + (1 << 3))
> > +#define O_satp_vsatp_scratch0 (base + (2 << 3))
> > +#define O_satp_vsatp_scratch1 (base + (3 << 3))
> > +#define O_satp_vsatp_scratch2 (base + (4 << 3))
> > +#define O_satp_vsatp_scratch3 (base + (5 << 3))
> > +#define O_satp_vsatp_scratch4 (base + (6 << 3))
> > +#define O_satp_vsatp_scratch5 (base + (7 << 3))
> > +#define O_satp_vsatp_scratch6 (base + (8 << 3))
> > +#define O_satp_vsatp_scratch7 (base + (9 << 3))
> > +#define O_satp_vsatp_scratch8 (base + (10 << 3))
> > +#define O_hgatp_scratch0 (base + (11 << 3))
> > +#define O_hgatp_scratch1 (base + (12 << 3))
> > +#define O_hgatp_scratch2 (base + (13 << 3))
> > +#define O_hgatp_scratch3 (base + (14 << 3))
> > +#define O_hgatp_scratch4 (base + (15 << 3))
> > +#define O_hgatp_scratch5 (base + (16 << 3))
> > +#define O_amo_scratch (base + (17 << 3)) /* Points to 17 dwords */
> > +
> > +#ifdef __riscv_compressed
> > + #define JUMP_TABLE_SHIFT 2
> > + #define JUMP_TABLE_OFFSET 4
> > +#else
> > + #define JUMP_TABLE_SHIFT 3
> > + #define JUMP_TABLE_OFFSET 8
> > +#endif
> > diff --git a/platform/generic/mips/stw.S b/platform/generic/mips/stw.S
> > new file mode 100644
> > index 0000000..e032372
> > --- /dev/null
> > +++ b/platform/generic/mips/stw.S
> > @@ -0,0 +1,986 @@
> > +/*
> > + * SPDX-License-Identifier: BSD-2-Clause
> > + *
> > + * Copyright (c) 2025 MIPS
> > + *
> > + * This file implements MIPS custom exception handler for software table walker
> > + * when hardware table walker is disabled or not available, rdtime emulation,
> > + * and AMO instruction emulation.
> > + */
> > +
> > +/* Define STW_TLB_4KB to force to use 4KB pages in every level for software table walker.
> > + This is for debugging only. */
> > +//#define STW_TLB_4KB 1
> > +
> > +#include <mips/stw.h>
> > +#include <mips/board.h>
> > +#include <mips/p8700.h>
> > +
> > +#if defined(__riscv_zbb)
> > +#define ZBB_PRESENT 1
> > +#endif
> > +
> > + .text
> > + .align 8
> > + .globl mipstvec_handler_stw
> > +mipstvec_handler_stw:
> > + j mipstvec_handler_stw_not_vec ; .align 2 /* 0 */
> > + j fail ; .align 2 /* 1 */
> > + j illegal_inst_handler ; .align 2 /* 2 */
> > + j fail ; .align 2 /* 3 */
> > + j fail ; .align 2 /* 4 */
> > + j htw_load_access_fault_handler ; .align 2 /* 5 */
> > + j fail ; .align 2 /* 6 */
> > + j fail ; .align 2 /* 7 */
> > + j fail ; .align 2 /* 8 */
> > + j fail ; .align 2 /* 9 */
> > + j fail ; .align 2 /* 10 */
> > + j fail ; .align 2 /* 11 */
> > + j fail ; .align 2 /* 12 */
> > + j fail ; .align 2 /* 13 */
> > + j fail ; .align 2 /* 14 */
> > + j fail ; .align 2 /* 15 */
> > + j fail ; .align 2 /* 16 */
> > + j fail ; .align 2 /* 17 */
> > + j fail ; .align 2 /* 18 */
> > + j fail ; .align 2 /* 19 */
> > + j fail ; .align 2 /* 20 */
> > + j htw_page_fault_handler ; .align 2 /* 21 */
> > + j fail ; .align 2 /* 22 */
> > + j fail ; .align 2 /* 23 */
> > + j satp_refill_handler ; .align 2 /* 24 */
> > + j satp_refill_handler ; .align 2 /* 25 */
> > + j read_time_handler ; .align 2 /* 26 */
> > + j satp_refill_handler ; .align 2 /* 27 */
> > + j hgatp_refill_handler ; .align 2 /* 28 */
> > + j hgatp_refill_handler ; .align 2 /* 29 */
> > + j read_time_handler ; .align 2 /* 30 */
> > + j hgatp_refill_handler ; .align 2 /* 31 */
> > +
> > +mipstvec_handler_stw_not_vec:
> > + csrci CSR_MIPSCONFIG5, MIPSCONFIG5_MTW
> > + csrrw sp, mscratch, sp // Save sp to mscratch, load mscratch to sp
> > + sd x1, O_save_x1(sp) // Save x1 to memory
> > + csrr x1, mcause // Read mcause
> > +
> > +#define _mipstvec_handler_dispatch(i) ; \
> > + addi x1, x1, -i ; \
> > + bnez x1, 10f ; \
> > + ld x1, O_save_x1(sp) ; \
> > + csrrw sp, mscratch, sp ; \
> > + j mipstvec_handler_stw + 4 * i ; \
> > +10: addi x1, x1, i
> > +
> > +#define _mipstvec_handler_dispatch_mtw(i) ; \
> > + addi x1, x1, -i ; \
> > + bnez x1, 10f ; \
> > + ld x1, O_save_x1(sp) ; \
> > + csrrw sp, mscratch, sp ; \
> > + csrsi CSR_MIPSCONFIG5, MIPSCONFIG5_MTW ; \
> > + j mipstvec_handler_stw + 4 * i ; \
> > +10: addi x1, x1, i
> > +
> > + _mipstvec_handler_dispatch(2)
> > + _mipstvec_handler_dispatch(20)
> > + _mipstvec_handler_dispatch(21)
> > + _mipstvec_handler_dispatch(23)
> > + _mipstvec_handler_dispatch(24)
> > + _mipstvec_handler_dispatch(25)
> > + _mipstvec_handler_dispatch(26)
> > + _mipstvec_handler_dispatch(27)
> > + _mipstvec_handler_dispatch_mtw(28)
> > + _mipstvec_handler_dispatch_mtw(29)
> > + _mipstvec_handler_dispatch_mtw(30)
> > + _mipstvec_handler_dispatch_mtw(31)
> > + j fail
> > +
> > +satp_refill_handler:
> > +vsatp_refill_handler:
> > + csrrw sp, mscratch, sp /* sp = mscratch; mscratch = saved sp */
> > + sd t0, O_satp_vsatp_scratch0(sp) /* save t0 */
> > + csrrw t0, mscratch, sp /* t0 = saved sp; restore mscratch */
> > + sd t0, O_satp_vsatp_scratch8(sp) /* save sp */
> > + sd t1, O_satp_vsatp_scratch1(sp) /* save t1 */
> > + sd t2, O_satp_vsatp_scratch2(sp) /* save t2 */
> > + sd t3, O_satp_vsatp_scratch3(sp) /* save t3 */
> > + sd s4, O_satp_vsatp_scratch4(sp) /* save s4 */
> > + sd t5, O_satp_vsatp_scratch5(sp) /* save t5 */
> > + sd t6, O_satp_vsatp_scratch6(sp) /* save t6 */
> > + sd s7, O_satp_vsatp_scratch7(sp) /* save s7 */
> > +
> > + /* Save mstatus, mepc (not actually needed for non-vmode refill) */
> > + csrr s4, mstatus
> > + csrr t5, mepc
> > + csrrsi t6, CSR_MIPSCONFIG5, MIPSCONFIG5_MTW /* set MTW bit */
> > +
> > + /* Only V can be set out of following bits for PTE to be non-leaf */
> > + li s7, PTE_V | PTE_R | PTE_W | PTE_X | PTE_U | PTE_A | PTE_D | PTE_N | PTE_RSVD
> > +
> > +_read_xsatp:
> > + /* t1 = vsatp if vmode exception (mstatus.GVA=1) else satp */
> > + sll t3, s4, __riscv_xlen - 1 - mstatus_GVA_LSB
> > + bgez t3, 1f
> > + csrr t3, vsatp
> > + j 2f
> > +1: csrr t3, satp
> > +2:
> > +
> > +_find_xsatp_mode:
> > + slli t0, t3, 20 // t0 = satp.PPN << 20 (clear out MODE, ASID)
> > + srli t0, t0, 8 // "a" = t0 = satp.PPN << 12 (i.e. * PAGESIZE)
> > + li t1, 0 // Is this PTE global? (Need to track during walk).
> > + csrr t2, mtval // va
> > +
> > + // Branch according to xsatp.MODE
> > + srli t3, t3, 60
> > + addi t3, t3, -SATP_MODE_SV39
> > + beqz t3, _xsatp_Sv39_level2 // Sv39
> > + addi t3, t3, SATP_MODE_SV39 - SATP_MODE_SV48
> > + beqz t3, _xsatp_Sv39_level3 // Sv48
> > + j fail
> > +
> > +_xsatp_Sv39_level3:
> > + extract (t3, t2, 47, 39) // t3 = VPN[2]
> > + slli t3, t3, 3 // t3 = VPN[2] * PTESIZE
> > + add t0, t0, t3 // t0 = a + VPN[2] * PTESIZE
> > + ld t0, 0(t0) // t0 = PTE
> > + and t3, t0, s7
> > + xori t3, t3, PTE_V
> > + bnez t3, _xsatp_level3_leaf
> > + andi t3, t0, PTE_G
> > + or t1, t1, t3
> > + extract (t0, t0, 53, 10) // t0 = PTE[53:10]
> > + slli t0, t0, 12 // "a" = t0 = PTE[53:10] * PAGESIZE
> > +
> > +_xsatp_Sv39_level2:
> > + extract (t3, t2, 38, 30) // t3 = VPN[2]
> > + slli t3, t3, 3 // t3 = VPN[2] * PTESIZE
> > + add t0, t0, t3 // t0 = a + VPN[2] * PTESIZE
> > + ld t0, 0(t0) // t0 = PTE
> > + and t3, t0, s7
> > + xori t3, t3, PTE_V
> > + bnez t3, _xsatp_level2_leaf
> > + andi t3, t0, PTE_G
> > + or t1, t1, t3
> > + extract (t0, t0, 53, 10) // t0 = PTE[53:10]
> > + slli t0, t0, 12 // "a" = t0 = PTE[53:10] * PAGESIZE
> > +
> > +_xsatp_Sv39_level1:
> > + extract (t3, t2, 29, 21) // t3 = VPN[2]
> > + slli t3, t3, 3 // t3 = VPN[2] * PTESIZE
> > + add t0, t0, t3 // t0 = a + VPN[2] * PTESIZE
> > + ld t0, 0(t0) // t0 = PTE
> > + and t3, t0, s7
> > + xori t3, t3, PTE_V
> > + bnez t3, _xsatp_level1_leaf
> > + andi t3, t0, PTE_G
> > + or t1, t1, t3
> > + extract (t0, t0, 53, 10) // t0 = PTE[53:10]
> > + slli t0, t0, 12 // "a" = t0 = PTE[53:10] * PAGESIZE
> > +
> > +_xsatp_Sv39_level0:
> > + extract (t3, t2, 20, 13) // t3 = VPN[2] (even page)
> > + slli t3, t3, 4 // t3 = VPN[2] (even page) * 2 * PTESIZE
> > + add t0, t0, t3 // t0 = a + VPN[2] (even page) 2 * PTESIZE
> > + ld t3, 0(t0) // t3 = even PTE
> > + ld t0, 8(t0) // t0 = odd PTE
> > +
> > +_xsatp_level0_leaf:
> > + or t3, t3, t1 // global if parent table is global
> > + or t0, t0, t1 // global if parent table is global
> > + li t1, 0x1000 // even/odd bit
> > + or t2, t2, t1 // Odd page mtval
> > + csrw mtval, t2
> > + MTLBWR (t0, 0) // Write odd PTE to TLB
> > + csrc mtval, t1 // Even page mtval
> > + MTLBWR (t3, 0) // Write even PTE to TLB
> > +
> > +_xsatp_mret:
> > + csrw mstatus, s4 /* Restore mstatus */
> > + csrw mepc, t5 /* Restore mepc */
> > + csrw CSR_MIPSCONFIG5, t6 /* Restore mipsconfig5 */
> > +
> > + ld t0, O_satp_vsatp_scratch0(sp) /* restore t0 */
> > + ld t1, O_satp_vsatp_scratch1(sp) /* restore t1 */
> > + ld t2, O_satp_vsatp_scratch2(sp) /* restore t2 */
> > + ld t3, O_satp_vsatp_scratch3(sp) /* restore t3 */
> > + ld s4, O_satp_vsatp_scratch4(sp) /* restore s4 */
> > + ld t5, O_satp_vsatp_scratch5(sp) /* restore t5 */
> > + ld t6, O_satp_vsatp_scratch6(sp) /* restore t6 */
> > + ld s7, O_satp_vsatp_scratch7(sp) /* restore sp */
> > + ld sp, O_satp_vsatp_scratch8(sp) /* restore sp */
> > +
> > + mret
> > +
> > +_xsatp_level1_leaf:
> > + or t0, t0, t1 // global if parent table is global
> > +#ifdef STW_TLB_4KB
> > + extract (t3, t2, 20, 12)
> > + sll t3, t3, 10
> > + or t0, t0, t3
> > + csrw mtval, t2
> > + MTLBWR (t0, 0)
> > +#else
> > + csrw mtval, t2
> > + MTLBWR (t0, 1)
> > +#endif
> > + j _xsatp_mret
> > +
> > +_xsatp_level2_leaf:
> > + or t0, t0, t1 // global if parent table is global
> > +#ifdef STW_TLB_4KB
> > + extract (t3, t2, 29, 12)
> > + sll t3, t3, 10
> > + or t0, t0, t3
> > + csrw mtval, t2
> > + MTLBWR (t0, 0)
> > +#else
> > + csrw mtval, t2
> > + MTLBWR (t0, 2)
> > +#endif
> > + j _xsatp_mret
> > +
> > +_xsatp_level3_leaf:
> > + or t0, t0, t1 // global if parent table is global
> > +#ifdef STW_TLB_4KB
> > + extract (t3, t2, 38, 12)
> > + sll t3, t3, 10
> > + or t0, t0, t3
> > + csrw mtval, t2
> > + MTLBWR (t0, 0)
> > +#else
> > + csrw mtval, t2
> > + MTLBWR (t0, 3)
> > +#endif
> > + j _xsatp_mret
> > +
> > +hgatp_refill_handler:
> > + csrrw sp, mscratch, sp /* sp = mscratch; mscratch = saved sp */
> > + sd t0, O_hgatp_scratch0(sp) /* save t0 */
> > + csrrw t0, mscratch, sp /* t0 = saved sp; restore mscratch */
> > + sd t0, O_hgatp_scratch5(sp) /* save sp */
> > + sd t1, O_hgatp_scratch1(sp) /* save t1 */
> > + sd t2, O_hgatp_scratch2(sp) /* save t2 */
> > + sd t3, O_hgatp_scratch3(sp) /* save t3 */
> > + sd s4, O_hgatp_scratch4(sp) /* save s4 */
> > +
> > + /* Only V can be set out of following bits for PTE to be non-leaf */
> > + li s4, PTE_V | PTE_R | PTE_W | PTE_X | PTE_U | PTE_A | PTE_D | PTE_N | PTE_RSVD
> > +
> > + /* set MTW=1 */
> > + csrsi CSR_MIPSCONFIG5, MIPSCONFIG5_MTW
> > +
> > +_find_hgatp_mode:
> > + csrr t3, hgatp
> > + slli t0, t3, 20 // t0 = hgatp.PPN << 20 (clear out MODE, ASID)
> > + srli t0, t0, 8 // "a" = t0 = hgatp.PPN << 12 (i.e. * PAGESIZE)
> > + li t1, 0 // Is this PTE global? (Need to track during walk).
> > + csrr t2, mtval // gpa
> > +
> > + // Branch according to hgatp.MODE
> > + srli t3, t3, 60
> > + addi t3, t3, -SATP_MODE_SV39
> > + bnez t3, 1f
> > + extract (t3, t2, 38, 28) // t3 = VPN[2]
> > + j _hgatp_Sv39x4_level2_got_vpn2
> > +1: addi t3, t3, SATP_MODE_SV39 - SATP_MODE_SV48
> > + beqz t3, _hgatp_Sv39x4_level3
> > + j fail
> > +
> > +_hgatp_Sv39x4_level3:
> > + extract (t3, t2, 47, 37) // t3 = VPN[2]
> > + slli t3, t3, 3 // t3 = VPN[2] * PTESIZE
> > + add t0, t0, t3 // t0 = a + VPN[2] * PTESIZE
> > + ld t0, 0(t0) // t0 = PTE
> > + and t3, t0, s4
> > + xori t3, t3, PTE_V
> > + bnez t3, _hgatp_level3_leaf
> > + andi t3, t0, PTE_G
> > + or t1, t1, t3
> > + extract (t0, t0, 53, 10) // t0 = PTE[53:10]
> > + slli t0, t0, 12 // "a" = t0 = PTE[53:10] * PAGESIZE
> > +
> > +_hgatp_Sv39x4_level2:
> > + extract (t3, t2, 36, 28) // t3 = VPN[2]
> > +_hgatp_Sv39x4_level2_got_vpn2:
> > + slli t3, t3, 3 // t3 = VPN[2] * PTESIZE
> > + add t0, t0, t3 // t0 = a + VPN[2] * PTESIZE
> > + ld t0, 0(t0) // t0 = PTE
> > + and t3, t0, s4
> > + xori t3, t3, PTE_V
> > + bnez t3, _hgatp_level2_leaf
> > + andi t3, t0, PTE_G
> > + or t1, t1, t3
> > + extract (t0, t0, 53, 10) // t0 = PTE[53:10]
> > + slli t0, t0, 12 // "a" = t0 = PTE[53:10] * PAGESIZE
> > +
> > +_hgatp_Sv39x4_level1:
> > + extract (t3, t2, 27, 19) // t3 = VPN[2]
> > + slli t3, t3, 3 // t3 = VPN[2] * PTESIZE
> > + add t0, t0, t3 // t0 = a + VPN[2] * PTESIZE
> > + ld t0, 0(t0) // t0 = PTE
> > + and t3, t0, s4
> > + xori t3, t3, PTE_V
> > + bnez t3, _hgatp_level1_leaf
> > + andi t3, t0, PTE_G
> > + or t1, t1, t3
> > + extract (t0, t0, 53, 10) // t0 = PTE[53:10]
> > + slli t0, t0, 12 // "a" = t0 = PTE[53:10] * PAGESIZE
> > +
> > +_hgatp_Sv39x4_level0:
> > + extract (t3, t2, 18, 11) // t3 = VPN[2] (even page)
> > + slli t3, t3, 4 // t3 = VPN[2] (even page) * 2 * PTESIZE
> > + add t0, t0, t3 // t0 = a + VPN[2] (even page) 2 * PTESIZE
> > + ld t2, 0(t0) // t2 = even PTE
> > + ld t3, 8(t0) // t3 = odd PTE
> > +
> > +_hgatp_level0_leaf:
> > + or t2, t2, t1 // global if parent table is global
> > + or t3, t3, t1 // global if parent table is global
> > + li t0, 0x0400 // even/odd bit
> > + csrc mtval, t0
> > + MTLBWR_HG (t2, 0)
> > + csrs mtval, t0
> > + MTLBWR_HG (t3, 0)
> > +
> > +_hgatp_mret:
> > + csrci CSR_MIPSCONFIG5, MIPSCONFIG5_MTW /* Clear MTW bit */
> > +
> > + ld t0, O_hgatp_scratch0(sp) /* restore t0 */
> > + ld t1, O_hgatp_scratch1(sp) /* restore t1 */
> > + ld t2, O_hgatp_scratch2(sp) /* restore t2 */
> > + ld t3, O_hgatp_scratch3(sp) /* restore t3 */
> > + ld s4, O_hgatp_scratch4(sp) /* restore s4 */
> > + ld sp, O_hgatp_scratch5(sp) /* restore sp */
> > +
> > + mret
> > +
> > +_hgatp_level1_leaf:
> > + or t0, t0, t1 // global if parent table is global
> > +#ifdef STW_TLB_4KB
> > + extract (t3, t2, 20, 12)
> > + sll t3, t3, 10
> > + or t0, t0, t3
> > + MTLBWR_HG (t0, 0)
> > +#else
> > + MTLBWR_HG (t0, 1)
> > +#endif
> > + j _hgatp_mret
> > +
> > +_hgatp_level2_leaf:
> > + or t0, t0, t1 // global if parent table is global
> > +#ifdef STW_TLB_4KB
> > + extract (t3, t2, 29, 12)
> > + sll t3, t3, 10
> > + or t0, t0, t3
> > + MTLBWR_HG (t0, 0)
> > +#else
> > + MTLBWR_HG (t0, 2)
> > +#endif
> > + j _hgatp_mret
> > +
> > +_hgatp_level3_leaf:
> > + or t0, t0, t1 // global if parent table is global
> > +#ifdef STW_TLB_4KB
> > + extract (t3, t2, 38, 12)
> > + sll t3, t3, 10
> > + or t0, t0, t3
> > + MTLBWR_HG (t0, 0)
> > +#else
> > + MTLBWR_HG (t0, 3)
> > +#endif
> > + j _hgatp_mret
> > +
> > +htw_load_access_fault_handler:
> > +htw_hgatp_refill_handler:
> > +htw_page_fault_handler:
> > + j fail
> > +
> > +
> > +
> > +/********************
> > + * rdtime emulation *
> > + ********************/
> > + .global read_time_handler
> > +read_time_handler:
> > + csrrw sp, mscratch, sp /* sp = mscratch; mscratch = saved sp */
> > + sd x1, O_satp_vsatp_scratch0(sp) /* save sp */
> > + sd x3, O_satp_vsatp_scratch1(sp) /* save x3 */
> > +
> > + /* Set x1 to address of function which will set rd to x3 */
> > + csrr x1, mtval
> > + srli x1, x1, 7 - JUMP_TABLE_SHIFT
> > + andi x1, x1, 0x1f << JUMP_TABLE_SHIFT
> > + lla x3, write_xr_rdtime
> > + add x1, x1, x3
> > +
> > + /* Read the time memory mapped register */
> > + lui x3, %hi(TIMER_ADDR)
> > + ld x3, %lo(TIMER_ADDR)(x3)
> > +
> > + /* Call function which sets rd = x3 */
> > + jalr x1
> > +
> > + /* Increment mepc to skip instruction we just emulated */
> > + csrr x1, mepc
> > + addi x1, x1, 4
> > + csrw mepc, x1
> > +
> > + /* Restore gprs from memory */
> > + ld x1, O_satp_vsatp_scratch0(sp) /* restore x1 */
> > + ld x3, O_satp_vsatp_scratch1(sp) /* restore x3 */
> > + csrrw sp, mscratch, sp
> > +
> > + mret
> > +
> > +/***************************************
> > + * Custom Illegal Instruction handling *
> > + ***************************************/
> > +
> > +illegal_inst_handler:
> > + csrrw sp, mscratch, sp /* sp = mscratch; mscratch = saved sp */
> > + sd x1, (O_amo_scratch + 0 * 8)(sp)
> > + csrrw x1, mscratch, sp /* x1 = saved sp; restore mscratch */
> > + sd x1, (O_amo_scratch + 1 * 8)(sp) /* save sp */
> > + sd x3, (O_amo_scratch + 2 * 8)(sp)
> > + sd x4, (O_amo_scratch + 3 * 8)(sp)
> > + sd x5, (O_amo_scratch + 4 * 8)(sp)
> > + sd x6, (O_amo_scratch + 5 * 8)(sp)
> > + sd x7, (O_amo_scratch + 6 * 8)(sp)
> > + sd x8, (O_amo_scratch + 7 * 8)(sp)
> > + sd x9, (O_amo_scratch + 8 * 8)(sp)
> > + sd x10, (O_amo_scratch + 9 * 8)(sp)
> > +
> > +// Planned register use:
> > +// x1 - ra, temporary, result
> > +// x2 - sp
> > +// x3 - rs1 value
> > +// x4 - rs2 value
> > +// x5 - temporary (mtval, mtval_match)
> > +// x6 - saved mepc
> > +// x7 - saved mtvec
> > +// x8 - saved mstatus
> > +// x9 - saved mtval
> > +// x10 - temporary (fail count)
> > +
> > + csrr x9, mtval // x9 = faulting opcode
> > +
> > + /* x3 = rs1 value */
> > + lla x7, read_xr_amo // x7 = base address of table of read_xr funcs
> > + srli x6, x9, 15 - JUMP_TABLE_SHIFT // Align rs1 idx as table offset
> > + andi x6, x6, 0x1f << JUMP_TABLE_SHIFT // Isolated aligned rs1
> > + add x4, x6, x7 // Apply offset to jump table
> > + jalr x4 // Call func to read rs1 into x4
> > + move x3, x4 // x3 = rs1 value
> > +
> > + /* x4 = rs2 value */
> > + srli x6, x9, 20 - JUMP_TABLE_SHIFT // Align rs2 idx as table offset
> > + andi x6, x6, 0x1f << JUMP_TABLE_SHIFT // Isolate aligned rs2
> > + add x4, x6, x7 // Apply offset to jump table
> > + jalr x4 // Call func to read rs1 into x4
> > +
> > + /* x6 = saved epc */
> > + csrr x6, mepc // Save mepc
> > +
> > + /* Use a local handler for mtvec exceptions */
> > + lla x1, _illegal_inst_mtvec_handler
> > + csrrw x7, mtvec, x1 // x7 = saved mtvec
> > +
> > + /*
> > + * Extract the AMO opcode match bits, write that value to t5. Each AMO
> > + * instruction has a single unique value for these match bits. Since
> > + * every AMO has the same value for the lower 12 bits, we xor the
> > + * match value with the value of those lower 12 bits. This allows us
> > + * to construct the compare value for each AMO instruction using a
> > + * single LUI instruction.
> > + */
> > + li x1, 0b11111000000000000111000001111111
> > + and x5, x9, x1
> > + xori x5, x5, 0b000000101111
> > +
> > + li x1, 0b00000000000000000010000000000000
> > + beq x5, x1, _illegal_inst_handler_amoadd_w
> > +
> > + li x1, 0b00000000000000000011000000000000
> > + beq x5, x1, _illegal_inst_handler_amoadd_d
> > +
> > + li x1, 0b01100000000000000010000000000000
> > + beq x5, x1, _illegal_inst_handler_amoand_w
> > +
> > + li x1, 0b01100000000000000011000000000000
> > + beq x5, x1, _illegal_inst_handler_amoand_d
> > +
> > + li x1, 0b10100000000000000010000000000000
> > + beq x5, x1, _illegal_inst_handler_amomax_w
> > +
> > + li x1, 0b10100000000000000011000000000000
> > + beq x5, x1, _illegal_inst_handler_amomax_d
> > +
> > + li x1, 0b11100000000000000010000000000000
> > + beq x5, x1, _illegal_inst_handler_amomaxu_w
> > +
> > + li x1, 0b11100000000000000011000000000000
> > + beq x5, x1, _illegal_inst_handler_amomaxu_d
> > +
> > + li x1, 0b10000000000000000010000000000000
> > + beq x5, x1, _illegal_inst_handler_amomin_w
> > +
> > + li x1, 0b10000000000000000011000000000000
> > + beq x5, x1, _illegal_inst_handler_amomin_d
> > +
> > + li x1, 0b11000000000000000010000000000000
> > + beq x5, x1, _illegal_inst_handler_amominu_w
> > +
> > + li x1, 0b11000000000000000011000000000000
> > + beq x5, x1, _illegal_inst_handler_amominu_d
> > +
> > + li x1, 0b01000000000000000010000000000000
> > + beq x5, x1, _illegal_inst_handler_amoor_w
> > +
> > + li x1, 0b01000000000000000011000000000000
> > + beq x5, x1, _illegal_inst_handler_amoor_d
> > +
> > + li x1, 0b00001000000000000010000000000000
> > + beq x5, x1, _illegal_inst_handler_amoswap_w
> > +
> > + li x1, 0b00001000000000000011000000000000
> > + beq x5, x1, _illegal_inst_handler_amoswap_d
> > +
> > + li x1, 0b00100000000000000010000000000000
> > + beq x5, x1, _illegal_inst_handler_amoxor_w
> > +
> > + li x1, 0b00100000000000000011000000000000
> > + beq x5, x1, _illegal_inst_handler_amoxor_d
> > +
> > + j fail
> > +
> > +/**
> > + * Input:
> > + * x3 = rs1
> > + * x4 = rs2
> > + * Ouput:
> > + * x5 = old memory value
> > + *
> > + * Try LR/SC while counting down from NUM_TRIES_WITHOUT_LOCK to 0.
> > + * If counter reaches 0, acquire the global lock, then repeat LR/SC,
> > + * counting down from NUM_TRIES_WITHOUT_LOCK + NUM_TRIES_WITH_LOCK to
> > + * NUM_TRIES_WITHOUT_LOCK + 1
> > + * If counter reaches NUM_TRIES_WITHOUT_LOCK + 1 then fail completely.
> > + * On LR/SC success, if counter > NUM_TRIES_WITHOUT_LOCK then we had the lock,
> > + * and need to release it.
> > + *
> > + * Pseudocode:
> > + *
> > + * # Wait until not locked.
> > + * while locked:
> > + * pass
> > + *
> > + * counter = NUM_TRIES_WITHOUT_LOCK
> > + * while 1:
> > + * value, fail = amo()
> > + * if fail: # SC fail.
> > + * counter -= NUM_TRIES_WITHOUT_LOCK + 1
> > + * if counter == 0:
> > + * fail
> > + * counter += NUM_TRIES_WITHOUT_LOCK
> > + * if counter == 0:
> > + * get_lock()
> > + * counter = NUM_TRIES_WITH_LOCK + NUM_TRIES_WITHOUT_LOCK
> > + * else: # SC pass.
> > + * counter -= NUM_TRIES_WITH_LOCK
> > + * if counter > 0:
> > + * free_lock()
> > + * return
> > + */
> > +
> > +#define NUM_TRIES_WITHOUT_LOCK 20
> > +#define NUM_TRIES_WITH_LOCK 10000
> > +//#define NO_AMO_EMULATION_LOCK 1
> > +
> > +#if NO_AMO_EMULATION_LOCK
> > +#define DO_AMO(SIZE, AMO_OPERATION...) ; \
> > + /* Set mstatus.MPRV = 1, x8 = saved mstatus */ ; \
> > +25: li x8, MSTATUS_MPRV ; \
> > + csrrs x8, mstatus, x8 ; \
> > + ; \
> > +30: lr.SIZE.aq x5, (x3) ; \
> > + AMO_OPERATION ; \
> > + sc.SIZE.aqrl x1, x1, (x3) ; \
> > + beqz x1, _illegal_inst_handler_return ; \
> > + j 30b
> > +#else
> > +#define DO_AMO(SIZE, AMO_OPERATION...) ; \
> > + /* Wait until lock is clear */ ; \
> > + lla x10, amo_lock ; \
> > +10: lr.d x5, (x10) ; \
> > + beqz x5, 20f ; \
> > + PAUSE() ; \
> > + j 10b ; \
> > + ; \
> > +20: li x10, NUM_TRIES_WITHOUT_LOCK ; \
> > + ; \
> > + /* Set mstatus.MPRV = 1, x8 = saved mstatus */ ; \
> > +25: li x8, MSTATUS_MPRV ; \
> > + csrrs x8, mstatus, x8 ; \
> > + ; \
> > +30: lr.SIZE.aq x5, (x3) ; \
> > + AMO_OPERATION ; \
> > + sc.SIZE.aqrl x1, x1, (x3) ; \
> > + beqz x1, _illegal_inst_handler_return ; \
> > + /* SC failed */ ; \
> > + addi x10, x10, -NUM_TRIES_WITHOUT_LOCK + 1 ; \
> > + bnez x10, 40f ; \
> > + csrw mstatus, x8 ; \
> > + j fail ; \
> > +40: addi x10, x10, NUM_TRIES_WITHOUT_LOCK ; \
> > + bnez x10, 30b ; \
> > + ; \
> > + /* Acquire lock */ ; \
> > + csrw mstatus, x8 ; \
> > + lla x10, amo_lock ; \
> > +50: lr.d x5, (x10) ; \
> > + beqz x5, 60f ; \
> > + PAUSE() ; \
> > + j 50b ; \
> > +60: sc.d x5, sp, (x10) /* Use sp as lock value */ ; \
> > + bnez x5, 50b ; \
> > + ; \
> > + /* Retry with lock */ ; \
> > + li x10, NUM_TRIES_WITH_LOCK + NUM_TRIES_WITHOUT_LOCK ; \
> > + j 25b
> > +#endif /* NO_AMO_EMULATION_LOCK */
> > +
> > +_illegal_inst_handler_amoadd_w:
> > + DO_AMO(w, addw x1, x5, x4)
> > +
> > +_illegal_inst_handler_amoadd_d:
> > + DO_AMO(d, add x1, x5, x4)
> > +
> > +_illegal_inst_handler_amoand_w:
> > + DO_AMO(w, and x1, x5, x4)
> > +
> > +_illegal_inst_handler_amoand_d:
> > + DO_AMO(d, and x1, x5, x4)
> > +
> > +_illegal_inst_handler_amomax_w:
> > + addw x4, x4, x0
> > +#if ZBB_PRESENT
> > + DO_AMO(w, max x1, x5, x4)
> > +#else
> > + DO_AMO(w,
> > + move x1, x5 ;
> > + bge x5, x4, 5f ;
> > + move x1, x4 ;
> > +5:
> > + )
> > +#endif
> > +
> > +_illegal_inst_handler_amomax_d:
> > +#if ZBB_PRESENT
> > + DO_AMO(d, max x1, x5, x4)
> > +#else
> > + DO_AMO(d,
> > + move x1, x5 ;
> > + bge x5, x4, 5f ;
> > + move x1, x4 ;
> > +5:
> > + )
> > +#endif
> > +
> > +_illegal_inst_handler_amomaxu_w:
> > + addw x4, x4, x0
> > +#if ZBB_PRESENT
> > + DO_AMO(w, maxu x1, x5, x4)
> > +#else
> > + DO_AMO(w,
> > + move x1, x5 ;
> > + bgeu x5, x4, 5f ;
> > + move x1, x4 ;
> > +5:
> > + )
> > +#endif
> > +
> > +_illegal_inst_handler_amomaxu_d:
> > +#if ZBB_PRESENT
> > + DO_AMO(d, maxu x1, x5, x4)
> > +#else
> > + DO_AMO(d,
> > + move x1, x5 ;
> > + bgeu x5, x4, 5f ;
> > + move x1, x4 ;
> > +5:
> > + )
> > +#endif
> > +
> > +_illegal_inst_handler_amomin_w:
> > + addw x4, x4, x0
> > +#if ZBB_PRESENT
> > + DO_AMO(w, min x1, x5, x4)
> > +#else
> > + DO_AMO(w,
> > + move x1, x5 ;
> > + ble x5, x4, 5f ;
> > + move x1, x4 ;
> > +5:
> > + )
> > +#endif
> > +
> > +_illegal_inst_handler_amomin_d:
> > +#if ZBB_PRESENT
> > + DO_AMO(d, min x1, x5, x4)
> > +#else
> > + DO_AMO(d,
> > + move x1, x5 ;
> > + ble x5, x4, 5f ;
> > + move x1, x4 ;
> > +5:
> > + )
> > +#endif
> > +
> > +_illegal_inst_handler_amominu_w:
> > + addw x4, x4, x0
> > +#if ZBB_PRESENT
> > + DO_AMO(w, minu x1, x5, x4)
> > +#else
> > + DO_AMO(w,
> > + move x1, x5 ;
> > + bleu x5, x4, 5f ;
> > + move x1, x4 ;
> > +5:
> > + )
> > +#endif
> > +
> > +_illegal_inst_handler_amominu_d:
> > +#if ZBB_PRESENT
> > + DO_AMO(d, minu x1, x5, x4)
> > +#else
> > + DO_AMO(d,
> > + move x1, x5 ;
> > + bleu x5, x4, 5f ;
> > + move x1, x4 ;
> > +5:
> > + )
> > +#endif
> > +
> > +_illegal_inst_handler_amoor_w:
> > + DO_AMO(w, or x1, x5, x4)
> > +
> > +_illegal_inst_handler_amoor_d:
> > + DO_AMO(d, or x1, x5, x4)
> > +
> > +_illegal_inst_handler_amoswap_w:
> > + DO_AMO(w, move x1, x4)
> > +
> > +_illegal_inst_handler_amoswap_d:
> > + DO_AMO(d, move x1, x4)
> > +
> > +_illegal_inst_handler_amoxor_w:
> > + DO_AMO(w, xor x1, x5, x4)
> > +
> > +_illegal_inst_handler_amoxor_d:
> > + DO_AMO(d, xor x1, x5, x4)
> > +
> > +_illegal_inst_handler_return:
> > + csrw mstatus, x8 // Restore mstatus (undo MPRV)
> > +
> > +#if NO_AMO_EMULATION_LOCK
> > +#else
> > + /* Clear amo_lock if we had acquired it. */
> > + addi x10, x10, -NUM_TRIES_WITHOUT_LOCK
> > + blez x10, 10f
> > + lla x10, amo_lock
> > + sd x0, (x10)
> > +10:
> > +#endif /* NO_AMO_EMULATION_LOCK */
> > +
> > + /* write rd with value in x5 */
> > + lla x4, write_xr_amo // x4 = base address of write_xr funcs
> > + srli x3, x9, 7 - JUMP_TABLE_SHIFT // Align rd idx as table offset
> > + andi x3, x3, 0x1f << JUMP_TABLE_SHIFT // Isolate aligned rd
> > + add x1, x4, x3 // Apply offset to jump table
> > + jalr x1 // Call func to write x5 to rd
> > +
> > + addi x6, x6, 4 // Saved mepc += 4 (skip emulated instruction)
> > +
> > +_illegal_inst_handler_mret:
> > + csrw mepc, x6 // Restore mepc
> > + csrw mtvec, x7 // Restore mtvec
> > +
> > + /* Restore working set of XRs */
> > + ld x1, (O_amo_scratch + 0 * 8)(sp)
> > + ld x3, (O_amo_scratch + 2 * 8)(sp)
> > + ld x4, (O_amo_scratch + 3 * 8)(sp)
> > + ld x5, (O_amo_scratch + 4 * 8)(sp)
> > + ld x6, (O_amo_scratch + 5 * 8)(sp)
> > + ld x7, (O_amo_scratch + 6 * 8)(sp)
> > + ld x8, (O_amo_scratch + 7 * 8)(sp)
> > + ld x9, (O_amo_scratch + 8 * 8)(sp)
> > + ld x10, (O_amo_scratch + 9 * 8)(sp)
> > + ld sp, (O_amo_scratch + 1 * 8)(sp) /* restore sp last */
> > +
> > + mret // Return
> > +
> > + .align 2
> > +_illegal_inst_mtvec_handler:
> > + /*
> > + * If any exception occurs on a load/store during AMO emulation,
> > + * just re-execute the original faulting AMO. This will regenerate
> > + * the exception (page fault, access fault) and allow it to
> > + * be handled as though from the original context
> > + */
> > + csrw mstatus, x8 // Restore mstatus
> > +
> > + csrr x5, mcause
> > +
> > + li x1, CAUSE_LOAD_PAGE_FAULT
> > + beq x5, x1, _illegal_inst_handler_mret
> > +
> > + li x1, CAUSE_STORE_PAGE_FAULT
> > + beq x5, x1, _illegal_inst_handler_mret
> > +
> > + li x1, CAUSE_GUEST_LOAD_PAGE_FAULT
> > + beq x5, x1, _illegal_inst_handler_mret
> > +
> > + li x1, CAUSE_GUEST_STORE_PAGE_FAULT
> > + beq x5, x1, _illegal_inst_handler_mret
> > +
> > + li x1, CAUSE_LOAD_ACCESS
> > + beq x5, x1, _illegal_inst_handler_mret
> > +
> > + li x1, CAUSE_STORE_ACCESS
> > + beq x5, x1, _illegal_inst_handler_mret
> > +
> > + // An unexpected exception during AMO emulation is fatal.
> > + j fail
> > +
> > +/**
> > + * This is a table of 32 functions.
> > + * Calling the function read_xr_amo + rd * JUMP_TABLE_OFFSET does
> > + * x4 = XR[rd]. For xrs where the value is stored in memory by the AMO handler,
> > + * do x4 = MEM[address where $rd is stored], which has the equivalent effect.
> > + */
> > +read_xr_amo:
> > + li x4, 0 ; jr ra
> > + ld x4, (O_amo_scratch + 0 * 8)(sp) ; jr ra
> > + ld x4, (O_amo_scratch + 1 * 8)(sp) ; jr ra
> > + ld x4, (O_amo_scratch + 2 * 8)(sp) ; jr ra
> > + ld x4, (O_amo_scratch + 3 * 8)(sp) ; jr ra
> > + ld x4, (O_amo_scratch + 4 * 8)(sp) ; jr ra
> > + ld x4, (O_amo_scratch + 5 * 8)(sp) ; jr ra
> > + ld x4, (O_amo_scratch + 6 * 8)(sp) ; jr ra
> > + ld x4, (O_amo_scratch + 7 * 8)(sp) ; jr ra
> > + ld x4, (O_amo_scratch + 8 * 8)(sp) ; jr ra
> > + ld x4, (O_amo_scratch + 9 * 8)(sp) ; jr ra
> > + move x4, x11 ; jr ra
> > + move x4, x12 ; jr ra
> > + move x4, x13 ; jr ra
> > + move x4, x14 ; jr ra
> > + move x4, x15 ; jr ra
> > + move x4, x16 ; jr ra
> > + move x4, x17 ; jr ra
> > + move x4, x18 ; jr ra
> > + move x4, x19 ; jr ra
> > + move x4, x20 ; jr ra
> > + move x4, x21 ; jr ra
> > + move x4, x22 ; jr ra
> > + move x4, x23 ; jr ra
> > + move x4, x24 ; jr ra
> > + move x4, x25 ; jr ra
> > + move x4, x26 ; jr ra
> > + move x4, x27 ; jr ra
> > + move x4, x28 ; jr ra
> > + move x4, x29 ; jr ra
> > + move x4, x30 ; jr ra
> > + move x4, x31 ; jr ra
> > +
> > +/**
> > + * This is a table of 32 functions.
> > + * Calling the function write_xr_amo + rd * JUMP_TABLE_OFFSET does:
> > + * XR[rd] = x5. For xrs which will be restored from memory at the end of
> > + * the AMO handler, do MEM[address where $rd is stored] = x5.
> > + */
> > +write_xr_amo:
> > + jr ra ; jr ra
> > + sd x5, (O_amo_scratch + 0 * 8)(sp) ; jr ra
> > + sd x5, (O_amo_scratch + 1 * 8)(sp) ; jr ra
> > + sd x5, (O_amo_scratch + 2 * 8)(sp) ; jr ra
> > + sd x5, (O_amo_scratch + 3 * 8)(sp) ; jr ra
> > + sd x5, (O_amo_scratch + 4 * 8)(sp) ; jr ra
> > + sd x5, (O_amo_scratch + 5 * 8)(sp) ; jr ra
> > + sd x5, (O_amo_scratch + 6 * 8)(sp) ; jr ra
> > + sd x5, (O_amo_scratch + 7 * 8)(sp) ; jr ra
> > + sd x5, (O_amo_scratch + 8 * 8)(sp) ; jr ra
> > + sd x5, (O_amo_scratch + 9 * 8)(sp) ; jr ra
> > + move x11, x5 ; jr ra
> > + move x12, x5 ; jr ra
> > + move x13, x5 ; jr ra
> > + move x14, x5 ; jr ra
> > + move x15, x5 ; jr ra
> > + move x16, x5 ; jr ra
> > + move x17, x5 ; jr ra
> > + move x18, x5 ; jr ra
> > + move x19, x5 ; jr ra
> > + move x20, x5 ; jr ra
> > + move x21, x5 ; jr ra
> > + move x22, x5 ; jr ra
> > + move x23, x5 ; jr ra
> > + move x24, x5 ; jr ra
> > + move x25, x5 ; jr ra
> > + move x26, x5 ; jr ra
> > + move x27, x5 ; jr ra
> > + move x28, x5 ; jr ra
> > + move x29, x5 ; jr ra
> > + move x30, x5 ; jr ra
> > + move x31, x5 ; jr ra
> > +
> > +/**
> > + * This is a table of 32 functions.
> > + * Calling the function write_xr_rdtime + rd * JUMP_TABLE_OFFSET does:
> > + * XR[rd] = x3. For xrs which will be restored from memory at the end of
> > + * the rdtime handler, do MEM[address where $rd is stored] = x3.
> > + */
> > +write_xr_rdtime:
> > + jr ra ; jr ra
> > + sd x3, O_satp_vsatp_scratch0(sp) ; jr ra
> > + j _write_xr_rdtime_x1 ; jr ra
> > + sd x3, O_satp_vsatp_scratch1(sp) ; jr ra
> > + move x4, x3 ; jr ra
> > + move x5, x3 ; jr ra
> > + move x6, x3 ; jr ra
> > + move x7, x3 ; jr ra
> > + move x8, x3 ; jr ra
> > + move x9, x3 ; jr ra
> > + move x10, x3 ; jr ra
> > + move x11, x3 ; jr ra
> > + move x12, x3 ; jr ra
> > + move x13, x3 ; jr ra
> > + move x14, x3 ; jr ra
> > + move x15, x3 ; jr ra
> > + move x16, x3 ; jr ra
> > + move x17, x3 ; jr ra
> > + move x18, x3 ; jr ra
> > + move x19, x3 ; jr ra
> > + move x20, x3 ; jr ra
> > + move x21, x3 ; jr ra
> > + move x22, x3 ; jr ra
> > + move x23, x3 ; jr ra
> > + move x24, x3 ; jr ra
> > + move x25, x3 ; jr ra
> > + move x26, x3 ; jr ra
> > + move x27, x3 ; jr ra
> > + move x28, x3 ; jr ra
> > + move x29, x3 ; jr ra
> > + move x30, x3 ; jr ra
> > + move x31, x3 ; jr ra
> > +_write_xr_rdtime_x1:
> > + csrw mscratch, x3 ; jr ra
> > +
> > +fail:
> > + unimp
> > +
> > + .section .sbss
> > + .align 6
> > + .type amo_lock, @object
> > + .size amo_lock, 64
> > +amo_lock:
> > + .zero 64
> > --
> > 2.47.1
> >
> >
> > --
> > opensbi mailing list
> > opensbi@lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/opensbi
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply [flat|nested] 70+ messages in thread
* [PATCH v2 05/11] platform: generic: mips: add extra scratch space
2025-02-12 12:27 ` Anup Patel
` (3 preceding siblings ...)
2025-02-26 0:53 ` [PATCH v2 04/11] platform: generic: mips: add custom exception handler Chao-ying Fu
@ 2025-02-26 0:53 ` Chao-ying Fu
2025-03-28 4:56 ` Anup Patel
2025-02-26 0:53 ` [PATCH v2 06/11] platform: generic: mips: add an entry function Chao-ying Fu
` (43 subsequent siblings)
48 siblings, 1 reply; 70+ messages in thread
From: Chao-ying Fu @ 2025-02-26 0:53 UTC (permalink / raw)
To: opensbi
We need extra scratch space used by the custom exception handler.
---
include/sbi/sbi_scratch.h | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/include/sbi/sbi_scratch.h b/include/sbi/sbi_scratch.h
index 0d188d1..ff8b75e 100644
--- a/include/sbi/sbi_scratch.h
+++ b/include/sbi/sbi_scratch.h
@@ -44,8 +44,16 @@
#define SBI_SCRATCH_OPTIONS_OFFSET (13 * __SIZEOF_POINTER__)
/** Offset of hartindex member in sbi_scratch */
#define SBI_SCRATCH_HARTINDEX_OFFSET (14 * __SIZEOF_POINTER__)
+#ifdef CONFIG_PLATFORM_MIPS_P8700
+#define MIPS_P8700_STW_SIZE 34
+/** Offset of stw_tmp in sbi_scratch */
+#define SBI_SCRATCH_STW_TMP_OFFSET (15 * __SIZEOF_POINTER__)
+/** Offset of extra space in sbi_scratch */
+#define SBI_SCRATCH_EXTRA_SPACE_OFFSET ((15 + MIPS_P8700_STW_SIZE) * __SIZEOF_POINTER__)
+#else
/** Offset of extra space in sbi_scratch */
#define SBI_SCRATCH_EXTRA_SPACE_OFFSET (15 * __SIZEOF_POINTER__)
+#endif
/** Maximum size of sbi_scratch (4KB) */
#define SBI_SCRATCH_SIZE (0x1000)
@@ -87,6 +95,10 @@ struct sbi_scratch {
unsigned long options;
/** Index of the hart */
unsigned long hartindex;
+#ifdef CONFIG_PLATFORM_MIPS_P8700
+ /** for stw */
+ unsigned long stw_tmp[MIPS_P8700_STW_SIZE];
+#endif
};
/**
--
2.47.1
^ permalink raw reply related [flat|nested] 70+ messages in thread* Re: [PATCH v2 05/11] platform: generic: mips: add extra scratch space
2025-02-26 0:53 ` [PATCH v2 05/11] platform: generic: mips: add extra scratch space Chao-ying Fu
@ 2025-03-28 4:56 ` Anup Patel
0 siblings, 0 replies; 70+ messages in thread
From: Anup Patel @ 2025-03-28 4:56 UTC (permalink / raw)
To: Chao-ying Fu; +Cc: opensbi, Chao-ying Fu
On Wed, Feb 26, 2025 at 7:38 AM Chao-ying Fu <icebergfu@gmail.com> wrote:
>
> We need extra scratch space used by the custom exception handler.
The custom MIPS specific exception handler itself is unjustified so
this extra custom scratch space makes no sense at the moment.
Imagine, more platforms adding their own custom scratch space.
Regards,
Anup
> ---
> include/sbi/sbi_scratch.h | 12 ++++++++++++
> 1 file changed, 12 insertions(+)
>
> diff --git a/include/sbi/sbi_scratch.h b/include/sbi/sbi_scratch.h
> index 0d188d1..ff8b75e 100644
> --- a/include/sbi/sbi_scratch.h
> +++ b/include/sbi/sbi_scratch.h
> @@ -44,8 +44,16 @@
> #define SBI_SCRATCH_OPTIONS_OFFSET (13 * __SIZEOF_POINTER__)
> /** Offset of hartindex member in sbi_scratch */
> #define SBI_SCRATCH_HARTINDEX_OFFSET (14 * __SIZEOF_POINTER__)
> +#ifdef CONFIG_PLATFORM_MIPS_P8700
> +#define MIPS_P8700_STW_SIZE 34
> +/** Offset of stw_tmp in sbi_scratch */
> +#define SBI_SCRATCH_STW_TMP_OFFSET (15 * __SIZEOF_POINTER__)
> +/** Offset of extra space in sbi_scratch */
> +#define SBI_SCRATCH_EXTRA_SPACE_OFFSET ((15 + MIPS_P8700_STW_SIZE) * __SIZEOF_POINTER__)
> +#else
> /** Offset of extra space in sbi_scratch */
> #define SBI_SCRATCH_EXTRA_SPACE_OFFSET (15 * __SIZEOF_POINTER__)
> +#endif
> /** Maximum size of sbi_scratch (4KB) */
> #define SBI_SCRATCH_SIZE (0x1000)
>
> @@ -87,6 +95,10 @@ struct sbi_scratch {
> unsigned long options;
> /** Index of the hart */
> unsigned long hartindex;
> +#ifdef CONFIG_PLATFORM_MIPS_P8700
> + /** for stw */
> + unsigned long stw_tmp[MIPS_P8700_STW_SIZE];
> +#endif
> };
>
> /**
> --
> 2.47.1
>
>
> --
> opensbi mailing list
> opensbi@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply [flat|nested] 70+ messages in thread
* [PATCH v2 06/11] platform: generic: mips: add an entry function
2025-02-12 12:27 ` Anup Patel
` (4 preceding siblings ...)
2025-02-26 0:53 ` [PATCH v2 05/11] platform: generic: mips: add extra scratch space Chao-ying Fu
@ 2025-02-26 0:53 ` Chao-ying Fu
2025-03-28 5:00 ` Anup Patel
2025-02-26 0:53 ` [PATCH v2 07/11] platform: generic: mips: add the platform file Chao-ying Fu
` (42 subsequent siblings)
48 siblings, 1 reply; 70+ messages in thread
From: Chao-ying Fu @ 2025-02-26 0:53 UTC (permalink / raw)
To: opensbi
All harts run the same entry function to initialize
MIPS custom CSR registers and CM registers.
---
platform/generic/mips/cps-vec.S | 202 ++++++++++++++++++++++++++++++++
1 file changed, 202 insertions(+)
create mode 100644 platform/generic/mips/cps-vec.S
diff --git a/platform/generic/mips/cps-vec.S b/platform/generic/mips/cps-vec.S
new file mode 100644
index 0000000..5049532
--- /dev/null
+++ b/platform/generic/mips/cps-vec.S
@@ -0,0 +1,202 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 MIPS
+ *
+ */
+
+#include <sbi/riscv_encoding.h>
+#include <mips/p8700.h>
+
+ .text
+ .align 12
+ .globl mips_cps_core_entry
+mips_cps_core_entry:
+ j 1f
+
+ .align 2
+nmi_vector:
+ j 1f
+
+ .align 2
+cacheerr_vector:
+ j 1f
+
+ .align 2
+debugexc_vector:
+ j 1f
+
+ .align 2
+1:
+ li x1, 0
+ li x2, 0
+ li x3, 0
+ li x4, 0
+ li x5, 0
+ li x6, 0
+ li x7, 0
+ li x8, 0
+ li x9, 0
+ li x10, 0
+ li x11, 0
+ li x12, 0
+ li x13, 0
+ li x14, 0
+ li x15, 0
+ li x16, 0
+ li x17, 0
+ li x18, 0
+ li x19, 0
+ li x20, 0
+ li x21, 0
+ li x22, 0
+ li x23, 0
+ li x24, 0
+ li x25, 0
+ li x26, 0
+ li x27, 0
+ li x28, 0
+ li x29, 0
+ li x30, 0
+ li x31, 0
+
+ /* a0 has mhartid */
+ csrr a0, CSR_MHARTID
+
+ /* Test mhartid lowest 4 bits */
+ andi t0, a0, 0xf
+ bnez t0, setup_pmp
+
+ /* Cluster cl Core co Hart 0 */
+ li s0, CM_BASE
+
+cm_relocate_done:
+ li t0, GCR_CORE_COH_EN_EN
+
+ /* Get core number to update CM_BASE */
+ srl t1, a0, MHARTID_CORE_SHIFT
+ andi t1, t1, MHARTID_CORE_MASK
+ sll t1, t1, CM_BASE_CORE_SHIFT
+ add s0, s0, t1
+ INDEXED(sd, t0, t1, GCR_OFF_LOCAL + GCR_CORE_COH_EN, s0)
+ fence
+
+setup_pmp:
+ li t0, DRAM_PMP_ADDR
+ csrw CSR_PMPADDR14, t0
+ li t0, 0x1fffffffffffffff # All from 0x0
+ csrw CSR_PMPADDR15, t0
+ li t0, ((PMP_A_NAPOT|PMP_R|PMP_W|PMP_X)<<56)|((PMP_A_NAPOT|PMP_R|PMP_W|PMP_X)<<48)
+ csrw CSR_PMPCFG2, t0
+ /* Set cacheable for pmp6, uncacheable for pmp7 */
+ li t0, (CCA_CACHE_DISABLE << 56)|(CCA_CACHE_ENABLE << 48)
+ csrw CSR_MIPSPMACFG2, t0
+ /* Reset pmpcfg0 */
+ csrw CSR_PMPCFG0, zero
+ /* Reset pmacfg0 */
+ csrw CSR_MIPSPMACFG0, zero
+ fence
+
+per_cluster:
+ li t0, 0xffff
+ and t0, t0, a0
+ bnez t0, per_core
+
+ /* L2 Prefetch */
+ li t0, 0xfffff110
+ sw t0, L2_PFT_CONTROL_OFFSET(s0)
+ li t0, 0x15ff
+ sw t0, L2_PFT_CONTROL_B_OFFSET(s0)
+
+per_core:
+ andi t0, a0, 0xf
+ bnez t0, per_hart
+
+ /* Enable Load Pair */
+ /* Enable Store Pair */
+ /* Enable HTW */
+ li t0, (1<<12)|(1<<13)|(1<<7)
+ csrc CSR_MIPSCONFIG7, t0
+
+ /* Disable noRFO */
+ li t0, (1<<25)
+ csrs CSR_MIPSCONFIG7, t0
+
+ /* Disable misaligned load/store to have misaligned address exceptions */
+ li t0, (1<<9)
+ csrs CSR_MIPSCONFIG7, t0
+
+ /* Enable L1-D$ Prefetch */
+ li t0, 0xff
+ csrw CSR_MIPSCONFIG11, t0
+
+ li t0, 4
+ csrs CSR_MIPSCONFIG8, t0
+ li t0, 8
+ csrs CSR_MIPSCONFIG9, t0
+ fence
+ fence.i
+
+ li t0, 0x104
+ csrs CSR_MIPSCONFIG8, t0
+ li t0, 8
+ csrs CSR_MIPSCONFIG9, t0
+ fence
+ fence.i
+
+ li t0, 0x204
+ csrs CSR_MIPSCONFIG8, t0
+ li t0, 8
+ csrs CSR_MIPSCONFIG9, t0
+ fence
+ fence.i
+
+ li t0, 0x304
+ csrs CSR_MIPSCONFIG8, t0
+ li t0, 8
+ csrs CSR_MIPSCONFIG9, t0
+ fence
+ fence.i
+
+ li t0, 0x404
+ csrs CSR_MIPSCONFIG8, t0
+ li t0, 8
+ csrs CSR_MIPSCONFIG9, t0
+ fence
+ fence.i
+
+ li t0, 0x504
+ csrs CSR_MIPSCONFIG8, t0
+ li t0, 8
+ csrs CSR_MIPSCONFIG9, t0
+ fence
+ fence.i
+
+ li t0, 0x604
+ csrs CSR_MIPSCONFIG8, t0
+ li t0, 8
+ csrs CSR_MIPSCONFIG9, t0
+ fence
+ fence.i
+
+ li t0, 0x704
+ csrs CSR_MIPSCONFIG8, t0
+ li t0, 8
+ csrs CSR_MIPSCONFIG9, t0
+ fence
+ fence.i
+
+per_hart:
+ /* Set up mipstvec */
+ lla t0, mipstvec_handler_stw
+ ori t0, t0, 1
+ csrw CSR_MIPSTVEC, t0
+
+ /* Let hart 0 jump to _start */
+ beqz a0, 1f
+ lla t0, _start_warm
+ jr t0
+1:
+ lla t0, _start
+ jr t0
+
--
2.47.1
^ permalink raw reply related [flat|nested] 70+ messages in thread* Re: [PATCH v2 06/11] platform: generic: mips: add an entry function
2025-02-26 0:53 ` [PATCH v2 06/11] platform: generic: mips: add an entry function Chao-ying Fu
@ 2025-03-28 5:00 ` Anup Patel
0 siblings, 0 replies; 70+ messages in thread
From: Anup Patel @ 2025-03-28 5:00 UTC (permalink / raw)
To: Chao-ying Fu; +Cc: opensbi, Chao-ying Fu
On Wed, Feb 26, 2025 at 6:24 AM Chao-ying Fu <icebergfu@gmail.com> wrote:
>
> All harts run the same entry function to initialize
> MIPS custom CSR registers and CM registers.
The platform specific nascent_init() is exactly for this kind
of early CSR setup. Please use that instead of introducing
custom entry.
Regards,
Anup
> ---
> platform/generic/mips/cps-vec.S | 202 ++++++++++++++++++++++++++++++++
> 1 file changed, 202 insertions(+)
> create mode 100644 platform/generic/mips/cps-vec.S
>
> diff --git a/platform/generic/mips/cps-vec.S b/platform/generic/mips/cps-vec.S
> new file mode 100644
> index 0000000..5049532
> --- /dev/null
> +++ b/platform/generic/mips/cps-vec.S
> @@ -0,0 +1,202 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Copyright (c) 2025 MIPS
> + *
> + */
> +
> +#include <sbi/riscv_encoding.h>
> +#include <mips/p8700.h>
> +
> + .text
> + .align 12
> + .globl mips_cps_core_entry
> +mips_cps_core_entry:
> + j 1f
> +
> + .align 2
> +nmi_vector:
> + j 1f
> +
> + .align 2
> +cacheerr_vector:
> + j 1f
> +
> + .align 2
> +debugexc_vector:
> + j 1f
> +
> + .align 2
> +1:
> + li x1, 0
> + li x2, 0
> + li x3, 0
> + li x4, 0
> + li x5, 0
> + li x6, 0
> + li x7, 0
> + li x8, 0
> + li x9, 0
> + li x10, 0
> + li x11, 0
> + li x12, 0
> + li x13, 0
> + li x14, 0
> + li x15, 0
> + li x16, 0
> + li x17, 0
> + li x18, 0
> + li x19, 0
> + li x20, 0
> + li x21, 0
> + li x22, 0
> + li x23, 0
> + li x24, 0
> + li x25, 0
> + li x26, 0
> + li x27, 0
> + li x28, 0
> + li x29, 0
> + li x30, 0
> + li x31, 0
> +
> + /* a0 has mhartid */
> + csrr a0, CSR_MHARTID
> +
> + /* Test mhartid lowest 4 bits */
> + andi t0, a0, 0xf
> + bnez t0, setup_pmp
> +
> + /* Cluster cl Core co Hart 0 */
> + li s0, CM_BASE
> +
> +cm_relocate_done:
> + li t0, GCR_CORE_COH_EN_EN
> +
> + /* Get core number to update CM_BASE */
> + srl t1, a0, MHARTID_CORE_SHIFT
> + andi t1, t1, MHARTID_CORE_MASK
> + sll t1, t1, CM_BASE_CORE_SHIFT
> + add s0, s0, t1
> + INDEXED(sd, t0, t1, GCR_OFF_LOCAL + GCR_CORE_COH_EN, s0)
> + fence
> +
> +setup_pmp:
> + li t0, DRAM_PMP_ADDR
> + csrw CSR_PMPADDR14, t0
> + li t0, 0x1fffffffffffffff # All from 0x0
> + csrw CSR_PMPADDR15, t0
> + li t0, ((PMP_A_NAPOT|PMP_R|PMP_W|PMP_X)<<56)|((PMP_A_NAPOT|PMP_R|PMP_W|PMP_X)<<48)
> + csrw CSR_PMPCFG2, t0
> + /* Set cacheable for pmp6, uncacheable for pmp7 */
> + li t0, (CCA_CACHE_DISABLE << 56)|(CCA_CACHE_ENABLE << 48)
> + csrw CSR_MIPSPMACFG2, t0
> + /* Reset pmpcfg0 */
> + csrw CSR_PMPCFG0, zero
> + /* Reset pmacfg0 */
> + csrw CSR_MIPSPMACFG0, zero
> + fence
> +
> +per_cluster:
> + li t0, 0xffff
> + and t0, t0, a0
> + bnez t0, per_core
> +
> + /* L2 Prefetch */
> + li t0, 0xfffff110
> + sw t0, L2_PFT_CONTROL_OFFSET(s0)
> + li t0, 0x15ff
> + sw t0, L2_PFT_CONTROL_B_OFFSET(s0)
> +
> +per_core:
> + andi t0, a0, 0xf
> + bnez t0, per_hart
> +
> + /* Enable Load Pair */
> + /* Enable Store Pair */
> + /* Enable HTW */
> + li t0, (1<<12)|(1<<13)|(1<<7)
> + csrc CSR_MIPSCONFIG7, t0
> +
> + /* Disable noRFO */
> + li t0, (1<<25)
> + csrs CSR_MIPSCONFIG7, t0
> +
> + /* Disable misaligned load/store to have misaligned address exceptions */
> + li t0, (1<<9)
> + csrs CSR_MIPSCONFIG7, t0
> +
> + /* Enable L1-D$ Prefetch */
> + li t0, 0xff
> + csrw CSR_MIPSCONFIG11, t0
> +
> + li t0, 4
> + csrs CSR_MIPSCONFIG8, t0
> + li t0, 8
> + csrs CSR_MIPSCONFIG9, t0
> + fence
> + fence.i
> +
> + li t0, 0x104
> + csrs CSR_MIPSCONFIG8, t0
> + li t0, 8
> + csrs CSR_MIPSCONFIG9, t0
> + fence
> + fence.i
> +
> + li t0, 0x204
> + csrs CSR_MIPSCONFIG8, t0
> + li t0, 8
> + csrs CSR_MIPSCONFIG9, t0
> + fence
> + fence.i
> +
> + li t0, 0x304
> + csrs CSR_MIPSCONFIG8, t0
> + li t0, 8
> + csrs CSR_MIPSCONFIG9, t0
> + fence
> + fence.i
> +
> + li t0, 0x404
> + csrs CSR_MIPSCONFIG8, t0
> + li t0, 8
> + csrs CSR_MIPSCONFIG9, t0
> + fence
> + fence.i
> +
> + li t0, 0x504
> + csrs CSR_MIPSCONFIG8, t0
> + li t0, 8
> + csrs CSR_MIPSCONFIG9, t0
> + fence
> + fence.i
> +
> + li t0, 0x604
> + csrs CSR_MIPSCONFIG8, t0
> + li t0, 8
> + csrs CSR_MIPSCONFIG9, t0
> + fence
> + fence.i
> +
> + li t0, 0x704
> + csrs CSR_MIPSCONFIG8, t0
> + li t0, 8
> + csrs CSR_MIPSCONFIG9, t0
> + fence
> + fence.i
> +
> +per_hart:
> + /* Set up mipstvec */
> + lla t0, mipstvec_handler_stw
> + ori t0, t0, 1
> + csrw CSR_MIPSTVEC, t0
> +
> + /* Let hart 0 jump to _start */
> + beqz a0, 1f
> + lla t0, _start_warm
> + jr t0
> +1:
> + lla t0, _start
> + jr t0
> +
> --
> 2.47.1
>
>
> --
> opensbi mailing list
> opensbi@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply [flat|nested] 70+ messages in thread
* [PATCH v2 07/11] platform: generic: mips: add the platform file.
2025-02-12 12:27 ` Anup Patel
` (5 preceding siblings ...)
2025-02-26 0:53 ` [PATCH v2 06/11] platform: generic: mips: add an entry function Chao-ying Fu
@ 2025-02-26 0:53 ` Chao-ying Fu
2025-02-26 0:53 ` [PATCH v2 08/11] platform: generic: mips: add a dts file Chao-ying Fu
` (41 subsequent siblings)
48 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-02-26 0:53 UTC (permalink / raw)
To: opensbi
We add the platform file for MIPS P8700.
---
platform/generic/mips/p8700.c | 202 ++++++++++++++++++++++++++++++++++
1 file changed, 202 insertions(+)
create mode 100644 platform/generic/mips/p8700.c
diff --git a/platform/generic/mips/p8700.c b/platform/generic/mips/p8700.c
new file mode 100644
index 0000000..1bd627f
--- /dev/null
+++ b/platform/generic/mips/p8700.c
@@ -0,0 +1,202 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 MIPS
+ *
+ */
+
+#include <platform_override.h>
+#include <sbi/sbi_domain.h>
+#include <sbi/sbi_error.h>
+#include <sbi/sbi_hsm.h>
+#include <sbi/sbi_timer.h>
+#include <sbi_utils/fdt/fdt_helper.h>
+#include <mips/p8700.h>
+#include <mips/mips-cm.h>
+
+extern void mips_cps_core_entry(void);
+
+#if CLUSTERS_IN_PLATFORM > 1
+static void power_up_other_cluster(u32 hartid)
+{
+ unsigned int stat;
+ unsigned int timeout;
+ bool local_p = (cpu_cluster(current_hartid()) == cpu_cluster(hartid));
+
+ /* Power up cluster cl core 0 hart 0 */
+ write_cpc_pwrup_ctl(hartid, 1, local_p);
+
+ /* Wait for the CM to start up */
+ timeout = 100;
+ while (true) {
+ stat = read_cpc_cm_stat_conf(hartid, local_p);
+ stat = EXT(stat, CPC_Cx_STAT_CONF_SEQ_STATE);
+ if (stat == CPC_Cx_STAT_CONF_SEQ_STATE_U5)
+ break;
+
+ /* Delay a little while before we start warning */
+ if (timeout) {
+ sbi_dprintf("Delay a little while before we start warning\n");
+ timeout--;
+ }
+ else {
+ sbi_printf("Waiting for cluster %u CM to power up... STAT_CONF=0x%x\n",
+ cpu_cluster(hartid), stat);
+ break;
+ }
+ }
+}
+#endif
+
+static int mips_hart_start(u32 hartid, ulong saddr)
+{
+ unsigned int stat;
+ unsigned int timeout;
+ bool local_p = (cpu_cluster(current_hartid()) == cpu_cluster(hartid));
+
+ /* Hart 0 is the boot hart, and we don't use the CPC cmd to start. */
+ if (hartid == 0)
+ return SBI_ENOTSUPP;
+
+ if (cpu_hart(hartid) == 0) {
+ /* Change cluster cl core co hart 0 reset base */
+ write_gcr_co_reset_base(hartid,
+ (unsigned long)mips_cps_core_entry, local_p);
+
+ /* Ensure its coherency is disabled */
+ write_gcr_co_coherence(hartid, 0, local_p);
+
+ /* Start cluster cl core co hart 0 */
+ write_cpc_co_vp_run(hartid, 1 << cpu_hart(hartid), local_p);
+
+ /* Reset cluster cl core co hart 0 */
+ write_cpc_co_cmd(hartid, CPC_Cx_CMD_RESET, local_p);
+
+ timeout = 100;
+ while (true) {
+ stat = read_cpc_co_stat_conf(hartid, local_p);
+ stat = EXT(stat, CPC_Cx_STAT_CONF_SEQ_STATE);
+ if (stat == CPC_Cx_STAT_CONF_SEQ_STATE_U6)
+ break;
+
+ /* Delay a little while before we start warning */
+ if (timeout) {
+ sbi_timer_mdelay(10);
+ timeout--;
+ }
+ else {
+ sbi_printf("Waiting for cluster %u core %u hart %u to start... STAT_CONF=0x%x\n",
+ cpu_cluster(hartid),
+ cpu_core(hartid), cpu_hart(hartid),
+ stat);
+ break;
+ }
+ }
+ }
+ else {
+ write_gcr_co_reset_base(hartid,
+ (unsigned long)mips_cps_core_entry, local_p);
+ write_cpc_co_vp_run(hartid, 1 << cpu_hart(hartid), local_p);
+ }
+
+ return 0;
+}
+
+static int mips_hart_stop()
+{
+ u32 hartid = current_hartid();
+ bool local_p = (cpu_cluster(current_hartid()) == cpu_cluster(hartid));
+
+ /* Hart 0 is the boot hart, and we don't use the CPC cmd to stop. */
+ if (hartid == 0)
+ return SBI_ENOTSUPP;
+
+ write_cpc_co_vp_stop(hartid, 1 << cpu_hart(hartid), local_p);
+
+ return 0;
+}
+
+static const struct sbi_hsm_device mips_hsm = {
+ .name = "mips_hsm",
+ .hart_start = mips_hart_start,
+ .hart_stop = mips_hart_stop,
+};
+
+static int mips_p8700_final_init(bool cold_boot, void *fdt,
+ const struct fdt_match *match)
+{
+ if (cold_boot)
+ sbi_hsm_set_device(&mips_hsm);
+
+ return 0;
+}
+
+static int mips_p8700_early_init(bool cold_boot, const void *fdt,
+ const struct fdt_match *match)
+{
+ int rc;
+
+ if (cold_boot)
+ {
+#if CLUSTERS_IN_PLATFORM > 1
+ int i;
+ /* Power up other clusters in the platform. */
+ for (i = 1; i < CLUSTERS_IN_PLATFORM; i++) {
+ power_up_other_cluster(i << NEW_CLUSTER_SHIFT);
+ }
+#endif
+
+ /* For the CPC mtime region, the minimum size is 0x10000. */
+ rc = sbi_domain_root_add_memrange(CM_BASE, SIZE_FOR_CPC_MTIME,
+ P8700_ALIGN,
+ (SBI_DOMAIN_MEMREGION_MMIO |
+ SBI_DOMAIN_MEMREGION_M_READABLE |
+ SBI_DOMAIN_MEMREGION_M_WRITABLE));
+ if (rc)
+ return rc;
+
+ /* For the APLIC and ACLINT m-mode region */
+ rc = sbi_domain_root_add_memrange(AIA_BASE, SIZE_FOR_AIA_M_MODE,
+ P8700_ALIGN,
+ (SBI_DOMAIN_MEMREGION_MMIO |
+ SBI_DOMAIN_MEMREGION_M_READABLE |
+ SBI_DOMAIN_MEMREGION_M_WRITABLE));
+ if (rc)
+ return rc;
+
+#if CLUSTERS_IN_PLATFORM > 1
+ for (i = 0; i < CLUSTERS_IN_PLATFORM; i++) {
+ /* For the CPC mtime region, the minimum size is 0x10000. */
+ rc = sbi_domain_root_add_memrange(GLOBAL_CM_BASE[i], SIZE_FOR_CPC_MTIME,
+ P8700_ALIGN,
+ (SBI_DOMAIN_MEMREGION_MMIO |
+ SBI_DOMAIN_MEMREGION_M_READABLE |
+ SBI_DOMAIN_MEMREGION_M_WRITABLE));
+ if (rc)
+ return rc;
+
+ /* For the APLIC and ACLINT m-mode region */
+ rc = sbi_domain_root_add_memrange(AIA_BASE - CM_BASE + GLOBAL_CM_BASE[i], SIZE_FOR_AIA_M_MODE,
+ P8700_ALIGN,
+ (SBI_DOMAIN_MEMREGION_MMIO |
+ SBI_DOMAIN_MEMREGION_M_READABLE |
+ SBI_DOMAIN_MEMREGION_M_WRITABLE));
+ if (rc)
+ return rc;
+ }
+#endif
+ }
+
+ return 0;
+}
+
+static const struct fdt_match mips_p8700_match[] = {
+ { .compatible = "mips,p8700" },
+ { },
+};
+
+const struct platform_override mips_p8700 = {
+ .match_table = mips_p8700_match,
+ .early_init = mips_p8700_early_init,
+ .final_init = mips_p8700_final_init,
+};
--
2.47.1
^ permalink raw reply related [flat|nested] 70+ messages in thread* [PATCH v2 08/11] platform: generic: mips: add a dts file
2025-02-12 12:27 ` Anup Patel
` (6 preceding siblings ...)
2025-02-26 0:53 ` [PATCH v2 07/11] platform: generic: mips: add the platform file Chao-ying Fu
@ 2025-02-26 0:53 ` Chao-ying Fu
2025-02-26 0:53 ` [PATCH v2 09/11] platform: generic: mips: add objects.mk Chao-ying Fu
` (40 subsequent siblings)
48 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-02-26 0:53 UTC (permalink / raw)
To: opensbi
We add a dts file for 4 cores 2 threads each on a Boston board.
---
platform/generic/mips/mips,boston-p8700.dts | 353 ++++++++++++++++++++
1 file changed, 353 insertions(+)
create mode 100644 platform/generic/mips/mips,boston-p8700.dts
diff --git a/platform/generic/mips/mips,boston-p8700.dts b/platform/generic/mips/mips,boston-p8700.dts
new file mode 100644
index 0000000..9e3ca2a
--- /dev/null
+++ b/platform/generic/mips/mips,boston-p8700.dts
@@ -0,0 +1,353 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 MIPS
+ *
+ */
+
+/dts-v1/;
+
+#define CM_BASE 0x16100000
+#define APLIC_M_BASE (CM_BASE + 0x40000)
+#define APLIC_S_BASE (CM_BASE + 0x60000)
+#define MSWI_BASE (CM_BASE + 0x50000)
+#define MTIMER_BASE (MSWI_BASE + 0x4000)
+#define CPC_TIMER (CM_BASE + 0x8050)
+
+#define BITFILE_FREQUENCY 25000000
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ model = "MIPS P8700";
+ compatible = "mips,p8700";
+
+ chosen {
+ stdout-path = &uart0;
+ // For Qemu
+ //bootargs = "root=/dev/sda rw earlycon console=ttyS0,115200n8r";
+ // For a Boston board
+ bootargs = "root=/dev/mmcblk0p5 rw rootwait earlycon console=ttyS0,115200n8r";
+
+ opensbi-domains {
+ compatible = "opensbi,domain,config";
+
+ tmem: tmem {
+ compatible = "opensbi,domain,memregion";
+ base = <0x0 0x80000000>;
+ order = <31>;
+ };
+
+ allmem: allmem {
+ compatible = "opensbi,domain,memregion";
+ base = <0x0 0x0>;
+ order = <64>;
+ };
+
+ tdomain: trusted-domain {
+ compatible = "opensbi,domain,instance";
+ possible-harts = <&cpu0 &cpu1 &cpu2 &cpu3 &cpu4 &cpu5 &cpu6 &cpu7>;
+ regions = <&tmem 0x3f>, <&allmem 0x3f>;
+ };
+ };
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ timebase-frequency = <BITFILE_FREQUENCY>;
+
+ cpu0: cpu at 0 {
+ phandle = <0x00000001>;
+ device_type = "cpu";
+ compatible = "riscv";
+ opensbi-domain = <&tdomain>;
+ mmu-type = "riscv,sv39";
+ riscv,isa = "rv64imafdcsu";
+ status = "okay";
+ reg = <0x00000000>;
+
+ interrupt-controller {
+ phandle = <0x00000002>;
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu1: cpu at 1 {
+ phandle = <0x00000005>;
+ device_type = "cpu";
+ compatible = "riscv";
+ opensbi-domain = <&tdomain>;
+ mmu-type = "riscv,sv39";
+ riscv,isa = "rv64imafdcsu";
+ status = "okay";
+ reg = <0x00000001>;
+
+ interrupt-controller {
+ phandle = <0x00000006>;
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu2: cpu at 2 {
+ phandle = <0x00000007>;
+ device_type = "cpu";
+ compatible = "riscv";
+ opensbi-domain = <&tdomain>;
+ mmu-type = "riscv,sv39";
+ riscv,isa = "rv64imafdcsu";
+ status = "okay";
+ reg = <0x00000010>;
+
+ interrupt-controller {
+ phandle = <0x00000008>;
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu3: cpu at 3 {
+ phandle = <0x00000009>;
+ device_type = "cpu";
+ compatible = "riscv";
+ opensbi-domain = <&tdomain>;
+ mmu-type = "riscv,sv39";
+ riscv,isa = "rv64imafdcsu";
+ status = "okay";
+ reg = <0x00000011>;
+
+ interrupt-controller {
+ phandle = <0x0000000a>;
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu4: cpu at 4 {
+ phandle = <0x0000000b>;
+ device_type = "cpu";
+ compatible = "riscv";
+ opensbi-domain = <&tdomain>;
+ mmu-type = "riscv,sv39";
+ riscv,isa = "rv64imafdcsu";
+ status = "okay";
+ reg = <0x00000020>;
+
+ interrupt-controller {
+ phandle = <0x0000000c>;
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu5: cpu at 5 {
+ phandle = <0x0000000d>;
+ device_type = "cpu";
+ compatible = "riscv";
+ opensbi-domain = <&tdomain>;
+ mmu-type = "riscv,sv39";
+ riscv,isa = "rv64imafdcsu";
+ status = "okay";
+ reg = <0x00000021>;
+
+ interrupt-controller {
+ phandle = <0x0000000e>;
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu6: cpu at 6 {
+ phandle = <0x0000000f>;
+ device_type = "cpu";
+ compatible = "riscv";
+ opensbi-domain = <&tdomain>;
+ mmu-type = "riscv,sv39";
+ riscv,isa = "rv64imafdcsu";
+ status = "okay";
+ reg = <0x00000030>;
+
+ interrupt-controller {
+ phandle = <0x00000010>;
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu7: cpu at 7 {
+ phandle = <0x00000011>;
+ device_type = "cpu";
+ compatible = "riscv";
+ opensbi-domain = <&tdomain>;
+ mmu-type = "riscv,sv39";
+ riscv,isa = "rv64imafdcsu";
+ status = "okay";
+ reg = <0x00000031>;
+
+ interrupt-controller {
+ phandle = <0x00000012>;
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+ };
+
+ memory at 0 {
+ device_type = "memory";
+ reg = <0x80000000 0x80000000>;
+ };
+
+ pci2: pci at 14000000 {
+ compatible = "xlnx,axi-pcie-host-1.00.a";
+ device_type = "pci";
+ reg = <0x14000000 0x2000000>;
+
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+
+ interrupt-parent = <4>;
+ interrupts = <0x00000007 0x00000004>;
+
+ ranges = <0x02000000 0 0x16000000
+ 0x16000000 0 0x100000>;
+
+ bus-range = <0x00 0xff>;
+
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &pci2_intc 1>,
+ <0 0 0 2 &pci2_intc 2>,
+ <0 0 0 3 &pci2_intc 3>,
+ <0 0 0 4 &pci2_intc 4>;
+
+ pci2_intc: interrupt-controller {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ };
+
+ pci2_root at 0,0,0 {
+ compatible = "pci10ee,7021", "pci-bridge";
+ reg = <0x00000000 0 0 0 0>;
+
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+
+ eg20t_bridge at 1,0,0 {
+ compatible = "pci8086,8800", "pci-bridge";
+ reg = <0x00010000 0 0 0 0>;
+
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+
+ eg20t_mac at 2,0,1 {
+ compatible = "pci8086,8802", "intel,pch-gbe";
+ reg = <0x00020100 0 0 0 0>;
+ phy-reset-gpios = <&eg20t_gpio 6 1>;
+ };
+
+ eg20t_gpio: eg20t_gpio at 2,0,2 {
+ compatible = "pci8086,8803", "intel,eg20t-gpio";
+ reg = <0x00020200 0 0 0 0>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ eg20t_i2c at 2,12,2 {
+ compatible = "pci8086,8817";
+ reg = <0x00026200 0 0 0 0>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rtc at 68 {
+ compatible = "st,m41t81s";
+ reg = <0x68>;
+ };
+ };
+ };
+ };
+ };
+
+ uart0: uart at 17ffe000 {
+ compatible = "ns16550a";
+ reg = <0x17ffe000 0x1000>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+
+ interrupt-parent = <4>;
+ interrupts = <0x00000004 0x00000004>;
+
+ clock-frequency = <BITFILE_FREQUENCY>;
+
+ u-boot,dm-pre-reloc;
+ };
+
+ lcd: lcd at 17fff000 {
+ compatible = "img,boston-lcd";
+ reg = <0x17fff000 0x8>;
+ };
+
+ flash at 18000000 {
+ compatible = "cfi-flash";
+ reg = <0x18000000 0x8000000>;
+ bank-width = <2>;
+ };
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges;
+
+ aplic_s0 {
+ phandle = <0x00000004>;
+ #interrupt-cells = <0x00000002>;
+ compatible = "riscv,aplic";
+ interrupt-controller;
+ interrupts-extended = <2 9 6 9 8 9 10 9 12 9 14 9 16 9 18 9>;
+ reg = <APLIC_S_BASE 0x00008000>;
+ riscv,num-sources = <0x00000035>;
+ };
+
+ aplic_m0 {
+ phandle = <0x00000003>;
+ #interrupt-cells = <0x00000002>;
+ riscv,delegate = <0x00000004 0x00000001 0x00000035>;
+ riscv,children = <0x00000004>;
+ compatible = "riscv,aplic";
+ interrupt-controller;
+ interrupts-extended = <2 11 6 11 8 11 10 11 12 11 14 11 16 11 18 11>;
+ reg = <APLIC_M_BASE 0x00008000>;
+ riscv,num-sources = <0x00000035>;
+ };
+
+ mswi0 {
+ compatible = "riscv,aclint-mswi";
+ interrupts-extended = <2 3>, <6 3>, <8 3>, <10 3>, <12 3>, <14 3>, <16 3>, <18 3>;
+ reg = <MSWI_BASE 0x4000>;
+ interrupt-controller;
+ #interrupt-cells = <0>;
+ };
+
+ mtimer0 {
+ compatible = "riscv,aclint-mtimer";
+ reg = <CPC_TIMER 0x8>,
+ <MTIMER_BASE 0x7ff8>;
+ interrupts-extended = <2 7>, <6 7>, <8 7>, <10 7>, <12 7>, <14 7>, <16 7>, <18 7>;
+ };
+ };
+};
--
2.47.1
^ permalink raw reply related [flat|nested] 70+ messages in thread* [PATCH v2 09/11] platform: generic: mips: add objects.mk
2025-02-12 12:27 ` Anup Patel
` (7 preceding siblings ...)
2025-02-26 0:53 ` [PATCH v2 08/11] platform: generic: mips: add a dts file Chao-ying Fu
@ 2025-02-26 0:53 ` Chao-ying Fu
2025-02-26 0:53 ` [PATCH v2 10/11] Change to jump to mips_cps_core_entry Chao-ying Fu
` (39 subsequent siblings)
48 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-02-26 0:53 UTC (permalink / raw)
To: opensbi
We build MIPS files.
---
platform/generic/mips/objects.mk | 7 +++++++
1 file changed, 7 insertions(+)
create mode 100644 platform/generic/mips/objects.mk
diff --git a/platform/generic/mips/objects.mk b/platform/generic/mips/objects.mk
new file mode 100644
index 0000000..0254d35
--- /dev/null
+++ b/platform/generic/mips/objects.mk
@@ -0,0 +1,7 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+
+carray-platform_override_modules-$(CONFIG_PLATFORM_MIPS_P8700) += mips_p8700
+platform-objs-$(CONFIG_PLATFORM_MIPS_P8700) += mips/p8700.o mips/stw.o mips/cps-vec.o
+platform-dtb-$(CONFIG_PLATFORM_MIPS_P8700) += mips/mips,boston-p8700.dtb
--
2.47.1
^ permalink raw reply related [flat|nested] 70+ messages in thread* [PATCH v2 10/11] Change to jump to mips_cps_core_entry
2025-02-12 12:27 ` Anup Patel
` (8 preceding siblings ...)
2025-02-26 0:53 ` [PATCH v2 09/11] platform: generic: mips: add objects.mk Chao-ying Fu
@ 2025-02-26 0:53 ` Chao-ying Fu
2025-02-26 0:53 ` [PATCH v2 11/11] Initialize MIPS custom PMA registers Chao-ying Fu
` (38 subsequent siblings)
48 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-02-26 0:53 UTC (permalink / raw)
To: opensbi
For MIPS P8700, all harts start from mips_cps_core_entry.
---
firmware/fw_base.S | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/firmware/fw_base.S b/firmware/fw_base.S
index 536bcd2..1812736 100644
--- a/firmware/fw_base.S
+++ b/firmware/fw_base.S
@@ -45,6 +45,11 @@
.align 3
.globl _start
.globl _start_warm
+#ifdef CONFIG_PLATFORM_MIPS_P8700
+ lla t0, mips_cps_core_entry
+ jr t0
+#endif
+
_start:
/* Find preferred boot HART id */
MOV_3R s0, a0, s1, a1, s2, a2
--
2.47.1
^ permalink raw reply related [flat|nested] 70+ messages in thread* [PATCH v2 11/11] Initialize MIPS custom PMA registers
2025-02-12 12:27 ` Anup Patel
` (9 preceding siblings ...)
2025-02-26 0:53 ` [PATCH v2 10/11] Change to jump to mips_cps_core_entry Chao-ying Fu
@ 2025-02-26 0:53 ` Chao-ying Fu
2025-04-10 22:45 ` [PATCH v3 0/9] *** Add MIPS P8700 platform *** Chao-ying Fu
` (37 subsequent siblings)
48 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-02-26 0:53 UTC (permalink / raw)
To: opensbi
Before PMP set up, we need to set up MIPS custom PMA registers.
---
lib/sbi/riscv_asm.c | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/lib/sbi/riscv_asm.c b/lib/sbi/riscv_asm.c
index c7d75ac..ca7edbe 100644
--- a/lib/sbi/riscv_asm.c
+++ b/lib/sbi/riscv_asm.c
@@ -12,6 +12,9 @@
#include <sbi/sbi_error.h>
#include <sbi/sbi_platform.h>
#include <sbi/sbi_console.h>
+#ifdef CONFIG_PLATFORM_MIPS_P8700
+#include <mips/p8700.h>
+#endif
/* determine CPU extension, return non-zero support */
int misa_extension_imp(char ext)
@@ -119,6 +122,9 @@ unsigned long csr_read_num(int csr_num)
unsigned long ret = 0;
switch (csr_num) {
+#ifdef CONFIG_PLATFORM_MIPS_P8700
+ switchcase_csr_read_16(CSR_MIPSPMACFG0, ret)
+#endif
switchcase_csr_read_16(CSR_PMPCFG0, ret)
switchcase_csr_read_64(CSR_PMPADDR0, ret)
switchcase_csr_read(CSR_MCYCLE, ret)
@@ -199,6 +205,9 @@ void csr_write_num(int csr_num, unsigned long val)
switchcase_csr_write_32(__csr_num + 32, __val)
switch (csr_num) {
+#ifdef CONFIG_PLATFORM_MIPS_P8700
+ switchcase_csr_write_16(CSR_MIPSPMACFG0, val)
+#endif
switchcase_csr_write_16(CSR_PMPCFG0, val)
switchcase_csr_write_64(CSR_PMPADDR0, val)
switchcase_csr_write(CSR_MCYCLE, val)
@@ -301,6 +310,29 @@ int is_pmp_entry_mapped(unsigned long entry)
return false;
}
+#ifdef CONFIG_PLATFORM_MIPS_P8700
+extern unsigned long _fw_start;
+static void pma_set(unsigned int n, unsigned long addr)
+{
+ int pmacfg_csr, pmacfg_shift;
+ unsigned long cfgmask;
+ unsigned long pmacfg, cca;
+
+ pmacfg_csr = (CSR_MIPSPMACFG0 + (n >> 2)) & ~1;
+ pmacfg_shift = (n & 7) << 3;
+ cfgmask = ~(0xffUL << pmacfg_shift);
+
+ /* Read pmacfg to change cacheability */
+ pmacfg = (csr_read_num(pmacfg_csr) & cfgmask);
+ if (addr >= (unsigned long)&_fw_start)
+ cca = CCA_CACHE_ENABLE | PMA_SPECULATION;
+ else
+ cca = CCA_CACHE_DISABLE;
+ pmacfg |= ((cca << pmacfg_shift) & ~cfgmask);
+ csr_write_num(pmacfg_csr, pmacfg);
+}
+#endif
+
int pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
unsigned long log2len)
{
@@ -312,6 +344,10 @@ int pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
if (n >= PMP_COUNT || log2len > __riscv_xlen || log2len < PMP_SHIFT)
return SBI_EINVAL;
+#ifdef CONFIG_PLATFORM_MIPS_P8700
+ pma_set(n, addr);
+#endif
+
/* calculate PMP register and offset */
#if __riscv_xlen == 32
pmpcfg_csr = CSR_PMPCFG0 + (n >> 2);
--
2.47.1
^ permalink raw reply related [flat|nested] 70+ messages in thread* [PATCH v3 0/9] *** Add MIPS P8700 platform ***
2025-02-12 12:27 ` Anup Patel
` (10 preceding siblings ...)
2025-02-26 0:53 ` [PATCH v2 11/11] Initialize MIPS custom PMA registers Chao-ying Fu
@ 2025-04-10 22:45 ` Chao-ying Fu
2025-04-10 22:45 ` [PATCH v3 1/9] platform: generic: mips: add P8700 Chao-ying Fu
` (36 subsequent siblings)
48 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-04-10 22:45 UTC (permalink / raw)
To: opensbi; +Cc: Chao-ying Fu
***
Changes in v3:
Remove stw.s, stw.h, and extra scratch space.
Use nascent_init to initialze MIPS CSRs.
Add amo emulation via illegal instruction exceptions.
Change to use AMO and RDTIME illegal instruction exceptions.
Revise the dts file.
Remove code that jumps to mips_cps_core_entry.
Changes in v2:
Break up one patch to 11 patches.
***
Chao-ying Fu (9):
platform: generic: mips: add P8700
platform: generic: mips: add header files
platform: generic: mips: add an entry function
platform: generic: add nanscent_init to platform_override
platform: generic: mips: add the platform file
lib: Emulate amo instructions
platform: generic: mips: add a dts file
platform: generic: mips: add objects.mk
Initialize MIPS custom PMA registers
include/sbi/sbi_atomic.h | 90 ++++
lib/sbi/objects.mk | 1 +
lib/sbi/riscv_asm.c | 36 ++
lib/sbi/sbi_atomic.c | 182 +++++++
lib/sbi/sbi_illegal_insn.c | 492 +++++++++++++++++++
platform/generic/Kconfig | 4 +
platform/generic/configs/defconfig | 1 +
platform/generic/include/mips/board.h | 33 ++
platform/generic/include/mips/mips-cm.h | 88 ++++
platform/generic/include/mips/p8700.h | 122 +++++
platform/generic/include/platform_override.h | 1 +
platform/generic/mips/cps-vec.S | 75 +++
platform/generic/mips/mips,boston-p8700.dts | 339 +++++++++++++
platform/generic/mips/objects.mk | 7 +
platform/generic/mips/p8700.c | 267 ++++++++++
platform/generic/platform.c | 6 +-
16 files changed, 1743 insertions(+), 1 deletion(-)
create mode 100644 include/sbi/sbi_atomic.h
create mode 100644 lib/sbi/sbi_atomic.c
create mode 100644 platform/generic/include/mips/board.h
create mode 100644 platform/generic/include/mips/mips-cm.h
create mode 100644 platform/generic/include/mips/p8700.h
create mode 100644 platform/generic/mips/cps-vec.S
create mode 100644 platform/generic/mips/mips,boston-p8700.dts
create mode 100644 platform/generic/mips/objects.mk
create mode 100644 platform/generic/mips/p8700.c
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply [flat|nested] 70+ messages in thread* [PATCH v3 1/9] platform: generic: mips: add P8700
2025-02-12 12:27 ` Anup Patel
` (11 preceding siblings ...)
2025-04-10 22:45 ` [PATCH v3 0/9] *** Add MIPS P8700 platform *** Chao-ying Fu
@ 2025-04-10 22:45 ` Chao-ying Fu
2025-04-10 22:45 ` [PATCH v3 2/9] platform: generic: mips: add header files Chao-ying Fu
` (35 subsequent siblings)
48 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-04-10 22:45 UTC (permalink / raw)
To: opensbi; +Cc: Chao-ying Fu
Add a new config first.
Signed-off-by: Chao-ying Fu <cfu@mips.com>
---
platform/generic/Kconfig | 4 ++++
platform/generic/configs/defconfig | 1 +
2 files changed, 5 insertions(+)
diff --git a/platform/generic/Kconfig b/platform/generic/Kconfig
index 688da3f..a24d6ab 100644
--- a/platform/generic/Kconfig
+++ b/platform/generic/Kconfig
@@ -68,6 +68,10 @@ config PLATFORM_THEAD
select THEAD_C9XX_PMU
default n
+config PLATFORM_MIPS_P8700
+ bool "MIPS P8700 support"
+ default n
+
source "$(OPENSBI_SRC_DIR)/platform/generic/andes/Kconfig"
source "$(OPENSBI_SRC_DIR)/platform/generic/thead/Kconfig"
diff --git a/platform/generic/configs/defconfig b/platform/generic/configs/defconfig
index bb26062..ce1f1ae 100644
--- a/platform/generic/configs/defconfig
+++ b/platform/generic/configs/defconfig
@@ -6,6 +6,7 @@ CONFIG_PLATFORM_SIFIVE_FU740=y
CONFIG_PLATFORM_SOPHGO_SG2042=y
CONFIG_PLATFORM_STARFIVE_JH7110=y
CONFIG_PLATFORM_THEAD=y
+CONFIG_PLATFORM_MIPS_P8700=n
CONFIG_FDT_CPPC=y
CONFIG_FDT_CPPC_RPMI=y
CONFIG_FDT_GPIO=y
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 70+ messages in thread* [PATCH v3 2/9] platform: generic: mips: add header files
2025-02-12 12:27 ` Anup Patel
` (12 preceding siblings ...)
2025-04-10 22:45 ` [PATCH v3 1/9] platform: generic: mips: add P8700 Chao-ying Fu
@ 2025-04-10 22:45 ` Chao-ying Fu
2025-04-10 22:45 ` [PATCH v3 3/9] platform: generic: mips: add an entry function Chao-ying Fu
` (34 subsequent siblings)
48 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-04-10 22:45 UTC (permalink / raw)
To: opensbi; +Cc: Chao-ying Fu
Add header files to define MIPS Custom CSRs and define for the board.
Add accessor functions for MIPS CM registers.
Signed-off-by: Chao-ying Fu <cfu@mips.com>
---
platform/generic/include/mips/board.h | 33 +++++++
platform/generic/include/mips/mips-cm.h | 88 +++++++++++++++++
platform/generic/include/mips/p8700.h | 122 ++++++++++++++++++++++++
3 files changed, 243 insertions(+)
create mode 100644 platform/generic/include/mips/board.h
create mode 100644 platform/generic/include/mips/mips-cm.h
create mode 100644 platform/generic/include/mips/p8700.h
diff --git a/platform/generic/include/mips/board.h b/platform/generic/include/mips/board.h
new file mode 100644
index 0000000..6fe7b8b
--- /dev/null
+++ b/platform/generic/include/mips/board.h
@@ -0,0 +1,33 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 MIPS
+ *
+ */
+
+#ifndef __BOARD_H__
+#define __BOARD_H__
+
+/* Please review all defines to change for your board. */
+
+/* Use in stw.S, p8700.c, p8700.h, mips-cm.h */
+#define CM_BASE 0x16100000
+
+/* Use in mips-cm.h, p8700.c */
+#define CLUSTERS_IN_PLATFORM 1
+#if CLUSTERS_IN_PLATFORM > 1
+/* Define global CM bases for cluster 0, 1, 2, and more. */
+#define GLOBAL_CM_BASE0 0
+#define GLOBAL_CM_BASE1 0
+#define GLOBAL_CM_BASE2 0
+#endif
+
+/* Use in stw.S */
+#define TIMER_ADDR (CM_BASE + 0x8050)
+
+/* Use in cps-vec.S */
+#define DRAM_ADDRESS 0x80000000
+#define DRAM_SIZE 0x80000000
+#define DRAM_PMP_ADDR ((DRAM_ADDRESS >> 2) | ((DRAM_SIZE - 1) >> 3))
+
+#endif
diff --git a/platform/generic/include/mips/mips-cm.h b/platform/generic/include/mips/mips-cm.h
new file mode 100644
index 0000000..19b4384
--- /dev/null
+++ b/platform/generic/include/mips/mips-cm.h
@@ -0,0 +1,88 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 MIPS
+ *
+ */
+
+#ifndef __MIPS_CM_H__
+#define __MIPS_CM_H__
+
+#include <mips/p8700.h>
+#include <sbi/sbi_console.h>
+
+/* Define 1 to print out CM read and write info */
+#define DEBUG_CM 0
+
+#if CLUSTERS_IN_PLATFORM > 1
+static long GLOBAL_CM_BASE[CLUSTERS_IN_PLATFORM] = {GLOBAL_CM_BASE0, GLOBAL_CM_BASE1, GLOBAL_CM_BASE2};
+#else
+static long GLOBAL_CM_BASE[CLUSTERS_IN_PLATFORM] = {CM_BASE};
+#endif
+
+#define CPS_ACCESSOR_R(unit, sz, base, off, name) \
+static inline u##sz read_##unit##_##name(u32 hartid, bool local_p) \
+{ \
+ u##sz value; \
+ long cmd_reg; \
+ int cl, co; \
+ cl = cpu_cluster(hartid); \
+ co = cpu_core(hartid); \
+ cmd_reg = (local_p ? (base) : ((base) - CM_BASE + GLOBAL_CM_BASE[cl])) \
+ + (co << CM_BASE_CORE_SHIFT) \
+ + off; \
+ if (DEBUG_CM) \
+ sbi_printf("CM READ%d cmd_reg=%lx\n", sz, cmd_reg); \
+ if (sz == 32) \
+ asm volatile("lw %0,0(%1)":"=r"(value):"r"(cmd_reg)); \
+ else if (sz == 64) \
+ asm volatile("ld %0,0(%1)":"=r"(value):"r"(cmd_reg)); \
+ asm volatile("fence"); \
+ return value; \
+}
+
+#define CPS_ACCESSOR_W(unit, sz, base, off, name) \
+static inline void write_##unit##_##name(u32 hartid, u##sz value, bool local_p) \
+{ \
+ long cmd_reg; \
+ int cl, co; \
+ cl = cpu_cluster(hartid); \
+ co = cpu_core(hartid); \
+ cmd_reg = (local_p ? (base) : ((base) - CM_BASE + GLOBAL_CM_BASE[cl])) \
+ + (co << CM_BASE_CORE_SHIFT) \
+ + off; \
+ if (DEBUG_CM) \
+ sbi_printf("CM WRITE%d cmd_reg=%lx value=%lx\n", sz, \
+ cmd_reg, (u64)value); \
+ if (sz == 32) \
+ asm volatile("sw %0,0(%1)"::"r"(value),"r"(cmd_reg)); \
+ else if (sz == 64) \
+ asm volatile("sd %0,0(%1)"::"r"(value),"r"(cmd_reg)); \
+ asm volatile("fence"); \
+}
+
+#define CPS_ACCESSOR_RW(unit, sz, base, off, name) \
+ CPS_ACCESSOR_R(unit, sz, base, off, name) \
+ CPS_ACCESSOR_W(unit, sz, base, off, name)
+
+#define CPC_CX_ACCESSOR_RW(sz, off, name) \
+ CPS_ACCESSOR_RW(cpc, sz, CPC_BASE, CPC_OFF_LOCAL + (off), co_##name)
+
+#define GCR_CX_ACCESSOR_RW(sz, off, name) \
+ CPS_ACCESSOR_RW(gcr, sz, CM_BASE, GCR_OFF_LOCAL + (off), co_##name)
+
+GCR_CX_ACCESSOR_RW(64, cpu_hart(hartid) << CM_BASE_HART_SHIFT, reset_base)
+GCR_CX_ACCESSOR_RW(32, GCR_CORE_COH_EN, coherence)
+
+CPC_CX_ACCESSOR_RW(32, CPC_Cx_VP_RUN, vp_run)
+CPC_CX_ACCESSOR_RW(32, CPC_Cx_VP_STOP, vp_stop)
+CPC_CX_ACCESSOR_RW(32, CPC_Cx_CMD, cmd)
+CPC_CX_ACCESSOR_RW(32, CPC_Cx_STAT_CONF, stat_conf)
+
+#define CPC_ACCESSOR_RW(sz, off, name) \
+ CPS_ACCESSOR_RW(cpc, sz, CPC_BASE, off, name)
+
+CPC_ACCESSOR_RW(32, CPC_PWRUP_CTL, pwrup_ctl)
+CPC_ACCESSOR_RW(32, CPC_CM_STAT_CONF, cm_stat_conf)
+
+#endif
diff --git a/platform/generic/include/mips/p8700.h b/platform/generic/include/mips/p8700.h
new file mode 100644
index 0000000..6aa71d9
--- /dev/null
+++ b/platform/generic/include/mips/p8700.h
@@ -0,0 +1,122 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 MIPS
+ *
+ */
+
+#ifndef __P8700_H__
+#define __P8700_H__
+
+#include <mips/board.h>
+
+/* PMA */
+#define CSR_MIPSPMACFG0 0x7e0
+#define CSR_MIPSPMACFG1 0x7e1
+#define CSR_MIPSPMACFG2 0x7e2
+#define CSR_MIPSPMACFG3 0x7e3
+#define CSR_MIPSPMACFG4 0x7e4
+#define CSR_MIPSPMACFG5 0x7e5
+#define CSR_MIPSPMACFG6 0x7e6
+#define CSR_MIPSPMACFG7 0x7e7
+#define CSR_MIPSPMACFG8 0x7e8
+#define CSR_MIPSPMACFG9 0x7e9
+#define CSR_MIPSPMACFG10 0x7ea
+#define CSR_MIPSPMACFG11 0x7eb
+#define CSR_MIPSPMACFG12 0x7ec
+#define CSR_MIPSPMACFG13 0x7ed
+#define CSR_MIPSPMACFG14 0x7ee
+#define CSR_MIPSPMACFG15 0x7ef
+
+/* MIPS CCA */
+#define CCA_CACHE_ENABLE 0
+#define CCA_CACHE_DISABLE 2
+#define PMA_SPECULATION (1 << 3)
+
+/* MIPS CSR */
+#define CSR_MIPSTVEC 0x7c0
+#define CSR_MIPSCONFIG0 0x7d0
+#define CSR_MIPSCONFIG1 0x7d1
+#define CSR_MIPSCONFIG2 0x7d2
+#define CSR_MIPSCONFIG3 0x7d3
+#define CSR_MIPSCONFIG4 0x7d4
+#define CSR_MIPSCONFIG5 0x7d5
+#define CSR_MIPSCONFIG6 0x7d6
+#define CSR_MIPSCONFIG7 0x7d7
+#define CSR_MIPSCONFIG8 0x7d8
+#define CSR_MIPSCONFIG9 0x7d9
+#define CSR_MIPSCONFIG10 0x7da
+#define CSR_MIPSCONFIG11 0x7db
+
+#define MIPSCONFIG5_MTW 4
+
+#define GEN_MASK(h, l) (((1ul << ((h) + 1 - (l))) - 1) << (l))
+#define EXT(val, mask) (((val) & (mask)) >> (__builtin_ffs(mask) - 1))
+
+/*
+ * We allocate the number of bits to encode clusters, cores, and harts
+ * from the original mhartid to a new dense index.
+ */
+#define NUM_OF_BITS_FOR_CLUSTERS 4
+#define NUM_OF_BITS_FOR_CORES 12
+#define NUM_OF_BITS_FOR_HARTS 4
+
+/* mhartid field info */
+#define MHARTID_CORE_MASK 0xff
+#define MHARTID_CORE_SHIFT 4
+
+/* To get the field from new/hashed mhartid */
+#define NEW_CLUSTER_SHIFT (NUM_OF_BITS_FOR_CORES + NUM_OF_BITS_FOR_HARTS)
+#define NEW_CLUSTER_MASK ((1 << NUM_OF_BITS_FOR_CLUSTERS) - 1)
+#define NEW_CORE_SHIFT NUM_OF_BITS_FOR_HARTS
+#define NEW_CORE_MASK ((1 << NUM_OF_BITS_FOR_CORES) - 1)
+#define NEW_HART_MASK ((1 << NUM_OF_BITS_FOR_HARTS) - 1)
+#define cpu_cluster(i) (((i) >> NEW_CLUSTER_SHIFT) & NEW_CLUSTER_MASK)
+#define cpu_core(i) (((i) >> NEW_CORE_SHIFT) & NEW_CORE_MASK)
+#define cpu_hart(i) ((i) & NEW_HART_MASK)
+
+#define CPC_BASE (CM_BASE + 0x8000)
+
+#define SIZE_FOR_CPC_MTIME 0x10000 /* The size must be 2^order */
+#define AIA_BASE (CM_BASE + 0x40000)
+#define SIZE_FOR_AIA_M_MODE 0x20000 /* The size must be 2^order */
+#define P8700_ALIGN 0x10000
+
+#define CM_BASE_HART_SHIFT 3
+#define CM_BASE_CORE_SHIFT 8
+#define CM_BASE_CLUSTER_SHIFT 19
+
+/* GCR Block offsets */
+#define GCR_OFF_LOCAL 0x2000
+
+#define GCR_BASE_OFFSET 0x0008
+#define GCR_CORE_COH_EN 0x00f8
+#define GCR_CORE_COH_EN_EN (0x1 << 0)
+
+#define L2_PFT_CONTROL_OFFSET 0x0300
+#define L2_PFT_CONTROL_B_OFFSET 0x0308
+
+/* CPC Block offsets */
+#define CPC_PWRUP_CTL 0x0030
+#define CPC_CM_STAT_CONF 0x1008
+
+#define CPC_OFF_LOCAL 0x2000
+
+#define CPC_Cx_VP_STOP 0x0020
+#define CPC_Cx_VP_RUN 0x0028
+#define CPC_Cx_CMD 0x0000
+
+#define CPC_Cx_CMD_PWRUP 0x3
+#define CPC_Cx_CMD_RESET 0x4
+
+#define CPC_Cx_STAT_CONF 0x0008
+#define CPC_Cx_STAT_CONF_SEQ_STATE GEN_MASK(22, 19)
+#define CPC_Cx_STAT_CONF_SEQ_STATE_U5 6
+#define CPC_Cx_STAT_CONF_SEQ_STATE_U6 7
+
+#define INDEXED(op, reg, idx, offset, base) \
+ li idx, offset ;\
+ add idx, idx, base ;\
+ op reg, (idx)
+
+#endif
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 70+ messages in thread* [PATCH v3 3/9] platform: generic: mips: add an entry function
2025-02-12 12:27 ` Anup Patel
` (13 preceding siblings ...)
2025-04-10 22:45 ` [PATCH v3 2/9] platform: generic: mips: add header files Chao-ying Fu
@ 2025-04-10 22:45 ` Chao-ying Fu
2025-04-10 22:45 ` [PATCH v3 4/9] platform: generic: add nanscent_init to platform_override Chao-ying Fu
` (33 subsequent siblings)
48 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-04-10 22:45 UTC (permalink / raw)
To: opensbi; +Cc: Chao-ying Fu
The entry function is minimum boot code for harts to execute after
reset, nmi, cache error, and debug exception.
Signed-off-by: Chao-ying Fu <cfu@mips.com>
---
platform/generic/mips/cps-vec.S | 75 +++++++++++++++++++++++++++++++++
1 file changed, 75 insertions(+)
create mode 100644 platform/generic/mips/cps-vec.S
diff --git a/platform/generic/mips/cps-vec.S b/platform/generic/mips/cps-vec.S
new file mode 100644
index 0000000..9309e20
--- /dev/null
+++ b/platform/generic/mips/cps-vec.S
@@ -0,0 +1,75 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 MIPS
+ *
+ */
+
+#include <sbi/riscv_encoding.h>
+#include <mips/p8700.h>
+
+ .text
+ .align 12
+ .globl mips_cps_core_entry
+mips_cps_core_entry:
+ j 1f
+
+ .align 2
+nmi_vector:
+ j 1f
+
+ .align 2
+cacheerr_vector:
+ j 1f
+
+ .align 2
+debugexc_vector:
+ j 1f
+
+ .align 2
+1:
+ li x1, 0
+ li x2, 0
+ li x3, 0
+ li x4, 0
+ li x5, 0
+ li x6, 0
+ li x7, 0
+ li x8, 0
+ li x9, 0
+ li x10, 0
+#ifdef FW_FDT_PATH
+ li x11, 0
+#endif
+ li x12, 0
+ li x13, 0
+ li x14, 0
+ li x15, 0
+ li x16, 0
+ li x17, 0
+ li x18, 0
+ li x19, 0
+ li x20, 0
+ li x21, 0
+ li x22, 0
+ li x23, 0
+ li x24, 0
+ li x25, 0
+ li x26, 0
+ li x27, 0
+ li x28, 0
+ li x29, 0
+ li x30, 0
+ li x31, 0
+
+ /* a0 has mhartid */
+ csrr a0, CSR_MHARTID
+
+ /* Let hart 0 jump to _start */
+ beqz a0, 1f
+ lla t0, _start_warm
+ jr t0
+1:
+ lla t0, _start
+ jr t0
+
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 70+ messages in thread* [PATCH v3 4/9] platform: generic: add nanscent_init to platform_override
2025-02-12 12:27 ` Anup Patel
` (14 preceding siblings ...)
2025-04-10 22:45 ` [PATCH v3 3/9] platform: generic: mips: add an entry function Chao-ying Fu
@ 2025-04-10 22:45 ` Chao-ying Fu
2025-04-10 22:45 ` [PATCH v3 5/9] platform: generic: mips: add the platform file Chao-ying Fu
` (32 subsequent siblings)
48 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-04-10 22:45 UTC (permalink / raw)
To: opensbi; +Cc: Chao-ying Fu
This allows generic platforms to override nascent_init.
Signed-off-by: Chao-ying Fu <cfu@mips.com>
---
platform/generic/include/platform_override.h | 1 +
platform/generic/platform.c | 6 +++++-
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/platform/generic/include/platform_override.h b/platform/generic/include/platform_override.h
index 946fb8f..8d63837 100644
--- a/platform/generic/include/platform_override.h
+++ b/platform/generic/include/platform_override.h
@@ -21,6 +21,7 @@ struct platform_override {
u64 (*tlbr_flush_limit)(const struct fdt_match *match);
u32 (*tlb_num_entries)(const struct fdt_match *match);
bool (*cold_boot_allowed)(u32 hartid, const struct fdt_match *match);
+ int (*nascent_init)(const struct fdt_match *match);
int (*early_init)(bool cold_boot, const void *fdt, const struct fdt_match *match);
int (*final_init)(bool cold_boot, void *fdt, const struct fdt_match *match);
void (*early_exit)(const struct fdt_match *match);
diff --git a/platform/generic/platform.c b/platform/generic/platform.c
index b2f29e8..b7e744b 100644
--- a/platform/generic/platform.c
+++ b/platform/generic/platform.c
@@ -238,7 +238,11 @@ static int generic_nascent_init(void)
{
if (platform_has_mlevel_imsic)
imsic_local_irqchip_init();
- return 0;
+
+ if (!generic_plat || !generic_plat->nascent_init)
+ return 0;
+
+ return generic_plat->nascent_init(generic_plat_match);
}
static int generic_early_init(bool cold_boot)
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 70+ messages in thread* [PATCH v3 5/9] platform: generic: mips: add the platform file
2025-02-12 12:27 ` Anup Patel
` (15 preceding siblings ...)
2025-04-10 22:45 ` [PATCH v3 4/9] platform: generic: add nanscent_init to platform_override Chao-ying Fu
@ 2025-04-10 22:45 ` Chao-ying Fu
2025-04-10 22:45 ` [PATCH v3 6/9] lib: Emulate amo instructions Chao-ying Fu
` (31 subsequent siblings)
48 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-04-10 22:45 UTC (permalink / raw)
To: opensbi; +Cc: Chao-ying Fu
We add the platform file for MIPS P8700.
Signed-off-by: Chao-ying Fu <cfu@mips.com>
---
platform/generic/mips/p8700.c | 267 ++++++++++++++++++++++++++++++++++
1 file changed, 267 insertions(+)
create mode 100644 platform/generic/mips/p8700.c
diff --git a/platform/generic/mips/p8700.c b/platform/generic/mips/p8700.c
new file mode 100644
index 0000000..ea27118
--- /dev/null
+++ b/platform/generic/mips/p8700.c
@@ -0,0 +1,267 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 MIPS
+ *
+ */
+
+#include <platform_override.h>
+#include <sbi/sbi_domain.h>
+#include <sbi/sbi_error.h>
+#include <sbi/sbi_hsm.h>
+#include <sbi/sbi_timer.h>
+#include <sbi_utils/fdt/fdt_helper.h>
+#include <mips/p8700.h>
+#include <mips/mips-cm.h>
+
+extern void mips_cps_core_entry(void);
+
+#if CLUSTERS_IN_PLATFORM > 1
+static void power_up_other_cluster(u32 hartid)
+{
+ unsigned int stat;
+ unsigned int timeout;
+ bool local_p = (cpu_cluster(current_hartid()) == cpu_cluster(hartid));
+
+ /* Power up cluster cl core 0 hart 0 */
+ write_cpc_pwrup_ctl(hartid, 1, local_p);
+
+ /* Wait for the CM to start up */
+ timeout = 100;
+ while (true) {
+ stat = read_cpc_cm_stat_conf(hartid, local_p);
+ stat = EXT(stat, CPC_Cx_STAT_CONF_SEQ_STATE);
+ if (stat == CPC_Cx_STAT_CONF_SEQ_STATE_U5)
+ break;
+
+ /* Delay a little while before we start warning */
+ if (timeout) {
+ sbi_dprintf("Delay a little while before we start warning\n");
+ timeout--;
+ }
+ else {
+ sbi_printf("Waiting for cluster %u CM to power up... STAT_CONF=0x%x\n",
+ cpu_cluster(hartid), stat);
+ break;
+ }
+ }
+}
+#endif
+
+static int mips_hart_start(u32 hartid, ulong saddr)
+{
+ unsigned int stat;
+ unsigned int timeout;
+ bool local_p = (cpu_cluster(current_hartid()) == cpu_cluster(hartid));
+
+ /* Hart 0 is the boot hart, and we don't use the CPC cmd to start. */
+ if (hartid == 0)
+ return SBI_ENOTSUPP;
+
+ if (cpu_hart(hartid) == 0) {
+ /* Change cluster cl core co hart 0 reset base */
+ write_gcr_co_reset_base(hartid,
+ (unsigned long)mips_cps_core_entry, local_p);
+
+ /* Ensure its coherency is disabled */
+ write_gcr_co_coherence(hartid, 0, local_p);
+
+ /* Start cluster cl core co hart 0 */
+ write_cpc_co_vp_run(hartid, 1 << cpu_hart(hartid), local_p);
+
+ /* Reset cluster cl core co hart 0 */
+ write_cpc_co_cmd(hartid, CPC_Cx_CMD_RESET, local_p);
+
+ timeout = 100;
+ while (true) {
+ stat = read_cpc_co_stat_conf(hartid, local_p);
+ stat = EXT(stat, CPC_Cx_STAT_CONF_SEQ_STATE);
+ if (stat == CPC_Cx_STAT_CONF_SEQ_STATE_U6)
+ break;
+
+ /* Delay a little while before we start warning */
+ if (timeout) {
+ sbi_timer_mdelay(10);
+ timeout--;
+ }
+ else {
+ sbi_printf("Waiting for cluster %u core %u hart %u to start... STAT_CONF=0x%x\n",
+ cpu_cluster(hartid),
+ cpu_core(hartid), cpu_hart(hartid),
+ stat);
+ break;
+ }
+ }
+ }
+ else {
+ write_gcr_co_reset_base(hartid,
+ (unsigned long)mips_cps_core_entry, local_p);
+ write_cpc_co_vp_run(hartid, 1 << cpu_hart(hartid), local_p);
+ }
+
+ return 0;
+}
+
+static int mips_hart_stop()
+{
+ u32 hartid = current_hartid();
+ bool local_p = (cpu_cluster(current_hartid()) == cpu_cluster(hartid));
+
+ /* Hart 0 is the boot hart, and we don't use the CPC cmd to stop. */
+ if (hartid == 0)
+ return SBI_ENOTSUPP;
+
+ write_cpc_co_vp_stop(hartid, 1 << cpu_hart(hartid), local_p);
+
+ return 0;
+}
+
+static const struct sbi_hsm_device mips_hsm = {
+ .name = "mips_hsm",
+ .hart_start = mips_hart_start,
+ .hart_stop = mips_hart_stop,
+};
+
+static int mips_p8700_final_init(bool cold_boot, void *fdt,
+ const struct fdt_match *match)
+{
+ if (cold_boot)
+ sbi_hsm_set_device(&mips_hsm);
+
+ return 0;
+}
+
+static int mips_p8700_early_init(bool cold_boot, const void *fdt,
+ const struct fdt_match *match)
+{
+ int rc;
+
+ if (cold_boot)
+ {
+#if CLUSTERS_IN_PLATFORM > 1
+ int i;
+ /* Power up other clusters in the platform. */
+ for (i = 1; i < CLUSTERS_IN_PLATFORM; i++) {
+ power_up_other_cluster(i << NEW_CLUSTER_SHIFT);
+ }
+#endif
+
+ /* For the CPC mtime region, the minimum size is 0x10000. */
+ rc = sbi_domain_root_add_memrange(CM_BASE, SIZE_FOR_CPC_MTIME,
+ P8700_ALIGN,
+ (SBI_DOMAIN_MEMREGION_MMIO |
+ SBI_DOMAIN_MEMREGION_M_READABLE |
+ SBI_DOMAIN_MEMREGION_M_WRITABLE));
+ if (rc)
+ return rc;
+
+ /* For the APLIC and ACLINT m-mode region */
+ rc = sbi_domain_root_add_memrange(AIA_BASE, SIZE_FOR_AIA_M_MODE,
+ P8700_ALIGN,
+ (SBI_DOMAIN_MEMREGION_MMIO |
+ SBI_DOMAIN_MEMREGION_M_READABLE |
+ SBI_DOMAIN_MEMREGION_M_WRITABLE));
+ if (rc)
+ return rc;
+
+#if CLUSTERS_IN_PLATFORM > 1
+ for (i = 0; i < CLUSTERS_IN_PLATFORM; i++) {
+ /* For the CPC mtime region, the minimum size is 0x10000. */
+ rc = sbi_domain_root_add_memrange(GLOBAL_CM_BASE[i], SIZE_FOR_CPC_MTIME,
+ P8700_ALIGN,
+ (SBI_DOMAIN_MEMREGION_MMIO |
+ SBI_DOMAIN_MEMREGION_M_READABLE |
+ SBI_DOMAIN_MEMREGION_M_WRITABLE));
+ if (rc)
+ return rc;
+
+ /* For the APLIC and ACLINT m-mode region */
+ rc = sbi_domain_root_add_memrange(AIA_BASE - CM_BASE + GLOBAL_CM_BASE[i], SIZE_FOR_AIA_M_MODE,
+ P8700_ALIGN,
+ (SBI_DOMAIN_MEMREGION_MMIO |
+ SBI_DOMAIN_MEMREGION_M_READABLE |
+ SBI_DOMAIN_MEMREGION_M_WRITABLE));
+ if (rc)
+ return rc;
+ }
+#endif
+ }
+
+ return 0;
+}
+
+static int mips_p8700_nascent_init(const struct fdt_match *match)
+{
+ u64 hartid = current_hartid();
+ u64 cm_base = CM_BASE;
+ int i;
+
+ /* Coherence enable for every core */
+ if (cpu_hart(hartid) == 0) {
+ cm_base += (cpu_core(hartid) << CM_BASE_CORE_SHIFT);
+ asm volatile("sd %0,0(%1)"::"r"(GCR_CORE_COH_EN_EN),
+ "r"(cm_base + GCR_OFF_LOCAL + GCR_CORE_COH_EN));
+ asm volatile("fence");
+ }
+
+ /* Set up pmp for DRAM */
+ csr_write(CSR_PMPADDR14, DRAM_PMP_ADDR);
+ /* All from 0x0 */
+ csr_write(CSR_PMPADDR15, 0x1fffffffffffffff);
+ csr_write(CSR_PMPCFG2, ((PMP_A_NAPOT|PMP_R|PMP_W|PMP_X)<<56)|
+ ((PMP_A_NAPOT|PMP_R|PMP_W|PMP_X)<<48));
+ /* Set cacheable for pmp6, uncacheable for pmp7 */
+ csr_write(CSR_MIPSPMACFG2, ((u64)CCA_CACHE_DISABLE << 56)|
+ ((u64)CCA_CACHE_ENABLE << 48));
+ /* Reset pmpcfg0 */
+ csr_write(CSR_PMPCFG0, 0);
+ /* Reset pmacfg0 */
+ csr_write(CSR_MIPSPMACFG0, 0);
+ asm volatile("fence");
+
+ /* Per cluster set up */
+ if (cpu_core(hartid) == 0 && cpu_hart(hartid) == 0) {
+ /* Enable L2 prefetch */
+ asm volatile("sw %0,0(%1)"::"r"(0xfffff110),
+ "r"(cm_base + L2_PFT_CONTROL_OFFSET));
+ asm volatile("sw %0,0(%1)"::"r"(0x15ff),
+ "r"(cm_base + L2_PFT_CONTROL_B_OFFSET));
+ }
+
+ /* Per core set up */
+ if (cpu_hart(hartid) == 0) {
+ /* Enable load pair, store pair, and HTW */
+ csr_clear(CSR_MIPSCONFIG7, (1<<12)|(1<<13)|(1<<7));
+
+ /* Disable noRFO, misaligned load/store */
+ csr_set(CSR_MIPSCONFIG7, (1<<25)|(1<<9));
+
+ /* Enable L1-D$ Prefetch */
+ csr_write(CSR_MIPSCONFIG11, 0xff);
+
+ for (i = 0; i < 8; i++) {
+ csr_set(CSR_MIPSCONFIG8, 4 + 0x100 * i);
+ csr_set(CSR_MIPSCONFIG9, 8);
+ asm volatile("fence");
+ asm volatile("fence.i");
+ }
+ }
+
+ /* Per hart set up */
+ /* Enable AMO and RDTIME illegal instruction exceptions. */
+ csr_write(CSR_MIPSCONFIG6, (1<<2)|(1<<1));
+
+ return 0;
+}
+
+static const struct fdt_match mips_p8700_match[] = {
+ { .compatible = "mips,p8700" },
+ { },
+};
+
+const struct platform_override mips_p8700 = {
+ .match_table = mips_p8700_match,
+ .nascent_init = mips_p8700_nascent_init,
+ .early_init = mips_p8700_early_init,
+ .final_init = mips_p8700_final_init,
+};
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 70+ messages in thread* [PATCH v3 6/9] lib: Emulate amo instructions
2025-02-12 12:27 ` Anup Patel
` (16 preceding siblings ...)
2025-04-10 22:45 ` [PATCH v3 5/9] platform: generic: mips: add the platform file Chao-ying Fu
@ 2025-04-10 22:45 ` Chao-ying Fu
2025-04-10 22:45 ` [PATCH v3 7/9] platform: generic: mips: add a dts file Chao-ying Fu
` (30 subsequent siblings)
48 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-04-10 22:45 UTC (permalink / raw)
To: opensbi; +Cc: Chao-ying Fu
Match amo instruction opcode to emulate from illegal instruction
exceptions.
Signed-off-by: Chao-ying Fu <cfu@mips.com>
---
include/sbi/sbi_atomic.h | 90 +++++++
lib/sbi/objects.mk | 1 +
lib/sbi/sbi_atomic.c | 182 ++++++++++++++
lib/sbi/sbi_illegal_insn.c | 492 +++++++++++++++++++++++++++++++++++++
4 files changed, 765 insertions(+)
create mode 100644 include/sbi/sbi_atomic.h
create mode 100644 lib/sbi/sbi_atomic.c
diff --git a/include/sbi/sbi_atomic.h b/include/sbi/sbi_atomic.h
new file mode 100644
index 0000000..561da89
--- /dev/null
+++ b/include/sbi/sbi_atomic.h
@@ -0,0 +1,90 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 MIPS
+ *
+ */
+
+#ifndef __SBI_ATOMIC_H__
+#define __SBI_ATOMIC_H__
+
+#include <sbi/sbi_types.h>
+
+struct sbi_trap_regs;
+
+int sbi_atomic_add_w(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_add_d(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_and_w(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_and_d(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_or_w(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_or_d(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_xor_w(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_xor_d(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_max_w(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_max_d(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_min_w(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_min_d(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_maxu_w(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_maxu_d(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_minu_w(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_minu_d(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_swap_w(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_swap_d(ulong insn, struct sbi_trap_regs *regs);
+
+int sbi_atomic_add_w_aq(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_add_d_aq(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_and_w_aq(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_and_d_aq(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_or_w_aq(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_or_d_aq(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_xor_w_aq(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_xor_d_aq(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_max_w_aq(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_max_d_aq(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_min_w_aq(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_min_d_aq(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_maxu_w_aq(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_maxu_d_aq(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_minu_w_aq(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_minu_d_aq(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_swap_w_aq(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_swap_d_aq(ulong insn, struct sbi_trap_regs *regs);
+
+int sbi_atomic_add_w_rl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_add_d_rl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_and_w_rl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_and_d_rl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_or_w_rl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_or_d_rl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_xor_w_rl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_xor_d_rl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_max_w_rl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_max_d_rl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_min_w_rl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_min_d_rl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_maxu_w_rl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_maxu_d_rl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_minu_w_rl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_minu_d_rl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_swap_w_rl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_swap_d_rl(ulong insn, struct sbi_trap_regs *regs);
+
+int sbi_atomic_add_w_aqrl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_add_d_aqrl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_and_w_aqrl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_and_d_aqrl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_or_w_aqrl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_or_d_aqrl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_xor_w_aqrl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_xor_d_aqrl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_max_w_aqrl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_max_d_aqrl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_min_w_aqrl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_min_d_aqrl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_maxu_w_aqrl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_maxu_d_aqrl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_minu_w_aqrl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_minu_d_aqrl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_swap_w_aqrl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_swap_d_aqrl(ulong insn, struct sbi_trap_regs *regs);
+#endif
diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
index 9cb2842..af7a846 100644
--- a/lib/sbi/objects.mk
+++ b/lib/sbi/objects.mk
@@ -99,3 +99,4 @@ libsbi-objs-y += sbi_trap_v_ldst.o
libsbi-objs-y += sbi_unpriv.o
libsbi-objs-y += sbi_expected_trap.o
libsbi-objs-y += sbi_cppc.o
+libsbi-objs-y += sbi_atomic.o
diff --git a/lib/sbi/sbi_atomic.c b/lib/sbi/sbi_atomic.c
new file mode 100644
index 0000000..afd28d2
--- /dev/null
+++ b/lib/sbi/sbi_atomic.c
@@ -0,0 +1,182 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 MIPS
+ *
+ */
+
+#include <sbi/riscv_asm.h>
+#include <sbi/sbi_trap.h>
+#include <sbi/sbi_hart.h>
+
+#define DEFINE_UNPRIVILEGED_LR_FUNCTION(type, aqrl, insn) \
+ type sbi_lr_##type##aqrl(const type *addr, \
+ struct sbi_trap_info *trap) \
+ { \
+ register ulong tinfo asm("a3"); \
+ register ulong mstatus = 0; \
+ register ulong mtvec = sbi_hart_expected_trap_addr(); \
+ type ret = 0; \
+ trap->cause = 0; \
+ asm volatile( \
+ "add %[tinfo], %[taddr], zero\n" \
+ "csrrw %[mtvec], " STR(CSR_MTVEC) ", %[mtvec]\n" \
+ "csrrs %[mstatus], " STR(CSR_MSTATUS) ", %[mprv]\n" \
+ ".option push\n" \
+ ".option norvc\n" \
+ #insn " %[ret], %[addr]\n" \
+ ".option pop\n" \
+ "csrw " STR(CSR_MSTATUS) ", %[mstatus]\n" \
+ "csrw " STR(CSR_MTVEC) ", %[mtvec]" \
+ : [mstatus] "+&r"(mstatus), [mtvec] "+&r"(mtvec), \
+ [tinfo] "+&r"(tinfo), [ret] "=&r"(ret) \
+ : [addr] "m"(*addr), [mprv] "r"(MSTATUS_MPRV), \
+ [taddr] "r"((ulong)trap) \
+ : "a4", "memory"); \
+ return ret; \
+ }
+
+#define DEFINE_UNPRIVILEGED_SC_FUNCTION(type, aqrl, insn) \
+ type sbi_sc_##type##aqrl(type *addr, type val, \
+ struct sbi_trap_info *trap) \
+ { \
+ register ulong tinfo asm("a3"); \
+ register ulong mstatus = 0; \
+ register ulong mtvec = sbi_hart_expected_trap_addr(); \
+ type ret = 0; \
+ trap->cause = 0; \
+ asm volatile( \
+ "add %[tinfo], %[taddr], zero\n" \
+ "csrrw %[mtvec], " STR(CSR_MTVEC) ", %[mtvec]\n" \
+ "csrrs %[mstatus], " STR(CSR_MSTATUS) ", %[mprv]\n" \
+ ".option push\n" \
+ ".option norvc\n" \
+ #insn " %[ret], %[val], %[addr]\n" \
+ ".option pop\n" \
+ "csrw " STR(CSR_MSTATUS) ", %[mstatus]\n" \
+ "csrw " STR(CSR_MTVEC) ", %[mtvec]" \
+ : [mstatus] "+&r"(mstatus), [mtvec] "+&r"(mtvec), \
+ [tinfo] "+&r"(tinfo), [ret] "=&r"(ret) \
+ : [addr] "m"(*addr), [mprv] "r"(MSTATUS_MPRV), \
+ [val] "r"(val), [taddr] "r"((ulong)trap) \
+ : "a4", "memory"); \
+ return ret; \
+ }
+
+DEFINE_UNPRIVILEGED_LR_FUNCTION(s32, , lr.w);
+DEFINE_UNPRIVILEGED_LR_FUNCTION(s32, _aq, lr.w.aq);
+DEFINE_UNPRIVILEGED_LR_FUNCTION(s32, _rl, lr.w.rl);
+DEFINE_UNPRIVILEGED_LR_FUNCTION(s32, _aqrl, lr.w.aqrl);
+DEFINE_UNPRIVILEGED_SC_FUNCTION(s32, , sc.w);
+DEFINE_UNPRIVILEGED_SC_FUNCTION(s32, _aq, sc.w.aq);
+DEFINE_UNPRIVILEGED_SC_FUNCTION(s32, _rl, sc.w.rl);
+DEFINE_UNPRIVILEGED_SC_FUNCTION(s32, _aqrl, sc.w.aqrl);
+#if __riscv_xlen == 64
+DEFINE_UNPRIVILEGED_LR_FUNCTION(s64, , lr.d);
+DEFINE_UNPRIVILEGED_LR_FUNCTION(s64, _aq, lr.d.aq);
+DEFINE_UNPRIVILEGED_LR_FUNCTION(s64, _rl, lr.d.rl);
+DEFINE_UNPRIVILEGED_LR_FUNCTION(s64, _aqrl, lr.d.aqrl);
+DEFINE_UNPRIVILEGED_SC_FUNCTION(s64, , sc.d);
+DEFINE_UNPRIVILEGED_SC_FUNCTION(s64, _aq, sc.d.aq);
+DEFINE_UNPRIVILEGED_SC_FUNCTION(s64, _rl, sc.d.rl);
+DEFINE_UNPRIVILEGED_SC_FUNCTION(s64, _aqrl, sc.d.aqrl);
+#endif
+
+#define DEFINE_ATOMIC_FUNCTION(name, type, func) \
+ int sbi_atomic_##name(ulong insn, struct sbi_trap_regs *regs) \
+ { \
+ struct sbi_trap_info uptrap; \
+ ulong addr = GET_RS1(insn, regs); \
+ ulong val = GET_RS2(insn, regs); \
+ ulong rd_val = 0; \
+ ulong fail = 1; \
+ while (fail) { \
+ rd_val = sbi_lr_##type((void *)addr, &uptrap); \
+ if (uptrap.cause) { \
+ return sbi_trap_redirect(regs, &uptrap); \
+ } \
+ fail = sbi_sc_##type((void *)addr, func, &uptrap); \
+ if (uptrap.cause) { \
+ return sbi_trap_redirect(regs, &uptrap); \
+ } \
+ } \
+ SET_RD(insn, regs, rd_val); \
+ regs->mepc += 4; \
+ return 0; \
+ }
+
+DEFINE_ATOMIC_FUNCTION(add_w, s32, rd_val + val);
+DEFINE_ATOMIC_FUNCTION(add_w_aq, s32_aq, rd_val + val);
+DEFINE_ATOMIC_FUNCTION(add_w_rl, s32_rl, rd_val + val);
+DEFINE_ATOMIC_FUNCTION(add_w_aqrl, s32_aqrl, rd_val + val);
+DEFINE_ATOMIC_FUNCTION(and_w, s32, rd_val & val);
+DEFINE_ATOMIC_FUNCTION(and_w_aq, s32_aq, rd_val & val);
+DEFINE_ATOMIC_FUNCTION(and_w_rl, s32_rl, rd_val & val);
+DEFINE_ATOMIC_FUNCTION(and_w_aqrl, s32_aqrl, rd_val & val);
+DEFINE_ATOMIC_FUNCTION(or_w, s32, rd_val | val);
+DEFINE_ATOMIC_FUNCTION(or_w_aq, s32_aq, rd_val | val);
+DEFINE_ATOMIC_FUNCTION(or_w_rl, s32_rl, rd_val | val);
+DEFINE_ATOMIC_FUNCTION(or_w_aqrl, s32_aqrl, rd_val | val);
+DEFINE_ATOMIC_FUNCTION(xor_w, s32, rd_val ^ val);
+DEFINE_ATOMIC_FUNCTION(xor_w_aq, s32_aq, rd_val ^ val);
+DEFINE_ATOMIC_FUNCTION(xor_w_rl, s32_rl, rd_val ^ val);
+DEFINE_ATOMIC_FUNCTION(xor_w_aqrl, s32_aqrl, rd_val ^ val);
+DEFINE_ATOMIC_FUNCTION(swap_w, s32, val);
+DEFINE_ATOMIC_FUNCTION(swap_w_aq, s32_aq, val);
+DEFINE_ATOMIC_FUNCTION(swap_w_rl, s32_rl, val);
+DEFINE_ATOMIC_FUNCTION(swap_w_aqrl, s32_aqrl, val);
+DEFINE_ATOMIC_FUNCTION(max_w, s32, (s32)rd_val > (s32)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(max_w_aq, s32_aq, (s32)rd_val > (s32)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(max_w_rl, s32_rl, (s32)rd_val > (s32)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(max_w_aqrl, s32_aqrl, (s32)rd_val > (s32)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(maxu_w, s32, (u32)rd_val > (u32)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(maxu_w_aq, s32_aq, (u32)rd_val > (u32)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(maxu_w_rl, s32_rl, (u32)rd_val > (u32)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(maxu_w_aqrl, s32_aqrl, (u32)rd_val > (u32)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(min_w, s32, (s32)rd_val < (s32)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(min_w_aq, s32_aq, (s32)rd_val < (s32)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(min_w_rl, s32_rl, (s32)rd_val < (s32)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(min_w_aqrl, s32_aqrl, (s32)rd_val < (s32)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(minu_w, s32, (u32)rd_val < (u32)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(minu_w_aq, s32_aq, (u32)rd_val < (u32)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(minu_w_rl, s32_rl, (u32)rd_val < (u32)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(minu_w_aqrl, s32_aqrl, (u32)rd_val < (u32)val ? rd_val : val);
+
+#if __riscv_xlen == 64
+DEFINE_ATOMIC_FUNCTION(add_d, s64, rd_val + val);
+DEFINE_ATOMIC_FUNCTION(add_d_aq, s64_aq, rd_val + val);
+DEFINE_ATOMIC_FUNCTION(add_d_rl, s64_rl, rd_val + val);
+DEFINE_ATOMIC_FUNCTION(add_d_aqrl, s64_aqrl, rd_val + val);
+DEFINE_ATOMIC_FUNCTION(and_d, s64, rd_val & val);
+DEFINE_ATOMIC_FUNCTION(and_d_aq, s64_aq, rd_val & val);
+DEFINE_ATOMIC_FUNCTION(and_d_rl, s64_rl, rd_val & val);
+DEFINE_ATOMIC_FUNCTION(and_d_aqrl, s64_aqrl, rd_val & val);
+DEFINE_ATOMIC_FUNCTION(or_d, s64, rd_val | val);
+DEFINE_ATOMIC_FUNCTION(or_d_aq, s64_aq, rd_val | val);
+DEFINE_ATOMIC_FUNCTION(or_d_rl, s64_rl, rd_val | val);
+DEFINE_ATOMIC_FUNCTION(or_d_aqrl, s64_aqrl, rd_val | val);
+DEFINE_ATOMIC_FUNCTION(xor_d, s64, rd_val ^ val);
+DEFINE_ATOMIC_FUNCTION(xor_d_aq, s64_aq, rd_val ^ val);
+DEFINE_ATOMIC_FUNCTION(xor_d_rl, s64_rl, rd_val ^ val);
+DEFINE_ATOMIC_FUNCTION(xor_d_aqrl, s64_aqrl, rd_val ^ val);
+DEFINE_ATOMIC_FUNCTION(swap_d, s64, val);
+DEFINE_ATOMIC_FUNCTION(swap_d_aq, s64_aq, val);
+DEFINE_ATOMIC_FUNCTION(swap_d_rl, s64_rl, val);
+DEFINE_ATOMIC_FUNCTION(swap_d_aqrl, s64_aqrl, val);
+DEFINE_ATOMIC_FUNCTION(max_d, s64, (s64)rd_val > (s64)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(max_d_aq, s64_aq, (s64)rd_val > (s64)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(max_d_rl, s64_rl, (s64)rd_val > (s64)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(max_d_aqrl, s64_aqrl, (s64)rd_val > (s64)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(maxu_d, s64, (u64)rd_val > (u64)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(maxu_d_aq, s64_aq, (u64)rd_val > (u64)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(maxu_d_rl, s64_rl, (u64)rd_val > (u64)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(maxu_d_aqrl, s64_aqrl, (u64)rd_val > (u64)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(min_d, s64, (s64)rd_val < (s64)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(min_d_aq, s64_aq, (s64)rd_val < (s64)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(min_d_rl, s64_rl, (s64)rd_val < (s64)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(min_d_aqrl, s64_aqrl, (s64)rd_val < (s64)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(minu_d, s64, (u64)rd_val < (u64)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(minu_d_aq, s64_aq, (u64)rd_val < (u64)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(minu_d_rl, s64_rl, (u64)rd_val < (u64)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(minu_d_aqrl, s64_aqrl, (u64)rd_val < (u64)val ? rd_val : val);
+#endif
diff --git a/lib/sbi/sbi_illegal_insn.c b/lib/sbi/sbi_illegal_insn.c
index 784bc4c..4a01f59 100644
--- a/lib/sbi/sbi_illegal_insn.c
+++ b/lib/sbi/sbi_illegal_insn.c
@@ -10,6 +10,7 @@
#include <sbi/riscv_asm.h>
#include <sbi/riscv_barrier.h>
#include <sbi/riscv_encoding.h>
+#include <sbi/sbi_atomic.h>
#include <sbi/sbi_bitops.h>
#include <sbi/sbi_emulate_csr.h>
#include <sbi/sbi_error.h>
@@ -19,6 +20,13 @@
#include <sbi/sbi_unpriv.h>
#include <sbi/sbi_console.h>
+#define OPCODE_MASK 0x0000007f
+#define AMO_OPCODE 0x0000002f
+#define WD_MASK 0x00007000
+#define WD_SHIFT 12
+#define AQRL_MASK 0x06000000
+#define AQRL_SHIFT 25
+
typedef int (*illegal_insn_func)(ulong insn, struct sbi_trap_regs *regs);
static int truly_illegal_insn(ulong insn, struct sbi_trap_regs *regs)
@@ -146,6 +154,487 @@ static const illegal_insn_func illegal_insn_table[32] = {
truly_illegal_insn /* 31 */
};
+static int other_illegal_insn(ulong insn, struct sbi_trap_regs *regs)
+{
+ return illegal_insn_table[(insn & 0x7c) >> 2](insn, regs);
+}
+
+static const illegal_insn_func amoadd_table[32] = {
+ other_illegal_insn, /* 0 */
+ other_illegal_insn, /* 1 */
+ other_illegal_insn, /* 2 */
+ other_illegal_insn, /* 3 */
+ other_illegal_insn, /* 4 */
+ other_illegal_insn, /* 5 */
+ other_illegal_insn, /* 6 */
+ other_illegal_insn, /* 7 */
+ sbi_atomic_add_w, /* 8 */
+ sbi_atomic_add_w_rl, /* 9 */
+ sbi_atomic_add_w_aq, /* 10 */
+ sbi_atomic_add_w_aqrl, /* 11 */
+#if __riscv_xlen == 64
+ sbi_atomic_add_d, /* 12 */
+ sbi_atomic_add_d_rl, /* 13 */
+ sbi_atomic_add_d_aq, /* 14 */
+ sbi_atomic_add_d_aqrl, /* 15 */
+#else
+ other_illegal_insn, /* 12 */
+ other_illegal_insn, /* 13 */
+ other_illegal_insn, /* 14 */
+ other_illegal_insn, /* 15 */
+#endif
+ other_illegal_insn, /* 16 */
+ other_illegal_insn, /* 17 */
+ other_illegal_insn, /* 18 */
+ other_illegal_insn, /* 19 */
+ other_illegal_insn, /* 20 */
+ other_illegal_insn, /* 21 */
+ other_illegal_insn, /* 22 */
+ other_illegal_insn, /* 23 */
+ other_illegal_insn, /* 24 */
+ other_illegal_insn, /* 25 */
+ other_illegal_insn, /* 26 */
+ other_illegal_insn, /* 27 */
+ other_illegal_insn, /* 28 */
+ other_illegal_insn, /* 29 */
+ other_illegal_insn, /* 30 */
+ other_illegal_insn, /* 31 */
+};
+
+static const illegal_insn_func amoswap_table[32] = {
+ other_illegal_insn, /* 0 */
+ other_illegal_insn, /* 1 */
+ other_illegal_insn, /* 2 */
+ other_illegal_insn, /* 3 */
+ other_illegal_insn, /* 4 */
+ other_illegal_insn, /* 5 */
+ other_illegal_insn, /* 6 */
+ other_illegal_insn, /* 7 */
+ sbi_atomic_swap_w, /* 8 */
+ sbi_atomic_swap_w_rl, /* 9 */
+ sbi_atomic_swap_w_aq, /* 10 */
+ sbi_atomic_swap_w_aqrl, /* 11 */
+#if __riscv_xlen == 64
+ sbi_atomic_swap_d, /* 12 */
+ sbi_atomic_swap_d_rl, /* 13 */
+ sbi_atomic_swap_d_aq, /* 14 */
+ sbi_atomic_swap_d_aqrl, /* 15 */
+#else
+ other_illegal_insn, /* 12 */
+ other_illegal_insn, /* 13 */
+ other_illegal_insn, /* 14 */
+ other_illegal_insn, /* 15 */
+#endif
+ other_illegal_insn, /* 16 */
+ other_illegal_insn, /* 17 */
+ other_illegal_insn, /* 18 */
+ other_illegal_insn, /* 19 */
+ other_illegal_insn, /* 20 */
+ other_illegal_insn, /* 21 */
+ other_illegal_insn, /* 22 */
+ other_illegal_insn, /* 23 */
+ other_illegal_insn, /* 24 */
+ other_illegal_insn, /* 25 */
+ other_illegal_insn, /* 26 */
+ other_illegal_insn, /* 27 */
+ other_illegal_insn, /* 28 */
+ other_illegal_insn, /* 29 */
+ other_illegal_insn, /* 30 */
+ other_illegal_insn, /* 31 */
+};
+
+static const illegal_insn_func amoxor_table[32] = {
+ other_illegal_insn, /* 0 */
+ other_illegal_insn, /* 1 */
+ other_illegal_insn, /* 2 */
+ other_illegal_insn, /* 3 */
+ other_illegal_insn, /* 4 */
+ other_illegal_insn, /* 5 */
+ other_illegal_insn, /* 6 */
+ other_illegal_insn, /* 7 */
+ sbi_atomic_xor_w, /* 8 */
+ sbi_atomic_xor_w_rl, /* 9 */
+ sbi_atomic_xor_w_aq, /* 10 */
+ sbi_atomic_xor_w_aqrl, /* 11 */
+#if __riscv_xlen == 64
+ sbi_atomic_xor_d, /* 12 */
+ sbi_atomic_xor_d_rl, /* 13 */
+ sbi_atomic_xor_d_aq, /* 14 */
+ sbi_atomic_xor_d_aqrl, /* 15 */
+#else
+ other_illegal_insn, /* 12 */
+ other_illegal_insn, /* 13 */
+ other_illegal_insn, /* 14 */
+ other_illegal_insn, /* 15 */
+#endif
+ other_illegal_insn, /* 16 */
+ other_illegal_insn, /* 17 */
+ other_illegal_insn, /* 18 */
+ other_illegal_insn, /* 19 */
+ other_illegal_insn, /* 20 */
+ other_illegal_insn, /* 21 */
+ other_illegal_insn, /* 22 */
+ other_illegal_insn, /* 23 */
+ other_illegal_insn, /* 24 */
+ other_illegal_insn, /* 25 */
+ other_illegal_insn, /* 26 */
+ other_illegal_insn, /* 27 */
+ other_illegal_insn, /* 28 */
+ other_illegal_insn, /* 29 */
+ other_illegal_insn, /* 30 */
+ other_illegal_insn, /* 31 */
+};
+
+static const illegal_insn_func amoor_table[32] = {
+ other_illegal_insn, /* 0 */
+ other_illegal_insn, /* 1 */
+ other_illegal_insn, /* 2 */
+ other_illegal_insn, /* 3 */
+ other_illegal_insn, /* 4 */
+ other_illegal_insn, /* 5 */
+ other_illegal_insn, /* 6 */
+ other_illegal_insn, /* 7 */
+ sbi_atomic_or_w, /* 8 */
+ sbi_atomic_or_w_rl, /* 9 */
+ sbi_atomic_or_w_aq, /* 10 */
+ sbi_atomic_or_w_aqrl, /* 11 */
+#if __riscv_xlen == 64
+ sbi_atomic_or_d, /* 12 */
+ sbi_atomic_or_d_rl, /* 13 */
+ sbi_atomic_or_d_aq, /* 14 */
+ sbi_atomic_or_d_aqrl, /* 15 */
+#else
+ other_illegal_insn, /* 12 */
+ other_illegal_insn, /* 13 */
+ other_illegal_insn, /* 14 */
+ other_illegal_insn, /* 15 */
+#endif
+ other_illegal_insn, /* 16 */
+ other_illegal_insn, /* 17 */
+ other_illegal_insn, /* 18 */
+ other_illegal_insn, /* 19 */
+ other_illegal_insn, /* 20 */
+ other_illegal_insn, /* 21 */
+ other_illegal_insn, /* 22 */
+ other_illegal_insn, /* 23 */
+ other_illegal_insn, /* 24 */
+ other_illegal_insn, /* 25 */
+ other_illegal_insn, /* 26 */
+ other_illegal_insn, /* 27 */
+ other_illegal_insn, /* 28 */
+ other_illegal_insn, /* 29 */
+ other_illegal_insn, /* 30 */
+ other_illegal_insn, /* 31 */
+};
+
+static const illegal_insn_func amoand_table[32] = {
+ other_illegal_insn, /* 0 */
+ other_illegal_insn, /* 1 */
+ other_illegal_insn, /* 2 */
+ other_illegal_insn, /* 3 */
+ other_illegal_insn, /* 4 */
+ other_illegal_insn, /* 5 */
+ other_illegal_insn, /* 6 */
+ other_illegal_insn, /* 7 */
+ sbi_atomic_and_w, /* 8 */
+ sbi_atomic_and_w_rl, /* 9 */
+ sbi_atomic_and_w_aq, /* 10 */
+ sbi_atomic_and_w_aqrl, /* 11 */
+#if __riscv_xlen == 64
+ sbi_atomic_and_d, /* 12 */
+ sbi_atomic_and_d_rl, /* 13 */
+ sbi_atomic_and_d_aq, /* 14 */
+ sbi_atomic_and_d_aqrl, /* 15 */
+#else
+ other_illegal_insn, /* 12 */
+ other_illegal_insn, /* 13 */
+ other_illegal_insn, /* 14 */
+ other_illegal_insn, /* 15 */
+#endif
+ other_illegal_insn, /* 16 */
+ other_illegal_insn, /* 17 */
+ other_illegal_insn, /* 18 */
+ other_illegal_insn, /* 19 */
+ other_illegal_insn, /* 20 */
+ other_illegal_insn, /* 21 */
+ other_illegal_insn, /* 22 */
+ other_illegal_insn, /* 23 */
+ other_illegal_insn, /* 24 */
+ other_illegal_insn, /* 25 */
+ other_illegal_insn, /* 26 */
+ other_illegal_insn, /* 27 */
+ other_illegal_insn, /* 28 */
+ other_illegal_insn, /* 29 */
+ other_illegal_insn, /* 30 */
+ other_illegal_insn, /* 31 */
+};
+
+static const illegal_insn_func amomin_table[32] = {
+ other_illegal_insn, /* 0 */
+ other_illegal_insn, /* 1 */
+ other_illegal_insn, /* 2 */
+ other_illegal_insn, /* 3 */
+ other_illegal_insn, /* 4 */
+ other_illegal_insn, /* 5 */
+ other_illegal_insn, /* 6 */
+ other_illegal_insn, /* 7 */
+ sbi_atomic_min_w, /* 8 */
+ sbi_atomic_min_w_rl, /* 9 */
+ sbi_atomic_min_w_aq, /* 10 */
+ sbi_atomic_min_w_aqrl, /* 11 */
+#if __riscv_xlen == 64
+ sbi_atomic_min_d, /* 12 */
+ sbi_atomic_min_d_rl, /* 13 */
+ sbi_atomic_min_d_aq, /* 14 */
+ sbi_atomic_min_d_aqrl, /* 15 */
+#else
+ other_illegal_insn, /* 12 */
+ other_illegal_insn, /* 13 */
+ other_illegal_insn, /* 14 */
+ other_illegal_insn, /* 15 */
+#endif
+ other_illegal_insn, /* 16 */
+ other_illegal_insn, /* 17 */
+ other_illegal_insn, /* 18 */
+ other_illegal_insn, /* 19 */
+ other_illegal_insn, /* 20 */
+ other_illegal_insn, /* 21 */
+ other_illegal_insn, /* 22 */
+ other_illegal_insn, /* 23 */
+ other_illegal_insn, /* 24 */
+ other_illegal_insn, /* 25 */
+ other_illegal_insn, /* 26 */
+ other_illegal_insn, /* 27 */
+ other_illegal_insn, /* 28 */
+ other_illegal_insn, /* 29 */
+ other_illegal_insn, /* 30 */
+ other_illegal_insn, /* 31 */
+};
+
+static const illegal_insn_func amomax_table[32] = {
+ other_illegal_insn, /* 0 */
+ other_illegal_insn, /* 1 */
+ other_illegal_insn, /* 2 */
+ other_illegal_insn, /* 3 */
+ other_illegal_insn, /* 4 */
+ other_illegal_insn, /* 5 */
+ other_illegal_insn, /* 6 */
+ other_illegal_insn, /* 7 */
+ sbi_atomic_max_w, /* 8 */
+ sbi_atomic_max_w_rl, /* 9 */
+ sbi_atomic_max_w_aq, /* 10 */
+ sbi_atomic_max_w_aqrl, /* 11 */
+#if __riscv_xlen == 64
+ sbi_atomic_max_d, /* 12 */
+ sbi_atomic_max_d_rl, /* 13 */
+ sbi_atomic_max_d_aq, /* 14 */
+ sbi_atomic_max_d_aqrl, /* 15 */
+#else
+ other_illegal_insn, /* 12 */
+ other_illegal_insn, /* 13 */
+ other_illegal_insn, /* 14 */
+ other_illegal_insn, /* 15 */
+#endif
+ other_illegal_insn, /* 16 */
+ other_illegal_insn, /* 17 */
+ other_illegal_insn, /* 18 */
+ other_illegal_insn, /* 19 */
+ other_illegal_insn, /* 20 */
+ other_illegal_insn, /* 21 */
+ other_illegal_insn, /* 22 */
+ other_illegal_insn, /* 23 */
+ other_illegal_insn, /* 24 */
+ other_illegal_insn, /* 25 */
+ other_illegal_insn, /* 26 */
+ other_illegal_insn, /* 27 */
+ other_illegal_insn, /* 28 */
+ other_illegal_insn, /* 29 */
+ other_illegal_insn, /* 30 */
+ other_illegal_insn, /* 31 */
+};
+
+static const illegal_insn_func amominu_table[32] = {
+ other_illegal_insn, /* 0 */
+ other_illegal_insn, /* 1 */
+ other_illegal_insn, /* 2 */
+ other_illegal_insn, /* 3 */
+ other_illegal_insn, /* 4 */
+ other_illegal_insn, /* 5 */
+ other_illegal_insn, /* 6 */
+ other_illegal_insn, /* 7 */
+ sbi_atomic_minu_w, /* 8 */
+ sbi_atomic_minu_w_rl, /* 9 */
+ sbi_atomic_minu_w_aq, /* 10 */
+ sbi_atomic_minu_w_aqrl, /* 11 */
+#if __riscv_xlen == 64
+ sbi_atomic_minu_d, /* 12 */
+ sbi_atomic_minu_d_rl, /* 13 */
+ sbi_atomic_minu_d_aq, /* 14 */
+ sbi_atomic_minu_d_aqrl, /* 15 */
+#else
+ other_illegal_insn, /* 12 */
+ other_illegal_insn, /* 13 */
+ other_illegal_insn, /* 14 */
+ other_illegal_insn, /* 15 */
+#endif
+ other_illegal_insn, /* 16 */
+ other_illegal_insn, /* 17 */
+ other_illegal_insn, /* 18 */
+ other_illegal_insn, /* 19 */
+ other_illegal_insn, /* 20 */
+ other_illegal_insn, /* 21 */
+ other_illegal_insn, /* 22 */
+ other_illegal_insn, /* 23 */
+ other_illegal_insn, /* 24 */
+ other_illegal_insn, /* 25 */
+ other_illegal_insn, /* 26 */
+ other_illegal_insn, /* 27 */
+ other_illegal_insn, /* 28 */
+ other_illegal_insn, /* 29 */
+ other_illegal_insn, /* 30 */
+ other_illegal_insn, /* 31 */
+};
+
+static const illegal_insn_func amomaxu_table[32] = {
+ other_illegal_insn, /* 0 */
+ other_illegal_insn, /* 1 */
+ other_illegal_insn, /* 2 */
+ other_illegal_insn, /* 3 */
+ other_illegal_insn, /* 4 */
+ other_illegal_insn, /* 5 */
+ other_illegal_insn, /* 6 */
+ other_illegal_insn, /* 7 */
+ sbi_atomic_maxu_w, /* 8 */
+ sbi_atomic_maxu_w_rl, /* 9 */
+ sbi_atomic_maxu_w_aq, /* 10 */
+ sbi_atomic_maxu_w_aqrl, /* 11 */
+#if __riscv_xlen == 64
+ sbi_atomic_maxu_d, /* 12 */
+ sbi_atomic_maxu_d_rl, /* 13 */
+ sbi_atomic_maxu_d_aq, /* 14 */
+ sbi_atomic_maxu_d_aqrl, /* 15 */
+#else
+ other_illegal_insn, /* 12 */
+ other_illegal_insn, /* 13 */
+ other_illegal_insn, /* 14 */
+ other_illegal_insn, /* 15 */
+#endif
+ other_illegal_insn, /* 16 */
+ other_illegal_insn, /* 17 */
+ other_illegal_insn, /* 18 */
+ other_illegal_insn, /* 19 */
+ other_illegal_insn, /* 20 */
+ other_illegal_insn, /* 21 */
+ other_illegal_insn, /* 22 */
+ other_illegal_insn, /* 23 */
+ other_illegal_insn, /* 24 */
+ other_illegal_insn, /* 25 */
+ other_illegal_insn, /* 26 */
+ other_illegal_insn, /* 27 */
+ other_illegal_insn, /* 28 */
+ other_illegal_insn, /* 29 */
+ other_illegal_insn, /* 30 */
+ other_illegal_insn, /* 31 */
+};
+
+static int amoadd_insn(ulong insn, struct sbi_trap_regs *regs)
+{
+ int wd = ((insn & WD_MASK) >> WD_SHIFT) << 2;
+ int aqrl = (insn & AQRL_MASK) >> AQRL_SHIFT;
+ return amoadd_table[wd + aqrl](insn, regs);
+}
+
+static int amoswap_insn(ulong insn, struct sbi_trap_regs *regs)
+{
+ int wd = ((insn & WD_MASK) >> WD_SHIFT) << 2;
+ int aqrl = (insn & AQRL_MASK) >> AQRL_SHIFT;
+ return amoswap_table[wd + aqrl](insn, regs);
+}
+
+static int amoxor_insn(ulong insn, struct sbi_trap_regs *regs)
+{
+ int wd = ((insn & WD_MASK) >> WD_SHIFT) << 2;
+ int aqrl = (insn & AQRL_MASK) >> AQRL_SHIFT;
+ return amoxor_table[wd + aqrl](insn, regs);
+}
+
+static int amoor_insn(ulong insn, struct sbi_trap_regs *regs)
+{
+ int wd = ((insn & WD_MASK) >> WD_SHIFT) << 2;
+ int aqrl = (insn & AQRL_MASK) >> AQRL_SHIFT;
+ return amoor_table[wd + aqrl](insn, regs);
+}
+
+static int amoand_insn(ulong insn, struct sbi_trap_regs *regs)
+{
+ int wd = ((insn & WD_MASK) >> WD_SHIFT) << 2;
+ int aqrl = (insn & AQRL_MASK) >> AQRL_SHIFT;
+ return amoand_table[wd + aqrl](insn, regs);
+}
+
+static int amomin_insn(ulong insn, struct sbi_trap_regs *regs)
+{
+ int wd = ((insn & WD_MASK) >> WD_SHIFT) << 2;
+ int aqrl = (insn & AQRL_MASK) >> AQRL_SHIFT;
+ return amomin_table[wd + aqrl](insn, regs);
+}
+
+static int amomax_insn(ulong insn, struct sbi_trap_regs *regs)
+{
+ int wd = ((insn & WD_MASK) >> WD_SHIFT) << 2;
+ int aqrl = (insn & AQRL_MASK) >> AQRL_SHIFT;
+ return amomax_table[wd + aqrl](insn, regs);
+}
+
+static int amominu_insn(ulong insn, struct sbi_trap_regs *regs)
+{
+ int wd = ((insn & WD_MASK) >> WD_SHIFT) << 2;
+ int aqrl = (insn & AQRL_MASK) >> AQRL_SHIFT;
+ return amominu_table[wd + aqrl](insn, regs);
+}
+
+static int amomaxu_insn(ulong insn, struct sbi_trap_regs *regs)
+{
+ int wd = ((insn & WD_MASK) >> WD_SHIFT) << 2;
+ int aqrl = (insn & AQRL_MASK) >> AQRL_SHIFT;
+ return amomaxu_table[wd + aqrl](insn, regs);
+}
+
+static const illegal_insn_func amo_insn_table[32] = {
+ amoadd_insn, /* 0 */
+ amoswap_insn, /* 1 */
+ other_illegal_insn, /* 2 */
+ other_illegal_insn, /* 3 */
+ amoxor_insn, /* 4 */
+ other_illegal_insn, /* 5 */
+ other_illegal_insn, /* 6 */
+ other_illegal_insn, /* 7 */
+ amoor_insn, /* 8 */
+ other_illegal_insn, /* 9 */
+ other_illegal_insn, /* 10 */
+ other_illegal_insn, /* 11 */
+ amoand_insn, /* 12 */
+ other_illegal_insn, /* 13 */
+ other_illegal_insn, /* 14 */
+ other_illegal_insn, /* 15 */
+ amomin_insn, /* 16 */
+ other_illegal_insn, /* 17 */
+ other_illegal_insn, /* 18 */
+ other_illegal_insn, /* 19 */
+ amomax_insn, /* 20 */
+ other_illegal_insn, /* 21 */
+ other_illegal_insn, /* 22 */
+ other_illegal_insn, /* 23 */
+ amominu_insn, /* 24 */
+ other_illegal_insn, /* 25 */
+ other_illegal_insn, /* 26 */
+ other_illegal_insn, /* 27 */
+ amomaxu_insn, /* 28 */
+ other_illegal_insn, /* 29 */
+ other_illegal_insn, /* 30 */
+ other_illegal_insn /* 31 */
+};
+
int sbi_illegal_insn_handler(struct sbi_trap_context *tcntx)
{
struct sbi_trap_regs *regs = &tcntx->regs;
@@ -172,5 +661,8 @@ int sbi_illegal_insn_handler(struct sbi_trap_context *tcntx)
return truly_illegal_insn(insn, regs);
}
+ if ((insn & OPCODE_MASK) == AMO_OPCODE)
+ return amo_insn_table[(insn >> 27) & 0x1f](insn, regs);
+
return illegal_insn_table[(insn & 0x7c) >> 2](insn, regs);
}
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 70+ messages in thread* [PATCH v3 7/9] platform: generic: mips: add a dts file
2025-02-12 12:27 ` Anup Patel
` (17 preceding siblings ...)
2025-04-10 22:45 ` [PATCH v3 6/9] lib: Emulate amo instructions Chao-ying Fu
@ 2025-04-10 22:45 ` Chao-ying Fu
2025-04-10 22:45 ` [PATCH v3 8/9] platform: generic: mips: add objects.mk Chao-ying Fu
` (29 subsequent siblings)
48 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-04-10 22:45 UTC (permalink / raw)
To: opensbi; +Cc: Chao-ying Fu
We add a dts file for 4 cores 2 threads each on a Boston board.
Signed-off-by: Chao-ying Fu <cfu@mips.com>
---
platform/generic/mips/mips,boston-p8700.dts | 339 ++++++++++++++++++++
1 file changed, 339 insertions(+)
create mode 100644 platform/generic/mips/mips,boston-p8700.dts
diff --git a/platform/generic/mips/mips,boston-p8700.dts b/platform/generic/mips/mips,boston-p8700.dts
new file mode 100644
index 0000000..a8de86e
--- /dev/null
+++ b/platform/generic/mips/mips,boston-p8700.dts
@@ -0,0 +1,339 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 MIPS
+ *
+ */
+
+/dts-v1/;
+
+#define CM_BASE 0x16100000
+#define APLIC_M_BASE (CM_BASE + 0x40000)
+#define APLIC_S_BASE (CM_BASE + 0x60000)
+#define MSWI_BASE (CM_BASE + 0x50000)
+#define MTIMER_BASE (MSWI_BASE + 0x4000)
+#define CPC_TIMER (CM_BASE + 0x8050)
+
+#define IRQ_TYPE_LEVEL_HIGH 4
+#define UART_INT 4
+#define PCIE2_INT 7
+
+#define BITFILE_FREQUENCY 25000000
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ model = "MIPS P8700";
+ compatible = "mips,p8700";
+
+ chosen {
+ stdout-path = &uart0;
+ // For Qemu
+ //bootargs = "root=/dev/sda rw earlycon console=ttyS0,115200n8r";
+ // For a Boston board
+ bootargs = "root=/dev/mmcblk0p5 rw rootwait earlycon console=ttyS0,115200n8r";
+
+ opensbi-domains {
+ compatible = "opensbi,domain,config";
+
+ tmem: tmem {
+ compatible = "opensbi,domain,memregion";
+ base = <0x0 0x80000000>;
+ order = <31>;
+ };
+
+ allmem: allmem {
+ compatible = "opensbi,domain,memregion";
+ base = <0x0 0x0>;
+ order = <64>;
+ };
+
+ tdomain: trusted-domain {
+ compatible = "opensbi,domain,instance";
+ possible-harts = <&cpu0 &cpu1 &cpu2 &cpu3 &cpu4 &cpu5 &cpu6 &cpu7>;
+ regions = <&tmem 0x3f>, <&allmem 0x3f>;
+ };
+ };
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ timebase-frequency = <BITFILE_FREQUENCY>;
+
+ cpu0: cpu@0 {
+ device_type = "cpu";
+ compatible = "riscv";
+ opensbi-domain = <&tdomain>;
+ mmu-type = "riscv,sv39";
+ riscv,isa = "rv64imafdcsu";
+ status = "okay";
+ reg = <0x00000000>;
+
+ cpu0_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu1: cpu@1 {
+ device_type = "cpu";
+ compatible = "riscv";
+ opensbi-domain = <&tdomain>;
+ mmu-type = "riscv,sv39";
+ riscv,isa = "rv64imafdcsu";
+ status = "okay";
+ reg = <0x00000001>;
+
+ cpu1_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu2: cpu@2 {
+ device_type = "cpu";
+ compatible = "riscv";
+ opensbi-domain = <&tdomain>;
+ mmu-type = "riscv,sv39";
+ riscv,isa = "rv64imafdcsu";
+ status = "okay";
+ reg = <0x00000010>;
+
+ cpu2_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu3: cpu@3 {
+ device_type = "cpu";
+ compatible = "riscv";
+ opensbi-domain = <&tdomain>;
+ mmu-type = "riscv,sv39";
+ riscv,isa = "rv64imafdcsu";
+ status = "okay";
+ reg = <0x00000011>;
+
+ cpu3_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu4: cpu@4 {
+ device_type = "cpu";
+ compatible = "riscv";
+ opensbi-domain = <&tdomain>;
+ mmu-type = "riscv,sv39";
+ riscv,isa = "rv64imafdcsu";
+ status = "okay";
+ reg = <0x00000020>;
+
+ cpu4_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu5: cpu@5 {
+ device_type = "cpu";
+ compatible = "riscv";
+ opensbi-domain = <&tdomain>;
+ mmu-type = "riscv,sv39";
+ riscv,isa = "rv64imafdcsu";
+ status = "okay";
+ reg = <0x00000021>;
+
+ cpu5_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu6: cpu@6 {
+ device_type = "cpu";
+ compatible = "riscv";
+ opensbi-domain = <&tdomain>;
+ mmu-type = "riscv,sv39";
+ riscv,isa = "rv64imafdcsu";
+ status = "okay";
+ reg = <0x00000030>;
+
+ cpu6_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu7: cpu@7 {
+ device_type = "cpu";
+ compatible = "riscv";
+ opensbi-domain = <&tdomain>;
+ mmu-type = "riscv,sv39";
+ riscv,isa = "rv64imafdcsu";
+ status = "okay";
+ reg = <0x00000031>;
+
+ cpu7_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x80000000 0x80000000>;
+ };
+
+ pci2: pci@14000000 {
+ compatible = "xlnx,axi-pcie-host-1.00.a";
+ device_type = "pci";
+ reg = <0x14000000 0x2000000>;
+
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+
+ interrupt-parent = <&aplic_s0>;
+ interrupts = <PCIE2_INT IRQ_TYPE_LEVEL_HIGH>;
+
+ ranges = <0x02000000 0 0x16000000
+ 0x16000000 0 0x100000>;
+
+ bus-range = <0x00 0xff>;
+
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &pci2_intc 1>,
+ <0 0 0 2 &pci2_intc 2>,
+ <0 0 0 3 &pci2_intc 3>,
+ <0 0 0 4 &pci2_intc 4>;
+
+ pci2_intc: interrupt-controller {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ };
+
+ pci2_root@0,0 {
+ compatible = "pci10ee,7021", "pci-bridge";
+ reg = <0x00000000 0 0 0 0>;
+
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+
+ eg20t_bridge@1,0,0 {
+ compatible = "pci8086,8800", "pci-bridge";
+ reg = <0x00010000 0 0 0 0>;
+
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+
+ eg20t_mac@2,0,1 {
+ compatible = "pci8086,8802", "intel,pch-gbe";
+ reg = <0x00020100 0 0 0 0>;
+ phy-reset-gpios = <&eg20t_gpio 6 1>;
+ };
+
+ eg20t_gpio: eg20t_gpio@2,0,2 {
+ compatible = "pci8086,8803", "intel,eg20t-gpio";
+ reg = <0x00020200 0 0 0 0>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ eg20t_i2c@2,12,2 {
+ compatible = "pci8086,8817";
+ reg = <0x00026200 0 0 0 0>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rtc@68 {
+ compatible = "st,m41t81s";
+ reg = <0x68>;
+ };
+ };
+ };
+ };
+ };
+
+ uart0: uart@17ffe000 {
+ compatible = "ns16550a";
+ reg = <0x17ffe000 0x1000>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+
+ interrupt-parent = <&aplic_s0>;
+ interrupts = <UART_INT IRQ_TYPE_LEVEL_HIGH>;
+
+ clock-frequency = <BITFILE_FREQUENCY>;
+
+ u-boot,dm-pre-reloc;
+ };
+
+ lcd: lcd@17fff000 {
+ compatible = "img,boston-lcd";
+ reg = <0x17fff000 0x8>;
+ };
+
+ flash@18000000 {
+ compatible = "cfi-flash";
+ reg = <0x18000000 0x8000000>;
+ bank-width = <2>;
+ };
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges;
+
+ aplic_s0: interrupt-controller@16160000 {
+ #interrupt-cells = <0x00000002>;
+ compatible = "riscv,aplic";
+ interrupt-controller;
+ interrupts-extended = <&cpu0_intc 9>, <&cpu1_intc 9>, <&cpu2_intc 9>, <&cpu3_intc 9>, <&cpu4_intc 9>, <&cpu5_intc 9>, <&cpu6_intc 9>, <&cpu7_intc 9>;
+ reg = <APLIC_S_BASE 0x00008000>;
+ riscv,num-sources = <0x00000035>;
+ };
+
+ aplic_m0: interrupt-controller@16140000 {
+ #interrupt-cells = <0x00000002>;
+ riscv,delegate = <&aplic_s0 0x00000001 0x00000035>;
+ riscv,children = <&aplic_s0>;
+ compatible = "riscv,aplic";
+ interrupt-controller;
+ interrupts-extended = <&cpu0_intc 11>, <&cpu1_intc 11>, <&cpu2_intc 11>, <&cpu3_intc 11>, <&cpu4_intc 11>, <&cpu5_intc 11>, <&cpu6_intc 11>, <&cpu7_intc 11>;
+ reg = <APLIC_M_BASE 0x00008000>;
+ riscv,num-sources = <0x00000035>;
+ };
+
+ mswi0: interrupt-controller@16150000 {
+ compatible = "riscv,aclint-mswi";
+ interrupts-extended = <&cpu0_intc 3>, <&cpu1_intc 3>, <&cpu2_intc 3>, <&cpu3_intc 3>, <&cpu4_intc 3>, <&cpu5_intc 3>, <&cpu6_intc 3>, <&cpu7_intc 3>;
+ reg = <MSWI_BASE 0x4000>;
+ interrupt-controller;
+ #interrupt-cells = <0>;
+ };
+
+ mtimer0: timer@16154000 {
+ compatible = "riscv,aclint-mtimer";
+ reg = <CPC_TIMER 0x8>,
+ <MTIMER_BASE 0x7ff8>;
+ interrupts-extended = <&cpu0_intc 7>, <&cpu1_intc 7>, <&cpu2_intc 7>, <&cpu3_intc 7>, <&cpu4_intc 7>, <&cpu5_intc 7>, <&cpu6_intc 7>, <&cpu7_intc 7>;
+ };
+ };
+};
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 70+ messages in thread* [PATCH v3 8/9] platform: generic: mips: add objects.mk
2025-02-12 12:27 ` Anup Patel
` (18 preceding siblings ...)
2025-04-10 22:45 ` [PATCH v3 7/9] platform: generic: mips: add a dts file Chao-ying Fu
@ 2025-04-10 22:45 ` Chao-ying Fu
2025-04-10 22:45 ` [PATCH v3 9/9] Initialize MIPS custom PMA registers Chao-ying Fu
` (28 subsequent siblings)
48 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-04-10 22:45 UTC (permalink / raw)
To: opensbi; +Cc: Chao-ying Fu
We build MIPS files.
Signed-off-by: Chao-ying Fu <cfu@mips.com>
---
platform/generic/mips/objects.mk | 7 +++++++
1 file changed, 7 insertions(+)
create mode 100644 platform/generic/mips/objects.mk
diff --git a/platform/generic/mips/objects.mk b/platform/generic/mips/objects.mk
new file mode 100644
index 0000000..6b051c0
--- /dev/null
+++ b/platform/generic/mips/objects.mk
@@ -0,0 +1,7 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+
+carray-platform_override_modules-$(CONFIG_PLATFORM_MIPS_P8700) += mips_p8700
+platform-objs-$(CONFIG_PLATFORM_MIPS_P8700) += mips/p8700.o mips/cps-vec.o
+platform-dtb-$(CONFIG_PLATFORM_MIPS_P8700) += mips/mips,boston-p8700.dtb
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 70+ messages in thread* [PATCH v3 9/9] Initialize MIPS custom PMA registers
2025-02-12 12:27 ` Anup Patel
` (19 preceding siblings ...)
2025-04-10 22:45 ` [PATCH v3 8/9] platform: generic: mips: add objects.mk Chao-ying Fu
@ 2025-04-10 22:45 ` Chao-ying Fu
2025-04-29 23:29 ` [PATCH v4 0/8] *** Add MIPS P8700 platform *** Chao-ying Fu
` (27 subsequent siblings)
48 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-04-10 22:45 UTC (permalink / raw)
To: opensbi; +Cc: Chao-ying Fu
Before PMP set up, we need to set up MIPS custom PMA registers
to have correct cacheable or uncacheable execution for pmp regions.
Signed-off-by: Chao-ying Fu <cfu@mips.com>
---
lib/sbi/riscv_asm.c | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/lib/sbi/riscv_asm.c b/lib/sbi/riscv_asm.c
index c7d75ac..ca7edbe 100644
--- a/lib/sbi/riscv_asm.c
+++ b/lib/sbi/riscv_asm.c
@@ -12,6 +12,9 @@
#include <sbi/sbi_error.h>
#include <sbi/sbi_platform.h>
#include <sbi/sbi_console.h>
+#ifdef CONFIG_PLATFORM_MIPS_P8700
+#include <mips/p8700.h>
+#endif
/* determine CPU extension, return non-zero support */
int misa_extension_imp(char ext)
@@ -119,6 +122,9 @@ unsigned long csr_read_num(int csr_num)
unsigned long ret = 0;
switch (csr_num) {
+#ifdef CONFIG_PLATFORM_MIPS_P8700
+ switchcase_csr_read_16(CSR_MIPSPMACFG0, ret)
+#endif
switchcase_csr_read_16(CSR_PMPCFG0, ret)
switchcase_csr_read_64(CSR_PMPADDR0, ret)
switchcase_csr_read(CSR_MCYCLE, ret)
@@ -199,6 +205,9 @@ void csr_write_num(int csr_num, unsigned long val)
switchcase_csr_write_32(__csr_num + 32, __val)
switch (csr_num) {
+#ifdef CONFIG_PLATFORM_MIPS_P8700
+ switchcase_csr_write_16(CSR_MIPSPMACFG0, val)
+#endif
switchcase_csr_write_16(CSR_PMPCFG0, val)
switchcase_csr_write_64(CSR_PMPADDR0, val)
switchcase_csr_write(CSR_MCYCLE, val)
@@ -301,6 +310,29 @@ int is_pmp_entry_mapped(unsigned long entry)
return false;
}
+#ifdef CONFIG_PLATFORM_MIPS_P8700
+extern unsigned long _fw_start;
+static void pma_set(unsigned int n, unsigned long addr)
+{
+ int pmacfg_csr, pmacfg_shift;
+ unsigned long cfgmask;
+ unsigned long pmacfg, cca;
+
+ pmacfg_csr = (CSR_MIPSPMACFG0 + (n >> 2)) & ~1;
+ pmacfg_shift = (n & 7) << 3;
+ cfgmask = ~(0xffUL << pmacfg_shift);
+
+ /* Read pmacfg to change cacheability */
+ pmacfg = (csr_read_num(pmacfg_csr) & cfgmask);
+ if (addr >= (unsigned long)&_fw_start)
+ cca = CCA_CACHE_ENABLE | PMA_SPECULATION;
+ else
+ cca = CCA_CACHE_DISABLE;
+ pmacfg |= ((cca << pmacfg_shift) & ~cfgmask);
+ csr_write_num(pmacfg_csr, pmacfg);
+}
+#endif
+
int pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
unsigned long log2len)
{
@@ -312,6 +344,10 @@ int pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
if (n >= PMP_COUNT || log2len > __riscv_xlen || log2len < PMP_SHIFT)
return SBI_EINVAL;
+#ifdef CONFIG_PLATFORM_MIPS_P8700
+ pma_set(n, addr);
+#endif
+
/* calculate PMP register and offset */
#if __riscv_xlen == 32
pmpcfg_csr = CSR_PMPCFG0 + (n >> 2);
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 70+ messages in thread* [PATCH v4 0/8] *** Add MIPS P8700 platform ***
2025-02-12 12:27 ` Anup Patel
` (20 preceding siblings ...)
2025-04-10 22:45 ` [PATCH v3 9/9] Initialize MIPS custom PMA registers Chao-ying Fu
@ 2025-04-29 23:29 ` Chao-ying Fu
2025-05-19 12:16 ` Anup Patel
2025-04-29 23:29 ` [PATCH v4 1/8] platform: generic: mips: add P8700 Chao-ying Fu
` (26 subsequent siblings)
48 siblings, 1 reply; 70+ messages in thread
From: Chao-ying Fu @ 2025-04-29 23:29 UTC (permalink / raw)
To: opensbi; +Cc: Chao-ying Fu
***
Changes in v4:
Remove code that overrides nascent_init.
Update p8700.c to work with the latest override.
Use csr_set for mipsconfig6 in p8700.c.
Add riscv,cbom-block-size to the dts file.
Changes in v3:
Remove stw.s, stw.h, and extra scratch space.
Use nascent_init to initialze MIPS CSRs.
Add amo emulation via illegal instruction exceptions.
Change to use AMO and RDTIME illegal instruction exceptions.
Revise the dts file.
Remove code that jumps to mips_cps_core_entry.
Changes in v2:
Break up one patch to 11 patches.
Changes in v1:
Original code.
***
Chao-ying Fu (8):
platform: generic: mips: add P8700
platform: generic: mips: add header files
platform: generic: mips: add an entry function
platform: generic: mips: add the platform file
lib: Emulate amo instructions
platform: generic: mips: add a dts file
platform: generic: mips: add objects.mk
Initialize MIPS custom PMA registers
include/sbi/sbi_atomic.h | 90 ++++
lib/sbi/objects.mk | 1 +
lib/sbi/riscv_asm.c | 36 ++
lib/sbi/sbi_atomic.c | 182 ++++++++
lib/sbi/sbi_illegal_insn.c | 492 ++++++++++++++++++++
platform/generic/Kconfig | 4 +
platform/generic/configs/defconfig | 1 +
platform/generic/include/mips/board.h | 33 ++
platform/generic/include/mips/mips-cm.h | 88 ++++
platform/generic/include/mips/p8700.h | 122 +++++
platform/generic/mips/cps-vec.S | 75 +++
platform/generic/mips/mips,boston-p8700.dts | 347 ++++++++++++++
platform/generic/mips/objects.mk | 7 +
platform/generic/mips/p8700.c | 276 +++++++++++
14 files changed, 1754 insertions(+)
create mode 100644 include/sbi/sbi_atomic.h
create mode 100644 lib/sbi/sbi_atomic.c
create mode 100644 platform/generic/include/mips/board.h
create mode 100644 platform/generic/include/mips/mips-cm.h
create mode 100644 platform/generic/include/mips/p8700.h
create mode 100644 platform/generic/mips/cps-vec.S
create mode 100644 platform/generic/mips/mips,boston-p8700.dts
create mode 100644 platform/generic/mips/objects.mk
create mode 100644 platform/generic/mips/p8700.c
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply [flat|nested] 70+ messages in thread* Re: [PATCH v4 0/8] *** Add MIPS P8700 platform ***
2025-04-29 23:29 ` [PATCH v4 0/8] *** Add MIPS P8700 platform *** Chao-ying Fu
@ 2025-05-19 12:16 ` Anup Patel
2025-05-19 18:33 ` Chao-ying Fu
0 siblings, 1 reply; 70+ messages in thread
From: Anup Patel @ 2025-05-19 12:16 UTC (permalink / raw)
To: Chao-ying Fu; +Cc: opensbi, Chao-ying Fu
On Wed, Apr 30, 2025 at 5:37 AM Chao-ying Fu <icebergfu@gmail.com> wrote:
>
> ***
> Changes in v4:
> Remove code that overrides nascent_init.
> Update p8700.c to work with the latest override.
> Use csr_set for mipsconfig6 in p8700.c.
> Add riscv,cbom-block-size to the dts file.
>
> Changes in v3:
> Remove stw.s, stw.h, and extra scratch space.
> Use nascent_init to initialze MIPS CSRs.
> Add amo emulation via illegal instruction exceptions.
> Change to use AMO and RDTIME illegal instruction exceptions.
> Revise the dts file.
> Remove code that jumps to mips_cps_core_entry.
>
> Changes in v2:
> Break up one patch to 11 patches.
>
> Changes in v1:
> Original code.
> ***
>
> Chao-ying Fu (8):
> platform: generic: mips: add P8700
> platform: generic: mips: add header files
> platform: generic: mips: add an entry function
> platform: generic: mips: add the platform file
> lib: Emulate amo instructions
> platform: generic: mips: add a dts file
> platform: generic: mips: add objects.mk
> Initialize MIPS custom PMA registers
Drop the AMO emulation patch since I have send another version
of this patch.
Also, you need to rebase this series on latest OpenSBI because
the platform override mechanism in generic platform has changed.
Regards,
Anup
>
> include/sbi/sbi_atomic.h | 90 ++++
> lib/sbi/objects.mk | 1 +
> lib/sbi/riscv_asm.c | 36 ++
> lib/sbi/sbi_atomic.c | 182 ++++++++
> lib/sbi/sbi_illegal_insn.c | 492 ++++++++++++++++++++
> platform/generic/Kconfig | 4 +
> platform/generic/configs/defconfig | 1 +
> platform/generic/include/mips/board.h | 33 ++
> platform/generic/include/mips/mips-cm.h | 88 ++++
> platform/generic/include/mips/p8700.h | 122 +++++
> platform/generic/mips/cps-vec.S | 75 +++
> platform/generic/mips/mips,boston-p8700.dts | 347 ++++++++++++++
> platform/generic/mips/objects.mk | 7 +
> platform/generic/mips/p8700.c | 276 +++++++++++
> 14 files changed, 1754 insertions(+)
> create mode 100644 include/sbi/sbi_atomic.h
> create mode 100644 lib/sbi/sbi_atomic.c
> create mode 100644 platform/generic/include/mips/board.h
> create mode 100644 platform/generic/include/mips/mips-cm.h
> create mode 100644 platform/generic/include/mips/p8700.h
> create mode 100644 platform/generic/mips/cps-vec.S
> create mode 100644 platform/generic/mips/mips,boston-p8700.dts
> create mode 100644 platform/generic/mips/objects.mk
> create mode 100644 platform/generic/mips/p8700.c
>
> --
> 2.47.1
>
>
> --
> opensbi mailing list
> opensbi@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply [flat|nested] 70+ messages in thread
* Re: [PATCH v4 0/8] *** Add MIPS P8700 platform ***
2025-05-19 12:16 ` Anup Patel
@ 2025-05-19 18:33 ` Chao-ying Fu
2025-05-19 21:52 ` Chao-ying Fu
0 siblings, 1 reply; 70+ messages in thread
From: Chao-ying Fu @ 2025-05-19 18:33 UTC (permalink / raw)
To: Anup Patel; +Cc: opensbi, Chao-ying Fu
On Mon, May 19, 2025 at 5:16 AM Anup Patel <anup@brainfault.org> wrote:
>
> On Wed, Apr 30, 2025 at 5:37 AM Chao-ying Fu <icebergfu@gmail.com> wrote:
> >
> > ***
> > Changes in v4:
> > Remove code that overrides nascent_init.
> > Update p8700.c to work with the latest override.
> > Use csr_set for mipsconfig6 in p8700.c.
> > Add riscv,cbom-block-size to the dts file.
> >
> > Changes in v3:
> > Remove stw.s, stw.h, and extra scratch space.
> > Use nascent_init to initialze MIPS CSRs.
> > Add amo emulation via illegal instruction exceptions.
> > Change to use AMO and RDTIME illegal instruction exceptions.
> > Revise the dts file.
> > Remove code that jumps to mips_cps_core_entry.
> >
> > Changes in v2:
> > Break up one patch to 11 patches.
> >
> > Changes in v1:
> > Original code.
> > ***
> >
> > Chao-ying Fu (8):
> > platform: generic: mips: add P8700
> > platform: generic: mips: add header files
> > platform: generic: mips: add an entry function
> > platform: generic: mips: add the platform file
> > lib: Emulate amo instructions
> > platform: generic: mips: add a dts file
> > platform: generic: mips: add objects.mk
> > Initialize MIPS custom PMA registers
>
> Drop the AMO emulation patch since I have send another version
> of this patch.
>
> Also, you need to rebase this series on latest OpenSBI because
> the platform override mechanism in generic platform has changed.
>
> Regards,
> Anup
Yes. I will drop the AMO patch, rebase, and send out a new patch set (v6).
Note: I sent out v5 two weeks ago. (Please ignore v5.)
Thanks a lot for the review!
Regards,
Chao-ying
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply [flat|nested] 70+ messages in thread
* Re: [PATCH v4 0/8] *** Add MIPS P8700 platform ***
2025-05-19 18:33 ` Chao-ying Fu
@ 2025-05-19 21:52 ` Chao-ying Fu
0 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-05-19 21:52 UTC (permalink / raw)
To: Anup Patel; +Cc: opensbi, Chao-ying Fu
On Mon, May 19, 2025 at 11:33 AM Chao-ying Fu <icebergfu@gmail.com> wrote:
>
> On Mon, May 19, 2025 at 5:16 AM Anup Patel <anup@brainfault.org> wrote:
> >
> > On Wed, Apr 30, 2025 at 5:37 AM Chao-ying Fu <icebergfu@gmail.com> wrote:
> > >
> > > ***
> > > Changes in v4:
> > > Remove code that overrides nascent_init.
> > > Update p8700.c to work with the latest override.
> > > Use csr_set for mipsconfig6 in p8700.c.
> > > Add riscv,cbom-block-size to the dts file.
> > >
> > > Changes in v3:
> > > Remove stw.s, stw.h, and extra scratch space.
> > > Use nascent_init to initialze MIPS CSRs.
> > > Add amo emulation via illegal instruction exceptions.
> > > Change to use AMO and RDTIME illegal instruction exceptions.
> > > Revise the dts file.
> > > Remove code that jumps to mips_cps_core_entry.
> > >
> > > Changes in v2:
> > > Break up one patch to 11 patches.
> > >
> > > Changes in v1:
> > > Original code.
> > > ***
> > >
> > > Chao-ying Fu (8):
> > > platform: generic: mips: add P8700
> > > platform: generic: mips: add header files
> > > platform: generic: mips: add an entry function
> > > platform: generic: mips: add the platform file
> > > lib: Emulate amo instructions
> > > platform: generic: mips: add a dts file
> > > platform: generic: mips: add objects.mk
> > > Initialize MIPS custom PMA registers
> >
> > Drop the AMO emulation patch since I have send another version
> > of this patch.
> >
> > Also, you need to rebase this series on latest OpenSBI because
> > the platform override mechanism in generic platform has changed.
> >
> > Regards,
> > Anup
>
> Yes. I will drop the AMO patch, rebase, and send out a new patch set (v6).
> Note: I sent out v5 two weeks ago. (Please ignore v5.)
> Thanks a lot for the review!
Sorry. I got confused about v5 and v6. I didn't send out v5
previously. So, I will send out v5 soon.
Thanks!
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply [flat|nested] 70+ messages in thread
* [PATCH v4 1/8] platform: generic: mips: add P8700
2025-02-12 12:27 ` Anup Patel
` (21 preceding siblings ...)
2025-04-29 23:29 ` [PATCH v4 0/8] *** Add MIPS P8700 platform *** Chao-ying Fu
@ 2025-04-29 23:29 ` Chao-ying Fu
2025-04-29 23:29 ` [PATCH v4 2/8] platform: generic: mips: add header files Chao-ying Fu
` (25 subsequent siblings)
48 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-04-29 23:29 UTC (permalink / raw)
To: opensbi; +Cc: Chao-ying Fu
Add a new config first.
Signed-off-by: Chao-ying Fu <cfu@mips.com>
---
platform/generic/Kconfig | 4 ++++
platform/generic/configs/defconfig | 1 +
2 files changed, 5 insertions(+)
diff --git a/platform/generic/Kconfig b/platform/generic/Kconfig
index 688da3f..a24d6ab 100644
--- a/platform/generic/Kconfig
+++ b/platform/generic/Kconfig
@@ -68,6 +68,10 @@ config PLATFORM_THEAD
select THEAD_C9XX_PMU
default n
+config PLATFORM_MIPS_P8700
+ bool "MIPS P8700 support"
+ default n
+
source "$(OPENSBI_SRC_DIR)/platform/generic/andes/Kconfig"
source "$(OPENSBI_SRC_DIR)/platform/generic/thead/Kconfig"
diff --git a/platform/generic/configs/defconfig b/platform/generic/configs/defconfig
index bb26062..ce1f1ae 100644
--- a/platform/generic/configs/defconfig
+++ b/platform/generic/configs/defconfig
@@ -6,6 +6,7 @@ CONFIG_PLATFORM_SIFIVE_FU740=y
CONFIG_PLATFORM_SOPHGO_SG2042=y
CONFIG_PLATFORM_STARFIVE_JH7110=y
CONFIG_PLATFORM_THEAD=y
+CONFIG_PLATFORM_MIPS_P8700=n
CONFIG_FDT_CPPC=y
CONFIG_FDT_CPPC_RPMI=y
CONFIG_FDT_GPIO=y
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 70+ messages in thread* [PATCH v4 2/8] platform: generic: mips: add header files
2025-02-12 12:27 ` Anup Patel
` (22 preceding siblings ...)
2025-04-29 23:29 ` [PATCH v4 1/8] platform: generic: mips: add P8700 Chao-ying Fu
@ 2025-04-29 23:29 ` Chao-ying Fu
2025-04-29 23:29 ` [PATCH v4 3/8] platform: generic: mips: add an entry function Chao-ying Fu
` (24 subsequent siblings)
48 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-04-29 23:29 UTC (permalink / raw)
To: opensbi; +Cc: Chao-ying Fu
Add header files to define MIPS Custom CSRs and define for the board.
Add accessor functions for MIPS CM registers.
Signed-off-by: Chao-ying Fu <cfu@mips.com>
---
platform/generic/include/mips/board.h | 33 +++++++
platform/generic/include/mips/mips-cm.h | 88 +++++++++++++++++
platform/generic/include/mips/p8700.h | 122 ++++++++++++++++++++++++
3 files changed, 243 insertions(+)
create mode 100644 platform/generic/include/mips/board.h
create mode 100644 platform/generic/include/mips/mips-cm.h
create mode 100644 platform/generic/include/mips/p8700.h
diff --git a/platform/generic/include/mips/board.h b/platform/generic/include/mips/board.h
new file mode 100644
index 0000000..6fe7b8b
--- /dev/null
+++ b/platform/generic/include/mips/board.h
@@ -0,0 +1,33 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 MIPS
+ *
+ */
+
+#ifndef __BOARD_H__
+#define __BOARD_H__
+
+/* Please review all defines to change for your board. */
+
+/* Use in stw.S, p8700.c, p8700.h, mips-cm.h */
+#define CM_BASE 0x16100000
+
+/* Use in mips-cm.h, p8700.c */
+#define CLUSTERS_IN_PLATFORM 1
+#if CLUSTERS_IN_PLATFORM > 1
+/* Define global CM bases for cluster 0, 1, 2, and more. */
+#define GLOBAL_CM_BASE0 0
+#define GLOBAL_CM_BASE1 0
+#define GLOBAL_CM_BASE2 0
+#endif
+
+/* Use in stw.S */
+#define TIMER_ADDR (CM_BASE + 0x8050)
+
+/* Use in cps-vec.S */
+#define DRAM_ADDRESS 0x80000000
+#define DRAM_SIZE 0x80000000
+#define DRAM_PMP_ADDR ((DRAM_ADDRESS >> 2) | ((DRAM_SIZE - 1) >> 3))
+
+#endif
diff --git a/platform/generic/include/mips/mips-cm.h b/platform/generic/include/mips/mips-cm.h
new file mode 100644
index 0000000..19b4384
--- /dev/null
+++ b/platform/generic/include/mips/mips-cm.h
@@ -0,0 +1,88 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 MIPS
+ *
+ */
+
+#ifndef __MIPS_CM_H__
+#define __MIPS_CM_H__
+
+#include <mips/p8700.h>
+#include <sbi/sbi_console.h>
+
+/* Define 1 to print out CM read and write info */
+#define DEBUG_CM 0
+
+#if CLUSTERS_IN_PLATFORM > 1
+static long GLOBAL_CM_BASE[CLUSTERS_IN_PLATFORM] = {GLOBAL_CM_BASE0, GLOBAL_CM_BASE1, GLOBAL_CM_BASE2};
+#else
+static long GLOBAL_CM_BASE[CLUSTERS_IN_PLATFORM] = {CM_BASE};
+#endif
+
+#define CPS_ACCESSOR_R(unit, sz, base, off, name) \
+static inline u##sz read_##unit##_##name(u32 hartid, bool local_p) \
+{ \
+ u##sz value; \
+ long cmd_reg; \
+ int cl, co; \
+ cl = cpu_cluster(hartid); \
+ co = cpu_core(hartid); \
+ cmd_reg = (local_p ? (base) : ((base) - CM_BASE + GLOBAL_CM_BASE[cl])) \
+ + (co << CM_BASE_CORE_SHIFT) \
+ + off; \
+ if (DEBUG_CM) \
+ sbi_printf("CM READ%d cmd_reg=%lx\n", sz, cmd_reg); \
+ if (sz == 32) \
+ asm volatile("lw %0,0(%1)":"=r"(value):"r"(cmd_reg)); \
+ else if (sz == 64) \
+ asm volatile("ld %0,0(%1)":"=r"(value):"r"(cmd_reg)); \
+ asm volatile("fence"); \
+ return value; \
+}
+
+#define CPS_ACCESSOR_W(unit, sz, base, off, name) \
+static inline void write_##unit##_##name(u32 hartid, u##sz value, bool local_p) \
+{ \
+ long cmd_reg; \
+ int cl, co; \
+ cl = cpu_cluster(hartid); \
+ co = cpu_core(hartid); \
+ cmd_reg = (local_p ? (base) : ((base) - CM_BASE + GLOBAL_CM_BASE[cl])) \
+ + (co << CM_BASE_CORE_SHIFT) \
+ + off; \
+ if (DEBUG_CM) \
+ sbi_printf("CM WRITE%d cmd_reg=%lx value=%lx\n", sz, \
+ cmd_reg, (u64)value); \
+ if (sz == 32) \
+ asm volatile("sw %0,0(%1)"::"r"(value),"r"(cmd_reg)); \
+ else if (sz == 64) \
+ asm volatile("sd %0,0(%1)"::"r"(value),"r"(cmd_reg)); \
+ asm volatile("fence"); \
+}
+
+#define CPS_ACCESSOR_RW(unit, sz, base, off, name) \
+ CPS_ACCESSOR_R(unit, sz, base, off, name) \
+ CPS_ACCESSOR_W(unit, sz, base, off, name)
+
+#define CPC_CX_ACCESSOR_RW(sz, off, name) \
+ CPS_ACCESSOR_RW(cpc, sz, CPC_BASE, CPC_OFF_LOCAL + (off), co_##name)
+
+#define GCR_CX_ACCESSOR_RW(sz, off, name) \
+ CPS_ACCESSOR_RW(gcr, sz, CM_BASE, GCR_OFF_LOCAL + (off), co_##name)
+
+GCR_CX_ACCESSOR_RW(64, cpu_hart(hartid) << CM_BASE_HART_SHIFT, reset_base)
+GCR_CX_ACCESSOR_RW(32, GCR_CORE_COH_EN, coherence)
+
+CPC_CX_ACCESSOR_RW(32, CPC_Cx_VP_RUN, vp_run)
+CPC_CX_ACCESSOR_RW(32, CPC_Cx_VP_STOP, vp_stop)
+CPC_CX_ACCESSOR_RW(32, CPC_Cx_CMD, cmd)
+CPC_CX_ACCESSOR_RW(32, CPC_Cx_STAT_CONF, stat_conf)
+
+#define CPC_ACCESSOR_RW(sz, off, name) \
+ CPS_ACCESSOR_RW(cpc, sz, CPC_BASE, off, name)
+
+CPC_ACCESSOR_RW(32, CPC_PWRUP_CTL, pwrup_ctl)
+CPC_ACCESSOR_RW(32, CPC_CM_STAT_CONF, cm_stat_conf)
+
+#endif
diff --git a/platform/generic/include/mips/p8700.h b/platform/generic/include/mips/p8700.h
new file mode 100644
index 0000000..6aa71d9
--- /dev/null
+++ b/platform/generic/include/mips/p8700.h
@@ -0,0 +1,122 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 MIPS
+ *
+ */
+
+#ifndef __P8700_H__
+#define __P8700_H__
+
+#include <mips/board.h>
+
+/* PMA */
+#define CSR_MIPSPMACFG0 0x7e0
+#define CSR_MIPSPMACFG1 0x7e1
+#define CSR_MIPSPMACFG2 0x7e2
+#define CSR_MIPSPMACFG3 0x7e3
+#define CSR_MIPSPMACFG4 0x7e4
+#define CSR_MIPSPMACFG5 0x7e5
+#define CSR_MIPSPMACFG6 0x7e6
+#define CSR_MIPSPMACFG7 0x7e7
+#define CSR_MIPSPMACFG8 0x7e8
+#define CSR_MIPSPMACFG9 0x7e9
+#define CSR_MIPSPMACFG10 0x7ea
+#define CSR_MIPSPMACFG11 0x7eb
+#define CSR_MIPSPMACFG12 0x7ec
+#define CSR_MIPSPMACFG13 0x7ed
+#define CSR_MIPSPMACFG14 0x7ee
+#define CSR_MIPSPMACFG15 0x7ef
+
+/* MIPS CCA */
+#define CCA_CACHE_ENABLE 0
+#define CCA_CACHE_DISABLE 2
+#define PMA_SPECULATION (1 << 3)
+
+/* MIPS CSR */
+#define CSR_MIPSTVEC 0x7c0
+#define CSR_MIPSCONFIG0 0x7d0
+#define CSR_MIPSCONFIG1 0x7d1
+#define CSR_MIPSCONFIG2 0x7d2
+#define CSR_MIPSCONFIG3 0x7d3
+#define CSR_MIPSCONFIG4 0x7d4
+#define CSR_MIPSCONFIG5 0x7d5
+#define CSR_MIPSCONFIG6 0x7d6
+#define CSR_MIPSCONFIG7 0x7d7
+#define CSR_MIPSCONFIG8 0x7d8
+#define CSR_MIPSCONFIG9 0x7d9
+#define CSR_MIPSCONFIG10 0x7da
+#define CSR_MIPSCONFIG11 0x7db
+
+#define MIPSCONFIG5_MTW 4
+
+#define GEN_MASK(h, l) (((1ul << ((h) + 1 - (l))) - 1) << (l))
+#define EXT(val, mask) (((val) & (mask)) >> (__builtin_ffs(mask) - 1))
+
+/*
+ * We allocate the number of bits to encode clusters, cores, and harts
+ * from the original mhartid to a new dense index.
+ */
+#define NUM_OF_BITS_FOR_CLUSTERS 4
+#define NUM_OF_BITS_FOR_CORES 12
+#define NUM_OF_BITS_FOR_HARTS 4
+
+/* mhartid field info */
+#define MHARTID_CORE_MASK 0xff
+#define MHARTID_CORE_SHIFT 4
+
+/* To get the field from new/hashed mhartid */
+#define NEW_CLUSTER_SHIFT (NUM_OF_BITS_FOR_CORES + NUM_OF_BITS_FOR_HARTS)
+#define NEW_CLUSTER_MASK ((1 << NUM_OF_BITS_FOR_CLUSTERS) - 1)
+#define NEW_CORE_SHIFT NUM_OF_BITS_FOR_HARTS
+#define NEW_CORE_MASK ((1 << NUM_OF_BITS_FOR_CORES) - 1)
+#define NEW_HART_MASK ((1 << NUM_OF_BITS_FOR_HARTS) - 1)
+#define cpu_cluster(i) (((i) >> NEW_CLUSTER_SHIFT) & NEW_CLUSTER_MASK)
+#define cpu_core(i) (((i) >> NEW_CORE_SHIFT) & NEW_CORE_MASK)
+#define cpu_hart(i) ((i) & NEW_HART_MASK)
+
+#define CPC_BASE (CM_BASE + 0x8000)
+
+#define SIZE_FOR_CPC_MTIME 0x10000 /* The size must be 2^order */
+#define AIA_BASE (CM_BASE + 0x40000)
+#define SIZE_FOR_AIA_M_MODE 0x20000 /* The size must be 2^order */
+#define P8700_ALIGN 0x10000
+
+#define CM_BASE_HART_SHIFT 3
+#define CM_BASE_CORE_SHIFT 8
+#define CM_BASE_CLUSTER_SHIFT 19
+
+/* GCR Block offsets */
+#define GCR_OFF_LOCAL 0x2000
+
+#define GCR_BASE_OFFSET 0x0008
+#define GCR_CORE_COH_EN 0x00f8
+#define GCR_CORE_COH_EN_EN (0x1 << 0)
+
+#define L2_PFT_CONTROL_OFFSET 0x0300
+#define L2_PFT_CONTROL_B_OFFSET 0x0308
+
+/* CPC Block offsets */
+#define CPC_PWRUP_CTL 0x0030
+#define CPC_CM_STAT_CONF 0x1008
+
+#define CPC_OFF_LOCAL 0x2000
+
+#define CPC_Cx_VP_STOP 0x0020
+#define CPC_Cx_VP_RUN 0x0028
+#define CPC_Cx_CMD 0x0000
+
+#define CPC_Cx_CMD_PWRUP 0x3
+#define CPC_Cx_CMD_RESET 0x4
+
+#define CPC_Cx_STAT_CONF 0x0008
+#define CPC_Cx_STAT_CONF_SEQ_STATE GEN_MASK(22, 19)
+#define CPC_Cx_STAT_CONF_SEQ_STATE_U5 6
+#define CPC_Cx_STAT_CONF_SEQ_STATE_U6 7
+
+#define INDEXED(op, reg, idx, offset, base) \
+ li idx, offset ;\
+ add idx, idx, base ;\
+ op reg, (idx)
+
+#endif
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 70+ messages in thread* [PATCH v4 3/8] platform: generic: mips: add an entry function
2025-02-12 12:27 ` Anup Patel
` (23 preceding siblings ...)
2025-04-29 23:29 ` [PATCH v4 2/8] platform: generic: mips: add header files Chao-ying Fu
@ 2025-04-29 23:29 ` Chao-ying Fu
2025-04-29 23:29 ` [PATCH v4 4/8] platform: generic: mips: add the platform file Chao-ying Fu
` (23 subsequent siblings)
48 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-04-29 23:29 UTC (permalink / raw)
To: opensbi; +Cc: Chao-ying Fu
The entry function is minimum boot code for harts to execute after
reset, nmi, cache error, and debug exception.
Signed-off-by: Chao-ying Fu <cfu@mips.com>
---
platform/generic/mips/cps-vec.S | 75 +++++++++++++++++++++++++++++++++
1 file changed, 75 insertions(+)
create mode 100644 platform/generic/mips/cps-vec.S
diff --git a/platform/generic/mips/cps-vec.S b/platform/generic/mips/cps-vec.S
new file mode 100644
index 0000000..9309e20
--- /dev/null
+++ b/platform/generic/mips/cps-vec.S
@@ -0,0 +1,75 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 MIPS
+ *
+ */
+
+#include <sbi/riscv_encoding.h>
+#include <mips/p8700.h>
+
+ .text
+ .align 12
+ .globl mips_cps_core_entry
+mips_cps_core_entry:
+ j 1f
+
+ .align 2
+nmi_vector:
+ j 1f
+
+ .align 2
+cacheerr_vector:
+ j 1f
+
+ .align 2
+debugexc_vector:
+ j 1f
+
+ .align 2
+1:
+ li x1, 0
+ li x2, 0
+ li x3, 0
+ li x4, 0
+ li x5, 0
+ li x6, 0
+ li x7, 0
+ li x8, 0
+ li x9, 0
+ li x10, 0
+#ifdef FW_FDT_PATH
+ li x11, 0
+#endif
+ li x12, 0
+ li x13, 0
+ li x14, 0
+ li x15, 0
+ li x16, 0
+ li x17, 0
+ li x18, 0
+ li x19, 0
+ li x20, 0
+ li x21, 0
+ li x22, 0
+ li x23, 0
+ li x24, 0
+ li x25, 0
+ li x26, 0
+ li x27, 0
+ li x28, 0
+ li x29, 0
+ li x30, 0
+ li x31, 0
+
+ /* a0 has mhartid */
+ csrr a0, CSR_MHARTID
+
+ /* Let hart 0 jump to _start */
+ beqz a0, 1f
+ lla t0, _start_warm
+ jr t0
+1:
+ lla t0, _start
+ jr t0
+
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 70+ messages in thread* [PATCH v4 4/8] platform: generic: mips: add the platform file
2025-02-12 12:27 ` Anup Patel
` (24 preceding siblings ...)
2025-04-29 23:29 ` [PATCH v4 3/8] platform: generic: mips: add an entry function Chao-ying Fu
@ 2025-04-29 23:29 ` Chao-ying Fu
2025-04-29 23:29 ` [PATCH v4 5/8] lib: Emulate amo instructions Chao-ying Fu
` (22 subsequent siblings)
48 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-04-29 23:29 UTC (permalink / raw)
To: opensbi; +Cc: Chao-ying Fu
We add the platform file for MIPS P8700.
Signed-off-by: Chao-ying Fu <cfu@mips.com>
---
platform/generic/mips/p8700.c | 276 ++++++++++++++++++++++++++++++++++
1 file changed, 276 insertions(+)
create mode 100644 platform/generic/mips/p8700.c
diff --git a/platform/generic/mips/p8700.c b/platform/generic/mips/p8700.c
new file mode 100644
index 0000000..9ac8a58
--- /dev/null
+++ b/platform/generic/mips/p8700.c
@@ -0,0 +1,276 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 MIPS
+ *
+ */
+
+#include <platform_override.h>
+#include <sbi/sbi_domain.h>
+#include <sbi/sbi_error.h>
+#include <sbi/sbi_hsm.h>
+#include <sbi/sbi_timer.h>
+#include <sbi_utils/fdt/fdt_helper.h>
+#include <mips/p8700.h>
+#include <mips/mips-cm.h>
+
+extern void mips_cps_core_entry(void);
+
+#if CLUSTERS_IN_PLATFORM > 1
+static void power_up_other_cluster(u32 hartid)
+{
+ unsigned int stat;
+ unsigned int timeout;
+ bool local_p = (cpu_cluster(current_hartid()) == cpu_cluster(hartid));
+
+ /* Power up cluster cl core 0 hart 0 */
+ write_cpc_pwrup_ctl(hartid, 1, local_p);
+
+ /* Wait for the CM to start up */
+ timeout = 100;
+ while (true) {
+ stat = read_cpc_cm_stat_conf(hartid, local_p);
+ stat = EXT(stat, CPC_Cx_STAT_CONF_SEQ_STATE);
+ if (stat == CPC_Cx_STAT_CONF_SEQ_STATE_U5)
+ break;
+
+ /* Delay a little while before we start warning */
+ if (timeout) {
+ sbi_dprintf("Delay a little while before we start warning\n");
+ timeout--;
+ }
+ else {
+ sbi_printf("Waiting for cluster %u CM to power up... STAT_CONF=0x%x\n",
+ cpu_cluster(hartid), stat);
+ break;
+ }
+ }
+}
+#endif
+
+static int mips_hart_start(u32 hartid, ulong saddr)
+{
+ unsigned int stat;
+ unsigned int timeout;
+ bool local_p = (cpu_cluster(current_hartid()) == cpu_cluster(hartid));
+
+ /* Hart 0 is the boot hart, and we don't use the CPC cmd to start. */
+ if (hartid == 0)
+ return SBI_ENOTSUPP;
+
+ if (cpu_hart(hartid) == 0) {
+ /* Change cluster cl core co hart 0 reset base */
+ write_gcr_co_reset_base(hartid,
+ (unsigned long)mips_cps_core_entry, local_p);
+
+ /* Ensure its coherency is disabled */
+ write_gcr_co_coherence(hartid, 0, local_p);
+
+ /* Start cluster cl core co hart 0 */
+ write_cpc_co_vp_run(hartid, 1 << cpu_hart(hartid), local_p);
+
+ /* Reset cluster cl core co hart 0 */
+ write_cpc_co_cmd(hartid, CPC_Cx_CMD_RESET, local_p);
+
+ timeout = 100;
+ while (true) {
+ stat = read_cpc_co_stat_conf(hartid, local_p);
+ stat = EXT(stat, CPC_Cx_STAT_CONF_SEQ_STATE);
+ if (stat == CPC_Cx_STAT_CONF_SEQ_STATE_U6)
+ break;
+
+ /* Delay a little while before we start warning */
+ if (timeout) {
+ sbi_timer_mdelay(10);
+ timeout--;
+ }
+ else {
+ sbi_printf("Waiting for cluster %u core %u hart %u to start... STAT_CONF=0x%x\n",
+ cpu_cluster(hartid),
+ cpu_core(hartid), cpu_hart(hartid),
+ stat);
+ break;
+ }
+ }
+ }
+ else {
+ write_gcr_co_reset_base(hartid,
+ (unsigned long)mips_cps_core_entry, local_p);
+ write_cpc_co_vp_run(hartid, 1 << cpu_hart(hartid), local_p);
+ }
+
+ return 0;
+}
+
+static int mips_hart_stop()
+{
+ u32 hartid = current_hartid();
+ bool local_p = (cpu_cluster(current_hartid()) == cpu_cluster(hartid));
+
+ /* Hart 0 is the boot hart, and we don't use the CPC cmd to stop. */
+ if (hartid == 0)
+ return SBI_ENOTSUPP;
+
+ write_cpc_co_vp_stop(hartid, 1 << cpu_hart(hartid), local_p);
+
+ return 0;
+}
+
+static const struct sbi_hsm_device mips_hsm = {
+ .name = "mips_hsm",
+ .hart_start = mips_hart_start,
+ .hart_stop = mips_hart_stop,
+};
+
+static int mips_p8700_final_init(bool cold_boot)
+{
+ if (cold_boot)
+ sbi_hsm_set_device(&mips_hsm);
+
+ return generic_final_init(cold_boot);
+}
+
+static int mips_p8700_early_init(bool cold_boot)
+{
+ int rc;
+
+ rc = generic_early_init(cold_boot);
+ if (rc)
+ return rc;
+
+ if (cold_boot)
+ {
+#if CLUSTERS_IN_PLATFORM > 1
+ int i;
+ /* Power up other clusters in the platform. */
+ for (i = 1; i < CLUSTERS_IN_PLATFORM; i++) {
+ power_up_other_cluster(i << NEW_CLUSTER_SHIFT);
+ }
+#endif
+
+ /* For the CPC mtime region, the minimum size is 0x10000. */
+ rc = sbi_domain_root_add_memrange(CM_BASE, SIZE_FOR_CPC_MTIME,
+ P8700_ALIGN,
+ (SBI_DOMAIN_MEMREGION_MMIO |
+ SBI_DOMAIN_MEMREGION_M_READABLE |
+ SBI_DOMAIN_MEMREGION_M_WRITABLE));
+ if (rc)
+ return rc;
+
+ /* For the APLIC and ACLINT m-mode region */
+ rc = sbi_domain_root_add_memrange(AIA_BASE, SIZE_FOR_AIA_M_MODE,
+ P8700_ALIGN,
+ (SBI_DOMAIN_MEMREGION_MMIO |
+ SBI_DOMAIN_MEMREGION_M_READABLE |
+ SBI_DOMAIN_MEMREGION_M_WRITABLE));
+ if (rc)
+ return rc;
+
+#if CLUSTERS_IN_PLATFORM > 1
+ for (i = 0; i < CLUSTERS_IN_PLATFORM; i++) {
+ /* For the CPC mtime region, the minimum size is 0x10000. */
+ rc = sbi_domain_root_add_memrange(GLOBAL_CM_BASE[i], SIZE_FOR_CPC_MTIME,
+ P8700_ALIGN,
+ (SBI_DOMAIN_MEMREGION_MMIO |
+ SBI_DOMAIN_MEMREGION_M_READABLE |
+ SBI_DOMAIN_MEMREGION_M_WRITABLE));
+ if (rc)
+ return rc;
+
+ /* For the APLIC and ACLINT m-mode region */
+ rc = sbi_domain_root_add_memrange(AIA_BASE - CM_BASE + GLOBAL_CM_BASE[i], SIZE_FOR_AIA_M_MODE,
+ P8700_ALIGN,
+ (SBI_DOMAIN_MEMREGION_MMIO |
+ SBI_DOMAIN_MEMREGION_M_READABLE |
+ SBI_DOMAIN_MEMREGION_M_WRITABLE));
+ if (rc)
+ return rc;
+ }
+#endif
+ }
+
+ return 0;
+}
+
+static int mips_p8700_nascent_init(void)
+{
+ u64 hartid = current_hartid();
+ u64 cm_base = CM_BASE;
+ int i;
+
+ /* Coherence enable for every core */
+ if (cpu_hart(hartid) == 0) {
+ cm_base += (cpu_core(hartid) << CM_BASE_CORE_SHIFT);
+ asm volatile("sd %0,0(%1)"::"r"(GCR_CORE_COH_EN_EN),
+ "r"(cm_base + GCR_OFF_LOCAL + GCR_CORE_COH_EN));
+ asm volatile("fence");
+ }
+
+ /* Set up pmp for DRAM */
+ csr_write(CSR_PMPADDR14, DRAM_PMP_ADDR);
+ /* All from 0x0 */
+ csr_write(CSR_PMPADDR15, 0x1fffffffffffffff);
+ csr_write(CSR_PMPCFG2, ((PMP_A_NAPOT|PMP_R|PMP_W|PMP_X)<<56)|
+ ((PMP_A_NAPOT|PMP_R|PMP_W|PMP_X)<<48));
+ /* Set cacheable for pmp6, uncacheable for pmp7 */
+ csr_write(CSR_MIPSPMACFG2, ((u64)CCA_CACHE_DISABLE << 56)|
+ ((u64)CCA_CACHE_ENABLE << 48));
+ /* Reset pmpcfg0 */
+ csr_write(CSR_PMPCFG0, 0);
+ /* Reset pmacfg0 */
+ csr_write(CSR_MIPSPMACFG0, 0);
+ asm volatile("fence");
+
+ /* Per cluster set up */
+ if (cpu_core(hartid) == 0 && cpu_hart(hartid) == 0) {
+ /* Enable L2 prefetch */
+ asm volatile("sw %0,0(%1)"::"r"(0xfffff110),
+ "r"(cm_base + L2_PFT_CONTROL_OFFSET));
+ asm volatile("sw %0,0(%1)"::"r"(0x15ff),
+ "r"(cm_base + L2_PFT_CONTROL_B_OFFSET));
+ }
+
+ /* Per core set up */
+ if (cpu_hart(hartid) == 0) {
+ /* Enable load pair, store pair, and HTW */
+ csr_clear(CSR_MIPSCONFIG7, (1<<12)|(1<<13)|(1<<7));
+
+ /* Disable noRFO, misaligned load/store */
+ csr_set(CSR_MIPSCONFIG7, (1<<25)|(1<<9));
+
+ /* Enable L1-D$ Prefetch */
+ csr_write(CSR_MIPSCONFIG11, 0xff);
+
+ for (i = 0; i < 8; i++) {
+ csr_set(CSR_MIPSCONFIG8, 4 + 0x100 * i);
+ csr_set(CSR_MIPSCONFIG9, 8);
+ asm volatile("fence");
+ asm volatile("fence.i");
+ }
+ }
+
+ /* Per hart set up */
+ /* Enable AMO and RDTIME illegal instruction exceptions. */
+ csr_set(CSR_MIPSCONFIG6, (1<<2)|(1<<1));
+
+ return 0;
+}
+
+static int mips_p8700_platform_init(const void *fdt, int nodeoff, const struct fdt_match *match)
+{
+ generic_platform_ops.early_init = mips_p8700_early_init;
+ generic_platform_ops.final_init = mips_p8700_final_init;
+ generic_platform_ops.nascent_init = mips_p8700_nascent_init;
+
+ return 0;
+}
+
+static const struct fdt_match mips_p8700_match[] = {
+ { .compatible = "mips,p8700" },
+ { },
+};
+
+const struct fdt_driver mips_p8700 = {
+ .match_table = mips_p8700_match,
+ .init = mips_p8700_platform_init,
+};
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 70+ messages in thread* [PATCH v4 5/8] lib: Emulate amo instructions
2025-02-12 12:27 ` Anup Patel
` (25 preceding siblings ...)
2025-04-29 23:29 ` [PATCH v4 4/8] platform: generic: mips: add the platform file Chao-ying Fu
@ 2025-04-29 23:29 ` Chao-ying Fu
2025-05-19 12:14 ` Anup Patel
2025-04-29 23:29 ` [PATCH v4 6/8] platform: generic: mips: add a dts file Chao-ying Fu
` (21 subsequent siblings)
48 siblings, 1 reply; 70+ messages in thread
From: Chao-ying Fu @ 2025-04-29 23:29 UTC (permalink / raw)
To: opensbi; +Cc: Chao-ying Fu
Match amo instruction opcode to emulate from illegal instruction
exceptions.
Signed-off-by: Chao-ying Fu <cfu@mips.com>
---
include/sbi/sbi_atomic.h | 90 +++++++
lib/sbi/objects.mk | 1 +
lib/sbi/sbi_atomic.c | 182 ++++++++++++++
lib/sbi/sbi_illegal_insn.c | 492 +++++++++++++++++++++++++++++++++++++
4 files changed, 765 insertions(+)
create mode 100644 include/sbi/sbi_atomic.h
create mode 100644 lib/sbi/sbi_atomic.c
diff --git a/include/sbi/sbi_atomic.h b/include/sbi/sbi_atomic.h
new file mode 100644
index 0000000..561da89
--- /dev/null
+++ b/include/sbi/sbi_atomic.h
@@ -0,0 +1,90 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 MIPS
+ *
+ */
+
+#ifndef __SBI_ATOMIC_H__
+#define __SBI_ATOMIC_H__
+
+#include <sbi/sbi_types.h>
+
+struct sbi_trap_regs;
+
+int sbi_atomic_add_w(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_add_d(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_and_w(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_and_d(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_or_w(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_or_d(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_xor_w(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_xor_d(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_max_w(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_max_d(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_min_w(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_min_d(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_maxu_w(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_maxu_d(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_minu_w(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_minu_d(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_swap_w(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_swap_d(ulong insn, struct sbi_trap_regs *regs);
+
+int sbi_atomic_add_w_aq(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_add_d_aq(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_and_w_aq(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_and_d_aq(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_or_w_aq(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_or_d_aq(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_xor_w_aq(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_xor_d_aq(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_max_w_aq(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_max_d_aq(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_min_w_aq(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_min_d_aq(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_maxu_w_aq(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_maxu_d_aq(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_minu_w_aq(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_minu_d_aq(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_swap_w_aq(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_swap_d_aq(ulong insn, struct sbi_trap_regs *regs);
+
+int sbi_atomic_add_w_rl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_add_d_rl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_and_w_rl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_and_d_rl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_or_w_rl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_or_d_rl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_xor_w_rl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_xor_d_rl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_max_w_rl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_max_d_rl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_min_w_rl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_min_d_rl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_maxu_w_rl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_maxu_d_rl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_minu_w_rl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_minu_d_rl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_swap_w_rl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_swap_d_rl(ulong insn, struct sbi_trap_regs *regs);
+
+int sbi_atomic_add_w_aqrl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_add_d_aqrl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_and_w_aqrl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_and_d_aqrl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_or_w_aqrl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_or_d_aqrl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_xor_w_aqrl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_xor_d_aqrl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_max_w_aqrl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_max_d_aqrl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_min_w_aqrl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_min_d_aqrl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_maxu_w_aqrl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_maxu_d_aqrl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_minu_w_aqrl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_minu_d_aqrl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_swap_w_aqrl(ulong insn, struct sbi_trap_regs *regs);
+int sbi_atomic_swap_d_aqrl(ulong insn, struct sbi_trap_regs *regs);
+#endif
diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
index 9cb2842..af7a846 100644
--- a/lib/sbi/objects.mk
+++ b/lib/sbi/objects.mk
@@ -99,3 +99,4 @@ libsbi-objs-y += sbi_trap_v_ldst.o
libsbi-objs-y += sbi_unpriv.o
libsbi-objs-y += sbi_expected_trap.o
libsbi-objs-y += sbi_cppc.o
+libsbi-objs-y += sbi_atomic.o
diff --git a/lib/sbi/sbi_atomic.c b/lib/sbi/sbi_atomic.c
new file mode 100644
index 0000000..afd28d2
--- /dev/null
+++ b/lib/sbi/sbi_atomic.c
@@ -0,0 +1,182 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 MIPS
+ *
+ */
+
+#include <sbi/riscv_asm.h>
+#include <sbi/sbi_trap.h>
+#include <sbi/sbi_hart.h>
+
+#define DEFINE_UNPRIVILEGED_LR_FUNCTION(type, aqrl, insn) \
+ type sbi_lr_##type##aqrl(const type *addr, \
+ struct sbi_trap_info *trap) \
+ { \
+ register ulong tinfo asm("a3"); \
+ register ulong mstatus = 0; \
+ register ulong mtvec = sbi_hart_expected_trap_addr(); \
+ type ret = 0; \
+ trap->cause = 0; \
+ asm volatile( \
+ "add %[tinfo], %[taddr], zero\n" \
+ "csrrw %[mtvec], " STR(CSR_MTVEC) ", %[mtvec]\n" \
+ "csrrs %[mstatus], " STR(CSR_MSTATUS) ", %[mprv]\n" \
+ ".option push\n" \
+ ".option norvc\n" \
+ #insn " %[ret], %[addr]\n" \
+ ".option pop\n" \
+ "csrw " STR(CSR_MSTATUS) ", %[mstatus]\n" \
+ "csrw " STR(CSR_MTVEC) ", %[mtvec]" \
+ : [mstatus] "+&r"(mstatus), [mtvec] "+&r"(mtvec), \
+ [tinfo] "+&r"(tinfo), [ret] "=&r"(ret) \
+ : [addr] "m"(*addr), [mprv] "r"(MSTATUS_MPRV), \
+ [taddr] "r"((ulong)trap) \
+ : "a4", "memory"); \
+ return ret; \
+ }
+
+#define DEFINE_UNPRIVILEGED_SC_FUNCTION(type, aqrl, insn) \
+ type sbi_sc_##type##aqrl(type *addr, type val, \
+ struct sbi_trap_info *trap) \
+ { \
+ register ulong tinfo asm("a3"); \
+ register ulong mstatus = 0; \
+ register ulong mtvec = sbi_hart_expected_trap_addr(); \
+ type ret = 0; \
+ trap->cause = 0; \
+ asm volatile( \
+ "add %[tinfo], %[taddr], zero\n" \
+ "csrrw %[mtvec], " STR(CSR_MTVEC) ", %[mtvec]\n" \
+ "csrrs %[mstatus], " STR(CSR_MSTATUS) ", %[mprv]\n" \
+ ".option push\n" \
+ ".option norvc\n" \
+ #insn " %[ret], %[val], %[addr]\n" \
+ ".option pop\n" \
+ "csrw " STR(CSR_MSTATUS) ", %[mstatus]\n" \
+ "csrw " STR(CSR_MTVEC) ", %[mtvec]" \
+ : [mstatus] "+&r"(mstatus), [mtvec] "+&r"(mtvec), \
+ [tinfo] "+&r"(tinfo), [ret] "=&r"(ret) \
+ : [addr] "m"(*addr), [mprv] "r"(MSTATUS_MPRV), \
+ [val] "r"(val), [taddr] "r"((ulong)trap) \
+ : "a4", "memory"); \
+ return ret; \
+ }
+
+DEFINE_UNPRIVILEGED_LR_FUNCTION(s32, , lr.w);
+DEFINE_UNPRIVILEGED_LR_FUNCTION(s32, _aq, lr.w.aq);
+DEFINE_UNPRIVILEGED_LR_FUNCTION(s32, _rl, lr.w.rl);
+DEFINE_UNPRIVILEGED_LR_FUNCTION(s32, _aqrl, lr.w.aqrl);
+DEFINE_UNPRIVILEGED_SC_FUNCTION(s32, , sc.w);
+DEFINE_UNPRIVILEGED_SC_FUNCTION(s32, _aq, sc.w.aq);
+DEFINE_UNPRIVILEGED_SC_FUNCTION(s32, _rl, sc.w.rl);
+DEFINE_UNPRIVILEGED_SC_FUNCTION(s32, _aqrl, sc.w.aqrl);
+#if __riscv_xlen == 64
+DEFINE_UNPRIVILEGED_LR_FUNCTION(s64, , lr.d);
+DEFINE_UNPRIVILEGED_LR_FUNCTION(s64, _aq, lr.d.aq);
+DEFINE_UNPRIVILEGED_LR_FUNCTION(s64, _rl, lr.d.rl);
+DEFINE_UNPRIVILEGED_LR_FUNCTION(s64, _aqrl, lr.d.aqrl);
+DEFINE_UNPRIVILEGED_SC_FUNCTION(s64, , sc.d);
+DEFINE_UNPRIVILEGED_SC_FUNCTION(s64, _aq, sc.d.aq);
+DEFINE_UNPRIVILEGED_SC_FUNCTION(s64, _rl, sc.d.rl);
+DEFINE_UNPRIVILEGED_SC_FUNCTION(s64, _aqrl, sc.d.aqrl);
+#endif
+
+#define DEFINE_ATOMIC_FUNCTION(name, type, func) \
+ int sbi_atomic_##name(ulong insn, struct sbi_trap_regs *regs) \
+ { \
+ struct sbi_trap_info uptrap; \
+ ulong addr = GET_RS1(insn, regs); \
+ ulong val = GET_RS2(insn, regs); \
+ ulong rd_val = 0; \
+ ulong fail = 1; \
+ while (fail) { \
+ rd_val = sbi_lr_##type((void *)addr, &uptrap); \
+ if (uptrap.cause) { \
+ return sbi_trap_redirect(regs, &uptrap); \
+ } \
+ fail = sbi_sc_##type((void *)addr, func, &uptrap); \
+ if (uptrap.cause) { \
+ return sbi_trap_redirect(regs, &uptrap); \
+ } \
+ } \
+ SET_RD(insn, regs, rd_val); \
+ regs->mepc += 4; \
+ return 0; \
+ }
+
+DEFINE_ATOMIC_FUNCTION(add_w, s32, rd_val + val);
+DEFINE_ATOMIC_FUNCTION(add_w_aq, s32_aq, rd_val + val);
+DEFINE_ATOMIC_FUNCTION(add_w_rl, s32_rl, rd_val + val);
+DEFINE_ATOMIC_FUNCTION(add_w_aqrl, s32_aqrl, rd_val + val);
+DEFINE_ATOMIC_FUNCTION(and_w, s32, rd_val & val);
+DEFINE_ATOMIC_FUNCTION(and_w_aq, s32_aq, rd_val & val);
+DEFINE_ATOMIC_FUNCTION(and_w_rl, s32_rl, rd_val & val);
+DEFINE_ATOMIC_FUNCTION(and_w_aqrl, s32_aqrl, rd_val & val);
+DEFINE_ATOMIC_FUNCTION(or_w, s32, rd_val | val);
+DEFINE_ATOMIC_FUNCTION(or_w_aq, s32_aq, rd_val | val);
+DEFINE_ATOMIC_FUNCTION(or_w_rl, s32_rl, rd_val | val);
+DEFINE_ATOMIC_FUNCTION(or_w_aqrl, s32_aqrl, rd_val | val);
+DEFINE_ATOMIC_FUNCTION(xor_w, s32, rd_val ^ val);
+DEFINE_ATOMIC_FUNCTION(xor_w_aq, s32_aq, rd_val ^ val);
+DEFINE_ATOMIC_FUNCTION(xor_w_rl, s32_rl, rd_val ^ val);
+DEFINE_ATOMIC_FUNCTION(xor_w_aqrl, s32_aqrl, rd_val ^ val);
+DEFINE_ATOMIC_FUNCTION(swap_w, s32, val);
+DEFINE_ATOMIC_FUNCTION(swap_w_aq, s32_aq, val);
+DEFINE_ATOMIC_FUNCTION(swap_w_rl, s32_rl, val);
+DEFINE_ATOMIC_FUNCTION(swap_w_aqrl, s32_aqrl, val);
+DEFINE_ATOMIC_FUNCTION(max_w, s32, (s32)rd_val > (s32)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(max_w_aq, s32_aq, (s32)rd_val > (s32)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(max_w_rl, s32_rl, (s32)rd_val > (s32)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(max_w_aqrl, s32_aqrl, (s32)rd_val > (s32)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(maxu_w, s32, (u32)rd_val > (u32)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(maxu_w_aq, s32_aq, (u32)rd_val > (u32)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(maxu_w_rl, s32_rl, (u32)rd_val > (u32)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(maxu_w_aqrl, s32_aqrl, (u32)rd_val > (u32)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(min_w, s32, (s32)rd_val < (s32)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(min_w_aq, s32_aq, (s32)rd_val < (s32)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(min_w_rl, s32_rl, (s32)rd_val < (s32)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(min_w_aqrl, s32_aqrl, (s32)rd_val < (s32)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(minu_w, s32, (u32)rd_val < (u32)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(minu_w_aq, s32_aq, (u32)rd_val < (u32)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(minu_w_rl, s32_rl, (u32)rd_val < (u32)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(minu_w_aqrl, s32_aqrl, (u32)rd_val < (u32)val ? rd_val : val);
+
+#if __riscv_xlen == 64
+DEFINE_ATOMIC_FUNCTION(add_d, s64, rd_val + val);
+DEFINE_ATOMIC_FUNCTION(add_d_aq, s64_aq, rd_val + val);
+DEFINE_ATOMIC_FUNCTION(add_d_rl, s64_rl, rd_val + val);
+DEFINE_ATOMIC_FUNCTION(add_d_aqrl, s64_aqrl, rd_val + val);
+DEFINE_ATOMIC_FUNCTION(and_d, s64, rd_val & val);
+DEFINE_ATOMIC_FUNCTION(and_d_aq, s64_aq, rd_val & val);
+DEFINE_ATOMIC_FUNCTION(and_d_rl, s64_rl, rd_val & val);
+DEFINE_ATOMIC_FUNCTION(and_d_aqrl, s64_aqrl, rd_val & val);
+DEFINE_ATOMIC_FUNCTION(or_d, s64, rd_val | val);
+DEFINE_ATOMIC_FUNCTION(or_d_aq, s64_aq, rd_val | val);
+DEFINE_ATOMIC_FUNCTION(or_d_rl, s64_rl, rd_val | val);
+DEFINE_ATOMIC_FUNCTION(or_d_aqrl, s64_aqrl, rd_val | val);
+DEFINE_ATOMIC_FUNCTION(xor_d, s64, rd_val ^ val);
+DEFINE_ATOMIC_FUNCTION(xor_d_aq, s64_aq, rd_val ^ val);
+DEFINE_ATOMIC_FUNCTION(xor_d_rl, s64_rl, rd_val ^ val);
+DEFINE_ATOMIC_FUNCTION(xor_d_aqrl, s64_aqrl, rd_val ^ val);
+DEFINE_ATOMIC_FUNCTION(swap_d, s64, val);
+DEFINE_ATOMIC_FUNCTION(swap_d_aq, s64_aq, val);
+DEFINE_ATOMIC_FUNCTION(swap_d_rl, s64_rl, val);
+DEFINE_ATOMIC_FUNCTION(swap_d_aqrl, s64_aqrl, val);
+DEFINE_ATOMIC_FUNCTION(max_d, s64, (s64)rd_val > (s64)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(max_d_aq, s64_aq, (s64)rd_val > (s64)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(max_d_rl, s64_rl, (s64)rd_val > (s64)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(max_d_aqrl, s64_aqrl, (s64)rd_val > (s64)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(maxu_d, s64, (u64)rd_val > (u64)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(maxu_d_aq, s64_aq, (u64)rd_val > (u64)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(maxu_d_rl, s64_rl, (u64)rd_val > (u64)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(maxu_d_aqrl, s64_aqrl, (u64)rd_val > (u64)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(min_d, s64, (s64)rd_val < (s64)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(min_d_aq, s64_aq, (s64)rd_val < (s64)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(min_d_rl, s64_rl, (s64)rd_val < (s64)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(min_d_aqrl, s64_aqrl, (s64)rd_val < (s64)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(minu_d, s64, (u64)rd_val < (u64)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(minu_d_aq, s64_aq, (u64)rd_val < (u64)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(minu_d_rl, s64_rl, (u64)rd_val < (u64)val ? rd_val : val);
+DEFINE_ATOMIC_FUNCTION(minu_d_aqrl, s64_aqrl, (u64)rd_val < (u64)val ? rd_val : val);
+#endif
diff --git a/lib/sbi/sbi_illegal_insn.c b/lib/sbi/sbi_illegal_insn.c
index 784bc4c..4a01f59 100644
--- a/lib/sbi/sbi_illegal_insn.c
+++ b/lib/sbi/sbi_illegal_insn.c
@@ -10,6 +10,7 @@
#include <sbi/riscv_asm.h>
#include <sbi/riscv_barrier.h>
#include <sbi/riscv_encoding.h>
+#include <sbi/sbi_atomic.h>
#include <sbi/sbi_bitops.h>
#include <sbi/sbi_emulate_csr.h>
#include <sbi/sbi_error.h>
@@ -19,6 +20,13 @@
#include <sbi/sbi_unpriv.h>
#include <sbi/sbi_console.h>
+#define OPCODE_MASK 0x0000007f
+#define AMO_OPCODE 0x0000002f
+#define WD_MASK 0x00007000
+#define WD_SHIFT 12
+#define AQRL_MASK 0x06000000
+#define AQRL_SHIFT 25
+
typedef int (*illegal_insn_func)(ulong insn, struct sbi_trap_regs *regs);
static int truly_illegal_insn(ulong insn, struct sbi_trap_regs *regs)
@@ -146,6 +154,487 @@ static const illegal_insn_func illegal_insn_table[32] = {
truly_illegal_insn /* 31 */
};
+static int other_illegal_insn(ulong insn, struct sbi_trap_regs *regs)
+{
+ return illegal_insn_table[(insn & 0x7c) >> 2](insn, regs);
+}
+
+static const illegal_insn_func amoadd_table[32] = {
+ other_illegal_insn, /* 0 */
+ other_illegal_insn, /* 1 */
+ other_illegal_insn, /* 2 */
+ other_illegal_insn, /* 3 */
+ other_illegal_insn, /* 4 */
+ other_illegal_insn, /* 5 */
+ other_illegal_insn, /* 6 */
+ other_illegal_insn, /* 7 */
+ sbi_atomic_add_w, /* 8 */
+ sbi_atomic_add_w_rl, /* 9 */
+ sbi_atomic_add_w_aq, /* 10 */
+ sbi_atomic_add_w_aqrl, /* 11 */
+#if __riscv_xlen == 64
+ sbi_atomic_add_d, /* 12 */
+ sbi_atomic_add_d_rl, /* 13 */
+ sbi_atomic_add_d_aq, /* 14 */
+ sbi_atomic_add_d_aqrl, /* 15 */
+#else
+ other_illegal_insn, /* 12 */
+ other_illegal_insn, /* 13 */
+ other_illegal_insn, /* 14 */
+ other_illegal_insn, /* 15 */
+#endif
+ other_illegal_insn, /* 16 */
+ other_illegal_insn, /* 17 */
+ other_illegal_insn, /* 18 */
+ other_illegal_insn, /* 19 */
+ other_illegal_insn, /* 20 */
+ other_illegal_insn, /* 21 */
+ other_illegal_insn, /* 22 */
+ other_illegal_insn, /* 23 */
+ other_illegal_insn, /* 24 */
+ other_illegal_insn, /* 25 */
+ other_illegal_insn, /* 26 */
+ other_illegal_insn, /* 27 */
+ other_illegal_insn, /* 28 */
+ other_illegal_insn, /* 29 */
+ other_illegal_insn, /* 30 */
+ other_illegal_insn, /* 31 */
+};
+
+static const illegal_insn_func amoswap_table[32] = {
+ other_illegal_insn, /* 0 */
+ other_illegal_insn, /* 1 */
+ other_illegal_insn, /* 2 */
+ other_illegal_insn, /* 3 */
+ other_illegal_insn, /* 4 */
+ other_illegal_insn, /* 5 */
+ other_illegal_insn, /* 6 */
+ other_illegal_insn, /* 7 */
+ sbi_atomic_swap_w, /* 8 */
+ sbi_atomic_swap_w_rl, /* 9 */
+ sbi_atomic_swap_w_aq, /* 10 */
+ sbi_atomic_swap_w_aqrl, /* 11 */
+#if __riscv_xlen == 64
+ sbi_atomic_swap_d, /* 12 */
+ sbi_atomic_swap_d_rl, /* 13 */
+ sbi_atomic_swap_d_aq, /* 14 */
+ sbi_atomic_swap_d_aqrl, /* 15 */
+#else
+ other_illegal_insn, /* 12 */
+ other_illegal_insn, /* 13 */
+ other_illegal_insn, /* 14 */
+ other_illegal_insn, /* 15 */
+#endif
+ other_illegal_insn, /* 16 */
+ other_illegal_insn, /* 17 */
+ other_illegal_insn, /* 18 */
+ other_illegal_insn, /* 19 */
+ other_illegal_insn, /* 20 */
+ other_illegal_insn, /* 21 */
+ other_illegal_insn, /* 22 */
+ other_illegal_insn, /* 23 */
+ other_illegal_insn, /* 24 */
+ other_illegal_insn, /* 25 */
+ other_illegal_insn, /* 26 */
+ other_illegal_insn, /* 27 */
+ other_illegal_insn, /* 28 */
+ other_illegal_insn, /* 29 */
+ other_illegal_insn, /* 30 */
+ other_illegal_insn, /* 31 */
+};
+
+static const illegal_insn_func amoxor_table[32] = {
+ other_illegal_insn, /* 0 */
+ other_illegal_insn, /* 1 */
+ other_illegal_insn, /* 2 */
+ other_illegal_insn, /* 3 */
+ other_illegal_insn, /* 4 */
+ other_illegal_insn, /* 5 */
+ other_illegal_insn, /* 6 */
+ other_illegal_insn, /* 7 */
+ sbi_atomic_xor_w, /* 8 */
+ sbi_atomic_xor_w_rl, /* 9 */
+ sbi_atomic_xor_w_aq, /* 10 */
+ sbi_atomic_xor_w_aqrl, /* 11 */
+#if __riscv_xlen == 64
+ sbi_atomic_xor_d, /* 12 */
+ sbi_atomic_xor_d_rl, /* 13 */
+ sbi_atomic_xor_d_aq, /* 14 */
+ sbi_atomic_xor_d_aqrl, /* 15 */
+#else
+ other_illegal_insn, /* 12 */
+ other_illegal_insn, /* 13 */
+ other_illegal_insn, /* 14 */
+ other_illegal_insn, /* 15 */
+#endif
+ other_illegal_insn, /* 16 */
+ other_illegal_insn, /* 17 */
+ other_illegal_insn, /* 18 */
+ other_illegal_insn, /* 19 */
+ other_illegal_insn, /* 20 */
+ other_illegal_insn, /* 21 */
+ other_illegal_insn, /* 22 */
+ other_illegal_insn, /* 23 */
+ other_illegal_insn, /* 24 */
+ other_illegal_insn, /* 25 */
+ other_illegal_insn, /* 26 */
+ other_illegal_insn, /* 27 */
+ other_illegal_insn, /* 28 */
+ other_illegal_insn, /* 29 */
+ other_illegal_insn, /* 30 */
+ other_illegal_insn, /* 31 */
+};
+
+static const illegal_insn_func amoor_table[32] = {
+ other_illegal_insn, /* 0 */
+ other_illegal_insn, /* 1 */
+ other_illegal_insn, /* 2 */
+ other_illegal_insn, /* 3 */
+ other_illegal_insn, /* 4 */
+ other_illegal_insn, /* 5 */
+ other_illegal_insn, /* 6 */
+ other_illegal_insn, /* 7 */
+ sbi_atomic_or_w, /* 8 */
+ sbi_atomic_or_w_rl, /* 9 */
+ sbi_atomic_or_w_aq, /* 10 */
+ sbi_atomic_or_w_aqrl, /* 11 */
+#if __riscv_xlen == 64
+ sbi_atomic_or_d, /* 12 */
+ sbi_atomic_or_d_rl, /* 13 */
+ sbi_atomic_or_d_aq, /* 14 */
+ sbi_atomic_or_d_aqrl, /* 15 */
+#else
+ other_illegal_insn, /* 12 */
+ other_illegal_insn, /* 13 */
+ other_illegal_insn, /* 14 */
+ other_illegal_insn, /* 15 */
+#endif
+ other_illegal_insn, /* 16 */
+ other_illegal_insn, /* 17 */
+ other_illegal_insn, /* 18 */
+ other_illegal_insn, /* 19 */
+ other_illegal_insn, /* 20 */
+ other_illegal_insn, /* 21 */
+ other_illegal_insn, /* 22 */
+ other_illegal_insn, /* 23 */
+ other_illegal_insn, /* 24 */
+ other_illegal_insn, /* 25 */
+ other_illegal_insn, /* 26 */
+ other_illegal_insn, /* 27 */
+ other_illegal_insn, /* 28 */
+ other_illegal_insn, /* 29 */
+ other_illegal_insn, /* 30 */
+ other_illegal_insn, /* 31 */
+};
+
+static const illegal_insn_func amoand_table[32] = {
+ other_illegal_insn, /* 0 */
+ other_illegal_insn, /* 1 */
+ other_illegal_insn, /* 2 */
+ other_illegal_insn, /* 3 */
+ other_illegal_insn, /* 4 */
+ other_illegal_insn, /* 5 */
+ other_illegal_insn, /* 6 */
+ other_illegal_insn, /* 7 */
+ sbi_atomic_and_w, /* 8 */
+ sbi_atomic_and_w_rl, /* 9 */
+ sbi_atomic_and_w_aq, /* 10 */
+ sbi_atomic_and_w_aqrl, /* 11 */
+#if __riscv_xlen == 64
+ sbi_atomic_and_d, /* 12 */
+ sbi_atomic_and_d_rl, /* 13 */
+ sbi_atomic_and_d_aq, /* 14 */
+ sbi_atomic_and_d_aqrl, /* 15 */
+#else
+ other_illegal_insn, /* 12 */
+ other_illegal_insn, /* 13 */
+ other_illegal_insn, /* 14 */
+ other_illegal_insn, /* 15 */
+#endif
+ other_illegal_insn, /* 16 */
+ other_illegal_insn, /* 17 */
+ other_illegal_insn, /* 18 */
+ other_illegal_insn, /* 19 */
+ other_illegal_insn, /* 20 */
+ other_illegal_insn, /* 21 */
+ other_illegal_insn, /* 22 */
+ other_illegal_insn, /* 23 */
+ other_illegal_insn, /* 24 */
+ other_illegal_insn, /* 25 */
+ other_illegal_insn, /* 26 */
+ other_illegal_insn, /* 27 */
+ other_illegal_insn, /* 28 */
+ other_illegal_insn, /* 29 */
+ other_illegal_insn, /* 30 */
+ other_illegal_insn, /* 31 */
+};
+
+static const illegal_insn_func amomin_table[32] = {
+ other_illegal_insn, /* 0 */
+ other_illegal_insn, /* 1 */
+ other_illegal_insn, /* 2 */
+ other_illegal_insn, /* 3 */
+ other_illegal_insn, /* 4 */
+ other_illegal_insn, /* 5 */
+ other_illegal_insn, /* 6 */
+ other_illegal_insn, /* 7 */
+ sbi_atomic_min_w, /* 8 */
+ sbi_atomic_min_w_rl, /* 9 */
+ sbi_atomic_min_w_aq, /* 10 */
+ sbi_atomic_min_w_aqrl, /* 11 */
+#if __riscv_xlen == 64
+ sbi_atomic_min_d, /* 12 */
+ sbi_atomic_min_d_rl, /* 13 */
+ sbi_atomic_min_d_aq, /* 14 */
+ sbi_atomic_min_d_aqrl, /* 15 */
+#else
+ other_illegal_insn, /* 12 */
+ other_illegal_insn, /* 13 */
+ other_illegal_insn, /* 14 */
+ other_illegal_insn, /* 15 */
+#endif
+ other_illegal_insn, /* 16 */
+ other_illegal_insn, /* 17 */
+ other_illegal_insn, /* 18 */
+ other_illegal_insn, /* 19 */
+ other_illegal_insn, /* 20 */
+ other_illegal_insn, /* 21 */
+ other_illegal_insn, /* 22 */
+ other_illegal_insn, /* 23 */
+ other_illegal_insn, /* 24 */
+ other_illegal_insn, /* 25 */
+ other_illegal_insn, /* 26 */
+ other_illegal_insn, /* 27 */
+ other_illegal_insn, /* 28 */
+ other_illegal_insn, /* 29 */
+ other_illegal_insn, /* 30 */
+ other_illegal_insn, /* 31 */
+};
+
+static const illegal_insn_func amomax_table[32] = {
+ other_illegal_insn, /* 0 */
+ other_illegal_insn, /* 1 */
+ other_illegal_insn, /* 2 */
+ other_illegal_insn, /* 3 */
+ other_illegal_insn, /* 4 */
+ other_illegal_insn, /* 5 */
+ other_illegal_insn, /* 6 */
+ other_illegal_insn, /* 7 */
+ sbi_atomic_max_w, /* 8 */
+ sbi_atomic_max_w_rl, /* 9 */
+ sbi_atomic_max_w_aq, /* 10 */
+ sbi_atomic_max_w_aqrl, /* 11 */
+#if __riscv_xlen == 64
+ sbi_atomic_max_d, /* 12 */
+ sbi_atomic_max_d_rl, /* 13 */
+ sbi_atomic_max_d_aq, /* 14 */
+ sbi_atomic_max_d_aqrl, /* 15 */
+#else
+ other_illegal_insn, /* 12 */
+ other_illegal_insn, /* 13 */
+ other_illegal_insn, /* 14 */
+ other_illegal_insn, /* 15 */
+#endif
+ other_illegal_insn, /* 16 */
+ other_illegal_insn, /* 17 */
+ other_illegal_insn, /* 18 */
+ other_illegal_insn, /* 19 */
+ other_illegal_insn, /* 20 */
+ other_illegal_insn, /* 21 */
+ other_illegal_insn, /* 22 */
+ other_illegal_insn, /* 23 */
+ other_illegal_insn, /* 24 */
+ other_illegal_insn, /* 25 */
+ other_illegal_insn, /* 26 */
+ other_illegal_insn, /* 27 */
+ other_illegal_insn, /* 28 */
+ other_illegal_insn, /* 29 */
+ other_illegal_insn, /* 30 */
+ other_illegal_insn, /* 31 */
+};
+
+static const illegal_insn_func amominu_table[32] = {
+ other_illegal_insn, /* 0 */
+ other_illegal_insn, /* 1 */
+ other_illegal_insn, /* 2 */
+ other_illegal_insn, /* 3 */
+ other_illegal_insn, /* 4 */
+ other_illegal_insn, /* 5 */
+ other_illegal_insn, /* 6 */
+ other_illegal_insn, /* 7 */
+ sbi_atomic_minu_w, /* 8 */
+ sbi_atomic_minu_w_rl, /* 9 */
+ sbi_atomic_minu_w_aq, /* 10 */
+ sbi_atomic_minu_w_aqrl, /* 11 */
+#if __riscv_xlen == 64
+ sbi_atomic_minu_d, /* 12 */
+ sbi_atomic_minu_d_rl, /* 13 */
+ sbi_atomic_minu_d_aq, /* 14 */
+ sbi_atomic_minu_d_aqrl, /* 15 */
+#else
+ other_illegal_insn, /* 12 */
+ other_illegal_insn, /* 13 */
+ other_illegal_insn, /* 14 */
+ other_illegal_insn, /* 15 */
+#endif
+ other_illegal_insn, /* 16 */
+ other_illegal_insn, /* 17 */
+ other_illegal_insn, /* 18 */
+ other_illegal_insn, /* 19 */
+ other_illegal_insn, /* 20 */
+ other_illegal_insn, /* 21 */
+ other_illegal_insn, /* 22 */
+ other_illegal_insn, /* 23 */
+ other_illegal_insn, /* 24 */
+ other_illegal_insn, /* 25 */
+ other_illegal_insn, /* 26 */
+ other_illegal_insn, /* 27 */
+ other_illegal_insn, /* 28 */
+ other_illegal_insn, /* 29 */
+ other_illegal_insn, /* 30 */
+ other_illegal_insn, /* 31 */
+};
+
+static const illegal_insn_func amomaxu_table[32] = {
+ other_illegal_insn, /* 0 */
+ other_illegal_insn, /* 1 */
+ other_illegal_insn, /* 2 */
+ other_illegal_insn, /* 3 */
+ other_illegal_insn, /* 4 */
+ other_illegal_insn, /* 5 */
+ other_illegal_insn, /* 6 */
+ other_illegal_insn, /* 7 */
+ sbi_atomic_maxu_w, /* 8 */
+ sbi_atomic_maxu_w_rl, /* 9 */
+ sbi_atomic_maxu_w_aq, /* 10 */
+ sbi_atomic_maxu_w_aqrl, /* 11 */
+#if __riscv_xlen == 64
+ sbi_atomic_maxu_d, /* 12 */
+ sbi_atomic_maxu_d_rl, /* 13 */
+ sbi_atomic_maxu_d_aq, /* 14 */
+ sbi_atomic_maxu_d_aqrl, /* 15 */
+#else
+ other_illegal_insn, /* 12 */
+ other_illegal_insn, /* 13 */
+ other_illegal_insn, /* 14 */
+ other_illegal_insn, /* 15 */
+#endif
+ other_illegal_insn, /* 16 */
+ other_illegal_insn, /* 17 */
+ other_illegal_insn, /* 18 */
+ other_illegal_insn, /* 19 */
+ other_illegal_insn, /* 20 */
+ other_illegal_insn, /* 21 */
+ other_illegal_insn, /* 22 */
+ other_illegal_insn, /* 23 */
+ other_illegal_insn, /* 24 */
+ other_illegal_insn, /* 25 */
+ other_illegal_insn, /* 26 */
+ other_illegal_insn, /* 27 */
+ other_illegal_insn, /* 28 */
+ other_illegal_insn, /* 29 */
+ other_illegal_insn, /* 30 */
+ other_illegal_insn, /* 31 */
+};
+
+static int amoadd_insn(ulong insn, struct sbi_trap_regs *regs)
+{
+ int wd = ((insn & WD_MASK) >> WD_SHIFT) << 2;
+ int aqrl = (insn & AQRL_MASK) >> AQRL_SHIFT;
+ return amoadd_table[wd + aqrl](insn, regs);
+}
+
+static int amoswap_insn(ulong insn, struct sbi_trap_regs *regs)
+{
+ int wd = ((insn & WD_MASK) >> WD_SHIFT) << 2;
+ int aqrl = (insn & AQRL_MASK) >> AQRL_SHIFT;
+ return amoswap_table[wd + aqrl](insn, regs);
+}
+
+static int amoxor_insn(ulong insn, struct sbi_trap_regs *regs)
+{
+ int wd = ((insn & WD_MASK) >> WD_SHIFT) << 2;
+ int aqrl = (insn & AQRL_MASK) >> AQRL_SHIFT;
+ return amoxor_table[wd + aqrl](insn, regs);
+}
+
+static int amoor_insn(ulong insn, struct sbi_trap_regs *regs)
+{
+ int wd = ((insn & WD_MASK) >> WD_SHIFT) << 2;
+ int aqrl = (insn & AQRL_MASK) >> AQRL_SHIFT;
+ return amoor_table[wd + aqrl](insn, regs);
+}
+
+static int amoand_insn(ulong insn, struct sbi_trap_regs *regs)
+{
+ int wd = ((insn & WD_MASK) >> WD_SHIFT) << 2;
+ int aqrl = (insn & AQRL_MASK) >> AQRL_SHIFT;
+ return amoand_table[wd + aqrl](insn, regs);
+}
+
+static int amomin_insn(ulong insn, struct sbi_trap_regs *regs)
+{
+ int wd = ((insn & WD_MASK) >> WD_SHIFT) << 2;
+ int aqrl = (insn & AQRL_MASK) >> AQRL_SHIFT;
+ return amomin_table[wd + aqrl](insn, regs);
+}
+
+static int amomax_insn(ulong insn, struct sbi_trap_regs *regs)
+{
+ int wd = ((insn & WD_MASK) >> WD_SHIFT) << 2;
+ int aqrl = (insn & AQRL_MASK) >> AQRL_SHIFT;
+ return amomax_table[wd + aqrl](insn, regs);
+}
+
+static int amominu_insn(ulong insn, struct sbi_trap_regs *regs)
+{
+ int wd = ((insn & WD_MASK) >> WD_SHIFT) << 2;
+ int aqrl = (insn & AQRL_MASK) >> AQRL_SHIFT;
+ return amominu_table[wd + aqrl](insn, regs);
+}
+
+static int amomaxu_insn(ulong insn, struct sbi_trap_regs *regs)
+{
+ int wd = ((insn & WD_MASK) >> WD_SHIFT) << 2;
+ int aqrl = (insn & AQRL_MASK) >> AQRL_SHIFT;
+ return amomaxu_table[wd + aqrl](insn, regs);
+}
+
+static const illegal_insn_func amo_insn_table[32] = {
+ amoadd_insn, /* 0 */
+ amoswap_insn, /* 1 */
+ other_illegal_insn, /* 2 */
+ other_illegal_insn, /* 3 */
+ amoxor_insn, /* 4 */
+ other_illegal_insn, /* 5 */
+ other_illegal_insn, /* 6 */
+ other_illegal_insn, /* 7 */
+ amoor_insn, /* 8 */
+ other_illegal_insn, /* 9 */
+ other_illegal_insn, /* 10 */
+ other_illegal_insn, /* 11 */
+ amoand_insn, /* 12 */
+ other_illegal_insn, /* 13 */
+ other_illegal_insn, /* 14 */
+ other_illegal_insn, /* 15 */
+ amomin_insn, /* 16 */
+ other_illegal_insn, /* 17 */
+ other_illegal_insn, /* 18 */
+ other_illegal_insn, /* 19 */
+ amomax_insn, /* 20 */
+ other_illegal_insn, /* 21 */
+ other_illegal_insn, /* 22 */
+ other_illegal_insn, /* 23 */
+ amominu_insn, /* 24 */
+ other_illegal_insn, /* 25 */
+ other_illegal_insn, /* 26 */
+ other_illegal_insn, /* 27 */
+ amomaxu_insn, /* 28 */
+ other_illegal_insn, /* 29 */
+ other_illegal_insn, /* 30 */
+ other_illegal_insn /* 31 */
+};
+
int sbi_illegal_insn_handler(struct sbi_trap_context *tcntx)
{
struct sbi_trap_regs *regs = &tcntx->regs;
@@ -172,5 +661,8 @@ int sbi_illegal_insn_handler(struct sbi_trap_context *tcntx)
return truly_illegal_insn(insn, regs);
}
+ if ((insn & OPCODE_MASK) == AMO_OPCODE)
+ return amo_insn_table[(insn >> 27) & 0x1f](insn, regs);
+
return illegal_insn_table[(insn & 0x7c) >> 2](insn, regs);
}
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 70+ messages in thread* Re: [PATCH v4 5/8] lib: Emulate amo instructions
2025-04-29 23:29 ` [PATCH v4 5/8] lib: Emulate amo instructions Chao-ying Fu
@ 2025-05-19 12:14 ` Anup Patel
0 siblings, 0 replies; 70+ messages in thread
From: Anup Patel @ 2025-05-19 12:14 UTC (permalink / raw)
To: Chao-ying Fu; +Cc: opensbi, Chao-ying Fu
On Wed, Apr 30, 2025 at 5:37 AM Chao-ying Fu <icebergfu@gmail.com> wrote:
>
> Match amo instruction opcode to emulate from illegal instruction
> exceptions.
>
> Signed-off-by: Chao-ying Fu <cfu@mips.com>
There is still quite a bit of refactoring required in this patch so
to save time, I will send-out v5 of this patch and merge it.
Regards,
Anup
> ---
> include/sbi/sbi_atomic.h | 90 +++++++
> lib/sbi/objects.mk | 1 +
> lib/sbi/sbi_atomic.c | 182 ++++++++++++++
> lib/sbi/sbi_illegal_insn.c | 492 +++++++++++++++++++++++++++++++++++++
> 4 files changed, 765 insertions(+)
> create mode 100644 include/sbi/sbi_atomic.h
> create mode 100644 lib/sbi/sbi_atomic.c
>
> diff --git a/include/sbi/sbi_atomic.h b/include/sbi/sbi_atomic.h
> new file mode 100644
> index 0000000..561da89
> --- /dev/null
> +++ b/include/sbi/sbi_atomic.h
> @@ -0,0 +1,90 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Copyright (c) 2025 MIPS
> + *
> + */
> +
> +#ifndef __SBI_ATOMIC_H__
> +#define __SBI_ATOMIC_H__
> +
> +#include <sbi/sbi_types.h>
> +
> +struct sbi_trap_regs;
> +
> +int sbi_atomic_add_w(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_add_d(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_and_w(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_and_d(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_or_w(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_or_d(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_xor_w(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_xor_d(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_max_w(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_max_d(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_min_w(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_min_d(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_maxu_w(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_maxu_d(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_minu_w(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_minu_d(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_swap_w(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_swap_d(ulong insn, struct sbi_trap_regs *regs);
> +
> +int sbi_atomic_add_w_aq(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_add_d_aq(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_and_w_aq(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_and_d_aq(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_or_w_aq(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_or_d_aq(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_xor_w_aq(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_xor_d_aq(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_max_w_aq(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_max_d_aq(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_min_w_aq(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_min_d_aq(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_maxu_w_aq(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_maxu_d_aq(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_minu_w_aq(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_minu_d_aq(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_swap_w_aq(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_swap_d_aq(ulong insn, struct sbi_trap_regs *regs);
> +
> +int sbi_atomic_add_w_rl(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_add_d_rl(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_and_w_rl(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_and_d_rl(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_or_w_rl(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_or_d_rl(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_xor_w_rl(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_xor_d_rl(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_max_w_rl(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_max_d_rl(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_min_w_rl(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_min_d_rl(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_maxu_w_rl(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_maxu_d_rl(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_minu_w_rl(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_minu_d_rl(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_swap_w_rl(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_swap_d_rl(ulong insn, struct sbi_trap_regs *regs);
> +
> +int sbi_atomic_add_w_aqrl(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_add_d_aqrl(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_and_w_aqrl(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_and_d_aqrl(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_or_w_aqrl(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_or_d_aqrl(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_xor_w_aqrl(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_xor_d_aqrl(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_max_w_aqrl(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_max_d_aqrl(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_min_w_aqrl(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_min_d_aqrl(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_maxu_w_aqrl(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_maxu_d_aqrl(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_minu_w_aqrl(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_minu_d_aqrl(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_swap_w_aqrl(ulong insn, struct sbi_trap_regs *regs);
> +int sbi_atomic_swap_d_aqrl(ulong insn, struct sbi_trap_regs *regs);
> +#endif
> diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
> index 9cb2842..af7a846 100644
> --- a/lib/sbi/objects.mk
> +++ b/lib/sbi/objects.mk
> @@ -99,3 +99,4 @@ libsbi-objs-y += sbi_trap_v_ldst.o
> libsbi-objs-y += sbi_unpriv.o
> libsbi-objs-y += sbi_expected_trap.o
> libsbi-objs-y += sbi_cppc.o
> +libsbi-objs-y += sbi_atomic.o
> diff --git a/lib/sbi/sbi_atomic.c b/lib/sbi/sbi_atomic.c
> new file mode 100644
> index 0000000..afd28d2
> --- /dev/null
> +++ b/lib/sbi/sbi_atomic.c
> @@ -0,0 +1,182 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Copyright (c) 2025 MIPS
> + *
> + */
> +
> +#include <sbi/riscv_asm.h>
> +#include <sbi/sbi_trap.h>
> +#include <sbi/sbi_hart.h>
> +
> +#define DEFINE_UNPRIVILEGED_LR_FUNCTION(type, aqrl, insn) \
> + type sbi_lr_##type##aqrl(const type *addr, \
> + struct sbi_trap_info *trap) \
> + { \
> + register ulong tinfo asm("a3"); \
> + register ulong mstatus = 0; \
> + register ulong mtvec = sbi_hart_expected_trap_addr(); \
> + type ret = 0; \
> + trap->cause = 0; \
> + asm volatile( \
> + "add %[tinfo], %[taddr], zero\n" \
> + "csrrw %[mtvec], " STR(CSR_MTVEC) ", %[mtvec]\n" \
> + "csrrs %[mstatus], " STR(CSR_MSTATUS) ", %[mprv]\n" \
> + ".option push\n" \
> + ".option norvc\n" \
> + #insn " %[ret], %[addr]\n" \
> + ".option pop\n" \
> + "csrw " STR(CSR_MSTATUS) ", %[mstatus]\n" \
> + "csrw " STR(CSR_MTVEC) ", %[mtvec]" \
> + : [mstatus] "+&r"(mstatus), [mtvec] "+&r"(mtvec), \
> + [tinfo] "+&r"(tinfo), [ret] "=&r"(ret) \
> + : [addr] "m"(*addr), [mprv] "r"(MSTATUS_MPRV), \
> + [taddr] "r"((ulong)trap) \
> + : "a4", "memory"); \
> + return ret; \
> + }
> +
> +#define DEFINE_UNPRIVILEGED_SC_FUNCTION(type, aqrl, insn) \
> + type sbi_sc_##type##aqrl(type *addr, type val, \
> + struct sbi_trap_info *trap) \
> + { \
> + register ulong tinfo asm("a3"); \
> + register ulong mstatus = 0; \
> + register ulong mtvec = sbi_hart_expected_trap_addr(); \
> + type ret = 0; \
> + trap->cause = 0; \
> + asm volatile( \
> + "add %[tinfo], %[taddr], zero\n" \
> + "csrrw %[mtvec], " STR(CSR_MTVEC) ", %[mtvec]\n" \
> + "csrrs %[mstatus], " STR(CSR_MSTATUS) ", %[mprv]\n" \
> + ".option push\n" \
> + ".option norvc\n" \
> + #insn " %[ret], %[val], %[addr]\n" \
> + ".option pop\n" \
> + "csrw " STR(CSR_MSTATUS) ", %[mstatus]\n" \
> + "csrw " STR(CSR_MTVEC) ", %[mtvec]" \
> + : [mstatus] "+&r"(mstatus), [mtvec] "+&r"(mtvec), \
> + [tinfo] "+&r"(tinfo), [ret] "=&r"(ret) \
> + : [addr] "m"(*addr), [mprv] "r"(MSTATUS_MPRV), \
> + [val] "r"(val), [taddr] "r"((ulong)trap) \
> + : "a4", "memory"); \
> + return ret; \
> + }
> +
> +DEFINE_UNPRIVILEGED_LR_FUNCTION(s32, , lr.w);
> +DEFINE_UNPRIVILEGED_LR_FUNCTION(s32, _aq, lr.w.aq);
> +DEFINE_UNPRIVILEGED_LR_FUNCTION(s32, _rl, lr.w.rl);
> +DEFINE_UNPRIVILEGED_LR_FUNCTION(s32, _aqrl, lr.w.aqrl);
> +DEFINE_UNPRIVILEGED_SC_FUNCTION(s32, , sc.w);
> +DEFINE_UNPRIVILEGED_SC_FUNCTION(s32, _aq, sc.w.aq);
> +DEFINE_UNPRIVILEGED_SC_FUNCTION(s32, _rl, sc.w.rl);
> +DEFINE_UNPRIVILEGED_SC_FUNCTION(s32, _aqrl, sc.w.aqrl);
> +#if __riscv_xlen == 64
> +DEFINE_UNPRIVILEGED_LR_FUNCTION(s64, , lr.d);
> +DEFINE_UNPRIVILEGED_LR_FUNCTION(s64, _aq, lr.d.aq);
> +DEFINE_UNPRIVILEGED_LR_FUNCTION(s64, _rl, lr.d.rl);
> +DEFINE_UNPRIVILEGED_LR_FUNCTION(s64, _aqrl, lr.d.aqrl);
> +DEFINE_UNPRIVILEGED_SC_FUNCTION(s64, , sc.d);
> +DEFINE_UNPRIVILEGED_SC_FUNCTION(s64, _aq, sc.d.aq);
> +DEFINE_UNPRIVILEGED_SC_FUNCTION(s64, _rl, sc.d.rl);
> +DEFINE_UNPRIVILEGED_SC_FUNCTION(s64, _aqrl, sc.d.aqrl);
> +#endif
> +
> +#define DEFINE_ATOMIC_FUNCTION(name, type, func) \
> + int sbi_atomic_##name(ulong insn, struct sbi_trap_regs *regs) \
> + { \
> + struct sbi_trap_info uptrap; \
> + ulong addr = GET_RS1(insn, regs); \
> + ulong val = GET_RS2(insn, regs); \
> + ulong rd_val = 0; \
> + ulong fail = 1; \
> + while (fail) { \
> + rd_val = sbi_lr_##type((void *)addr, &uptrap); \
> + if (uptrap.cause) { \
> + return sbi_trap_redirect(regs, &uptrap); \
> + } \
> + fail = sbi_sc_##type((void *)addr, func, &uptrap); \
> + if (uptrap.cause) { \
> + return sbi_trap_redirect(regs, &uptrap); \
> + } \
> + } \
> + SET_RD(insn, regs, rd_val); \
> + regs->mepc += 4; \
> + return 0; \
> + }
> +
> +DEFINE_ATOMIC_FUNCTION(add_w, s32, rd_val + val);
> +DEFINE_ATOMIC_FUNCTION(add_w_aq, s32_aq, rd_val + val);
> +DEFINE_ATOMIC_FUNCTION(add_w_rl, s32_rl, rd_val + val);
> +DEFINE_ATOMIC_FUNCTION(add_w_aqrl, s32_aqrl, rd_val + val);
> +DEFINE_ATOMIC_FUNCTION(and_w, s32, rd_val & val);
> +DEFINE_ATOMIC_FUNCTION(and_w_aq, s32_aq, rd_val & val);
> +DEFINE_ATOMIC_FUNCTION(and_w_rl, s32_rl, rd_val & val);
> +DEFINE_ATOMIC_FUNCTION(and_w_aqrl, s32_aqrl, rd_val & val);
> +DEFINE_ATOMIC_FUNCTION(or_w, s32, rd_val | val);
> +DEFINE_ATOMIC_FUNCTION(or_w_aq, s32_aq, rd_val | val);
> +DEFINE_ATOMIC_FUNCTION(or_w_rl, s32_rl, rd_val | val);
> +DEFINE_ATOMIC_FUNCTION(or_w_aqrl, s32_aqrl, rd_val | val);
> +DEFINE_ATOMIC_FUNCTION(xor_w, s32, rd_val ^ val);
> +DEFINE_ATOMIC_FUNCTION(xor_w_aq, s32_aq, rd_val ^ val);
> +DEFINE_ATOMIC_FUNCTION(xor_w_rl, s32_rl, rd_val ^ val);
> +DEFINE_ATOMIC_FUNCTION(xor_w_aqrl, s32_aqrl, rd_val ^ val);
> +DEFINE_ATOMIC_FUNCTION(swap_w, s32, val);
> +DEFINE_ATOMIC_FUNCTION(swap_w_aq, s32_aq, val);
> +DEFINE_ATOMIC_FUNCTION(swap_w_rl, s32_rl, val);
> +DEFINE_ATOMIC_FUNCTION(swap_w_aqrl, s32_aqrl, val);
> +DEFINE_ATOMIC_FUNCTION(max_w, s32, (s32)rd_val > (s32)val ? rd_val : val);
> +DEFINE_ATOMIC_FUNCTION(max_w_aq, s32_aq, (s32)rd_val > (s32)val ? rd_val : val);
> +DEFINE_ATOMIC_FUNCTION(max_w_rl, s32_rl, (s32)rd_val > (s32)val ? rd_val : val);
> +DEFINE_ATOMIC_FUNCTION(max_w_aqrl, s32_aqrl, (s32)rd_val > (s32)val ? rd_val : val);
> +DEFINE_ATOMIC_FUNCTION(maxu_w, s32, (u32)rd_val > (u32)val ? rd_val : val);
> +DEFINE_ATOMIC_FUNCTION(maxu_w_aq, s32_aq, (u32)rd_val > (u32)val ? rd_val : val);
> +DEFINE_ATOMIC_FUNCTION(maxu_w_rl, s32_rl, (u32)rd_val > (u32)val ? rd_val : val);
> +DEFINE_ATOMIC_FUNCTION(maxu_w_aqrl, s32_aqrl, (u32)rd_val > (u32)val ? rd_val : val);
> +DEFINE_ATOMIC_FUNCTION(min_w, s32, (s32)rd_val < (s32)val ? rd_val : val);
> +DEFINE_ATOMIC_FUNCTION(min_w_aq, s32_aq, (s32)rd_val < (s32)val ? rd_val : val);
> +DEFINE_ATOMIC_FUNCTION(min_w_rl, s32_rl, (s32)rd_val < (s32)val ? rd_val : val);
> +DEFINE_ATOMIC_FUNCTION(min_w_aqrl, s32_aqrl, (s32)rd_val < (s32)val ? rd_val : val);
> +DEFINE_ATOMIC_FUNCTION(minu_w, s32, (u32)rd_val < (u32)val ? rd_val : val);
> +DEFINE_ATOMIC_FUNCTION(minu_w_aq, s32_aq, (u32)rd_val < (u32)val ? rd_val : val);
> +DEFINE_ATOMIC_FUNCTION(minu_w_rl, s32_rl, (u32)rd_val < (u32)val ? rd_val : val);
> +DEFINE_ATOMIC_FUNCTION(minu_w_aqrl, s32_aqrl, (u32)rd_val < (u32)val ? rd_val : val);
> +
> +#if __riscv_xlen == 64
> +DEFINE_ATOMIC_FUNCTION(add_d, s64, rd_val + val);
> +DEFINE_ATOMIC_FUNCTION(add_d_aq, s64_aq, rd_val + val);
> +DEFINE_ATOMIC_FUNCTION(add_d_rl, s64_rl, rd_val + val);
> +DEFINE_ATOMIC_FUNCTION(add_d_aqrl, s64_aqrl, rd_val + val);
> +DEFINE_ATOMIC_FUNCTION(and_d, s64, rd_val & val);
> +DEFINE_ATOMIC_FUNCTION(and_d_aq, s64_aq, rd_val & val);
> +DEFINE_ATOMIC_FUNCTION(and_d_rl, s64_rl, rd_val & val);
> +DEFINE_ATOMIC_FUNCTION(and_d_aqrl, s64_aqrl, rd_val & val);
> +DEFINE_ATOMIC_FUNCTION(or_d, s64, rd_val | val);
> +DEFINE_ATOMIC_FUNCTION(or_d_aq, s64_aq, rd_val | val);
> +DEFINE_ATOMIC_FUNCTION(or_d_rl, s64_rl, rd_val | val);
> +DEFINE_ATOMIC_FUNCTION(or_d_aqrl, s64_aqrl, rd_val | val);
> +DEFINE_ATOMIC_FUNCTION(xor_d, s64, rd_val ^ val);
> +DEFINE_ATOMIC_FUNCTION(xor_d_aq, s64_aq, rd_val ^ val);
> +DEFINE_ATOMIC_FUNCTION(xor_d_rl, s64_rl, rd_val ^ val);
> +DEFINE_ATOMIC_FUNCTION(xor_d_aqrl, s64_aqrl, rd_val ^ val);
> +DEFINE_ATOMIC_FUNCTION(swap_d, s64, val);
> +DEFINE_ATOMIC_FUNCTION(swap_d_aq, s64_aq, val);
> +DEFINE_ATOMIC_FUNCTION(swap_d_rl, s64_rl, val);
> +DEFINE_ATOMIC_FUNCTION(swap_d_aqrl, s64_aqrl, val);
> +DEFINE_ATOMIC_FUNCTION(max_d, s64, (s64)rd_val > (s64)val ? rd_val : val);
> +DEFINE_ATOMIC_FUNCTION(max_d_aq, s64_aq, (s64)rd_val > (s64)val ? rd_val : val);
> +DEFINE_ATOMIC_FUNCTION(max_d_rl, s64_rl, (s64)rd_val > (s64)val ? rd_val : val);
> +DEFINE_ATOMIC_FUNCTION(max_d_aqrl, s64_aqrl, (s64)rd_val > (s64)val ? rd_val : val);
> +DEFINE_ATOMIC_FUNCTION(maxu_d, s64, (u64)rd_val > (u64)val ? rd_val : val);
> +DEFINE_ATOMIC_FUNCTION(maxu_d_aq, s64_aq, (u64)rd_val > (u64)val ? rd_val : val);
> +DEFINE_ATOMIC_FUNCTION(maxu_d_rl, s64_rl, (u64)rd_val > (u64)val ? rd_val : val);
> +DEFINE_ATOMIC_FUNCTION(maxu_d_aqrl, s64_aqrl, (u64)rd_val > (u64)val ? rd_val : val);
> +DEFINE_ATOMIC_FUNCTION(min_d, s64, (s64)rd_val < (s64)val ? rd_val : val);
> +DEFINE_ATOMIC_FUNCTION(min_d_aq, s64_aq, (s64)rd_val < (s64)val ? rd_val : val);
> +DEFINE_ATOMIC_FUNCTION(min_d_rl, s64_rl, (s64)rd_val < (s64)val ? rd_val : val);
> +DEFINE_ATOMIC_FUNCTION(min_d_aqrl, s64_aqrl, (s64)rd_val < (s64)val ? rd_val : val);
> +DEFINE_ATOMIC_FUNCTION(minu_d, s64, (u64)rd_val < (u64)val ? rd_val : val);
> +DEFINE_ATOMIC_FUNCTION(minu_d_aq, s64_aq, (u64)rd_val < (u64)val ? rd_val : val);
> +DEFINE_ATOMIC_FUNCTION(minu_d_rl, s64_rl, (u64)rd_val < (u64)val ? rd_val : val);
> +DEFINE_ATOMIC_FUNCTION(minu_d_aqrl, s64_aqrl, (u64)rd_val < (u64)val ? rd_val : val);
> +#endif
> diff --git a/lib/sbi/sbi_illegal_insn.c b/lib/sbi/sbi_illegal_insn.c
> index 784bc4c..4a01f59 100644
> --- a/lib/sbi/sbi_illegal_insn.c
> +++ b/lib/sbi/sbi_illegal_insn.c
> @@ -10,6 +10,7 @@
> #include <sbi/riscv_asm.h>
> #include <sbi/riscv_barrier.h>
> #include <sbi/riscv_encoding.h>
> +#include <sbi/sbi_atomic.h>
> #include <sbi/sbi_bitops.h>
> #include <sbi/sbi_emulate_csr.h>
> #include <sbi/sbi_error.h>
> @@ -19,6 +20,13 @@
> #include <sbi/sbi_unpriv.h>
> #include <sbi/sbi_console.h>
>
> +#define OPCODE_MASK 0x0000007f
> +#define AMO_OPCODE 0x0000002f
> +#define WD_MASK 0x00007000
> +#define WD_SHIFT 12
> +#define AQRL_MASK 0x06000000
> +#define AQRL_SHIFT 25
> +
> typedef int (*illegal_insn_func)(ulong insn, struct sbi_trap_regs *regs);
>
> static int truly_illegal_insn(ulong insn, struct sbi_trap_regs *regs)
> @@ -146,6 +154,487 @@ static const illegal_insn_func illegal_insn_table[32] = {
> truly_illegal_insn /* 31 */
> };
>
> +static int other_illegal_insn(ulong insn, struct sbi_trap_regs *regs)
> +{
> + return illegal_insn_table[(insn & 0x7c) >> 2](insn, regs);
> +}
> +
> +static const illegal_insn_func amoadd_table[32] = {
> + other_illegal_insn, /* 0 */
> + other_illegal_insn, /* 1 */
> + other_illegal_insn, /* 2 */
> + other_illegal_insn, /* 3 */
> + other_illegal_insn, /* 4 */
> + other_illegal_insn, /* 5 */
> + other_illegal_insn, /* 6 */
> + other_illegal_insn, /* 7 */
> + sbi_atomic_add_w, /* 8 */
> + sbi_atomic_add_w_rl, /* 9 */
> + sbi_atomic_add_w_aq, /* 10 */
> + sbi_atomic_add_w_aqrl, /* 11 */
> +#if __riscv_xlen == 64
> + sbi_atomic_add_d, /* 12 */
> + sbi_atomic_add_d_rl, /* 13 */
> + sbi_atomic_add_d_aq, /* 14 */
> + sbi_atomic_add_d_aqrl, /* 15 */
> +#else
> + other_illegal_insn, /* 12 */
> + other_illegal_insn, /* 13 */
> + other_illegal_insn, /* 14 */
> + other_illegal_insn, /* 15 */
> +#endif
> + other_illegal_insn, /* 16 */
> + other_illegal_insn, /* 17 */
> + other_illegal_insn, /* 18 */
> + other_illegal_insn, /* 19 */
> + other_illegal_insn, /* 20 */
> + other_illegal_insn, /* 21 */
> + other_illegal_insn, /* 22 */
> + other_illegal_insn, /* 23 */
> + other_illegal_insn, /* 24 */
> + other_illegal_insn, /* 25 */
> + other_illegal_insn, /* 26 */
> + other_illegal_insn, /* 27 */
> + other_illegal_insn, /* 28 */
> + other_illegal_insn, /* 29 */
> + other_illegal_insn, /* 30 */
> + other_illegal_insn, /* 31 */
> +};
> +
> +static const illegal_insn_func amoswap_table[32] = {
> + other_illegal_insn, /* 0 */
> + other_illegal_insn, /* 1 */
> + other_illegal_insn, /* 2 */
> + other_illegal_insn, /* 3 */
> + other_illegal_insn, /* 4 */
> + other_illegal_insn, /* 5 */
> + other_illegal_insn, /* 6 */
> + other_illegal_insn, /* 7 */
> + sbi_atomic_swap_w, /* 8 */
> + sbi_atomic_swap_w_rl, /* 9 */
> + sbi_atomic_swap_w_aq, /* 10 */
> + sbi_atomic_swap_w_aqrl, /* 11 */
> +#if __riscv_xlen == 64
> + sbi_atomic_swap_d, /* 12 */
> + sbi_atomic_swap_d_rl, /* 13 */
> + sbi_atomic_swap_d_aq, /* 14 */
> + sbi_atomic_swap_d_aqrl, /* 15 */
> +#else
> + other_illegal_insn, /* 12 */
> + other_illegal_insn, /* 13 */
> + other_illegal_insn, /* 14 */
> + other_illegal_insn, /* 15 */
> +#endif
> + other_illegal_insn, /* 16 */
> + other_illegal_insn, /* 17 */
> + other_illegal_insn, /* 18 */
> + other_illegal_insn, /* 19 */
> + other_illegal_insn, /* 20 */
> + other_illegal_insn, /* 21 */
> + other_illegal_insn, /* 22 */
> + other_illegal_insn, /* 23 */
> + other_illegal_insn, /* 24 */
> + other_illegal_insn, /* 25 */
> + other_illegal_insn, /* 26 */
> + other_illegal_insn, /* 27 */
> + other_illegal_insn, /* 28 */
> + other_illegal_insn, /* 29 */
> + other_illegal_insn, /* 30 */
> + other_illegal_insn, /* 31 */
> +};
> +
> +static const illegal_insn_func amoxor_table[32] = {
> + other_illegal_insn, /* 0 */
> + other_illegal_insn, /* 1 */
> + other_illegal_insn, /* 2 */
> + other_illegal_insn, /* 3 */
> + other_illegal_insn, /* 4 */
> + other_illegal_insn, /* 5 */
> + other_illegal_insn, /* 6 */
> + other_illegal_insn, /* 7 */
> + sbi_atomic_xor_w, /* 8 */
> + sbi_atomic_xor_w_rl, /* 9 */
> + sbi_atomic_xor_w_aq, /* 10 */
> + sbi_atomic_xor_w_aqrl, /* 11 */
> +#if __riscv_xlen == 64
> + sbi_atomic_xor_d, /* 12 */
> + sbi_atomic_xor_d_rl, /* 13 */
> + sbi_atomic_xor_d_aq, /* 14 */
> + sbi_atomic_xor_d_aqrl, /* 15 */
> +#else
> + other_illegal_insn, /* 12 */
> + other_illegal_insn, /* 13 */
> + other_illegal_insn, /* 14 */
> + other_illegal_insn, /* 15 */
> +#endif
> + other_illegal_insn, /* 16 */
> + other_illegal_insn, /* 17 */
> + other_illegal_insn, /* 18 */
> + other_illegal_insn, /* 19 */
> + other_illegal_insn, /* 20 */
> + other_illegal_insn, /* 21 */
> + other_illegal_insn, /* 22 */
> + other_illegal_insn, /* 23 */
> + other_illegal_insn, /* 24 */
> + other_illegal_insn, /* 25 */
> + other_illegal_insn, /* 26 */
> + other_illegal_insn, /* 27 */
> + other_illegal_insn, /* 28 */
> + other_illegal_insn, /* 29 */
> + other_illegal_insn, /* 30 */
> + other_illegal_insn, /* 31 */
> +};
> +
> +static const illegal_insn_func amoor_table[32] = {
> + other_illegal_insn, /* 0 */
> + other_illegal_insn, /* 1 */
> + other_illegal_insn, /* 2 */
> + other_illegal_insn, /* 3 */
> + other_illegal_insn, /* 4 */
> + other_illegal_insn, /* 5 */
> + other_illegal_insn, /* 6 */
> + other_illegal_insn, /* 7 */
> + sbi_atomic_or_w, /* 8 */
> + sbi_atomic_or_w_rl, /* 9 */
> + sbi_atomic_or_w_aq, /* 10 */
> + sbi_atomic_or_w_aqrl, /* 11 */
> +#if __riscv_xlen == 64
> + sbi_atomic_or_d, /* 12 */
> + sbi_atomic_or_d_rl, /* 13 */
> + sbi_atomic_or_d_aq, /* 14 */
> + sbi_atomic_or_d_aqrl, /* 15 */
> +#else
> + other_illegal_insn, /* 12 */
> + other_illegal_insn, /* 13 */
> + other_illegal_insn, /* 14 */
> + other_illegal_insn, /* 15 */
> +#endif
> + other_illegal_insn, /* 16 */
> + other_illegal_insn, /* 17 */
> + other_illegal_insn, /* 18 */
> + other_illegal_insn, /* 19 */
> + other_illegal_insn, /* 20 */
> + other_illegal_insn, /* 21 */
> + other_illegal_insn, /* 22 */
> + other_illegal_insn, /* 23 */
> + other_illegal_insn, /* 24 */
> + other_illegal_insn, /* 25 */
> + other_illegal_insn, /* 26 */
> + other_illegal_insn, /* 27 */
> + other_illegal_insn, /* 28 */
> + other_illegal_insn, /* 29 */
> + other_illegal_insn, /* 30 */
> + other_illegal_insn, /* 31 */
> +};
> +
> +static const illegal_insn_func amoand_table[32] = {
> + other_illegal_insn, /* 0 */
> + other_illegal_insn, /* 1 */
> + other_illegal_insn, /* 2 */
> + other_illegal_insn, /* 3 */
> + other_illegal_insn, /* 4 */
> + other_illegal_insn, /* 5 */
> + other_illegal_insn, /* 6 */
> + other_illegal_insn, /* 7 */
> + sbi_atomic_and_w, /* 8 */
> + sbi_atomic_and_w_rl, /* 9 */
> + sbi_atomic_and_w_aq, /* 10 */
> + sbi_atomic_and_w_aqrl, /* 11 */
> +#if __riscv_xlen == 64
> + sbi_atomic_and_d, /* 12 */
> + sbi_atomic_and_d_rl, /* 13 */
> + sbi_atomic_and_d_aq, /* 14 */
> + sbi_atomic_and_d_aqrl, /* 15 */
> +#else
> + other_illegal_insn, /* 12 */
> + other_illegal_insn, /* 13 */
> + other_illegal_insn, /* 14 */
> + other_illegal_insn, /* 15 */
> +#endif
> + other_illegal_insn, /* 16 */
> + other_illegal_insn, /* 17 */
> + other_illegal_insn, /* 18 */
> + other_illegal_insn, /* 19 */
> + other_illegal_insn, /* 20 */
> + other_illegal_insn, /* 21 */
> + other_illegal_insn, /* 22 */
> + other_illegal_insn, /* 23 */
> + other_illegal_insn, /* 24 */
> + other_illegal_insn, /* 25 */
> + other_illegal_insn, /* 26 */
> + other_illegal_insn, /* 27 */
> + other_illegal_insn, /* 28 */
> + other_illegal_insn, /* 29 */
> + other_illegal_insn, /* 30 */
> + other_illegal_insn, /* 31 */
> +};
> +
> +static const illegal_insn_func amomin_table[32] = {
> + other_illegal_insn, /* 0 */
> + other_illegal_insn, /* 1 */
> + other_illegal_insn, /* 2 */
> + other_illegal_insn, /* 3 */
> + other_illegal_insn, /* 4 */
> + other_illegal_insn, /* 5 */
> + other_illegal_insn, /* 6 */
> + other_illegal_insn, /* 7 */
> + sbi_atomic_min_w, /* 8 */
> + sbi_atomic_min_w_rl, /* 9 */
> + sbi_atomic_min_w_aq, /* 10 */
> + sbi_atomic_min_w_aqrl, /* 11 */
> +#if __riscv_xlen == 64
> + sbi_atomic_min_d, /* 12 */
> + sbi_atomic_min_d_rl, /* 13 */
> + sbi_atomic_min_d_aq, /* 14 */
> + sbi_atomic_min_d_aqrl, /* 15 */
> +#else
> + other_illegal_insn, /* 12 */
> + other_illegal_insn, /* 13 */
> + other_illegal_insn, /* 14 */
> + other_illegal_insn, /* 15 */
> +#endif
> + other_illegal_insn, /* 16 */
> + other_illegal_insn, /* 17 */
> + other_illegal_insn, /* 18 */
> + other_illegal_insn, /* 19 */
> + other_illegal_insn, /* 20 */
> + other_illegal_insn, /* 21 */
> + other_illegal_insn, /* 22 */
> + other_illegal_insn, /* 23 */
> + other_illegal_insn, /* 24 */
> + other_illegal_insn, /* 25 */
> + other_illegal_insn, /* 26 */
> + other_illegal_insn, /* 27 */
> + other_illegal_insn, /* 28 */
> + other_illegal_insn, /* 29 */
> + other_illegal_insn, /* 30 */
> + other_illegal_insn, /* 31 */
> +};
> +
> +static const illegal_insn_func amomax_table[32] = {
> + other_illegal_insn, /* 0 */
> + other_illegal_insn, /* 1 */
> + other_illegal_insn, /* 2 */
> + other_illegal_insn, /* 3 */
> + other_illegal_insn, /* 4 */
> + other_illegal_insn, /* 5 */
> + other_illegal_insn, /* 6 */
> + other_illegal_insn, /* 7 */
> + sbi_atomic_max_w, /* 8 */
> + sbi_atomic_max_w_rl, /* 9 */
> + sbi_atomic_max_w_aq, /* 10 */
> + sbi_atomic_max_w_aqrl, /* 11 */
> +#if __riscv_xlen == 64
> + sbi_atomic_max_d, /* 12 */
> + sbi_atomic_max_d_rl, /* 13 */
> + sbi_atomic_max_d_aq, /* 14 */
> + sbi_atomic_max_d_aqrl, /* 15 */
> +#else
> + other_illegal_insn, /* 12 */
> + other_illegal_insn, /* 13 */
> + other_illegal_insn, /* 14 */
> + other_illegal_insn, /* 15 */
> +#endif
> + other_illegal_insn, /* 16 */
> + other_illegal_insn, /* 17 */
> + other_illegal_insn, /* 18 */
> + other_illegal_insn, /* 19 */
> + other_illegal_insn, /* 20 */
> + other_illegal_insn, /* 21 */
> + other_illegal_insn, /* 22 */
> + other_illegal_insn, /* 23 */
> + other_illegal_insn, /* 24 */
> + other_illegal_insn, /* 25 */
> + other_illegal_insn, /* 26 */
> + other_illegal_insn, /* 27 */
> + other_illegal_insn, /* 28 */
> + other_illegal_insn, /* 29 */
> + other_illegal_insn, /* 30 */
> + other_illegal_insn, /* 31 */
> +};
> +
> +static const illegal_insn_func amominu_table[32] = {
> + other_illegal_insn, /* 0 */
> + other_illegal_insn, /* 1 */
> + other_illegal_insn, /* 2 */
> + other_illegal_insn, /* 3 */
> + other_illegal_insn, /* 4 */
> + other_illegal_insn, /* 5 */
> + other_illegal_insn, /* 6 */
> + other_illegal_insn, /* 7 */
> + sbi_atomic_minu_w, /* 8 */
> + sbi_atomic_minu_w_rl, /* 9 */
> + sbi_atomic_minu_w_aq, /* 10 */
> + sbi_atomic_minu_w_aqrl, /* 11 */
> +#if __riscv_xlen == 64
> + sbi_atomic_minu_d, /* 12 */
> + sbi_atomic_minu_d_rl, /* 13 */
> + sbi_atomic_minu_d_aq, /* 14 */
> + sbi_atomic_minu_d_aqrl, /* 15 */
> +#else
> + other_illegal_insn, /* 12 */
> + other_illegal_insn, /* 13 */
> + other_illegal_insn, /* 14 */
> + other_illegal_insn, /* 15 */
> +#endif
> + other_illegal_insn, /* 16 */
> + other_illegal_insn, /* 17 */
> + other_illegal_insn, /* 18 */
> + other_illegal_insn, /* 19 */
> + other_illegal_insn, /* 20 */
> + other_illegal_insn, /* 21 */
> + other_illegal_insn, /* 22 */
> + other_illegal_insn, /* 23 */
> + other_illegal_insn, /* 24 */
> + other_illegal_insn, /* 25 */
> + other_illegal_insn, /* 26 */
> + other_illegal_insn, /* 27 */
> + other_illegal_insn, /* 28 */
> + other_illegal_insn, /* 29 */
> + other_illegal_insn, /* 30 */
> + other_illegal_insn, /* 31 */
> +};
> +
> +static const illegal_insn_func amomaxu_table[32] = {
> + other_illegal_insn, /* 0 */
> + other_illegal_insn, /* 1 */
> + other_illegal_insn, /* 2 */
> + other_illegal_insn, /* 3 */
> + other_illegal_insn, /* 4 */
> + other_illegal_insn, /* 5 */
> + other_illegal_insn, /* 6 */
> + other_illegal_insn, /* 7 */
> + sbi_atomic_maxu_w, /* 8 */
> + sbi_atomic_maxu_w_rl, /* 9 */
> + sbi_atomic_maxu_w_aq, /* 10 */
> + sbi_atomic_maxu_w_aqrl, /* 11 */
> +#if __riscv_xlen == 64
> + sbi_atomic_maxu_d, /* 12 */
> + sbi_atomic_maxu_d_rl, /* 13 */
> + sbi_atomic_maxu_d_aq, /* 14 */
> + sbi_atomic_maxu_d_aqrl, /* 15 */
> +#else
> + other_illegal_insn, /* 12 */
> + other_illegal_insn, /* 13 */
> + other_illegal_insn, /* 14 */
> + other_illegal_insn, /* 15 */
> +#endif
> + other_illegal_insn, /* 16 */
> + other_illegal_insn, /* 17 */
> + other_illegal_insn, /* 18 */
> + other_illegal_insn, /* 19 */
> + other_illegal_insn, /* 20 */
> + other_illegal_insn, /* 21 */
> + other_illegal_insn, /* 22 */
> + other_illegal_insn, /* 23 */
> + other_illegal_insn, /* 24 */
> + other_illegal_insn, /* 25 */
> + other_illegal_insn, /* 26 */
> + other_illegal_insn, /* 27 */
> + other_illegal_insn, /* 28 */
> + other_illegal_insn, /* 29 */
> + other_illegal_insn, /* 30 */
> + other_illegal_insn, /* 31 */
> +};
> +
> +static int amoadd_insn(ulong insn, struct sbi_trap_regs *regs)
> +{
> + int wd = ((insn & WD_MASK) >> WD_SHIFT) << 2;
> + int aqrl = (insn & AQRL_MASK) >> AQRL_SHIFT;
> + return amoadd_table[wd + aqrl](insn, regs);
> +}
> +
> +static int amoswap_insn(ulong insn, struct sbi_trap_regs *regs)
> +{
> + int wd = ((insn & WD_MASK) >> WD_SHIFT) << 2;
> + int aqrl = (insn & AQRL_MASK) >> AQRL_SHIFT;
> + return amoswap_table[wd + aqrl](insn, regs);
> +}
> +
> +static int amoxor_insn(ulong insn, struct sbi_trap_regs *regs)
> +{
> + int wd = ((insn & WD_MASK) >> WD_SHIFT) << 2;
> + int aqrl = (insn & AQRL_MASK) >> AQRL_SHIFT;
> + return amoxor_table[wd + aqrl](insn, regs);
> +}
> +
> +static int amoor_insn(ulong insn, struct sbi_trap_regs *regs)
> +{
> + int wd = ((insn & WD_MASK) >> WD_SHIFT) << 2;
> + int aqrl = (insn & AQRL_MASK) >> AQRL_SHIFT;
> + return amoor_table[wd + aqrl](insn, regs);
> +}
> +
> +static int amoand_insn(ulong insn, struct sbi_trap_regs *regs)
> +{
> + int wd = ((insn & WD_MASK) >> WD_SHIFT) << 2;
> + int aqrl = (insn & AQRL_MASK) >> AQRL_SHIFT;
> + return amoand_table[wd + aqrl](insn, regs);
> +}
> +
> +static int amomin_insn(ulong insn, struct sbi_trap_regs *regs)
> +{
> + int wd = ((insn & WD_MASK) >> WD_SHIFT) << 2;
> + int aqrl = (insn & AQRL_MASK) >> AQRL_SHIFT;
> + return amomin_table[wd + aqrl](insn, regs);
> +}
> +
> +static int amomax_insn(ulong insn, struct sbi_trap_regs *regs)
> +{
> + int wd = ((insn & WD_MASK) >> WD_SHIFT) << 2;
> + int aqrl = (insn & AQRL_MASK) >> AQRL_SHIFT;
> + return amomax_table[wd + aqrl](insn, regs);
> +}
> +
> +static int amominu_insn(ulong insn, struct sbi_trap_regs *regs)
> +{
> + int wd = ((insn & WD_MASK) >> WD_SHIFT) << 2;
> + int aqrl = (insn & AQRL_MASK) >> AQRL_SHIFT;
> + return amominu_table[wd + aqrl](insn, regs);
> +}
> +
> +static int amomaxu_insn(ulong insn, struct sbi_trap_regs *regs)
> +{
> + int wd = ((insn & WD_MASK) >> WD_SHIFT) << 2;
> + int aqrl = (insn & AQRL_MASK) >> AQRL_SHIFT;
> + return amomaxu_table[wd + aqrl](insn, regs);
> +}
> +
> +static const illegal_insn_func amo_insn_table[32] = {
> + amoadd_insn, /* 0 */
> + amoswap_insn, /* 1 */
> + other_illegal_insn, /* 2 */
> + other_illegal_insn, /* 3 */
> + amoxor_insn, /* 4 */
> + other_illegal_insn, /* 5 */
> + other_illegal_insn, /* 6 */
> + other_illegal_insn, /* 7 */
> + amoor_insn, /* 8 */
> + other_illegal_insn, /* 9 */
> + other_illegal_insn, /* 10 */
> + other_illegal_insn, /* 11 */
> + amoand_insn, /* 12 */
> + other_illegal_insn, /* 13 */
> + other_illegal_insn, /* 14 */
> + other_illegal_insn, /* 15 */
> + amomin_insn, /* 16 */
> + other_illegal_insn, /* 17 */
> + other_illegal_insn, /* 18 */
> + other_illegal_insn, /* 19 */
> + amomax_insn, /* 20 */
> + other_illegal_insn, /* 21 */
> + other_illegal_insn, /* 22 */
> + other_illegal_insn, /* 23 */
> + amominu_insn, /* 24 */
> + other_illegal_insn, /* 25 */
> + other_illegal_insn, /* 26 */
> + other_illegal_insn, /* 27 */
> + amomaxu_insn, /* 28 */
> + other_illegal_insn, /* 29 */
> + other_illegal_insn, /* 30 */
> + other_illegal_insn /* 31 */
> +};
> +
> int sbi_illegal_insn_handler(struct sbi_trap_context *tcntx)
> {
> struct sbi_trap_regs *regs = &tcntx->regs;
> @@ -172,5 +661,8 @@ int sbi_illegal_insn_handler(struct sbi_trap_context *tcntx)
> return truly_illegal_insn(insn, regs);
> }
>
> + if ((insn & OPCODE_MASK) == AMO_OPCODE)
> + return amo_insn_table[(insn >> 27) & 0x1f](insn, regs);
> +
> return illegal_insn_table[(insn & 0x7c) >> 2](insn, regs);
> }
> --
> 2.47.1
>
>
> --
> opensbi mailing list
> opensbi@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply [flat|nested] 70+ messages in thread
* [PATCH v4 6/8] platform: generic: mips: add a dts file
2025-02-12 12:27 ` Anup Patel
` (26 preceding siblings ...)
2025-04-29 23:29 ` [PATCH v4 5/8] lib: Emulate amo instructions Chao-ying Fu
@ 2025-04-29 23:29 ` Chao-ying Fu
2025-04-29 23:29 ` [PATCH v4 7/8] platform: generic: mips: add objects.mk Chao-ying Fu
` (20 subsequent siblings)
48 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-04-29 23:29 UTC (permalink / raw)
To: opensbi; +Cc: Chao-ying Fu
We add a dts file for 4 cores 2 threads each on a Boston board.
Signed-off-by: Chao-ying Fu <cfu@mips.com>
---
platform/generic/mips/mips,boston-p8700.dts | 347 ++++++++++++++++++++
1 file changed, 347 insertions(+)
create mode 100644 platform/generic/mips/mips,boston-p8700.dts
diff --git a/platform/generic/mips/mips,boston-p8700.dts b/platform/generic/mips/mips,boston-p8700.dts
new file mode 100644
index 0000000..6da646c
--- /dev/null
+++ b/platform/generic/mips/mips,boston-p8700.dts
@@ -0,0 +1,347 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 MIPS
+ *
+ */
+
+/dts-v1/;
+
+#define CM_BASE 0x16100000
+#define APLIC_M_BASE (CM_BASE + 0x40000)
+#define APLIC_S_BASE (CM_BASE + 0x60000)
+#define MSWI_BASE (CM_BASE + 0x50000)
+#define MTIMER_BASE (MSWI_BASE + 0x4000)
+#define CPC_TIMER (CM_BASE + 0x8050)
+
+#define IRQ_TYPE_LEVEL_HIGH 4
+#define UART_INT 4
+#define PCIE2_INT 7
+
+#define BITFILE_FREQUENCY 25000000
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ model = "MIPS P8700";
+ compatible = "mips,p8700";
+
+ chosen {
+ stdout-path = &uart0;
+ // For Qemu
+ //bootargs = "root=/dev/sda rw earlycon console=ttyS0,115200n8r";
+ // For a Boston board
+ bootargs = "root=/dev/mmcblk0p5 rw rootwait earlycon console=ttyS0,115200n8r";
+
+ opensbi-domains {
+ compatible = "opensbi,domain,config";
+
+ tmem: tmem {
+ compatible = "opensbi,domain,memregion";
+ base = <0x0 0x80000000>;
+ order = <31>;
+ };
+
+ allmem: allmem {
+ compatible = "opensbi,domain,memregion";
+ base = <0x0 0x0>;
+ order = <64>;
+ };
+
+ tdomain: trusted-domain {
+ compatible = "opensbi,domain,instance";
+ possible-harts = <&cpu0 &cpu1 &cpu2 &cpu3 &cpu4 &cpu5 &cpu6 &cpu7>;
+ regions = <&tmem 0x3f>, <&allmem 0x3f>;
+ };
+ };
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ timebase-frequency = <BITFILE_FREQUENCY>;
+
+ cpu0: cpu@0 {
+ device_type = "cpu";
+ compatible = "riscv";
+ riscv,cbom-block-size = <64>;
+ opensbi-domain = <&tdomain>;
+ mmu-type = "riscv,sv39";
+ riscv,isa = "rv64imafdcsu";
+ status = "okay";
+ reg = <0x00000000>;
+
+ cpu0_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu1: cpu@1 {
+ device_type = "cpu";
+ compatible = "riscv";
+ riscv,cbom-block-size = <64>;
+ opensbi-domain = <&tdomain>;
+ mmu-type = "riscv,sv39";
+ riscv,isa = "rv64imafdcsu";
+ status = "okay";
+ reg = <0x00000001>;
+
+ cpu1_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu2: cpu@2 {
+ device_type = "cpu";
+ compatible = "riscv";
+ riscv,cbom-block-size = <64>;
+ opensbi-domain = <&tdomain>;
+ mmu-type = "riscv,sv39";
+ riscv,isa = "rv64imafdcsu";
+ status = "okay";
+ reg = <0x00000010>;
+
+ cpu2_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu3: cpu@3 {
+ device_type = "cpu";
+ compatible = "riscv";
+ riscv,cbom-block-size = <64>;
+ opensbi-domain = <&tdomain>;
+ mmu-type = "riscv,sv39";
+ riscv,isa = "rv64imafdcsu";
+ status = "okay";
+ reg = <0x00000011>;
+
+ cpu3_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu4: cpu@4 {
+ device_type = "cpu";
+ compatible = "riscv";
+ riscv,cbom-block-size = <64>;
+ opensbi-domain = <&tdomain>;
+ mmu-type = "riscv,sv39";
+ riscv,isa = "rv64imafdcsu";
+ status = "okay";
+ reg = <0x00000020>;
+
+ cpu4_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu5: cpu@5 {
+ device_type = "cpu";
+ compatible = "riscv";
+ riscv,cbom-block-size = <64>;
+ opensbi-domain = <&tdomain>;
+ mmu-type = "riscv,sv39";
+ riscv,isa = "rv64imafdcsu";
+ status = "okay";
+ reg = <0x00000021>;
+
+ cpu5_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu6: cpu@6 {
+ device_type = "cpu";
+ compatible = "riscv";
+ riscv,cbom-block-size = <64>;
+ opensbi-domain = <&tdomain>;
+ mmu-type = "riscv,sv39";
+ riscv,isa = "rv64imafdcsu";
+ status = "okay";
+ reg = <0x00000030>;
+
+ cpu6_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu7: cpu@7 {
+ device_type = "cpu";
+ compatible = "riscv";
+ riscv,cbom-block-size = <64>;
+ opensbi-domain = <&tdomain>;
+ mmu-type = "riscv,sv39";
+ riscv,isa = "rv64imafdcsu";
+ status = "okay";
+ reg = <0x00000031>;
+
+ cpu7_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x80000000 0x80000000>;
+ };
+
+ pci2: pci@14000000 {
+ compatible = "xlnx,axi-pcie-host-1.00.a";
+ device_type = "pci";
+ reg = <0x14000000 0x2000000>;
+
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+
+ interrupt-parent = <&aplic_s0>;
+ interrupts = <PCIE2_INT IRQ_TYPE_LEVEL_HIGH>;
+
+ ranges = <0x02000000 0 0x16000000
+ 0x16000000 0 0x100000>;
+
+ bus-range = <0x00 0xff>;
+
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &pci2_intc 1>,
+ <0 0 0 2 &pci2_intc 2>,
+ <0 0 0 3 &pci2_intc 3>,
+ <0 0 0 4 &pci2_intc 4>;
+
+ pci2_intc: interrupt-controller {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ };
+
+ pci2_root@0,0 {
+ compatible = "pci10ee,7021", "pci-bridge";
+ reg = <0x00000000 0 0 0 0>;
+
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+
+ eg20t_bridge@1,0,0 {
+ compatible = "pci8086,8800", "pci-bridge";
+ reg = <0x00010000 0 0 0 0>;
+
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+
+ eg20t_mac@2,0,1 {
+ compatible = "pci8086,8802", "intel,pch-gbe";
+ reg = <0x00020100 0 0 0 0>;
+ phy-reset-gpios = <&eg20t_gpio 6 1>;
+ };
+
+ eg20t_gpio: eg20t_gpio@2,0,2 {
+ compatible = "pci8086,8803", "intel,eg20t-gpio";
+ reg = <0x00020200 0 0 0 0>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ eg20t_i2c@2,12,2 {
+ compatible = "pci8086,8817";
+ reg = <0x00026200 0 0 0 0>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rtc@68 {
+ compatible = "st,m41t81s";
+ reg = <0x68>;
+ };
+ };
+ };
+ };
+ };
+
+ uart0: uart@17ffe000 {
+ compatible = "ns16550a";
+ reg = <0x17ffe000 0x1000>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+
+ interrupt-parent = <&aplic_s0>;
+ interrupts = <UART_INT IRQ_TYPE_LEVEL_HIGH>;
+
+ clock-frequency = <BITFILE_FREQUENCY>;
+
+ u-boot,dm-pre-reloc;
+ };
+
+ lcd: lcd@17fff000 {
+ compatible = "img,boston-lcd";
+ reg = <0x17fff000 0x8>;
+ };
+
+ flash@18000000 {
+ compatible = "cfi-flash";
+ reg = <0x18000000 0x8000000>;
+ bank-width = <2>;
+ };
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges;
+
+ aplic_s0: interrupt-controller@16160000 {
+ #interrupt-cells = <0x00000002>;
+ compatible = "riscv,aplic";
+ interrupt-controller;
+ interrupts-extended = <&cpu0_intc 9>, <&cpu1_intc 9>, <&cpu2_intc 9>, <&cpu3_intc 9>, <&cpu4_intc 9>, <&cpu5_intc 9>, <&cpu6_intc 9>, <&cpu7_intc 9>;
+ reg = <APLIC_S_BASE 0x00008000>;
+ riscv,num-sources = <0x00000035>;
+ };
+
+ aplic_m0: interrupt-controller@16140000 {
+ #interrupt-cells = <0x00000002>;
+ riscv,delegate = <&aplic_s0 0x00000001 0x00000035>;
+ riscv,children = <&aplic_s0>;
+ compatible = "riscv,aplic";
+ interrupt-controller;
+ interrupts-extended = <&cpu0_intc 11>, <&cpu1_intc 11>, <&cpu2_intc 11>, <&cpu3_intc 11>, <&cpu4_intc 11>, <&cpu5_intc 11>, <&cpu6_intc 11>, <&cpu7_intc 11>;
+ reg = <APLIC_M_BASE 0x00008000>;
+ riscv,num-sources = <0x00000035>;
+ };
+
+ mswi0: interrupt-controller@16150000 {
+ compatible = "riscv,aclint-mswi";
+ interrupts-extended = <&cpu0_intc 3>, <&cpu1_intc 3>, <&cpu2_intc 3>, <&cpu3_intc 3>, <&cpu4_intc 3>, <&cpu5_intc 3>, <&cpu6_intc 3>, <&cpu7_intc 3>;
+ reg = <MSWI_BASE 0x4000>;
+ interrupt-controller;
+ #interrupt-cells = <0>;
+ };
+
+ mtimer0: timer@16154000 {
+ compatible = "riscv,aclint-mtimer";
+ reg = <CPC_TIMER 0x8>,
+ <MTIMER_BASE 0x7ff8>;
+ interrupts-extended = <&cpu0_intc 7>, <&cpu1_intc 7>, <&cpu2_intc 7>, <&cpu3_intc 7>, <&cpu4_intc 7>, <&cpu5_intc 7>, <&cpu6_intc 7>, <&cpu7_intc 7>;
+ };
+ };
+};
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 70+ messages in thread* [PATCH v4 7/8] platform: generic: mips: add objects.mk
2025-02-12 12:27 ` Anup Patel
` (27 preceding siblings ...)
2025-04-29 23:29 ` [PATCH v4 6/8] platform: generic: mips: add a dts file Chao-ying Fu
@ 2025-04-29 23:29 ` Chao-ying Fu
2025-04-29 23:29 ` [PATCH v4 8/8] Initialize MIPS custom PMA registers Chao-ying Fu
` (19 subsequent siblings)
48 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-04-29 23:29 UTC (permalink / raw)
To: opensbi; +Cc: Chao-ying Fu
We build MIPS files.
Signed-off-by: Chao-ying Fu <cfu@mips.com>
---
platform/generic/mips/objects.mk | 7 +++++++
1 file changed, 7 insertions(+)
create mode 100644 platform/generic/mips/objects.mk
diff --git a/platform/generic/mips/objects.mk b/platform/generic/mips/objects.mk
new file mode 100644
index 0000000..6b051c0
--- /dev/null
+++ b/platform/generic/mips/objects.mk
@@ -0,0 +1,7 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+
+carray-platform_override_modules-$(CONFIG_PLATFORM_MIPS_P8700) += mips_p8700
+platform-objs-$(CONFIG_PLATFORM_MIPS_P8700) += mips/p8700.o mips/cps-vec.o
+platform-dtb-$(CONFIG_PLATFORM_MIPS_P8700) += mips/mips,boston-p8700.dtb
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 70+ messages in thread* [PATCH v4 8/8] Initialize MIPS custom PMA registers
2025-02-12 12:27 ` Anup Patel
` (28 preceding siblings ...)
2025-04-29 23:29 ` [PATCH v4 7/8] platform: generic: mips: add objects.mk Chao-ying Fu
@ 2025-04-29 23:29 ` Chao-ying Fu
2025-05-19 21:58 ` [PATCH v5 00/10] *** Add MIPS P8700 Platform *** Chao-ying Fu
` (18 subsequent siblings)
48 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-04-29 23:29 UTC (permalink / raw)
To: opensbi; +Cc: Chao-ying Fu
Before PMP set up, we need to set up MIPS custom PMA registers
to have correct cacheable or uncacheable execution for pmp regions.
Signed-off-by: Chao-ying Fu <cfu@mips.com>
---
lib/sbi/riscv_asm.c | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/lib/sbi/riscv_asm.c b/lib/sbi/riscv_asm.c
index c7d75ac..ca7edbe 100644
--- a/lib/sbi/riscv_asm.c
+++ b/lib/sbi/riscv_asm.c
@@ -12,6 +12,9 @@
#include <sbi/sbi_error.h>
#include <sbi/sbi_platform.h>
#include <sbi/sbi_console.h>
+#ifdef CONFIG_PLATFORM_MIPS_P8700
+#include <mips/p8700.h>
+#endif
/* determine CPU extension, return non-zero support */
int misa_extension_imp(char ext)
@@ -119,6 +122,9 @@ unsigned long csr_read_num(int csr_num)
unsigned long ret = 0;
switch (csr_num) {
+#ifdef CONFIG_PLATFORM_MIPS_P8700
+ switchcase_csr_read_16(CSR_MIPSPMACFG0, ret)
+#endif
switchcase_csr_read_16(CSR_PMPCFG0, ret)
switchcase_csr_read_64(CSR_PMPADDR0, ret)
switchcase_csr_read(CSR_MCYCLE, ret)
@@ -199,6 +205,9 @@ void csr_write_num(int csr_num, unsigned long val)
switchcase_csr_write_32(__csr_num + 32, __val)
switch (csr_num) {
+#ifdef CONFIG_PLATFORM_MIPS_P8700
+ switchcase_csr_write_16(CSR_MIPSPMACFG0, val)
+#endif
switchcase_csr_write_16(CSR_PMPCFG0, val)
switchcase_csr_write_64(CSR_PMPADDR0, val)
switchcase_csr_write(CSR_MCYCLE, val)
@@ -301,6 +310,29 @@ int is_pmp_entry_mapped(unsigned long entry)
return false;
}
+#ifdef CONFIG_PLATFORM_MIPS_P8700
+extern unsigned long _fw_start;
+static void pma_set(unsigned int n, unsigned long addr)
+{
+ int pmacfg_csr, pmacfg_shift;
+ unsigned long cfgmask;
+ unsigned long pmacfg, cca;
+
+ pmacfg_csr = (CSR_MIPSPMACFG0 + (n >> 2)) & ~1;
+ pmacfg_shift = (n & 7) << 3;
+ cfgmask = ~(0xffUL << pmacfg_shift);
+
+ /* Read pmacfg to change cacheability */
+ pmacfg = (csr_read_num(pmacfg_csr) & cfgmask);
+ if (addr >= (unsigned long)&_fw_start)
+ cca = CCA_CACHE_ENABLE | PMA_SPECULATION;
+ else
+ cca = CCA_CACHE_DISABLE;
+ pmacfg |= ((cca << pmacfg_shift) & ~cfgmask);
+ csr_write_num(pmacfg_csr, pmacfg);
+}
+#endif
+
int pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
unsigned long log2len)
{
@@ -312,6 +344,10 @@ int pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
if (n >= PMP_COUNT || log2len > __riscv_xlen || log2len < PMP_SHIFT)
return SBI_EINVAL;
+#ifdef CONFIG_PLATFORM_MIPS_P8700
+ pma_set(n, addr);
+#endif
+
/* calculate PMP register and offset */
#if __riscv_xlen == 32
pmpcfg_csr = CSR_PMPCFG0 + (n >> 2);
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 70+ messages in thread* [PATCH v5 00/10] *** Add MIPS P8700 Platform ***
2025-02-12 12:27 ` Anup Patel
` (29 preceding siblings ...)
2025-04-29 23:29 ` [PATCH v4 8/8] Initialize MIPS custom PMA registers Chao-ying Fu
@ 2025-05-19 21:58 ` Chao-ying Fu
2025-05-20 5:18 ` Anup Patel
2025-05-19 21:58 ` [PATCH v5 01/10] platform: generic: mips: add P8700 Chao-ying Fu
` (17 subsequent siblings)
48 siblings, 1 reply; 70+ messages in thread
From: Chao-ying Fu @ 2025-05-19 21:58 UTC (permalink / raw)
To: opensbi; +Cc: Chao-ying Fu
***
Changes in v5:
Drop the amo emulation code.
Change to use macros to insert instructions in p8700.c.
Add 3 new patches to recognize mmio regions and set up cacheability based on
mmio regions.
Changes in v4:
Remove code that overrides nascent_init.
Update p8700.c to work with the latest override.
Use csr_set for mipsconfig6 in p8700.c.
Add riscv,cbom-block-size to the dts file.
Changes in v3:
Remove stw.s, stw.h, and extra scratch space.
Use nascent_init to initialze MIPS CSRs.
Add amo emulation via illegal instruction exceptions.
Change to use AMO and RDTIME illegal instruction exceptions.
Revise the dts file.
Remove code that jumps to mips_cps_core_entry.
Changes in v2:
Break up one patch to 11 patches.
Changes in v1:
Original code.
***
Chao-ying Fu (8):
platform: generic: mips: add P8700
platform: generic: mips: add header files
platform: generic: mips: add an entry function
platform: generic: mips: add the platform file
platform: generic: mips: add a dts file
platform: generic: mips: add objects.mk
Initialize MIPS custom PMA registers
platform: generic: mips: add mmio to allmem in the dts file
Vladimir Kondratiev (2):
devices to use MMIO memory
Fix PMA init for MMIO regions
include/sbi/riscv_asm.h | 2 +
lib/sbi/riscv_asm.c | 32 ++
lib/sbi/sbi_hart.c | 13 +
lib/utils/fdt/fdt_fixup.c | 2 +-
platform/generic/Kconfig | 4 +
platform/generic/configs/defconfig | 1 +
platform/generic/include/mips/board.h | 33 ++
platform/generic/include/mips/mips-cm.h | 88 +++++
platform/generic/include/mips/p8700.h | 113 +++++++
platform/generic/mips/cps-vec.S | 75 +++++
platform/generic/mips/mips,boston-p8700.dts | 348 ++++++++++++++++++++
platform/generic/mips/objects.mk | 7 +
platform/generic/mips/p8700.c | 279 ++++++++++++++++
13 files changed, 996 insertions(+), 1 deletion(-)
create mode 100644 platform/generic/include/mips/board.h
create mode 100644 platform/generic/include/mips/mips-cm.h
create mode 100644 platform/generic/include/mips/p8700.h
create mode 100644 platform/generic/mips/cps-vec.S
create mode 100644 platform/generic/mips/mips,boston-p8700.dts
create mode 100644 platform/generic/mips/objects.mk
create mode 100644 platform/generic/mips/p8700.c
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply [flat|nested] 70+ messages in thread* Re: [PATCH v5 00/10] *** Add MIPS P8700 Platform ***
2025-05-19 21:58 ` [PATCH v5 00/10] *** Add MIPS P8700 Platform *** Chao-ying Fu
@ 2025-05-20 5:18 ` Anup Patel
0 siblings, 0 replies; 70+ messages in thread
From: Anup Patel @ 2025-05-20 5:18 UTC (permalink / raw)
To: Chao-ying Fu; +Cc: opensbi, Chao-ying Fu
On Tue, May 20, 2025 at 3:29 AM Chao-ying Fu <icebergfu@gmail.com> wrote:
>
Please write proper description in cover-letter and also drop the "***"
from cover-letter subject.
Use "git format-patch -M -C --cover-letter --subect-prefix=xyz" to
generate patches and always use "git send-email" to send patches.
Regards,
Anup
> ***
> Changes in v5:
> Drop the amo emulation code.
> Change to use macros to insert instructions in p8700.c.
> Add 3 new patches to recognize mmio regions and set up cacheability based on
> mmio regions.
>
> Changes in v4:
> Remove code that overrides nascent_init.
> Update p8700.c to work with the latest override.
> Use csr_set for mipsconfig6 in p8700.c.
> Add riscv,cbom-block-size to the dts file.
>
> Changes in v3:
> Remove stw.s, stw.h, and extra scratch space.
> Use nascent_init to initialze MIPS CSRs.
> Add amo emulation via illegal instruction exceptions.
> Change to use AMO and RDTIME illegal instruction exceptions.
> Revise the dts file.
> Remove code that jumps to mips_cps_core_entry.
>
> Changes in v2:
> Break up one patch to 11 patches.
>
> Changes in v1:
> Original code.
> ***
>
> Chao-ying Fu (8):
> platform: generic: mips: add P8700
> platform: generic: mips: add header files
> platform: generic: mips: add an entry function
> platform: generic: mips: add the platform file
> platform: generic: mips: add a dts file
> platform: generic: mips: add objects.mk
> Initialize MIPS custom PMA registers
> platform: generic: mips: add mmio to allmem in the dts file
>
> Vladimir Kondratiev (2):
> devices to use MMIO memory
> Fix PMA init for MMIO regions
>
> include/sbi/riscv_asm.h | 2 +
> lib/sbi/riscv_asm.c | 32 ++
> lib/sbi/sbi_hart.c | 13 +
> lib/utils/fdt/fdt_fixup.c | 2 +-
> platform/generic/Kconfig | 4 +
> platform/generic/configs/defconfig | 1 +
> platform/generic/include/mips/board.h | 33 ++
> platform/generic/include/mips/mips-cm.h | 88 +++++
> platform/generic/include/mips/p8700.h | 113 +++++++
> platform/generic/mips/cps-vec.S | 75 +++++
> platform/generic/mips/mips,boston-p8700.dts | 348 ++++++++++++++++++++
> platform/generic/mips/objects.mk | 7 +
> platform/generic/mips/p8700.c | 279 ++++++++++++++++
> 13 files changed, 996 insertions(+), 1 deletion(-)
> create mode 100644 platform/generic/include/mips/board.h
> create mode 100644 platform/generic/include/mips/mips-cm.h
> create mode 100644 platform/generic/include/mips/p8700.h
> create mode 100644 platform/generic/mips/cps-vec.S
> create mode 100644 platform/generic/mips/mips,boston-p8700.dts
> create mode 100644 platform/generic/mips/objects.mk
> create mode 100644 platform/generic/mips/p8700.c
>
> --
> 2.47.1
>
>
> --
> opensbi mailing list
> opensbi@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply [flat|nested] 70+ messages in thread
* [PATCH v5 01/10] platform: generic: mips: add P8700
2025-02-12 12:27 ` Anup Patel
` (30 preceding siblings ...)
2025-05-19 21:58 ` [PATCH v5 00/10] *** Add MIPS P8700 Platform *** Chao-ying Fu
@ 2025-05-19 21:58 ` Chao-ying Fu
2025-05-19 21:58 ` [PATCH v5 02/10] platform: generic: mips: add header files Chao-ying Fu
` (16 subsequent siblings)
48 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-05-19 21:58 UTC (permalink / raw)
To: opensbi; +Cc: Chao-ying Fu
Add a new config first.
Signed-off-by: Chao-ying Fu <cfu@mips.com>
---
platform/generic/Kconfig | 4 ++++
platform/generic/configs/defconfig | 1 +
2 files changed, 5 insertions(+)
diff --git a/platform/generic/Kconfig b/platform/generic/Kconfig
index 688da3f..a24d6ab 100644
--- a/platform/generic/Kconfig
+++ b/platform/generic/Kconfig
@@ -68,6 +68,10 @@ config PLATFORM_THEAD
select THEAD_C9XX_PMU
default n
+config PLATFORM_MIPS_P8700
+ bool "MIPS P8700 support"
+ default n
+
source "$(OPENSBI_SRC_DIR)/platform/generic/andes/Kconfig"
source "$(OPENSBI_SRC_DIR)/platform/generic/thead/Kconfig"
diff --git a/platform/generic/configs/defconfig b/platform/generic/configs/defconfig
index bb26062..ce1f1ae 100644
--- a/platform/generic/configs/defconfig
+++ b/platform/generic/configs/defconfig
@@ -6,6 +6,7 @@ CONFIG_PLATFORM_SIFIVE_FU740=y
CONFIG_PLATFORM_SOPHGO_SG2042=y
CONFIG_PLATFORM_STARFIVE_JH7110=y
CONFIG_PLATFORM_THEAD=y
+CONFIG_PLATFORM_MIPS_P8700=n
CONFIG_FDT_CPPC=y
CONFIG_FDT_CPPC_RPMI=y
CONFIG_FDT_GPIO=y
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 70+ messages in thread* [PATCH v5 02/10] platform: generic: mips: add header files
2025-02-12 12:27 ` Anup Patel
` (31 preceding siblings ...)
2025-05-19 21:58 ` [PATCH v5 01/10] platform: generic: mips: add P8700 Chao-ying Fu
@ 2025-05-19 21:58 ` Chao-ying Fu
2025-05-19 21:58 ` [PATCH v5 03/10] platform: generic: mips: add an entry function Chao-ying Fu
` (15 subsequent siblings)
48 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-05-19 21:58 UTC (permalink / raw)
To: opensbi; +Cc: Chao-ying Fu
Add header files to define MIPS Custom CSRs and define for the board.
Add accessor functions for MIPS CM registers.
Signed-off-by: Chao-ying Fu <cfu@mips.com>
---
platform/generic/include/mips/board.h | 33 +++++++
platform/generic/include/mips/mips-cm.h | 88 ++++++++++++++++++
platform/generic/include/mips/p8700.h | 113 ++++++++++++++++++++++++
3 files changed, 234 insertions(+)
create mode 100644 platform/generic/include/mips/board.h
create mode 100644 platform/generic/include/mips/mips-cm.h
create mode 100644 platform/generic/include/mips/p8700.h
diff --git a/platform/generic/include/mips/board.h b/platform/generic/include/mips/board.h
new file mode 100644
index 0000000..6fe7b8b
--- /dev/null
+++ b/platform/generic/include/mips/board.h
@@ -0,0 +1,33 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 MIPS
+ *
+ */
+
+#ifndef __BOARD_H__
+#define __BOARD_H__
+
+/* Please review all defines to change for your board. */
+
+/* Use in stw.S, p8700.c, p8700.h, mips-cm.h */
+#define CM_BASE 0x16100000
+
+/* Use in mips-cm.h, p8700.c */
+#define CLUSTERS_IN_PLATFORM 1
+#if CLUSTERS_IN_PLATFORM > 1
+/* Define global CM bases for cluster 0, 1, 2, and more. */
+#define GLOBAL_CM_BASE0 0
+#define GLOBAL_CM_BASE1 0
+#define GLOBAL_CM_BASE2 0
+#endif
+
+/* Use in stw.S */
+#define TIMER_ADDR (CM_BASE + 0x8050)
+
+/* Use in cps-vec.S */
+#define DRAM_ADDRESS 0x80000000
+#define DRAM_SIZE 0x80000000
+#define DRAM_PMP_ADDR ((DRAM_ADDRESS >> 2) | ((DRAM_SIZE - 1) >> 3))
+
+#endif
diff --git a/platform/generic/include/mips/mips-cm.h b/platform/generic/include/mips/mips-cm.h
new file mode 100644
index 0000000..19b4384
--- /dev/null
+++ b/platform/generic/include/mips/mips-cm.h
@@ -0,0 +1,88 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 MIPS
+ *
+ */
+
+#ifndef __MIPS_CM_H__
+#define __MIPS_CM_H__
+
+#include <mips/p8700.h>
+#include <sbi/sbi_console.h>
+
+/* Define 1 to print out CM read and write info */
+#define DEBUG_CM 0
+
+#if CLUSTERS_IN_PLATFORM > 1
+static long GLOBAL_CM_BASE[CLUSTERS_IN_PLATFORM] = {GLOBAL_CM_BASE0, GLOBAL_CM_BASE1, GLOBAL_CM_BASE2};
+#else
+static long GLOBAL_CM_BASE[CLUSTERS_IN_PLATFORM] = {CM_BASE};
+#endif
+
+#define CPS_ACCESSOR_R(unit, sz, base, off, name) \
+static inline u##sz read_##unit##_##name(u32 hartid, bool local_p) \
+{ \
+ u##sz value; \
+ long cmd_reg; \
+ int cl, co; \
+ cl = cpu_cluster(hartid); \
+ co = cpu_core(hartid); \
+ cmd_reg = (local_p ? (base) : ((base) - CM_BASE + GLOBAL_CM_BASE[cl])) \
+ + (co << CM_BASE_CORE_SHIFT) \
+ + off; \
+ if (DEBUG_CM) \
+ sbi_printf("CM READ%d cmd_reg=%lx\n", sz, cmd_reg); \
+ if (sz == 32) \
+ asm volatile("lw %0,0(%1)":"=r"(value):"r"(cmd_reg)); \
+ else if (sz == 64) \
+ asm volatile("ld %0,0(%1)":"=r"(value):"r"(cmd_reg)); \
+ asm volatile("fence"); \
+ return value; \
+}
+
+#define CPS_ACCESSOR_W(unit, sz, base, off, name) \
+static inline void write_##unit##_##name(u32 hartid, u##sz value, bool local_p) \
+{ \
+ long cmd_reg; \
+ int cl, co; \
+ cl = cpu_cluster(hartid); \
+ co = cpu_core(hartid); \
+ cmd_reg = (local_p ? (base) : ((base) - CM_BASE + GLOBAL_CM_BASE[cl])) \
+ + (co << CM_BASE_CORE_SHIFT) \
+ + off; \
+ if (DEBUG_CM) \
+ sbi_printf("CM WRITE%d cmd_reg=%lx value=%lx\n", sz, \
+ cmd_reg, (u64)value); \
+ if (sz == 32) \
+ asm volatile("sw %0,0(%1)"::"r"(value),"r"(cmd_reg)); \
+ else if (sz == 64) \
+ asm volatile("sd %0,0(%1)"::"r"(value),"r"(cmd_reg)); \
+ asm volatile("fence"); \
+}
+
+#define CPS_ACCESSOR_RW(unit, sz, base, off, name) \
+ CPS_ACCESSOR_R(unit, sz, base, off, name) \
+ CPS_ACCESSOR_W(unit, sz, base, off, name)
+
+#define CPC_CX_ACCESSOR_RW(sz, off, name) \
+ CPS_ACCESSOR_RW(cpc, sz, CPC_BASE, CPC_OFF_LOCAL + (off), co_##name)
+
+#define GCR_CX_ACCESSOR_RW(sz, off, name) \
+ CPS_ACCESSOR_RW(gcr, sz, CM_BASE, GCR_OFF_LOCAL + (off), co_##name)
+
+GCR_CX_ACCESSOR_RW(64, cpu_hart(hartid) << CM_BASE_HART_SHIFT, reset_base)
+GCR_CX_ACCESSOR_RW(32, GCR_CORE_COH_EN, coherence)
+
+CPC_CX_ACCESSOR_RW(32, CPC_Cx_VP_RUN, vp_run)
+CPC_CX_ACCESSOR_RW(32, CPC_Cx_VP_STOP, vp_stop)
+CPC_CX_ACCESSOR_RW(32, CPC_Cx_CMD, cmd)
+CPC_CX_ACCESSOR_RW(32, CPC_Cx_STAT_CONF, stat_conf)
+
+#define CPC_ACCESSOR_RW(sz, off, name) \
+ CPS_ACCESSOR_RW(cpc, sz, CPC_BASE, off, name)
+
+CPC_ACCESSOR_RW(32, CPC_PWRUP_CTL, pwrup_ctl)
+CPC_ACCESSOR_RW(32, CPC_CM_STAT_CONF, cm_stat_conf)
+
+#endif
diff --git a/platform/generic/include/mips/p8700.h b/platform/generic/include/mips/p8700.h
new file mode 100644
index 0000000..b02aaed
--- /dev/null
+++ b/platform/generic/include/mips/p8700.h
@@ -0,0 +1,113 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 MIPS
+ *
+ */
+
+#ifndef __P8700_H__
+#define __P8700_H__
+
+#include <mips/board.h>
+
+/* PMA */
+#define CSR_MIPSPMACFG0 0x7e0
+#define CSR_MIPSPMACFG1 0x7e1
+#define CSR_MIPSPMACFG2 0x7e2
+#define CSR_MIPSPMACFG3 0x7e3
+#define CSR_MIPSPMACFG4 0x7e4
+#define CSR_MIPSPMACFG5 0x7e5
+#define CSR_MIPSPMACFG6 0x7e6
+#define CSR_MIPSPMACFG7 0x7e7
+#define CSR_MIPSPMACFG8 0x7e8
+#define CSR_MIPSPMACFG9 0x7e9
+#define CSR_MIPSPMACFG10 0x7ea
+#define CSR_MIPSPMACFG11 0x7eb
+#define CSR_MIPSPMACFG12 0x7ec
+#define CSR_MIPSPMACFG13 0x7ed
+#define CSR_MIPSPMACFG14 0x7ee
+#define CSR_MIPSPMACFG15 0x7ef
+
+/* MIPS CCA */
+#define CCA_CACHE_ENABLE 0
+#define CCA_CACHE_DISABLE 2
+#define PMA_SPECULATION (1 << 3)
+
+/* MIPS CSR */
+#define CSR_MIPSTVEC 0x7c0
+#define CSR_MIPSCONFIG0 0x7d0
+#define CSR_MIPSCONFIG1 0x7d1
+#define CSR_MIPSCONFIG2 0x7d2
+#define CSR_MIPSCONFIG3 0x7d3
+#define CSR_MIPSCONFIG4 0x7d4
+#define CSR_MIPSCONFIG5 0x7d5
+#define CSR_MIPSCONFIG6 0x7d6
+#define CSR_MIPSCONFIG7 0x7d7
+#define CSR_MIPSCONFIG8 0x7d8
+#define CSR_MIPSCONFIG9 0x7d9
+#define CSR_MIPSCONFIG10 0x7da
+#define CSR_MIPSCONFIG11 0x7db
+
+#define MIPSCONFIG5_MTW 4
+
+#define GEN_MASK(h, l) (((1ul << ((h) + 1 - (l))) - 1) << (l))
+#define EXT(val, mask) (((val) & (mask)) >> (__builtin_ffs(mask) - 1))
+
+/*
+ * We allocate the number of bits to encode clusters, cores, and harts
+ * from the original mhartid to a new dense index.
+ */
+#define NUM_OF_BITS_FOR_CLUSTERS 4
+#define NUM_OF_BITS_FOR_CORES 12
+#define NUM_OF_BITS_FOR_HARTS 4
+
+/* To get the field from new/hashed mhartid */
+#define NEW_CLUSTER_SHIFT (NUM_OF_BITS_FOR_CORES + NUM_OF_BITS_FOR_HARTS)
+#define NEW_CLUSTER_MASK ((1 << NUM_OF_BITS_FOR_CLUSTERS) - 1)
+#define NEW_CORE_SHIFT NUM_OF_BITS_FOR_HARTS
+#define NEW_CORE_MASK ((1 << NUM_OF_BITS_FOR_CORES) - 1)
+#define NEW_HART_MASK ((1 << NUM_OF_BITS_FOR_HARTS) - 1)
+#define cpu_cluster(i) (((i) >> NEW_CLUSTER_SHIFT) & NEW_CLUSTER_MASK)
+#define cpu_core(i) (((i) >> NEW_CORE_SHIFT) & NEW_CORE_MASK)
+#define cpu_hart(i) ((i) & NEW_HART_MASK)
+
+#define CPC_BASE (CM_BASE + 0x8000)
+
+#define SIZE_FOR_CPC_MTIME 0x10000 /* The size must be 2^order */
+#define AIA_BASE (CM_BASE + 0x40000)
+#define SIZE_FOR_AIA_M_MODE 0x20000 /* The size must be 2^order */
+#define P8700_ALIGN 0x10000
+
+#define CM_BASE_HART_SHIFT 3
+#define CM_BASE_CORE_SHIFT 8
+#define CM_BASE_CLUSTER_SHIFT 19
+
+/* GCR Block offsets */
+#define GCR_OFF_LOCAL 0x2000
+
+#define GCR_BASE_OFFSET 0x0008
+#define GCR_CORE_COH_EN 0x00f8
+#define GCR_CORE_COH_EN_EN (0x1 << 0)
+
+#define L2_PFT_CONTROL_OFFSET 0x0300
+#define L2_PFT_CONTROL_B_OFFSET 0x0308
+
+/* CPC Block offsets */
+#define CPC_PWRUP_CTL 0x0030
+#define CPC_CM_STAT_CONF 0x1008
+
+#define CPC_OFF_LOCAL 0x2000
+
+#define CPC_Cx_VP_STOP 0x0020
+#define CPC_Cx_VP_RUN 0x0028
+#define CPC_Cx_CMD 0x0000
+
+#define CPC_Cx_CMD_PWRUP 0x3
+#define CPC_Cx_CMD_RESET 0x4
+
+#define CPC_Cx_STAT_CONF 0x0008
+#define CPC_Cx_STAT_CONF_SEQ_STATE GEN_MASK(22, 19)
+#define CPC_Cx_STAT_CONF_SEQ_STATE_U5 6
+#define CPC_Cx_STAT_CONF_SEQ_STATE_U6 7
+
+#endif
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 70+ messages in thread* [PATCH v5 03/10] platform: generic: mips: add an entry function
2025-02-12 12:27 ` Anup Patel
` (32 preceding siblings ...)
2025-05-19 21:58 ` [PATCH v5 02/10] platform: generic: mips: add header files Chao-ying Fu
@ 2025-05-19 21:58 ` Chao-ying Fu
2025-05-20 5:29 ` Anup Patel
2025-05-19 21:58 ` [PATCH v5 04/10] platform: generic: mips: add the platform file Chao-ying Fu
` (14 subsequent siblings)
48 siblings, 1 reply; 70+ messages in thread
From: Chao-ying Fu @ 2025-05-19 21:58 UTC (permalink / raw)
To: opensbi; +Cc: Chao-ying Fu
The entry function is minimum boot code for harts to execute after
reset, nmi, cache error, and debug exception.
Signed-off-by: Chao-ying Fu <cfu@mips.com>
---
platform/generic/mips/cps-vec.S | 75 +++++++++++++++++++++++++++++++++
1 file changed, 75 insertions(+)
create mode 100644 platform/generic/mips/cps-vec.S
diff --git a/platform/generic/mips/cps-vec.S b/platform/generic/mips/cps-vec.S
new file mode 100644
index 0000000..9309e20
--- /dev/null
+++ b/platform/generic/mips/cps-vec.S
@@ -0,0 +1,75 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 MIPS
+ *
+ */
+
+#include <sbi/riscv_encoding.h>
+#include <mips/p8700.h>
+
+ .text
+ .align 12
+ .globl mips_cps_core_entry
+mips_cps_core_entry:
+ j 1f
+
+ .align 2
+nmi_vector:
+ j 1f
+
+ .align 2
+cacheerr_vector:
+ j 1f
+
+ .align 2
+debugexc_vector:
+ j 1f
+
+ .align 2
+1:
+ li x1, 0
+ li x2, 0
+ li x3, 0
+ li x4, 0
+ li x5, 0
+ li x6, 0
+ li x7, 0
+ li x8, 0
+ li x9, 0
+ li x10, 0
+#ifdef FW_FDT_PATH
+ li x11, 0
+#endif
+ li x12, 0
+ li x13, 0
+ li x14, 0
+ li x15, 0
+ li x16, 0
+ li x17, 0
+ li x18, 0
+ li x19, 0
+ li x20, 0
+ li x21, 0
+ li x22, 0
+ li x23, 0
+ li x24, 0
+ li x25, 0
+ li x26, 0
+ li x27, 0
+ li x28, 0
+ li x29, 0
+ li x30, 0
+ li x31, 0
+
+ /* a0 has mhartid */
+ csrr a0, CSR_MHARTID
+
+ /* Let hart 0 jump to _start */
+ beqz a0, 1f
+ lla t0, _start_warm
+ jr t0
+1:
+ lla t0, _start
+ jr t0
+
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 70+ messages in thread* Re: [PATCH v5 03/10] platform: generic: mips: add an entry function
2025-05-19 21:58 ` [PATCH v5 03/10] platform: generic: mips: add an entry function Chao-ying Fu
@ 2025-05-20 5:29 ` Anup Patel
2025-05-22 20:50 ` Chao-ying Fu
0 siblings, 1 reply; 70+ messages in thread
From: Anup Patel @ 2025-05-20 5:29 UTC (permalink / raw)
To: Chao-ying Fu; +Cc: opensbi, Chao-ying Fu
On Tue, May 20, 2025 at 3:29 AM Chao-ying Fu <icebergfu@gmail.com> wrote:
>
> The entry function is minimum boot code for harts to execute after
> reset, nmi, cache error, and debug exception.
This does not belong in OpenSBI because it is the job of
previous booting stage to jump at the right entry point in
OpenSBI. The previous booting stage also has the
responsibility of passing the DTB/FDT address to OpenSBI.
Almost all RISC-V platforms have their own early boot
stage which boots before OpenSBI. Some of these RISCV
platforms also use U-Boot SPL as their early boot stage.
Regards,
Anup
>
> Signed-off-by: Chao-ying Fu <cfu@mips.com>
> ---
> platform/generic/mips/cps-vec.S | 75 +++++++++++++++++++++++++++++++++
> 1 file changed, 75 insertions(+)
> create mode 100644 platform/generic/mips/cps-vec.S
>
> diff --git a/platform/generic/mips/cps-vec.S b/platform/generic/mips/cps-vec.S
> new file mode 100644
> index 0000000..9309e20
> --- /dev/null
> +++ b/platform/generic/mips/cps-vec.S
> @@ -0,0 +1,75 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Copyright (c) 2025 MIPS
> + *
> + */
> +
> +#include <sbi/riscv_encoding.h>
> +#include <mips/p8700.h>
> +
> + .text
> + .align 12
> + .globl mips_cps_core_entry
> +mips_cps_core_entry:
> + j 1f
> +
> + .align 2
> +nmi_vector:
> + j 1f
> +
> + .align 2
> +cacheerr_vector:
> + j 1f
> +
> + .align 2
> +debugexc_vector:
> + j 1f
> +
> + .align 2
> +1:
> + li x1, 0
> + li x2, 0
> + li x3, 0
> + li x4, 0
> + li x5, 0
> + li x6, 0
> + li x7, 0
> + li x8, 0
> + li x9, 0
> + li x10, 0
> +#ifdef FW_FDT_PATH
> + li x11, 0
> +#endif
> + li x12, 0
> + li x13, 0
> + li x14, 0
> + li x15, 0
> + li x16, 0
> + li x17, 0
> + li x18, 0
> + li x19, 0
> + li x20, 0
> + li x21, 0
> + li x22, 0
> + li x23, 0
> + li x24, 0
> + li x25, 0
> + li x26, 0
> + li x27, 0
> + li x28, 0
> + li x29, 0
> + li x30, 0
> + li x31, 0
> +
> + /* a0 has mhartid */
> + csrr a0, CSR_MHARTID
> +
> + /* Let hart 0 jump to _start */
> + beqz a0, 1f
> + lla t0, _start_warm
> + jr t0
> +1:
> + lla t0, _start
> + jr t0
> +
> --
> 2.47.1
>
>
> --
> opensbi mailing list
> opensbi@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply [flat|nested] 70+ messages in thread
* Re: [PATCH v5 03/10] platform: generic: mips: add an entry function
2025-05-20 5:29 ` Anup Patel
@ 2025-05-22 20:50 ` Chao-ying Fu
0 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-05-22 20:50 UTC (permalink / raw)
To: Anup Patel; +Cc: opensbi, Chao-ying Fu
On Mon, May 19, 2025 at 10:29 PM Anup Patel <anup@brainfault.org> wrote:
>
> On Tue, May 20, 2025 at 3:29 AM Chao-ying Fu <icebergfu@gmail.com> wrote:
> >
> > The entry function is minimum boot code for harts to execute after
> > reset, nmi, cache error, and debug exception.
>
> This does not belong in OpenSBI because it is the job of
> previous booting stage to jump at the right entry point in
> OpenSBI. The previous booting stage also has the
> responsibility of passing the DTB/FDT address to OpenSBI.
>
> Almost all RISC-V platforms have their own early boot
> stage which boots before OpenSBI. Some of these RISCV
> platforms also use U-Boot SPL as their early boot stage.
>
> Regards,
> Anup
Yes, I will remove this file. Thanks!
NOTE: Andes has a similar mechanism to let harts boot to a new entry function.
.section .text, "ax", %progbits
.align 3
.global __ae350_enable_coherency_warmboot
__ae350_enable_coherency_warmboot:
call ra, __ae350_enable_coherency
j _start_warm
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply [flat|nested] 70+ messages in thread
* [PATCH v5 04/10] platform: generic: mips: add the platform file
2025-02-12 12:27 ` Anup Patel
` (33 preceding siblings ...)
2025-05-19 21:58 ` [PATCH v5 03/10] platform: generic: mips: add an entry function Chao-ying Fu
@ 2025-05-19 21:58 ` Chao-ying Fu
2025-05-19 21:58 ` [PATCH v5 05/10] platform: generic: mips: add a dts file Chao-ying Fu
` (13 subsequent siblings)
48 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-05-19 21:58 UTC (permalink / raw)
To: opensbi; +Cc: Chao-ying Fu
We add the platform file for MIPS P8700.
Signed-off-by: Chao-ying Fu <cfu@mips.com>
---
platform/generic/mips/p8700.c | 279 ++++++++++++++++++++++++++++++++++
1 file changed, 279 insertions(+)
create mode 100644 platform/generic/mips/p8700.c
diff --git a/platform/generic/mips/p8700.c b/platform/generic/mips/p8700.c
new file mode 100644
index 0000000..5f3c48a
--- /dev/null
+++ b/platform/generic/mips/p8700.c
@@ -0,0 +1,279 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 MIPS
+ *
+ */
+
+#include <platform_override.h>
+#include <sbi/riscv_barrier.h>
+#include <sbi/riscv_io.h>
+#include <sbi/sbi_domain.h>
+#include <sbi/sbi_error.h>
+#include <sbi/sbi_hsm.h>
+#include <sbi/sbi_timer.h>
+#include <sbi_utils/fdt/fdt_helper.h>
+#include <mips/p8700.h>
+#include <mips/mips-cm.h>
+
+extern void mips_cps_core_entry(void);
+
+#if CLUSTERS_IN_PLATFORM > 1
+static void power_up_other_cluster(u32 hartid)
+{
+ unsigned int stat;
+ unsigned int timeout;
+ bool local_p = (cpu_cluster(current_hartid()) == cpu_cluster(hartid));
+
+ /* Power up cluster cl core 0 hart 0 */
+ write_cpc_pwrup_ctl(hartid, 1, local_p);
+
+ /* Wait for the CM to start up */
+ timeout = 100;
+ while (true) {
+ stat = read_cpc_cm_stat_conf(hartid, local_p);
+ stat = EXT(stat, CPC_Cx_STAT_CONF_SEQ_STATE);
+ if (stat == CPC_Cx_STAT_CONF_SEQ_STATE_U5)
+ break;
+
+ /* Delay a little while before we start warning */
+ if (timeout) {
+ sbi_dprintf("Delay a little while before we start warning\n");
+ timeout--;
+ }
+ else {
+ sbi_printf("Waiting for cluster %u CM to power up... STAT_CONF=0x%x\n",
+ cpu_cluster(hartid), stat);
+ break;
+ }
+ }
+}
+#endif
+
+static int mips_hart_start(u32 hartid, ulong saddr)
+{
+ unsigned int stat;
+ unsigned int timeout;
+ bool local_p = (cpu_cluster(current_hartid()) == cpu_cluster(hartid));
+
+ /* Hart 0 is the boot hart, and we don't use the CPC cmd to start. */
+ if (hartid == 0)
+ return SBI_ENOTSUPP;
+
+ if (cpu_hart(hartid) == 0) {
+ /* Change cluster cl core co hart 0 reset base */
+ write_gcr_co_reset_base(hartid,
+ (unsigned long)mips_cps_core_entry, local_p);
+
+ /* Ensure its coherency is disabled */
+ write_gcr_co_coherence(hartid, 0, local_p);
+
+ /* Start cluster cl core co hart 0 */
+ write_cpc_co_vp_run(hartid, 1 << cpu_hart(hartid), local_p);
+
+ /* Reset cluster cl core co hart 0 */
+ write_cpc_co_cmd(hartid, CPC_Cx_CMD_RESET, local_p);
+
+ timeout = 100;
+ while (true) {
+ stat = read_cpc_co_stat_conf(hartid, local_p);
+ stat = EXT(stat, CPC_Cx_STAT_CONF_SEQ_STATE);
+ if (stat == CPC_Cx_STAT_CONF_SEQ_STATE_U6)
+ break;
+
+ /* Delay a little while before we start warning */
+ if (timeout) {
+ sbi_timer_mdelay(10);
+ timeout--;
+ }
+ else {
+ sbi_printf("Waiting for cluster %u core %u hart %u to start... STAT_CONF=0x%x\n",
+ cpu_cluster(hartid),
+ cpu_core(hartid), cpu_hart(hartid),
+ stat);
+ break;
+ }
+ }
+ }
+ else {
+ write_gcr_co_reset_base(hartid,
+ (unsigned long)mips_cps_core_entry, local_p);
+ write_cpc_co_vp_run(hartid, 1 << cpu_hart(hartid), local_p);
+ }
+
+ return 0;
+}
+
+static int mips_hart_stop()
+{
+ u32 hartid = current_hartid();
+ bool local_p = (cpu_cluster(current_hartid()) == cpu_cluster(hartid));
+
+ /* Hart 0 is the boot hart, and we don't use the CPC cmd to stop. */
+ if (hartid == 0)
+ return SBI_ENOTSUPP;
+
+ write_cpc_co_vp_stop(hartid, 1 << cpu_hart(hartid), local_p);
+
+ return 0;
+}
+
+static const struct sbi_hsm_device mips_hsm = {
+ .name = "mips_hsm",
+ .hart_start = mips_hart_start,
+ .hart_stop = mips_hart_stop,
+};
+
+static int mips_p8700_final_init(bool cold_boot)
+{
+ if (cold_boot)
+ sbi_hsm_set_device(&mips_hsm);
+
+ return generic_final_init(cold_boot);
+}
+
+static int mips_p8700_early_init(bool cold_boot)
+{
+ int rc;
+
+ rc = generic_early_init(cold_boot);
+ if (rc)
+ return rc;
+
+ if (cold_boot)
+ {
+#if CLUSTERS_IN_PLATFORM > 1
+ int i;
+ /* Power up other clusters in the platform. */
+ for (i = 1; i < CLUSTERS_IN_PLATFORM; i++) {
+ power_up_other_cluster(i << NEW_CLUSTER_SHIFT);
+ }
+#endif
+
+ /* For the CPC mtime region, the minimum size is 0x10000. */
+ rc = sbi_domain_root_add_memrange(CM_BASE, SIZE_FOR_CPC_MTIME,
+ P8700_ALIGN,
+ (SBI_DOMAIN_MEMREGION_MMIO |
+ SBI_DOMAIN_MEMREGION_M_READABLE |
+ SBI_DOMAIN_MEMREGION_M_WRITABLE));
+ if (rc)
+ return rc;
+
+ /* For the APLIC and ACLINT m-mode region */
+ rc = sbi_domain_root_add_memrange(AIA_BASE, SIZE_FOR_AIA_M_MODE,
+ P8700_ALIGN,
+ (SBI_DOMAIN_MEMREGION_MMIO |
+ SBI_DOMAIN_MEMREGION_M_READABLE |
+ SBI_DOMAIN_MEMREGION_M_WRITABLE));
+ if (rc)
+ return rc;
+
+#if CLUSTERS_IN_PLATFORM > 1
+ for (i = 0; i < CLUSTERS_IN_PLATFORM; i++) {
+ /* For the CPC mtime region, the minimum size is 0x10000. */
+ rc = sbi_domain_root_add_memrange(GLOBAL_CM_BASE[i], SIZE_FOR_CPC_MTIME,
+ P8700_ALIGN,
+ (SBI_DOMAIN_MEMREGION_MMIO |
+ SBI_DOMAIN_MEMREGION_M_READABLE |
+ SBI_DOMAIN_MEMREGION_M_WRITABLE));
+ if (rc)
+ return rc;
+
+ /* For the APLIC and ACLINT m-mode region */
+ rc = sbi_domain_root_add_memrange(AIA_BASE - CM_BASE + GLOBAL_CM_BASE[i], SIZE_FOR_AIA_M_MODE,
+ P8700_ALIGN,
+ (SBI_DOMAIN_MEMREGION_MMIO |
+ SBI_DOMAIN_MEMREGION_M_READABLE |
+ SBI_DOMAIN_MEMREGION_M_WRITABLE));
+ if (rc)
+ return rc;
+ }
+#endif
+ }
+
+ return 0;
+}
+
+static int mips_p8700_nascent_init(void)
+{
+ u64 hartid = current_hartid();
+ u64 cm_base = CM_BASE;
+ int i;
+
+ /* Coherence enable for every core */
+ if (cpu_hart(hartid) == 0) {
+ cm_base += (cpu_core(hartid) << CM_BASE_CORE_SHIFT);
+ __raw_writeq(GCR_CORE_COH_EN_EN,
+ (void *)(cm_base + GCR_OFF_LOCAL +
+ GCR_CORE_COH_EN));
+ mb();
+ }
+
+ /* Set up pmp for DRAM */
+ csr_write(CSR_PMPADDR14, DRAM_PMP_ADDR);
+ /* All from 0x0 */
+ csr_write(CSR_PMPADDR15, 0x1fffffffffffffff);
+ csr_write(CSR_PMPCFG2, ((PMP_A_NAPOT|PMP_R|PMP_W|PMP_X)<<56)|
+ ((PMP_A_NAPOT|PMP_R|PMP_W|PMP_X)<<48));
+ /* Set cacheable for pmp6, uncacheable for pmp7 */
+ csr_write(CSR_MIPSPMACFG2, ((u64)CCA_CACHE_DISABLE << 56)|
+ ((u64)CCA_CACHE_ENABLE << 48));
+ /* Reset pmpcfg0 */
+ csr_write(CSR_PMPCFG0, 0);
+ /* Reset pmacfg0 */
+ csr_write(CSR_MIPSPMACFG0, 0);
+ mb();
+
+ /* Per cluster set up */
+ if (cpu_core(hartid) == 0 && cpu_hart(hartid) == 0) {
+ /* Enable L2 prefetch */
+ __raw_writel(0xfffff110,
+ (void *)(cm_base + L2_PFT_CONTROL_OFFSET));
+ __raw_writel(0x15ff,
+ (void *)(cm_base + L2_PFT_CONTROL_B_OFFSET));
+ }
+
+ /* Per core set up */
+ if (cpu_hart(hartid) == 0) {
+ /* Enable load pair, store pair, and HTW */
+ csr_clear(CSR_MIPSCONFIG7, (1<<12)|(1<<13)|(1<<7));
+
+ /* Disable noRFO, misaligned load/store */
+ csr_set(CSR_MIPSCONFIG7, (1<<25)|(1<<9));
+
+ /* Enable L1-D$ Prefetch */
+ csr_write(CSR_MIPSCONFIG11, 0xff);
+
+ for (i = 0; i < 8; i++) {
+ csr_set(CSR_MIPSCONFIG8, 4 + 0x100 * i);
+ csr_set(CSR_MIPSCONFIG9, 8);
+ mb();
+ RISCV_FENCE_I;
+ }
+ }
+
+ /* Per hart set up */
+ /* Enable AMO and RDTIME illegal instruction exceptions. */
+ csr_set(CSR_MIPSCONFIG6, (1<<2)|(1<<1));
+
+ return 0;
+}
+
+static int mips_p8700_platform_init(const void *fdt, int nodeoff, const struct fdt_match *match)
+{
+ generic_platform_ops.early_init = mips_p8700_early_init;
+ generic_platform_ops.final_init = mips_p8700_final_init;
+ generic_platform_ops.nascent_init = mips_p8700_nascent_init;
+
+ return 0;
+}
+
+static const struct fdt_match mips_p8700_match[] = {
+ { .compatible = "mips,p8700" },
+ { },
+};
+
+const struct fdt_driver mips_p8700 = {
+ .match_table = mips_p8700_match,
+ .init = mips_p8700_platform_init,
+};
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 70+ messages in thread* [PATCH v5 05/10] platform: generic: mips: add a dts file
2025-02-12 12:27 ` Anup Patel
` (34 preceding siblings ...)
2025-05-19 21:58 ` [PATCH v5 04/10] platform: generic: mips: add the platform file Chao-ying Fu
@ 2025-05-19 21:58 ` Chao-ying Fu
2025-05-20 5:31 ` Anup Patel
2025-05-19 21:58 ` [PATCH v5 06/10] platform: generic: mips: add objects.mk Chao-ying Fu
` (12 subsequent siblings)
48 siblings, 1 reply; 70+ messages in thread
From: Chao-ying Fu @ 2025-05-19 21:58 UTC (permalink / raw)
To: opensbi; +Cc: Chao-ying Fu
We add a dts file for 4 cores 2 threads each on a Boston board.
Signed-off-by: Chao-ying Fu <cfu@mips.com>
---
platform/generic/mips/mips,boston-p8700.dts | 347 ++++++++++++++++++++
1 file changed, 347 insertions(+)
create mode 100644 platform/generic/mips/mips,boston-p8700.dts
diff --git a/platform/generic/mips/mips,boston-p8700.dts b/platform/generic/mips/mips,boston-p8700.dts
new file mode 100644
index 0000000..6da646c
--- /dev/null
+++ b/platform/generic/mips/mips,boston-p8700.dts
@@ -0,0 +1,347 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 MIPS
+ *
+ */
+
+/dts-v1/;
+
+#define CM_BASE 0x16100000
+#define APLIC_M_BASE (CM_BASE + 0x40000)
+#define APLIC_S_BASE (CM_BASE + 0x60000)
+#define MSWI_BASE (CM_BASE + 0x50000)
+#define MTIMER_BASE (MSWI_BASE + 0x4000)
+#define CPC_TIMER (CM_BASE + 0x8050)
+
+#define IRQ_TYPE_LEVEL_HIGH 4
+#define UART_INT 4
+#define PCIE2_INT 7
+
+#define BITFILE_FREQUENCY 25000000
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ model = "MIPS P8700";
+ compatible = "mips,p8700";
+
+ chosen {
+ stdout-path = &uart0;
+ // For Qemu
+ //bootargs = "root=/dev/sda rw earlycon console=ttyS0,115200n8r";
+ // For a Boston board
+ bootargs = "root=/dev/mmcblk0p5 rw rootwait earlycon console=ttyS0,115200n8r";
+
+ opensbi-domains {
+ compatible = "opensbi,domain,config";
+
+ tmem: tmem {
+ compatible = "opensbi,domain,memregion";
+ base = <0x0 0x80000000>;
+ order = <31>;
+ };
+
+ allmem: allmem {
+ compatible = "opensbi,domain,memregion";
+ base = <0x0 0x0>;
+ order = <64>;
+ };
+
+ tdomain: trusted-domain {
+ compatible = "opensbi,domain,instance";
+ possible-harts = <&cpu0 &cpu1 &cpu2 &cpu3 &cpu4 &cpu5 &cpu6 &cpu7>;
+ regions = <&tmem 0x3f>, <&allmem 0x3f>;
+ };
+ };
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ timebase-frequency = <BITFILE_FREQUENCY>;
+
+ cpu0: cpu@0 {
+ device_type = "cpu";
+ compatible = "riscv";
+ riscv,cbom-block-size = <64>;
+ opensbi-domain = <&tdomain>;
+ mmu-type = "riscv,sv39";
+ riscv,isa = "rv64imafdcsu";
+ status = "okay";
+ reg = <0x00000000>;
+
+ cpu0_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu1: cpu@1 {
+ device_type = "cpu";
+ compatible = "riscv";
+ riscv,cbom-block-size = <64>;
+ opensbi-domain = <&tdomain>;
+ mmu-type = "riscv,sv39";
+ riscv,isa = "rv64imafdcsu";
+ status = "okay";
+ reg = <0x00000001>;
+
+ cpu1_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu2: cpu@2 {
+ device_type = "cpu";
+ compatible = "riscv";
+ riscv,cbom-block-size = <64>;
+ opensbi-domain = <&tdomain>;
+ mmu-type = "riscv,sv39";
+ riscv,isa = "rv64imafdcsu";
+ status = "okay";
+ reg = <0x00000010>;
+
+ cpu2_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu3: cpu@3 {
+ device_type = "cpu";
+ compatible = "riscv";
+ riscv,cbom-block-size = <64>;
+ opensbi-domain = <&tdomain>;
+ mmu-type = "riscv,sv39";
+ riscv,isa = "rv64imafdcsu";
+ status = "okay";
+ reg = <0x00000011>;
+
+ cpu3_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu4: cpu@4 {
+ device_type = "cpu";
+ compatible = "riscv";
+ riscv,cbom-block-size = <64>;
+ opensbi-domain = <&tdomain>;
+ mmu-type = "riscv,sv39";
+ riscv,isa = "rv64imafdcsu";
+ status = "okay";
+ reg = <0x00000020>;
+
+ cpu4_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu5: cpu@5 {
+ device_type = "cpu";
+ compatible = "riscv";
+ riscv,cbom-block-size = <64>;
+ opensbi-domain = <&tdomain>;
+ mmu-type = "riscv,sv39";
+ riscv,isa = "rv64imafdcsu";
+ status = "okay";
+ reg = <0x00000021>;
+
+ cpu5_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu6: cpu@6 {
+ device_type = "cpu";
+ compatible = "riscv";
+ riscv,cbom-block-size = <64>;
+ opensbi-domain = <&tdomain>;
+ mmu-type = "riscv,sv39";
+ riscv,isa = "rv64imafdcsu";
+ status = "okay";
+ reg = <0x00000030>;
+
+ cpu6_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ cpu7: cpu@7 {
+ device_type = "cpu";
+ compatible = "riscv";
+ riscv,cbom-block-size = <64>;
+ opensbi-domain = <&tdomain>;
+ mmu-type = "riscv,sv39";
+ riscv,isa = "rv64imafdcsu";
+ status = "okay";
+ reg = <0x00000031>;
+
+ cpu7_intc: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x80000000 0x80000000>;
+ };
+
+ pci2: pci@14000000 {
+ compatible = "xlnx,axi-pcie-host-1.00.a";
+ device_type = "pci";
+ reg = <0x14000000 0x2000000>;
+
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+
+ interrupt-parent = <&aplic_s0>;
+ interrupts = <PCIE2_INT IRQ_TYPE_LEVEL_HIGH>;
+
+ ranges = <0x02000000 0 0x16000000
+ 0x16000000 0 0x100000>;
+
+ bus-range = <0x00 0xff>;
+
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &pci2_intc 1>,
+ <0 0 0 2 &pci2_intc 2>,
+ <0 0 0 3 &pci2_intc 3>,
+ <0 0 0 4 &pci2_intc 4>;
+
+ pci2_intc: interrupt-controller {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ };
+
+ pci2_root@0,0 {
+ compatible = "pci10ee,7021", "pci-bridge";
+ reg = <0x00000000 0 0 0 0>;
+
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+
+ eg20t_bridge@1,0,0 {
+ compatible = "pci8086,8800", "pci-bridge";
+ reg = <0x00010000 0 0 0 0>;
+
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+
+ eg20t_mac@2,0,1 {
+ compatible = "pci8086,8802", "intel,pch-gbe";
+ reg = <0x00020100 0 0 0 0>;
+ phy-reset-gpios = <&eg20t_gpio 6 1>;
+ };
+
+ eg20t_gpio: eg20t_gpio@2,0,2 {
+ compatible = "pci8086,8803", "intel,eg20t-gpio";
+ reg = <0x00020200 0 0 0 0>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ eg20t_i2c@2,12,2 {
+ compatible = "pci8086,8817";
+ reg = <0x00026200 0 0 0 0>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rtc@68 {
+ compatible = "st,m41t81s";
+ reg = <0x68>;
+ };
+ };
+ };
+ };
+ };
+
+ uart0: uart@17ffe000 {
+ compatible = "ns16550a";
+ reg = <0x17ffe000 0x1000>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+
+ interrupt-parent = <&aplic_s0>;
+ interrupts = <UART_INT IRQ_TYPE_LEVEL_HIGH>;
+
+ clock-frequency = <BITFILE_FREQUENCY>;
+
+ u-boot,dm-pre-reloc;
+ };
+
+ lcd: lcd@17fff000 {
+ compatible = "img,boston-lcd";
+ reg = <0x17fff000 0x8>;
+ };
+
+ flash@18000000 {
+ compatible = "cfi-flash";
+ reg = <0x18000000 0x8000000>;
+ bank-width = <2>;
+ };
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges;
+
+ aplic_s0: interrupt-controller@16160000 {
+ #interrupt-cells = <0x00000002>;
+ compatible = "riscv,aplic";
+ interrupt-controller;
+ interrupts-extended = <&cpu0_intc 9>, <&cpu1_intc 9>, <&cpu2_intc 9>, <&cpu3_intc 9>, <&cpu4_intc 9>, <&cpu5_intc 9>, <&cpu6_intc 9>, <&cpu7_intc 9>;
+ reg = <APLIC_S_BASE 0x00008000>;
+ riscv,num-sources = <0x00000035>;
+ };
+
+ aplic_m0: interrupt-controller@16140000 {
+ #interrupt-cells = <0x00000002>;
+ riscv,delegate = <&aplic_s0 0x00000001 0x00000035>;
+ riscv,children = <&aplic_s0>;
+ compatible = "riscv,aplic";
+ interrupt-controller;
+ interrupts-extended = <&cpu0_intc 11>, <&cpu1_intc 11>, <&cpu2_intc 11>, <&cpu3_intc 11>, <&cpu4_intc 11>, <&cpu5_intc 11>, <&cpu6_intc 11>, <&cpu7_intc 11>;
+ reg = <APLIC_M_BASE 0x00008000>;
+ riscv,num-sources = <0x00000035>;
+ };
+
+ mswi0: interrupt-controller@16150000 {
+ compatible = "riscv,aclint-mswi";
+ interrupts-extended = <&cpu0_intc 3>, <&cpu1_intc 3>, <&cpu2_intc 3>, <&cpu3_intc 3>, <&cpu4_intc 3>, <&cpu5_intc 3>, <&cpu6_intc 3>, <&cpu7_intc 3>;
+ reg = <MSWI_BASE 0x4000>;
+ interrupt-controller;
+ #interrupt-cells = <0>;
+ };
+
+ mtimer0: timer@16154000 {
+ compatible = "riscv,aclint-mtimer";
+ reg = <CPC_TIMER 0x8>,
+ <MTIMER_BASE 0x7ff8>;
+ interrupts-extended = <&cpu0_intc 7>, <&cpu1_intc 7>, <&cpu2_intc 7>, <&cpu3_intc 7>, <&cpu4_intc 7>, <&cpu5_intc 7>, <&cpu6_intc 7>, <&cpu7_intc 7>;
+ };
+ };
+};
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 70+ messages in thread* Re: [PATCH v5 05/10] platform: generic: mips: add a dts file
2025-05-19 21:58 ` [PATCH v5 05/10] platform: generic: mips: add a dts file Chao-ying Fu
@ 2025-05-20 5:31 ` Anup Patel
2025-05-22 20:52 ` Chao-ying Fu
0 siblings, 1 reply; 70+ messages in thread
From: Anup Patel @ 2025-05-20 5:31 UTC (permalink / raw)
To: Chao-ying Fu; +Cc: opensbi, Chao-ying Fu
On Tue, May 20, 2025 at 3:29 AM Chao-ying Fu <icebergfu@gmail.com> wrote:
>
> We add a dts file for 4 cores 2 threads each on a Boston board.
Even this should be part of your early boot stage before OpenSBI.
Regards,
Anup
>
> Signed-off-by: Chao-ying Fu <cfu@mips.com>
> ---
> platform/generic/mips/mips,boston-p8700.dts | 347 ++++++++++++++++++++
> 1 file changed, 347 insertions(+)
> create mode 100644 platform/generic/mips/mips,boston-p8700.dts
>
> diff --git a/platform/generic/mips/mips,boston-p8700.dts b/platform/generic/mips/mips,boston-p8700.dts
> new file mode 100644
> index 0000000..6da646c
> --- /dev/null
> +++ b/platform/generic/mips/mips,boston-p8700.dts
> @@ -0,0 +1,347 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Copyright (c) 2025 MIPS
> + *
> + */
> +
> +/dts-v1/;
> +
> +#define CM_BASE 0x16100000
> +#define APLIC_M_BASE (CM_BASE + 0x40000)
> +#define APLIC_S_BASE (CM_BASE + 0x60000)
> +#define MSWI_BASE (CM_BASE + 0x50000)
> +#define MTIMER_BASE (MSWI_BASE + 0x4000)
> +#define CPC_TIMER (CM_BASE + 0x8050)
> +
> +#define IRQ_TYPE_LEVEL_HIGH 4
> +#define UART_INT 4
> +#define PCIE2_INT 7
> +
> +#define BITFILE_FREQUENCY 25000000
> +
> +/ {
> + #address-cells = <1>;
> + #size-cells = <1>;
> + model = "MIPS P8700";
> + compatible = "mips,p8700";
> +
> + chosen {
> + stdout-path = &uart0;
> + // For Qemu
> + //bootargs = "root=/dev/sda rw earlycon console=ttyS0,115200n8r";
> + // For a Boston board
> + bootargs = "root=/dev/mmcblk0p5 rw rootwait earlycon console=ttyS0,115200n8r";
> +
> + opensbi-domains {
> + compatible = "opensbi,domain,config";
> +
> + tmem: tmem {
> + compatible = "opensbi,domain,memregion";
> + base = <0x0 0x80000000>;
> + order = <31>;
> + };
> +
> + allmem: allmem {
> + compatible = "opensbi,domain,memregion";
> + base = <0x0 0x0>;
> + order = <64>;
> + };
> +
> + tdomain: trusted-domain {
> + compatible = "opensbi,domain,instance";
> + possible-harts = <&cpu0 &cpu1 &cpu2 &cpu3 &cpu4 &cpu5 &cpu6 &cpu7>;
> + regions = <&tmem 0x3f>, <&allmem 0x3f>;
> + };
> + };
> + };
> +
> + cpus {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + timebase-frequency = <BITFILE_FREQUENCY>;
> +
> + cpu0: cpu@0 {
> + device_type = "cpu";
> + compatible = "riscv";
> + riscv,cbom-block-size = <64>;
> + opensbi-domain = <&tdomain>;
> + mmu-type = "riscv,sv39";
> + riscv,isa = "rv64imafdcsu";
> + status = "okay";
> + reg = <0x00000000>;
> +
> + cpu0_intc: interrupt-controller {
> + compatible = "riscv,cpu-intc";
> + interrupt-controller;
> + #interrupt-cells = <1>;
> + };
> + };
> +
> + cpu1: cpu@1 {
> + device_type = "cpu";
> + compatible = "riscv";
> + riscv,cbom-block-size = <64>;
> + opensbi-domain = <&tdomain>;
> + mmu-type = "riscv,sv39";
> + riscv,isa = "rv64imafdcsu";
> + status = "okay";
> + reg = <0x00000001>;
> +
> + cpu1_intc: interrupt-controller {
> + compatible = "riscv,cpu-intc";
> + interrupt-controller;
> + #interrupt-cells = <1>;
> + };
> + };
> +
> + cpu2: cpu@2 {
> + device_type = "cpu";
> + compatible = "riscv";
> + riscv,cbom-block-size = <64>;
> + opensbi-domain = <&tdomain>;
> + mmu-type = "riscv,sv39";
> + riscv,isa = "rv64imafdcsu";
> + status = "okay";
> + reg = <0x00000010>;
> +
> + cpu2_intc: interrupt-controller {
> + compatible = "riscv,cpu-intc";
> + interrupt-controller;
> + #interrupt-cells = <1>;
> + };
> + };
> +
> + cpu3: cpu@3 {
> + device_type = "cpu";
> + compatible = "riscv";
> + riscv,cbom-block-size = <64>;
> + opensbi-domain = <&tdomain>;
> + mmu-type = "riscv,sv39";
> + riscv,isa = "rv64imafdcsu";
> + status = "okay";
> + reg = <0x00000011>;
> +
> + cpu3_intc: interrupt-controller {
> + compatible = "riscv,cpu-intc";
> + interrupt-controller;
> + #interrupt-cells = <1>;
> + };
> + };
> +
> + cpu4: cpu@4 {
> + device_type = "cpu";
> + compatible = "riscv";
> + riscv,cbom-block-size = <64>;
> + opensbi-domain = <&tdomain>;
> + mmu-type = "riscv,sv39";
> + riscv,isa = "rv64imafdcsu";
> + status = "okay";
> + reg = <0x00000020>;
> +
> + cpu4_intc: interrupt-controller {
> + compatible = "riscv,cpu-intc";
> + interrupt-controller;
> + #interrupt-cells = <1>;
> + };
> + };
> +
> + cpu5: cpu@5 {
> + device_type = "cpu";
> + compatible = "riscv";
> + riscv,cbom-block-size = <64>;
> + opensbi-domain = <&tdomain>;
> + mmu-type = "riscv,sv39";
> + riscv,isa = "rv64imafdcsu";
> + status = "okay";
> + reg = <0x00000021>;
> +
> + cpu5_intc: interrupt-controller {
> + compatible = "riscv,cpu-intc";
> + interrupt-controller;
> + #interrupt-cells = <1>;
> + };
> + };
> +
> + cpu6: cpu@6 {
> + device_type = "cpu";
> + compatible = "riscv";
> + riscv,cbom-block-size = <64>;
> + opensbi-domain = <&tdomain>;
> + mmu-type = "riscv,sv39";
> + riscv,isa = "rv64imafdcsu";
> + status = "okay";
> + reg = <0x00000030>;
> +
> + cpu6_intc: interrupt-controller {
> + compatible = "riscv,cpu-intc";
> + interrupt-controller;
> + #interrupt-cells = <1>;
> + };
> + };
> +
> + cpu7: cpu@7 {
> + device_type = "cpu";
> + compatible = "riscv";
> + riscv,cbom-block-size = <64>;
> + opensbi-domain = <&tdomain>;
> + mmu-type = "riscv,sv39";
> + riscv,isa = "rv64imafdcsu";
> + status = "okay";
> + reg = <0x00000031>;
> +
> + cpu7_intc: interrupt-controller {
> + compatible = "riscv,cpu-intc";
> + interrupt-controller;
> + #interrupt-cells = <1>;
> + };
> + };
> + };
> +
> + memory@80000000 {
> + device_type = "memory";
> + reg = <0x80000000 0x80000000>;
> + };
> +
> + pci2: pci@14000000 {
> + compatible = "xlnx,axi-pcie-host-1.00.a";
> + device_type = "pci";
> + reg = <0x14000000 0x2000000>;
> +
> + #address-cells = <3>;
> + #size-cells = <2>;
> + #interrupt-cells = <1>;
> +
> + interrupt-parent = <&aplic_s0>;
> + interrupts = <PCIE2_INT IRQ_TYPE_LEVEL_HIGH>;
> +
> + ranges = <0x02000000 0 0x16000000
> + 0x16000000 0 0x100000>;
> +
> + bus-range = <0x00 0xff>;
> +
> + interrupt-map-mask = <0 0 0 7>;
> + interrupt-map = <0 0 0 1 &pci2_intc 1>,
> + <0 0 0 2 &pci2_intc 2>,
> + <0 0 0 3 &pci2_intc 3>,
> + <0 0 0 4 &pci2_intc 4>;
> +
> + pci2_intc: interrupt-controller {
> + interrupt-controller;
> + #address-cells = <0>;
> + #interrupt-cells = <1>;
> + };
> +
> + pci2_root@0,0 {
> + compatible = "pci10ee,7021", "pci-bridge";
> + reg = <0x00000000 0 0 0 0>;
> +
> + #address-cells = <3>;
> + #size-cells = <2>;
> + #interrupt-cells = <1>;
> +
> + eg20t_bridge@1,0,0 {
> + compatible = "pci8086,8800", "pci-bridge";
> + reg = <0x00010000 0 0 0 0>;
> +
> + #address-cells = <3>;
> + #size-cells = <2>;
> + #interrupt-cells = <1>;
> +
> + eg20t_mac@2,0,1 {
> + compatible = "pci8086,8802", "intel,pch-gbe";
> + reg = <0x00020100 0 0 0 0>;
> + phy-reset-gpios = <&eg20t_gpio 6 1>;
> + };
> +
> + eg20t_gpio: eg20t_gpio@2,0,2 {
> + compatible = "pci8086,8803", "intel,eg20t-gpio";
> + reg = <0x00020200 0 0 0 0>;
> +
> + gpio-controller;
> + #gpio-cells = <2>;
> + };
> +
> + eg20t_i2c@2,12,2 {
> + compatible = "pci8086,8817";
> + reg = <0x00026200 0 0 0 0>;
> +
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + rtc@68 {
> + compatible = "st,m41t81s";
> + reg = <0x68>;
> + };
> + };
> + };
> + };
> + };
> +
> + uart0: uart@17ffe000 {
> + compatible = "ns16550a";
> + reg = <0x17ffe000 0x1000>;
> + reg-shift = <2>;
> + reg-io-width = <4>;
> +
> + interrupt-parent = <&aplic_s0>;
> + interrupts = <UART_INT IRQ_TYPE_LEVEL_HIGH>;
> +
> + clock-frequency = <BITFILE_FREQUENCY>;
> +
> + u-boot,dm-pre-reloc;
> + };
> +
> + lcd: lcd@17fff000 {
> + compatible = "img,boston-lcd";
> + reg = <0x17fff000 0x8>;
> + };
> +
> + flash@18000000 {
> + compatible = "cfi-flash";
> + reg = <0x18000000 0x8000000>;
> + bank-width = <2>;
> + };
> +
> + soc {
> + #address-cells = <1>;
> + #size-cells = <1>;
> + compatible = "simple-bus";
> + ranges;
> +
> + aplic_s0: interrupt-controller@16160000 {
> + #interrupt-cells = <0x00000002>;
> + compatible = "riscv,aplic";
> + interrupt-controller;
> + interrupts-extended = <&cpu0_intc 9>, <&cpu1_intc 9>, <&cpu2_intc 9>, <&cpu3_intc 9>, <&cpu4_intc 9>, <&cpu5_intc 9>, <&cpu6_intc 9>, <&cpu7_intc 9>;
> + reg = <APLIC_S_BASE 0x00008000>;
> + riscv,num-sources = <0x00000035>;
> + };
> +
> + aplic_m0: interrupt-controller@16140000 {
> + #interrupt-cells = <0x00000002>;
> + riscv,delegate = <&aplic_s0 0x00000001 0x00000035>;
> + riscv,children = <&aplic_s0>;
> + compatible = "riscv,aplic";
> + interrupt-controller;
> + interrupts-extended = <&cpu0_intc 11>, <&cpu1_intc 11>, <&cpu2_intc 11>, <&cpu3_intc 11>, <&cpu4_intc 11>, <&cpu5_intc 11>, <&cpu6_intc 11>, <&cpu7_intc 11>;
> + reg = <APLIC_M_BASE 0x00008000>;
> + riscv,num-sources = <0x00000035>;
> + };
> +
> + mswi0: interrupt-controller@16150000 {
> + compatible = "riscv,aclint-mswi";
> + interrupts-extended = <&cpu0_intc 3>, <&cpu1_intc 3>, <&cpu2_intc 3>, <&cpu3_intc 3>, <&cpu4_intc 3>, <&cpu5_intc 3>, <&cpu6_intc 3>, <&cpu7_intc 3>;
> + reg = <MSWI_BASE 0x4000>;
> + interrupt-controller;
> + #interrupt-cells = <0>;
> + };
> +
> + mtimer0: timer@16154000 {
> + compatible = "riscv,aclint-mtimer";
> + reg = <CPC_TIMER 0x8>,
> + <MTIMER_BASE 0x7ff8>;
> + interrupts-extended = <&cpu0_intc 7>, <&cpu1_intc 7>, <&cpu2_intc 7>, <&cpu3_intc 7>, <&cpu4_intc 7>, <&cpu5_intc 7>, <&cpu6_intc 7>, <&cpu7_intc 7>;
> + };
> + };
> +};
> --
> 2.47.1
>
>
> --
> opensbi mailing list
> opensbi@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply [flat|nested] 70+ messages in thread
* [PATCH v5 06/10] platform: generic: mips: add objects.mk
2025-02-12 12:27 ` Anup Patel
` (35 preceding siblings ...)
2025-05-19 21:58 ` [PATCH v5 05/10] platform: generic: mips: add a dts file Chao-ying Fu
@ 2025-05-19 21:58 ` Chao-ying Fu
2025-05-19 21:58 ` [PATCH v5 07/10] Initialize MIPS custom PMA registers Chao-ying Fu
` (11 subsequent siblings)
48 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-05-19 21:58 UTC (permalink / raw)
To: opensbi; +Cc: Chao-ying Fu
We build MIPS files.
Signed-off-by: Chao-ying Fu <cfu@mips.com>
---
platform/generic/mips/objects.mk | 7 +++++++
1 file changed, 7 insertions(+)
create mode 100644 platform/generic/mips/objects.mk
diff --git a/platform/generic/mips/objects.mk b/platform/generic/mips/objects.mk
new file mode 100644
index 0000000..6b051c0
--- /dev/null
+++ b/platform/generic/mips/objects.mk
@@ -0,0 +1,7 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+
+carray-platform_override_modules-$(CONFIG_PLATFORM_MIPS_P8700) += mips_p8700
+platform-objs-$(CONFIG_PLATFORM_MIPS_P8700) += mips/p8700.o mips/cps-vec.o
+platform-dtb-$(CONFIG_PLATFORM_MIPS_P8700) += mips/mips,boston-p8700.dtb
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 70+ messages in thread* [PATCH v5 07/10] Initialize MIPS custom PMA registers
2025-02-12 12:27 ` Anup Patel
` (36 preceding siblings ...)
2025-05-19 21:58 ` [PATCH v5 06/10] platform: generic: mips: add objects.mk Chao-ying Fu
@ 2025-05-19 21:58 ` Chao-ying Fu
2025-05-20 5:08 ` Anup Patel
2025-05-19 21:58 ` [PATCH v5 08/10] devices to use MMIO memory Chao-ying Fu
` (10 subsequent siblings)
48 siblings, 1 reply; 70+ messages in thread
From: Chao-ying Fu @ 2025-05-19 21:58 UTC (permalink / raw)
To: opensbi; +Cc: Chao-ying Fu
Before PMP set up, we need to set up MIPS custom PMA registers
to have correct cacheable or uncacheable execution for pmp regions.
Signed-off-by: Chao-ying Fu <cfu@mips.com>
---
lib/sbi/riscv_asm.c | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/lib/sbi/riscv_asm.c b/lib/sbi/riscv_asm.c
index c7d75ac..7eb02cf 100644
--- a/lib/sbi/riscv_asm.c
+++ b/lib/sbi/riscv_asm.c
@@ -12,6 +12,9 @@
#include <sbi/sbi_error.h>
#include <sbi/sbi_platform.h>
#include <sbi/sbi_console.h>
+#ifdef CONFIG_PLATFORM_MIPS_P8700
+#include <mips/p8700.h>
+#endif
/* determine CPU extension, return non-zero support */
int misa_extension_imp(char ext)
@@ -119,6 +122,9 @@ unsigned long csr_read_num(int csr_num)
unsigned long ret = 0;
switch (csr_num) {
+#ifdef CONFIG_PLATFORM_MIPS_P8700
+ switchcase_csr_read_16(CSR_MIPSPMACFG0, ret)
+#endif
switchcase_csr_read_16(CSR_PMPCFG0, ret)
switchcase_csr_read_64(CSR_PMPADDR0, ret)
switchcase_csr_read(CSR_MCYCLE, ret)
@@ -199,6 +205,9 @@ void csr_write_num(int csr_num, unsigned long val)
switchcase_csr_write_32(__csr_num + 32, __val)
switch (csr_num) {
+#ifdef CONFIG_PLATFORM_MIPS_P8700
+ switchcase_csr_write_16(CSR_MIPSPMACFG0, val)
+#endif
switchcase_csr_write_16(CSR_PMPCFG0, val)
switchcase_csr_write_64(CSR_PMPADDR0, val)
switchcase_csr_write(CSR_MCYCLE, val)
@@ -301,6 +310,29 @@ int is_pmp_entry_mapped(unsigned long entry)
return false;
}
+#ifdef CONFIG_PLATFORM_MIPS_P8700
+extern unsigned long _fw_start;
+static void pma_set(unsigned int n, unsigned long addr)
+{
+ int pmacfg_csr, pmacfg_shift;
+ unsigned long cfgmask;
+ unsigned long pmacfg, cca;
+
+ pmacfg_csr = (CSR_MIPSPMACFG0 + (n >> 2)) & ~1;
+ pmacfg_shift = (n & 7) << 3;
+ cfgmask = ~(0xffUL << pmacfg_shift);
+
+ /* Read pmacfg to change cacheability */
+ pmacfg = (csr_read_num(pmacfg_csr) & cfgmask);
+ if (addr >= (unsigned long)&_fw_start)
+ cca = CCA_CACHE_ENABLE | PMA_SPECULATION;
+ else
+ cca = CCA_CACHE_DISABLE;
+ pmacfg |= ((cca << pmacfg_shift) & ~cfgmask);
+ csr_write_num(pmacfg_csr, pmacfg);
+}
+#endif
+
int pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
unsigned long log2len)
{
@@ -312,6 +344,10 @@ int pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
if (n >= PMP_COUNT || log2len > __riscv_xlen || log2len < PMP_SHIFT)
return SBI_EINVAL;
+#ifdef CONFIG_PLATFORM_MIPS_P8700
+ pma_set(n, addr);
+#endif
+
/* calculate PMP register and offset */
#if __riscv_xlen == 32
pmpcfg_csr = CSR_PMPCFG0 + (n >> 2);
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 70+ messages in thread* Re: [PATCH v5 07/10] Initialize MIPS custom PMA registers
2025-05-19 21:58 ` [PATCH v5 07/10] Initialize MIPS custom PMA registers Chao-ying Fu
@ 2025-05-20 5:08 ` Anup Patel
2025-05-22 20:47 ` Chao-ying Fu
0 siblings, 1 reply; 70+ messages in thread
From: Anup Patel @ 2025-05-20 5:08 UTC (permalink / raw)
To: Chao-ying Fu; +Cc: opensbi, Chao-ying Fu
On Tue, May 20, 2025 at 3:29 AM Chao-ying Fu <icebergfu@gmail.com> wrote:
>
> Before PMP set up, we need to set up MIPS custom PMA registers
> to have correct cacheable or uncacheable execution for pmp regions.
>
> Signed-off-by: Chao-ying Fu <cfu@mips.com>
This MIPS specific PMA programming has to be under platform/generic/mips/
Regards,
Anup
> ---
> lib/sbi/riscv_asm.c | 36 ++++++++++++++++++++++++++++++++++++
> 1 file changed, 36 insertions(+)
>
> diff --git a/lib/sbi/riscv_asm.c b/lib/sbi/riscv_asm.c
> index c7d75ac..7eb02cf 100644
> --- a/lib/sbi/riscv_asm.c
> +++ b/lib/sbi/riscv_asm.c
> @@ -12,6 +12,9 @@
> #include <sbi/sbi_error.h>
> #include <sbi/sbi_platform.h>
> #include <sbi/sbi_console.h>
> +#ifdef CONFIG_PLATFORM_MIPS_P8700
> +#include <mips/p8700.h>
> +#endif
>
> /* determine CPU extension, return non-zero support */
> int misa_extension_imp(char ext)
> @@ -119,6 +122,9 @@ unsigned long csr_read_num(int csr_num)
> unsigned long ret = 0;
>
> switch (csr_num) {
> +#ifdef CONFIG_PLATFORM_MIPS_P8700
> + switchcase_csr_read_16(CSR_MIPSPMACFG0, ret)
> +#endif
> switchcase_csr_read_16(CSR_PMPCFG0, ret)
> switchcase_csr_read_64(CSR_PMPADDR0, ret)
> switchcase_csr_read(CSR_MCYCLE, ret)
> @@ -199,6 +205,9 @@ void csr_write_num(int csr_num, unsigned long val)
> switchcase_csr_write_32(__csr_num + 32, __val)
>
> switch (csr_num) {
> +#ifdef CONFIG_PLATFORM_MIPS_P8700
> + switchcase_csr_write_16(CSR_MIPSPMACFG0, val)
> +#endif
> switchcase_csr_write_16(CSR_PMPCFG0, val)
> switchcase_csr_write_64(CSR_PMPADDR0, val)
> switchcase_csr_write(CSR_MCYCLE, val)
> @@ -301,6 +310,29 @@ int is_pmp_entry_mapped(unsigned long entry)
> return false;
> }
>
> +#ifdef CONFIG_PLATFORM_MIPS_P8700
> +extern unsigned long _fw_start;
> +static void pma_set(unsigned int n, unsigned long addr)
> +{
> + int pmacfg_csr, pmacfg_shift;
> + unsigned long cfgmask;
> + unsigned long pmacfg, cca;
> +
> + pmacfg_csr = (CSR_MIPSPMACFG0 + (n >> 2)) & ~1;
> + pmacfg_shift = (n & 7) << 3;
> + cfgmask = ~(0xffUL << pmacfg_shift);
> +
> + /* Read pmacfg to change cacheability */
> + pmacfg = (csr_read_num(pmacfg_csr) & cfgmask);
> + if (addr >= (unsigned long)&_fw_start)
> + cca = CCA_CACHE_ENABLE | PMA_SPECULATION;
> + else
> + cca = CCA_CACHE_DISABLE;
> + pmacfg |= ((cca << pmacfg_shift) & ~cfgmask);
> + csr_write_num(pmacfg_csr, pmacfg);
> +}
> +#endif
> +
> int pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
> unsigned long log2len)
> {
> @@ -312,6 +344,10 @@ int pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
> if (n >= PMP_COUNT || log2len > __riscv_xlen || log2len < PMP_SHIFT)
> return SBI_EINVAL;
>
> +#ifdef CONFIG_PLATFORM_MIPS_P8700
> + pma_set(n, addr);
> +#endif
> +
> /* calculate PMP register and offset */
> #if __riscv_xlen == 32
> pmpcfg_csr = CSR_PMPCFG0 + (n >> 2);
> --
> 2.47.1
>
>
> --
> opensbi mailing list
> opensbi@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply [flat|nested] 70+ messages in thread* Re: [PATCH v5 07/10] Initialize MIPS custom PMA registers
2025-05-20 5:08 ` Anup Patel
@ 2025-05-22 20:47 ` Chao-ying Fu
0 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-05-22 20:47 UTC (permalink / raw)
To: Anup Patel; +Cc: opensbi, Chao-ying Fu
On Mon, May 19, 2025 at 10:09 PM Anup Patel <anup@brainfault.org> wrote:
>
> On Tue, May 20, 2025 at 3:29 AM Chao-ying Fu <icebergfu@gmail.com> wrote:
> >
> > Before PMP set up, we need to set up MIPS custom PMA registers
> > to have correct cacheable or uncacheable execution for pmp regions.
> >
> > Signed-off-by: Chao-ying Fu <cfu@mips.com>
>
> This MIPS specific PMA programming has to be under platform/generic/mips/
>
> Regards,
> Anup
Yes, I will move code to MIPS p8700.c and will add a platform pma_set
function to let platforms implement their own versions (if needed).
Thanks a lot!
Regards,
Chao-ying
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply [flat|nested] 70+ messages in thread
* [PATCH v5 08/10] devices to use MMIO memory
2025-02-12 12:27 ` Anup Patel
` (37 preceding siblings ...)
2025-05-19 21:58 ` [PATCH v5 07/10] Initialize MIPS custom PMA registers Chao-ying Fu
@ 2025-05-19 21:58 ` Chao-ying Fu
2025-05-19 21:58 ` [PATCH v5 09/10] platform: generic: mips: add mmio to allmem in the dts file Chao-ying Fu
` (9 subsequent siblings)
48 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-05-19 21:58 UTC (permalink / raw)
To: opensbi; +Cc: Vladimir Kondratiev
From: Vladimir Kondratiev <vladimir.kondratiev@mobileye.com>
When applying FDT fixups, request device memory to be of
MMIO type
Signed-off-by: Vladimir Kondratiev <vladimir.kondratiev@mobileye.com>
---
lib/utils/fdt/fdt_fixup.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/utils/fdt/fdt_fixup.c b/lib/utils/fdt/fdt_fixup.c
index e237dd0..aa64977 100644
--- a/lib/utils/fdt/fdt_fixup.c
+++ b/lib/utils/fdt/fdt_fixup.c
@@ -154,7 +154,7 @@ static void fdt_domain_based_fixup_one(void *fdt, int nodeoff)
return;
if (!sbi_domain_check_addr(dom, reg_addr, dom->next_mode,
- SBI_DOMAIN_READ | SBI_DOMAIN_WRITE)) {
+ SBI_DOMAIN_READ | SBI_DOMAIN_WRITE | SBI_DOMAIN_MMIO)) {
rc = fdt_open_into(fdt, fdt, fdt_totalsize(fdt) + 32);
if (rc < 0)
return;
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 70+ messages in thread* [PATCH v5 09/10] platform: generic: mips: add mmio to allmem in the dts file
2025-02-12 12:27 ` Anup Patel
` (38 preceding siblings ...)
2025-05-19 21:58 ` [PATCH v5 08/10] devices to use MMIO memory Chao-ying Fu
@ 2025-05-19 21:58 ` Chao-ying Fu
2025-05-19 21:58 ` [PATCH v5 10/10] Fix PMA init for MMIO regions Chao-ying Fu
` (8 subsequent siblings)
48 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-05-19 21:58 UTC (permalink / raw)
To: opensbi; +Cc: Chao-ying Fu
After we change the fdt fixup to check mmio, we let the aplic_s node
be still there by adding mmio to allmem.
Signed-off-by: Chao-ying Fu <cfu@mips.com>
---
platform/generic/mips/mips,boston-p8700.dts | 1 +
1 file changed, 1 insertion(+)
diff --git a/platform/generic/mips/mips,boston-p8700.dts b/platform/generic/mips/mips,boston-p8700.dts
index 6da646c..dd1bae5 100644
--- a/platform/generic/mips/mips,boston-p8700.dts
+++ b/platform/generic/mips/mips,boston-p8700.dts
@@ -46,6 +46,7 @@
compatible = "opensbi,domain,memregion";
base = <0x0 0x0>;
order = <64>;
+ mmio;
};
tdomain: trusted-domain {
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 70+ messages in thread* [PATCH v5 10/10] Fix PMA init for MMIO regions
2025-02-12 12:27 ` Anup Patel
` (39 preceding siblings ...)
2025-05-19 21:58 ` [PATCH v5 09/10] platform: generic: mips: add mmio to allmem in the dts file Chao-ying Fu
@ 2025-05-19 21:58 ` Chao-ying Fu
2025-05-22 21:21 ` [MIPS P8700 v6 0/7] Add MIPS P8700 support to generic platform Chao-ying Fu
` (7 subsequent siblings)
48 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-05-19 21:58 UTC (permalink / raw)
To: opensbi; +Cc: Vladimir Kondratiev
From: Vladimir Kondratiev <vladimir.kondratiev@mobileye.com>
Convey MMIO flag as specified by SBI_DOMAIN_MEMREGION_MMIO
to the pma_set(); use this flag to decide upon memory cacheability
Introduce non-architecture bit PMP_MMIO for this new flag, have it
out of valid bit mask for the PMPCFG register to avoid side effects
Signed-off-by: Vladimir Kondratiev <vladimir.kondratiev@mobileye.com>
---
include/sbi/riscv_asm.h | 2 ++
lib/sbi/riscv_asm.c | 10 +++-------
lib/sbi/sbi_hart.c | 13 +++++++++++++
3 files changed, 18 insertions(+), 7 deletions(-)
diff --git a/include/sbi/riscv_asm.h b/include/sbi/riscv_asm.h
index ef48dc8..1bb2be7 100644
--- a/include/sbi/riscv_asm.h
+++ b/include/sbi/riscv_asm.h
@@ -215,6 +215,8 @@ int pmp_disable(unsigned int n);
/* Check if the matching field is set */
int is_pmp_entry_mapped(unsigned long entry);
+#define PMP_MMIO _UL(0x100)
+
int pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
unsigned long log2len);
diff --git a/lib/sbi/riscv_asm.c b/lib/sbi/riscv_asm.c
index 7eb02cf..9f31c3e 100644
--- a/lib/sbi/riscv_asm.c
+++ b/lib/sbi/riscv_asm.c
@@ -311,8 +311,7 @@ int is_pmp_entry_mapped(unsigned long entry)
}
#ifdef CONFIG_PLATFORM_MIPS_P8700
-extern unsigned long _fw_start;
-static void pma_set(unsigned int n, unsigned long addr)
+static void pma_set(unsigned int n, unsigned long prot, unsigned long addr)
{
int pmacfg_csr, pmacfg_shift;
unsigned long cfgmask;
@@ -324,10 +323,7 @@ static void pma_set(unsigned int n, unsigned long addr)
/* Read pmacfg to change cacheability */
pmacfg = (csr_read_num(pmacfg_csr) & cfgmask);
- if (addr >= (unsigned long)&_fw_start)
- cca = CCA_CACHE_ENABLE | PMA_SPECULATION;
- else
- cca = CCA_CACHE_DISABLE;
+ cca = (prot & PMP_MMIO) ? CCA_CACHE_DISABLE : CCA_CACHE_ENABLE | PMA_SPECULATION;
pmacfg |= ((cca << pmacfg_shift) & ~cfgmask);
csr_write_num(pmacfg_csr, pmacfg);
}
@@ -345,7 +341,7 @@ int pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
return SBI_EINVAL;
#ifdef CONFIG_PLATFORM_MIPS_P8700
- pma_set(n, addr);
+ pma_set(n, prot, addr);
#endif
/* calculate PMP register and offset */
diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c
index fc4925b..ab56890 100644
--- a/lib/sbi/sbi_hart.c
+++ b/lib/sbi/sbi_hart.c
@@ -361,6 +361,13 @@ static unsigned int sbi_hart_get_smepmp_flags(struct sbi_scratch *scratch,
pmp_flags |= PMP_X;
}
+ /*
+ * indicate whether it is MMIO, to be evaluated by code,
+ * out of pmpcfg mask
+ */
+ if (reg->flags & SBI_DOMAIN_MEMREGION_MMIO)
+ pmp_flags |= PMP_MMIO;
+
return pmp_flags;
}
@@ -489,6 +496,12 @@ static int sbi_hart_oldpmp_configure(struct sbi_scratch *scratch,
pmp_flags |= PMP_W;
if (reg->flags & SBI_DOMAIN_MEMREGION_SU_EXECUTABLE)
pmp_flags |= PMP_X;
+ /*
+ * indicate whether it is MMIO, to be evaluated by code,
+ * out of pmpcfg mask
+ */
+ if (reg->flags & SBI_DOMAIN_MEMREGION_MMIO)
+ pmp_flags |= PMP_MMIO;
pmp_addr = reg->base >> PMP_SHIFT;
if (pmp_log2gran <= reg->order && pmp_addr < pmp_addr_max) {
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 70+ messages in thread* [MIPS P8700 v6 0/7] Add MIPS P8700 support to generic platform
2025-02-12 12:27 ` Anup Patel
` (40 preceding siblings ...)
2025-05-19 21:58 ` [PATCH v5 10/10] Fix PMA init for MMIO regions Chao-ying Fu
@ 2025-05-22 21:21 ` Chao-ying Fu
2025-06-14 16:18 ` Anup Patel
2025-05-22 21:21 ` [MIPS P8700 v6 1/7] platform: generic: mips: add P8700 Chao-ying Fu
` (6 subsequent siblings)
48 siblings, 1 reply; 70+ messages in thread
From: Chao-ying Fu @ 2025-05-22 21:21 UTC (permalink / raw)
To: opensbi; +Cc: Chao-ying Fu
---
Changes in v6:
Drop the dts file.
Drop the entry function.
Add a new platform pma_set function.
Move PMA code to MIPS p8700.c.
Changes in v5:
Drop the amo emulation code.
Change to use macros to insert instructions in p8700.c.
Add 3 new patches to recognize mmio regions and set up cacheability based on
mmio regions.
Changes in v4:
Remove code that overrides nascent_init.
Update p8700.c to work with the latest override.
Use csr_set for mipsconfig6 in p8700.c.
Add riscv,cbom-block-size to the dts file.
Changes in v3:
Remove stw.s, stw.h, and extra scratch space.
Use nascent_init to initialze MIPS CSRs.
Add amo emulation via illegal instruction exceptions.
Change to use AMO and RDTIME illegal instruction exceptions.
Revise the dts file.
Remove code that jumps to mips_cps_core_entry.
Changes in v2:
Break up one patch to 11 patches.
Changes in v1:
Original code.
---
Chao-ying Fu (5):
platform: generic: mips: add P8700
platform: generic: mips: add header files
platform: generic: mips: add the platform file
platform: generic: mips: add objects.mk
lib: sbi_platform: Add the platform pma_set function to set up
cacheability
Vladimir Kondratiev (2):
devices to use MMIO memory
Convey MMIO flag as specified by SBI_DOMAIN_MEMREGION_MMIO
include/sbi/riscv_asm.h | 2 +
include/sbi/sbi_platform.h | 19 ++
lib/sbi/riscv_asm.c | 3 +
lib/sbi/sbi_hart.c | 13 +
lib/utils/fdt/fdt_fixup.c | 2 +-
platform/generic/Kconfig | 4 +
platform/generic/configs/defconfig | 1 +
platform/generic/include/mips/board.h | 33 +++
platform/generic/include/mips/mips-cm.h | 88 ++++++
platform/generic/include/mips/p8700.h | 113 ++++++++
platform/generic/mips/objects.mk | 6 +
platform/generic/mips/p8700.c | 361 ++++++++++++++++++++++++
12 files changed, 644 insertions(+), 1 deletion(-)
create mode 100644 platform/generic/include/mips/board.h
create mode 100644 platform/generic/include/mips/mips-cm.h
create mode 100644 platform/generic/include/mips/p8700.h
create mode 100644 platform/generic/mips/objects.mk
create mode 100644 platform/generic/mips/p8700.c
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply [flat|nested] 70+ messages in thread* Re: [MIPS P8700 v6 0/7] Add MIPS P8700 support to generic platform
2025-05-22 21:21 ` [MIPS P8700 v6 0/7] Add MIPS P8700 support to generic platform Chao-ying Fu
@ 2025-06-14 16:18 ` Anup Patel
0 siblings, 0 replies; 70+ messages in thread
From: Anup Patel @ 2025-06-14 16:18 UTC (permalink / raw)
To: Chao-ying Fu; +Cc: opensbi, Chao-ying Fu
On Fri, May 23, 2025 at 2:51 AM Chao-ying Fu <icebergfu@gmail.com> wrote:
>
> ---
> Changes in v6:
> Drop the dts file.
> Drop the entry function.
> Add a new platform pma_set function.
> Move PMA code to MIPS p8700.c.
>
> Changes in v5:
> Drop the amo emulation code.
> Change to use macros to insert instructions in p8700.c.
> Add 3 new patches to recognize mmio regions and set up cacheability based on
> mmio regions.
>
> Changes in v4:
> Remove code that overrides nascent_init.
> Update p8700.c to work with the latest override.
> Use csr_set for mipsconfig6 in p8700.c.
> Add riscv,cbom-block-size to the dts file.
>
> Changes in v3:
> Remove stw.s, stw.h, and extra scratch space.
> Use nascent_init to initialze MIPS CSRs.
> Add amo emulation via illegal instruction exceptions.
> Change to use AMO and RDTIME illegal instruction exceptions.
> Revise the dts file.
> Remove code that jumps to mips_cps_core_entry.
>
> Changes in v2:
> Break up one patch to 11 patches.
>
> Changes in v1:
> Original code.
> ---
>
> Chao-ying Fu (5):
> platform: generic: mips: add P8700
> platform: generic: mips: add header files
> platform: generic: mips: add the platform file
> platform: generic: mips: add objects.mk
> lib: sbi_platform: Add the platform pma_set function to set up
> cacheability
>
> Vladimir Kondratiev (2):
> devices to use MMIO memory
> Convey MMIO flag as specified by SBI_DOMAIN_MEMREGION_MMIO
>
> include/sbi/riscv_asm.h | 2 +
> include/sbi/sbi_platform.h | 19 ++
> lib/sbi/riscv_asm.c | 3 +
> lib/sbi/sbi_hart.c | 13 +
> lib/utils/fdt/fdt_fixup.c | 2 +-
> platform/generic/Kconfig | 4 +
> platform/generic/configs/defconfig | 1 +
> platform/generic/include/mips/board.h | 33 +++
> platform/generic/include/mips/mips-cm.h | 88 ++++++
> platform/generic/include/mips/p8700.h | 113 ++++++++
> platform/generic/mips/objects.mk | 6 +
> platform/generic/mips/p8700.c | 361 ++++++++++++++++++++++++
> 12 files changed, 644 insertions(+), 1 deletion(-)
> create mode 100644 platform/generic/include/mips/board.h
> create mode 100644 platform/generic/include/mips/mips-cm.h
> create mode 100644 platform/generic/include/mips/p8700.h
> create mode 100644 platform/generic/mips/objects.mk
> create mode 100644 platform/generic/mips/p8700.c
>
I have squashed the first 4 patches into one patch and applied
to the riscv/opensbi repo. I have also made sure that p8700
only compiles for RV64 because it does not compile for RV32.
The remaining three patches need more reviews.
Thanks,
Anup
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply [flat|nested] 70+ messages in thread
* [MIPS P8700 v6 1/7] platform: generic: mips: add P8700
2025-02-12 12:27 ` Anup Patel
` (41 preceding siblings ...)
2025-05-22 21:21 ` [MIPS P8700 v6 0/7] Add MIPS P8700 support to generic platform Chao-ying Fu
@ 2025-05-22 21:21 ` Chao-ying Fu
2025-05-22 21:21 ` [MIPS P8700 v6 2/7] platform: generic: mips: add header files Chao-ying Fu
` (5 subsequent siblings)
48 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-05-22 21:21 UTC (permalink / raw)
To: opensbi; +Cc: Chao-ying Fu
Add a new config first.
Signed-off-by: Chao-ying Fu <cfu@mips.com>
---
platform/generic/Kconfig | 4 ++++
platform/generic/configs/defconfig | 1 +
2 files changed, 5 insertions(+)
diff --git a/platform/generic/Kconfig b/platform/generic/Kconfig
index 688da3f..a24d6ab 100644
--- a/platform/generic/Kconfig
+++ b/platform/generic/Kconfig
@@ -68,6 +68,10 @@ config PLATFORM_THEAD
select THEAD_C9XX_PMU
default n
+config PLATFORM_MIPS_P8700
+ bool "MIPS P8700 support"
+ default n
+
source "$(OPENSBI_SRC_DIR)/platform/generic/andes/Kconfig"
source "$(OPENSBI_SRC_DIR)/platform/generic/thead/Kconfig"
diff --git a/platform/generic/configs/defconfig b/platform/generic/configs/defconfig
index bb26062..ce1f1ae 100644
--- a/platform/generic/configs/defconfig
+++ b/platform/generic/configs/defconfig
@@ -6,6 +6,7 @@ CONFIG_PLATFORM_SIFIVE_FU740=y
CONFIG_PLATFORM_SOPHGO_SG2042=y
CONFIG_PLATFORM_STARFIVE_JH7110=y
CONFIG_PLATFORM_THEAD=y
+CONFIG_PLATFORM_MIPS_P8700=n
CONFIG_FDT_CPPC=y
CONFIG_FDT_CPPC_RPMI=y
CONFIG_FDT_GPIO=y
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 70+ messages in thread* [MIPS P8700 v6 2/7] platform: generic: mips: add header files
2025-02-12 12:27 ` Anup Patel
` (42 preceding siblings ...)
2025-05-22 21:21 ` [MIPS P8700 v6 1/7] platform: generic: mips: add P8700 Chao-ying Fu
@ 2025-05-22 21:21 ` Chao-ying Fu
2025-05-22 21:21 ` [MIPS P8700 v6 3/7] platform: generic: mips: add the platform file Chao-ying Fu
` (4 subsequent siblings)
48 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-05-22 21:21 UTC (permalink / raw)
To: opensbi; +Cc: Chao-ying Fu
Add header files to define MIPS Custom CSRs and define for the board.
Add accessor functions for MIPS CM registers.
Signed-off-by: Chao-ying Fu <cfu@mips.com>
---
platform/generic/include/mips/board.h | 33 +++++++
platform/generic/include/mips/mips-cm.h | 88 ++++++++++++++++++
platform/generic/include/mips/p8700.h | 113 ++++++++++++++++++++++++
3 files changed, 234 insertions(+)
create mode 100644 platform/generic/include/mips/board.h
create mode 100644 platform/generic/include/mips/mips-cm.h
create mode 100644 platform/generic/include/mips/p8700.h
diff --git a/platform/generic/include/mips/board.h b/platform/generic/include/mips/board.h
new file mode 100644
index 0000000..6fe7b8b
--- /dev/null
+++ b/platform/generic/include/mips/board.h
@@ -0,0 +1,33 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 MIPS
+ *
+ */
+
+#ifndef __BOARD_H__
+#define __BOARD_H__
+
+/* Please review all defines to change for your board. */
+
+/* Use in stw.S, p8700.c, p8700.h, mips-cm.h */
+#define CM_BASE 0x16100000
+
+/* Use in mips-cm.h, p8700.c */
+#define CLUSTERS_IN_PLATFORM 1
+#if CLUSTERS_IN_PLATFORM > 1
+/* Define global CM bases for cluster 0, 1, 2, and more. */
+#define GLOBAL_CM_BASE0 0
+#define GLOBAL_CM_BASE1 0
+#define GLOBAL_CM_BASE2 0
+#endif
+
+/* Use in stw.S */
+#define TIMER_ADDR (CM_BASE + 0x8050)
+
+/* Use in cps-vec.S */
+#define DRAM_ADDRESS 0x80000000
+#define DRAM_SIZE 0x80000000
+#define DRAM_PMP_ADDR ((DRAM_ADDRESS >> 2) | ((DRAM_SIZE - 1) >> 3))
+
+#endif
diff --git a/platform/generic/include/mips/mips-cm.h b/platform/generic/include/mips/mips-cm.h
new file mode 100644
index 0000000..19b4384
--- /dev/null
+++ b/platform/generic/include/mips/mips-cm.h
@@ -0,0 +1,88 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 MIPS
+ *
+ */
+
+#ifndef __MIPS_CM_H__
+#define __MIPS_CM_H__
+
+#include <mips/p8700.h>
+#include <sbi/sbi_console.h>
+
+/* Define 1 to print out CM read and write info */
+#define DEBUG_CM 0
+
+#if CLUSTERS_IN_PLATFORM > 1
+static long GLOBAL_CM_BASE[CLUSTERS_IN_PLATFORM] = {GLOBAL_CM_BASE0, GLOBAL_CM_BASE1, GLOBAL_CM_BASE2};
+#else
+static long GLOBAL_CM_BASE[CLUSTERS_IN_PLATFORM] = {CM_BASE};
+#endif
+
+#define CPS_ACCESSOR_R(unit, sz, base, off, name) \
+static inline u##sz read_##unit##_##name(u32 hartid, bool local_p) \
+{ \
+ u##sz value; \
+ long cmd_reg; \
+ int cl, co; \
+ cl = cpu_cluster(hartid); \
+ co = cpu_core(hartid); \
+ cmd_reg = (local_p ? (base) : ((base) - CM_BASE + GLOBAL_CM_BASE[cl])) \
+ + (co << CM_BASE_CORE_SHIFT) \
+ + off; \
+ if (DEBUG_CM) \
+ sbi_printf("CM READ%d cmd_reg=%lx\n", sz, cmd_reg); \
+ if (sz == 32) \
+ asm volatile("lw %0,0(%1)":"=r"(value):"r"(cmd_reg)); \
+ else if (sz == 64) \
+ asm volatile("ld %0,0(%1)":"=r"(value):"r"(cmd_reg)); \
+ asm volatile("fence"); \
+ return value; \
+}
+
+#define CPS_ACCESSOR_W(unit, sz, base, off, name) \
+static inline void write_##unit##_##name(u32 hartid, u##sz value, bool local_p) \
+{ \
+ long cmd_reg; \
+ int cl, co; \
+ cl = cpu_cluster(hartid); \
+ co = cpu_core(hartid); \
+ cmd_reg = (local_p ? (base) : ((base) - CM_BASE + GLOBAL_CM_BASE[cl])) \
+ + (co << CM_BASE_CORE_SHIFT) \
+ + off; \
+ if (DEBUG_CM) \
+ sbi_printf("CM WRITE%d cmd_reg=%lx value=%lx\n", sz, \
+ cmd_reg, (u64)value); \
+ if (sz == 32) \
+ asm volatile("sw %0,0(%1)"::"r"(value),"r"(cmd_reg)); \
+ else if (sz == 64) \
+ asm volatile("sd %0,0(%1)"::"r"(value),"r"(cmd_reg)); \
+ asm volatile("fence"); \
+}
+
+#define CPS_ACCESSOR_RW(unit, sz, base, off, name) \
+ CPS_ACCESSOR_R(unit, sz, base, off, name) \
+ CPS_ACCESSOR_W(unit, sz, base, off, name)
+
+#define CPC_CX_ACCESSOR_RW(sz, off, name) \
+ CPS_ACCESSOR_RW(cpc, sz, CPC_BASE, CPC_OFF_LOCAL + (off), co_##name)
+
+#define GCR_CX_ACCESSOR_RW(sz, off, name) \
+ CPS_ACCESSOR_RW(gcr, sz, CM_BASE, GCR_OFF_LOCAL + (off), co_##name)
+
+GCR_CX_ACCESSOR_RW(64, cpu_hart(hartid) << CM_BASE_HART_SHIFT, reset_base)
+GCR_CX_ACCESSOR_RW(32, GCR_CORE_COH_EN, coherence)
+
+CPC_CX_ACCESSOR_RW(32, CPC_Cx_VP_RUN, vp_run)
+CPC_CX_ACCESSOR_RW(32, CPC_Cx_VP_STOP, vp_stop)
+CPC_CX_ACCESSOR_RW(32, CPC_Cx_CMD, cmd)
+CPC_CX_ACCESSOR_RW(32, CPC_Cx_STAT_CONF, stat_conf)
+
+#define CPC_ACCESSOR_RW(sz, off, name) \
+ CPS_ACCESSOR_RW(cpc, sz, CPC_BASE, off, name)
+
+CPC_ACCESSOR_RW(32, CPC_PWRUP_CTL, pwrup_ctl)
+CPC_ACCESSOR_RW(32, CPC_CM_STAT_CONF, cm_stat_conf)
+
+#endif
diff --git a/platform/generic/include/mips/p8700.h b/platform/generic/include/mips/p8700.h
new file mode 100644
index 0000000..b02aaed
--- /dev/null
+++ b/platform/generic/include/mips/p8700.h
@@ -0,0 +1,113 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 MIPS
+ *
+ */
+
+#ifndef __P8700_H__
+#define __P8700_H__
+
+#include <mips/board.h>
+
+/* PMA */
+#define CSR_MIPSPMACFG0 0x7e0
+#define CSR_MIPSPMACFG1 0x7e1
+#define CSR_MIPSPMACFG2 0x7e2
+#define CSR_MIPSPMACFG3 0x7e3
+#define CSR_MIPSPMACFG4 0x7e4
+#define CSR_MIPSPMACFG5 0x7e5
+#define CSR_MIPSPMACFG6 0x7e6
+#define CSR_MIPSPMACFG7 0x7e7
+#define CSR_MIPSPMACFG8 0x7e8
+#define CSR_MIPSPMACFG9 0x7e9
+#define CSR_MIPSPMACFG10 0x7ea
+#define CSR_MIPSPMACFG11 0x7eb
+#define CSR_MIPSPMACFG12 0x7ec
+#define CSR_MIPSPMACFG13 0x7ed
+#define CSR_MIPSPMACFG14 0x7ee
+#define CSR_MIPSPMACFG15 0x7ef
+
+/* MIPS CCA */
+#define CCA_CACHE_ENABLE 0
+#define CCA_CACHE_DISABLE 2
+#define PMA_SPECULATION (1 << 3)
+
+/* MIPS CSR */
+#define CSR_MIPSTVEC 0x7c0
+#define CSR_MIPSCONFIG0 0x7d0
+#define CSR_MIPSCONFIG1 0x7d1
+#define CSR_MIPSCONFIG2 0x7d2
+#define CSR_MIPSCONFIG3 0x7d3
+#define CSR_MIPSCONFIG4 0x7d4
+#define CSR_MIPSCONFIG5 0x7d5
+#define CSR_MIPSCONFIG6 0x7d6
+#define CSR_MIPSCONFIG7 0x7d7
+#define CSR_MIPSCONFIG8 0x7d8
+#define CSR_MIPSCONFIG9 0x7d9
+#define CSR_MIPSCONFIG10 0x7da
+#define CSR_MIPSCONFIG11 0x7db
+
+#define MIPSCONFIG5_MTW 4
+
+#define GEN_MASK(h, l) (((1ul << ((h) + 1 - (l))) - 1) << (l))
+#define EXT(val, mask) (((val) & (mask)) >> (__builtin_ffs(mask) - 1))
+
+/*
+ * We allocate the number of bits to encode clusters, cores, and harts
+ * from the original mhartid to a new dense index.
+ */
+#define NUM_OF_BITS_FOR_CLUSTERS 4
+#define NUM_OF_BITS_FOR_CORES 12
+#define NUM_OF_BITS_FOR_HARTS 4
+
+/* To get the field from new/hashed mhartid */
+#define NEW_CLUSTER_SHIFT (NUM_OF_BITS_FOR_CORES + NUM_OF_BITS_FOR_HARTS)
+#define NEW_CLUSTER_MASK ((1 << NUM_OF_BITS_FOR_CLUSTERS) - 1)
+#define NEW_CORE_SHIFT NUM_OF_BITS_FOR_HARTS
+#define NEW_CORE_MASK ((1 << NUM_OF_BITS_FOR_CORES) - 1)
+#define NEW_HART_MASK ((1 << NUM_OF_BITS_FOR_HARTS) - 1)
+#define cpu_cluster(i) (((i) >> NEW_CLUSTER_SHIFT) & NEW_CLUSTER_MASK)
+#define cpu_core(i) (((i) >> NEW_CORE_SHIFT) & NEW_CORE_MASK)
+#define cpu_hart(i) ((i) & NEW_HART_MASK)
+
+#define CPC_BASE (CM_BASE + 0x8000)
+
+#define SIZE_FOR_CPC_MTIME 0x10000 /* The size must be 2^order */
+#define AIA_BASE (CM_BASE + 0x40000)
+#define SIZE_FOR_AIA_M_MODE 0x20000 /* The size must be 2^order */
+#define P8700_ALIGN 0x10000
+
+#define CM_BASE_HART_SHIFT 3
+#define CM_BASE_CORE_SHIFT 8
+#define CM_BASE_CLUSTER_SHIFT 19
+
+/* GCR Block offsets */
+#define GCR_OFF_LOCAL 0x2000
+
+#define GCR_BASE_OFFSET 0x0008
+#define GCR_CORE_COH_EN 0x00f8
+#define GCR_CORE_COH_EN_EN (0x1 << 0)
+
+#define L2_PFT_CONTROL_OFFSET 0x0300
+#define L2_PFT_CONTROL_B_OFFSET 0x0308
+
+/* CPC Block offsets */
+#define CPC_PWRUP_CTL 0x0030
+#define CPC_CM_STAT_CONF 0x1008
+
+#define CPC_OFF_LOCAL 0x2000
+
+#define CPC_Cx_VP_STOP 0x0020
+#define CPC_Cx_VP_RUN 0x0028
+#define CPC_Cx_CMD 0x0000
+
+#define CPC_Cx_CMD_PWRUP 0x3
+#define CPC_Cx_CMD_RESET 0x4
+
+#define CPC_Cx_STAT_CONF 0x0008
+#define CPC_Cx_STAT_CONF_SEQ_STATE GEN_MASK(22, 19)
+#define CPC_Cx_STAT_CONF_SEQ_STATE_U5 6
+#define CPC_Cx_STAT_CONF_SEQ_STATE_U6 7
+
+#endif
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 70+ messages in thread* [MIPS P8700 v6 3/7] platform: generic: mips: add the platform file
2025-02-12 12:27 ` Anup Patel
` (43 preceding siblings ...)
2025-05-22 21:21 ` [MIPS P8700 v6 2/7] platform: generic: mips: add header files Chao-ying Fu
@ 2025-05-22 21:21 ` Chao-ying Fu
2025-05-22 21:21 ` [MIPS P8700 v6 4/7] platform: generic: mips: add objects.mk Chao-ying Fu
` (3 subsequent siblings)
48 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-05-22 21:21 UTC (permalink / raw)
To: opensbi; +Cc: Chao-ying Fu
We add the platform file for MIPS P8700.
Signed-off-by: Chao-ying Fu <cfu@mips.com>
---
platform/generic/mips/p8700.c | 270 ++++++++++++++++++++++++++++++++++
1 file changed, 270 insertions(+)
create mode 100644 platform/generic/mips/p8700.c
diff --git a/platform/generic/mips/p8700.c b/platform/generic/mips/p8700.c
new file mode 100644
index 0000000..6b68717
--- /dev/null
+++ b/platform/generic/mips/p8700.c
@@ -0,0 +1,270 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 MIPS
+ *
+ */
+
+#include <platform_override.h>
+#include <sbi/riscv_barrier.h>
+#include <sbi/riscv_io.h>
+#include <sbi/sbi_domain.h>
+#include <sbi/sbi_error.h>
+#include <sbi/sbi_hsm.h>
+#include <sbi/sbi_timer.h>
+#include <sbi_utils/fdt/fdt_helper.h>
+#include <mips/p8700.h>
+#include <mips/mips-cm.h>
+
+#if CLUSTERS_IN_PLATFORM > 1
+static void power_up_other_cluster(u32 hartid)
+{
+ unsigned int stat;
+ unsigned int timeout;
+ bool local_p = (cpu_cluster(current_hartid()) == cpu_cluster(hartid));
+
+ /* Power up cluster cl core 0 hart 0 */
+ write_cpc_pwrup_ctl(hartid, 1, local_p);
+
+ /* Wait for the CM to start up */
+ timeout = 100;
+ while (true) {
+ stat = read_cpc_cm_stat_conf(hartid, local_p);
+ stat = EXT(stat, CPC_Cx_STAT_CONF_SEQ_STATE);
+ if (stat == CPC_Cx_STAT_CONF_SEQ_STATE_U5)
+ break;
+
+ /* Delay a little while before we start warning */
+ if (timeout) {
+ sbi_dprintf("Delay a little while before we start warning\n");
+ timeout--;
+ }
+ else {
+ sbi_printf("Waiting for cluster %u CM to power up... STAT_CONF=0x%x\n",
+ cpu_cluster(hartid), stat);
+ break;
+ }
+ }
+}
+#endif
+
+static int mips_hart_start(u32 hartid, ulong saddr)
+{
+ unsigned int stat;
+ unsigned int timeout;
+ bool local_p = (cpu_cluster(current_hartid()) == cpu_cluster(hartid));
+
+ /* Hart 0 is the boot hart, and we don't use the CPC cmd to start. */
+ if (hartid == 0)
+ return SBI_ENOTSUPP;
+
+ if (cpu_hart(hartid) == 0) {
+ /* Ensure its coherency is disabled */
+ write_gcr_co_coherence(hartid, 0, local_p);
+
+ /* Start cluster cl core co hart 0 */
+ write_cpc_co_vp_run(hartid, 1 << cpu_hart(hartid), local_p);
+
+ /* Reset cluster cl core co hart 0 */
+ write_cpc_co_cmd(hartid, CPC_Cx_CMD_RESET, local_p);
+
+ timeout = 100;
+ while (true) {
+ stat = read_cpc_co_stat_conf(hartid, local_p);
+ stat = EXT(stat, CPC_Cx_STAT_CONF_SEQ_STATE);
+ if (stat == CPC_Cx_STAT_CONF_SEQ_STATE_U6)
+ break;
+
+ /* Delay a little while before we start warning */
+ if (timeout) {
+ sbi_timer_mdelay(10);
+ timeout--;
+ }
+ else {
+ sbi_printf("Waiting for cluster %u core %u hart %u to start... STAT_CONF=0x%x\n",
+ cpu_cluster(hartid),
+ cpu_core(hartid), cpu_hart(hartid),
+ stat);
+ break;
+ }
+ }
+ }
+ else {
+ write_cpc_co_vp_run(hartid, 1 << cpu_hart(hartid), local_p);
+ }
+
+ return 0;
+}
+
+static int mips_hart_stop()
+{
+ u32 hartid = current_hartid();
+ bool local_p = (cpu_cluster(current_hartid()) == cpu_cluster(hartid));
+
+ /* Hart 0 is the boot hart, and we don't use the CPC cmd to stop. */
+ if (hartid == 0)
+ return SBI_ENOTSUPP;
+
+ write_cpc_co_vp_stop(hartid, 1 << cpu_hart(hartid), local_p);
+
+ return 0;
+}
+
+static const struct sbi_hsm_device mips_hsm = {
+ .name = "mips_hsm",
+ .hart_start = mips_hart_start,
+ .hart_stop = mips_hart_stop,
+};
+
+static int mips_p8700_final_init(bool cold_boot)
+{
+ if (cold_boot)
+ sbi_hsm_set_device(&mips_hsm);
+
+ return generic_final_init(cold_boot);
+}
+
+static int mips_p8700_early_init(bool cold_boot)
+{
+ int rc;
+
+ rc = generic_early_init(cold_boot);
+ if (rc)
+ return rc;
+
+ if (cold_boot) {
+#if CLUSTERS_IN_PLATFORM > 1
+ int i;
+ /* Power up other clusters in the platform. */
+ for (i = 1; i < CLUSTERS_IN_PLATFORM; i++) {
+ power_up_other_cluster(i << NEW_CLUSTER_SHIFT);
+ }
+#endif
+
+ /* For the CPC mtime region, the minimum size is 0x10000. */
+ rc = sbi_domain_root_add_memrange(CM_BASE, SIZE_FOR_CPC_MTIME,
+ P8700_ALIGN,
+ (SBI_DOMAIN_MEMREGION_MMIO |
+ SBI_DOMAIN_MEMREGION_M_READABLE |
+ SBI_DOMAIN_MEMREGION_M_WRITABLE));
+ if (rc)
+ return rc;
+
+ /* For the APLIC and ACLINT m-mode region */
+ rc = sbi_domain_root_add_memrange(AIA_BASE, SIZE_FOR_AIA_M_MODE,
+ P8700_ALIGN,
+ (SBI_DOMAIN_MEMREGION_MMIO |
+ SBI_DOMAIN_MEMREGION_M_READABLE |
+ SBI_DOMAIN_MEMREGION_M_WRITABLE));
+ if (rc)
+ return rc;
+
+#if CLUSTERS_IN_PLATFORM > 1
+ for (i = 0; i < CLUSTERS_IN_PLATFORM; i++) {
+ /* For the CPC mtime region, the minimum size is 0x10000. */
+ rc = sbi_domain_root_add_memrange(GLOBAL_CM_BASE[i], SIZE_FOR_CPC_MTIME,
+ P8700_ALIGN,
+ (SBI_DOMAIN_MEMREGION_MMIO |
+ SBI_DOMAIN_MEMREGION_M_READABLE |
+ SBI_DOMAIN_MEMREGION_M_WRITABLE));
+ if (rc)
+ return rc;
+
+ /* For the APLIC and ACLINT m-mode region */
+ rc = sbi_domain_root_add_memrange(AIA_BASE - CM_BASE + GLOBAL_CM_BASE[i], SIZE_FOR_AIA_M_MODE,
+ P8700_ALIGN,
+ (SBI_DOMAIN_MEMREGION_MMIO |
+ SBI_DOMAIN_MEMREGION_M_READABLE |
+ SBI_DOMAIN_MEMREGION_M_WRITABLE));
+ if (rc)
+ return rc;
+ }
+#endif
+ }
+
+ return 0;
+}
+
+static int mips_p8700_nascent_init(void)
+{
+ u64 hartid = current_hartid();
+ u64 cm_base = CM_BASE;
+ int i;
+
+ /* Coherence enable for every core */
+ if (cpu_hart(hartid) == 0) {
+ cm_base += (cpu_core(hartid) << CM_BASE_CORE_SHIFT);
+ __raw_writeq(GCR_CORE_COH_EN_EN,
+ (void *)(cm_base + GCR_OFF_LOCAL +
+ GCR_CORE_COH_EN));
+ mb();
+ }
+
+ /* Set up pmp for DRAM */
+ csr_write(CSR_PMPADDR14, DRAM_PMP_ADDR);
+ /* All from 0x0 */
+ csr_write(CSR_PMPADDR15, 0x1fffffffffffffff);
+ csr_write(CSR_PMPCFG2, ((PMP_A_NAPOT|PMP_R|PMP_W|PMP_X)<<56)|
+ ((PMP_A_NAPOT|PMP_R|PMP_W|PMP_X)<<48));
+ /* Set cacheable for pmp6, uncacheable for pmp7 */
+ csr_write(CSR_MIPSPMACFG2, ((u64)CCA_CACHE_DISABLE << 56)|
+ ((u64)CCA_CACHE_ENABLE << 48));
+ /* Reset pmpcfg0 */
+ csr_write(CSR_PMPCFG0, 0);
+ /* Reset pmacfg0 */
+ csr_write(CSR_MIPSPMACFG0, 0);
+ mb();
+
+ /* Per cluster set up */
+ if (cpu_core(hartid) == 0 && cpu_hart(hartid) == 0) {
+ /* Enable L2 prefetch */
+ __raw_writel(0xfffff110,
+ (void *)(cm_base + L2_PFT_CONTROL_OFFSET));
+ __raw_writel(0x15ff,
+ (void *)(cm_base + L2_PFT_CONTROL_B_OFFSET));
+ }
+
+ /* Per core set up */
+ if (cpu_hart(hartid) == 0) {
+ /* Enable load pair, store pair, and HTW */
+ csr_clear(CSR_MIPSCONFIG7, (1<<12)|(1<<13)|(1<<7));
+
+ /* Disable noRFO, misaligned load/store */
+ csr_set(CSR_MIPSCONFIG7, (1<<25)|(1<<9));
+
+ /* Enable L1-D$ Prefetch */
+ csr_write(CSR_MIPSCONFIG11, 0xff);
+
+ for (i = 0; i < 8; i++) {
+ csr_set(CSR_MIPSCONFIG8, 4 + 0x100 * i);
+ csr_set(CSR_MIPSCONFIG9, 8);
+ mb();
+ RISCV_FENCE_I;
+ }
+ }
+
+ /* Per hart set up */
+ /* Enable AMO and RDTIME illegal instruction exceptions. */
+ csr_set(CSR_MIPSCONFIG6, (1<<2)|(1<<1));
+
+ return 0;
+}
+
+static int mips_p8700_platform_init(const void *fdt, int nodeoff, const struct fdt_match *match)
+{
+ generic_platform_ops.early_init = mips_p8700_early_init;
+ generic_platform_ops.final_init = mips_p8700_final_init;
+ generic_platform_ops.nascent_init = mips_p8700_nascent_init;
+
+ return 0;
+}
+
+static const struct fdt_match mips_p8700_match[] = {
+ { .compatible = "mips,p8700" },
+ { },
+};
+
+const struct fdt_driver mips_p8700 = {
+ .match_table = mips_p8700_match,
+ .init = mips_p8700_platform_init,
+};
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 70+ messages in thread* [MIPS P8700 v6 4/7] platform: generic: mips: add objects.mk
2025-02-12 12:27 ` Anup Patel
` (44 preceding siblings ...)
2025-05-22 21:21 ` [MIPS P8700 v6 3/7] platform: generic: mips: add the platform file Chao-ying Fu
@ 2025-05-22 21:21 ` Chao-ying Fu
2025-05-22 21:21 ` [MIPS P8700 v6 5/7] devices to use MMIO memory Chao-ying Fu
` (2 subsequent siblings)
48 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-05-22 21:21 UTC (permalink / raw)
To: opensbi; +Cc: Chao-ying Fu
We build MIPS files.
Signed-off-by: Chao-ying Fu <cfu@mips.com>
---
platform/generic/mips/objects.mk | 6 ++++++
1 file changed, 6 insertions(+)
create mode 100644 platform/generic/mips/objects.mk
diff --git a/platform/generic/mips/objects.mk b/platform/generic/mips/objects.mk
new file mode 100644
index 0000000..16885e7
--- /dev/null
+++ b/platform/generic/mips/objects.mk
@@ -0,0 +1,6 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+
+carray-platform_override_modules-$(CONFIG_PLATFORM_MIPS_P8700) += mips_p8700
+platform-objs-$(CONFIG_PLATFORM_MIPS_P8700) += mips/p8700.o
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 70+ messages in thread* [MIPS P8700 v6 5/7] devices to use MMIO memory
2025-02-12 12:27 ` Anup Patel
` (45 preceding siblings ...)
2025-05-22 21:21 ` [MIPS P8700 v6 4/7] platform: generic: mips: add objects.mk Chao-ying Fu
@ 2025-05-22 21:21 ` Chao-ying Fu
2025-05-22 21:21 ` [MIPS P8700 v6 6/7] Convey MMIO flag as specified by SBI_DOMAIN_MEMREGION_MMIO Chao-ying Fu
2025-05-22 21:21 ` [MIPS P8700 v6 7/7] lib: sbi_platform: Add the platform pma_set function to set up cacheability Chao-ying Fu
48 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-05-22 21:21 UTC (permalink / raw)
To: opensbi; +Cc: Vladimir Kondratiev
From: Vladimir Kondratiev <vladimir.kondratiev@mobileye.com>
When applying FDT fixups, request device memory to be of
MMIO type
Signed-off-by: Vladimir Kondratiev <vladimir.kondratiev@mobileye.com>
---
lib/utils/fdt/fdt_fixup.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/utils/fdt/fdt_fixup.c b/lib/utils/fdt/fdt_fixup.c
index f3fe8af..b0ed20c 100644
--- a/lib/utils/fdt/fdt_fixup.c
+++ b/lib/utils/fdt/fdt_fixup.c
@@ -185,7 +185,7 @@ static void fdt_domain_based_fixup_one(void *fdt, int nodeoff)
return;
if (!sbi_domain_check_addr(dom, reg_addr, dom->next_mode,
- SBI_DOMAIN_READ | SBI_DOMAIN_WRITE)) {
+ SBI_DOMAIN_READ | SBI_DOMAIN_WRITE | SBI_DOMAIN_MMIO)) {
rc = fdt_open_into(fdt, fdt, fdt_totalsize(fdt) + 32);
if (rc < 0)
return;
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 70+ messages in thread* [MIPS P8700 v6 6/7] Convey MMIO flag as specified by SBI_DOMAIN_MEMREGION_MMIO
2025-02-12 12:27 ` Anup Patel
` (46 preceding siblings ...)
2025-05-22 21:21 ` [MIPS P8700 v6 5/7] devices to use MMIO memory Chao-ying Fu
@ 2025-05-22 21:21 ` Chao-ying Fu
2025-05-22 21:21 ` [MIPS P8700 v6 7/7] lib: sbi_platform: Add the platform pma_set function to set up cacheability Chao-ying Fu
48 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-05-22 21:21 UTC (permalink / raw)
To: opensbi; +Cc: Vladimir Kondratiev
From: Vladimir Kondratiev <vladimir.kondratiev@mobileye.com>
Introduce non-architecture bit PMP_MMIO for this new flag, have it
out of valid bit mask for the PMPCFG register to avoid side effects
Signed-off-by: Vladimir Kondratiev <vladimir.kondratiev@mobileye.com>
---
include/sbi/riscv_asm.h | 2 ++
lib/sbi/sbi_hart.c | 13 +++++++++++++
2 files changed, 15 insertions(+)
diff --git a/include/sbi/riscv_asm.h b/include/sbi/riscv_asm.h
index ef48dc8..1bb2be7 100644
--- a/include/sbi/riscv_asm.h
+++ b/include/sbi/riscv_asm.h
@@ -215,6 +215,8 @@ int pmp_disable(unsigned int n);
/* Check if the matching field is set */
int is_pmp_entry_mapped(unsigned long entry);
+#define PMP_MMIO _UL(0x100)
+
int pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
unsigned long log2len);
diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c
index 74ccdd8..49aaa49 100644
--- a/lib/sbi/sbi_hart.c
+++ b/lib/sbi/sbi_hart.c
@@ -361,6 +361,13 @@ static unsigned int sbi_hart_get_smepmp_flags(struct sbi_scratch *scratch,
pmp_flags |= PMP_X;
}
+ /*
+ * indicate whether it is MMIO, to be evaluated by code,
+ * out of pmpcfg mask
+ */
+ if (reg->flags & SBI_DOMAIN_MEMREGION_MMIO)
+ pmp_flags |= PMP_MMIO;
+
return pmp_flags;
}
@@ -489,6 +496,12 @@ static int sbi_hart_oldpmp_configure(struct sbi_scratch *scratch,
pmp_flags |= PMP_W;
if (reg->flags & SBI_DOMAIN_MEMREGION_SU_EXECUTABLE)
pmp_flags |= PMP_X;
+ /*
+ * indicate whether it is MMIO, to be evaluated by code,
+ * out of pmpcfg mask
+ */
+ if (reg->flags & SBI_DOMAIN_MEMREGION_MMIO)
+ pmp_flags |= PMP_MMIO;
pmp_addr = reg->base >> PMP_SHIFT;
if (pmp_log2gran <= reg->order && pmp_addr < pmp_addr_max) {
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 70+ messages in thread* [MIPS P8700 v6 7/7] lib: sbi_platform: Add the platform pma_set function to set up cacheability
2025-02-12 12:27 ` Anup Patel
` (47 preceding siblings ...)
2025-05-22 21:21 ` [MIPS P8700 v6 6/7] Convey MMIO flag as specified by SBI_DOMAIN_MEMREGION_MMIO Chao-ying Fu
@ 2025-05-22 21:21 ` Chao-ying Fu
48 siblings, 0 replies; 70+ messages in thread
From: Chao-ying Fu @ 2025-05-22 21:21 UTC (permalink / raw)
To: opensbi; +Cc: Chao-ying Fu, Chao-ying Fu
From: Chao-ying Fu <cfu@wavecomp.com>
Before the corresponding PMP is changed, we allow platforms to set up PMA.
Add mips_p8700_pma_set.
Signed-off-by: Chao-ying Fu <cfu@mips.com>
---
include/sbi/sbi_platform.h | 19 ++++++++
lib/sbi/riscv_asm.c | 3 ++
platform/generic/mips/p8700.c | 91 +++++++++++++++++++++++++++++++++++
3 files changed, 113 insertions(+)
diff --git a/include/sbi/sbi_platform.h b/include/sbi/sbi_platform.h
index 08ece32..b3a5eda 100644
--- a/include/sbi/sbi_platform.h
+++ b/include/sbi/sbi_platform.h
@@ -142,6 +142,9 @@ struct sbi_platform_operations {
/** platform specific handler to fixup store fault */
int (*emulate_store)(int wlen, unsigned long addr,
union sbi_ldst_data in_val);
+
+ /** platform specific pma set up */
+ void (*pma_set)(unsigned int n, unsigned long prot, unsigned long addr);
};
/** Platform default per-HART stack size for exception/interrupt handling */
@@ -644,6 +647,22 @@ static inline int sbi_platform_emulate_store(const struct sbi_platform *plat,
return SBI_ENOTSUPP;
}
+/**
+ * PMA set up for cacheability based on the corresponding PMP
+ *
+ * @param plat pointer to struct sbi_platform
+ * @param n index of the pmp/pma entry
+ * @param prot attribute of the pmp entry
+ * @param addr address of the pmp entry
+ */
+static inline void sbi_platform_pma_set(const struct sbi_platform *plat,
+ unsigned int n, unsigned long prot,
+ unsigned long addr)
+{
+ if (plat && sbi_platform_ops(plat)->pma_set)
+ sbi_platform_ops(plat)->pma_set(n, prot, addr);
+}
+
#endif
#endif
diff --git a/lib/sbi/riscv_asm.c b/lib/sbi/riscv_asm.c
index c7d75ac..3b0cde5 100644
--- a/lib/sbi/riscv_asm.c
+++ b/lib/sbi/riscv_asm.c
@@ -312,6 +312,9 @@ int pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
if (n >= PMP_COUNT || log2len > __riscv_xlen || log2len < PMP_SHIFT)
return SBI_EINVAL;
+ /* Allow the platform to set up PMA if needed */
+ sbi_platform_pma_set(sbi_platform_thishart_ptr(), n, prot, addr);
+
/* calculate PMP register and offset */
#if __riscv_xlen == 32
pmpcfg_csr = CSR_PMPCFG0 + (n >> 2);
diff --git a/platform/generic/mips/p8700.c b/platform/generic/mips/p8700.c
index 6b68717..8ca497f 100644
--- a/platform/generic/mips/p8700.c
+++ b/platform/generic/mips/p8700.c
@@ -16,6 +16,96 @@
#include <mips/p8700.h>
#include <mips/mips-cm.h>
+static unsigned long mips_csr_read_num(int csr_num)
+{
+#define switchcase_csr_read(__csr_num, __val) \
+ case __csr_num: \
+ __val = csr_read(__csr_num); \
+ break;
+#define switchcase_csr_read_2(__csr_num, __val) \
+ switchcase_csr_read(__csr_num + 0, __val) \
+ switchcase_csr_read(__csr_num + 1, __val)
+#define switchcase_csr_read_4(__csr_num, __val) \
+ switchcase_csr_read_2(__csr_num + 0, __val) \
+ switchcase_csr_read_2(__csr_num + 2, __val)
+#define switchcase_csr_read_8(__csr_num, __val) \
+ switchcase_csr_read_4(__csr_num + 0, __val) \
+ switchcase_csr_read_4(__csr_num + 4, __val)
+#define switchcase_csr_read_16(__csr_num, __val) \
+ switchcase_csr_read_8(__csr_num + 0, __val) \
+ switchcase_csr_read_8(__csr_num + 8, __val)
+
+ unsigned long ret = 0;
+
+ switch(csr_num) {
+ switchcase_csr_read_16(CSR_MIPSPMACFG0, ret)
+
+ default:
+ sbi_panic("%s: Unknown CSR %#x", __func__, csr_num);
+ break;
+ }
+
+ return ret;
+
+#undef switchcase_csr_read_16
+#undef switchcase_csr_read_8
+#undef switchcase_csr_read_4
+#undef switchcase_csr_read_2
+#undef switchcase_csr_read
+}
+
+static void mips_csr_write_num(int csr_num, unsigned long val)
+{
+#define switchcase_csr_write(__csr_num, __val) \
+ case __csr_num: \
+ csr_write(__csr_num, __val); \
+ break;
+#define switchcase_csr_write_2(__csr_num, __val) \
+ switchcase_csr_write(__csr_num + 0, __val) \
+ switchcase_csr_write(__csr_num + 1, __val)
+#define switchcase_csr_write_4(__csr_num, __val) \
+ switchcase_csr_write_2(__csr_num + 0, __val) \
+ switchcase_csr_write_2(__csr_num + 2, __val)
+#define switchcase_csr_write_8(__csr_num, __val) \
+ switchcase_csr_write_4(__csr_num + 0, __val) \
+ switchcase_csr_write_4(__csr_num + 4, __val)
+#define switchcase_csr_write_16(__csr_num, __val) \
+ switchcase_csr_write_8(__csr_num + 0, __val) \
+ switchcase_csr_write_8(__csr_num + 8, __val)
+
+ switch(csr_num) {
+ switchcase_csr_write_16(CSR_MIPSPMACFG0, val)
+
+ default:
+ sbi_panic("%s: Unknown CSR %#x", __func__, csr_num);
+ break;
+ }
+
+#undef switchcase_csr_write_16
+#undef switchcase_csr_write_8
+#undef switchcase_csr_write_4
+#undef switchcase_csr_write_2
+#undef switchcase_csr_write
+}
+
+static void mips_p8700_pma_set(unsigned int n, unsigned long prot, unsigned long addr)
+{
+ int pmacfg_csr, pmacfg_shift;
+ unsigned long cfgmask;
+ unsigned long pmacfg, cca;
+
+ pmacfg_csr = (CSR_MIPSPMACFG0 + (n >> 2)) & ~1;
+ pmacfg_shift = (n & 7) << 3;
+ cfgmask = ~(0xffUL << pmacfg_shift);
+
+ /* Read pmacfg to change cacheability */
+ pmacfg = (mips_csr_read_num(pmacfg_csr) & cfgmask);
+ cca = (prot & PMP_MMIO) ? CCA_CACHE_DISABLE :
+ CCA_CACHE_ENABLE | PMA_SPECULATION;
+ pmacfg |= ((cca << pmacfg_shift) & ~cfgmask);
+ mips_csr_write_num(pmacfg_csr, pmacfg);
+}
+
#if CLUSTERS_IN_PLATFORM > 1
static void power_up_other_cluster(u32 hartid)
{
@@ -255,6 +345,7 @@ static int mips_p8700_platform_init(const void *fdt, int nodeoff, const struct f
generic_platform_ops.early_init = mips_p8700_early_init;
generic_platform_ops.final_init = mips_p8700_final_init;
generic_platform_ops.nascent_init = mips_p8700_nascent_init;
+ generic_platform_ops.pma_set = mips_p8700_pma_set;
return 0;
}
--
2.47.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 70+ messages in thread