1
The following changes since commit c95bd5ff1660883d15ad6e0005e4c8571604f51a:
1
The following changes since commit 20c1df5476e1e9b5d3f5b94f9f3ce01d21f14c46:
2
2
3
Merge remote-tracking branch 'remotes/philmd/tags/mips-fixes-20210322' into staging (2021-03-22 14:26:13 +0000)
3
Merge remote-tracking branch 'remotes/kraxel/tags/fixes-20200713-pull-request' into staging (2020-07-13 16:58:44 +0100)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
git@github.com:alistair23/qemu.git tags/pull-riscv-to-apply-20210322-2
7
git@github.com:alistair23/qemu.git tags/pull-riscv-to-apply-20200713
8
8
9
for you to fetch changes up to 9a27f69bd668d9d71674407badc412ce1231c7d5:
9
for you to fetch changes up to cfad709bceb629a4ebeb5d8a3acd1871b9a6436b:
10
10
11
target/riscv: Prevent lost illegal instruction exceptions (2021-03-22 21:54:40 -0400)
11
target/riscv: Fix pmp NA4 implementation (2020-07-13 17:25:37 -0700)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
RISC-V PR for 6.0
14
This is a colection of bug fixes and small imrprovements for RISC-V.
15
15
16
This PR includes:
16
This includes some vector extensions fixes, a PMP bug fix, OpenTitan
17
- Fix for vector CSR access
17
UART bug fix and support for OpenSBI dynamic firmware.
18
- Improvements to the Ibex UART device
19
- PMP improvements and bug fixes
20
- Hypervisor extension bug fixes
21
- ramfb support for the virt machine
22
- Fast read support for SST flash
23
- Improvements to the microchip_pfsoc machine
24
18
25
----------------------------------------------------------------
19
----------------------------------------------------------------
26
Alexander Wagner (1):
20
Alexandre Mergnat (1):
27
hw/char: disable ibex uart receive if the buffer is full
21
target/riscv: Fix pmp NA4 implementation
28
22
29
Asherah Connor (2):
23
Alistair Francis (2):
30
hw/riscv: Add fw_cfg support to virt
24
hw/char: Convert the Ibex UART to use the qdev Clock model
31
hw/riscv: allow ramfb on virt
25
hw/char: Convert the Ibex UART to use the registerfields API
26
27
Atish Patra (4):
28
riscv: Unify Qemu's reset vector code path
29
RISC-V: Copy the fdt in dram instead of ROM
30
riscv: Add opensbi firmware dynamic support
31
RISC-V: Support 64 bit start address
32
32
33
Bin Meng (3):
33
Bin Meng (3):
34
hw/block: m25p80: Support fast read for SST flashes
34
MAINTAINERS: Add an entry for OpenSBI firmware
35
hw/riscv: microchip_pfsoc: Map EMMC/SD mux register
35
hw/riscv: virt: Sort the SoC memmap table entries
36
docs/system: riscv: Add documentation for 'microchip-icicle-kit' machine
36
hw/riscv: Modify MROM size to end at 0x10000
37
37
38
Frank Chang (1):
38
Frank Chang (4):
39
target/riscv: fix vs() to return proper error code
39
target/riscv: fix rsub gvec tcg_assert_listed_vecop assertion
40
target/riscv: correct the gvec IR called in gen_vec_rsub16_i64()
41
target/riscv: fix return value of do_opivx_widen()
42
target/riscv: fix vill bit index in vtype register
40
43
41
Georg Kotheimer (6):
44
Liao Pingfang (1):
42
target/riscv: Adjust privilege level for HLV(X)/HSV instructions
45
tcg/riscv: Remove superfluous breaks
43
target/riscv: Make VSTIP and VSEIP read-only in hip
44
target/riscv: Use background registers also for MSTATUS_MPV
45
target/riscv: Fix read and write accesses to vsip and vsie
46
target/riscv: Add proper two-stage lookup exception detection
47
target/riscv: Prevent lost illegal instruction exceptions
48
46
49
Jim Shu (3):
47
include/hw/char/ibex_uart.h | 79 ++++++++--------
50
target/riscv: propagate PMP permission to TLB page
48
include/hw/riscv/boot.h | 7 ++
51
target/riscv: add log of PMP permission checking
49
include/hw/riscv/boot_opensbi.h | 58 ++++++++++++
52
target/riscv: flush TLB pages if PMP permission has been changed
50
target/riscv/cpu.h | 2 +-
51
hw/char/ibex_uart.c | 158 ++++++++++++++++++--------------
52
hw/riscv/boot.c | 107 +++++++++++++++++++++
53
hw/riscv/sifive_u.c | 53 ++++++-----
54
hw/riscv/spike.c | 59 ++++--------
55
hw/riscv/virt.c | 63 ++++---------
56
target/riscv/insn_trans/trans_rvv.inc.c | 9 +-
57
target/riscv/pmp.c | 2 +-
58
tcg/riscv/tcg-target.inc.c | 2 -
59
MAINTAINERS | 7 ++
60
13 files changed, 387 insertions(+), 219 deletions(-)
61
create mode 100644 include/hw/riscv/boot_opensbi.h
53
62
54
docs/system/riscv/microchip-icicle-kit.rst | 89 ++++++++++++++
55
docs/system/target-riscv.rst | 1 +
56
include/hw/char/ibex_uart.h | 4 +
57
include/hw/riscv/microchip_pfsoc.h | 1 +
58
include/hw/riscv/virt.h | 2 +
59
target/riscv/cpu.h | 4 +
60
target/riscv/pmp.h | 4 +-
61
hw/block/m25p80.c | 3 +
62
hw/char/ibex_uart.c | 23 +++-
63
hw/riscv/microchip_pfsoc.c | 6 +
64
hw/riscv/virt.c | 33 ++++++
65
target/riscv/cpu.c | 1 +
66
target/riscv/cpu_helper.c | 144 +++++++++++++++--------
67
target/riscv/csr.c | 77 +++++++------
68
target/riscv/pmp.c | 84 ++++++++++----
69
target/riscv/translate.c | 179 +----------------------------
70
hw/riscv/Kconfig | 1 +
71
17 files changed, 367 insertions(+), 289 deletions(-)
72
create mode 100644 docs/system/riscv/microchip-icicle-kit.rst
73
diff view generated by jsdifflib
1
From: Georg Kotheimer <georg.kotheimer@kernkonzept.com>
1
From: Bin Meng <bmeng.cn@gmail.com>
2
2
3
When decode_insn16() fails, we fall back to decode_RV32_64C() for
3
List me as the maintainer for OpenSBI firmware related files.
4
further compressed instruction decoding. However, prior to this change,
5
we did not raise an illegal instruction exception, if decode_RV32_64C()
6
fails to decode the instruction. This means that we skipped illegal
7
compressed instructions instead of raising an illegal instruction
8
exception.
9
4
10
Instead of patching decode_RV32_64C(), we can just remove it,
5
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
11
as it is dead code since f330433b363 anyway.
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
12
7
Message-Id: <1593177220-28143-1-git-send-email-bmeng.cn@gmail.com>
13
Signed-off-by: Georg Kotheimer <georg.kotheimer@kernkonzept.com>
14
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20210322121609.3097928-1-georg.kotheimer@kernkonzept.com
17
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
8
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
18
---
9
---
19
target/riscv/translate.c | 179 +--------------------------------------
10
MAINTAINERS | 7 +++++++
20
1 file changed, 1 insertion(+), 178 deletions(-)
11
1 file changed, 7 insertions(+)
21
12
22
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
13
diff --git a/MAINTAINERS b/MAINTAINERS
23
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
24
--- a/target/riscv/translate.c
15
--- a/MAINTAINERS
25
+++ b/target/riscv/translate.c
16
+++ b/MAINTAINERS
26
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
17
@@ -XXX,XX +XXX,XX @@ F: hw/i386/intel_iommu.c
27
CPUState *cs;
18
F: hw/i386/intel_iommu_internal.h
28
} DisasContext;
19
F: include/hw/i386/intel_iommu.h
29
20
30
-#ifdef TARGET_RISCV64
21
+OpenSBI Firmware
31
-/* convert riscv funct3 to qemu memop for load/store */
22
+M: Bin Meng <bmeng.cn@gmail.com>
32
-static const int tcg_memop_lookup[8] = {
23
+S: Supported
33
- [0 ... 7] = -1,
24
+F: pc-bios/opensbi-*
34
- [0] = MO_SB,
25
+F: .gitlab-ci.d/opensbi.yml
35
- [1] = MO_TESW,
26
+F: .gitlab-ci.d/opensbi/
36
- [2] = MO_TESL,
27
+
37
- [3] = MO_TEQ,
28
Usermode Emulation
38
- [4] = MO_UB,
29
------------------
39
- [5] = MO_TEUW,
30
Overall usermode emulation
40
- [6] = MO_TEUL,
41
-};
42
-#endif
43
-
44
#ifdef TARGET_RISCV64
45
#define CASE_OP_32_64(X) case X: case glue(X, W)
46
#else
47
@@ -XXX,XX +XXX,XX @@ static void gen_jal(DisasContext *ctx, int rd, target_ulong imm)
48
ctx->base.is_jmp = DISAS_NORETURN;
49
}
50
51
-#ifdef TARGET_RISCV64
52
-static void gen_load_c(DisasContext *ctx, uint32_t opc, int rd, int rs1,
53
- target_long imm)
54
-{
55
- TCGv t0 = tcg_temp_new();
56
- TCGv t1 = tcg_temp_new();
57
- gen_get_gpr(t0, rs1);
58
- tcg_gen_addi_tl(t0, t0, imm);
59
- int memop = tcg_memop_lookup[(opc >> 12) & 0x7];
60
-
61
- if (memop < 0) {
62
- gen_exception_illegal(ctx);
63
- return;
64
- }
65
-
66
- tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, memop);
67
- gen_set_gpr(rd, t1);
68
- tcg_temp_free(t0);
69
- tcg_temp_free(t1);
70
-}
71
-
72
-static void gen_store_c(DisasContext *ctx, uint32_t opc, int rs1, int rs2,
73
- target_long imm)
74
-{
75
- TCGv t0 = tcg_temp_new();
76
- TCGv dat = tcg_temp_new();
77
- gen_get_gpr(t0, rs1);
78
- tcg_gen_addi_tl(t0, t0, imm);
79
- gen_get_gpr(dat, rs2);
80
- int memop = tcg_memop_lookup[(opc >> 12) & 0x7];
81
-
82
- if (memop < 0) {
83
- gen_exception_illegal(ctx);
84
- return;
85
- }
86
-
87
- tcg_gen_qemu_st_tl(dat, t0, ctx->mem_idx, memop);
88
- tcg_temp_free(t0);
89
- tcg_temp_free(dat);
90
-}
91
-#endif
92
-
93
#ifndef CONFIG_USER_ONLY
94
/* The states of mstatus_fs are:
95
* 0 = disabled, 1 = initial, 2 = clean, 3 = dirty
96
@@ -XXX,XX +XXX,XX @@ static void mark_fs_dirty(DisasContext *ctx)
97
static inline void mark_fs_dirty(DisasContext *ctx) { }
98
#endif
99
100
-#if !defined(TARGET_RISCV64)
101
-static void gen_fp_load(DisasContext *ctx, uint32_t opc, int rd,
102
- int rs1, target_long imm)
103
-{
104
- TCGv t0;
105
-
106
- if (ctx->mstatus_fs == 0) {
107
- gen_exception_illegal(ctx);
108
- return;
109
- }
110
-
111
- t0 = tcg_temp_new();
112
- gen_get_gpr(t0, rs1);
113
- tcg_gen_addi_tl(t0, t0, imm);
114
-
115
- switch (opc) {
116
- case OPC_RISC_FLW:
117
- if (!has_ext(ctx, RVF)) {
118
- goto do_illegal;
119
- }
120
- tcg_gen_qemu_ld_i64(cpu_fpr[rd], t0, ctx->mem_idx, MO_TEUL);
121
- /* RISC-V requires NaN-boxing of narrower width floating point values */
122
- tcg_gen_ori_i64(cpu_fpr[rd], cpu_fpr[rd], 0xffffffff00000000ULL);
123
- break;
124
- case OPC_RISC_FLD:
125
- if (!has_ext(ctx, RVD)) {
126
- goto do_illegal;
127
- }
128
- tcg_gen_qemu_ld_i64(cpu_fpr[rd], t0, ctx->mem_idx, MO_TEQ);
129
- break;
130
- do_illegal:
131
- default:
132
- gen_exception_illegal(ctx);
133
- break;
134
- }
135
- tcg_temp_free(t0);
136
-
137
- mark_fs_dirty(ctx);
138
-}
139
-
140
-static void gen_fp_store(DisasContext *ctx, uint32_t opc, int rs1,
141
- int rs2, target_long imm)
142
-{
143
- TCGv t0;
144
-
145
- if (ctx->mstatus_fs == 0) {
146
- gen_exception_illegal(ctx);
147
- return;
148
- }
149
-
150
- t0 = tcg_temp_new();
151
- gen_get_gpr(t0, rs1);
152
- tcg_gen_addi_tl(t0, t0, imm);
153
-
154
- switch (opc) {
155
- case OPC_RISC_FSW:
156
- if (!has_ext(ctx, RVF)) {
157
- goto do_illegal;
158
- }
159
- tcg_gen_qemu_st_i64(cpu_fpr[rs2], t0, ctx->mem_idx, MO_TEUL);
160
- break;
161
- case OPC_RISC_FSD:
162
- if (!has_ext(ctx, RVD)) {
163
- goto do_illegal;
164
- }
165
- tcg_gen_qemu_st_i64(cpu_fpr[rs2], t0, ctx->mem_idx, MO_TEQ);
166
- break;
167
- do_illegal:
168
- default:
169
- gen_exception_illegal(ctx);
170
- break;
171
- }
172
-
173
- tcg_temp_free(t0);
174
-}
175
-#endif
176
-
177
static void gen_set_rm(DisasContext *ctx, int rm)
178
{
179
TCGv_i32 t0;
180
@@ -XXX,XX +XXX,XX @@ static void gen_set_rm(DisasContext *ctx, int rm)
181
tcg_temp_free_i32(t0);
182
}
183
184
-static void decode_RV32_64C0(DisasContext *ctx, uint16_t opcode)
185
-{
186
- uint8_t funct3 = extract16(opcode, 13, 3);
187
- uint8_t rd_rs2 = GET_C_RS2S(opcode);
188
- uint8_t rs1s = GET_C_RS1S(opcode);
189
-
190
- switch (funct3) {
191
- case 3:
192
-#if defined(TARGET_RISCV64)
193
- /* C.LD(RV64/128) -> ld rd', offset[7:3](rs1')*/
194
- gen_load_c(ctx, OPC_RISC_LD, rd_rs2, rs1s,
195
- GET_C_LD_IMM(opcode));
196
-#else
197
- /* C.FLW (RV32) -> flw rd', offset[6:2](rs1')*/
198
- gen_fp_load(ctx, OPC_RISC_FLW, rd_rs2, rs1s,
199
- GET_C_LW_IMM(opcode));
200
-#endif
201
- break;
202
- case 7:
203
-#if defined(TARGET_RISCV64)
204
- /* C.SD (RV64/128) -> sd rs2', offset[7:3](rs1')*/
205
- gen_store_c(ctx, OPC_RISC_SD, rs1s, rd_rs2,
206
- GET_C_LD_IMM(opcode));
207
-#else
208
- /* C.FSW (RV32) -> fsw rs2', offset[6:2](rs1')*/
209
- gen_fp_store(ctx, OPC_RISC_FSW, rs1s, rd_rs2,
210
- GET_C_LW_IMM(opcode));
211
-#endif
212
- break;
213
- }
214
-}
215
-
216
-static void decode_RV32_64C(DisasContext *ctx, uint16_t opcode)
217
-{
218
- uint8_t op = extract16(opcode, 0, 2);
219
-
220
- switch (op) {
221
- case 0:
222
- decode_RV32_64C0(ctx, opcode);
223
- break;
224
- }
225
-}
226
-
227
static int ex_plus_1(DisasContext *ctx, int nf)
228
{
229
return nf + 1;
230
@@ -XXX,XX +XXX,XX @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
231
} else {
232
ctx->pc_succ_insn = ctx->base.pc_next + 2;
233
if (!decode_insn16(ctx, opcode)) {
234
- /* fall back to old decoder */
235
- decode_RV32_64C(ctx, opcode);
236
+ gen_exception_illegal(ctx);
237
}
238
}
239
} else {
240
--
31
--
241
2.30.1
32
2.27.0
242
33
243
34
diff view generated by jsdifflib
1
From: Bin Meng <bin.meng@windriver.com>
1
From: Bin Meng <bin.meng@windriver.com>
2
2
3
This adds the documentation to describe what is supported for the
3
Adjust the PCIe memory maps to follow the order.
4
'microchip-icicle-kit' machine, and how to boot the machine in QEMU.
5
4
6
Signed-off-by: Bin Meng <bin.meng@windriver.com>
5
Signed-off-by: Bin Meng <bin.meng@windriver.com>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
6
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Message-id: 20210322075248.136255-2-bmeng.cn@gmail.com
7
Message-Id: <1593746511-19517-1-git-send-email-bmeng.cn@gmail.com>
9
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
8
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
10
---
9
---
11
docs/system/riscv/microchip-icicle-kit.rst | 89 ++++++++++++++++++++++
10
hw/riscv/virt.c | 6 +++---
12
docs/system/target-riscv.rst | 1 +
11
1 file changed, 3 insertions(+), 3 deletions(-)
13
2 files changed, 90 insertions(+)
14
create mode 100644 docs/system/riscv/microchip-icicle-kit.rst
15
12
16
diff --git a/docs/system/riscv/microchip-icicle-kit.rst b/docs/system/riscv/microchip-icicle-kit.rst
13
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
17
new file mode 100644
18
index XXXXXXX..XXXXXXX
19
--- /dev/null
20
+++ b/docs/system/riscv/microchip-icicle-kit.rst
21
@@ -XXX,XX +XXX,XX @@
22
+Microchip PolarFire SoC Icicle Kit (``microchip-icicle-kit``)
23
+=============================================================
24
+
25
+Microchip PolarFire SoC Icicle Kit integrates a PolarFire SoC, with one
26
+SiFive's E51 plus four U54 cores and many on-chip peripherals and an FPGA.
27
+
28
+For more details about Microchip PolarFire SoC, please see:
29
+https://www.microsemi.com/product-directory/soc-fpgas/5498-polarfire-soc-fpga
30
+
31
+The Icicle Kit board information can be found here:
32
+https://www.microsemi.com/existing-parts/parts/152514
33
+
34
+Supported devices
35
+-----------------
36
+
37
+The ``microchip-icicle-kit`` machine supports the following devices:
38
+
39
+ * 1 E51 core
40
+ * 4 U54 cores
41
+ * Core Level Interruptor (CLINT)
42
+ * Platform-Level Interrupt Controller (PLIC)
43
+ * L2 Loosely Integrated Memory (L2-LIM)
44
+ * DDR memory controller
45
+ * 5 MMUARTs
46
+ * 1 DMA controller
47
+ * 2 GEM Ethernet controllers
48
+ * 1 SDHC storage controller
49
+
50
+Boot options
51
+------------
52
+
53
+The ``microchip-icicle-kit`` machine can start using the standard -bios
54
+functionality for loading its BIOS image, aka Hart Software Services (HSS_).
55
+HSS loads the second stage bootloader U-Boot from an SD card. It does not
56
+support direct kernel loading via the -kernel option. One has to load kernel
57
+from U-Boot.
58
+
59
+The memory is set to 1537 MiB by default which is the minimum required high
60
+memory size by HSS. A sanity check on ram size is performed in the machine
61
+init routine to prompt user to increase the RAM size to > 1537 MiB when less
62
+than 1537 MiB ram is detected.
63
+
64
+Boot the machine
65
+----------------
66
+
67
+HSS 2020.12 release is tested at the time of writing. To build an HSS image
68
+that can be booted by the ``microchip-icicle-kit`` machine, type the following
69
+in the HSS source tree:
70
+
71
+.. code-block:: bash
72
+
73
+ $ export CROSS_COMPILE=riscv64-linux-
74
+ $ cp boards/mpfs-icicle-kit-es/def_config .config
75
+ $ make BOARD=mpfs-icicle-kit-es
76
+
77
+Download the official SD card image released by Microchip and prepare it for
78
+QEMU usage:
79
+
80
+.. code-block:: bash
81
+
82
+ $ wget ftp://ftpsoc.microsemi.com/outgoing/core-image-minimal-dev-icicle-kit-es-sd-20201009141623.rootfs.wic.gz
83
+ $ gunzip core-image-minimal-dev-icicle-kit-es-sd-20201009141623.rootfs.wic.gz
84
+ $ qemu-img resize core-image-minimal-dev-icicle-kit-es-sd-20201009141623.rootfs.wic 4G
85
+
86
+Then we can boot the machine by:
87
+
88
+.. code-block:: bash
89
+
90
+ $ qemu-system-riscv64 -M microchip-icicle-kit -smp 5 \
91
+ -bios path/to/hss.bin -sd path/to/sdcard.img \
92
+ -nic user,model=cadence_gem \
93
+ -nic tap,ifname=tap,model=cadence_gem,script=no \
94
+ -display none -serial stdio \
95
+ -chardev socket,id=serial1,path=serial1.sock,server=on,wait=on \
96
+ -serial chardev:serial1
97
+
98
+With above command line, current terminal session will be used for the first
99
+serial port. Open another terminal window, and use `minicom` to connect the
100
+second serial port.
101
+
102
+.. code-block:: bash
103
+
104
+ $ minicom -D unix\#serial1.sock
105
+
106
+HSS output is on the first serial port (stdio) and U-Boot outputs on the
107
+second serial port. U-Boot will automatically load the Linux kernel from
108
+the SD card image.
109
+
110
+.. _HSS: https://github.com/polarfire-soc/hart-software-services
111
diff --git a/docs/system/target-riscv.rst b/docs/system/target-riscv.rst
112
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
113
--- a/docs/system/target-riscv.rst
15
--- a/hw/riscv/virt.c
114
+++ b/docs/system/target-riscv.rst
16
+++ b/hw/riscv/virt.c
115
@@ -XXX,XX +XXX,XX @@ undocumented; you can get a complete list by running
17
@@ -XXX,XX +XXX,XX @@ static const struct MemmapEntry {
116
.. toctree::
18
[VIRT_TEST] = { 0x100000, 0x1000 },
117
:maxdepth: 1
19
[VIRT_RTC] = { 0x101000, 0x1000 },
118
20
[VIRT_CLINT] = { 0x2000000, 0x10000 },
119
+ riscv/microchip-icicle-kit
21
+ [VIRT_PCIE_PIO] = { 0x3000000, 0x10000 },
120
riscv/sifive_u
22
[VIRT_PLIC] = { 0xc000000, 0x4000000 },
121
23
[VIRT_UART0] = { 0x10000000, 0x100 },
122
RISC-V CPU features
24
[VIRT_VIRTIO] = { 0x10001000, 0x1000 },
25
[VIRT_FLASH] = { 0x20000000, 0x4000000 },
26
- [VIRT_DRAM] = { 0x80000000, 0x0 },
27
- [VIRT_PCIE_MMIO] = { 0x40000000, 0x40000000 },
28
- [VIRT_PCIE_PIO] = { 0x03000000, 0x00010000 },
29
[VIRT_PCIE_ECAM] = { 0x30000000, 0x10000000 },
30
+ [VIRT_PCIE_MMIO] = { 0x40000000, 0x40000000 },
31
+ [VIRT_DRAM] = { 0x80000000, 0x0 },
32
};
33
34
#define VIRT_FLASH_SECTOR_SIZE (256 * KiB)
123
--
35
--
124
2.30.1
36
2.27.0
125
37
126
38
diff view generated by jsdifflib
1
From: Asherah Connor <ashe@kivikakk.ee>
1
From: Atish Patra <atish.patra@wdc.com>
2
2
3
Allow ramfb on virt. This lets `-device ramfb' work.
3
Currently, all riscv machines except sifive_u have identical reset vector
4
4
code implementations with memory addresses being different for all machines.
5
Signed-off-by: Asherah Connor <ashe@kivikakk.ee>
5
They can be easily combined into a single function in common code.
6
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
6
7
Move it to common function and let all the machines use the common function.
8
9
Signed-off-by: Atish Patra <atish.patra@wdc.com>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Message-id: 20210318235041.17175-3-ashe@kivikakk.ee
11
Reviewed-by: Bin Meng <bin.meng@windriver.com>
12
Tested-by: Bin Meng <bin.meng@windriver.com>
13
Message-Id: <20200701183949.398134-2-atish.patra@wdc.com>
9
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
14
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
10
---
15
---
11
hw/riscv/virt.c | 3 +++
16
include/hw/riscv/boot.h | 2 ++
12
1 file changed, 3 insertions(+)
17
hw/riscv/boot.c | 46 +++++++++++++++++++++++++++++++++++++++++
13
18
hw/riscv/sifive_u.c | 1 -
19
hw/riscv/spike.c | 41 +++---------------------------------
20
hw/riscv/virt.c | 40 +++--------------------------------
21
5 files changed, 54 insertions(+), 76 deletions(-)
22
23
diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h
24
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/riscv/boot.h
26
+++ b/include/hw/riscv/boot.h
27
@@ -XXX,XX +XXX,XX @@ target_ulong riscv_load_kernel(const char *kernel_filename,
28
symbol_fn_t sym_cb);
29
hwaddr riscv_load_initrd(const char *filename, uint64_t mem_size,
30
uint64_t kernel_entry, hwaddr *start);
31
+void riscv_setup_rom_reset_vec(hwaddr saddr, hwaddr rom_base,
32
+ hwaddr rom_size, void *fdt);
33
34
#endif /* RISCV_BOOT_H */
35
diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/hw/riscv/boot.c
38
+++ b/hw/riscv/boot.c
39
@@ -XXX,XX +XXX,XX @@
40
#include "hw/loader.h"
41
#include "hw/riscv/boot.h"
42
#include "elf.h"
43
+#include "sysemu/device_tree.h"
44
#include "sysemu/qtest.h"
45
46
+#include <libfdt.h>
47
+
48
#if defined(TARGET_RISCV32)
49
# define KERNEL_BOOT_ADDRESS 0x80400000
50
#else
51
@@ -XXX,XX +XXX,XX @@ hwaddr riscv_load_initrd(const char *filename, uint64_t mem_size,
52
53
return *start + size;
54
}
55
+
56
+void riscv_setup_rom_reset_vec(hwaddr start_addr, hwaddr rom_base,
57
+ hwaddr rom_size, void *fdt)
58
+{
59
+ int i;
60
+
61
+ /* reset vector */
62
+ uint32_t reset_vec[8] = {
63
+ 0x00000297, /* 1: auipc t0, %pcrel_hi(dtb) */
64
+ 0x02028593, /* addi a1, t0, %pcrel_lo(1b) */
65
+ 0xf1402573, /* csrr a0, mhartid */
66
+#if defined(TARGET_RISCV32)
67
+ 0x0182a283, /* lw t0, 24(t0) */
68
+#elif defined(TARGET_RISCV64)
69
+ 0x0182b283, /* ld t0, 24(t0) */
70
+#endif
71
+ 0x00028067, /* jr t0 */
72
+ 0x00000000,
73
+ start_addr, /* start: .dword */
74
+ 0x00000000,
75
+ /* dtb: */
76
+ };
77
+
78
+ /* copy in the reset vector in little_endian byte order */
79
+ for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
80
+ reset_vec[i] = cpu_to_le32(reset_vec[i]);
81
+ }
82
+ rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
83
+ rom_base, &address_space_memory);
84
+
85
+ /* copy in the device tree */
86
+ if (fdt_pack(fdt) || fdt_totalsize(fdt) >
87
+ rom_size - sizeof(reset_vec)) {
88
+ error_report("not enough space to store device-tree");
89
+ exit(1);
90
+ }
91
+ qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
92
+ rom_add_blob_fixed_as("mrom.fdt", fdt, fdt_totalsize(fdt),
93
+ rom_base + sizeof(reset_vec),
94
+ &address_space_memory);
95
+
96
+ return;
97
+}
98
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
99
index XXXXXXX..XXXXXXX 100644
100
--- a/hw/riscv/sifive_u.c
101
+++ b/hw/riscv/sifive_u.c
102
@@ -XXX,XX +XXX,XX @@
103
#include "sysemu/device_tree.h"
104
#include "sysemu/runstate.h"
105
#include "sysemu/sysemu.h"
106
-#include "exec/address-spaces.h"
107
108
#include <libfdt.h>
109
110
diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
111
index XXXXXXX..XXXXXXX 100644
112
--- a/hw/riscv/spike.c
113
+++ b/hw/riscv/spike.c
114
@@ -XXX,XX +XXX,XX @@
115
#include "sysemu/device_tree.h"
116
#include "sysemu/qtest.h"
117
#include "sysemu/sysemu.h"
118
-#include "exec/address-spaces.h"
119
-
120
-#include <libfdt.h>
121
122
#if defined(TARGET_RISCV32)
123
# define BIOS_FILENAME "opensbi-riscv32-spike-fw_jump.elf"
124
@@ -XXX,XX +XXX,XX @@ static void spike_board_init(MachineState *machine)
125
MemoryRegion *system_memory = get_system_memory();
126
MemoryRegion *main_mem = g_new(MemoryRegion, 1);
127
MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
128
- int i;
129
unsigned int smp_cpus = machine->smp.cpus;
130
131
/* Initialize SOC */
132
@@ -XXX,XX +XXX,XX @@ static void spike_board_init(MachineState *machine)
133
}
134
}
135
136
- /* reset vector */
137
- uint32_t reset_vec[8] = {
138
- 0x00000297, /* 1: auipc t0, %pcrel_hi(dtb) */
139
- 0x02028593, /* addi a1, t0, %pcrel_lo(1b) */
140
- 0xf1402573, /* csrr a0, mhartid */
141
-#if defined(TARGET_RISCV32)
142
- 0x0182a283, /* lw t0, 24(t0) */
143
-#elif defined(TARGET_RISCV64)
144
- 0x0182b283, /* ld t0, 24(t0) */
145
-#endif
146
- 0x00028067, /* jr t0 */
147
- 0x00000000,
148
- memmap[SPIKE_DRAM].base, /* start: .dword DRAM_BASE */
149
- 0x00000000,
150
- /* dtb: */
151
- };
152
-
153
- /* copy in the reset vector in little_endian byte order */
154
- for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
155
- reset_vec[i] = cpu_to_le32(reset_vec[i]);
156
- }
157
- rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
158
- memmap[SPIKE_MROM].base, &address_space_memory);
159
-
160
- /* copy in the device tree */
161
- if (fdt_pack(s->fdt) || fdt_totalsize(s->fdt) >
162
- memmap[SPIKE_MROM].size - sizeof(reset_vec)) {
163
- error_report("not enough space to store device-tree");
164
- exit(1);
165
- }
166
- qemu_fdt_dumpdtb(s->fdt, fdt_totalsize(s->fdt));
167
- rom_add_blob_fixed_as("mrom.fdt", s->fdt, fdt_totalsize(s->fdt),
168
- memmap[SPIKE_MROM].base + sizeof(reset_vec),
169
- &address_space_memory);
170
+ /* load the reset vector */
171
+ riscv_setup_rom_reset_vec(memmap[SPIKE_DRAM].base, memmap[SPIKE_MROM].base,
172
+ memmap[SPIKE_MROM].size, s->fdt);
173
174
/* initialize HTIF using symbols found in load_kernel */
175
htif_mm_init(system_memory, mask_rom, &s->soc.harts[0].env, serial_hd(0));
14
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
176
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
15
index XXXXXXX..XXXXXXX 100644
177
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/riscv/virt.c
178
--- a/hw/riscv/virt.c
17
+++ b/hw/riscv/virt.c
179
+++ b/hw/riscv/virt.c
18
@@ -XXX,XX +XXX,XX @@
180
@@ -XXX,XX +XXX,XX @@
181
#include "sysemu/arch_init.h"
182
#include "sysemu/device_tree.h"
19
#include "sysemu/sysemu.h"
183
#include "sysemu/sysemu.h"
184
-#include "exec/address-spaces.h"
20
#include "hw/pci/pci.h"
185
#include "hw/pci/pci.h"
21
#include "hw/pci-host/gpex.h"
186
#include "hw/pci-host/gpex.h"
22
+#include "hw/display/ramfb.h"
187
23
188
-#include <libfdt.h>
24
static const MemMapEntry virt_memmap[] = {
189
-
25
[VIRT_DEBUG] = { 0x0, 0x100 },
190
#if defined(TARGET_RISCV32)
26
@@ -XXX,XX +XXX,XX @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
191
# define BIOS_FILENAME "opensbi-riscv32-virt-fw_jump.bin"
27
mc->cpu_index_to_instance_props = riscv_numa_cpu_index_to_props;
192
#else
28
mc->get_default_cpu_node_id = riscv_numa_get_default_cpu_node_id;
193
@@ -XXX,XX +XXX,XX @@ static void virt_machine_init(MachineState *machine)
29
mc->numa_mem_supported = true;
194
start_addr = virt_memmap[VIRT_FLASH].base;
30
+
195
}
31
+ machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
196
32
}
197
- /* reset vector */
33
198
- uint32_t reset_vec[8] = {
34
static const TypeInfo virt_machine_typeinfo = {
199
- 0x00000297, /* 1: auipc t0, %pcrel_hi(dtb) */
200
- 0x02028593, /* addi a1, t0, %pcrel_lo(1b) */
201
- 0xf1402573, /* csrr a0, mhartid */
202
-#if defined(TARGET_RISCV32)
203
- 0x0182a283, /* lw t0, 24(t0) */
204
-#elif defined(TARGET_RISCV64)
205
- 0x0182b283, /* ld t0, 24(t0) */
206
-#endif
207
- 0x00028067, /* jr t0 */
208
- 0x00000000,
209
- start_addr, /* start: .dword */
210
- 0x00000000,
211
- /* dtb: */
212
- };
213
-
214
- /* copy in the reset vector in little_endian byte order */
215
- for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
216
- reset_vec[i] = cpu_to_le32(reset_vec[i]);
217
- }
218
- rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
219
- memmap[VIRT_MROM].base, &address_space_memory);
220
-
221
- /* copy in the device tree */
222
- if (fdt_pack(s->fdt) || fdt_totalsize(s->fdt) >
223
- memmap[VIRT_MROM].size - sizeof(reset_vec)) {
224
- error_report("not enough space to store device-tree");
225
- exit(1);
226
- }
227
- qemu_fdt_dumpdtb(s->fdt, fdt_totalsize(s->fdt));
228
- rom_add_blob_fixed_as("mrom.fdt", s->fdt, fdt_totalsize(s->fdt),
229
- memmap[VIRT_MROM].base + sizeof(reset_vec),
230
- &address_space_memory);
231
+ /* load the reset vector */
232
+ riscv_setup_rom_reset_vec(start_addr, virt_memmap[VIRT_MROM].base,
233
+ virt_memmap[VIRT_MROM].size, s->fdt);
234
235
/* create PLIC hart topology configuration string */
236
plic_hart_config_len = (strlen(VIRT_PLIC_HART_CONFIG) + 1) * smp_cpus;
35
--
237
--
36
2.30.1
238
2.27.0
37
239
38
240
diff view generated by jsdifflib
1
From: Asherah Connor <ashe@kivikakk.ee>
1
From: Atish Patra <atish.patra@wdc.com>
2
2
3
Provides fw_cfg for the virt machine on riscv. This enables
3
Currently, the fdt is copied to the ROM after the reset vector. The firmware
4
using e.g. ramfb later.
4
has to copy it to DRAM. Instead of this, directly copy the device tree to a
5
5
pre-computed dram address. The device tree load address should be as far as
6
Signed-off-by: Asherah Connor <ashe@kivikakk.ee>
6
possible from kernel and initrd images. That's why it is kept at the end of
7
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
7
the DRAM or 4GB whichever is lesser.
8
9
Signed-off-by: Atish Patra <atish.patra@wdc.com>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Message-id: 20210318235041.17175-2-ashe@kivikakk.ee
11
Reviewed-by: Bin Meng <bin.meng@windriver.com>
12
Tested-by: Bin Meng <bin.meng@windriver.com>
13
Message-Id: <20200701183949.398134-3-atish.patra@wdc.com>
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
14
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
---
15
---
12
include/hw/riscv/virt.h | 2 ++
16
include/hw/riscv/boot.h | 4 +++-
13
hw/riscv/virt.c | 30 ++++++++++++++++++++++++++++++
17
hw/riscv/boot.c | 53 +++++++++++++++++++++++++++++------------
14
hw/riscv/Kconfig | 1 +
18
hw/riscv/sifive_u.c | 28 ++++++++++------------
15
3 files changed, 33 insertions(+)
19
hw/riscv/spike.c | 7 +++++-
16
20
hw/riscv/virt.c | 7 +++++-
17
diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
21
5 files changed, 66 insertions(+), 33 deletions(-)
18
index XXXXXXX..XXXXXXX 100644
22
19
--- a/include/hw/riscv/virt.h
23
diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h
20
+++ b/include/hw/riscv/virt.h
24
index XXXXXXX..XXXXXXX 100644
21
@@ -XXX,XX +XXX,XX @@ struct RISCVVirtState {
25
--- a/include/hw/riscv/boot.h
22
RISCVHartArrayState soc[VIRT_SOCKETS_MAX];
26
+++ b/include/hw/riscv/boot.h
23
DeviceState *plic[VIRT_SOCKETS_MAX];
27
@@ -XXX,XX +XXX,XX @@ target_ulong riscv_load_kernel(const char *kernel_filename,
24
PFlashCFI01 *flash[2];
28
symbol_fn_t sym_cb);
25
+ FWCfgState *fw_cfg;
29
hwaddr riscv_load_initrd(const char *filename, uint64_t mem_size,
26
30
uint64_t kernel_entry, hwaddr *start);
27
int fdt_size;
31
+uint32_t riscv_load_fdt(hwaddr dram_start, uint64_t dram_size, void *fdt);
28
};
32
void riscv_setup_rom_reset_vec(hwaddr saddr, hwaddr rom_base,
29
@@ -XXX,XX +XXX,XX @@ enum {
33
- hwaddr rom_size, void *fdt);
30
VIRT_PLIC,
34
+ hwaddr rom_size,
31
VIRT_UART0,
35
+ uint32_t fdt_load_addr, void *fdt);
32
VIRT_VIRTIO,
36
33
+ VIRT_FW_CFG,
37
#endif /* RISCV_BOOT_H */
34
VIRT_FLASH,
38
diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
35
VIRT_DRAM,
39
index XXXXXXX..XXXXXXX 100644
36
VIRT_PCIE_MMIO,
40
--- a/hw/riscv/boot.c
41
+++ b/hw/riscv/boot.c
42
@@ -XXX,XX +XXX,XX @@ hwaddr riscv_load_initrd(const char *filename, uint64_t mem_size,
43
return *start + size;
44
}
45
46
+uint32_t riscv_load_fdt(hwaddr dram_base, uint64_t mem_size, void *fdt)
47
+{
48
+ uint32_t temp, fdt_addr;
49
+ hwaddr dram_end = dram_base + mem_size;
50
+ int fdtsize = fdt_totalsize(fdt);
51
+
52
+ if (fdtsize <= 0) {
53
+ error_report("invalid device-tree");
54
+ exit(1);
55
+ }
56
+
57
+ /*
58
+ * We should put fdt as far as possible to avoid kernel/initrd overwriting
59
+ * its content. But it should be addressable by 32 bit system as well.
60
+ * Thus, put it at an aligned address that less than fdt size from end of
61
+ * dram or 4GB whichever is lesser.
62
+ */
63
+ temp = MIN(dram_end, 4096 * MiB);
64
+ fdt_addr = QEMU_ALIGN_DOWN(temp - fdtsize, 2 * MiB);
65
+
66
+ fdt_pack(fdt);
67
+ /* copy in the device tree */
68
+ qemu_fdt_dumpdtb(fdt, fdtsize);
69
+
70
+ rom_add_blob_fixed_as("fdt", fdt, fdtsize, fdt_addr,
71
+ &address_space_memory);
72
+
73
+ return fdt_addr;
74
+}
75
+
76
void riscv_setup_rom_reset_vec(hwaddr start_addr, hwaddr rom_base,
77
- hwaddr rom_size, void *fdt)
78
+ hwaddr rom_size,
79
+ uint32_t fdt_load_addr, void *fdt)
80
{
81
int i;
82
83
/* reset vector */
84
- uint32_t reset_vec[8] = {
85
+ uint32_t reset_vec[10] = {
86
0x00000297, /* 1: auipc t0, %pcrel_hi(dtb) */
87
- 0x02028593, /* addi a1, t0, %pcrel_lo(1b) */
88
0xf1402573, /* csrr a0, mhartid */
89
#if defined(TARGET_RISCV32)
90
+ 0x0202a583, /* lw a1, 32(t0) */
91
0x0182a283, /* lw t0, 24(t0) */
92
#elif defined(TARGET_RISCV64)
93
+ 0x0202b583, /* ld a1, 32(t0) */
94
0x0182b283, /* ld t0, 24(t0) */
95
#endif
96
0x00028067, /* jr t0 */
97
0x00000000,
98
start_addr, /* start: .dword */
99
+ 0x00000000,
100
+ fdt_load_addr, /* fdt_laddr: .dword */
101
0x00000000,
102
/* dtb: */
103
};
104
105
/* copy in the reset vector in little_endian byte order */
106
- for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
107
+ for (i = 0; i < ARRAY_SIZE(reset_vec); i++) {
108
reset_vec[i] = cpu_to_le32(reset_vec[i]);
109
}
110
rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
111
rom_base, &address_space_memory);
112
113
- /* copy in the device tree */
114
- if (fdt_pack(fdt) || fdt_totalsize(fdt) >
115
- rom_size - sizeof(reset_vec)) {
116
- error_report("not enough space to store device-tree");
117
- exit(1);
118
- }
119
- qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
120
- rom_add_blob_fixed_as("mrom.fdt", fdt, fdt_totalsize(fdt),
121
- rom_base + sizeof(reset_vec),
122
- &address_space_memory);
123
-
124
return;
125
}
126
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
127
index XXXXXXX..XXXXXXX 100644
128
--- a/hw/riscv/sifive_u.c
129
+++ b/hw/riscv/sifive_u.c
130
@@ -XXX,XX +XXX,XX @@ static void sifive_u_machine_init(MachineState *machine)
131
MemoryRegion *flash0 = g_new(MemoryRegion, 1);
132
target_ulong start_addr = memmap[SIFIVE_U_DRAM].base;
133
int i;
134
+ uint32_t fdt_load_addr;
135
136
/* Initialize SoC */
137
object_initialize_child(OBJECT(machine), "soc", &s->soc, TYPE_RISCV_U_SOC);
138
@@ -XXX,XX +XXX,XX @@ static void sifive_u_machine_init(MachineState *machine)
139
}
140
}
141
142
+ /* Compute the fdt load address in dram */
143
+ fdt_load_addr = riscv_load_fdt(memmap[SIFIVE_U_DRAM].base,
144
+ machine->ram_size, s->fdt);
145
+
146
/* reset vector */
147
- uint32_t reset_vec[8] = {
148
+ uint32_t reset_vec[11] = {
149
s->msel, /* MSEL pin state */
150
0x00000297, /* 1: auipc t0, %pcrel_hi(dtb) */
151
- 0x01c28593, /* addi a1, t0, %pcrel_lo(1b) */
152
0xf1402573, /* csrr a0, mhartid */
153
#if defined(TARGET_RISCV32)
154
+ 0x0202a583, /* lw a1, 32(t0) */
155
0x0182a283, /* lw t0, 24(t0) */
156
#elif defined(TARGET_RISCV64)
157
- 0x0182e283, /* lwu t0, 24(t0) */
158
+ 0x0202b583, /* ld a1, 32(t0) */
159
+ 0x0182b283, /* ld t0, 24(t0) */
160
#endif
161
0x00028067, /* jr t0 */
162
0x00000000,
163
start_addr, /* start: .dword */
164
+ 0x00000000,
165
+ fdt_load_addr, /* fdt_laddr: .dword */
166
+ 0x00000000,
167
/* dtb: */
168
};
169
170
/* copy in the reset vector in little_endian byte order */
171
- for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
172
+ for (i = 0; i < ARRAY_SIZE(reset_vec); i++) {
173
reset_vec[i] = cpu_to_le32(reset_vec[i]);
174
}
175
rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
176
memmap[SIFIVE_U_MROM].base, &address_space_memory);
177
-
178
- /* copy in the device tree */
179
- if (fdt_pack(s->fdt) || fdt_totalsize(s->fdt) >
180
- memmap[SIFIVE_U_MROM].size - sizeof(reset_vec)) {
181
- error_report("not enough space to store device-tree");
182
- exit(1);
183
- }
184
- qemu_fdt_dumpdtb(s->fdt, fdt_totalsize(s->fdt));
185
- rom_add_blob_fixed_as("mrom.fdt", s->fdt, fdt_totalsize(s->fdt),
186
- memmap[SIFIVE_U_MROM].base + sizeof(reset_vec),
187
- &address_space_memory);
188
}
189
190
static bool sifive_u_machine_get_start_in_flash(Object *obj, Error **errp)
191
diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
192
index XXXXXXX..XXXXXXX 100644
193
--- a/hw/riscv/spike.c
194
+++ b/hw/riscv/spike.c
195
@@ -XXX,XX +XXX,XX @@ static void spike_board_init(MachineState *machine)
196
MemoryRegion *main_mem = g_new(MemoryRegion, 1);
197
MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
198
unsigned int smp_cpus = machine->smp.cpus;
199
+ uint32_t fdt_load_addr;
200
201
/* Initialize SOC */
202
object_initialize_child(OBJECT(machine), "soc", &s->soc,
203
@@ -XXX,XX +XXX,XX @@ static void spike_board_init(MachineState *machine)
204
}
205
}
206
207
+ /* Compute the fdt load address in dram */
208
+ fdt_load_addr = riscv_load_fdt(memmap[SPIKE_DRAM].base,
209
+ machine->ram_size, s->fdt);
210
/* load the reset vector */
211
riscv_setup_rom_reset_vec(memmap[SPIKE_DRAM].base, memmap[SPIKE_MROM].base,
212
- memmap[SPIKE_MROM].size, s->fdt);
213
+ memmap[SPIKE_MROM].size,
214
+ fdt_load_addr, s->fdt);
215
216
/* initialize HTIF using symbols found in load_kernel */
217
htif_mm_init(system_memory, mask_rom, &s->soc.harts[0].env, serial_hd(0));
37
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
218
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
38
index XXXXXXX..XXXXXXX 100644
219
index XXXXXXX..XXXXXXX 100644
39
--- a/hw/riscv/virt.c
220
--- a/hw/riscv/virt.c
40
+++ b/hw/riscv/virt.c
221
+++ b/hw/riscv/virt.c
41
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry virt_memmap[] = {
222
@@ -XXX,XX +XXX,XX @@ static void virt_machine_init(MachineState *machine)
42
[VIRT_PLIC] = { 0xc000000, VIRT_PLIC_SIZE(VIRT_CPUS_MAX * 2) },
223
char *plic_hart_config;
43
[VIRT_UART0] = { 0x10000000, 0x100 },
224
size_t plic_hart_config_len;
44
[VIRT_VIRTIO] = { 0x10001000, 0x1000 },
225
target_ulong start_addr = memmap[VIRT_DRAM].base;
45
+ [VIRT_FW_CFG] = { 0x10100000, 0x18 },
226
+ uint32_t fdt_load_addr;
46
[VIRT_FLASH] = { 0x20000000, 0x4000000 },
227
int i;
47
[VIRT_PCIE_ECAM] = { 0x30000000, 0x10000000 },
228
unsigned int smp_cpus = machine->smp.cpus;
48
[VIRT_PCIE_MMIO] = { 0x40000000, 0x40000000 },
229
49
@@ -XXX,XX +XXX,XX @@ static inline DeviceState *gpex_pcie_init(MemoryRegion *sys_mem,
50
return dev;
51
}
52
53
+static FWCfgState *create_fw_cfg(const MachineState *mc)
54
+{
55
+ hwaddr base = virt_memmap[VIRT_FW_CFG].base;
56
+ hwaddr size = virt_memmap[VIRT_FW_CFG].size;
57
+ FWCfgState *fw_cfg;
58
+ char *nodename;
59
+
60
+ fw_cfg = fw_cfg_init_mem_wide(base + 8, base, 8, base + 16,
61
+ &address_space_memory);
62
+ fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)mc->smp.cpus);
63
+
64
+ nodename = g_strdup_printf("/fw-cfg@%" PRIx64, base);
65
+ qemu_fdt_add_subnode(mc->fdt, nodename);
66
+ qemu_fdt_setprop_string(mc->fdt, nodename,
67
+ "compatible", "qemu,fw-cfg-mmio");
68
+ qemu_fdt_setprop_sized_cells(mc->fdt, nodename, "reg",
69
+ 2, base, 2, size);
70
+ qemu_fdt_setprop(mc->fdt, nodename, "dma-coherent", NULL, 0);
71
+ g_free(nodename);
72
+ return fw_cfg;
73
+}
74
+
75
static void virt_machine_init(MachineState *machine)
76
{
77
const MemMapEntry *memmap = virt_memmap;
78
@@ -XXX,XX +XXX,XX @@ static void virt_machine_init(MachineState *machine)
230
@@ -XXX,XX +XXX,XX @@ static void virt_machine_init(MachineState *machine)
79
start_addr = virt_memmap[VIRT_FLASH].base;
231
start_addr = virt_memmap[VIRT_FLASH].base;
80
}
232
}
81
233
82
+ /*
234
+ /* Compute the fdt load address in dram */
83
+ * Init fw_cfg. Must be done before riscv_load_fdt, otherwise the device
235
+ fdt_load_addr = riscv_load_fdt(memmap[VIRT_DRAM].base,
84
+ * tree cannot be altered and we get FDT_ERR_NOSPACE.
236
+ machine->ram_size, s->fdt);
85
+ */
237
/* load the reset vector */
86
+ s->fw_cfg = create_fw_cfg(machine);
238
riscv_setup_rom_reset_vec(start_addr, virt_memmap[VIRT_MROM].base,
87
+ rom_set_fw(s->fw_cfg);
239
- virt_memmap[VIRT_MROM].size, s->fdt);
88
+
240
+ virt_memmap[VIRT_MROM].size,
89
/* Compute the fdt load address in dram */
241
+ fdt_load_addr, s->fdt);
90
fdt_load_addr = riscv_load_fdt(memmap[VIRT_DRAM].base,
242
91
machine->ram_size, machine->fdt);
243
/* create PLIC hart topology configuration string */
92
diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
244
plic_hart_config_len = (strlen(VIRT_PLIC_HART_CONFIG) + 1) * smp_cpus;
93
index XXXXXXX..XXXXXXX 100644
94
--- a/hw/riscv/Kconfig
95
+++ b/hw/riscv/Kconfig
96
@@ -XXX,XX +XXX,XX @@ config RISCV_VIRT
97
select SIFIVE_PLIC
98
select SIFIVE_TEST
99
select VIRTIO_MMIO
100
+ select FW_CFG_DMA
101
102
config SIFIVE_E
103
bool
104
--
245
--
105
2.30.1
246
2.27.0
106
247
107
248
diff view generated by jsdifflib
1
From: Jim Shu <cwshu@andestech.com>
1
From: Atish Patra <atish.patra@wdc.com>
2
2
3
Currently, PMP permission checking of TLB page is bypassed if TLB hits
3
OpenSBI is the default firmware in Qemu and has various firmware loading
4
Fix it by propagating PMP permission to TLB page permission.
4
options. Currently, qemu loader uses fw_jump which has a compile time
5
5
pre-defined address where fdt & kernel image must reside. This puts a
6
PMP permission checking also use MMU-style API to change TLB permission
6
constraint on image size of the Linux kernel depending on the fdt location
7
and size.
7
and available memory. However, fw_dynamic allows the loader to specify
8
8
the next stage location (i.e. Linux kernel/U-Boot) in memory and other
9
Signed-off-by: Jim Shu <cwshu@andestech.com>
9
configurable boot options available in OpenSBI.
10
11
Add support for OpenSBI dynamic firmware loading support. This doesn't
12
break existing setup and fw_jump will continue to work as it is. Any
13
other firmware will continue to work without any issues as long as it
14
doesn't expect anything specific from loader in "a2" register.
15
16
Signed-off-by: Atish Patra <atish.patra@wdc.com>
10
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
17
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
11
Message-id: 1613916082-19528-2-git-send-email-cwshu@andestech.com
18
Reviewed-by: Bin Meng <bin.meng@windriver.com>
19
Tested-by: Bin Meng <bin.meng@windriver.com>
20
Message-Id: <20200701183949.398134-4-atish.patra@wdc.com>
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
21
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
13
---
22
---
14
target/riscv/pmp.h | 4 +-
23
include/hw/riscv/boot.h | 5 ++-
15
target/riscv/cpu_helper.c | 84 +++++++++++++++++++++++++++++----------
24
include/hw/riscv/boot_opensbi.h | 58 +++++++++++++++++++++++++++++++++
16
target/riscv/pmp.c | 80 +++++++++++++++++++++++++++----------
25
hw/riscv/boot.c | 42 +++++++++++++++++++++---
17
3 files changed, 125 insertions(+), 43 deletions(-)
26
hw/riscv/sifive_u.c | 20 +++++++++---
18
27
hw/riscv/spike.c | 13 ++++++--
19
diff --git a/target/riscv/pmp.h b/target/riscv/pmp.h
28
hw/riscv/virt.c | 12 +++++--
20
index XXXXXXX..XXXXXXX 100644
29
6 files changed, 134 insertions(+), 16 deletions(-)
21
--- a/target/riscv/pmp.h
30
create mode 100644 include/hw/riscv/boot_opensbi.h
22
+++ b/target/riscv/pmp.h
31
23
@@ -XXX,XX +XXX,XX @@ void pmpaddr_csr_write(CPURISCVState *env, uint32_t addr_index,
32
diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h
24
target_ulong val);
33
index XXXXXXX..XXXXXXX 100644
25
target_ulong pmpaddr_csr_read(CPURISCVState *env, uint32_t addr_index);
34
--- a/include/hw/riscv/boot.h
26
bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr,
35
+++ b/include/hw/riscv/boot.h
27
- target_ulong size, pmp_priv_t priv, target_ulong mode);
36
@@ -XXX,XX +XXX,XX @@ hwaddr riscv_load_initrd(const char *filename, uint64_t mem_size,
28
+ target_ulong size, pmp_priv_t privs, pmp_priv_t *allowed_privs,
37
uint64_t kernel_entry, hwaddr *start);
29
+ target_ulong mode);
38
uint32_t riscv_load_fdt(hwaddr dram_start, uint64_t dram_size, void *fdt);
30
bool pmp_is_range_in_tlb(CPURISCVState *env, hwaddr tlb_sa,
39
void riscv_setup_rom_reset_vec(hwaddr saddr, hwaddr rom_base,
31
target_ulong *tlb_size);
40
- hwaddr rom_size,
32
void pmp_update_rule_addr(CPURISCVState *env, uint32_t pmp_index);
41
+ hwaddr rom_size, uint64_t kernel_entry,
33
void pmp_update_rule_nums(CPURISCVState *env);
42
uint32_t fdt_load_addr, void *fdt);
34
uint32_t pmp_get_num_rules(CPURISCVState *env);
43
+void riscv_rom_copy_firmware_info(hwaddr rom_base, hwaddr rom_size,
35
+int pmp_priv_to_page_prot(pmp_priv_t pmp_priv);
44
+ uint32_t reset_vec_size,
36
45
+ uint64_t kernel_entry);
46
47
#endif /* RISCV_BOOT_H */
48
diff --git a/include/hw/riscv/boot_opensbi.h b/include/hw/riscv/boot_opensbi.h
49
new file mode 100644
50
index XXXXXXX..XXXXXXX
51
--- /dev/null
52
+++ b/include/hw/riscv/boot_opensbi.h
53
@@ -XXX,XX +XXX,XX @@
54
+/* SPDX-License-Identifier: BSD-2-Clause */
55
+/*
56
+ * Copyright (c) 2019 Western Digital Corporation or its affiliates.
57
+ *
58
+ * Based on include/sbi/{fw_dynamic.h,sbi_scratch.h} from the OpenSBI project.
59
+ */
60
+#ifndef OPENSBI_H
61
+#define OPENSBI_H
62
+
63
+/** Expected value of info magic ('OSBI' ascii string in hex) */
64
+#define FW_DYNAMIC_INFO_MAGIC_VALUE 0x4942534f
65
+
66
+/** Maximum supported info version */
67
+#define FW_DYNAMIC_INFO_VERSION 0x2
68
+
69
+/** Possible next mode values */
70
+#define FW_DYNAMIC_INFO_NEXT_MODE_U 0x0
71
+#define FW_DYNAMIC_INFO_NEXT_MODE_S 0x1
72
+#define FW_DYNAMIC_INFO_NEXT_MODE_M 0x3
73
+
74
+enum sbi_scratch_options {
75
+ /** Disable prints during boot */
76
+ SBI_SCRATCH_NO_BOOT_PRINTS = (1 << 0),
77
+ /** Enable runtime debug prints */
78
+ SBI_SCRATCH_DEBUG_PRINTS = (1 << 1),
79
+};
80
+
81
+/** Representation dynamic info passed by previous booting stage */
82
+struct fw_dynamic_info {
83
+ /** Info magic */
84
+ target_long magic;
85
+ /** Info version */
86
+ target_long version;
87
+ /** Next booting stage address */
88
+ target_long next_addr;
89
+ /** Next booting stage mode */
90
+ target_long next_mode;
91
+ /** Options for OpenSBI library */
92
+ target_long options;
93
+ /**
94
+ * Preferred boot HART id
95
+ *
96
+ * It is possible that the previous booting stage uses same link
97
+ * address as the FW_DYNAMIC firmware. In this case, the relocation
98
+ * lottery mechanism can potentially overwrite the previous booting
99
+ * stage while other HARTs are still running in the previous booting
100
+ * stage leading to boot-time crash. To avoid this boot-time crash,
101
+ * the previous booting stage can specify last HART that will jump
102
+ * to the FW_DYNAMIC firmware as the preferred boot HART.
103
+ *
104
+ * To avoid specifying a preferred boot HART, the previous booting
105
+ * stage can set it to -1UL which will force the FW_DYNAMIC firmware
106
+ * to use the relocation lottery mechanism.
107
+ */
108
+ target_long boot_hart;
109
+};
110
+
111
+#endif
112
diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
113
index XXXXXXX..XXXXXXX 100644
114
--- a/hw/riscv/boot.c
115
+++ b/hw/riscv/boot.c
116
@@ -XXX,XX +XXX,XX @@
117
#include "hw/boards.h"
118
#include "hw/loader.h"
119
#include "hw/riscv/boot.h"
120
+#include "hw/riscv/boot_opensbi.h"
121
#include "elf.h"
122
#include "sysemu/device_tree.h"
123
#include "sysemu/qtest.h"
124
@@ -XXX,XX +XXX,XX @@
125
126
#if defined(TARGET_RISCV32)
127
# define KERNEL_BOOT_ADDRESS 0x80400000
128
+#define fw_dynamic_info_data(__val) cpu_to_le32(__val)
129
#else
130
# define KERNEL_BOOT_ADDRESS 0x80200000
131
+#define fw_dynamic_info_data(__val) cpu_to_le64(__val)
37
#endif
132
#endif
38
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
133
39
index XXXXXXX..XXXXXXX 100644
134
void riscv_find_and_load_firmware(MachineState *machine,
40
--- a/target/riscv/cpu_helper.c
135
@@ -XXX,XX +XXX,XX @@ uint32_t riscv_load_fdt(hwaddr dram_base, uint64_t mem_size, void *fdt)
41
+++ b/target/riscv/cpu_helper.c
136
return fdt_addr;
42
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv)
43
env->load_res = -1;
44
}
137
}
45
138
46
+/*
139
+void riscv_rom_copy_firmware_info(hwaddr rom_base, hwaddr rom_size,
47
+ * get_physical_address_pmp - check PMP permission for this physical address
140
+ uint32_t reset_vec_size, uint64_t kernel_entry)
48
+ *
49
+ * Match the PMP region and check permission for this physical address and it's
50
+ * TLB page. Returns 0 if the permission checking was successful
51
+ *
52
+ * @env: CPURISCVState
53
+ * @prot: The returned protection attributes
54
+ * @tlb_size: TLB page size containing addr. It could be modified after PMP
55
+ * permission checking. NULL if not set TLB page for addr.
56
+ * @addr: The physical address to be checked permission
57
+ * @access_type: The type of MMU access
58
+ * @mode: Indicates current privilege level.
59
+ */
60
+static int get_physical_address_pmp(CPURISCVState *env, int *prot,
61
+ target_ulong *tlb_size, hwaddr addr,
62
+ int size, MMUAccessType access_type,
63
+ int mode)
64
+{
141
+{
65
+ pmp_priv_t pmp_priv;
142
+ struct fw_dynamic_info dinfo;
66
+ target_ulong tlb_size_pmp = 0;
143
+ size_t dinfo_len;
67
+
144
+
68
+ if (!riscv_feature(env, RISCV_FEATURE_PMP)) {
145
+ dinfo.magic = fw_dynamic_info_data(FW_DYNAMIC_INFO_MAGIC_VALUE);
69
+ *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
146
+ dinfo.version = fw_dynamic_info_data(FW_DYNAMIC_INFO_VERSION);
70
+ return TRANSLATE_SUCCESS;
147
+ dinfo.next_mode = fw_dynamic_info_data(FW_DYNAMIC_INFO_NEXT_MODE_S);
148
+ dinfo.next_addr = fw_dynamic_info_data(kernel_entry);
149
+ dinfo.options = 0;
150
+ dinfo.boot_hart = 0;
151
+ dinfo_len = sizeof(dinfo);
152
+
153
+ /**
154
+ * copy the dynamic firmware info. This information is specific to
155
+ * OpenSBI but doesn't break any other firmware as long as they don't
156
+ * expect any certain value in "a2" register.
157
+ */
158
+ if (dinfo_len > (rom_size - reset_vec_size)) {
159
+ error_report("not enough space to store dynamic firmware info");
160
+ exit(1);
71
+ }
161
+ }
72
+
162
+
73
+ if (!pmp_hart_has_privs(env, addr, size, 1 << access_type, &pmp_priv,
163
+ rom_add_blob_fixed_as("mrom.finfo", &dinfo, dinfo_len,
74
+ mode)) {
164
+ rom_base + reset_vec_size,
75
+ *prot = 0;
165
+ &address_space_memory);
76
+ return TRANSLATE_PMP_FAIL;
77
+ }
78
+
79
+ *prot = pmp_priv_to_page_prot(pmp_priv);
80
+ if (tlb_size != NULL) {
81
+ if (pmp_is_range_in_tlb(env, addr & ~(*tlb_size - 1), &tlb_size_pmp)) {
82
+ *tlb_size = tlb_size_pmp;
83
+ }
84
+ }
85
+
86
+ return TRANSLATE_SUCCESS;
87
+}
166
+}
88
+
167
+
89
/* get_physical_address - get the physical address for this virtual address
168
void riscv_setup_rom_reset_vec(hwaddr start_addr, hwaddr rom_base,
90
*
169
- hwaddr rom_size,
91
* Do a page table walk to obtain the physical address corresponding to a
170
+ hwaddr rom_size, uint64_t kernel_entry,
92
@@ -XXX,XX +XXX,XX @@ restart:
171
uint32_t fdt_load_addr, void *fdt)
93
pte_addr = base + idx * ptesize;
172
{
173
int i;
174
175
/* reset vector */
176
uint32_t reset_vec[10] = {
177
- 0x00000297, /* 1: auipc t0, %pcrel_hi(dtb) */
178
+ 0x00000297, /* 1: auipc t0, %pcrel_hi(fw_dyn) */
179
+ 0x02828613, /* addi a2, t0, %pcrel_lo(1b) */
180
0xf1402573, /* csrr a0, mhartid */
181
#if defined(TARGET_RISCV32)
182
0x0202a583, /* lw a1, 32(t0) */
183
@@ -XXX,XX +XXX,XX @@ void riscv_setup_rom_reset_vec(hwaddr start_addr, hwaddr rom_base,
184
0x0182b283, /* ld t0, 24(t0) */
185
#endif
186
0x00028067, /* jr t0 */
187
- 0x00000000,
188
start_addr, /* start: .dword */
189
0x00000000,
190
fdt_load_addr, /* fdt_laddr: .dword */
191
0x00000000,
192
- /* dtb: */
193
+ /* fw_dyn: */
194
};
195
196
/* copy in the reset vector in little_endian byte order */
197
@@ -XXX,XX +XXX,XX @@ void riscv_setup_rom_reset_vec(hwaddr start_addr, hwaddr rom_base,
198
}
199
rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
200
rom_base, &address_space_memory);
201
+ riscv_rom_copy_firmware_info(rom_base, rom_size, sizeof(reset_vec),
202
+ kernel_entry);
203
204
return;
205
}
206
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
207
index XXXXXXX..XXXXXXX 100644
208
--- a/hw/riscv/sifive_u.c
209
+++ b/hw/riscv/sifive_u.c
210
@@ -XXX,XX +XXX,XX @@ static void sifive_u_machine_init(MachineState *machine)
211
target_ulong start_addr = memmap[SIFIVE_U_DRAM].base;
212
int i;
213
uint32_t fdt_load_addr;
214
+ uint64_t kernel_entry;
215
216
/* Initialize SoC */
217
object_initialize_child(OBJECT(machine), "soc", &s->soc, TYPE_RISCV_U_SOC);
218
@@ -XXX,XX +XXX,XX @@ static void sifive_u_machine_init(MachineState *machine)
219
riscv_find_and_load_firmware(machine, BIOS_FILENAME, start_addr, NULL);
220
221
if (machine->kernel_filename) {
222
- uint64_t kernel_entry = riscv_load_kernel(machine->kernel_filename,
223
- NULL);
224
+ kernel_entry = riscv_load_kernel(machine->kernel_filename, NULL);
225
226
if (machine->initrd_filename) {
227
hwaddr start;
228
@@ -XXX,XX +XXX,XX @@ static void sifive_u_machine_init(MachineState *machine)
229
qemu_fdt_setprop_cell(s->fdt, "/chosen", "linux,initrd-end",
230
end);
94
}
231
}
95
232
+ } else {
96
- if (riscv_feature(env, RISCV_FEATURE_PMP) &&
233
+ /*
97
- !pmp_hart_has_privs(env, pte_addr, sizeof(target_ulong),
234
+ * If dynamic firmware is used, it doesn't know where is the next mode
98
- 1 << MMU_DATA_LOAD, PRV_S)) {
235
+ * if kernel argument is not set.
99
+ int pmp_prot;
236
+ */
100
+ int pmp_ret = get_physical_address_pmp(env, &pmp_prot, NULL, pte_addr,
237
+ kernel_entry = 0;
101
+ sizeof(target_ulong),
238
}
102
+ MMU_DATA_LOAD, PRV_S);
239
103
+ if (pmp_ret != TRANSLATE_SUCCESS) {
240
/* Compute the fdt load address in dram */
104
return TRANSLATE_PMP_FAIL;
241
@@ -XXX,XX +XXX,XX @@ static void sifive_u_machine_init(MachineState *machine)
242
/* reset vector */
243
uint32_t reset_vec[11] = {
244
s->msel, /* MSEL pin state */
245
- 0x00000297, /* 1: auipc t0, %pcrel_hi(dtb) */
246
+ 0x00000297, /* 1: auipc t0, %pcrel_hi(fw_dyn) */
247
+ 0x02828613, /* addi a2, t0, %pcrel_lo(1b) */
248
0xf1402573, /* csrr a0, mhartid */
249
#if defined(TARGET_RISCV32)
250
0x0202a583, /* lw a1, 32(t0) */
251
@@ -XXX,XX +XXX,XX @@ static void sifive_u_machine_init(MachineState *machine)
252
0x0182b283, /* ld t0, 24(t0) */
253
#endif
254
0x00028067, /* jr t0 */
255
- 0x00000000,
256
start_addr, /* start: .dword */
257
0x00000000,
258
fdt_load_addr, /* fdt_laddr: .dword */
259
0x00000000,
260
- /* dtb: */
261
+ /* fw_dyn: */
262
};
263
264
/* copy in the reset vector in little_endian byte order */
265
@@ -XXX,XX +XXX,XX @@ static void sifive_u_machine_init(MachineState *machine)
266
}
267
rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
268
memmap[SIFIVE_U_MROM].base, &address_space_memory);
269
+
270
+ riscv_rom_copy_firmware_info(memmap[SIFIVE_U_MROM].base,
271
+ memmap[SIFIVE_U_MROM].size,
272
+ sizeof(reset_vec), kernel_entry);
273
}
274
275
static bool sifive_u_machine_get_start_in_flash(Object *obj, Error **errp)
276
diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
277
index XXXXXXX..XXXXXXX 100644
278
--- a/hw/riscv/spike.c
279
+++ b/hw/riscv/spike.c
280
@@ -XXX,XX +XXX,XX @@ static void spike_board_init(MachineState *machine)
281
MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
282
unsigned int smp_cpus = machine->smp.cpus;
283
uint32_t fdt_load_addr;
284
+ uint64_t kernel_entry;
285
286
/* Initialize SOC */
287
object_initialize_child(OBJECT(machine), "soc", &s->soc,
288
@@ -XXX,XX +XXX,XX @@ static void spike_board_init(MachineState *machine)
289
htif_symbol_callback);
290
291
if (machine->kernel_filename) {
292
- uint64_t kernel_entry = riscv_load_kernel(machine->kernel_filename,
293
- htif_symbol_callback);
294
+ kernel_entry = riscv_load_kernel(machine->kernel_filename,
295
+ htif_symbol_callback);
296
297
if (machine->initrd_filename) {
298
hwaddr start;
299
@@ -XXX,XX +XXX,XX @@ static void spike_board_init(MachineState *machine)
300
qemu_fdt_setprop_cell(s->fdt, "/chosen", "linux,initrd-end",
301
end);
105
}
302
}
106
107
@@ -XXX,XX +XXX,XX @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
108
#ifndef CONFIG_USER_ONLY
109
vaddr im_address;
110
hwaddr pa = 0;
111
- int prot, prot2;
112
+ int prot, prot2, prot_pmp;
113
bool pmp_violation = false;
114
bool first_stage_error = true;
115
bool two_stage_lookup = false;
116
int ret = TRANSLATE_FAIL;
117
int mode = mmu_idx;
118
- target_ulong tlb_size = 0;
119
+ /* default TLB page size */
120
+ target_ulong tlb_size = TARGET_PAGE_SIZE;
121
122
env->guest_phys_fault_addr = 0;
123
124
@@ -XXX,XX +XXX,XX @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
125
126
prot &= prot2;
127
128
- if (riscv_feature(env, RISCV_FEATURE_PMP) &&
129
- (ret == TRANSLATE_SUCCESS) &&
130
- !pmp_hart_has_privs(env, pa, size, 1 << access_type, mode)) {
131
- ret = TRANSLATE_PMP_FAIL;
132
+ if (ret == TRANSLATE_SUCCESS) {
133
+ ret = get_physical_address_pmp(env, &prot_pmp, &tlb_size, pa,
134
+ size, access_type, mode);
135
+ prot &= prot_pmp;
136
}
137
138
if (ret != TRANSLATE_SUCCESS) {
139
@@ -XXX,XX +XXX,XX @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
140
"%s address=%" VADDR_PRIx " ret %d physical "
141
TARGET_FMT_plx " prot %d\n",
142
__func__, address, ret, pa, prot);
143
- }
144
145
- if (riscv_feature(env, RISCV_FEATURE_PMP) &&
146
- (ret == TRANSLATE_SUCCESS) &&
147
- !pmp_hart_has_privs(env, pa, size, 1 << access_type, mode)) {
148
- ret = TRANSLATE_PMP_FAIL;
149
+ if (ret == TRANSLATE_SUCCESS) {
150
+ ret = get_physical_address_pmp(env, &prot_pmp, &tlb_size, pa,
151
+ size, access_type, mode);
152
+ prot &= prot_pmp;
153
+ }
154
}
155
+
156
if (ret == TRANSLATE_PMP_FAIL) {
157
pmp_violation = true;
158
}
159
160
if (ret == TRANSLATE_SUCCESS) {
161
- if (pmp_is_range_in_tlb(env, pa & TARGET_PAGE_MASK, &tlb_size)) {
162
- tlb_set_page(cs, address & ~(tlb_size - 1), pa & ~(tlb_size - 1),
163
- prot, mmu_idx, tlb_size);
164
- } else {
165
- tlb_set_page(cs, address & TARGET_PAGE_MASK, pa & TARGET_PAGE_MASK,
166
- prot, mmu_idx, TARGET_PAGE_SIZE);
167
- }
168
+ tlb_set_page(cs, address & ~(tlb_size - 1), pa & ~(tlb_size - 1),
169
+ prot, mmu_idx, tlb_size);
170
return true;
171
} else if (probe) {
172
return false;
173
diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c
174
index XXXXXXX..XXXXXXX 100644
175
--- a/target/riscv/pmp.c
176
+++ b/target/riscv/pmp.c
177
@@ -XXX,XX +XXX,XX @@ static int pmp_is_in_range(CPURISCVState *env, int pmp_index, target_ulong addr)
178
return result;
179
}
180
181
+/*
182
+ * Check if the address has required RWX privs when no PMP entry is matched.
183
+ */
184
+static bool pmp_hart_has_privs_default(CPURISCVState *env, target_ulong addr,
185
+ target_ulong size, pmp_priv_t privs, pmp_priv_t *allowed_privs,
186
+ target_ulong mode)
187
+{
188
+ bool ret;
189
+
190
+ if ((!riscv_feature(env, RISCV_FEATURE_PMP)) || (mode == PRV_M)) {
191
+ /*
192
+ * Privileged spec v1.10 states if HW doesn't implement any PMP entry
193
+ * or no PMP entry matches an M-Mode access, the access succeeds.
194
+ */
195
+ ret = true;
196
+ *allowed_privs = PMP_READ | PMP_WRITE | PMP_EXEC;
197
+ } else {
303
+ } else {
198
+ /*
304
+ /*
199
+ * Other modes are not allowed to succeed if they don't * match a rule,
305
+ * If dynamic firmware is used, it doesn't know where is the next mode
200
+ * but there are rules. We've checked for no rule earlier in this
306
+ * if kernel argument is not set.
201
+ * function.
307
+ */
202
+ */
308
+ kernel_entry = 0;
203
+ ret = false;
309
}
204
+ *allowed_privs = 0;
310
205
+ }
311
/* Compute the fdt load address in dram */
206
+
312
@@ -XXX,XX +XXX,XX @@ static void spike_board_init(MachineState *machine)
207
+ return ret;
313
machine->ram_size, s->fdt);
208
+}
314
/* load the reset vector */
209
+
315
riscv_setup_rom_reset_vec(memmap[SPIKE_DRAM].base, memmap[SPIKE_MROM].base,
210
316
- memmap[SPIKE_MROM].size,
211
/*
317
+ memmap[SPIKE_MROM].size, kernel_entry,
212
* Public Interface
318
fdt_load_addr, s->fdt);
213
@@ -XXX,XX +XXX,XX @@ static int pmp_is_in_range(CPURISCVState *env, int pmp_index, target_ulong addr)
319
214
* Check if the address has required RWX privs to complete desired operation
320
/* initialize HTIF using symbols found in load_kernel */
215
*/
321
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
216
bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr,
322
index XXXXXXX..XXXXXXX 100644
217
- target_ulong size, pmp_priv_t privs, target_ulong mode)
323
--- a/hw/riscv/virt.c
218
+ target_ulong size, pmp_priv_t privs, pmp_priv_t *allowed_privs,
324
+++ b/hw/riscv/virt.c
219
+ target_ulong mode)
325
@@ -XXX,XX +XXX,XX @@ static void virt_machine_init(MachineState *machine)
220
{
326
size_t plic_hart_config_len;
221
int i = 0;
327
target_ulong start_addr = memmap[VIRT_DRAM].base;
222
int ret = -1;
328
uint32_t fdt_load_addr;
223
int pmp_size = 0;
329
+ uint64_t kernel_entry;
224
target_ulong s = 0;
330
int i;
225
target_ulong e = 0;
331
unsigned int smp_cpus = machine->smp.cpus;
226
- pmp_priv_t allowed_privs = 0;
332
227
333
@@ -XXX,XX +XXX,XX @@ static void virt_machine_init(MachineState *machine)
228
/* Short cut if no rules */
334
memmap[VIRT_DRAM].base, NULL);
229
if (0 == pmp_get_num_rules(env)) {
335
230
- return (env->priv == PRV_M) ? true : false;
336
if (machine->kernel_filename) {
231
+ return pmp_hart_has_privs_default(env, addr, size, privs,
337
- uint64_t kernel_entry = riscv_load_kernel(machine->kernel_filename,
232
+ allowed_privs, mode);
338
- NULL);
233
}
339
+ kernel_entry = riscv_load_kernel(machine->kernel_filename, NULL);
234
340
235
if (size == 0) {
341
if (machine->initrd_filename) {
236
@@ -XXX,XX +XXX,XX @@ bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr,
342
hwaddr start;
237
* check
343
@@ -XXX,XX +XXX,XX @@ static void virt_machine_init(MachineState *machine)
238
*/
344
qemu_fdt_setprop_cell(s->fdt, "/chosen", "linux,initrd-end",
239
if (((s + e) == 2) && (PMP_AMATCH_OFF != a_field)) {
345
end);
240
- allowed_privs = PMP_READ | PMP_WRITE | PMP_EXEC;
241
+ *allowed_privs = PMP_READ | PMP_WRITE | PMP_EXEC;
242
if ((mode != PRV_M) || pmp_is_locked(env, i)) {
243
- allowed_privs &= env->pmp_state.pmp[i].cfg_reg;
244
+ *allowed_privs &= env->pmp_state.pmp[i].cfg_reg;
245
}
246
247
- if ((privs & allowed_privs) == privs) {
248
- ret = 1;
249
- break;
250
- } else {
251
- ret = 0;
252
- break;
253
- }
254
+ ret = ((privs & *allowed_privs) == privs);
255
+ break;
256
}
346
}
257
}
347
+ } else {
258
348
+ /*
259
/* No rule matched */
349
+ * If dynamic firmware is used, it doesn't know where is the next mode
260
if (ret == -1) {
350
+ * if kernel argument is not set.
261
- if (mode == PRV_M) {
351
+ */
262
- ret = 1; /* Privileged spec v1.10 states if no PMP entry matches an
352
+ kernel_entry = 0;
263
- * M-Mode access, the access succeeds */
353
}
264
- } else {
354
265
- ret = 0; /* Other modes are not allowed to succeed if they don't
355
if (drive_get(IF_PFLASH, 0, 0)) {
266
- * match a rule, but there are rules. We've checked for
356
@@ -XXX,XX +XXX,XX @@ static void virt_machine_init(MachineState *machine)
267
- * no rule earlier in this function. */
357
machine->ram_size, s->fdt);
268
- }
358
/* load the reset vector */
269
+ return pmp_hart_has_privs_default(env, addr, size, privs,
359
riscv_setup_rom_reset_vec(start_addr, virt_memmap[VIRT_MROM].base,
270
+ allowed_privs, mode);
360
- virt_memmap[VIRT_MROM].size,
271
}
361
+ virt_memmap[VIRT_MROM].size, kernel_entry,
272
362
fdt_load_addr, s->fdt);
273
return ret == 1 ? true : false;
363
274
}
364
/* create PLIC hart topology configuration string */
275
276
-
277
/*
278
* Handle a write to a pmpcfg CSP
279
*/
280
@@ -XXX,XX +XXX,XX @@ bool pmp_is_range_in_tlb(CPURISCVState *env, hwaddr tlb_sa,
281
282
return false;
283
}
284
+
285
+/*
286
+ * Convert PMP privilege to TLB page privilege.
287
+ */
288
+int pmp_priv_to_page_prot(pmp_priv_t pmp_priv)
289
+{
290
+ int prot = 0;
291
+
292
+ if (pmp_priv & PMP_READ) {
293
+ prot |= PAGE_READ;
294
+ }
295
+ if (pmp_priv & PMP_WRITE) {
296
+ prot |= PAGE_WRITE;
297
+ }
298
+ if (pmp_priv & PMP_EXEC) {
299
+ prot |= PAGE_EXEC;
300
+ }
301
+
302
+ return prot;
303
+}
304
--
365
--
305
2.30.1
366
2.27.0
306
367
307
368
diff view generated by jsdifflib
1
From: Bin Meng <bin.meng@windriver.com>
1
From: Atish Patra <atish.patra@wdc.com>
2
2
3
Since HSS commit c20a89f8dcac, the Icicle Kit reference design has
3
Even though the start address in ROM code is declared as a 64 bit address
4
been updated to use a register mapped at 0x4f000000 instead of a
4
for RV64, it can't be used as upper bits are set to zero in ROM code.
5
GPIO to control whether eMMC or SD card is to be used. With this
6
support the same HSS image can be used for both eMMC and SD card
7
boot flow, while previously two different board configurations were
8
used. This is undocumented but one can take a look at the HSS code
9
HSS_MMCInit() in services/mmc/mmc_api.c.
10
5
11
With this commit, HSS image built from 2020.12 release boots again.
6
Update the ROM code correctly to reflect the 64bit value.
12
7
13
Signed-off-by: Bin Meng <bin.meng@windriver.com>
8
Signed-off-by: Atish Patra <atish.patra@wdc.com>
14
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Reviewed-by: Bin Meng <bin.meng@windriver.com>
15
Message-id: 20210322075248.136255-1-bmeng.cn@gmail.com
10
Tested-by: Bin Meng <bin.meng@windriver.com>
11
Message-Id: <20200701183949.398134-5-atish.patra@wdc.com>
16
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
17
---
13
---
18
include/hw/riscv/microchip_pfsoc.h | 1 +
14
hw/riscv/boot.c | 6 +++++-
19
hw/riscv/microchip_pfsoc.c | 6 ++++++
15
hw/riscv/sifive_u.c | 6 +++++-
20
2 files changed, 7 insertions(+)
16
2 files changed, 10 insertions(+), 2 deletions(-)
21
17
22
diff --git a/include/hw/riscv/microchip_pfsoc.h b/include/hw/riscv/microchip_pfsoc.h
18
diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
23
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
24
--- a/include/hw/riscv/microchip_pfsoc.h
20
--- a/hw/riscv/boot.c
25
+++ b/include/hw/riscv/microchip_pfsoc.h
21
+++ b/hw/riscv/boot.c
26
@@ -XXX,XX +XXX,XX @@ enum {
22
@@ -XXX,XX +XXX,XX @@ void riscv_setup_rom_reset_vec(hwaddr start_addr, hwaddr rom_base,
27
MICROCHIP_PFSOC_ENVM_DATA,
23
uint32_t fdt_load_addr, void *fdt)
28
MICROCHIP_PFSOC_QSPI_XIP,
24
{
29
MICROCHIP_PFSOC_IOSCB,
25
int i;
30
+ MICROCHIP_PFSOC_EMMC_SD_MUX,
26
+ uint32_t start_addr_hi32 = 0x00000000;
31
MICROCHIP_PFSOC_DRAM_LO,
27
32
MICROCHIP_PFSOC_DRAM_LO_ALIAS,
28
+ #if defined(TARGET_RISCV64)
33
MICROCHIP_PFSOC_DRAM_HI,
29
+ start_addr_hi32 = start_addr >> 32;
34
diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
30
+ #endif
31
/* reset vector */
32
uint32_t reset_vec[10] = {
33
0x00000297, /* 1: auipc t0, %pcrel_hi(fw_dyn) */
34
@@ -XXX,XX +XXX,XX @@ void riscv_setup_rom_reset_vec(hwaddr start_addr, hwaddr rom_base,
35
#endif
36
0x00028067, /* jr t0 */
37
start_addr, /* start: .dword */
38
- 0x00000000,
39
+ start_addr_hi32,
40
fdt_load_addr, /* fdt_laddr: .dword */
41
0x00000000,
42
/* fw_dyn: */
43
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
35
index XXXXXXX..XXXXXXX 100644
44
index XXXXXXX..XXXXXXX 100644
36
--- a/hw/riscv/microchip_pfsoc.c
45
--- a/hw/riscv/sifive_u.c
37
+++ b/hw/riscv/microchip_pfsoc.c
46
+++ b/hw/riscv/sifive_u.c
38
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry microchip_pfsoc_memmap[] = {
47
@@ -XXX,XX +XXX,XX @@ static void sifive_u_machine_init(MachineState *machine)
39
[MICROCHIP_PFSOC_ENVM_DATA] = { 0x20220000, 0x20000 },
48
MemoryRegion *main_mem = g_new(MemoryRegion, 1);
40
[MICROCHIP_PFSOC_QSPI_XIP] = { 0x21000000, 0x1000000 },
49
MemoryRegion *flash0 = g_new(MemoryRegion, 1);
41
[MICROCHIP_PFSOC_IOSCB] = { 0x30000000, 0x10000000 },
50
target_ulong start_addr = memmap[SIFIVE_U_DRAM].base;
42
+ [MICROCHIP_PFSOC_EMMC_SD_MUX] = { 0x4f000000, 0x4 },
51
+ uint32_t start_addr_hi32 = 0x00000000;
43
[MICROCHIP_PFSOC_DRAM_LO] = { 0x80000000, 0x40000000 },
52
int i;
44
[MICROCHIP_PFSOC_DRAM_LO_ALIAS] = { 0xc0000000, 0x40000000 },
53
uint32_t fdt_load_addr;
45
[MICROCHIP_PFSOC_DRAM_HI] = { 0x1000000000, 0x0 },
54
uint64_t kernel_entry;
46
@@ -XXX,XX +XXX,XX @@ static void microchip_pfsoc_soc_realize(DeviceState *dev, Error **errp)
55
@@ -XXX,XX +XXX,XX @@ static void sifive_u_machine_init(MachineState *machine)
47
sysbus_mmio_map(SYS_BUS_DEVICE(&s->ioscb), 0,
56
/* Compute the fdt load address in dram */
48
memmap[MICROCHIP_PFSOC_IOSCB].base);
57
fdt_load_addr = riscv_load_fdt(memmap[SIFIVE_U_DRAM].base,
49
58
machine->ram_size, s->fdt);
50
+ /* eMMC/SD mux */
59
+ #if defined(TARGET_RISCV64)
51
+ create_unimplemented_device("microchip.pfsoc.emmc_sd_mux",
60
+ start_addr_hi32 = start_addr >> 32;
52
+ memmap[MICROCHIP_PFSOC_EMMC_SD_MUX].base,
61
+ #endif
53
+ memmap[MICROCHIP_PFSOC_EMMC_SD_MUX].size);
62
54
+
63
/* reset vector */
55
/* QSPI Flash */
64
uint32_t reset_vec[11] = {
56
memory_region_init_rom(qspi_xip_mem, OBJECT(dev),
65
@@ -XXX,XX +XXX,XX @@ static void sifive_u_machine_init(MachineState *machine)
57
"microchip.pfsoc.qspi_xip",
66
#endif
67
0x00028067, /* jr t0 */
68
start_addr, /* start: .dword */
69
- 0x00000000,
70
+ start_addr_hi32,
71
fdt_load_addr, /* fdt_laddr: .dword */
72
0x00000000,
73
/* fw_dyn: */
58
--
74
--
59
2.30.1
75
2.27.0
60
76
61
77
diff view generated by jsdifflib
1
From: Bin Meng <bin.meng@windriver.com>
1
From: Bin Meng <bin.meng@windriver.com>
2
2
3
Per SST25VF016B datasheet [1], SST flash requires a dummy byte after
3
At present the size of Mask ROM for sifive_u / spike / virt machines
4
the address bytes. Note only SPI mode is supported by SST flashes.
4
is set to 0x11000, which ends at an unusual address. This changes the
5
5
size to 0xf000 so that it ends at 0x10000.
6
[1] http://ww1.microchip.com/downloads/en/devicedoc/s71271_04.pdf
7
6
8
Signed-off-by: Bin Meng <bin.meng@windriver.com>
7
Signed-off-by: Bin Meng <bin.meng@windriver.com>
9
Acked-by: Alistair Francis <alistair.francis@wdc.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20210306060152.7250-1-bmeng.cn@gmail.com
9
Message-Id: <1594289144-24723-1-git-send-email-bmeng.cn@gmail.com>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
---
11
---
13
hw/block/m25p80.c | 3 +++
12
hw/riscv/sifive_u.c | 2 +-
14
1 file changed, 3 insertions(+)
13
hw/riscv/spike.c | 2 +-
14
hw/riscv/virt.c | 2 +-
15
3 files changed, 3 insertions(+), 3 deletions(-)
15
16
16
diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
17
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
17
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/block/m25p80.c
19
--- a/hw/riscv/sifive_u.c
19
+++ b/hw/block/m25p80.c
20
+++ b/hw/riscv/sifive_u.c
20
@@ -XXX,XX +XXX,XX @@ static void decode_fast_read_cmd(Flash *s)
21
@@ -XXX,XX +XXX,XX @@ static const struct MemmapEntry {
21
s->needed_bytes = get_addr_length(s);
22
hwaddr size;
22
switch (get_man(s)) {
23
} sifive_u_memmap[] = {
23
/* Dummy cycles - modeled with bytes writes instead of bits */
24
[SIFIVE_U_DEBUG] = { 0x0, 0x100 },
24
+ case MAN_SST:
25
- [SIFIVE_U_MROM] = { 0x1000, 0x11000 },
25
+ s->needed_bytes += 1;
26
+ [SIFIVE_U_MROM] = { 0x1000, 0xf000 },
26
+ break;
27
[SIFIVE_U_CLINT] = { 0x2000000, 0x10000 },
27
case MAN_WINBOND:
28
[SIFIVE_U_L2LIM] = { 0x8000000, 0x2000000 },
28
s->needed_bytes += 8;
29
[SIFIVE_U_PLIC] = { 0xc000000, 0x4000000 },
29
break;
30
diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/riscv/spike.c
33
+++ b/hw/riscv/spike.c
34
@@ -XXX,XX +XXX,XX @@ static const struct MemmapEntry {
35
hwaddr base;
36
hwaddr size;
37
} spike_memmap[] = {
38
- [SPIKE_MROM] = { 0x1000, 0x11000 },
39
+ [SPIKE_MROM] = { 0x1000, 0xf000 },
40
[SPIKE_CLINT] = { 0x2000000, 0x10000 },
41
[SPIKE_DRAM] = { 0x80000000, 0x0 },
42
};
43
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/hw/riscv/virt.c
46
+++ b/hw/riscv/virt.c
47
@@ -XXX,XX +XXX,XX @@ static const struct MemmapEntry {
48
hwaddr size;
49
} virt_memmap[] = {
50
[VIRT_DEBUG] = { 0x0, 0x100 },
51
- [VIRT_MROM] = { 0x1000, 0x11000 },
52
+ [VIRT_MROM] = { 0x1000, 0xf000 },
53
[VIRT_TEST] = { 0x100000, 0x1000 },
54
[VIRT_RTC] = { 0x101000, 0x1000 },
55
[VIRT_CLINT] = { 0x2000000, 0x10000 },
30
--
56
--
31
2.30.1
57
2.27.0
32
58
33
59
diff view generated by jsdifflib
1
From: Georg Kotheimer <georg.kotheimer@kernkonzept.com>
1
From: Frank Chang <frank.chang@sifive.com>
2
2
3
Signed-off-by: Georg Kotheimer <georg.kotheimer@kernkonzept.com>
3
gvec should provide vecop_list to avoid:
4
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
4
"tcg_tcg_assert_listed_vecop: code should not be reached bug" assertion.
5
Message-id: 20210311094902.1377593-1-georg.kotheimer@kernkonzept.com
5
6
Signed-off-by: Frank Chang <frank.chang@sifive.com>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-Id: <20200710104920.13550-2-frank.chang@sifive.com>
6
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
9
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
7
---
10
---
8
target/riscv/csr.c | 7 ++++---
11
target/riscv/insn_trans/trans_rvv.inc.c | 5 +++++
9
1 file changed, 4 insertions(+), 3 deletions(-)
12
1 file changed, 5 insertions(+)
10
13
11
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
14
diff --git a/target/riscv/insn_trans/trans_rvv.inc.c b/target/riscv/insn_trans/trans_rvv.inc.c
12
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
13
--- a/target/riscv/csr.c
16
--- a/target/riscv/insn_trans/trans_rvv.inc.c
14
+++ b/target/riscv/csr.c
17
+++ b/target/riscv/insn_trans/trans_rvv.inc.c
15
@@ -XXX,XX +XXX,XX @@ static const target_ulong sstatus_v1_10_mask = SSTATUS_SIE | SSTATUS_SPIE |
18
@@ -XXX,XX +XXX,XX @@ static void gen_rsub_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b)
16
SSTATUS_UIE | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS |
19
static void tcg_gen_gvec_rsubs(unsigned vece, uint32_t dofs, uint32_t aofs,
17
SSTATUS_SUM | SSTATUS_MXR | SSTATUS_SD;
20
TCGv_i64 c, uint32_t oprsz, uint32_t maxsz)
18
static const target_ulong sip_writable_mask = SIP_SSIP | MIP_USIP | MIP_UEIP;
19
-static const target_ulong hip_writable_mask = MIP_VSSIP | MIP_VSTIP | MIP_VSEIP;
20
+static const target_ulong hip_writable_mask = MIP_VSSIP;
21
+static const target_ulong hvip_writable_mask = MIP_VSSIP | MIP_VSTIP | MIP_VSEIP;
22
static const target_ulong vsip_writable_mask = MIP_VSSIP;
23
24
static const char valid_vm_1_10_32[16] = {
25
@@ -XXX,XX +XXX,XX @@ static int rmw_hvip(CPURISCVState *env, int csrno, target_ulong *ret_value,
26
target_ulong new_value, target_ulong write_mask)
27
{
21
{
28
int ret = rmw_mip(env, 0, ret_value, new_value,
22
+ static const TCGOpcode vecop_list[] = { INDEX_op_sub_vec, 0 };
29
- write_mask & hip_writable_mask);
23
static const GVecGen2s rsub_op[4] = {
30
+ write_mask & hvip_writable_mask);
24
{ .fni8 = gen_vec_rsub8_i64,
31
25
.fniv = gen_rsub_vec,
32
- *ret_value &= hip_writable_mask;
26
.fno = gen_helper_vec_rsubs8,
33
+ *ret_value &= hvip_writable_mask;
27
+ .opt_opc = vecop_list,
34
28
.vece = MO_8 },
35
return ret;
29
{ .fni8 = gen_vec_rsub16_i64,
36
}
30
.fniv = gen_rsub_vec,
31
.fno = gen_helper_vec_rsubs16,
32
+ .opt_opc = vecop_list,
33
.vece = MO_16 },
34
{ .fni4 = gen_rsub_i32,
35
.fniv = gen_rsub_vec,
36
.fno = gen_helper_vec_rsubs32,
37
+ .opt_opc = vecop_list,
38
.vece = MO_32 },
39
{ .fni8 = gen_rsub_i64,
40
.fniv = gen_rsub_vec,
41
.fno = gen_helper_vec_rsubs64,
42
+ .opt_opc = vecop_list,
43
.prefer_i64 = TCG_TARGET_REG_BITS == 64,
44
.vece = MO_64 },
45
};
37
--
46
--
38
2.30.1
47
2.27.0
39
48
40
49
diff view generated by jsdifflib
1
From: Georg Kotheimer <georg.kotheimer@kernkonzept.com>
1
From: Frank Chang <frank.chang@sifive.com>
2
2
3
The current condition for the use of background registers only
3
Signed-off-by: Frank Chang <frank.chang@sifive.com>
4
considers the hypervisor load and store instructions,
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
but not accesses from M mode via MSTATUS_MPRV+MPV.
5
Message-Id: <20200710104920.13550-3-frank.chang@sifive.com>
6
7
Signed-off-by: Georg Kotheimer <georg.kotheimer@kernkonzept.com>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Message-id: 20210311103036.1401073-1-georg.kotheimer@kernkonzept.com
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
6
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
---
7
---
12
target/riscv/cpu_helper.c | 2 +-
8
target/riscv/insn_trans/trans_rvv.inc.c | 2 +-
13
1 file changed, 1 insertion(+), 1 deletion(-)
9
1 file changed, 1 insertion(+), 1 deletion(-)
14
10
15
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
11
diff --git a/target/riscv/insn_trans/trans_rvv.inc.c b/target/riscv/insn_trans/trans_rvv.inc.c
16
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
17
--- a/target/riscv/cpu_helper.c
13
--- a/target/riscv/insn_trans/trans_rvv.inc.c
18
+++ b/target/riscv/cpu_helper.c
14
+++ b/target/riscv/insn_trans/trans_rvv.inc.c
19
@@ -XXX,XX +XXX,XX @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
15
@@ -XXX,XX +XXX,XX @@ static void gen_vec_rsub8_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
20
* was called. Background registers will be used if the guest has
16
21
* forced a two stage translation to be on (in HS or M mode).
17
static void gen_vec_rsub16_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
22
*/
18
{
23
- if (!riscv_cpu_virt_enabled(env) && riscv_cpu_two_stage_lookup(mmu_idx)) {
19
- tcg_gen_vec_sub8_i64(d, b, a);
24
+ if (!riscv_cpu_virt_enabled(env) && two_stage) {
20
+ tcg_gen_vec_sub16_i64(d, b, a);
25
use_background = true;
21
}
26
}
22
27
23
static void gen_rsub_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
28
--
24
--
29
2.30.1
25
2.27.0
30
26
31
27
diff view generated by jsdifflib
1
From: Frank Chang <frank.chang@sifive.com>
1
From: Frank Chang <frank.chang@sifive.com>
2
2
3
vs() should return -RISCV_EXCP_ILLEGAL_INST instead of -1 if rvv feature
3
do_opivx_widen() should return false if check function returns false.
4
is not enabled.
5
6
If -1 is returned, exception will be raised and cs->exception_index will
7
be set to the negative return value. The exception will then be treated
8
as an instruction access fault instead of illegal instruction fault.
9
4
10
Signed-off-by: Frank Chang <frank.chang@sifive.com>
5
Signed-off-by: Frank Chang <frank.chang@sifive.com>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
7
Message-Id: <20200710104920.13550-4-frank.chang@sifive.com>
13
Message-id: 20210223065935.20208-1-frank.chang@sifive.com
14
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
8
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
15
---
9
---
16
target/riscv/csr.c | 2 +-
10
target/riscv/insn_trans/trans_rvv.inc.c | 2 +-
17
1 file changed, 1 insertion(+), 1 deletion(-)
11
1 file changed, 1 insertion(+), 1 deletion(-)
18
12
19
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
13
diff --git a/target/riscv/insn_trans/trans_rvv.inc.c b/target/riscv/insn_trans/trans_rvv.inc.c
20
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
21
--- a/target/riscv/csr.c
15
--- a/target/riscv/insn_trans/trans_rvv.inc.c
22
+++ b/target/riscv/csr.c
16
+++ b/target/riscv/insn_trans/trans_rvv.inc.c
23
@@ -XXX,XX +XXX,XX @@ static int vs(CPURISCVState *env, int csrno)
17
@@ -XXX,XX +XXX,XX @@ static bool do_opivx_widen(DisasContext *s, arg_rmrr *a,
24
if (env->misa & RVV) {
18
if (opivx_widen_check(s, a)) {
25
return 0;
19
return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, fn, s);
26
}
20
}
27
- return -1;
21
- return true;
28
+ return -RISCV_EXCP_ILLEGAL_INST;
22
+ return false;
29
}
23
}
30
24
31
static int ctr(CPURISCVState *env, int csrno)
25
#define GEN_OPIVX_WIDEN_TRANS(NAME) \
32
--
26
--
33
2.30.1
27
2.27.0
34
28
35
29
diff view generated by jsdifflib
1
From: Georg Kotheimer <georg.kotheimer@kernkonzept.com>
1
From: Frank Chang <frank.chang@sifive.com>
2
2
3
The current two-stage lookup detection in riscv_cpu_do_interrupt falls
3
vill bit is at vtype[XLEN-1].
4
short of its purpose, as all it checks is whether two-stage address
5
translation either via the hypervisor-load store instructions or the
6
MPRV feature would be allowed.
7
4
8
What we really need instead is whether two-stage address translation was
5
Signed-off-by: Frank Chang <frank.chang@sifive.com>
9
active when the exception was raised. However, in riscv_cpu_do_interrupt
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
we do not have the information to reliably detect this. Therefore, when
7
Message-Id: <20200710104920.13550-5-frank.chang@sifive.com>
11
we raise a memory fault exception we have to record whether two-stage
12
address translation is active.
13
14
Signed-off-by: Georg Kotheimer <georg.kotheimer@kernkonzept.com>
15
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
16
Message-id: 20210319141459.1196741-1-georg.kotheimer@kernkonzept.com
17
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
8
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
18
---
9
---
19
target/riscv/cpu.h | 4 ++++
10
target/riscv/cpu.h | 2 +-
20
target/riscv/cpu.c | 1 +
11
1 file changed, 1 insertion(+), 1 deletion(-)
21
target/riscv/cpu_helper.c | 21 ++++++++-------------
22
3 files changed, 13 insertions(+), 13 deletions(-)
23
12
24
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
13
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
25
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
26
--- a/target/riscv/cpu.h
15
--- a/target/riscv/cpu.h
27
+++ b/target/riscv/cpu.h
16
+++ b/target/riscv/cpu.h
28
@@ -XXX,XX +XXX,XX @@ struct CPURISCVState {
17
@@ -XXX,XX +XXX,XX @@ FIELD(VTYPE, VLMUL, 0, 2)
29
target_ulong satp_hs;
18
FIELD(VTYPE, VSEW, 2, 3)
30
uint64_t mstatus_hs;
19
FIELD(VTYPE, VEDIV, 5, 2)
31
20
FIELD(VTYPE, RESERVED, 7, sizeof(target_ulong) * 8 - 9)
32
+ /* Signals whether the current exception occurred with two-stage address
21
-FIELD(VTYPE, VILL, sizeof(target_ulong) * 8 - 2, 1)
33
+ translation active. */
22
+FIELD(VTYPE, VILL, sizeof(target_ulong) * 8 - 1, 1)
34
+ bool two_stage_lookup;
23
35
+
24
struct CPURISCVState {
36
target_ulong scounteren;
25
target_ulong gpr[32];
37
target_ulong mcounteren;
38
39
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/target/riscv/cpu.c
42
+++ b/target/riscv/cpu.c
43
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_reset(DeviceState *dev)
44
env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
45
env->mcause = 0;
46
env->pc = env->resetvec;
47
+ env->two_stage_lookup = false;
48
#endif
49
cs->exception_index = EXCP_NONE;
50
env->load_res = -1;
51
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/riscv/cpu_helper.c
54
+++ b/target/riscv/cpu_helper.c
55
@@ -XXX,XX +XXX,XX @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
56
g_assert_not_reached();
57
}
58
env->badaddr = address;
59
+ env->two_stage_lookup = two_stage;
60
}
61
62
hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
63
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
64
}
65
66
env->badaddr = addr;
67
+ env->two_stage_lookup = riscv_cpu_virt_enabled(env) ||
68
+ riscv_cpu_two_stage_lookup(mmu_idx);
69
riscv_raise_exception(&cpu->env, cs->exception_index, retaddr);
70
}
71
72
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
73
g_assert_not_reached();
74
}
75
env->badaddr = addr;
76
+ env->two_stage_lookup = riscv_cpu_virt_enabled(env) ||
77
+ riscv_cpu_two_stage_lookup(mmu_idx);
78
riscv_raise_exception(env, cs->exception_index, retaddr);
79
}
80
#endif /* !CONFIG_USER_ONLY */
81
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_do_interrupt(CPUState *cs)
82
/* handle the trap in S-mode */
83
if (riscv_has_ext(env, RVH)) {
84
target_ulong hdeleg = async ? env->hideleg : env->hedeleg;
85
- bool two_stage_lookup = false;
86
87
- if (env->priv == PRV_M ||
88
- (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) ||
89
- (env->priv == PRV_U && !riscv_cpu_virt_enabled(env) &&
90
- get_field(env->hstatus, HSTATUS_HU))) {
91
- two_stage_lookup = true;
92
- }
93
-
94
- if ((riscv_cpu_virt_enabled(env) || two_stage_lookup) && write_tval) {
95
+ if (env->two_stage_lookup && write_tval) {
96
/*
97
* If we are writing a guest virtual address to stval, set
98
* this to 1. If we are trapping to VS we will set this to 0
99
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_do_interrupt(CPUState *cs)
100
riscv_cpu_set_force_hs_excep(env, 0);
101
} else {
102
/* Trap into HS mode */
103
- if (!two_stage_lookup) {
104
- env->hstatus = set_field(env->hstatus, HSTATUS_SPV,
105
- riscv_cpu_virt_enabled(env));
106
- }
107
+ env->hstatus = set_field(env->hstatus, HSTATUS_SPV, false);
108
htval = env->guest_phys_fault_addr;
109
}
110
}
111
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_do_interrupt(CPUState *cs)
112
* RISC-V ISA Specification.
113
*/
114
115
+ env->two_stage_lookup = false;
116
#endif
117
cs->exception_index = EXCP_NONE; /* mark handled to qemu */
118
}
119
--
26
--
120
2.30.1
27
2.27.0
121
28
122
29
diff view generated by jsdifflib
1
From: Georg Kotheimer <georg.kotheimer@kernkonzept.com>
1
Conver the Ibex UART to use the recently added qdev-clock functions.
2
2
3
The previous implementation was broken in many ways:
3
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
4
- Used mideleg instead of hideleg to mask accesses
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
- Used MIP_VSSIP instead of VS_MODE_INTERRUPTS to mask writes to vsie
5
Message-id: b0136fad870a29049959ec161c1217b967d7e19d.1594332223.git.alistair.francis@wdc.com
6
- Did not shift between S bits and VS bits (VSEIP <-> SEIP, ...)
6
Message-Id: <b0136fad870a29049959ec161c1217b967d7e19d.1594332223.git.alistair.francis@wdc.com>
7
---
8
include/hw/char/ibex_uart.h | 3 +++
9
hw/char/ibex_uart.c | 30 +++++++++++++++++++++++++++---
10
2 files changed, 30 insertions(+), 3 deletions(-)
7
11
8
Signed-off-by: Georg Kotheimer <georg.kotheimer@kernkonzept.com>
12
diff --git a/include/hw/char/ibex_uart.h b/include/hw/char/ibex_uart.h
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Message-id: 20210311094738.1376795-1-georg.kotheimer@kernkonzept.com
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
---
13
target/riscv/csr.c | 68 +++++++++++++++++++++++-----------------------
14
1 file changed, 34 insertions(+), 34 deletions(-)
15
16
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
17
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
18
--- a/target/riscv/csr.c
14
--- a/include/hw/char/ibex_uart.h
19
+++ b/target/riscv/csr.c
15
+++ b/include/hw/char/ibex_uart.h
20
@@ -XXX,XX +XXX,XX @@ static int write_sstatus(CPURISCVState *env, int csrno, target_ulong val)
16
@@ -XXX,XX +XXX,XX @@
21
return write_mstatus(env, CSR_MSTATUS, newval);
17
#define IBEX_UART_TIMEOUT_CTRL 0x2c
18
19
#define IBEX_UART_TX_FIFO_SIZE 16
20
+#define IBEX_UART_CLOCK 50000000 /* 50MHz clock */
21
22
#define TYPE_IBEX_UART "ibex-uart"
23
#define IBEX_UART(obj) \
24
@@ -XXX,XX +XXX,XX @@ typedef struct {
25
uint32_t uart_val;
26
uint32_t uart_timeout_ctrl;
27
28
+ Clock *f_clk;
29
+
30
CharBackend chr;
31
qemu_irq tx_watermark;
32
qemu_irq rx_watermark;
33
diff --git a/hw/char/ibex_uart.c b/hw/char/ibex_uart.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/char/ibex_uart.c
36
+++ b/hw/char/ibex_uart.c
37
@@ -XXX,XX +XXX,XX @@
38
#include "qemu/osdep.h"
39
#include "hw/char/ibex_uart.h"
40
#include "hw/irq.h"
41
+#include "hw/qdev-clock.h"
42
#include "hw/qdev-properties.h"
43
#include "migration/vmstate.h"
44
#include "qemu/log.h"
45
@@ -XXX,XX +XXX,XX @@ static void ibex_uart_reset(DeviceState *dev)
46
ibex_uart_update_irqs(s);
22
}
47
}
23
48
24
+static int read_vsie(CPURISCVState *env, int csrno, target_ulong *val)
49
+static uint64_t ibex_uart_get_baud(IbexUartState *s)
25
+{
50
+{
26
+ /* Shift the VS bits to their S bit location in vsie */
51
+ uint64_t baud;
27
+ *val = (env->mie & env->hideleg & VS_MODE_INTERRUPTS) >> 1;
52
+
28
+ return 0;
53
+ baud = ((s->uart_ctrl & UART_CTRL_NCO) >> 16);
54
+ baud *= clock_get_hz(s->f_clk);
55
+ baud >>= 20;
56
+
57
+ return baud;
29
+}
58
+}
30
+
59
+
31
static int read_sie(CPURISCVState *env, int csrno, target_ulong *val)
60
static uint64_t ibex_uart_read(void *opaque, hwaddr addr,
61
unsigned int size)
32
{
62
{
33
if (riscv_cpu_virt_enabled(env)) {
63
@@ -XXX,XX +XXX,XX @@ static void ibex_uart_write(void *opaque, hwaddr addr,
34
- /* Tell the guest the VS bits, shifted to the S bit locations */
64
"%s: UART_CTRL_RXBLVL is not supported\n", __func__);
35
- *val = (env->mie & env->mideleg & VS_MODE_INTERRUPTS) >> 1;
65
}
36
+ read_vsie(env, CSR_VSIE, val);
66
if (value & UART_CTRL_NCO) {
37
} else {
67
- uint64_t baud = ((value & UART_CTRL_NCO) >> 16);
38
*val = env->mie & env->mideleg;
68
- baud *= 1000;
69
- baud >>= 20;
70
+ uint64_t baud = ibex_uart_get_baud(s);
71
72
s->char_tx_time = (NANOSECONDS_PER_SECOND / baud) * 10;
73
}
74
@@ -XXX,XX +XXX,XX @@ static void ibex_uart_write(void *opaque, hwaddr addr,
39
}
75
}
40
return 0;
41
}
76
}
42
77
43
-static int write_sie(CPURISCVState *env, int csrno, target_ulong val)
78
+static void ibex_uart_clk_update(void *opaque)
44
+static int write_vsie(CPURISCVState *env, int csrno, target_ulong val)
45
{
46
- target_ulong newval;
47
+ /* Shift the S bits to their VS bit location in mie */
48
+ target_ulong newval = (env->mie & ~VS_MODE_INTERRUPTS) |
49
+ ((val << 1) & env->hideleg & VS_MODE_INTERRUPTS);
50
+ return write_mie(env, CSR_MIE, newval);
51
+}
52
53
+static int write_sie(CPURISCVState *env, int csrno, target_ulong val)
54
+{
79
+{
55
if (riscv_cpu_virt_enabled(env)) {
80
+ IbexUartState *s = opaque;
56
- /* Shift the guests S bits to VS */
81
+
57
- newval = (env->mie & ~VS_MODE_INTERRUPTS) |
82
+ /* recompute uart's speed on clock change */
58
- ((val << 1) & VS_MODE_INTERRUPTS);
83
+ uint64_t baud = ibex_uart_get_baud(s);
59
+ write_vsie(env, CSR_VSIE, val);
84
+
60
} else {
85
+ s->char_tx_time = (NANOSECONDS_PER_SECOND / baud) * 10;
61
- newval = (env->mie & ~S_MODE_INTERRUPTS) | (val & S_MODE_INTERRUPTS);
62
+ target_ulong newval = (env->mie & ~S_MODE_INTERRUPTS) |
63
+ (val & S_MODE_INTERRUPTS);
64
+ write_mie(env, CSR_MIE, newval);
65
}
66
67
- return write_mie(env, CSR_MIE, newval);
68
+ return 0;
69
}
70
71
static int read_stvec(CPURISCVState *env, int csrno, target_ulong *val)
72
@@ -XXX,XX +XXX,XX @@ static int write_sbadaddr(CPURISCVState *env, int csrno, target_ulong val)
73
return 0;
74
}
75
76
+static int rmw_vsip(CPURISCVState *env, int csrno, target_ulong *ret_value,
77
+ target_ulong new_value, target_ulong write_mask)
78
+{
79
+ /* Shift the S bits to their VS bit location in mip */
80
+ int ret = rmw_mip(env, 0, ret_value, new_value << 1,
81
+ (write_mask << 1) & vsip_writable_mask & env->hideleg);
82
+ *ret_value &= VS_MODE_INTERRUPTS;
83
+ /* Shift the VS bits to their S bit location in vsip */
84
+ *ret_value >>= 1;
85
+ return ret;
86
+}
86
+}
87
+
87
+
88
static int rmw_sip(CPURISCVState *env, int csrno, target_ulong *ret_value,
88
static void fifo_trigger_update(void *opaque)
89
target_ulong new_value, target_ulong write_mask)
90
{
89
{
91
int ret;
90
IbexUartState *s = opaque;
92
91
@@ -XXX,XX +XXX,XX @@ static void ibex_uart_init(Object *obj)
93
if (riscv_cpu_virt_enabled(env)) {
94
- /* Shift the new values to line up with the VS bits */
95
- ret = rmw_mip(env, CSR_MSTATUS, ret_value, new_value << 1,
96
- (write_mask & sip_writable_mask) << 1 & env->mideleg);
97
- ret &= vsip_writable_mask;
98
- ret >>= 1;
99
+ ret = rmw_vsip(env, CSR_VSIP, ret_value, new_value, write_mask);
100
} else {
101
ret = rmw_mip(env, CSR_MSTATUS, ret_value, new_value,
102
write_mask & env->mideleg & sip_writable_mask);
103
@@ -XXX,XX +XXX,XX @@ static int write_vsstatus(CPURISCVState *env, int csrno, target_ulong val)
104
return 0;
105
}
106
107
-static int rmw_vsip(CPURISCVState *env, int csrno, target_ulong *ret_value,
108
- target_ulong new_value, target_ulong write_mask)
109
-{
110
- int ret = rmw_mip(env, 0, ret_value, new_value,
111
- write_mask & env->mideleg & vsip_writable_mask);
112
- return ret;
113
-}
114
-
115
-static int read_vsie(CPURISCVState *env, int csrno, target_ulong *val)
116
-{
117
- *val = env->mie & env->mideleg & VS_MODE_INTERRUPTS;
118
- return 0;
119
-}
120
-
121
-static int write_vsie(CPURISCVState *env, int csrno, target_ulong val)
122
-{
123
- target_ulong newval = (env->mie & ~env->mideleg) | (val & env->mideleg & MIP_VSSIP);
124
- return write_mie(env, CSR_MIE, newval);
125
-}
126
-
127
static int read_vstvec(CPURISCVState *env, int csrno, target_ulong *val)
128
{
92
{
129
*val = env->vstvec;
93
IbexUartState *s = IBEX_UART(obj);
94
95
+ s->f_clk = qdev_init_clock_in(DEVICE(obj), "f_clock",
96
+ ibex_uart_clk_update, s);
97
+ clock_set_hz(s->f_clk, IBEX_UART_CLOCK);
98
+
99
sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->tx_watermark);
100
sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->rx_watermark);
101
sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->tx_empty);
130
--
102
--
131
2.30.1
103
2.27.0
132
104
133
105
diff view generated by jsdifflib
1
From: Alexander Wagner <alexander.wagner@ulal.de>
2
3
Not disabling the UART leads to QEMU overwriting the UART receive buffer with
4
the newest received byte. The rx_level variable is added to allow the use of
5
the existing OpenTitan driver libraries.
6
7
Signed-off-by: Alexander Wagner <alexander.wagner@ulal.de>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Message-id: 20210309152130.13038-1-alexander.wagner@ulal.de
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
1
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
2
Message-id: 06372c9cdeec715077899e71c858d9f0a2a3395b.1594332223.git.alistair.francis@wdc.com
3
Message-Id: <06372c9cdeec715077899e71c858d9f0a2a3395b.1594332223.git.alistair.francis@wdc.com>
11
---
4
---
12
include/hw/char/ibex_uart.h | 4 ++++
5
include/hw/char/ibex_uart.h | 76 ++++++++++-----------
13
hw/char/ibex_uart.c | 23 ++++++++++++++++++-----
6
hw/char/ibex_uart.c | 130 ++++++++++++++++++------------------
14
2 files changed, 22 insertions(+), 5 deletions(-)
7
2 files changed, 100 insertions(+), 106 deletions(-)
15
8
16
diff --git a/include/hw/char/ibex_uart.h b/include/hw/char/ibex_uart.h
9
diff --git a/include/hw/char/ibex_uart.h b/include/hw/char/ibex_uart.h
17
index XXXXXXX..XXXXXXX 100644
10
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/char/ibex_uart.h
11
--- a/include/hw/char/ibex_uart.h
19
+++ b/include/hw/char/ibex_uart.h
12
+++ b/include/hw/char/ibex_uart.h
20
@@ -XXX,XX +XXX,XX @@ REG32(FIFO_CTRL, 0x1c)
13
@@ -XXX,XX +XXX,XX @@
21
FIELD(FIFO_CTRL, RXILVL, 2, 3)
14
#define HW_IBEX_UART_H
22
FIELD(FIFO_CTRL, TXILVL, 5, 2)
15
23
REG32(FIFO_STATUS, 0x20)
16
#include "hw/sysbus.h"
24
+ FIELD(FIFO_STATUS, TXLVL, 0, 5)
17
+#include "hw/registerfields.h"
25
+ FIELD(FIFO_STATUS, RXLVL, 16, 5)
18
#include "chardev/char-fe.h"
26
REG32(OVRD, 0x24)
19
#include "qemu/timer.h"
27
REG32(VAL, 0x28)
20
28
REG32(TIMEOUT_CTRL, 0x2c)
21
-#define IBEX_UART_INTR_STATE 0x00
29
@@ -XXX,XX +XXX,XX @@ struct IbexUartState {
22
- #define INTR_STATE_TX_WATERMARK (1 << 0)
30
uint8_t tx_fifo[IBEX_UART_TX_FIFO_SIZE];
23
- #define INTR_STATE_RX_WATERMARK (1 << 1)
31
uint32_t tx_level;
24
- #define INTR_STATE_TX_EMPTY (1 << 2)
32
25
- #define INTR_STATE_RX_OVERFLOW (1 << 3)
33
+ uint32_t rx_level;
26
-#define IBEX_UART_INTR_ENABLE 0x04
34
+
27
-#define IBEX_UART_INTR_TEST 0x08
35
QEMUTimer *fifo_trigger_handle;
28
-
36
uint64_t char_tx_time;
29
-#define IBEX_UART_CTRL 0x0c
37
30
- #define UART_CTRL_TX_ENABLE (1 << 0)
31
- #define UART_CTRL_RX_ENABLE (1 << 1)
32
- #define UART_CTRL_NF (1 << 2)
33
- #define UART_CTRL_SLPBK (1 << 4)
34
- #define UART_CTRL_LLPBK (1 << 5)
35
- #define UART_CTRL_PARITY_EN (1 << 6)
36
- #define UART_CTRL_PARITY_ODD (1 << 7)
37
- #define UART_CTRL_RXBLVL (3 << 8)
38
- #define UART_CTRL_NCO (0xFFFF << 16)
39
-
40
-#define IBEX_UART_STATUS 0x10
41
- #define UART_STATUS_TXFULL (1 << 0)
42
- #define UART_STATUS_RXFULL (1 << 1)
43
- #define UART_STATUS_TXEMPTY (1 << 2)
44
- #define UART_STATUS_RXIDLE (1 << 4)
45
- #define UART_STATUS_RXEMPTY (1 << 5)
46
-
47
-#define IBEX_UART_RDATA 0x14
48
-#define IBEX_UART_WDATA 0x18
49
-
50
-#define IBEX_UART_FIFO_CTRL 0x1c
51
- #define FIFO_CTRL_RXRST (1 << 0)
52
- #define FIFO_CTRL_TXRST (1 << 1)
53
- #define FIFO_CTRL_RXILVL (7 << 2)
54
- #define FIFO_CTRL_RXILVL_SHIFT (2)
55
- #define FIFO_CTRL_TXILVL (3 << 5)
56
- #define FIFO_CTRL_TXILVL_SHIFT (5)
57
-
58
-#define IBEX_UART_FIFO_STATUS 0x20
59
-#define IBEX_UART_OVRD 0x24
60
-#define IBEX_UART_VAL 0x28
61
-#define IBEX_UART_TIMEOUT_CTRL 0x2c
62
+REG32(INTR_STATE, 0x00)
63
+ FIELD(INTR_STATE, TX_WATERMARK, 0, 1)
64
+ FIELD(INTR_STATE, RX_WATERMARK, 1, 1)
65
+ FIELD(INTR_STATE, TX_EMPTY, 2, 1)
66
+ FIELD(INTR_STATE, RX_OVERFLOW, 3, 1)
67
+REG32(INTR_ENABLE, 0x04)
68
+REG32(INTR_TEST, 0x08)
69
+REG32(CTRL, 0x0C)
70
+ FIELD(CTRL, TX_ENABLE, 0, 1)
71
+ FIELD(CTRL, RX_ENABLE, 1, 1)
72
+ FIELD(CTRL, NF, 2, 1)
73
+ FIELD(CTRL, SLPBK, 4, 1)
74
+ FIELD(CTRL, LLPBK, 5, 1)
75
+ FIELD(CTRL, PARITY_EN, 6, 1)
76
+ FIELD(CTRL, PARITY_ODD, 7, 1)
77
+ FIELD(CTRL, RXBLVL, 8, 2)
78
+ FIELD(CTRL, NCO, 16, 16)
79
+REG32(STATUS, 0x10)
80
+ FIELD(STATUS, TXFULL, 0, 1)
81
+ FIELD(STATUS, RXFULL, 1, 1)
82
+ FIELD(STATUS, TXEMPTY, 2, 1)
83
+ FIELD(STATUS, RXIDLE, 4, 1)
84
+ FIELD(STATUS, RXEMPTY, 5, 1)
85
+REG32(RDATA, 0x14)
86
+REG32(WDATA, 0x18)
87
+REG32(FIFO_CTRL, 0x1c)
88
+ FIELD(FIFO_CTRL, RXRST, 0, 1)
89
+ FIELD(FIFO_CTRL, TXRST, 1, 1)
90
+ FIELD(FIFO_CTRL, RXILVL, 2, 3)
91
+ FIELD(FIFO_CTRL, TXILVL, 5, 2)
92
+REG32(FIFO_STATUS, 0x20)
93
+REG32(OVRD, 0x24)
94
+REG32(VAL, 0x28)
95
+REG32(TIMEOUT_CTRL, 0x2c)
96
97
#define IBEX_UART_TX_FIFO_SIZE 16
98
#define IBEX_UART_CLOCK 50000000 /* 50MHz clock */
38
diff --git a/hw/char/ibex_uart.c b/hw/char/ibex_uart.c
99
diff --git a/hw/char/ibex_uart.c b/hw/char/ibex_uart.c
39
index XXXXXXX..XXXXXXX 100644
100
index XXXXXXX..XXXXXXX 100644
40
--- a/hw/char/ibex_uart.c
101
--- a/hw/char/ibex_uart.c
41
+++ b/hw/char/ibex_uart.c
102
+++ b/hw/char/ibex_uart.c
103
@@ -XXX,XX +XXX,XX @@
104
105
static void ibex_uart_update_irqs(IbexUartState *s)
106
{
107
- if (s->uart_intr_state & s->uart_intr_enable & INTR_STATE_TX_WATERMARK) {
108
+ if (s->uart_intr_state & s->uart_intr_enable & R_INTR_STATE_TX_WATERMARK_MASK) {
109
qemu_set_irq(s->tx_watermark, 1);
110
} else {
111
qemu_set_irq(s->tx_watermark, 0);
112
}
113
114
- if (s->uart_intr_state & s->uart_intr_enable & INTR_STATE_RX_WATERMARK) {
115
+ if (s->uart_intr_state & s->uart_intr_enable & R_INTR_STATE_RX_WATERMARK_MASK) {
116
qemu_set_irq(s->rx_watermark, 1);
117
} else {
118
qemu_set_irq(s->rx_watermark, 0);
119
}
120
121
- if (s->uart_intr_state & s->uart_intr_enable & INTR_STATE_TX_EMPTY) {
122
+ if (s->uart_intr_state & s->uart_intr_enable & R_INTR_STATE_TX_EMPTY_MASK) {
123
qemu_set_irq(s->tx_empty, 1);
124
} else {
125
qemu_set_irq(s->tx_empty, 0);
126
}
127
128
- if (s->uart_intr_state & s->uart_intr_enable & INTR_STATE_RX_OVERFLOW) {
129
+ if (s->uart_intr_state & s->uart_intr_enable & R_INTR_STATE_RX_OVERFLOW_MASK) {
130
qemu_set_irq(s->rx_overflow, 1);
131
} else {
132
qemu_set_irq(s->rx_overflow, 0);
42
@@ -XXX,XX +XXX,XX @@ static int ibex_uart_can_receive(void *opaque)
133
@@ -XXX,XX +XXX,XX @@ static int ibex_uart_can_receive(void *opaque)
43
{
134
{
44
IbexUartState *s = opaque;
135
IbexUartState *s = opaque;
45
136
46
- if (s->uart_ctrl & R_CTRL_RX_ENABLE_MASK) {
137
- if (s->uart_ctrl & UART_CTRL_RX_ENABLE) {
47
+ if ((s->uart_ctrl & R_CTRL_RX_ENABLE_MASK)
138
+ if (s->uart_ctrl & R_CTRL_RX_ENABLE_MASK) {
48
+ && !(s->uart_status & R_STATUS_RXFULL_MASK)) {
49
return 1;
139
return 1;
50
}
140
}
51
141
52
@@ -XXX,XX +XXX,XX @@ static void ibex_uart_receive(void *opaque, const uint8_t *buf, int size)
142
@@ -XXX,XX +XXX,XX @@ static int ibex_uart_can_receive(void *opaque)
53
143
static void ibex_uart_receive(void *opaque, const uint8_t *buf, int size)
54
s->uart_status &= ~R_STATUS_RXIDLE_MASK;
144
{
55
s->uart_status &= ~R_STATUS_RXEMPTY_MASK;
145
IbexUartState *s = opaque;
56
+ /* The RXFULL is set after receiving a single byte
146
- uint8_t rx_fifo_level = (s->uart_fifo_ctrl & FIFO_CTRL_RXILVL)
57
+ * as the FIFO buffers are not yet implemented.
147
- >> FIFO_CTRL_RXILVL_SHIFT;
58
+ */
148
+ uint8_t rx_fifo_level = (s->uart_fifo_ctrl & R_FIFO_CTRL_RXILVL_MASK)
59
+ s->uart_status |= R_STATUS_RXFULL_MASK;
149
+ >> R_FIFO_CTRL_RXILVL_SHIFT;
60
+ s->rx_level += 1;
150
151
s->uart_rdata = *buf;
152
153
- s->uart_status &= ~UART_STATUS_RXIDLE;
154
- s->uart_status &= ~UART_STATUS_RXEMPTY;
155
+ s->uart_status &= ~R_STATUS_RXIDLE_MASK;
156
+ s->uart_status &= ~R_STATUS_RXEMPTY_MASK;
61
157
62
if (size > rx_fifo_level) {
158
if (size > rx_fifo_level) {
63
s->uart_intr_state |= R_INTR_STATE_RX_WATERMARK_MASK;
159
- s->uart_intr_state |= INTR_STATE_RX_WATERMARK;
64
@@ -XXX,XX +XXX,XX @@ static void ibex_uart_reset(DeviceState *dev)
160
+ s->uart_intr_state |= R_INTR_STATE_RX_WATERMARK_MASK;
65
s->uart_timeout_ctrl = 0x00000000;
161
}
66
162
67
s->tx_level = 0;
163
ibex_uart_update_irqs(s);
68
+ s->rx_level = 0;
164
@@ -XXX,XX +XXX,XX @@ static gboolean ibex_uart_xmit(GIOChannel *chan, GIOCondition cond,
69
165
void *opaque)
70
s->char_tx_time = (NANOSECONDS_PER_SECOND / 230400) * 10;
166
{
167
IbexUartState *s = opaque;
168
- uint8_t tx_fifo_level = (s->uart_fifo_ctrl & FIFO_CTRL_TXILVL)
169
- >> FIFO_CTRL_TXILVL_SHIFT;
170
+ uint8_t tx_fifo_level = (s->uart_fifo_ctrl & R_FIFO_CTRL_TXILVL_MASK)
171
+ >> R_FIFO_CTRL_TXILVL_SHIFT;
172
int ret;
173
174
/* instant drain the fifo when there's no back-end */
175
@@ -XXX,XX +XXX,XX @@ static gboolean ibex_uart_xmit(GIOChannel *chan, GIOCondition cond,
176
}
177
178
if (!s->tx_level) {
179
- s->uart_status &= ~UART_STATUS_TXFULL;
180
- s->uart_status |= UART_STATUS_TXEMPTY;
181
- s->uart_intr_state |= INTR_STATE_TX_EMPTY;
182
- s->uart_intr_state &= ~INTR_STATE_TX_WATERMARK;
183
+ s->uart_status &= ~R_STATUS_TXFULL_MASK;
184
+ s->uart_status |= R_STATUS_TXEMPTY_MASK;
185
+ s->uart_intr_state |= R_INTR_STATE_TX_EMPTY_MASK;
186
+ s->uart_intr_state &= ~R_INTR_STATE_TX_WATERMARK_MASK;
187
ibex_uart_update_irqs(s);
188
return FALSE;
189
}
190
@@ -XXX,XX +XXX,XX @@ static gboolean ibex_uart_xmit(GIOChannel *chan, GIOCondition cond,
191
192
/* Clear the TX Full bit */
193
if (s->tx_level != IBEX_UART_TX_FIFO_SIZE) {
194
- s->uart_status &= ~UART_STATUS_TXFULL;
195
+ s->uart_status &= ~R_STATUS_TXFULL_MASK;
196
}
197
198
/* Disable the TX_WATERMARK IRQ */
199
if (s->tx_level < tx_fifo_level) {
200
- s->uart_intr_state &= ~INTR_STATE_TX_WATERMARK;
201
+ s->uart_intr_state &= ~R_INTR_STATE_TX_WATERMARK_MASK;
202
}
203
204
/* Set TX empty */
205
if (s->tx_level == 0) {
206
- s->uart_status |= UART_STATUS_TXEMPTY;
207
- s->uart_intr_state |= INTR_STATE_TX_EMPTY;
208
+ s->uart_status |= R_STATUS_TXEMPTY_MASK;
209
+ s->uart_intr_state |= R_INTR_STATE_TX_EMPTY_MASK;
210
}
211
212
ibex_uart_update_irqs(s);
213
@@ -XXX,XX +XXX,XX @@ static void uart_write_tx_fifo(IbexUartState *s, const uint8_t *buf,
214
int size)
215
{
216
uint64_t current_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
217
- uint8_t tx_fifo_level = (s->uart_fifo_ctrl & FIFO_CTRL_TXILVL)
218
- >> FIFO_CTRL_TXILVL_SHIFT;
219
+ uint8_t tx_fifo_level = (s->uart_fifo_ctrl & R_FIFO_CTRL_TXILVL_MASK)
220
+ >> R_FIFO_CTRL_TXILVL_SHIFT;
221
222
if (size > IBEX_UART_TX_FIFO_SIZE - s->tx_level) {
223
size = IBEX_UART_TX_FIFO_SIZE - s->tx_level;
224
@@ -XXX,XX +XXX,XX @@ static void uart_write_tx_fifo(IbexUartState *s, const uint8_t *buf,
225
s->tx_level += size;
226
227
if (s->tx_level > 0) {
228
- s->uart_status &= ~UART_STATUS_TXEMPTY;
229
+ s->uart_status &= ~R_STATUS_TXEMPTY_MASK;
230
}
231
232
if (s->tx_level >= tx_fifo_level) {
233
- s->uart_intr_state |= INTR_STATE_TX_WATERMARK;
234
+ s->uart_intr_state |= R_INTR_STATE_TX_WATERMARK_MASK;
235
ibex_uart_update_irqs(s);
236
}
237
238
if (s->tx_level == IBEX_UART_TX_FIFO_SIZE) {
239
- s->uart_status |= UART_STATUS_TXFULL;
240
+ s->uart_status |= R_STATUS_TXFULL_MASK;
241
}
242
243
timer_mod(s->fifo_trigger_handle, current_time +
244
@@ -XXX,XX +XXX,XX @@ static uint64_t ibex_uart_get_baud(IbexUartState *s)
245
{
246
uint64_t baud;
247
248
- baud = ((s->uart_ctrl & UART_CTRL_NCO) >> 16);
249
+ baud = ((s->uart_ctrl & R_CTRL_NCO_MASK) >> 16);
250
baud *= clock_get_hz(s->f_clk);
251
baud >>= 20;
71
252
72
@@ -XXX,XX +XXX,XX @@ static uint64_t ibex_uart_read(void *opaque, hwaddr addr,
253
@@ -XXX,XX +XXX,XX @@ static uint64_t ibex_uart_read(void *opaque, hwaddr addr,
73
254
IbexUartState *s = opaque;
74
case R_RDATA:
255
uint64_t retvalue = 0;
256
257
- switch (addr) {
258
- case IBEX_UART_INTR_STATE:
259
+ switch (addr >> 2) {
260
+ case R_INTR_STATE:
261
retvalue = s->uart_intr_state;
262
break;
263
- case IBEX_UART_INTR_ENABLE:
264
+ case R_INTR_ENABLE:
265
retvalue = s->uart_intr_enable;
266
break;
267
- case IBEX_UART_INTR_TEST:
268
+ case R_INTR_TEST:
269
qemu_log_mask(LOG_GUEST_ERROR,
270
"%s: wdata is write only\n", __func__);
271
break;
272
273
- case IBEX_UART_CTRL:
274
+ case R_CTRL:
275
retvalue = s->uart_ctrl;
276
break;
277
- case IBEX_UART_STATUS:
278
+ case R_STATUS:
279
retvalue = s->uart_status;
280
break;
281
282
- case IBEX_UART_RDATA:
283
+ case R_RDATA:
75
retvalue = s->uart_rdata;
284
retvalue = s->uart_rdata;
76
- if (s->uart_ctrl & R_CTRL_RX_ENABLE_MASK) {
285
- if (s->uart_ctrl & UART_CTRL_RX_ENABLE) {
77
+ if ((s->uart_ctrl & R_CTRL_RX_ENABLE_MASK) && (s->rx_level > 0)) {
286
+ if (s->uart_ctrl & R_CTRL_RX_ENABLE_MASK) {
78
qemu_chr_fe_accept_input(&s->chr);
287
qemu_chr_fe_accept_input(&s->chr);
79
288
80
- s->uart_status |= R_STATUS_RXIDLE_MASK;
289
- s->uart_status |= UART_STATUS_RXIDLE;
81
- s->uart_status |= R_STATUS_RXEMPTY_MASK;
290
- s->uart_status |= UART_STATUS_RXEMPTY;
82
+ s->rx_level -= 1;
291
+ s->uart_status |= R_STATUS_RXIDLE_MASK;
83
+ s->uart_status &= ~R_STATUS_RXFULL_MASK;
292
+ s->uart_status |= R_STATUS_RXEMPTY_MASK;
84
+ if (s->rx_level == 0) {
293
}
85
+ s->uart_status |= R_STATUS_RXIDLE_MASK;
294
break;
86
+ s->uart_status |= R_STATUS_RXEMPTY_MASK;
295
- case IBEX_UART_WDATA:
87
+ }
296
+ case R_WDATA:
88
}
297
qemu_log_mask(LOG_GUEST_ERROR,
89
break;
298
"%s: wdata is write only\n", __func__);
90
case R_WDATA:
299
break;
300
301
- case IBEX_UART_FIFO_CTRL:
302
+ case R_FIFO_CTRL:
303
retvalue = s->uart_fifo_ctrl;
304
break;
305
- case IBEX_UART_FIFO_STATUS:
306
+ case R_FIFO_STATUS:
307
retvalue = s->uart_fifo_status;
308
309
retvalue |= s->tx_level & 0x1F;
91
@@ -XXX,XX +XXX,XX @@ static uint64_t ibex_uart_read(void *opaque, hwaddr addr,
310
@@ -XXX,XX +XXX,XX @@ static uint64_t ibex_uart_read(void *opaque, hwaddr addr,
92
case R_FIFO_STATUS:
311
"%s: RX fifos are not supported\n", __func__);
93
retvalue = s->uart_fifo_status;
312
break;
94
313
95
- retvalue |= s->tx_level & 0x1F;
314
- case IBEX_UART_OVRD:
96
+ retvalue |= (s->rx_level & 0x1F) << R_FIFO_STATUS_RXLVL_SHIFT;
315
+ case R_OVRD:
97
+ retvalue |= (s->tx_level & 0x1F) << R_FIFO_STATUS_TXLVL_SHIFT;
316
retvalue = s->uart_ovrd;
98
99
qemu_log_mask(LOG_UNIMP,
317
qemu_log_mask(LOG_UNIMP,
100
"%s: RX fifos are not supported\n", __func__);
318
"%s: ovrd is not supported\n", __func__);
319
break;
320
- case IBEX_UART_VAL:
321
+ case R_VAL:
322
retvalue = s->uart_val;
323
qemu_log_mask(LOG_UNIMP,
324
"%s: val is not supported\n", __func__);
325
break;
326
- case IBEX_UART_TIMEOUT_CTRL:
327
+ case R_TIMEOUT_CTRL:
328
retvalue = s->uart_timeout_ctrl;
329
qemu_log_mask(LOG_UNIMP,
330
"%s: timeout_ctrl is not supported\n", __func__);
101
@@ -XXX,XX +XXX,XX @@ static void ibex_uart_write(void *opaque, hwaddr addr,
331
@@ -XXX,XX +XXX,XX @@ static void ibex_uart_write(void *opaque, hwaddr addr,
332
IbexUartState *s = opaque;
333
uint32_t value = val64;
334
335
- switch (addr) {
336
- case IBEX_UART_INTR_STATE:
337
+ switch (addr >> 2) {
338
+ case R_INTR_STATE:
339
/* Write 1 clear */
340
s->uart_intr_state &= ~value;
341
ibex_uart_update_irqs(s);
342
break;
343
- case IBEX_UART_INTR_ENABLE:
344
+ case R_INTR_ENABLE:
345
s->uart_intr_enable = value;
346
ibex_uart_update_irqs(s);
347
break;
348
- case IBEX_UART_INTR_TEST:
349
+ case R_INTR_TEST:
350
s->uart_intr_state |= value;
351
ibex_uart_update_irqs(s);
352
break;
353
354
- case IBEX_UART_CTRL:
355
+ case R_CTRL:
356
s->uart_ctrl = value;
357
358
- if (value & UART_CTRL_NF) {
359
+ if (value & R_CTRL_NF_MASK) {
360
qemu_log_mask(LOG_UNIMP,
361
"%s: UART_CTRL_NF is not supported\n", __func__);
362
}
363
- if (value & UART_CTRL_SLPBK) {
364
+ if (value & R_CTRL_SLPBK_MASK) {
365
qemu_log_mask(LOG_UNIMP,
366
"%s: UART_CTRL_SLPBK is not supported\n", __func__);
367
}
368
- if (value & UART_CTRL_LLPBK) {
369
+ if (value & R_CTRL_LLPBK_MASK) {
370
qemu_log_mask(LOG_UNIMP,
371
"%s: UART_CTRL_LLPBK is not supported\n", __func__);
372
}
373
- if (value & UART_CTRL_PARITY_EN) {
374
+ if (value & R_CTRL_PARITY_EN_MASK) {
375
qemu_log_mask(LOG_UNIMP,
376
"%s: UART_CTRL_PARITY_EN is not supported\n",
377
__func__);
378
}
379
- if (value & UART_CTRL_PARITY_ODD) {
380
+ if (value & R_CTRL_PARITY_ODD_MASK) {
381
qemu_log_mask(LOG_UNIMP,
382
"%s: UART_CTRL_PARITY_ODD is not supported\n",
383
__func__);
384
}
385
- if (value & UART_CTRL_RXBLVL) {
386
+ if (value & R_CTRL_RXBLVL_MASK) {
387
qemu_log_mask(LOG_UNIMP,
388
"%s: UART_CTRL_RXBLVL is not supported\n", __func__);
389
}
390
- if (value & UART_CTRL_NCO) {
391
+ if (value & R_CTRL_NCO_MASK) {
392
uint64_t baud = ibex_uart_get_baud(s);
393
394
s->char_tx_time = (NANOSECONDS_PER_SECOND / baud) * 10;
395
}
396
break;
397
- case IBEX_UART_STATUS:
398
+ case R_STATUS:
399
qemu_log_mask(LOG_GUEST_ERROR,
400
"%s: status is read only\n", __func__);
401
break;
402
403
- case IBEX_UART_RDATA:
404
+ case R_RDATA:
405
qemu_log_mask(LOG_GUEST_ERROR,
406
"%s: rdata is read only\n", __func__);
407
break;
408
- case IBEX_UART_WDATA:
409
+ case R_WDATA:
410
uart_write_tx_fifo(s, (uint8_t *) &value, 1);
411
break;
412
413
- case IBEX_UART_FIFO_CTRL:
414
+ case R_FIFO_CTRL:
102
s->uart_fifo_ctrl = value;
415
s->uart_fifo_ctrl = value;
103
416
104
if (value & R_FIFO_CTRL_RXRST_MASK) {
417
- if (value & FIFO_CTRL_RXRST) {
105
+ s->rx_level = 0;
418
+ if (value & R_FIFO_CTRL_RXRST_MASK) {
106
qemu_log_mask(LOG_UNIMP,
419
qemu_log_mask(LOG_UNIMP,
107
"%s: RX fifos are not supported\n", __func__);
420
"%s: RX fifos are not supported\n", __func__);
108
}
421
}
422
- if (value & FIFO_CTRL_TXRST) {
423
+ if (value & R_FIFO_CTRL_TXRST_MASK) {
424
s->tx_level = 0;
425
}
426
break;
427
- case IBEX_UART_FIFO_STATUS:
428
+ case R_FIFO_STATUS:
429
qemu_log_mask(LOG_GUEST_ERROR,
430
"%s: fifo_status is read only\n", __func__);
431
break;
432
433
- case IBEX_UART_OVRD:
434
+ case R_OVRD:
435
s->uart_ovrd = value;
436
qemu_log_mask(LOG_UNIMP,
437
"%s: ovrd is not supported\n", __func__);
438
break;
439
- case IBEX_UART_VAL:
440
+ case R_VAL:
441
qemu_log_mask(LOG_GUEST_ERROR,
442
"%s: val is read only\n", __func__);
443
break;
444
- case IBEX_UART_TIMEOUT_CTRL:
445
+ case R_TIMEOUT_CTRL:
446
s->uart_timeout_ctrl = value;
447
qemu_log_mask(LOG_UNIMP,
448
"%s: timeout_ctrl is not supported\n", __func__);
449
@@ -XXX,XX +XXX,XX @@ static void fifo_trigger_update(void *opaque)
450
{
451
IbexUartState *s = opaque;
452
453
- if (s->uart_ctrl & UART_CTRL_TX_ENABLE) {
454
+ if (s->uart_ctrl & R_CTRL_TX_ENABLE_MASK) {
455
ibex_uart_xmit(NULL, G_IO_OUT, s);
456
}
457
}
109
--
458
--
110
2.30.1
459
2.27.0
111
460
112
461
diff view generated by jsdifflib
1
From: Jim Shu <cwshu@andestech.com>
1
From: Liao Pingfang <liao.pingfang@zte.com.cn>
2
2
3
Like MMU translation, add qemu log of PMP permission checking for
3
Remove superfluous breaks, as there is a "return" before them.
4
debugging.
5
4
6
Signed-off-by: Jim Shu <cwshu@andestech.com>
5
Signed-off-by: Liao Pingfang <liao.pingfang@zte.com.cn>
6
Signed-off-by: Yi Wang <wang.yi59@zte.com.cn>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Thomas Huth <thuth@redhat.com>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Message-id: 1613916082-19528-3-git-send-email-cwshu@andestech.com
10
Message-Id: <1594600421-22942-1-git-send-email-wang.yi59@zte.com.cn>
9
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
10
---
12
---
11
target/riscv/cpu_helper.c | 12 ++++++++++++
13
tcg/riscv/tcg-target.inc.c | 2 --
12
1 file changed, 12 insertions(+)
14
1 file changed, 2 deletions(-)
13
15
14
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
16
diff --git a/tcg/riscv/tcg-target.inc.c b/tcg/riscv/tcg-target.inc.c
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/target/riscv/cpu_helper.c
18
--- a/tcg/riscv/tcg-target.inc.c
17
+++ b/target/riscv/cpu_helper.c
19
+++ b/tcg/riscv/tcg-target.inc.c
18
@@ -XXX,XX +XXX,XX @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
20
@@ -XXX,XX +XXX,XX @@ static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
19
if (ret == TRANSLATE_SUCCESS) {
21
break;
20
ret = get_physical_address_pmp(env, &prot_pmp, &tlb_size, pa,
22
case R_RISCV_JAL:
21
size, access_type, mode);
23
return reloc_jimm20(code_ptr, (tcg_insn_unit *)value);
22
+
24
- break;
23
+ qemu_log_mask(CPU_LOG_MMU,
25
case R_RISCV_CALL:
24
+ "%s PMP address=" TARGET_FMT_plx " ret %d prot"
26
return reloc_call(code_ptr, (tcg_insn_unit *)value);
25
+ " %d tlb_size " TARGET_FMT_lu "\n",
27
- break;
26
+ __func__, pa, ret, prot_pmp, tlb_size);
28
default:
27
+
29
tcg_abort();
28
prot &= prot_pmp;
29
}
30
31
@@ -XXX,XX +XXX,XX @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
32
if (ret == TRANSLATE_SUCCESS) {
33
ret = get_physical_address_pmp(env, &prot_pmp, &tlb_size, pa,
34
size, access_type, mode);
35
+
36
+ qemu_log_mask(CPU_LOG_MMU,
37
+ "%s PMP address=" TARGET_FMT_plx " ret %d prot"
38
+ " %d tlb_size " TARGET_FMT_lu "\n",
39
+ __func__, pa, ret, prot_pmp, tlb_size);
40
+
41
prot &= prot_pmp;
42
}
43
}
30
}
44
--
31
--
45
2.30.1
32
2.27.0
46
33
47
34
diff view generated by jsdifflib
1
From: Jim Shu <cwshu@andestech.com>
1
From: Alexandre Mergnat <amergnat@baylibre.com>
2
2
3
If PMP permission of any address has been changed by updating PMP entry,
3
The end address calculation for NA4 mode is wrong because the address
4
flush all TLB pages to prevent from getting old permission.
4
used isn't shifted.
5
5
6
Signed-off-by: Jim Shu <cwshu@andestech.com>
6
It doesn't watch 4 bytes but a huge range because the end address
7
calculation is wrong.
8
9
The solution is to use the shifted address calculated for start address
10
variable.
11
12
Modifications are tested on Zephyr OS userspace test suite which works
13
for other RISC-V boards (E31 and E34 core).
14
15
Signed-off-by: Alexandre Mergnat <amergnat@baylibre.com>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
16
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Message-id: 1613916082-19528-4-git-send-email-cwshu@andestech.com
17
Message-id: 20200706084550.24117-1-amergnat@baylibre.com
18
Message-Id: <20200706084550.24117-1-amergnat@baylibre.com>
19
[ Changes by AF:
20
- Improve the commit title and message
21
]
9
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
22
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
10
---
23
---
11
target/riscv/pmp.c | 4 ++++
24
target/riscv/pmp.c | 2 +-
12
1 file changed, 4 insertions(+)
25
1 file changed, 1 insertion(+), 1 deletion(-)
13
26
14
diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c
27
diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c
15
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
16
--- a/target/riscv/pmp.c
29
--- a/target/riscv/pmp.c
17
+++ b/target/riscv/pmp.c
30
+++ b/target/riscv/pmp.c
18
@@ -XXX,XX +XXX,XX @@
31
@@ -XXX,XX +XXX,XX @@ static void pmp_update_rule(CPURISCVState *env, uint32_t pmp_index)
19
#include "qapi/error.h"
32
20
#include "cpu.h"
33
case PMP_AMATCH_NA4:
21
#include "trace.h"
34
sa = this_addr << 2; /* shift up from [xx:0] to [xx+2:2] */
22
+#include "exec/exec-all.h"
35
- ea = (this_addr + 4u) - 1u;
23
36
+ ea = (sa + 4u) - 1u;
24
static void pmp_write_cfg(CPURISCVState *env, uint32_t addr_index,
37
break;
25
uint8_t val);
38
26
@@ -XXX,XX +XXX,XX @@ void pmpcfg_csr_write(CPURISCVState *env, uint32_t reg_index,
39
case PMP_AMATCH_NAPOT:
27
cfg_val = (val >> 8 * i) & 0xff;
28
pmp_write_cfg(env, (reg_index * 4) + i, cfg_val);
29
}
30
+
31
+ /* If PMP permission of any addr has been changed, flush TLB pages. */
32
+ tlb_flush(env_cpu(env));
33
}
34
35
36
--
40
--
37
2.30.1
41
2.27.0
38
42
39
43
diff view generated by jsdifflib
Deleted patch
1
From: Georg Kotheimer <georg.kotheimer@kernkonzept.com>
2
1
3
According to the specification the "field SPVP of hstatus controls the
4
privilege level of the access" for the hypervisor virtual-machine load
5
and store instructions HLV, HLVX and HSV.
6
7
Signed-off-by: Georg Kotheimer <georg.kotheimer@kernkonzept.com>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Message-id: 20210311103005.1400718-1-georg.kotheimer@kernkonzept.com
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
---
12
target/riscv/cpu_helper.c | 25 ++++++++++++++-----------
13
1 file changed, 14 insertions(+), 11 deletions(-)
14
15
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/riscv/cpu_helper.c
18
+++ b/target/riscv/cpu_helper.c
19
@@ -XXX,XX +XXX,XX @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
20
use_background = true;
21
}
22
23
- if (mode == PRV_M && access_type != MMU_INST_FETCH) {
24
+ /* MPRV does not affect the virtual-machine load/store
25
+ instructions, HLV, HLVX, and HSV. */
26
+ if (riscv_cpu_two_stage_lookup(mmu_idx)) {
27
+ mode = get_field(env->hstatus, HSTATUS_SPVP);
28
+ } else if (mode == PRV_M && access_type != MMU_INST_FETCH) {
29
if (get_field(env->mstatus, MSTATUS_MPRV)) {
30
mode = get_field(env->mstatus, MSTATUS_MPP);
31
}
32
@@ -XXX,XX +XXX,XX @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
33
qemu_log_mask(CPU_LOG_MMU, "%s ad %" VADDR_PRIx " rw %d mmu_idx %d\n",
34
__func__, address, access_type, mmu_idx);
35
36
- if (mode == PRV_M && access_type != MMU_INST_FETCH) {
37
- if (get_field(env->mstatus, MSTATUS_MPRV)) {
38
- mode = get_field(env->mstatus, MSTATUS_MPP);
39
+ /* MPRV does not affect the virtual-machine load/store
40
+ instructions, HLV, HLVX, and HSV. */
41
+ if (riscv_cpu_two_stage_lookup(mmu_idx)) {
42
+ mode = get_field(env->hstatus, HSTATUS_SPVP);
43
+ } else if (mode == PRV_M && access_type != MMU_INST_FETCH &&
44
+ get_field(env->mstatus, MSTATUS_MPRV)) {
45
+ mode = get_field(env->mstatus, MSTATUS_MPP);
46
+ if (riscv_has_ext(env, RVH) && get_field(env->mstatus, MSTATUS_MPV)) {
47
+ two_stage_lookup = true;
48
}
49
}
50
51
- if (riscv_has_ext(env, RVH) && env->priv == PRV_M &&
52
- access_type != MMU_INST_FETCH &&
53
- get_field(env->mstatus, MSTATUS_MPRV) &&
54
- get_field(env->mstatus, MSTATUS_MPV)) {
55
- two_stage_lookup = true;
56
- }
57
-
58
if (riscv_cpu_virt_enabled(env) ||
59
((riscv_cpu_two_stage_lookup(mmu_idx) || two_stage_lookup) &&
60
access_type != MMU_INST_FETCH)) {
61
--
62
2.30.1
63
64
diff view generated by jsdifflib