hifiveu: add new target for HiFive Unleashed/Unmatched RISC-V boards
[openwrt/staging/wigyori.git] / target / linux / hifiveu / patches-5.10 / 0021-riscv-sifive-apply-errata-cip-453-patch.patch
1 From fb63756f6b2e49160aaf85789f8ed88135eeea50 Mon Sep 17 00:00:00 2001
2 From: Vincent Chen <vincent.chen@sifive.com>
3 Date: Tue, 12 Jan 2021 15:29:29 +0800
4 Subject: [PATCH 21/29] riscv: sifive: apply errata cip-453 patch
5
6 Add sign extension to the $badaddr when the exception type is instruction
7 page fault or instruciton access fault to workaround the errata cip-453.
8
9 To avoid affecting the existing code sequence, this patch creates a
10 trampoline to add sign extension to the $baddaddr, and then replaces
11 the original exception handlers with this trampoline by ALTDATA. In this
12 case, only the specific sifive CPU jumps to the do_page_fault through
13 this trampoline. Other CPUs are not affected.
14
15 Signed-off-by: Vincent Chen <vincent.chen@sifive.com>
16 ---
17 arch/riscv/errata/Makefile | 1 +
18 arch/riscv/errata/sifive/Makefile | 2 +
19 arch/riscv/errata/sifive/altern_ops.c | 20 ++++++++++
20 arch/riscv/errata/sifive/errata.h | 6 +++
21 arch/riscv/errata/sifive/errata_cip_453.S | 64 +++++++++++++++++++++++++++++++
22 5 files changed, 93 insertions(+)
23 create mode 100644 arch/riscv/errata/sifive/Makefile
24 create mode 100644 arch/riscv/errata/sifive/altern_ops.c
25 create mode 100644 arch/riscv/errata/sifive/errata.h
26 create mode 100644 arch/riscv/errata/sifive/errata_cip_453.S
27
28 diff --git a/arch/riscv/errata/Makefile b/arch/riscv/errata/Makefile
29 index 43e6d54..be93ded 100644
30 --- a/arch/riscv/errata/Makefile
31 +++ b/arch/riscv/errata/Makefile
32 @@ -1 +1,2 @@
33 obj-y += alternative.o
34 +obj-$(CONFIG_SOC_SIFIVE) += sifive/
35 diff --git a/arch/riscv/errata/sifive/Makefile b/arch/riscv/errata/sifive/Makefile
36 new file mode 100644
37 index 00000000..b7f4cd7
38 --- /dev/null
39 +++ b/arch/riscv/errata/sifive/Makefile
40 @@ -0,0 +1,2 @@
41 +obj-y += altern_ops.o
42 +obj-y += errata_cip_453.o
43 diff --git a/arch/riscv/errata/sifive/altern_ops.c b/arch/riscv/errata/sifive/altern_ops.c
44 new file mode 100644
45 index 00000000..0dcec17
46 --- /dev/null
47 +++ b/arch/riscv/errata/sifive/altern_ops.c
48 @@ -0,0 +1,20 @@
49 +// SPDX-License-Identifier: GPL-2.0-only
50 +/*
51 + * Copyright (C) 2021 Sifive.
52 + */
53 +
54 +#include <asm/alternative.h>
55 +#include <linux/kernel.h>
56 +
57 +#include "errata.h"
58 +
59 +static bool __init sifive_errata_check(struct alt_entry *alt)
60 +{
61 + if (cpu_manufactor_info.vendorid == alt->vendorid &&
62 + cpu_manufactor_info.archid == alt->archid &&
63 + cpu_manufactor_info.impid == alt->impid)
64 + return true;
65 + return false;
66 +}
67 +
68 +REGISTER_ERRATA_CHECKFUNC(sifive_errata_check, SIFIVE_VENDOR_ID);
69 diff --git a/arch/riscv/errata/sifive/errata.h b/arch/riscv/errata/sifive/errata.h
70 new file mode 100644
71 index 00000000..1f3be47
72 --- /dev/null
73 +++ b/arch/riscv/errata/sifive/errata.h
74 @@ -0,0 +1,6 @@
75 +/* SPDX-License-Identifier: GPL-2.0-only */
76 +/*
77 + * Copyright (C) 2021 SiFive
78 + */
79 +
80 +#define SIFIVE_VENDOR_ID 0x489
81 diff --git a/arch/riscv/errata/sifive/errata_cip_453.S b/arch/riscv/errata/sifive/errata_cip_453.S
82 new file mode 100644
83 index 00000000..c1ea974
84 --- /dev/null
85 +++ b/arch/riscv/errata/sifive/errata_cip_453.S
86 @@ -0,0 +1,64 @@
87 +/* SPDX-License-Identifier: GPL-2.0-only */
88 +/*
89 + * Copyright (C) 2021 SiFive
90 + */
91 +
92 +#include <linux/linkage.h>
93 +#include <asm/asm.h>
94 +#include <asm/asm-offsets.h>
95 +#include <asm/alternative.h>
96 +#include "errata.h"
97 +
98 +#define INSN_PAGE_FAULT excp_vect_table + 12 << RISCV_LGPTR
99 +#define INSN_ACCESS_FAULT excp_vect_table + 1 << RISCV_LGPTR
100 +#define P_TRAMPOLINE sifive_ipage_fault_trampoline
101 +#define A_TRAMPOLINE sifive_iaccess_fault_trampoline
102 +#define MARCHID 0x8000000000000007
103 +#define MIMPID 0x20181004
104 +#define LEN 1 << RISCV_LGPTR
105 +
106 +.macro ADD_SIGN_EXT pt_reg badaddr tmp_reg
107 + REG_L \badaddr, PT_BADADDR(\pt_reg)
108 + li \tmp_reg,1
109 + slli \tmp_reg,\tmp_reg,0x26
110 + and \tmp_reg,\tmp_reg,\badaddr
111 + beqz \tmp_reg, 1f
112 + li \tmp_reg,-1
113 + slli \tmp_reg,\tmp_reg,0x27
114 + or \badaddr,\tmp_reg,\badaddr
115 + REG_S \badaddr, PT_BADADDR(\pt_reg)
116 +1:
117 +.endm
118 +
119 +
120 +.globl sifive_ipage_fault_trampoline
121 +.type sifive_ipage_fault_trampoline, @object
122 +.size sifive_ipage_fault_trampoline, 8
123 +sifive_ipage_fault_trampoline:
124 +.dword do_page_fault_trampoline
125 +
126 +ENTRY(do_page_fault_trampoline)
127 + ADD_SIGN_EXT a0, t0, t1
128 + la t0, do_page_fault
129 + jr t0
130 +END(do_page_fault_trampoline)
131 +
132 +.globl sifive_iaccess_fault_trampoline
133 +.type sifive_iaccess_fault_trampoline, @object
134 +.size sifive_iaccess_fault_trampoline, 8
135 +sifive_iaccess_fault_trampoline:
136 +.dword do_trap_insn_fault_trampoline
137 +
138 +ENTRY(do_trap_insn_fault_trampoline)
139 + ADD_SIGN_EXT a0, t0, t1
140 + la t0, do_trap_insn_fault
141 + jr t0
142 +END(do_trap_insn_fault_trampoline)
143 +
144 +/*
145 + * Replace the page fault exception handler with sifive_page_fault_trampoline
146 + * function
147 + */
148 +ALTDATA(INSN_PAGE_FAULT, P_TRAMPOLINE, SIFIVE_VENDOR_ID, MARCHID, MIMPID, LEN, LEN)
149 +ALTDATA(INSN_ACCESS_FAULT, A_TRAMPOLINE, SIFIVE_VENDOR_ID, MARCHID, MIMPID, LEN, LEN)
150 +
151 --
152 2.7.4
153