1
The following changes since commit ad10b4badc1dd5b28305f9b9f1168cf0aa3ae946:
1
From: Alistair Francis <alistair.francis@wdc.com>
2
2
3
Merge tag 'pull-error-2024-05-27' of https://repo.or.cz/qemu/armbru into staging (2024-05-27 06:40:42 -0700)
3
The following changes since commit ad38520bdeb2b1e0b487db317f29119e94c1c88d:
4
5
Merge remote-tracking branch 'remotes/stefanha-gitlab/tags/block-pull-request' into staging (2022-02-15 19:30:33 +0000)
4
6
5
are available in the Git repository at:
7
are available in the Git repository at:
6
8
7
https://github.com/alistair23/qemu.git tags/pull-riscv-to-apply-20240528
9
git@github.com:alistair23/qemu.git tags/pull-riscv-to-apply-20220216
8
10
9
for you to fetch changes up to 1806da76cb81088ea026ca3441551782b850e393:
11
for you to fetch changes up to 7035b8420fa52e8c94cf4317c0f88c1b73ced28d:
10
12
11
target/riscv: raise an exception when CSRRS/CSRRC writes a read-only CSR (2024-05-28 12:20:27 +1000)
13
docs/system: riscv: Update description of CPU (2022-02-16 12:25:52 +1000)
12
14
13
----------------------------------------------------------------
15
----------------------------------------------------------------
14
RISC-V PR for 9.1
16
Fourth RISC-V PR for QEMU 7.0
15
17
16
* APLICs add child earlier than realize
18
* Remove old Ibex PLIC header file
17
* Fix exposure of Zkr
19
* Allow writing 8 bytes with generic loader
18
* Raise exceptions on wrs.nto
20
* Fixes for RV128
19
* Implement SBI debug console (DBCN) calls for KVM
21
* Refactor RISC-V CPU configs
20
* Support 64-bit addresses for initrd
22
* Initial support for XVentanaCondOps custom extension
21
* Change RISCV_EXCP_SEMIHOST exception number to 63
23
* Fix for vill field in vtype
22
* Tolerate KVM disable ext errors
24
* Fix trap cause for RV32 HS-mode CSR access from RV64 HS-mode
23
* Set tval in breakpoints
25
* Support for svnapot, svinval and svpbmt extensions
24
* Add support for Zve32x extension
25
* Add support for Zve64x extension
26
* Relax vector register check in RISCV gdbstub
27
* Fix the element agnostic Vector function problem
28
* Fix Zvkb extension config
29
* Implement dynamic establishment of custom decoder
30
* Add th.sxstatus CSR emulation
31
* Fix Zvfhmin checking for vfwcvt.f.f.v and vfncvt.f.f.w instructions
32
* Check single width operator for vector fp widen instructions
33
* Check single width operator for vfncvt.rod.f.f.w
34
* Remove redudant SEW checking for vector fp narrow/widen instructions
35
* Prioritize pmp errors in raise_mmu_exception()
36
* Do not set mtval2 for non guest-page faults
37
* Remove experimental prefix from "B" extension
38
* Fixup CBO extension register calculation
39
* Fix the hart bit setting of AIA
40
* Fix reg_width in ricsv_gen_dynamic_vector_feature()
41
* Decode all of the pmpcfg and pmpaddr CSRs
42
* Raise an exception when CSRRS/CSRRC writes a read-only CSR
43
26
44
----------------------------------------------------------------
27
----------------------------------------------------------------
45
Alexei Filippov (1):
28
Anup Patel (18):
46
target/riscv: do not set mtval2 for non guest-page faults
29
target/riscv: Fix trap cause for RV32 HS-mode CSR access from RV64 HS-mode
30
target/riscv: Implement SGEIP bit in hip and hie CSRs
31
target/riscv: Implement hgeie and hgeip CSRs
32
target/riscv: Improve delivery of guest external interrupts
33
target/riscv: Allow setting CPU feature from machine/device emulation
34
target/riscv: Add AIA cpu feature
35
target/riscv: Add defines for AIA CSRs
36
target/riscv: Allow AIA device emulation to set ireg rmw callback
37
target/riscv: Implement AIA local interrupt priorities
38
target/riscv: Implement AIA CSRs for 64 local interrupts on RV32
39
target/riscv: Implement AIA hvictl and hviprioX CSRs
40
target/riscv: Implement AIA interrupt filtering CSRs
41
target/riscv: Implement AIA mtopi, stopi, and vstopi CSRs
42
target/riscv: Implement AIA xiselect and xireg CSRs
43
target/riscv: Implement AIA IMSIC interface CSRs
44
hw/riscv: virt: Use AIA INTC compatible string when available
45
target/riscv: Allow users to force enable AIA CSRs in HART
46
hw/intc: Add RISC-V AIA APLIC device emulation
47
47
48
Alistair Francis (2):
48
Frédéric Pétrot (1):
49
target/riscv: rvzicbo: Fixup CBO extension register calculation
49
target/riscv: correct "code should not be reached" for x-rv128
50
disas/riscv: Decode all of the pmpcfg and pmpaddr CSRs
51
50
52
Andrew Jones (2):
51
Guo Ren (1):
53
target/riscv/kvm: Fix exposure of Zkr
52
target/riscv: Ignore reserved bits in PTE for RV64
54
target/riscv: Raise exceptions on wrs.nto
55
53
56
Cheng Yang (1):
54
LIU Zhiwei (1):
57
hw/riscv/boot.c: Support 64-bit address for initrd
55
target/riscv: Fix vill field write in vtype
58
56
59
Christoph Müllner (1):
57
Petr Tesarik (1):
60
riscv: thead: Add th.sxstatus CSR emulation
58
Allow setting up to 8 bytes with the generic loader
61
59
62
Clément Léger (1):
60
Philipp Tomsich (7):
63
target/riscv: change RISCV_EXCP_SEMIHOST exception number to 63
61
target/riscv: refactor (anonymous struct) RISCVCPU.cfg into 'struct RISCVCPUConfig'
62
target/riscv: riscv_tr_init_disas_context: copy pointer-to-cfg into cfg_ptr
63
target/riscv: access configuration through cfg_ptr in DisasContext
64
target/riscv: access cfg structure through DisasContext
65
target/riscv: iterate over a table of decoders
66
target/riscv: Add XVentanaCondOps custom extension
67
target/riscv: add a MAINTAINERS entry for XVentanaCondOps
64
68
65
Daniel Henrique Barboza (6):
69
Weiwei Li (4):
66
target/riscv/kvm: implement SBI debug console (DBCN) calls
70
target/riscv: add PTE_A/PTE_D/PTE_U bits check for inner PTE
67
target/riscv/kvm: tolerate KVM disable ext errors
71
target/riscv: add support for svnapot extension
68
target/riscv/debug: set tval=pc in breakpoint exceptions
72
target/riscv: add support for svinval extension
69
trans_privileged.c.inc: set (m|s)tval on ebreak breakpoint
73
target/riscv: add support for svpbmt extension
70
target/riscv: prioritize pmp errors in raise_mmu_exception()
71
riscv, gdbstub.c: fix reg_width in ricsv_gen_dynamic_vector_feature()
72
74
73
Huang Tao (2):
75
Wilfred Mallawa (1):
74
target/riscv: Fix the element agnostic function problem
76
include: hw: remove ibex_plic.h
75
target/riscv: Implement dynamic establishment of custom decoder
76
77
77
Jason Chien (3):
78
Yu Li (1):
78
target/riscv: Add support for Zve32x extension
79
docs/system: riscv: Update description of CPU
79
target/riscv: Add support for Zve64x extension
80
target/riscv: Relax vector register check in RISCV gdbstub
81
80
82
Max Chou (4):
81
docs/system/riscv/virt.rst | 6 +-
83
target/riscv: rvv: Fix Zvfhmin checking for vfwcvt.f.f.v and vfncvt.f.f.w instructions
82
include/hw/intc/ibex_plic.h | 67 -
84
target/riscv: rvv: Check single width operator for vector fp widen instructions
83
include/hw/intc/riscv_aplic.h | 79 ++
85
target/riscv: rvv: Check single width operator for vfncvt.rod.f.f.w
84
target/riscv/cpu.h | 169 ++-
86
target/riscv: rvv: Remove redudant SEW checking for vector fp narrow/widen instructions
85
target/riscv/cpu_bits.h | 129 ++
86
target/riscv/XVentanaCondOps.decode | 25 +
87
target/riscv/insn32.decode | 7 +
88
hw/core/generic-loader.c | 2 +-
89
hw/intc/riscv_aplic.c | 978 +++++++++++++++
90
hw/riscv/virt.c | 13 +-
91
target/riscv/cpu.c | 113 +-
92
target/riscv/cpu_helper.c | 377 +++++-
93
target/riscv/csr.c | 1282 ++++++++++++++++++--
94
target/riscv/gdbstub.c | 3 +
95
target/riscv/machine.c | 24 +-
96
target/riscv/translate.c | 61 +-
97
target/riscv/vector_helper.c | 1 +
98
target/riscv/insn_trans/trans_rvb.c.inc | 8 +-
99
target/riscv/insn_trans/trans_rvi.c.inc | 2 +-
100
target/riscv/insn_trans/trans_rvv.c.inc | 146 ++-
101
target/riscv/insn_trans/trans_rvzfh.c.inc | 4 +-
102
target/riscv/insn_trans/trans_svinval.c.inc | 75 ++
103
.../riscv/insn_trans/trans_xventanacondops.c.inc | 39 +
104
MAINTAINERS | 7 +
105
hw/intc/Kconfig | 3 +
106
hw/intc/meson.build | 1 +
107
target/riscv/meson.build | 1 +
108
27 files changed, 3252 insertions(+), 370 deletions(-)
109
delete mode 100644 include/hw/intc/ibex_plic.h
110
create mode 100644 include/hw/intc/riscv_aplic.h
111
create mode 100644 target/riscv/XVentanaCondOps.decode
112
create mode 100644 hw/intc/riscv_aplic.c
113
create mode 100644 target/riscv/insn_trans/trans_svinval.c.inc
114
create mode 100644 target/riscv/insn_trans/trans_xventanacondops.c.inc
87
115
88
Rob Bradford (1):
89
target/riscv: Remove experimental prefix from "B" extension
90
91
Yangyu Chen (1):
92
target/riscv/cpu.c: fix Zvkb extension config
93
94
Yong-Xuan Wang (1):
95
target/riscv/kvm.c: Fix the hart bit setting of AIA
96
97
Yu-Ming Chang (1):
98
target/riscv: raise an exception when CSRRS/CSRRC writes a read-only CSR
99
100
yang.zhang (1):
101
hw/intc/riscv_aplic: APLICs should add child earlier than realize
102
103
MAINTAINERS | 1 +
104
target/riscv/cpu.h | 11 ++
105
target/riscv/cpu_bits.h | 2 +-
106
target/riscv/cpu_cfg.h | 2 +
107
target/riscv/helper.h | 1 +
108
target/riscv/sbi_ecall_interface.h | 17 +++
109
target/riscv/tcg/tcg-cpu.h | 15 +++
110
disas/riscv.c | 65 +++++++++-
111
hw/intc/riscv_aplic.c | 8 +-
112
hw/riscv/boot.c | 4 +-
113
target/riscv/cpu.c | 10 +-
114
target/riscv/cpu_helper.c | 37 +++---
115
target/riscv/csr.c | 71 +++++++++--
116
target/riscv/debug.c | 3 +
117
target/riscv/gdbstub.c | 8 +-
118
target/riscv/kvm/kvm-cpu.c | 157 ++++++++++++++++++++++++-
119
target/riscv/op_helper.c | 17 ++-
120
target/riscv/tcg/tcg-cpu.c | 50 +++++---
121
target/riscv/th_csr.c | 79 +++++++++++++
122
target/riscv/translate.c | 31 +++--
123
target/riscv/vector_internals.c | 22 ++++
124
target/riscv/insn_trans/trans_privileged.c.inc | 2 +
125
target/riscv/insn_trans/trans_rvv.c.inc | 46 +++++---
126
target/riscv/insn_trans/trans_rvzawrs.c.inc | 29 +++--
127
target/riscv/insn_trans/trans_rvzicbo.c.inc | 16 ++-
128
target/riscv/meson.build | 1 +
129
26 files changed, 596 insertions(+), 109 deletions(-)
130
create mode 100644 target/riscv/th_csr.c
131
diff view generated by jsdifflib
New patch
1
From: Wilfred Mallawa <wilfred.mallawa@wdc.com>
1
2
3
This patch removes the left-over/unused `ibex_plic.h` file. Previously
4
used by opentitan, which now follows the RISC-V standard and uses the
5
SiFivePlicState.
6
7
Fixes: 434e7e021 ("hw/intc: Remove the Ibex PLIC")
8
Signed-off-by: Wilfred Mallawa <wilfred.mallawa@wdc.com>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Message-id: 20220121055005.3159846-1-alistair.francis@opensource.wdc.com
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
13
---
14
include/hw/intc/ibex_plic.h | 67 -------------------------------------
15
1 file changed, 67 deletions(-)
16
delete mode 100644 include/hw/intc/ibex_plic.h
17
18
diff --git a/include/hw/intc/ibex_plic.h b/include/hw/intc/ibex_plic.h
19
deleted file mode 100644
20
index XXXXXXX..XXXXXXX
21
--- a/include/hw/intc/ibex_plic.h
22
+++ /dev/null
23
@@ -XXX,XX +XXX,XX @@
24
-/*
25
- * QEMU RISC-V lowRISC Ibex PLIC
26
- *
27
- * Copyright (c) 2020 Western Digital
28
- *
29
- * This program is free software; you can redistribute it and/or modify it
30
- * under the terms and conditions of the GNU General Public License,
31
- * version 2 or later, as published by the Free Software Foundation.
32
- *
33
- * This program is distributed in the hope it will be useful, but WITHOUT
34
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
35
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
36
- * more details.
37
- *
38
- * You should have received a copy of the GNU General Public License along with
39
- * this program. If not, see <http://www.gnu.org/licenses/>.
40
- */
41
-
42
-#ifndef HW_IBEX_PLIC_H
43
-#define HW_IBEX_PLIC_H
44
-
45
-#include "hw/sysbus.h"
46
-#include "qom/object.h"
47
-
48
-#define TYPE_IBEX_PLIC "ibex-plic"
49
-OBJECT_DECLARE_SIMPLE_TYPE(IbexPlicState, IBEX_PLIC)
50
-
51
-struct IbexPlicState {
52
- /*< private >*/
53
- SysBusDevice parent_obj;
54
-
55
- /*< public >*/
56
- MemoryRegion mmio;
57
-
58
- uint32_t *pending;
59
- uint32_t *hidden_pending;
60
- uint32_t *claimed;
61
- uint32_t *source;
62
- uint32_t *priority;
63
- uint32_t *enable;
64
- uint32_t threshold;
65
- uint32_t claim;
66
-
67
- /* config */
68
- uint32_t num_cpus;
69
- uint32_t num_sources;
70
-
71
- uint32_t pending_base;
72
- uint32_t pending_num;
73
-
74
- uint32_t source_base;
75
- uint32_t source_num;
76
-
77
- uint32_t priority_base;
78
- uint32_t priority_num;
79
-
80
- uint32_t enable_base;
81
- uint32_t enable_num;
82
-
83
- uint32_t threshold_base;
84
-
85
- uint32_t claim_base;
86
-
87
- qemu_irq *external_irqs;
88
-};
89
-
90
-#endif /* HW_IBEX_PLIC_H */
91
--
92
2.34.1
93
94
diff view generated by jsdifflib
New patch
1
From: Petr Tesarik <ptesarik@suse.com>
1
2
3
The documentation for the generic loader says that "the maximum size of
4
the data is 8 bytes". However, attempts to set data-len=8 trigger the
5
following assertion failure:
6
7
../hw/core/generic-loader.c:59: generic_loader_reset: Assertion `s->data_len < sizeof(s->data)' failed.
8
9
The type of s->data is uint64_t (i.e. 8 bytes long), so I believe this
10
assert should use <= instead of <.
11
12
Fixes: e481a1f63c93 ("generic-loader: Add a generic loader")
13
Signed-off-by: Petr Tesarik <ptesarik@suse.com>
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
16
Message-id: 20220120092715.7805-1-ptesarik@suse.com
17
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
18
---
19
hw/core/generic-loader.c | 2 +-
20
1 file changed, 1 insertion(+), 1 deletion(-)
21
22
diff --git a/hw/core/generic-loader.c b/hw/core/generic-loader.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/hw/core/generic-loader.c
25
+++ b/hw/core/generic-loader.c
26
@@ -XXX,XX +XXX,XX @@ static void generic_loader_reset(void *opaque)
27
}
28
29
if (s->data_len) {
30
- assert(s->data_len < sizeof(s->data));
31
+ assert(s->data_len <= sizeof(s->data));
32
dma_memory_write(s->cpu->as, s->addr, &s->data, s->data_len,
33
MEMTXATTRS_UNSPECIFIED);
34
}
35
--
36
2.34.1
37
38
diff view generated by jsdifflib
1
From: Jason Chien <jason.chien@sifive.com>
1
From: Frédéric Pétrot <frederic.petrot@univ-grenoble-alpes.fr>
2
2
3
In current implementation, the gdbstub allows reading vector registers
3
The addition of uxl support in gdbstub adds a few checks on the maximum
4
only if V extension is supported. However, all vector extensions and
4
register length, but omitted MXL_RV128, an experimental feature.
5
vector crypto extensions have the vector registers and they all depend
5
This patch makes rv128 react as rv64, as previously.
6
on Zve32x. The gdbstub should check for Zve32x instead.
7
6
8
Signed-off-by: Jason Chien <jason.chien@sifive.com>
7
Signed-off-by: Frédéric Pétrot <frederic.petrot@univ-grenoble-alpes.fr>
9
Reviewed-by: Frank Chang <frank.chang@sifive.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Reviewed-by: Max Chou <max.chou@sifive.com>
9
Reviewed-by: LIU Zhiwei <zhiwei_liu@c-sky.com>
11
Message-ID: <20240328022343.6871-4-jason.chien@sifive.com>
10
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
11
Message-id: 20220124202456.420258-1-frederic.petrot@univ-grenoble-alpes.fr
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
13
---
13
---
14
target/riscv/gdbstub.c | 2 +-
14
target/riscv/cpu.c | 3 +--
15
1 file changed, 1 insertion(+), 1 deletion(-)
15
target/riscv/gdbstub.c | 3 +++
16
2 files changed, 4 insertions(+), 2 deletions(-)
16
17
18
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/riscv/cpu.c
21
+++ b/target/riscv/cpu.c
22
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
23
switch (env->misa_mxl_max) {
24
#ifdef TARGET_RISCV64
25
case MXL_RV64:
26
- cc->gdb_core_xml_file = "riscv-64bit-cpu.xml";
27
- break;
28
case MXL_RV128:
29
+ cc->gdb_core_xml_file = "riscv-64bit-cpu.xml";
30
break;
31
#endif
32
case MXL_RV32:
17
diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
33
diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
18
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
19
--- a/target/riscv/gdbstub.c
35
--- a/target/riscv/gdbstub.c
20
+++ b/target/riscv/gdbstub.c
36
+++ b/target/riscv/gdbstub.c
37
@@ -XXX,XX +XXX,XX @@ int riscv_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
38
case MXL_RV32:
39
return gdb_get_reg32(mem_buf, tmp);
40
case MXL_RV64:
41
+ case MXL_RV128:
42
return gdb_get_reg64(mem_buf, tmp);
43
default:
44
g_assert_not_reached();
45
@@ -XXX,XX +XXX,XX @@ int riscv_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
46
length = 4;
47
break;
48
case MXL_RV64:
49
+ case MXL_RV128:
50
if (env->xl < MXL_RV64) {
51
tmp = (int32_t)ldq_p(mem_buf);
52
} else {
21
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
53
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
22
gdb_find_static_feature("riscv-32bit-fpu.xml"),
54
1, "riscv-32bit-virtual.xml", 0);
23
0);
55
break;
24
}
56
case MXL_RV64:
25
- if (env->misa_ext & RVV) {
57
+ case MXL_RV128:
26
+ if (cpu->cfg.ext_zve32x) {
58
gdb_register_coprocessor(cs, riscv_gdb_get_virtual,
27
gdb_register_coprocessor(cs, riscv_gdb_get_vector,
59
riscv_gdb_set_virtual,
28
riscv_gdb_set_vector,
60
1, "riscv-64bit-virtual.xml", 0);
29
ricsv_gen_dynamic_vector_feature(cs, cs->gdb_num_regs),
30
--
61
--
31
2.45.1
62
2.34.1
63
64
diff view generated by jsdifflib
New patch
1
From: Philipp Tomsich <philipp.tomsich@vrull.eu>
1
2
3
Signed-off-by: Philipp Tomsich <philipp.tomsich@vrull.eu>
4
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
5
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-Id: <20220202005249.3566542-2-philipp.tomsich@vrull.eu>
8
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
9
---
10
target/riscv/cpu.h | 78 ++++++++++++++++++++++++----------------------
11
1 file changed, 41 insertions(+), 37 deletions(-)
12
13
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/riscv/cpu.h
16
+++ b/target/riscv/cpu.h
17
@@ -XXX,XX +XXX,XX @@ struct RISCVCPUClass {
18
DeviceReset parent_reset;
19
};
20
21
+struct RISCVCPUConfig {
22
+ bool ext_i;
23
+ bool ext_e;
24
+ bool ext_g;
25
+ bool ext_m;
26
+ bool ext_a;
27
+ bool ext_f;
28
+ bool ext_d;
29
+ bool ext_c;
30
+ bool ext_s;
31
+ bool ext_u;
32
+ bool ext_h;
33
+ bool ext_j;
34
+ bool ext_v;
35
+ bool ext_zba;
36
+ bool ext_zbb;
37
+ bool ext_zbc;
38
+ bool ext_zbs;
39
+ bool ext_counters;
40
+ bool ext_ifencei;
41
+ bool ext_icsr;
42
+ bool ext_zfh;
43
+ bool ext_zfhmin;
44
+ bool ext_zve32f;
45
+ bool ext_zve64f;
46
+
47
+ char *priv_spec;
48
+ char *user_spec;
49
+ char *bext_spec;
50
+ char *vext_spec;
51
+ uint16_t vlen;
52
+ uint16_t elen;
53
+ bool mmu;
54
+ bool pmp;
55
+ bool epmp;
56
+ uint64_t resetvec;
57
+};
58
+
59
+typedef struct RISCVCPUConfig RISCVCPUConfig;
60
+
61
/**
62
* RISCVCPU:
63
* @env: #CPURISCVState
64
@@ -XXX,XX +XXX,XX @@ struct RISCVCPU {
65
char *dyn_vreg_xml;
66
67
/* Configuration Settings */
68
- struct {
69
- bool ext_i;
70
- bool ext_e;
71
- bool ext_g;
72
- bool ext_m;
73
- bool ext_a;
74
- bool ext_f;
75
- bool ext_d;
76
- bool ext_c;
77
- bool ext_s;
78
- bool ext_u;
79
- bool ext_h;
80
- bool ext_j;
81
- bool ext_v;
82
- bool ext_zba;
83
- bool ext_zbb;
84
- bool ext_zbc;
85
- bool ext_zbs;
86
- bool ext_counters;
87
- bool ext_ifencei;
88
- bool ext_icsr;
89
- bool ext_zfh;
90
- bool ext_zfhmin;
91
- bool ext_zve32f;
92
- bool ext_zve64f;
93
-
94
- char *priv_spec;
95
- char *user_spec;
96
- char *bext_spec;
97
- char *vext_spec;
98
- uint16_t vlen;
99
- uint16_t elen;
100
- bool mmu;
101
- bool pmp;
102
- bool epmp;
103
- uint64_t resetvec;
104
- } cfg;
105
+ RISCVCPUConfig cfg;
106
};
107
108
static inline int riscv_has_ext(CPURISCVState *env, target_ulong ext)
109
--
110
2.34.1
111
112
diff view generated by jsdifflib
1
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
1
From: Philipp Tomsich <philipp.tomsich@vrull.eu>
2
2
3
Privileged spec section 4.1.9 mentions:
3
As the number of extensions is growing, copying them individiually
4
into the DisasContext will scale less and less... instead we populate
5
a pointer to the RISCVCPUConfig structure in the DisasContext.
4
6
5
"When a trap is taken into S-mode, stval is written with
7
This adds an extra indirection when checking for the availability of
6
exception-specific information to assist software in handling the trap.
8
an extension (compared to copying the fields into DisasContext).
7
(...)
9
While not a performance problem today, we can always (shallow) copy
10
the entire structure into the DisasContext (instead of putting a
11
pointer to it) if this is ever deemed necessary.
8
12
9
If stval is written with a nonzero value when a breakpoint,
13
Signed-off-by: Philipp Tomsich <philipp.tomsich@vrull.eu>
10
address-misaligned, access-fault, or page-fault exception occurs on an
11
instruction fetch, load, or store, then stval will contain the faulting
12
virtual address."
13
14
A similar text is found for mtval in section 3.1.16.
15
16
Setting mtval/stval in this scenario is optional, but some softwares read
17
these regs when handling ebreaks.
18
19
Write 'badaddr' in all ebreak breakpoints to write the appropriate
20
'tval' during riscv_do_cpu_interrrupt().
21
22
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
23
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
14
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
24
Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
15
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
25
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
26
Message-ID: <20240416230437.1869024-3-dbarboza@ventanamicro.com>
17
Message-Id: <20220202005249.3566542-3-philipp.tomsich@vrull.eu>
27
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
18
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
28
---
19
---
29
target/riscv/insn_trans/trans_privileged.c.inc | 2 ++
20
target/riscv/translate.c | 2 ++
30
1 file changed, 2 insertions(+)
21
1 file changed, 2 insertions(+)
31
22
32
diff --git a/target/riscv/insn_trans/trans_privileged.c.inc b/target/riscv/insn_trans/trans_privileged.c.inc
23
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
33
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
34
--- a/target/riscv/insn_trans/trans_privileged.c.inc
25
--- a/target/riscv/translate.c
35
+++ b/target/riscv/insn_trans/trans_privileged.c.inc
26
+++ b/target/riscv/translate.c
36
@@ -XXX,XX +XXX,XX @@ static bool trans_ebreak(DisasContext *ctx, arg_ebreak *a)
27
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
37
if (pre == 0x01f01013 && ebreak == 0x00100073 && post == 0x40705013) {
28
int frm;
38
generate_exception(ctx, RISCV_EXCP_SEMIHOST);
29
RISCVMXL ol;
39
} else {
30
bool virt_enabled;
40
+ tcg_gen_st_tl(tcg_constant_tl(ebreak_addr), tcg_env,
31
+ const RISCVCPUConfig *cfg_ptr;
41
+ offsetof(CPURISCVState, badaddr));
32
bool ext_ifencei;
42
generate_exception(ctx, RISCV_EXCP_BREAKPOINT);
33
bool ext_zfh;
43
}
34
bool ext_zfhmin;
44
return true;
35
@@ -XXX,XX +XXX,XX @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
36
#endif
37
ctx->misa_ext = env->misa_ext;
38
ctx->frm = -1; /* unknown rounding mode */
39
+ ctx->cfg_ptr = &(cpu->cfg);
40
ctx->ext_ifencei = cpu->cfg.ext_ifencei;
41
ctx->ext_zfh = cpu->cfg.ext_zfh;
42
ctx->ext_zfhmin = cpu->cfg.ext_zfhmin;
45
--
43
--
46
2.45.1
44
2.34.1
45
46
diff view generated by jsdifflib
1
From: Max Chou <max.chou@sifive.com>
1
From: Philipp Tomsich <philipp.tomsich@vrull.eu>
2
2
3
The require_scale_rvf function only checks the double width operator for
3
The implementation in trans_{rvi,rvv,rvzfh}.c.inc accesses the shallow
4
the vector floating point widen instructions, so most of the widen
4
copies (in DisasContext) of some of the elements available in the
5
checking functions need to add require_rvf for single width operator.
5
RISCVCPUConfig structure. This commit redirects accesses to use the
6
cfg_ptr copied into DisasContext and removes the shallow copies.
6
7
7
The vfwcvt.f.x.v and vfwcvt.f.xu.v instructions convert single width
8
Signed-off-by: Philipp Tomsich <philipp.tomsich@vrull.eu>
8
integer to double width float, so the opfxv_widen_check function doesn’t
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
need require_rvf for the single width operator(integer).
10
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
10
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Signed-off-by: Max Chou <max.chou@sifive.com>
12
Message-Id: <20220202005249.3566542-4-philipp.tomsich@vrull.eu>
12
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
13
[ Changes by AF:
13
Cc: qemu-stable <qemu-stable@nongnu.org>
14
- Fixup checkpatch failures
14
Message-ID: <20240322092600.1198921-3-max.chou@sifive.com>
15
]
15
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
16
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
16
---
17
---
17
target/riscv/insn_trans/trans_rvv.c.inc | 5 +++++
18
target/riscv/translate.c | 14 ---
18
1 file changed, 5 insertions(+)
19
target/riscv/insn_trans/trans_rvi.c.inc | 2 +-
20
target/riscv/insn_trans/trans_rvv.c.inc | 146 ++++++++++++++--------
21
target/riscv/insn_trans/trans_rvzfh.c.inc | 4 +-
22
4 files changed, 97 insertions(+), 69 deletions(-)
19
23
24
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
25
index XXXXXXX..XXXXXXX 100644
26
--- a/target/riscv/translate.c
27
+++ b/target/riscv/translate.c
28
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
29
RISCVMXL ol;
30
bool virt_enabled;
31
const RISCVCPUConfig *cfg_ptr;
32
- bool ext_ifencei;
33
- bool ext_zfh;
34
- bool ext_zfhmin;
35
- bool ext_zve32f;
36
- bool ext_zve64f;
37
bool hlsx;
38
/* vector extension */
39
bool vill;
40
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
41
*/
42
int8_t lmul;
43
uint8_t sew;
44
- uint16_t vlen;
45
- uint16_t elen;
46
target_ulong vstart;
47
bool vl_eq_vlmax;
48
uint8_t ntemp;
49
@@ -XXX,XX +XXX,XX @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
50
ctx->misa_ext = env->misa_ext;
51
ctx->frm = -1; /* unknown rounding mode */
52
ctx->cfg_ptr = &(cpu->cfg);
53
- ctx->ext_ifencei = cpu->cfg.ext_ifencei;
54
- ctx->ext_zfh = cpu->cfg.ext_zfh;
55
- ctx->ext_zfhmin = cpu->cfg.ext_zfhmin;
56
- ctx->ext_zve32f = cpu->cfg.ext_zve32f;
57
- ctx->ext_zve64f = cpu->cfg.ext_zve64f;
58
- ctx->vlen = cpu->cfg.vlen;
59
- ctx->elen = cpu->cfg.elen;
60
ctx->mstatus_hs_fs = FIELD_EX32(tb_flags, TB_FLAGS, MSTATUS_HS_FS);
61
ctx->mstatus_hs_vs = FIELD_EX32(tb_flags, TB_FLAGS, MSTATUS_HS_VS);
62
ctx->hlsx = FIELD_EX32(tb_flags, TB_FLAGS, HLSX);
63
diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc
64
index XXXXXXX..XXXXXXX 100644
65
--- a/target/riscv/insn_trans/trans_rvi.c.inc
66
+++ b/target/riscv/insn_trans/trans_rvi.c.inc
67
@@ -XXX,XX +XXX,XX @@ static bool trans_fence(DisasContext *ctx, arg_fence *a)
68
69
static bool trans_fence_i(DisasContext *ctx, arg_fence_i *a)
70
{
71
- if (!ctx->ext_ifencei) {
72
+ if (!ctx->cfg_ptr->ext_ifencei) {
73
return false;
74
}
75
20
diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc
76
diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc
21
index XXXXXXX..XXXXXXX 100644
77
index XXXXXXX..XXXXXXX 100644
22
--- a/target/riscv/insn_trans/trans_rvv.c.inc
78
--- a/target/riscv/insn_trans/trans_rvv.c.inc
23
+++ b/target/riscv/insn_trans/trans_rvv.c.inc
79
+++ b/target/riscv/insn_trans/trans_rvv.c.inc
24
@@ -XXX,XX +XXX,XX @@ GEN_OPFVF_TRANS(vfrsub_vf, opfvf_check)
80
@@ -XXX,XX +XXX,XX @@ static bool require_zve32f(DisasContext *s)
25
static bool opfvv_widen_check(DisasContext *s, arg_rmrr *a)
81
}
82
83
/* Zve32f doesn't support FP64. (Section 18.2) */
84
- return s->ext_zve32f ? s->sew <= MO_32 : true;
85
+ return s->cfg_ptr->ext_zve32f ? s->sew <= MO_32 : true;
86
}
87
88
static bool require_scale_zve32f(DisasContext *s)
89
@@ -XXX,XX +XXX,XX @@ static bool require_scale_zve32f(DisasContext *s)
90
}
91
92
/* Zve32f doesn't support FP64. (Section 18.2) */
93
- return s->ext_zve64f ? s->sew <= MO_16 : true;
94
+ return s->cfg_ptr->ext_zve64f ? s->sew <= MO_16 : true;
95
}
96
97
static bool require_zve64f(DisasContext *s)
98
@@ -XXX,XX +XXX,XX @@ static bool require_zve64f(DisasContext *s)
99
}
100
101
/* Zve64f doesn't support FP64. (Section 18.2) */
102
- return s->ext_zve64f ? s->sew <= MO_32 : true;
103
+ return s->cfg_ptr->ext_zve64f ? s->sew <= MO_32 : true;
104
}
105
106
static bool require_scale_zve64f(DisasContext *s)
107
@@ -XXX,XX +XXX,XX @@ static bool require_scale_zve64f(DisasContext *s)
108
}
109
110
/* Zve64f doesn't support FP64. (Section 18.2) */
111
- return s->ext_zve64f ? s->sew <= MO_16 : true;
112
+ return s->cfg_ptr->ext_zve64f ? s->sew <= MO_16 : true;
113
}
114
115
/* Destination vector register group cannot overlap source mask register. */
116
@@ -XXX,XX +XXX,XX @@ static bool do_vsetvl(DisasContext *s, int rd, int rs1, TCGv s2)
117
TCGv s1, dst;
118
119
if (!require_rvv(s) ||
120
- !(has_ext(s, RVV) || s->ext_zve32f || s->ext_zve64f)) {
121
+ !(has_ext(s, RVV) || s->cfg_ptr->ext_zve32f ||
122
+ s->cfg_ptr->ext_zve64f)) {
123
return false;
124
}
125
126
@@ -XXX,XX +XXX,XX @@ static bool do_vsetivli(DisasContext *s, int rd, TCGv s1, TCGv s2)
127
TCGv dst;
128
129
if (!require_rvv(s) ||
130
- !(has_ext(s, RVV) || s->ext_zve32f || s->ext_zve64f)) {
131
+ !(has_ext(s, RVV) || s->cfg_ptr->ext_zve32f ||
132
+ s->cfg_ptr->ext_zve64f)) {
133
return false;
134
}
135
136
@@ -XXX,XX +XXX,XX @@ static bool trans_vsetivli(DisasContext *s, arg_vsetivli *a)
137
/* vector register offset from env */
138
static uint32_t vreg_ofs(DisasContext *s, int reg)
26
{
139
{
27
return require_rvv(s) &&
140
- return offsetof(CPURISCVState, vreg) + reg * s->vlen / 8;
28
+ require_rvf(s) &&
141
+ return offsetof(CPURISCVState, vreg) + reg * s->cfg_ptr->vlen / 8;
29
require_scale_rvf(s) &&
142
}
30
(s->sew != MO_8) &&
143
31
vext_check_isa_ill(s) &&
144
/* check functions */
32
@@ -XXX,XX +XXX,XX @@ GEN_OPFVV_WIDEN_TRANS(vfwsub_vv, opfvv_widen_check)
145
@@ -XXX,XX +XXX,XX @@ static bool vext_check_st_index(DisasContext *s, int vd, int vs2, int nf,
33
static bool opfvf_widen_check(DisasContext *s, arg_rmrr *a)
146
* when XLEN=32. (Section 18.2)
147
*/
148
if (get_xl(s) == MXL_RV32) {
149
- ret &= (!has_ext(s, RVV) && s->ext_zve64f ? eew != MO_64 : true);
150
+ ret &= (!has_ext(s, RVV) &&
151
+ s->cfg_ptr->ext_zve64f ? eew != MO_64 : true);
152
}
153
154
return ret;
155
@@ -XXX,XX +XXX,XX @@ static bool vext_wide_check_common(DisasContext *s, int vd, int vm)
34
{
156
{
35
return require_rvv(s) &&
157
return (s->lmul <= 2) &&
36
+ require_rvf(s) &&
158
(s->sew < MO_64) &&
37
require_scale_rvf(s) &&
159
- ((s->sew + 1) <= (s->elen >> 4)) &&
38
(s->sew != MO_8) &&
160
+ ((s->sew + 1) <= (s->cfg_ptr->elen >> 4)) &&
39
vext_check_isa_ill(s) &&
161
require_align(vd, s->lmul + 1) &&
40
@@ -XXX,XX +XXX,XX @@ GEN_OPFVF_WIDEN_TRANS(vfwsub_vf)
162
require_vm(vm, vd);
41
static bool opfwv_widen_check(DisasContext *s, arg_rmrr *a)
163
}
164
@@ -XXX,XX +XXX,XX @@ static bool vext_narrow_check_common(DisasContext *s, int vd, int vs2,
42
{
165
{
43
return require_rvv(s) &&
166
return (s->lmul <= 2) &&
44
+ require_rvf(s) &&
167
(s->sew < MO_64) &&
45
require_scale_rvf(s) &&
168
- ((s->sew + 1) <= (s->elen >> 4)) &&
46
(s->sew != MO_8) &&
169
+ ((s->sew + 1) <= (s->cfg_ptr->elen >> 4)) &&
47
vext_check_isa_ill(s) &&
170
require_align(vs2, s->lmul + 1) &&
48
@@ -XXX,XX +XXX,XX @@ GEN_OPFWV_WIDEN_TRANS(vfwsub_wv)
171
require_align(vd, s->lmul) &&
49
static bool opfwf_widen_check(DisasContext *s, arg_rmrr *a)
172
require_vm(vm, vd);
173
@@ -XXX,XX +XXX,XX @@ static bool ldst_us_trans(uint32_t vd, uint32_t rs1, uint32_t data,
174
* The first part is vlen in bytes, encoded in maxsz of simd_desc.
175
* The second part is lmul, encoded in data of simd_desc.
176
*/
177
- desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data));
178
+ desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlen / 8,
179
+ s->cfg_ptr->vlen / 8, data));
180
181
tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd));
182
tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0));
183
@@ -XXX,XX +XXX,XX @@ static bool ldst_stride_trans(uint32_t vd, uint32_t rs1, uint32_t rs2,
184
mask = tcg_temp_new_ptr();
185
base = get_gpr(s, rs1, EXT_NONE);
186
stride = get_gpr(s, rs2, EXT_NONE);
187
- desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data));
188
+ desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlen / 8,
189
+ s->cfg_ptr->vlen / 8, data));
190
191
tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd));
192
tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0));
193
@@ -XXX,XX +XXX,XX @@ static bool ldst_index_trans(uint32_t vd, uint32_t rs1, uint32_t vs2,
194
mask = tcg_temp_new_ptr();
195
index = tcg_temp_new_ptr();
196
base = get_gpr(s, rs1, EXT_NONE);
197
- desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data));
198
+ desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlen / 8,
199
+ s->cfg_ptr->vlen / 8, data));
200
201
tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd));
202
tcg_gen_addi_ptr(index, cpu_env, vreg_ofs(s, vs2));
203
@@ -XXX,XX +XXX,XX @@ static bool ldff_trans(uint32_t vd, uint32_t rs1, uint32_t data,
204
dest = tcg_temp_new_ptr();
205
mask = tcg_temp_new_ptr();
206
base = get_gpr(s, rs1, EXT_NONE);
207
- desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data));
208
+ desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlen / 8,
209
+ s->cfg_ptr->vlen / 8, data));
210
211
tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd));
212
tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0));
213
@@ -XXX,XX +XXX,XX @@ static bool ldst_whole_trans(uint32_t vd, uint32_t rs1, uint32_t nf,
214
215
uint32_t data = FIELD_DP32(0, VDATA, NF, nf);
216
dest = tcg_temp_new_ptr();
217
- desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data));
218
+ desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlen / 8,
219
+ s->cfg_ptr->vlen / 8, data));
220
221
base = get_gpr(s, rs1, EXT_NONE);
222
tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd));
223
@@ -XXX,XX +XXX,XX @@ GEN_LDST_WHOLE_TRANS(vs8r_v, 8, true)
224
static inline uint32_t MAXSZ(DisasContext *s)
50
{
225
{
51
return require_rvv(s) &&
226
int scale = s->lmul - 3;
52
+ require_rvf(s) &&
227
- return scale < 0 ? s->vlen >> -scale : s->vlen << scale;
53
require_scale_rvf(s) &&
228
+ return scale < 0 ? s->cfg_ptr->vlen >> -scale : s->cfg_ptr->vlen << scale;
54
(s->sew != MO_8) &&
229
}
55
vext_check_isa_ill(s) &&
230
56
@@ -XXX,XX +XXX,XX @@ GEN_OPFVV_TRANS(vfredmin_vs, freduction_check)
231
static bool opivv_check(DisasContext *s, arg_rmrr *a)
57
static bool freduction_widen_check(DisasContext *s, arg_rmrr *a)
232
@@ -XXX,XX +XXX,XX @@ do_opivv_gvec(DisasContext *s, arg_rmrr *a, GVecGen3Fn *gvec_fn,
233
data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
234
tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
235
vreg_ofs(s, a->rs1), vreg_ofs(s, a->rs2),
236
- cpu_env, s->vlen / 8, s->vlen / 8, data, fn);
237
+ cpu_env, s->cfg_ptr->vlen / 8,
238
+ s->cfg_ptr->vlen / 8, data, fn);
239
}
240
mark_vs_dirty(s);
241
gen_set_label(over);
242
@@ -XXX,XX +XXX,XX @@ static bool opivx_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, uint32_t vm,
243
244
data = FIELD_DP32(data, VDATA, VM, vm);
245
data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
246
- desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data));
247
+ desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlen / 8,
248
+ s->cfg_ptr->vlen / 8, data));
249
250
tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd));
251
tcg_gen_addi_ptr(src2, cpu_env, vreg_ofs(s, vs2));
252
@@ -XXX,XX +XXX,XX @@ static bool opivi_trans(uint32_t vd, uint32_t imm, uint32_t vs2, uint32_t vm,
253
254
data = FIELD_DP32(data, VDATA, VM, vm);
255
data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
256
- desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data));
257
+ desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlen / 8,
258
+ s->cfg_ptr->vlen / 8, data));
259
260
tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd));
261
tcg_gen_addi_ptr(src2, cpu_env, vreg_ofs(s, vs2));
262
@@ -XXX,XX +XXX,XX @@ static bool do_opivv_widen(DisasContext *s, arg_rmrr *a,
263
tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
264
vreg_ofs(s, a->rs1),
265
vreg_ofs(s, a->rs2),
266
- cpu_env, s->vlen / 8, s->vlen / 8,
267
+ cpu_env, s->cfg_ptr->vlen / 8,
268
+ s->cfg_ptr->vlen / 8,
269
data, fn);
270
mark_vs_dirty(s);
271
gen_set_label(over);
272
@@ -XXX,XX +XXX,XX @@ static bool do_opiwv_widen(DisasContext *s, arg_rmrr *a,
273
tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
274
vreg_ofs(s, a->rs1),
275
vreg_ofs(s, a->rs2),
276
- cpu_env, s->vlen / 8, s->vlen / 8, data, fn);
277
+ cpu_env, s->cfg_ptr->vlen / 8,
278
+ s->cfg_ptr->vlen / 8, data, fn);
279
mark_vs_dirty(s);
280
gen_set_label(over);
281
return true;
282
@@ -XXX,XX +XXX,XX @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
283
tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \
284
vreg_ofs(s, a->rs1), \
285
vreg_ofs(s, a->rs2), cpu_env, \
286
- s->vlen / 8, s->vlen / 8, data, \
287
+ s->cfg_ptr->vlen / 8, \
288
+ s->cfg_ptr->vlen / 8, data, \
289
fns[s->sew]); \
290
mark_vs_dirty(s); \
291
gen_set_label(over); \
292
@@ -XXX,XX +XXX,XX @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
293
tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \
294
vreg_ofs(s, a->rs1), \
295
vreg_ofs(s, a->rs2), cpu_env, \
296
- s->vlen / 8, s->vlen / 8, data, \
297
+ s->cfg_ptr->vlen / 8, \
298
+ s->cfg_ptr->vlen / 8, data, \
299
fns[s->sew]); \
300
mark_vs_dirty(s); \
301
gen_set_label(over); \
302
@@ -XXX,XX +XXX,XX @@ static bool vmulh_vv_check(DisasContext *s, arg_rmrr *a)
303
* are not included for EEW=64 in Zve64*. (Section 18.2)
304
*/
305
return opivv_check(s, a) &&
306
- (!has_ext(s, RVV) && s->ext_zve64f ? s->sew != MO_64 : true);
307
+ (!has_ext(s, RVV) &&
308
+ s->cfg_ptr->ext_zve64f ? s->sew != MO_64 : true);
309
}
310
311
static bool vmulh_vx_check(DisasContext *s, arg_rmrr *a)
312
@@ -XXX,XX +XXX,XX @@ static bool vmulh_vx_check(DisasContext *s, arg_rmrr *a)
313
* are not included for EEW=64 in Zve64*. (Section 18.2)
314
*/
315
return opivx_check(s, a) &&
316
- (!has_ext(s, RVV) && s->ext_zve64f ? s->sew != MO_64 : true);
317
+ (!has_ext(s, RVV) &&
318
+ s->cfg_ptr->ext_zve64f ? s->sew != MO_64 : true);
319
}
320
321
GEN_OPIVV_GVEC_TRANS(vmul_vv, mul)
322
@@ -XXX,XX +XXX,XX @@ static bool trans_vmv_v_v(DisasContext *s, arg_vmv_v_v *a)
323
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
324
325
tcg_gen_gvec_2_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, a->rs1),
326
- cpu_env, s->vlen / 8, s->vlen / 8, data,
327
+ cpu_env, s->cfg_ptr->vlen / 8,
328
+ s->cfg_ptr->vlen / 8, data,
329
fns[s->sew]);
330
gen_set_label(over);
331
}
332
@@ -XXX,XX +XXX,XX @@ static bool trans_vmv_v_x(DisasContext *s, arg_vmv_v_x *a)
333
};
334
335
tcg_gen_ext_tl_i64(s1_i64, s1);
336
- desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data));
337
+ desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlen / 8,
338
+ s->cfg_ptr->vlen / 8, data));
339
tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, a->rd));
340
fns[s->sew](dest, s1_i64, cpu_env, desc);
341
342
@@ -XXX,XX +XXX,XX @@ static bool trans_vmv_v_i(DisasContext *s, arg_vmv_v_i *a)
343
344
s1 = tcg_constant_i64(simm);
345
dest = tcg_temp_new_ptr();
346
- desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data));
347
+ desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlen / 8,
348
+ s->cfg_ptr->vlen / 8, data));
349
tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, a->rd));
350
fns[s->sew](dest, s1, cpu_env, desc);
351
352
@@ -XXX,XX +XXX,XX @@ static bool vsmul_vv_check(DisasContext *s, arg_rmrr *a)
353
* for EEW=64 in Zve64*. (Section 18.2)
354
*/
355
return opivv_check(s, a) &&
356
- (!has_ext(s, RVV) && s->ext_zve64f ? s->sew != MO_64 : true);
357
+ (!has_ext(s, RVV) &&
358
+ s->cfg_ptr->ext_zve64f ? s->sew != MO_64 : true);
359
}
360
361
static bool vsmul_vx_check(DisasContext *s, arg_rmrr *a)
362
@@ -XXX,XX +XXX,XX @@ static bool vsmul_vx_check(DisasContext *s, arg_rmrr *a)
363
* for EEW=64 in Zve64*. (Section 18.2)
364
*/
365
return opivx_check(s, a) &&
366
- (!has_ext(s, RVV) && s->ext_zve64f ? s->sew != MO_64 : true);
367
+ (!has_ext(s, RVV) &&
368
+ s->cfg_ptr->ext_zve64f ? s->sew != MO_64 : true);
369
}
370
371
GEN_OPIVV_TRANS(vsmul_vv, vsmul_vv_check)
372
@@ -XXX,XX +XXX,XX @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
373
tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \
374
vreg_ofs(s, a->rs1), \
375
vreg_ofs(s, a->rs2), cpu_env, \
376
- s->vlen / 8, s->vlen / 8, data, \
377
+ s->cfg_ptr->vlen / 8, \
378
+ s->cfg_ptr->vlen / 8, data, \
379
fns[s->sew - 1]); \
380
mark_vs_dirty(s); \
381
gen_set_label(over); \
382
@@ -XXX,XX +XXX,XX @@ static bool opfvf_trans(uint32_t vd, uint32_t rs1, uint32_t vs2,
383
dest = tcg_temp_new_ptr();
384
mask = tcg_temp_new_ptr();
385
src2 = tcg_temp_new_ptr();
386
- desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data));
387
+ desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlen / 8,
388
+ s->cfg_ptr->vlen / 8, data));
389
390
tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd));
391
tcg_gen_addi_ptr(src2, cpu_env, vreg_ofs(s, vs2));
392
@@ -XXX,XX +XXX,XX @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
393
tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \
394
vreg_ofs(s, a->rs1), \
395
vreg_ofs(s, a->rs2), cpu_env, \
396
- s->vlen / 8, s->vlen / 8, data, \
397
+ s->cfg_ptr->vlen / 8, \
398
+ s->cfg_ptr->vlen / 8, data, \
399
fns[s->sew - 1]); \
400
mark_vs_dirty(s); \
401
gen_set_label(over); \
402
@@ -XXX,XX +XXX,XX @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
403
tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \
404
vreg_ofs(s, a->rs1), \
405
vreg_ofs(s, a->rs2), cpu_env, \
406
- s->vlen / 8, s->vlen / 8, data, \
407
+ s->cfg_ptr->vlen / 8, \
408
+ s->cfg_ptr->vlen / 8, data, \
409
fns[s->sew - 1]); \
410
mark_vs_dirty(s); \
411
gen_set_label(over); \
412
@@ -XXX,XX +XXX,XX @@ static bool do_opfv(DisasContext *s, arg_rmr *a,
413
data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
414
tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
415
vreg_ofs(s, a->rs2), cpu_env,
416
- s->vlen / 8, s->vlen / 8, data, fn);
417
+ s->cfg_ptr->vlen / 8,
418
+ s->cfg_ptr->vlen / 8, data, fn);
419
mark_vs_dirty(s);
420
gen_set_label(over);
421
return true;
422
@@ -XXX,XX +XXX,XX @@ static bool trans_vfmv_v_f(DisasContext *s, arg_vfmv_v_f *a)
423
do_nanbox(s, t1, cpu_fpr[a->rs1]);
424
425
dest = tcg_temp_new_ptr();
426
- desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data));
427
+ desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlen / 8,
428
+ s->cfg_ptr->vlen / 8, data));
429
tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, a->rd));
430
431
fns[s->sew - 1](dest, t1, cpu_env, desc);
432
@@ -XXX,XX +XXX,XX @@ static bool trans_##NAME(DisasContext *s, arg_rmr *a) \
433
data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \
434
tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \
435
vreg_ofs(s, a->rs2), cpu_env, \
436
- s->vlen / 8, s->vlen / 8, data, \
437
+ s->cfg_ptr->vlen / 8, \
438
+ s->cfg_ptr->vlen / 8, data, \
439
fns[s->sew - 1]); \
440
mark_vs_dirty(s); \
441
gen_set_label(over); \
442
@@ -XXX,XX +XXX,XX @@ static bool trans_##NAME(DisasContext *s, arg_rmr *a) \
443
data = FIELD_DP32(data, VDATA, VM, a->vm); \
444
tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \
445
vreg_ofs(s, a->rs2), cpu_env, \
446
- s->vlen / 8, s->vlen / 8, data, \
447
+ s->cfg_ptr->vlen / 8, \
448
+ s->cfg_ptr->vlen / 8, data, \
449
fns[s->sew]); \
450
mark_vs_dirty(s); \
451
gen_set_label(over); \
452
@@ -XXX,XX +XXX,XX @@ static bool trans_##NAME(DisasContext *s, arg_rmr *a) \
453
data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \
454
tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \
455
vreg_ofs(s, a->rs2), cpu_env, \
456
- s->vlen / 8, s->vlen / 8, data, \
457
+ s->cfg_ptr->vlen / 8, \
458
+ s->cfg_ptr->vlen / 8, data, \
459
fns[s->sew - 1]); \
460
mark_vs_dirty(s); \
461
gen_set_label(over); \
462
@@ -XXX,XX +XXX,XX @@ static bool trans_##NAME(DisasContext *s, arg_rmr *a) \
463
data = FIELD_DP32(data, VDATA, VM, a->vm); \
464
tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \
465
vreg_ofs(s, a->rs2), cpu_env, \
466
- s->vlen / 8, s->vlen / 8, data, \
467
+ s->cfg_ptr->vlen / 8, \
468
+ s->cfg_ptr->vlen / 8, data, \
469
fns[s->sew]); \
470
mark_vs_dirty(s); \
471
gen_set_label(over); \
472
@@ -XXX,XX +XXX,XX @@ GEN_OPIVV_TRANS(vredxor_vs, reduction_check)
473
static bool reduction_widen_check(DisasContext *s, arg_rmrr *a)
58
{
474
{
59
return reduction_widen_check(s, a) &&
475
return reduction_check(s, a) && (s->sew < MO_64) &&
60
+ require_rvf(s) &&
476
- ((s->sew + 1) <= (s->elen >> 4));
61
require_scale_rvf(s) &&
477
+ ((s->sew + 1) <= (s->cfg_ptr->elen >> 4));
62
(s->sew != MO_8);
478
}
63
}
479
480
GEN_OPIVV_WIDEN_TRANS(vwredsum_vs, reduction_widen_check)
481
@@ -XXX,XX +XXX,XX @@ static bool trans_##NAME(DisasContext *s, arg_r *a) \
482
tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \
483
vreg_ofs(s, a->rs1), \
484
vreg_ofs(s, a->rs2), cpu_env, \
485
- s->vlen / 8, s->vlen / 8, data, fn); \
486
+ s->cfg_ptr->vlen / 8, \
487
+ s->cfg_ptr->vlen / 8, data, fn); \
488
mark_vs_dirty(s); \
489
gen_set_label(over); \
490
return true; \
491
@@ -XXX,XX +XXX,XX @@ static bool trans_vcpop_m(DisasContext *s, arg_rmr *a)
492
mask = tcg_temp_new_ptr();
493
src2 = tcg_temp_new_ptr();
494
dst = dest_gpr(s, a->rd);
495
- desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data));
496
+ desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlen / 8,
497
+ s->cfg_ptr->vlen / 8, data));
498
499
tcg_gen_addi_ptr(src2, cpu_env, vreg_ofs(s, a->rs2));
500
tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0));
501
@@ -XXX,XX +XXX,XX @@ static bool trans_vfirst_m(DisasContext *s, arg_rmr *a)
502
mask = tcg_temp_new_ptr();
503
src2 = tcg_temp_new_ptr();
504
dst = dest_gpr(s, a->rd);
505
- desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data));
506
+ desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlen / 8,
507
+ s->cfg_ptr->vlen / 8, data));
508
509
tcg_gen_addi_ptr(src2, cpu_env, vreg_ofs(s, a->rs2));
510
tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0));
511
@@ -XXX,XX +XXX,XX @@ static bool trans_##NAME(DisasContext *s, arg_rmr *a) \
512
data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \
513
tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), \
514
vreg_ofs(s, 0), vreg_ofs(s, a->rs2), \
515
- cpu_env, s->vlen / 8, s->vlen / 8, \
516
+ cpu_env, s->cfg_ptr->vlen / 8, \
517
+ s->cfg_ptr->vlen / 8, \
518
data, fn); \
519
mark_vs_dirty(s); \
520
gen_set_label(over); \
521
@@ -XXX,XX +XXX,XX @@ static bool trans_viota_m(DisasContext *s, arg_viota_m *a)
522
};
523
tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
524
vreg_ofs(s, a->rs2), cpu_env,
525
- s->vlen / 8, s->vlen / 8, data, fns[s->sew]);
526
+ s->cfg_ptr->vlen / 8,
527
+ s->cfg_ptr->vlen / 8, data, fns[s->sew]);
528
mark_vs_dirty(s);
529
gen_set_label(over);
530
return true;
531
@@ -XXX,XX +XXX,XX @@ static bool trans_vid_v(DisasContext *s, arg_vid_v *a)
532
gen_helper_vid_v_w, gen_helper_vid_v_d,
533
};
534
tcg_gen_gvec_2_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
535
- cpu_env, s->vlen / 8, s->vlen / 8,
536
+ cpu_env, s->cfg_ptr->vlen / 8,
537
+ s->cfg_ptr->vlen / 8,
538
data, fns[s->sew]);
539
mark_vs_dirty(s);
540
gen_set_label(over);
541
@@ -XXX,XX +XXX,XX @@ static bool trans_vrgather_vx(DisasContext *s, arg_rmrr *a)
542
543
if (a->vm && s->vl_eq_vlmax) {
544
int scale = s->lmul - (s->sew + 3);
545
- int vlmax = scale < 0 ? s->vlen >> -scale : s->vlen << scale;
546
+ int vlmax = scale < 0 ?
547
+ s->cfg_ptr->vlen >> -scale : s->cfg_ptr->vlen << scale;
548
TCGv_i64 dest = tcg_temp_new_i64();
549
550
if (a->rs1 == 0) {
551
@@ -XXX,XX +XXX,XX @@ static bool trans_vrgather_vi(DisasContext *s, arg_rmrr *a)
552
553
if (a->vm && s->vl_eq_vlmax) {
554
int scale = s->lmul - (s->sew + 3);
555
- int vlmax = scale < 0 ? s->vlen >> -scale : s->vlen << scale;
556
+ int vlmax = scale < 0 ?
557
+ s->cfg_ptr->vlen >> -scale : s->cfg_ptr->vlen << scale;
558
if (a->rs1 >= vlmax) {
559
tcg_gen_gvec_dup_imm(MO_64, vreg_ofs(s, a->rd),
560
MAXSZ(s), MAXSZ(s), 0);
561
@@ -XXX,XX +XXX,XX @@ static bool trans_vcompress_vm(DisasContext *s, arg_r *a)
562
data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
563
tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
564
vreg_ofs(s, a->rs1), vreg_ofs(s, a->rs2),
565
- cpu_env, s->vlen / 8, s->vlen / 8, data,
566
+ cpu_env, s->cfg_ptr->vlen / 8,
567
+ s->cfg_ptr->vlen / 8, data,
568
fns[s->sew]);
569
mark_vs_dirty(s);
570
gen_set_label(over);
571
@@ -XXX,XX +XXX,XX @@ static bool trans_##NAME(DisasContext *s, arg_##NAME * a) \
572
if (require_rvv(s) && \
573
QEMU_IS_ALIGNED(a->rd, LEN) && \
574
QEMU_IS_ALIGNED(a->rs2, LEN)) { \
575
- uint32_t maxsz = (s->vlen >> 3) * LEN; \
576
+ uint32_t maxsz = (s->cfg_ptr->vlen >> 3) * LEN; \
577
if (s->vstart == 0) { \
578
/* EEW = 8 */ \
579
tcg_gen_gvec_mov(MO_8, vreg_ofs(s, a->rd), \
580
@@ -XXX,XX +XXX,XX @@ static bool int_ext_op(DisasContext *s, arg_rmr *a, uint8_t seq)
581
582
tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
583
vreg_ofs(s, a->rs2), cpu_env,
584
- s->vlen / 8, s->vlen / 8, data, fn);
585
+ s->cfg_ptr->vlen / 8,
586
+ s->cfg_ptr->vlen / 8, data, fn);
587
588
mark_vs_dirty(s);
589
gen_set_label(over);
590
diff --git a/target/riscv/insn_trans/trans_rvzfh.c.inc b/target/riscv/insn_trans/trans_rvzfh.c.inc
591
index XXXXXXX..XXXXXXX 100644
592
--- a/target/riscv/insn_trans/trans_rvzfh.c.inc
593
+++ b/target/riscv/insn_trans/trans_rvzfh.c.inc
594
@@ -XXX,XX +XXX,XX @@
595
*/
596
597
#define REQUIRE_ZFH(ctx) do { \
598
- if (!ctx->ext_zfh) { \
599
+ if (!ctx->cfg_ptr->ext_zfh) { \
600
return false; \
601
} \
602
} while (0)
603
604
#define REQUIRE_ZFH_OR_ZFHMIN(ctx) do { \
605
- if (!(ctx->ext_zfh || ctx->ext_zfhmin)) { \
606
+ if (!(ctx->cfg_ptr->ext_zfh || ctx->cfg_ptr->ext_zfhmin)) { \
607
return false; \
608
} \
609
} while (0)
64
--
610
--
65
2.45.1
611
2.34.1
66
612
67
613
diff view generated by jsdifflib
1
From: Alistair Francis <alistair23@gmail.com>
1
From: Philipp Tomsich <philipp.tomsich@vrull.eu>
2
2
3
Previously we only listed a single pmpcfg CSR and the first 16 pmpaddr
3
The Zb[abcs] support code still uses the RISCV_CPU macros to access
4
CSRs. This patch fixes this to list all 16 pmpcfg and all 64 pmpaddr
4
the configuration information (i.e., check whether an extension is
5
CSRs are part of the disassembly.
5
available/enabled). Now that we provide this information directly
6
from DisasContext, we can access this directly via the cfg_ptr field.
6
7
7
Reported-by: Eric DeVolder <eric_devolder@yahoo.com>
8
Signed-off-by: Philipp Tomsich <philipp.tomsich@vrull.eu>
8
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Fixes: ea10325917 ("RISC-V Disassembler")
10
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Cc: qemu-stable <qemu-stable@nongnu.org>
12
Message-Id: <20220202005249.3566542-5-philipp.tomsich@vrull.eu>
12
Message-ID: <20240514051615.330979-1-alistair.francis@wdc.com>
13
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
13
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
14
---
14
---
15
disas/riscv.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++-
15
target/riscv/insn_trans/trans_rvb.c.inc | 8 ++++----
16
1 file changed, 64 insertions(+), 1 deletion(-)
16
1 file changed, 4 insertions(+), 4 deletions(-)
17
17
18
diff --git a/disas/riscv.c b/disas/riscv.c
18
diff --git a/target/riscv/insn_trans/trans_rvb.c.inc b/target/riscv/insn_trans/trans_rvb.c.inc
19
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
20
--- a/disas/riscv.c
20
--- a/target/riscv/insn_trans/trans_rvb.c.inc
21
+++ b/disas/riscv.c
21
+++ b/target/riscv/insn_trans/trans_rvb.c.inc
22
@@ -XXX,XX +XXX,XX @@ static const char *csr_name(int csrno)
22
@@ -XXX,XX +XXX,XX @@
23
case 0x0383: return "mibound";
23
*/
24
case 0x0384: return "mdbase";
24
25
case 0x0385: return "mdbound";
25
#define REQUIRE_ZBA(ctx) do { \
26
- case 0x03a0: return "pmpcfg3";
26
- if (!RISCV_CPU(ctx->cs)->cfg.ext_zba) { \
27
+ case 0x03a0: return "pmpcfg0";
27
+ if (ctx->cfg_ptr->ext_zba) { \
28
+ case 0x03a1: return "pmpcfg1";
28
return false; \
29
+ case 0x03a2: return "pmpcfg2";
29
} \
30
+ case 0x03a3: return "pmpcfg3";
30
} while (0)
31
+ case 0x03a4: return "pmpcfg4";
31
32
+ case 0x03a5: return "pmpcfg5";
32
#define REQUIRE_ZBB(ctx) do { \
33
+ case 0x03a6: return "pmpcfg6";
33
- if (!RISCV_CPU(ctx->cs)->cfg.ext_zbb) { \
34
+ case 0x03a7: return "pmpcfg7";
34
+ if (ctx->cfg_ptr->ext_zbb) { \
35
+ case 0x03a8: return "pmpcfg8";
35
return false; \
36
+ case 0x03a9: return "pmpcfg9";
36
} \
37
+ case 0x03aa: return "pmpcfg10";
37
} while (0)
38
+ case 0x03ab: return "pmpcfg11";
38
39
+ case 0x03ac: return "pmpcfg12";
39
#define REQUIRE_ZBC(ctx) do { \
40
+ case 0x03ad: return "pmpcfg13";
40
- if (!RISCV_CPU(ctx->cs)->cfg.ext_zbc) { \
41
+ case 0x03ae: return "pmpcfg14";
41
+ if (ctx->cfg_ptr->ext_zbc) { \
42
+ case 0x03af: return "pmpcfg15";
42
return false; \
43
case 0x03b0: return "pmpaddr0";
43
} \
44
case 0x03b1: return "pmpaddr1";
44
} while (0)
45
case 0x03b2: return "pmpaddr2";
45
46
@@ -XXX,XX +XXX,XX @@ static const char *csr_name(int csrno)
46
#define REQUIRE_ZBS(ctx) do { \
47
case 0x03bd: return "pmpaddr13";
47
- if (!RISCV_CPU(ctx->cs)->cfg.ext_zbs) { \
48
case 0x03be: return "pmpaddr14";
48
+ if (ctx->cfg_ptr->ext_zbs) { \
49
case 0x03bf: return "pmpaddr15";
49
return false; \
50
+ case 0x03c0: return "pmpaddr16";
50
} \
51
+ case 0x03c1: return "pmpaddr17";
51
} while (0)
52
+ case 0x03c2: return "pmpaddr18";
53
+ case 0x03c3: return "pmpaddr19";
54
+ case 0x03c4: return "pmpaddr20";
55
+ case 0x03c5: return "pmpaddr21";
56
+ case 0x03c6: return "pmpaddr22";
57
+ case 0x03c7: return "pmpaddr23";
58
+ case 0x03c8: return "pmpaddr24";
59
+ case 0x03c9: return "pmpaddr25";
60
+ case 0x03ca: return "pmpaddr26";
61
+ case 0x03cb: return "pmpaddr27";
62
+ case 0x03cc: return "pmpaddr28";
63
+ case 0x03cd: return "pmpaddr29";
64
+ case 0x03ce: return "pmpaddr30";
65
+ case 0x03cf: return "pmpaddr31";
66
+ case 0x03d0: return "pmpaddr32";
67
+ case 0x03d1: return "pmpaddr33";
68
+ case 0x03d2: return "pmpaddr34";
69
+ case 0x03d3: return "pmpaddr35";
70
+ case 0x03d4: return "pmpaddr36";
71
+ case 0x03d5: return "pmpaddr37";
72
+ case 0x03d6: return "pmpaddr38";
73
+ case 0x03d7: return "pmpaddr39";
74
+ case 0x03d8: return "pmpaddr40";
75
+ case 0x03d9: return "pmpaddr41";
76
+ case 0x03da: return "pmpaddr42";
77
+ case 0x03db: return "pmpaddr43";
78
+ case 0x03dc: return "pmpaddr44";
79
+ case 0x03dd: return "pmpaddr45";
80
+ case 0x03de: return "pmpaddr46";
81
+ case 0x03df: return "pmpaddr47";
82
+ case 0x03e0: return "pmpaddr48";
83
+ case 0x03e1: return "pmpaddr49";
84
+ case 0x03e2: return "pmpaddr50";
85
+ case 0x03e3: return "pmpaddr51";
86
+ case 0x03e4: return "pmpaddr52";
87
+ case 0x03e5: return "pmpaddr53";
88
+ case 0x03e6: return "pmpaddr54";
89
+ case 0x03e7: return "pmpaddr55";
90
+ case 0x03e8: return "pmpaddr56";
91
+ case 0x03e9: return "pmpaddr57";
92
+ case 0x03ea: return "pmpaddr58";
93
+ case 0x03eb: return "pmpaddr59";
94
+ case 0x03ec: return "pmpaddr60";
95
+ case 0x03ed: return "pmpaddr61";
96
+ case 0x03ee: return "pmpaddr62";
97
+ case 0x03ef: return "pmpaddr63";
98
case 0x0780: return "mtohost";
99
case 0x0781: return "mfromhost";
100
case 0x0782: return "mreset";
101
--
52
--
102
2.45.1
53
2.34.1
54
55
diff view generated by jsdifflib
1
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
1
From: Philipp Tomsich <philipp.tomsich@vrull.eu>
2
2
3
Running a KVM guest using a 6.9-rc3 kernel, in a 6.8 host that has zkr
3
To split up the decoder into multiple functions (both to support
4
enabled, will fail with a kernel oops SIGILL right at the start. The
4
vendor-specific opcodes in separate files and to simplify maintenance
5
reason is that we can't expose zkr without implementing the SEED CSR.
5
of orthogonal extensions), this changes decode_op to iterate over a
6
Disabling zkr in the guest would be a workaround, but if the KVM doesn't
6
table of decoders predicated on guard functions.
7
allow it we'll error out and never boot.
8
7
9
In hindsight this is too strict. If we keep proceeding, despite not
8
This commit only adds the new structure and the table, allowing for
10
disabling the extension in the KVM vcpu, we'll not add the extension in
9
the easy addition of additional decoders in the future.
11
the riscv,isa. The guest kernel will be unaware of the extension, i.e.
12
it doesn't matter if the KVM vcpu has it enabled underneath or not. So
13
it's ok to keep booting in this case.
14
10
15
Change our current logic to not error out if we fail to disable an
11
Signed-off-by: Philipp Tomsich <philipp.tomsich@vrull.eu>
16
extension in kvm_set_one_reg(), but show a warning and keep booting. It
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
is important to throw a warning because we must make the user aware that
13
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
18
the extension is still available in the vcpu, meaning that an
14
Message-Id: <20220202005249.3566542-6-philipp.tomsich@vrull.eu>
19
ill-behaved guest can ignore the riscv,isa settings and use the
20
extension.
21
22
The case we're handling happens with an EINVAL error code. If we fail to
23
disable the extension in KVM for any other reason, error out.
24
25
We'll also keep erroring out when we fail to enable an extension in KVM,
26
since adding the extension in riscv,isa at this point will cause a guest
27
malfunction because the extension isn't enabled in the vcpu.
28
29
Suggested-by: Andrew Jones <ajones@ventanamicro.com>
30
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
31
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
32
Cc: qemu-stable <qemu-stable@nongnu.org>
33
Message-ID: <20240422171425.333037-2-dbarboza@ventanamicro.com>
34
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
15
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
35
---
16
---
36
target/riscv/kvm/kvm-cpu.c | 12 ++++++++----
17
target/riscv/translate.c | 32 +++++++++++++++++++++++++++-----
37
1 file changed, 8 insertions(+), 4 deletions(-)
18
1 file changed, 27 insertions(+), 5 deletions(-)
38
19
39
diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
20
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
40
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
41
--- a/target/riscv/kvm/kvm-cpu.c
22
--- a/target/riscv/translate.c
42
+++ b/target/riscv/kvm/kvm-cpu.c
23
+++ b/target/riscv/translate.c
43
@@ -XXX,XX +XXX,XX @@ static void kvm_riscv_update_cpu_cfg_isa_ext(RISCVCPU *cpu, CPUState *cs)
24
@@ -XXX,XX +XXX,XX @@ static inline bool has_ext(DisasContext *ctx, uint32_t ext)
44
reg = kvm_cpu_cfg_get(cpu, multi_ext_cfg);
25
return ctx->misa_ext & ext;
45
ret = kvm_set_one_reg(cs, id, &reg);
26
}
46
if (ret != 0) {
27
47
- error_report("Unable to %s extension %s in KVM, error %d",
28
+static bool always_true_p(DisasContext *ctx __attribute__((__unused__)))
48
- reg ? "enable" : "disable",
29
+{
49
- multi_ext_cfg->name, ret);
30
+ return true;
50
- exit(EXIT_FAILURE);
31
+}
51
+ if (!reg && ret == -EINVAL) {
32
+
52
+ warn_report("KVM cannot disable extension %s",
33
#ifdef TARGET_RISCV32
53
+ multi_ext_cfg->name);
34
#define get_xl(ctx) MXL_RV32
54
+ } else {
35
#elif defined(CONFIG_USER_ONLY)
55
+ error_report("Unable to enable extension %s in KVM, error %d",
36
@@ -XXX,XX +XXX,XX @@ static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
56
+ multi_ext_cfg->name, ret);
37
57
+ exit(EXIT_FAILURE);
38
static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
39
{
40
- /* check for compressed insn */
41
+ /*
42
+ * A table with predicate (i.e., guard) functions and decoder functions
43
+ * that are tested in-order until a decoder matches onto the opcode.
44
+ */
45
+ static const struct {
46
+ bool (*guard_func)(DisasContext *);
47
+ bool (*decode_func)(DisasContext *, uint32_t);
48
+ } decoders[] = {
49
+ { always_true_p, decode_insn32 },
50
+ };
51
+
52
+ /* Check for compressed insn */
53
if (extract16(opcode, 0, 2) != 3) {
54
if (!has_ext(ctx, RVC)) {
55
gen_exception_illegal(ctx);
56
} else {
57
ctx->opcode = opcode;
58
ctx->pc_succ_insn = ctx->base.pc_next + 2;
59
- if (!decode_insn16(ctx, opcode)) {
60
- gen_exception_illegal(ctx);
61
+ if (decode_insn16(ctx, opcode)) {
62
+ return;
63
}
64
}
65
} else {
66
@@ -XXX,XX +XXX,XX @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
67
ctx->base.pc_next + 2));
68
ctx->opcode = opcode32;
69
ctx->pc_succ_insn = ctx->base.pc_next + 4;
70
- if (!decode_insn32(ctx, opcode32)) {
71
- gen_exception_illegal(ctx);
72
+
73
+ for (size_t i = 0; i < ARRAY_SIZE(decoders); ++i) {
74
+ if (decoders[i].guard_func(ctx) &&
75
+ decoders[i].decode_func(ctx, opcode32)) {
76
+ return;
58
+ }
77
+ }
59
}
78
}
60
}
79
}
80
+
81
+ gen_exception_illegal(ctx);
61
}
82
}
83
84
static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
62
--
85
--
63
2.45.1
86
2.34.1
87
88
diff view generated by jsdifflib
1
From: Christoph Müllner <christoph.muellner@vrull.eu>
1
From: Philipp Tomsich <philipp.tomsich@vrull.eu>
2
2
3
The th.sxstatus CSR can be used to identify available custom extension
3
This adds the decoder and translation for the XVentanaCondOps custom
4
on T-Head CPUs. The CSR is documented here:
4
extension (vendor-defined by Ventana Micro Systems), which is
5
https://github.com/T-head-Semi/thead-extension-spec/blob/master/xtheadsxstatus.adoc
5
documented at https://github.com/ventanamicro/ventana-custom-extensions/releases/download/v1.0.0/ventana-custom-extensions-v1.0.0.pdf
6
6
7
An important property of this patch is, that the th.sxstatus MAEE field
7
This commit then also adds a guard-function (has_XVentanaCondOps_p)
8
is not set (indicating that XTheadMae is not available).
8
and the decoder function to the table of decoders, enabling the
9
XTheadMae is a memory attribute extension (similar to Svpbmt) which is
9
support for the XVentanaCondOps extension.
10
implemented in many T-Head CPUs (C906, C910, etc.) and utilizes bits
11
in PTEs that are marked as reserved. QEMU maintainers prefer to not
12
implement XTheadMae, so we need give kernels a mechanism to identify
13
if XTheadMae is available in a system or not. And this patch introduces
14
this mechanism in QEMU in a way that's compatible with real HW
15
(i.e., probing the th.sxstatus.MAEE bit).
16
10
17
Further context can be found on the list:
11
Signed-off-by: Philipp Tomsich <philipp.tomsich@vrull.eu>
18
https://lists.gnu.org/archive/html/qemu-devel/2024-02/msg00775.html
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
20
Reviewed-by: LIU Zhiwei <zhiwe_liu@linux.alibaba.com>
21
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
13
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
22
Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
14
Message-Id: <20220202005249.3566542-7-philipp.tomsich@vrull.eu>
23
Message-ID: <20240429073656.2486732-1-christoph.muellner@vrull.eu>
24
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
15
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
25
---
16
---
26
MAINTAINERS | 1 +
17
target/riscv/cpu.h | 3 ++
27
target/riscv/cpu.h | 3 ++
18
target/riscv/XVentanaCondOps.decode | 25 ++++++++++++
28
target/riscv/cpu.c | 1 +
19
target/riscv/cpu.c | 3 ++
29
target/riscv/th_csr.c | 79 ++++++++++++++++++++++++++++++++++++++++
20
target/riscv/translate.c | 12 ++++++
30
target/riscv/meson.build | 1 +
21
.../insn_trans/trans_xventanacondops.c.inc | 39 +++++++++++++++++++
31
5 files changed, 85 insertions(+)
22
target/riscv/meson.build | 1 +
32
create mode 100644 target/riscv/th_csr.c
23
6 files changed, 83 insertions(+)
24
create mode 100644 target/riscv/XVentanaCondOps.decode
25
create mode 100644 target/riscv/insn_trans/trans_xventanacondops.c.inc
33
26
34
diff --git a/MAINTAINERS b/MAINTAINERS
35
index XXXXXXX..XXXXXXX 100644
36
--- a/MAINTAINERS
37
+++ b/MAINTAINERS
38
@@ -XXX,XX +XXX,XX @@ L: qemu-riscv@nongnu.org
39
S: Supported
40
F: target/riscv/insn_trans/trans_xthead.c.inc
41
F: target/riscv/xthead*.decode
42
+F: target/riscv/th_*
43
F: disas/riscv-xthead*
44
45
RISC-V XVentanaCondOps extension
46
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
27
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
47
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
48
--- a/target/riscv/cpu.h
29
--- a/target/riscv/cpu.h
49
+++ b/target/riscv/cpu.h
30
+++ b/target/riscv/cpu.h
50
@@ -XXX,XX +XXX,XX @@ target_ulong riscv_new_csr_seed(target_ulong new_value,
31
@@ -XXX,XX +XXX,XX @@ struct RISCVCPUConfig {
51
uint8_t satp_mode_max_from_map(uint32_t map);
32
bool ext_zve32f;
52
const char *satp_mode_str(uint8_t satp_mode, bool is_32_bit);
33
bool ext_zve64f;
53
34
54
+/* Implemented in th_csr.c */
35
+ /* Vendor-specific custom extensions */
55
+void th_register_custom_csrs(RISCVCPU *cpu);
36
+ bool ext_XVentanaCondOps;
56
+
37
+
57
#endif /* RISCV_CPU_H */
38
char *priv_spec;
39
char *user_spec;
40
char *bext_spec;
41
diff --git a/target/riscv/XVentanaCondOps.decode b/target/riscv/XVentanaCondOps.decode
42
new file mode 100644
43
index XXXXXXX..XXXXXXX
44
--- /dev/null
45
+++ b/target/riscv/XVentanaCondOps.decode
46
@@ -XXX,XX +XXX,XX @@
47
+#
48
+# RISC-V translation routines for the XVentanaCondOps extension
49
+#
50
+# Copyright (c) 2022 Dr. Philipp Tomsich, philipp.tomsich@vrull.eu
51
+#
52
+# SPDX-License-Identifier: LGPL-2.1-or-later
53
+#
54
+# Reference: VTx-family custom instructions
55
+# Custom ISA extensions for Ventana Micro Systems RISC-V cores
56
+# (https://github.com/ventanamicro/ventana-custom-extensions/releases/download/v1.0.0/ventana-custom-extensions-v1.0.0.pdf)
57
+
58
+# Fields
59
+%rs2 20:5
60
+%rs1 15:5
61
+%rd 7:5
62
+
63
+# Argument sets
64
+&r rd rs1 rs2 !extern
65
+
66
+# Formats
67
+@r ....... ..... ..... ... ..... ....... &r %rs2 %rs1 %rd
68
+
69
+# *** RV64 Custom-3 Extension ***
70
+vt_maskc 0000000 ..... ..... 110 ..... 1111011 @r
71
+vt_maskcn 0000000 ..... ..... 111 ..... 1111011 @r
58
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
72
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
59
index XXXXXXX..XXXXXXX 100644
73
index XXXXXXX..XXXXXXX 100644
60
--- a/target/riscv/cpu.c
74
--- a/target/riscv/cpu.c
61
+++ b/target/riscv/cpu.c
75
+++ b/target/riscv/cpu.c
62
@@ -XXX,XX +XXX,XX @@ static void rv64_thead_c906_cpu_init(Object *obj)
76
@@ -XXX,XX +XXX,XX @@ static Property riscv_cpu_properties[] = {
63
cpu->cfg.mvendorid = THEAD_VENDOR_ID;
77
DEFINE_PROP_BOOL("zbc", RISCVCPU, cfg.ext_zbc, true),
64
#ifndef CONFIG_USER_ONLY
78
DEFINE_PROP_BOOL("zbs", RISCVCPU, cfg.ext_zbs, true),
65
set_satp_mode_max_supported(cpu, VM_1_10_SV39);
79
66
+ th_register_custom_csrs(cpu);
80
+ /* Vendor-specific custom extensions */
67
#endif
81
+ DEFINE_PROP_BOOL("xventanacondops", RISCVCPU, cfg.ext_XVentanaCondOps, false),
68
82
+
69
/* inherited from parent obj via riscv_cpu_init() */
83
/* These are experimental so mark with 'x-' */
70
diff --git a/target/riscv/th_csr.c b/target/riscv/th_csr.c
84
DEFINE_PROP_BOOL("x-j", RISCVCPU, cfg.ext_j, false),
85
/* ePMP 0.9.3 */
86
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/target/riscv/translate.c
89
+++ b/target/riscv/translate.c
90
@@ -XXX,XX +XXX,XX @@ static bool always_true_p(DisasContext *ctx __attribute__((__unused__)))
91
return true;
92
}
93
94
+#define MATERIALISE_EXT_PREDICATE(ext) \
95
+ static bool has_ ## ext ## _p(DisasContext *ctx) \
96
+ { \
97
+ return ctx->cfg_ptr->ext_ ## ext ; \
98
+ }
99
+
100
+MATERIALISE_EXT_PREDICATE(XVentanaCondOps);
101
+
102
#ifdef TARGET_RISCV32
103
#define get_xl(ctx) MXL_RV32
104
#elif defined(CONFIG_USER_ONLY)
105
@@ -XXX,XX +XXX,XX @@ static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
106
#include "insn_trans/trans_rvb.c.inc"
107
#include "insn_trans/trans_rvzfh.c.inc"
108
#include "insn_trans/trans_privileged.c.inc"
109
+#include "insn_trans/trans_xventanacondops.c.inc"
110
111
/* Include the auto-generated decoder for 16 bit insn */
112
#include "decode-insn16.c.inc"
113
+/* Include decoders for factored-out extensions */
114
+#include "decode-XVentanaCondOps.c.inc"
115
116
static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
117
{
118
@@ -XXX,XX +XXX,XX @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
119
bool (*decode_func)(DisasContext *, uint32_t);
120
} decoders[] = {
121
{ always_true_p, decode_insn32 },
122
+ { has_XVentanaCondOps_p, decode_XVentanaCodeOps },
123
};
124
125
/* Check for compressed insn */
126
diff --git a/target/riscv/insn_trans/trans_xventanacondops.c.inc b/target/riscv/insn_trans/trans_xventanacondops.c.inc
71
new file mode 100644
127
new file mode 100644
72
index XXXXXXX..XXXXXXX
128
index XXXXXXX..XXXXXXX
73
--- /dev/null
129
--- /dev/null
74
+++ b/target/riscv/th_csr.c
130
+++ b/target/riscv/insn_trans/trans_xventanacondops.c.inc
75
@@ -XXX,XX +XXX,XX @@
131
@@ -XXX,XX +XXX,XX @@
76
+/*
132
+/*
77
+ * T-Head-specific CSRs.
133
+ * RISC-V translation routines for the XVentanaCondOps extension.
78
+ *
134
+ *
79
+ * Copyright (c) 2024 VRULL GmbH
135
+ * Copyright (c) 2021-2022 VRULL GmbH.
80
+ *
136
+ *
81
+ * This program is free software; you can redistribute it and/or modify it
137
+ * This program is free software; you can redistribute it and/or modify it
82
+ * under the terms and conditions of the GNU General Public License,
138
+ * under the terms and conditions of the GNU General Public License,
83
+ * version 2 or later, as published by the Free Software Foundation.
139
+ * version 2 or later, as published by the Free Software Foundation.
84
+ *
140
+ *
...
...
89
+ *
145
+ *
90
+ * You should have received a copy of the GNU General Public License along with
146
+ * You should have received a copy of the GNU General Public License along with
91
+ * this program. If not, see <http://www.gnu.org/licenses/>.
147
+ * this program. If not, see <http://www.gnu.org/licenses/>.
92
+ */
148
+ */
93
+
149
+
94
+#include "qemu/osdep.h"
150
+static bool gen_vt_condmask(DisasContext *ctx, arg_r *a, TCGCond cond)
95
+#include "cpu.h"
151
+{
96
+#include "cpu_vendorid.h"
152
+ TCGv dest = dest_gpr(ctx, a->rd);
153
+ TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);
154
+ TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
97
+
155
+
98
+#define CSR_TH_SXSTATUS 0x5c0
156
+ tcg_gen_movcond_tl(cond, dest, src2, ctx->zero, src1, ctx->zero);
99
+
157
+
100
+/* TH_SXSTATUS bits */
158
+ gen_set_gpr(ctx, a->rd, dest);
101
+#define TH_SXSTATUS_UCME BIT(16)
159
+ return true;
102
+#define TH_SXSTATUS_MAEE BIT(21)
103
+#define TH_SXSTATUS_THEADISAEE BIT(22)
104
+
105
+typedef struct {
106
+ int csrno;
107
+ int (*insertion_test)(RISCVCPU *cpu);
108
+ riscv_csr_operations csr_ops;
109
+} riscv_csr;
110
+
111
+static RISCVException smode(CPURISCVState *env, int csrno)
112
+{
113
+ if (riscv_has_ext(env, RVS)) {
114
+ return RISCV_EXCP_NONE;
115
+ }
116
+
117
+ return RISCV_EXCP_ILLEGAL_INST;
118
+}
160
+}
119
+
161
+
120
+static int test_thead_mvendorid(RISCVCPU *cpu)
162
+static bool trans_vt_maskc(DisasContext *ctx, arg_r *a)
121
+{
163
+{
122
+ if (cpu->cfg.mvendorid != THEAD_VENDOR_ID) {
164
+ return gen_vt_condmask(ctx, a, TCG_COND_NE);
123
+ return -1;
124
+ }
125
+
126
+ return 0;
127
+}
165
+}
128
+
166
+
129
+static RISCVException read_th_sxstatus(CPURISCVState *env, int csrno,
167
+static bool trans_vt_maskcn(DisasContext *ctx, arg_r *a)
130
+ target_ulong *val)
131
+{
168
+{
132
+ /* We don't set MAEE here, because QEMU does not implement MAEE. */
169
+ return gen_vt_condmask(ctx, a, TCG_COND_EQ);
133
+ *val = TH_SXSTATUS_UCME | TH_SXSTATUS_THEADISAEE;
134
+ return RISCV_EXCP_NONE;
135
+}
136
+
137
+static riscv_csr th_csr_list[] = {
138
+ {
139
+ .csrno = CSR_TH_SXSTATUS,
140
+ .insertion_test = test_thead_mvendorid,
141
+ .csr_ops = { "th.sxstatus", smode, read_th_sxstatus }
142
+ }
143
+};
144
+
145
+void th_register_custom_csrs(RISCVCPU *cpu)
146
+{
147
+ for (size_t i = 0; i < ARRAY_SIZE(th_csr_list); i++) {
148
+ int csrno = th_csr_list[i].csrno;
149
+ riscv_csr_operations *csr_ops = &th_csr_list[i].csr_ops;
150
+ if (!th_csr_list[i].insertion_test(cpu)) {
151
+ riscv_set_csr_ops(csrno, csr_ops);
152
+ }
153
+ }
154
+}
170
+}
155
diff --git a/target/riscv/meson.build b/target/riscv/meson.build
171
diff --git a/target/riscv/meson.build b/target/riscv/meson.build
156
index XXXXXXX..XXXXXXX 100644
172
index XXXXXXX..XXXXXXX 100644
157
--- a/target/riscv/meson.build
173
--- a/target/riscv/meson.build
158
+++ b/target/riscv/meson.build
174
+++ b/target/riscv/meson.build
159
@@ -XXX,XX +XXX,XX @@ riscv_system_ss.add(files(
175
@@ -XXX,XX +XXX,XX @@ dir = meson.current_source_dir()
160
'monitor.c',
176
gen = [
161
'machine.c',
177
decodetree.process('insn16.decode', extra_args: ['--static-decode=decode_insn16', '--insnwidth=16']),
162
'pmu.c',
178
decodetree.process('insn32.decode', extra_args: '--static-decode=decode_insn32'),
163
+ 'th_csr.c',
179
+ decodetree.process('XVentanaCondOps.decode', extra_args: '--static-decode=decode_XVentanaCodeOps'),
164
'time_helper.c',
180
]
165
'riscv-qmp-cmds.c',
181
166
))
182
riscv_ss = ss.source_set()
167
--
183
--
168
2.45.1
184
2.34.1
169
185
170
186
diff view generated by jsdifflib
New patch
1
From: Philipp Tomsich <philipp.tomsich@vrull.eu>
1
2
3
The XVentanaCondOps extension is supported by VRULL on behalf of the
4
Ventana Micro. Add myself as a point-of-contact.
5
6
Signed-off-by: Philipp Tomsich <philipp.tomsich@vrull.eu>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Message-Id: <20220202005249.3566542-8-philipp.tomsich@vrull.eu>
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
---
12
MAINTAINERS | 7 +++++++
13
1 file changed, 7 insertions(+)
14
15
diff --git a/MAINTAINERS b/MAINTAINERS
16
index XXXXXXX..XXXXXXX 100644
17
--- a/MAINTAINERS
18
+++ b/MAINTAINERS
19
@@ -XXX,XX +XXX,XX @@ F: include/hw/riscv/
20
F: linux-user/host/riscv32/
21
F: linux-user/host/riscv64/
22
23
+RISC-V XVentanaCondOps extension
24
+M: Philipp Tomsich <philipp.tomsich@vrull.eu>
25
+L: qemu-riscv@nongnu.org
26
+S: Supported
27
+F: target/riscv/XVentanaCondOps.decode
28
+F: target/riscv/insn_trans/trans_xventanacondops.c.inc
29
+
30
RENESAS RX CPUs
31
R: Yoshinori Sato <ysato@users.sourceforge.jp>
32
S: Orphan
33
--
34
2.34.1
35
36
diff view generated by jsdifflib
1
From: Max Chou <max.chou@sifive.com>
1
From: LIU Zhiwei <zhiwei_liu@c-sky.com>
2
2
3
The opfv_narrow_check needs to check the single width float operator by
3
The guest should be able to set the vill bit as part of vsetvl.
4
require_rvf.
5
4
6
Signed-off-by: Max Chou <max.chou@sifive.com>
5
Currently we may set env->vill to 1 in the vsetvl helper, but there
7
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
6
is nowhere that we set it to 0, so once it transitions to 1 it's stuck
8
Cc: qemu-stable <qemu-stable@nongnu.org>
7
there until the system is reset.
9
Message-ID: <20240322092600.1198921-4-max.chou@sifive.com>
8
9
Signed-off-by: LIU Zhiwei <zhiwei_liu@c-sky.com>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
12
Message-Id: <20220201064601.41143-1-zhiwei_liu@c-sky.com>
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
13
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
---
14
---
12
target/riscv/insn_trans/trans_rvv.c.inc | 1 +
15
target/riscv/vector_helper.c | 1 +
13
1 file changed, 1 insertion(+)
16
1 file changed, 1 insertion(+)
14
17
15
diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc
18
diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
16
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
17
--- a/target/riscv/insn_trans/trans_rvv.c.inc
20
--- a/target/riscv/vector_helper.c
18
+++ b/target/riscv/insn_trans/trans_rvv.c.inc
21
+++ b/target/riscv/vector_helper.c
19
@@ -XXX,XX +XXX,XX @@ static bool opffv_narrow_check(DisasContext *s, arg_rmr *a)
22
@@ -XXX,XX +XXX,XX @@ target_ulong HELPER(vsetvl)(CPURISCVState *env, target_ulong s1,
20
static bool opffv_rod_narrow_check(DisasContext *s, arg_rmr *a)
23
env->vl = vl;
21
{
24
env->vtype = s2;
22
return opfv_narrow_check(s, a) &&
25
env->vstart = 0;
23
+ require_rvf(s) &&
26
+ env->vill = 0;
24
require_scale_rvf(s) &&
27
return vl;
25
(s->sew != MO_8);
26
}
28
}
29
27
--
30
--
28
2.45.1
31
2.34.1
32
33
diff view generated by jsdifflib
New patch
1
From: Anup Patel <anup.patel@wdc.com>
1
2
3
We should be returning illegal instruction trap when RV64 HS-mode tries
4
to access RV32 HS-mode CSR.
5
6
Fixes: d6f20dacea51 ("target/riscv: Fix 32-bit HS mode access permissions")
7
Signed-off-by: Anup Patel <anup.patel@wdc.com>
8
Signed-off-by: Anup Patel <anup@brainfault.org>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
11
Reviewed-by: Frank Chang <frank.chang@sifive.com>
12
Message-id: 20220204174700.534953-2-anup@brainfault.org
13
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
14
---
15
target/riscv/csr.c | 2 +-
16
1 file changed, 1 insertion(+), 1 deletion(-)
17
18
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/riscv/csr.c
21
+++ b/target/riscv/csr.c
22
@@ -XXX,XX +XXX,XX @@ static RISCVException hmode(CPURISCVState *env, int csrno)
23
static RISCVException hmode32(CPURISCVState *env, int csrno)
24
{
25
if (riscv_cpu_mxl(env) != MXL_RV32) {
26
- if (riscv_cpu_virt_enabled(env)) {
27
+ if (!riscv_cpu_virt_enabled(env)) {
28
return RISCV_EXCP_ILLEGAL_INST;
29
} else {
30
return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
31
--
32
2.34.1
33
34
diff view generated by jsdifflib
1
From: Max Chou <max.chou@sifive.com>
1
From: Anup Patel <anup.patel@wdc.com>
2
2
3
If the checking functions check both the single and double width
3
A hypervisor can optionally take guest external interrupts using
4
operators at the same time, then the single width operator checking
4
SGEIP bit of hip and hie CSRs.
5
functions (require_rvf[min]) will check whether the SEW is 8.
6
5
7
Signed-off-by: Max Chou <max.chou@sifive.com>
6
Signed-off-by: Anup Patel <anup.patel@wdc.com>
8
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
7
Signed-off-by: Anup Patel <anup@brainfault.org>
9
Cc: qemu-stable <qemu-stable@nongnu.org>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Message-ID: <20240322092600.1198921-5-max.chou@sifive.com>
9
Reviewed-by: Frank Chang <frank.chang@sifive.com>
10
Message-id: 20220204174700.534953-3-anup@brainfault.org
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
---
12
---
13
target/riscv/insn_trans/trans_rvv.c.inc | 16 ++++------------
13
target/riscv/cpu_bits.h | 3 +++
14
1 file changed, 4 insertions(+), 12 deletions(-)
14
target/riscv/cpu.c | 3 ++-
15
target/riscv/csr.c | 18 +++++++++++-------
16
3 files changed, 16 insertions(+), 8 deletions(-)
15
17
16
diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc
18
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
17
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
18
--- a/target/riscv/insn_trans/trans_rvv.c.inc
20
--- a/target/riscv/cpu_bits.h
19
+++ b/target/riscv/insn_trans/trans_rvv.c.inc
21
+++ b/target/riscv/cpu_bits.h
20
@@ -XXX,XX +XXX,XX @@ static bool opfvv_widen_check(DisasContext *s, arg_rmrr *a)
22
@@ -XXX,XX +XXX,XX @@ typedef enum RISCVException {
21
return require_rvv(s) &&
23
#define IRQ_S_EXT 9
22
require_rvf(s) &&
24
#define IRQ_VS_EXT 10
23
require_scale_rvf(s) &&
25
#define IRQ_M_EXT 11
24
- (s->sew != MO_8) &&
26
+#define IRQ_S_GEXT 12
25
vext_check_isa_ill(s) &&
27
+#define IRQ_LOCAL_MAX 16
26
vext_check_dss(s, a->rd, a->rs1, a->rs2, a->vm);
28
29
/* mip masks */
30
#define MIP_USIP (1 << IRQ_U_SOFT)
31
@@ -XXX,XX +XXX,XX @@ typedef enum RISCVException {
32
#define MIP_SEIP (1 << IRQ_S_EXT)
33
#define MIP_VSEIP (1 << IRQ_VS_EXT)
34
#define MIP_MEIP (1 << IRQ_M_EXT)
35
+#define MIP_SGEIP (1 << IRQ_S_GEXT)
36
37
/* sip masks */
38
#define SIP_SSIP MIP_SSIP
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
}
45
}
46
env->mcause = 0;
47
+ env->miclaim = MIP_SGEIP;
48
env->pc = env->resetvec;
49
env->two_stage_lookup = false;
50
/* mmte is supposed to have pm.current hardwired to 1 */
51
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_init(Object *obj)
52
cpu_set_cpustate_pointers(cpu);
53
54
#ifndef CONFIG_USER_ONLY
55
- qdev_init_gpio_in(DEVICE(cpu), riscv_cpu_set_irq, 12);
56
+ qdev_init_gpio_in(DEVICE(cpu), riscv_cpu_set_irq, IRQ_LOCAL_MAX);
57
#endif /* CONFIG_USER_ONLY */
27
}
58
}
28
@@ -XXX,XX +XXX,XX @@ static bool opfvf_widen_check(DisasContext *s, arg_rmrr *a)
59
29
return require_rvv(s) &&
60
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
30
require_rvf(s) &&
61
index XXXXXXX..XXXXXXX 100644
31
require_scale_rvf(s) &&
62
--- a/target/riscv/csr.c
32
- (s->sew != MO_8) &&
63
+++ b/target/riscv/csr.c
33
vext_check_isa_ill(s) &&
64
@@ -XXX,XX +XXX,XX @@ static RISCVException read_timeh(CPURISCVState *env, int csrno,
34
vext_check_ds(s, a->rd, a->rs2, a->vm);
65
#define M_MODE_INTERRUPTS (MIP_MSIP | MIP_MTIP | MIP_MEIP)
66
#define S_MODE_INTERRUPTS (MIP_SSIP | MIP_STIP | MIP_SEIP)
67
#define VS_MODE_INTERRUPTS (MIP_VSSIP | MIP_VSTIP | MIP_VSEIP)
68
+#define HS_MODE_INTERRUPTS (MIP_SGEIP | VS_MODE_INTERRUPTS)
69
70
static const target_ulong delegable_ints = S_MODE_INTERRUPTS |
71
VS_MODE_INTERRUPTS;
72
static const target_ulong vs_delegable_ints = VS_MODE_INTERRUPTS;
73
static const target_ulong all_ints = M_MODE_INTERRUPTS | S_MODE_INTERRUPTS |
74
- VS_MODE_INTERRUPTS;
75
+ HS_MODE_INTERRUPTS;
76
#define DELEGABLE_EXCPS ((1ULL << (RISCV_EXCP_INST_ADDR_MIS)) | \
77
(1ULL << (RISCV_EXCP_INST_ACCESS_FAULT)) | \
78
(1ULL << (RISCV_EXCP_ILLEGAL_INST)) | \
79
@@ -XXX,XX +XXX,XX @@ static RISCVException write_mideleg(CPURISCVState *env, int csrno,
80
{
81
env->mideleg = (env->mideleg & ~delegable_ints) | (val & delegable_ints);
82
if (riscv_has_ext(env, RVH)) {
83
- env->mideleg |= VS_MODE_INTERRUPTS;
84
+ env->mideleg |= HS_MODE_INTERRUPTS;
85
}
86
return RISCV_EXCP_NONE;
35
}
87
}
36
@@ -XXX,XX +XXX,XX @@ static bool opfwv_widen_check(DisasContext *s, arg_rmrr *a)
88
@@ -XXX,XX +XXX,XX @@ static RISCVException write_mie(CPURISCVState *env, int csrno,
37
return require_rvv(s) &&
89
target_ulong val)
38
require_rvf(s) &&
90
{
39
require_scale_rvf(s) &&
91
env->mie = (env->mie & ~all_ints) | (val & all_ints);
40
- (s->sew != MO_8) &&
92
+ if (!riscv_has_ext(env, RVH)) {
41
vext_check_isa_ill(s) &&
93
+ env->mie &= ~MIP_SGEIP;
42
vext_check_dds(s, a->rd, a->rs1, a->rs2, a->vm);
94
+ }
95
return RISCV_EXCP_NONE;
43
}
96
}
44
@@ -XXX,XX +XXX,XX @@ static bool opfwf_widen_check(DisasContext *s, arg_rmrr *a)
97
45
return require_rvv(s) &&
98
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_sip(CPURISCVState *env, int csrno,
46
require_rvf(s) &&
99
}
47
require_scale_rvf(s) &&
100
48
- (s->sew != MO_8) &&
101
if (ret_value) {
49
vext_check_isa_ill(s) &&
102
- *ret_value &= env->mideleg;
50
vext_check_dd(s, a->rd, a->rs2, a->vm);
103
+ *ret_value &= env->mideleg & S_MODE_INTERRUPTS;
104
}
105
return ret;
51
}
106
}
52
@@ -XXX,XX +XXX,XX @@ static bool opffv_widen_check(DisasContext *s, arg_rmr *a)
107
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_hvip(CPURISCVState *env, int csrno,
108
write_mask & hvip_writable_mask);
109
110
if (ret_value) {
111
- *ret_value &= hvip_writable_mask;
112
+ *ret_value &= VS_MODE_INTERRUPTS;
113
}
114
return ret;
115
}
116
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_hip(CPURISCVState *env, int csrno,
117
write_mask & hip_writable_mask);
118
119
if (ret_value) {
120
- *ret_value &= hip_writable_mask;
121
+ *ret_value &= HS_MODE_INTERRUPTS;
122
}
123
return ret;
124
}
125
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_hip(CPURISCVState *env, int csrno,
126
static RISCVException read_hie(CPURISCVState *env, int csrno,
127
target_ulong *val)
53
{
128
{
54
return opfv_widen_check(s, a) &&
129
- *val = env->mie & VS_MODE_INTERRUPTS;
55
require_rvfmin(s) &&
130
+ *val = env->mie & HS_MODE_INTERRUPTS;
56
- require_scale_rvfmin(s) &&
131
return RISCV_EXCP_NONE;
57
- (s->sew != MO_8);
58
+ require_scale_rvfmin(s);
59
}
132
}
60
133
61
#define GEN_OPFV_WIDEN_TRANS(NAME, CHECK, HELPER, FRM) \
134
static RISCVException write_hie(CPURISCVState *env, int csrno,
62
@@ -XXX,XX +XXX,XX @@ static bool opffv_narrow_check(DisasContext *s, arg_rmr *a)
135
target_ulong val)
63
{
136
{
64
return opfv_narrow_check(s, a) &&
137
- target_ulong newval = (env->mie & ~VS_MODE_INTERRUPTS) | (val & VS_MODE_INTERRUPTS);
65
require_rvfmin(s) &&
138
+ target_ulong newval = (env->mie & ~HS_MODE_INTERRUPTS) | (val & HS_MODE_INTERRUPTS);
66
- require_scale_rvfmin(s) &&
139
return write_mie(env, CSR_MIE, newval);
67
- (s->sew != MO_8);
68
+ require_scale_rvfmin(s);
69
}
140
}
70
141
71
static bool opffv_rod_narrow_check(DisasContext *s, arg_rmr *a)
72
{
73
return opfv_narrow_check(s, a) &&
74
require_rvf(s) &&
75
- require_scale_rvf(s) &&
76
- (s->sew != MO_8);
77
+ require_scale_rvf(s);
78
}
79
80
#define GEN_OPFV_NARROW_TRANS(NAME, CHECK, HELPER, FRM) \
81
@@ -XXX,XX +XXX,XX @@ static bool freduction_widen_check(DisasContext *s, arg_rmrr *a)
82
{
83
return reduction_widen_check(s, a) &&
84
require_rvf(s) &&
85
- require_scale_rvf(s) &&
86
- (s->sew != MO_8);
87
+ require_scale_rvf(s);
88
}
89
90
GEN_OPFVV_WIDEN_TRANS(vfwredusum_vs, freduction_widen_check)
91
--
142
--
92
2.45.1
143
2.34.1
144
145
diff view generated by jsdifflib
1
From: Jason Chien <jason.chien@sifive.com>
1
From: Anup Patel <anup.patel@wdc.com>
2
2
3
Add support for Zve32x extension and replace some checks for Zve32f with
3
The hgeie and hgeip CSRs are required for emulating an external
4
Zve32x, since Zve32f depends on Zve32x.
4
interrupt controller capable of injecting virtual external interrupt
5
5
to Guest/VM running at VS-level.
6
Signed-off-by: Jason Chien <jason.chien@sifive.com>
6
7
Signed-off-by: Anup Patel <anup.patel@wdc.com>
8
Signed-off-by: Anup Patel <anup@brainfault.org>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
7
Reviewed-by: Frank Chang <frank.chang@sifive.com>
10
Reviewed-by: Frank Chang <frank.chang@sifive.com>
8
Reviewed-by: Max Chou <max.chou@sifive.com>
11
Message-id: 20220204174700.534953-4-anup@brainfault.org
9
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
10
Message-ID: <20240328022343.6871-2-jason.chien@sifive.com>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
---
13
---
13
target/riscv/cpu_cfg.h | 1 +
14
target/riscv/cpu.h | 5 +++
14
target/riscv/cpu.c | 2 ++
15
target/riscv/cpu_bits.h | 1 +
15
target/riscv/cpu_helper.c | 2 +-
16
target/riscv/cpu.c | 67 +++++++++++++++++++++++++++------------
16
target/riscv/csr.c | 2 +-
17
target/riscv/cpu_helper.c | 37 +++++++++++++++++++--
17
target/riscv/tcg/tcg-cpu.c | 16 ++++++++--------
18
target/riscv/csr.c | 43 +++++++++++++++++--------
18
target/riscv/insn_trans/trans_rvv.c.inc | 4 ++--
19
target/riscv/machine.c | 6 ++--
19
6 files changed, 15 insertions(+), 12 deletions(-)
20
6 files changed, 121 insertions(+), 38 deletions(-)
20
21
21
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
22
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
22
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
23
--- a/target/riscv/cpu_cfg.h
24
--- a/target/riscv/cpu.h
24
+++ b/target/riscv/cpu_cfg.h
25
+++ b/target/riscv/cpu.h
25
@@ -XXX,XX +XXX,XX @@ struct RISCVCPUConfig {
26
@@ -XXX,XX +XXX,XX @@ struct CPURISCVState {
26
bool ext_zhinx;
27
target_ulong priv;
27
bool ext_zhinxmin;
28
/* This contains QEMU specific information about the virt state. */
28
bool ext_zve32f;
29
target_ulong virt;
29
+ bool ext_zve32x;
30
+ target_ulong geilen;
30
bool ext_zve64f;
31
target_ulong resetvec;
31
bool ext_zve64d;
32
32
bool ext_zvbb;
33
target_ulong mhartid;
34
@@ -XXX,XX +XXX,XX @@ struct CPURISCVState {
35
target_ulong htval;
36
target_ulong htinst;
37
target_ulong hgatp;
38
+ target_ulong hgeie;
39
+ target_ulong hgeip;
40
uint64_t htimedelta;
41
42
/* Upper 64-bits of 128-bit CSRs */
43
@@ -XXX,XX +XXX,XX @@ int riscv_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
44
int riscv_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
45
int riscv_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
46
bool riscv_cpu_fp_enabled(CPURISCVState *env);
47
+target_ulong riscv_cpu_get_geilen(CPURISCVState *env);
48
+void riscv_cpu_set_geilen(CPURISCVState *env, target_ulong geilen);
49
bool riscv_cpu_vector_enabled(CPURISCVState *env);
50
bool riscv_cpu_virt_enabled(CPURISCVState *env);
51
void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable);
52
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
53
index XXXXXXX..XXXXXXX 100644
54
--- a/target/riscv/cpu_bits.h
55
+++ b/target/riscv/cpu_bits.h
56
@@ -XXX,XX +XXX,XX @@ typedef enum RISCVException {
57
#define IRQ_M_EXT 11
58
#define IRQ_S_GEXT 12
59
#define IRQ_LOCAL_MAX 16
60
+#define IRQ_LOCAL_GUEST_MAX (TARGET_LONG_BITS - 1)
61
62
/* mip masks */
63
#define MIP_USIP (1 << IRQ_U_SOFT)
33
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
64
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
34
index XXXXXXX..XXXXXXX 100644
65
index XXXXXXX..XXXXXXX 100644
35
--- a/target/riscv/cpu.c
66
--- a/target/riscv/cpu.c
36
+++ b/target/riscv/cpu.c
67
+++ b/target/riscv/cpu.c
37
@@ -XXX,XX +XXX,XX @@ const RISCVIsaExtData isa_edata_arr[] = {
68
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
38
ISA_EXT_DATA_ENTRY(zvbb, PRIV_VERSION_1_12_0, ext_zvbb),
69
static void riscv_cpu_set_irq(void *opaque, int irq, int level)
39
ISA_EXT_DATA_ENTRY(zvbc, PRIV_VERSION_1_12_0, ext_zvbc),
70
{
40
ISA_EXT_DATA_ENTRY(zve32f, PRIV_VERSION_1_10_0, ext_zve32f),
71
RISCVCPU *cpu = RISCV_CPU(opaque);
41
+ ISA_EXT_DATA_ENTRY(zve32x, PRIV_VERSION_1_10_0, ext_zve32x),
72
+ CPURISCVState *env = &cpu->env;
42
ISA_EXT_DATA_ENTRY(zve64f, PRIV_VERSION_1_10_0, ext_zve64f),
73
43
ISA_EXT_DATA_ENTRY(zve64d, PRIV_VERSION_1_10_0, ext_zve64d),
74
- switch (irq) {
44
ISA_EXT_DATA_ENTRY(zvfbfmin, PRIV_VERSION_1_12_0, ext_zvfbfmin),
75
- case IRQ_U_SOFT:
45
@@ -XXX,XX +XXX,XX @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
76
- case IRQ_S_SOFT:
46
MULTI_EXT_CFG_BOOL("zfh", ext_zfh, false),
77
- case IRQ_VS_SOFT:
47
MULTI_EXT_CFG_BOOL("zfhmin", ext_zfhmin, false),
78
- case IRQ_M_SOFT:
48
MULTI_EXT_CFG_BOOL("zve32f", ext_zve32f, false),
79
- case IRQ_U_TIMER:
49
+ MULTI_EXT_CFG_BOOL("zve32x", ext_zve32x, false),
80
- case IRQ_S_TIMER:
50
MULTI_EXT_CFG_BOOL("zve64f", ext_zve64f, false),
81
- case IRQ_VS_TIMER:
51
MULTI_EXT_CFG_BOOL("zve64d", ext_zve64d, false),
82
- case IRQ_M_TIMER:
52
MULTI_EXT_CFG_BOOL("zvfbfmin", ext_zvfbfmin, false),
83
- case IRQ_U_EXT:
84
- case IRQ_S_EXT:
85
- case IRQ_VS_EXT:
86
- case IRQ_M_EXT:
87
- if (kvm_enabled()) {
88
- kvm_riscv_set_irq(cpu, irq, level);
89
- } else {
90
- riscv_cpu_update_mip(cpu, 1 << irq, BOOL_TO_MASK(level));
91
+ if (irq < IRQ_LOCAL_MAX) {
92
+ switch (irq) {
93
+ case IRQ_U_SOFT:
94
+ case IRQ_S_SOFT:
95
+ case IRQ_VS_SOFT:
96
+ case IRQ_M_SOFT:
97
+ case IRQ_U_TIMER:
98
+ case IRQ_S_TIMER:
99
+ case IRQ_VS_TIMER:
100
+ case IRQ_M_TIMER:
101
+ case IRQ_U_EXT:
102
+ case IRQ_S_EXT:
103
+ case IRQ_VS_EXT:
104
+ case IRQ_M_EXT:
105
+ if (kvm_enabled()) {
106
+ kvm_riscv_set_irq(cpu, irq, level);
107
+ } else {
108
+ riscv_cpu_update_mip(cpu, 1 << irq, BOOL_TO_MASK(level));
109
+ }
110
+ break;
111
+ default:
112
+ g_assert_not_reached();
113
}
114
- break;
115
- default:
116
+ } else if (irq < (IRQ_LOCAL_MAX + IRQ_LOCAL_GUEST_MAX)) {
117
+ /* Require H-extension for handling guest local interrupts */
118
+ if (!riscv_has_ext(env, RVH)) {
119
+ g_assert_not_reached();
120
+ }
121
+
122
+ /* Compute bit position in HGEIP CSR */
123
+ irq = irq - IRQ_LOCAL_MAX + 1;
124
+ if (env->geilen < irq) {
125
+ g_assert_not_reached();
126
+ }
127
+
128
+ /* Update HGEIP CSR */
129
+ env->hgeip &= ~((target_ulong)1 << irq);
130
+ if (level) {
131
+ env->hgeip |= (target_ulong)1 << irq;
132
+ }
133
+
134
+ /* Update mip.SGEIP bit */
135
+ riscv_cpu_update_mip(cpu, MIP_SGEIP,
136
+ BOOL_TO_MASK(!!(env->hgeie & env->hgeip)));
137
+ } else {
138
g_assert_not_reached();
139
}
140
}
141
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_init(Object *obj)
142
cpu_set_cpustate_pointers(cpu);
143
144
#ifndef CONFIG_USER_ONLY
145
- qdev_init_gpio_in(DEVICE(cpu), riscv_cpu_set_irq, IRQ_LOCAL_MAX);
146
+ qdev_init_gpio_in(DEVICE(cpu), riscv_cpu_set_irq,
147
+ IRQ_LOCAL_MAX + IRQ_LOCAL_GUEST_MAX);
148
#endif /* CONFIG_USER_ONLY */
149
}
150
53
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
151
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
54
index XXXXXXX..XXXXXXX 100644
152
index XXXXXXX..XXXXXXX 100644
55
--- a/target/riscv/cpu_helper.c
153
--- a/target/riscv/cpu_helper.c
56
+++ b/target/riscv/cpu_helper.c
154
+++ b/target/riscv/cpu_helper.c
57
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
155
@@ -XXX,XX +XXX,XX @@ static int riscv_cpu_local_irq_pending(CPURISCVState *env)
58
*pc = env->xl == MXL_RV32 ? env->pc & UINT32_MAX : env->pc;
156
target_ulong mstatus_mie = get_field(env->mstatus, MSTATUS_MIE);
59
*cs_base = 0;
157
target_ulong mstatus_sie = get_field(env->mstatus, MSTATUS_SIE);
60
158
61
- if (cpu->cfg.ext_zve32f) {
159
- target_ulong pending = env->mip & env->mie;
62
+ if (cpu->cfg.ext_zve32x) {
160
+ target_ulong vsgemask =
63
/*
161
+ (target_ulong)1 << get_field(env->hstatus, HSTATUS_VGEIN);
64
* If env->vl equals to VLMAX, we can use generic vector operation
162
+ target_ulong vsgein = (env->hgeip & vsgemask) ? MIP_VSEIP : 0;
65
* expanders (GVEC) to accerlate the vector operations.
163
+
164
+ target_ulong pending = (env->mip | vsgein) & env->mie;
165
166
target_ulong mie = env->priv < PRV_M ||
167
(env->priv == PRV_M && mstatus_mie);
168
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env)
169
}
170
}
171
172
+target_ulong riscv_cpu_get_geilen(CPURISCVState *env)
173
+{
174
+ if (!riscv_has_ext(env, RVH)) {
175
+ return 0;
176
+ }
177
+
178
+ return env->geilen;
179
+}
180
+
181
+void riscv_cpu_set_geilen(CPURISCVState *env, target_ulong geilen)
182
+{
183
+ if (!riscv_has_ext(env, RVH)) {
184
+ return;
185
+ }
186
+
187
+ if (geilen > (TARGET_LONG_BITS - 1)) {
188
+ return;
189
+ }
190
+
191
+ env->geilen = geilen;
192
+}
193
+
194
bool riscv_cpu_virt_enabled(CPURISCVState *env)
195
{
196
if (!riscv_has_ext(env, RVH)) {
197
@@ -XXX,XX +XXX,XX @@ uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value)
198
{
199
CPURISCVState *env = &cpu->env;
200
CPUState *cs = CPU(cpu);
201
- uint32_t old = env->mip;
202
+ uint32_t gein, vsgein = 0, old = env->mip;
203
bool locked = false;
204
205
+ if (riscv_cpu_virt_enabled(env)) {
206
+ gein = get_field(env->hstatus, HSTATUS_VGEIN);
207
+ vsgein = (env->hgeip & (1ULL << gein)) ? MIP_VSEIP : 0;
208
+ }
209
+
210
if (!qemu_mutex_iothread_locked()) {
211
locked = true;
212
qemu_mutex_lock_iothread();
213
@@ -XXX,XX +XXX,XX @@ uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value)
214
215
env->mip = (env->mip & ~mask) | (value & mask);
216
217
- if (env->mip) {
218
+ if (env->mip | vsgein) {
219
cpu_interrupt(cs, CPU_INTERRUPT_HARD);
220
} else {
221
cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
66
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
222
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
67
index XXXXXXX..XXXXXXX 100644
223
index XXXXXXX..XXXXXXX 100644
68
--- a/target/riscv/csr.c
224
--- a/target/riscv/csr.c
69
+++ b/target/riscv/csr.c
225
+++ b/target/riscv/csr.c
70
@@ -XXX,XX +XXX,XX @@ static RISCVException fs(CPURISCVState *env, int csrno)
226
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_mip(CPURISCVState *env, int csrno,
71
227
RISCVCPU *cpu = env_archcpu(env);
72
static RISCVException vs(CPURISCVState *env, int csrno)
228
/* Allow software control of delegable interrupts not claimed by hardware */
73
{
229
target_ulong mask = write_mask & delegable_ints & ~env->miclaim;
74
- if (riscv_cpu_cfg(env)->ext_zve32f) {
230
- uint32_t old_mip;
75
+ if (riscv_cpu_cfg(env)->ext_zve32x) {
231
+ uint32_t gin, old_mip;
76
#if !defined(CONFIG_USER_ONLY)
232
77
if (!env->debugger && !riscv_cpu_vector_enabled(env)) {
233
if (mask) {
78
return RISCV_EXCP_ILLEGAL_INST;
234
old_mip = riscv_cpu_update_mip(cpu, mask, (new_value & mask));
79
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
235
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_mip(CPURISCVState *env, int csrno,
80
index XXXXXXX..XXXXXXX 100644
236
old_mip = env->mip;
81
--- a/target/riscv/tcg/tcg-cpu.c
237
}
82
+++ b/target/riscv/tcg/tcg-cpu.c
238
83
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
239
+ if (csrno != CSR_HVIP) {
84
return;
240
+ gin = get_field(env->hstatus, HSTATUS_VGEIN);
85
}
241
+ old_mip |= (env->hgeip & ((target_ulong)1 << gin)) ? MIP_VSEIP : 0;
86
242
+ }
87
- if (cpu->cfg.ext_zve32f && !riscv_has_ext(env, RVF)) {
243
+
88
- error_setg(errp, "Zve32f/Zve64f extensions require F extension");
244
if (ret_value) {
89
- return;
245
*ret_value = old_mip;
90
+ /* The Zve32f extension depends on the Zve32x extension */
246
}
91
+ if (cpu->cfg.ext_zve32f) {
247
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_vsip(CPURISCVState *env, int csrno,
92
+ if (!riscv_has_ext(env, RVF)) {
248
target_ulong new_value, target_ulong write_mask)
93
+ error_setg(errp, "Zve32f/Zve64f extensions require F extension");
249
{
94
+ return;
250
/* Shift the S bits to their VS bit location in mip */
95
+ }
251
- int ret = rmw_mip(env, 0, ret_value, new_value << 1,
96
+ cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve32x), true);
252
+ int ret = rmw_mip(env, csrno, ret_value, new_value << 1,
97
}
253
(write_mask << 1) & vsip_writable_mask & env->hideleg);
98
254
99
if (cpu->cfg.ext_zvfh) {
255
if (ret_value) {
100
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
256
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_sip(CPURISCVState *env, int csrno,
101
cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvbc), true);
257
if (riscv_cpu_virt_enabled(env)) {
102
}
258
ret = rmw_vsip(env, CSR_VSIP, ret_value, new_value, write_mask);
103
259
} else {
104
- /*
260
- ret = rmw_mip(env, CSR_MSTATUS, ret_value, new_value,
105
- * In principle Zve*x would also suffice here, were they supported
261
+ ret = rmw_mip(env, csrno, ret_value, new_value,
106
- * in qemu
262
write_mask & env->mideleg & sip_writable_mask);
107
- */
263
}
108
if ((cpu->cfg.ext_zvbb || cpu->cfg.ext_zvkb || cpu->cfg.ext_zvkg ||
264
109
cpu->cfg.ext_zvkned || cpu->cfg.ext_zvknha || cpu->cfg.ext_zvksed ||
265
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_hvip(CPURISCVState *env, int csrno,
110
- cpu->cfg.ext_zvksh) && !cpu->cfg.ext_zve32f) {
266
target_ulong *ret_value,
111
+ cpu->cfg.ext_zvksh) && !cpu->cfg.ext_zve32x) {
267
target_ulong new_value, target_ulong write_mask)
112
error_setg(errp,
268
{
113
"Vector crypto extensions require V or Zve* extensions");
269
- int ret = rmw_mip(env, 0, ret_value, new_value,
114
return;
270
+ int ret = rmw_mip(env, csrno, ret_value, new_value,
115
diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc
271
write_mask & hvip_writable_mask);
116
index XXXXXXX..XXXXXXX 100644
272
117
--- a/target/riscv/insn_trans/trans_rvv.c.inc
273
if (ret_value) {
118
+++ b/target/riscv/insn_trans/trans_rvv.c.inc
274
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_hip(CPURISCVState *env, int csrno,
119
@@ -XXX,XX +XXX,XX @@ static bool do_vsetvl(DisasContext *s, int rd, int rs1, TCGv s2)
275
target_ulong *ret_value,
120
{
276
target_ulong new_value, target_ulong write_mask)
121
TCGv s1, dst;
277
{
122
278
- int ret = rmw_mip(env, 0, ret_value, new_value,
123
- if (!require_rvv(s) || !s->cfg_ptr->ext_zve32f) {
279
+ int ret = rmw_mip(env, csrno, ret_value, new_value,
124
+ if (!require_rvv(s) || !s->cfg_ptr->ext_zve32x) {
280
write_mask & hip_writable_mask);
125
return false;
281
126
}
282
if (ret_value) {
127
283
@@ -XXX,XX +XXX,XX @@ static RISCVException write_hcounteren(CPURISCVState *env, int csrno,
128
@@ -XXX,XX +XXX,XX @@ static bool do_vsetivli(DisasContext *s, int rd, TCGv s1, TCGv s2)
284
return RISCV_EXCP_NONE;
129
{
285
}
130
TCGv dst;
286
131
287
-static RISCVException write_hgeie(CPURISCVState *env, int csrno,
132
- if (!require_rvv(s) || !s->cfg_ptr->ext_zve32f) {
288
- target_ulong val)
133
+ if (!require_rvv(s) || !s->cfg_ptr->ext_zve32x) {
289
+static RISCVException read_hgeie(CPURISCVState *env, int csrno,
134
return false;
290
+ target_ulong *val)
135
}
291
{
136
292
if (val) {
293
- qemu_log_mask(LOG_UNIMP, "No support for a non-zero GEILEN.");
294
+ *val = env->hgeie;
295
}
296
return RISCV_EXCP_NONE;
297
}
298
299
+static RISCVException write_hgeie(CPURISCVState *env, int csrno,
300
+ target_ulong val)
301
+{
302
+ /* Only GEILEN:1 bits implemented and BIT0 is never implemented */
303
+ val &= ((((target_ulong)1) << env->geilen) - 1) << 1;
304
+ env->hgeie = val;
305
+ /* Update mip.SGEIP bit */
306
+ riscv_cpu_update_mip(env_archcpu(env), MIP_SGEIP,
307
+ BOOL_TO_MASK(!!(env->hgeie & env->hgeip)));
308
+ return RISCV_EXCP_NONE;
309
+}
310
+
311
static RISCVException read_htval(CPURISCVState *env, int csrno,
312
target_ulong *val)
313
{
314
@@ -XXX,XX +XXX,XX @@ static RISCVException write_htinst(CPURISCVState *env, int csrno,
315
return RISCV_EXCP_NONE;
316
}
317
318
-static RISCVException write_hgeip(CPURISCVState *env, int csrno,
319
- target_ulong val)
320
+static RISCVException read_hgeip(CPURISCVState *env, int csrno,
321
+ target_ulong *val)
322
{
323
if (val) {
324
- qemu_log_mask(LOG_UNIMP, "No support for a non-zero GEILEN.");
325
+ *val = env->hgeip;
326
}
327
return RISCV_EXCP_NONE;
328
}
329
@@ -XXX,XX +XXX,XX @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
330
[CSR_HIP] = { "hip", hmode, NULL, NULL, rmw_hip },
331
[CSR_HIE] = { "hie", hmode, read_hie, write_hie },
332
[CSR_HCOUNTEREN] = { "hcounteren", hmode, read_hcounteren, write_hcounteren },
333
- [CSR_HGEIE] = { "hgeie", hmode, read_zero, write_hgeie },
334
+ [CSR_HGEIE] = { "hgeie", hmode, read_hgeie, write_hgeie },
335
[CSR_HTVAL] = { "htval", hmode, read_htval, write_htval },
336
[CSR_HTINST] = { "htinst", hmode, read_htinst, write_htinst },
337
- [CSR_HGEIP] = { "hgeip", hmode, read_zero, write_hgeip },
338
+ [CSR_HGEIP] = { "hgeip", hmode, read_hgeip, NULL },
339
[CSR_HGATP] = { "hgatp", hmode, read_hgatp, write_hgatp },
340
[CSR_HTIMEDELTA] = { "htimedelta", hmode, read_htimedelta, write_htimedelta },
341
[CSR_HTIMEDELTAH] = { "htimedeltah", hmode32, read_htimedeltah, write_htimedeltah },
342
diff --git a/target/riscv/machine.c b/target/riscv/machine.c
343
index XXXXXXX..XXXXXXX 100644
344
--- a/target/riscv/machine.c
345
+++ b/target/riscv/machine.c
346
@@ -XXX,XX +XXX,XX @@ static bool hyper_needed(void *opaque)
347
348
static const VMStateDescription vmstate_hyper = {
349
.name = "cpu/hyper",
350
- .version_id = 1,
351
- .minimum_version_id = 1,
352
+ .version_id = 2,
353
+ .minimum_version_id = 2,
354
.needed = hyper_needed,
355
.fields = (VMStateField[]) {
356
VMSTATE_UINTTL(env.hstatus, RISCVCPU),
357
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_hyper = {
358
VMSTATE_UINTTL(env.htval, RISCVCPU),
359
VMSTATE_UINTTL(env.htinst, RISCVCPU),
360
VMSTATE_UINTTL(env.hgatp, RISCVCPU),
361
+ VMSTATE_UINTTL(env.hgeie, RISCVCPU),
362
+ VMSTATE_UINTTL(env.hgeip, RISCVCPU),
363
VMSTATE_UINT64(env.htimedelta, RISCVCPU),
364
365
VMSTATE_UINT64(env.vsstatus, RISCVCPU),
137
--
366
--
138
2.45.1
367
2.34.1
368
369
diff view generated by jsdifflib
1
From: Alexei Filippov <alexei.filippov@syntacore.com>
1
From: Anup Patel <anup.patel@wdc.com>
2
2
3
Previous patch fixed the PMP priority in raise_mmu_exception() but we're still
3
The guest external interrupts from an interrupt controller are
4
setting mtval2 incorrectly. In riscv_cpu_tlb_fill(), after pmp check in 2 stage
4
delivered only when the Guest/VM is running (i.e. V=1). This means
5
translation part, mtval2 will be set in case of successes 2 stage translation but
5
any guest external interrupt which is triggered while the Guest/VM
6
failed pmp check.
6
is not running (i.e. V=0) will be missed on QEMU resulting in Guest
7
with sluggish response to serial console input and other I/O events.
7
8
8
In this case we gonna set mtval2 via env->guest_phys_fault_addr in context of
9
To solve this, we check and inject interrupt after setting V=1.
9
riscv_cpu_tlb_fill(), as this was a guest-page-fault, but it didn't and mtval2
10
should be zero, according to RISCV privileged spec sect. 9.4.4: When a guest
11
page-fault is taken into M-mode, mtval2 is written with either zero or guest
12
physical address that faulted, shifted by 2 bits. *For other traps, mtval2
13
is set to zero...*
14
10
15
Signed-off-by: Alexei Filippov <alexei.filippov@syntacore.com>
11
Signed-off-by: Anup Patel <anup.patel@wdc.com>
16
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
12
Signed-off-by: Anup Patel <anup@brainfault.org>
17
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
13
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
18
Message-ID: <20240503103052.6819-1-alexei.filippov@syntacore.com>
14
Reviewed-by: Frank Chang <frank.chang@sifive.com>
19
Cc: qemu-stable <qemu-stable@nongnu.org>
15
Message-id: 20220204174700.534953-5-anup@brainfault.org
20
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
16
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
21
---
17
---
22
target/riscv/cpu_helper.c | 12 ++++++------
18
target/riscv/cpu_helper.c | 13 +++++++++++++
23
1 file changed, 6 insertions(+), 6 deletions(-)
19
1 file changed, 13 insertions(+)
24
20
25
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
21
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
26
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
27
--- a/target/riscv/cpu_helper.c
23
--- a/target/riscv/cpu_helper.c
28
+++ b/target/riscv/cpu_helper.c
24
+++ b/target/riscv/cpu_helper.c
29
@@ -XXX,XX +XXX,XX @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
25
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable)
30
__func__, pa, ret, prot_pmp, tlb_size);
26
}
31
27
32
prot &= prot_pmp;
28
env->virt = set_field(env->virt, VIRT_ONOFF, enable);
33
- }
29
+
34
-
30
+ if (enable) {
35
- if (ret != TRANSLATE_SUCCESS) {
31
+ /*
36
+ } else {
32
+ * The guest external interrupts from an interrupt controller are
37
/*
33
+ * delivered only when the Guest/VM is running (i.e. V=1). This means
38
* Guest physical address translation failed, this is a HS
34
+ * any guest external interrupt which is triggered while the Guest/VM
39
* level exception
35
+ * is not running (i.e. V=0) will be missed on QEMU resulting in guest
40
*/
36
+ * with sluggish response to serial console input and other I/O events.
41
first_stage_error = false;
37
+ *
42
- env->guest_phys_fault_addr = (im_address |
38
+ * To solve this, we check and inject interrupt after setting V=1.
43
- (address &
39
+ */
44
- (TARGET_PAGE_SIZE - 1))) >> 2;
40
+ riscv_cpu_update_mip(env_archcpu(env), 0, 0);
45
+ if (ret != TRANSLATE_PMP_FAIL) {
41
+ }
46
+ env->guest_phys_fault_addr = (im_address |
42
}
47
+ (address &
43
48
+ (TARGET_PAGE_SIZE - 1))) >> 2;
44
bool riscv_cpu_two_stage_lookup(int mmu_idx)
49
+ }
50
}
51
}
52
} else {
53
--
45
--
54
2.45.1
46
2.34.1
47
48
diff view generated by jsdifflib
1
From: Jason Chien <jason.chien@sifive.com>
1
From: Anup Patel <anup.patel@wdc.com>
2
2
3
Add support for Zve64x extension. Enabling Zve64f enables Zve64x and
3
The machine or device emulation should be able to force set certain
4
enabling Zve64x enables Zve32x according to their dependency.
4
CPU features because:
5
1) We can have certain CPU features which are in-general optional
6
but implemented by RISC-V CPUs on the machine.
7
2) We can have devices which require a certain CPU feature. For example,
8
AIA IMSIC devices expect AIA CSRs implemented by RISC-V CPUs.
5
9
6
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2107
10
Signed-off-by: Anup Patel <anup.patel@wdc.com>
7
Signed-off-by: Jason Chien <jason.chien@sifive.com>
11
Signed-off-by: Anup Patel <anup@brainfault.org>
12
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
13
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Reviewed-by: Frank Chang <frank.chang@sifive.com>
14
Reviewed-by: Frank Chang <frank.chang@sifive.com>
9
Reviewed-by: Max Chou <max.chou@sifive.com>
15
Message-id: 20220204174700.534953-6-anup@brainfault.org
10
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
11
Message-ID: <20240328022343.6871-3-jason.chien@sifive.com>
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
16
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
13
---
17
---
14
target/riscv/cpu_cfg.h | 1 +
18
target/riscv/cpu.h | 5 +++++
15
target/riscv/cpu.c | 2 ++
19
target/riscv/cpu.c | 11 +++--------
16
target/riscv/tcg/tcg-cpu.c | 17 +++++++++++------
20
2 files changed, 8 insertions(+), 8 deletions(-)
17
3 files changed, 14 insertions(+), 6 deletions(-)
18
21
19
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
22
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
20
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
21
--- a/target/riscv/cpu_cfg.h
24
--- a/target/riscv/cpu.h
22
+++ b/target/riscv/cpu_cfg.h
25
+++ b/target/riscv/cpu.h
23
@@ -XXX,XX +XXX,XX @@ struct RISCVCPUConfig {
26
@@ -XXX,XX +XXX,XX @@ static inline bool riscv_feature(CPURISCVState *env, int feature)
24
bool ext_zve32x;
27
return env->features & (1ULL << feature);
25
bool ext_zve64f;
28
}
26
bool ext_zve64d;
29
27
+ bool ext_zve64x;
30
+static inline void riscv_set_feature(CPURISCVState *env, int feature)
28
bool ext_zvbb;
31
+{
29
bool ext_zvbc;
32
+ env->features |= (1ULL << feature);
30
bool ext_zvkb;
33
+}
34
+
35
#include "cpu_user.h"
36
37
extern const char * const riscv_int_regnames[];
31
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
38
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
32
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
33
--- a/target/riscv/cpu.c
40
--- a/target/riscv/cpu.c
34
+++ b/target/riscv/cpu.c
41
+++ b/target/riscv/cpu.c
35
@@ -XXX,XX +XXX,XX @@ const RISCVIsaExtData isa_edata_arr[] = {
42
@@ -XXX,XX +XXX,XX @@ static void set_vext_version(CPURISCVState *env, int vext_ver)
36
ISA_EXT_DATA_ENTRY(zve32x, PRIV_VERSION_1_10_0, ext_zve32x),
43
env->vext_ver = vext_ver;
37
ISA_EXT_DATA_ENTRY(zve64f, PRIV_VERSION_1_10_0, ext_zve64f),
44
}
38
ISA_EXT_DATA_ENTRY(zve64d, PRIV_VERSION_1_10_0, ext_zve64d),
45
39
+ ISA_EXT_DATA_ENTRY(zve64x, PRIV_VERSION_1_10_0, ext_zve64x),
46
-static void set_feature(CPURISCVState *env, int feature)
40
ISA_EXT_DATA_ENTRY(zvfbfmin, PRIV_VERSION_1_12_0, ext_zvfbfmin),
47
-{
41
ISA_EXT_DATA_ENTRY(zvfbfwma, PRIV_VERSION_1_12_0, ext_zvfbfwma),
48
- env->features |= (1ULL << feature);
42
ISA_EXT_DATA_ENTRY(zvfh, PRIV_VERSION_1_12_0, ext_zvfh),
49
-}
43
@@ -XXX,XX +XXX,XX @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
50
-
44
MULTI_EXT_CFG_BOOL("zve32x", ext_zve32x, false),
51
static void set_resetvec(CPURISCVState *env, target_ulong resetvec)
45
MULTI_EXT_CFG_BOOL("zve64f", ext_zve64f, false),
52
{
46
MULTI_EXT_CFG_BOOL("zve64d", ext_zve64d, false),
53
#ifndef CONFIG_USER_ONLY
47
+ MULTI_EXT_CFG_BOOL("zve64x", ext_zve64x, false),
54
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
48
MULTI_EXT_CFG_BOOL("zvfbfmin", ext_zvfbfmin, false),
49
MULTI_EXT_CFG_BOOL("zvfbfwma", ext_zvfbfwma, false),
50
MULTI_EXT_CFG_BOOL("zvfh", ext_zvfh, false),
51
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/riscv/tcg/tcg-cpu.c
54
+++ b/target/riscv/tcg/tcg-cpu.c
55
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
56
57
/* The Zve64d extension depends on the Zve64f extension */
58
if (cpu->cfg.ext_zve64d) {
59
+ if (!riscv_has_ext(env, RVD)) {
60
+ error_setg(errp, "Zve64d/V extensions require D extension");
61
+ return;
62
+ }
63
cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve64f), true);
64
}
55
}
65
56
66
- /* The Zve64f extension depends on the Zve32f extension */
57
if (cpu->cfg.mmu) {
67
+ /* The Zve64f extension depends on the Zve64x and Zve32f extensions */
58
- set_feature(env, RISCV_FEATURE_MMU);
68
if (cpu->cfg.ext_zve64f) {
59
+ riscv_set_feature(env, RISCV_FEATURE_MMU);
69
+ cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve64x), true);
70
cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve32f), true);
71
}
60
}
72
61
73
- if (cpu->cfg.ext_zve64d && !riscv_has_ext(env, RVD)) {
62
if (cpu->cfg.pmp) {
74
- error_setg(errp, "Zve64d/V extensions require D extension");
63
- set_feature(env, RISCV_FEATURE_PMP);
75
- return;
64
+ riscv_set_feature(env, RISCV_FEATURE_PMP);
76
+ /* The Zve64x extension depends on the Zve32x extension */
65
77
+ if (cpu->cfg.ext_zve64x) {
66
/*
78
+ cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve32x), true);
67
* Enhanced PMP should only be available
68
* on harts with PMP support
69
*/
70
if (cpu->cfg.epmp) {
71
- set_feature(env, RISCV_FEATURE_EPMP);
72
+ riscv_set_feature(env, RISCV_FEATURE_EPMP);
73
}
79
}
74
}
80
75
81
/* The Zve32f extension depends on the Zve32x extension */
82
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
83
return;
84
}
85
86
- if ((cpu->cfg.ext_zvbc || cpu->cfg.ext_zvknhb) && !cpu->cfg.ext_zve64f) {
87
+ if ((cpu->cfg.ext_zvbc || cpu->cfg.ext_zvknhb) && !cpu->cfg.ext_zve64x) {
88
error_setg(
89
errp,
90
- "Zvbc and Zvknhb extensions require V or Zve64{f,d} extensions");
91
+ "Zvbc and Zvknhb extensions require V or Zve64x extensions");
92
return;
93
}
94
95
--
76
--
96
2.45.1
77
2.34.1
78
79
diff view generated by jsdifflib
New patch
1
From: Anup Patel <anup.patel@wdc.com>
1
2
3
We define a CPU feature for AIA CSR support in RISC-V CPUs which
4
can be set by machine/device emulation. The RISC-V CSR emulation
5
will also check this feature for emulating AIA CSRs.
6
7
Signed-off-by: Anup Patel <anup.patel@wdc.com>
8
Signed-off-by: Anup Patel <anup@brainfault.org>
9
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
10
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
11
Reviewed-by: Frank Chang <frank.chang@sifive.com>
12
Message-id: 20220204174700.534953-7-anup@brainfault.org
13
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
14
---
15
target/riscv/cpu.h | 3 ++-
16
1 file changed, 2 insertions(+), 1 deletion(-)
17
18
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/riscv/cpu.h
21
+++ b/target/riscv/cpu.h
22
@@ -XXX,XX +XXX,XX @@ enum {
23
RISCV_FEATURE_MMU,
24
RISCV_FEATURE_PMP,
25
RISCV_FEATURE_EPMP,
26
- RISCV_FEATURE_MISA
27
+ RISCV_FEATURE_MISA,
28
+ RISCV_FEATURE_AIA
29
};
30
31
#define PRIV_VERSION_1_10_0 0x00011000
32
--
33
2.34.1
34
35
diff view generated by jsdifflib
1
From: Clément Léger <cleger@rivosinc.com>
1
From: Anup Patel <anup.patel@wdc.com>
2
2
3
The current semihost exception number (16) is a reserved number (range
3
The RISC-V AIA specification extends RISC-V local interrupts and
4
[16-17]). The upcoming double trap specification uses that number for
4
introduces new CSRs. This patch adds defines for the new AIA CSRs.
5
the double trap exception. Since the privileged spec (Table 22) defines
6
ranges for custom uses change the semihosting exception number to 63
7
which belongs to the range [48-63] in order to avoid any future
8
collisions with reserved exception.
9
5
10
Signed-off-by: Clément Léger <cleger@rivosinc.com>
6
Signed-off-by: Anup Patel <anup.patel@wdc.com>
11
7
Signed-off-by: Anup Patel <anup@brainfault.org>
12
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
13
Message-ID: <20240422135840.1959967-1-cleger@rivosinc.com>
9
Reviewed-by: Frank Chang <frank.chang@sifive.com>
10
Message-id: 20220204174700.534953-8-anup@brainfault.org
14
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
15
---
12
---
16
target/riscv/cpu_bits.h | 2 +-
13
target/riscv/cpu_bits.h | 119 ++++++++++++++++++++++++++++++++++++++++
17
1 file changed, 1 insertion(+), 1 deletion(-)
14
1 file changed, 119 insertions(+)
18
15
19
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
16
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
20
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
21
--- a/target/riscv/cpu_bits.h
18
--- a/target/riscv/cpu_bits.h
22
+++ b/target/riscv/cpu_bits.h
19
+++ b/target/riscv/cpu_bits.h
20
@@ -XXX,XX +XXX,XX @@
21
#define CSR_MTVAL 0x343
22
#define CSR_MIP 0x344
23
24
+/* Machine-Level Window to Indirectly Accessed Registers (AIA) */
25
+#define CSR_MISELECT 0x350
26
+#define CSR_MIREG 0x351
27
+
28
+/* Machine-Level Interrupts (AIA) */
29
+#define CSR_MTOPI 0xfb0
30
+
31
+/* Machine-Level IMSIC Interface (AIA) */
32
+#define CSR_MSETEIPNUM 0x358
33
+#define CSR_MCLREIPNUM 0x359
34
+#define CSR_MSETEIENUM 0x35a
35
+#define CSR_MCLREIENUM 0x35b
36
+#define CSR_MTOPEI 0x35c
37
+
38
+/* Virtual Interrupts for Supervisor Level (AIA) */
39
+#define CSR_MVIEN 0x308
40
+#define CSR_MVIP 0x309
41
+
42
+/* Machine-Level High-Half CSRs (AIA) */
43
+#define CSR_MIDELEGH 0x313
44
+#define CSR_MIEH 0x314
45
+#define CSR_MVIENH 0x318
46
+#define CSR_MVIPH 0x319
47
+#define CSR_MIPH 0x354
48
+
49
/* Supervisor Trap Setup */
50
#define CSR_SSTATUS 0x100
51
#define CSR_SEDELEG 0x102
52
@@ -XXX,XX +XXX,XX @@
53
#define CSR_SPTBR 0x180
54
#define CSR_SATP 0x180
55
56
+/* Supervisor-Level Window to Indirectly Accessed Registers (AIA) */
57
+#define CSR_SISELECT 0x150
58
+#define CSR_SIREG 0x151
59
+
60
+/* Supervisor-Level Interrupts (AIA) */
61
+#define CSR_STOPI 0xdb0
62
+
63
+/* Supervisor-Level IMSIC Interface (AIA) */
64
+#define CSR_SSETEIPNUM 0x158
65
+#define CSR_SCLREIPNUM 0x159
66
+#define CSR_SSETEIENUM 0x15a
67
+#define CSR_SCLREIENUM 0x15b
68
+#define CSR_STOPEI 0x15c
69
+
70
+/* Supervisor-Level High-Half CSRs (AIA) */
71
+#define CSR_SIEH 0x114
72
+#define CSR_SIPH 0x154
73
+
74
/* Hpervisor CSRs */
75
#define CSR_HSTATUS 0x600
76
#define CSR_HEDELEG 0x602
77
@@ -XXX,XX +XXX,XX @@
78
#define CSR_MTINST 0x34a
79
#define CSR_MTVAL2 0x34b
80
81
+/* Virtual Interrupts and Interrupt Priorities (H-extension with AIA) */
82
+#define CSR_HVIEN 0x608
83
+#define CSR_HVICTL 0x609
84
+#define CSR_HVIPRIO1 0x646
85
+#define CSR_HVIPRIO2 0x647
86
+
87
+/* VS-Level Window to Indirectly Accessed Registers (H-extension with AIA) */
88
+#define CSR_VSISELECT 0x250
89
+#define CSR_VSIREG 0x251
90
+
91
+/* VS-Level Interrupts (H-extension with AIA) */
92
+#define CSR_VSTOPI 0xeb0
93
+
94
+/* VS-Level IMSIC Interface (H-extension with AIA) */
95
+#define CSR_VSSETEIPNUM 0x258
96
+#define CSR_VSCLREIPNUM 0x259
97
+#define CSR_VSSETEIENUM 0x25a
98
+#define CSR_VSCLREIENUM 0x25b
99
+#define CSR_VSTOPEI 0x25c
100
+
101
+/* Hypervisor and VS-Level High-Half CSRs (H-extension with AIA) */
102
+#define CSR_HIDELEGH 0x613
103
+#define CSR_HVIENH 0x618
104
+#define CSR_HVIPH 0x655
105
+#define CSR_HVIPRIO1H 0x656
106
+#define CSR_HVIPRIO2H 0x657
107
+#define CSR_VSIEH 0x214
108
+#define CSR_VSIPH 0x254
109
+
110
/* Enhanced Physical Memory Protection (ePMP) */
111
#define CSR_MSECCFG 0x747
112
#define CSR_MSECCFGH 0x757
23
@@ -XXX,XX +XXX,XX @@ typedef enum RISCVException {
113
@@ -XXX,XX +XXX,XX @@ typedef enum RISCVException {
24
RISCV_EXCP_INST_PAGE_FAULT = 0xc, /* since: priv-1.10.0 */
114
#define UMTE_U_PM_INSN U_PM_INSN
25
RISCV_EXCP_LOAD_PAGE_FAULT = 0xd, /* since: priv-1.10.0 */
115
#define UMTE_MASK (UMTE_U_PM_ENABLE | MMTE_U_PM_CURRENT | UMTE_U_PM_INSN)
26
RISCV_EXCP_STORE_PAGE_FAULT = 0xf, /* since: priv-1.10.0 */
116
27
- RISCV_EXCP_SEMIHOST = 0x10,
117
+/* MISELECT, SISELECT, and VSISELECT bits (AIA) */
28
RISCV_EXCP_INST_GUEST_PAGE_FAULT = 0x14,
118
+#define ISELECT_IPRIO0 0x30
29
RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT = 0x15,
119
+#define ISELECT_IPRIO15 0x3f
30
RISCV_EXCP_VIRT_INSTRUCTION_FAULT = 0x16,
120
+#define ISELECT_IMSIC_EIDELIVERY 0x70
31
RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT = 0x17,
121
+#define ISELECT_IMSIC_EITHRESHOLD 0x72
32
+ RISCV_EXCP_SEMIHOST = 0x3f,
122
+#define ISELECT_IMSIC_EIP0 0x80
33
} RISCVException;
123
+#define ISELECT_IMSIC_EIP63 0xbf
34
124
+#define ISELECT_IMSIC_EIE0 0xc0
35
#define RISCV_EXCP_INT_FLAG 0x80000000
125
+#define ISELECT_IMSIC_EIE63 0xff
126
+#define ISELECT_IMSIC_FIRST ISELECT_IMSIC_EIDELIVERY
127
+#define ISELECT_IMSIC_LAST ISELECT_IMSIC_EIE63
128
+#define ISELECT_MASK 0x1ff
129
+
130
+/* Dummy [M|S|VS]ISELECT value for emulating [M|S|VS]TOPEI CSRs */
131
+#define ISELECT_IMSIC_TOPEI (ISELECT_MASK + 1)
132
+
133
+/* IMSIC bits (AIA) */
134
+#define IMSIC_TOPEI_IID_SHIFT 16
135
+#define IMSIC_TOPEI_IID_MASK 0x7ff
136
+#define IMSIC_TOPEI_IPRIO_MASK 0x7ff
137
+#define IMSIC_EIPx_BITS 32
138
+#define IMSIC_EIEx_BITS 32
139
+
140
+/* MTOPI and STOPI bits (AIA) */
141
+#define TOPI_IID_SHIFT 16
142
+#define TOPI_IID_MASK 0xfff
143
+#define TOPI_IPRIO_MASK 0xff
144
+
145
+/* Interrupt priority bits (AIA) */
146
+#define IPRIO_IRQ_BITS 8
147
+#define IPRIO_MMAXIPRIO 255
148
+#define IPRIO_DEFAULT_UPPER 4
149
+#define IPRIO_DEFAULT_MIDDLE (IPRIO_DEFAULT_UPPER + 24)
150
+#define IPRIO_DEFAULT_M IPRIO_DEFAULT_MIDDLE
151
+#define IPRIO_DEFAULT_S (IPRIO_DEFAULT_M + 3)
152
+#define IPRIO_DEFAULT_SGEXT (IPRIO_DEFAULT_S + 3)
153
+#define IPRIO_DEFAULT_VS (IPRIO_DEFAULT_SGEXT + 1)
154
+#define IPRIO_DEFAULT_LOWER (IPRIO_DEFAULT_VS + 3)
155
+
156
+/* HVICTL bits (AIA) */
157
+#define HVICTL_VTI 0x40000000
158
+#define HVICTL_IID 0x0fff0000
159
+#define HVICTL_IPRIOM 0x00000100
160
+#define HVICTL_IPRIO 0x000000ff
161
+#define HVICTL_VALID_MASK \
162
+ (HVICTL_VTI | HVICTL_IID | HVICTL_IPRIOM | HVICTL_IPRIO)
163
+
164
#endif
36
--
165
--
37
2.45.1
166
2.34.1
38
167
39
168
diff view generated by jsdifflib
1
From: Andrew Jones <ajones@ventanamicro.com>
1
From: Anup Patel <anup.patel@wdc.com>
2
2
3
Implementing wrs.nto to always just return is consistent with the
3
The AIA device emulation (such as AIA IMSIC) should be able to set
4
specification, as the instruction is permitted to terminate the
4
(or provide) AIA ireg read-modify-write callback for each privilege
5
stall for any reason, but it's not useful for virtualization, where
5
level of a RISC-V HART.
6
we'd like the guest to trap to the hypervisor in order to allow
7
scheduling of the lock holding VCPU. Change to always immediately
8
raise exceptions when the appropriate conditions are present,
9
otherwise continue to just return. Note, immediately raising
10
exceptions is also consistent with the specification since the
11
time limit that should expire prior to the exception is
12
implementation-specific.
13
6
14
Signed-off-by: Andrew Jones <ajones@ventanamicro.com>
7
Signed-off-by: Anup Patel <anup.patel@wdc.com>
15
Reviewed-by: Christoph Müllner <christoph.muellner@vrull.eu>
8
Signed-off-by: Anup Patel <anup@brainfault.org>
16
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
17
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
18
Message-ID: <20240424142808.62936-2-ajones@ventanamicro.com>
10
Reviewed-by: Frank Chang <frank.chang@sifive.com>
11
Message-id: 20220204174700.534953-9-anup@brainfault.org
19
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
20
---
13
---
21
target/riscv/helper.h | 1 +
14
target/riscv/cpu.h | 23 +++++++++++++++++++++++
22
target/riscv/op_helper.c | 11 ++++++++
15
target/riscv/cpu_helper.c | 14 ++++++++++++++
23
target/riscv/insn_trans/trans_rvzawrs.c.inc | 29 ++++++++++++++-------
16
2 files changed, 37 insertions(+)
24
3 files changed, 32 insertions(+), 9 deletions(-)
25
17
26
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
18
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
27
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
28
--- a/target/riscv/helper.h
20
--- a/target/riscv/cpu.h
29
+++ b/target/riscv/helper.h
21
+++ b/target/riscv/cpu.h
30
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_6(csrrw_i128, tl, env, int, tl, tl, tl, tl)
22
@@ -XXX,XX +XXX,XX @@ struct CPURISCVState {
31
DEF_HELPER_1(sret, tl, env)
23
uint64_t (*rdtime_fn)(uint32_t);
32
DEF_HELPER_1(mret, tl, env)
24
uint32_t rdtime_fn_arg;
33
DEF_HELPER_1(wfi, void, env)
25
34
+DEF_HELPER_1(wrs_nto, void, env)
26
+ /* machine specific AIA ireg read-modify-write callback */
35
DEF_HELPER_1(tlb_flush, void, env)
27
+#define AIA_MAKE_IREG(__isel, __priv, __virt, __vgein, __xlen) \
36
DEF_HELPER_1(tlb_flush_all, void, env)
28
+ ((((__xlen) & 0xff) << 24) | \
37
/* Native Debug */
29
+ (((__vgein) & 0x3f) << 20) | \
38
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
30
+ (((__virt) & 0x1) << 18) | \
31
+ (((__priv) & 0x3) << 16) | \
32
+ (__isel & 0xffff))
33
+#define AIA_IREG_ISEL(__ireg) ((__ireg) & 0xffff)
34
+#define AIA_IREG_PRIV(__ireg) (((__ireg) >> 16) & 0x3)
35
+#define AIA_IREG_VIRT(__ireg) (((__ireg) >> 18) & 0x1)
36
+#define AIA_IREG_VGEIN(__ireg) (((__ireg) >> 20) & 0x3f)
37
+#define AIA_IREG_XLEN(__ireg) (((__ireg) >> 24) & 0xff)
38
+ int (*aia_ireg_rmw_fn[4])(void *arg, target_ulong reg,
39
+ target_ulong *val, target_ulong new_val, target_ulong write_mask);
40
+ void *aia_ireg_rmw_fn_arg[4];
41
+
42
/* True if in debugger mode. */
43
bool debugger;
44
45
@@ -XXX,XX +XXX,XX @@ uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value);
46
#define BOOL_TO_MASK(x) (-!!(x)) /* helper for riscv_cpu_update_mip value */
47
void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(uint32_t),
48
uint32_t arg);
49
+void riscv_cpu_set_aia_ireg_rmw_fn(CPURISCVState *env, uint32_t priv,
50
+ int (*rmw_fn)(void *arg,
51
+ target_ulong reg,
52
+ target_ulong *val,
53
+ target_ulong new_val,
54
+ target_ulong write_mask),
55
+ void *rmw_fn_arg);
56
#endif
57
void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv);
58
59
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
39
index XXXXXXX..XXXXXXX 100644
60
index XXXXXXX..XXXXXXX 100644
40
--- a/target/riscv/op_helper.c
61
--- a/target/riscv/cpu_helper.c
41
+++ b/target/riscv/op_helper.c
62
+++ b/target/riscv/cpu_helper.c
42
@@ -XXX,XX +XXX,XX @@ void helper_wfi(CPURISCVState *env)
63
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(uint32_t),
43
}
64
env->rdtime_fn_arg = arg;
44
}
65
}
45
66
46
+void helper_wrs_nto(CPURISCVState *env)
67
+void riscv_cpu_set_aia_ireg_rmw_fn(CPURISCVState *env, uint32_t priv,
68
+ int (*rmw_fn)(void *arg,
69
+ target_ulong reg,
70
+ target_ulong *val,
71
+ target_ulong new_val,
72
+ target_ulong write_mask),
73
+ void *rmw_fn_arg)
47
+{
74
+{
48
+ if (env->virt_enabled && (env->priv == PRV_S || env->priv == PRV_U) &&
75
+ if (priv <= PRV_M) {
49
+ get_field(env->hstatus, HSTATUS_VTW) &&
76
+ env->aia_ireg_rmw_fn[priv] = rmw_fn;
50
+ !get_field(env->mstatus, MSTATUS_TW)) {
77
+ env->aia_ireg_rmw_fn_arg[priv] = rmw_fn_arg;
51
+ riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC());
52
+ } else if (env->priv != PRV_M && get_field(env->mstatus, MSTATUS_TW)) {
53
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
54
+ }
78
+ }
55
+}
79
+}
56
+
80
+
57
void helper_tlb_flush(CPURISCVState *env)
81
void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv)
58
{
82
{
59
CPUState *cs = env_cpu(env);
83
if (newpriv > PRV_M) {
60
diff --git a/target/riscv/insn_trans/trans_rvzawrs.c.inc b/target/riscv/insn_trans/trans_rvzawrs.c.inc
61
index XXXXXXX..XXXXXXX 100644
62
--- a/target/riscv/insn_trans/trans_rvzawrs.c.inc
63
+++ b/target/riscv/insn_trans/trans_rvzawrs.c.inc
64
@@ -XXX,XX +XXX,XX @@
65
* this program. If not, see <http://www.gnu.org/licenses/>.
66
*/
67
68
-static bool trans_wrs(DisasContext *ctx)
69
+static bool trans_wrs_sto(DisasContext *ctx, arg_wrs_sto *a)
70
{
71
if (!ctx->cfg_ptr->ext_zawrs) {
72
return false;
73
@@ -XXX,XX +XXX,XX @@ static bool trans_wrs(DisasContext *ctx)
74
return true;
75
}
76
77
-#define GEN_TRANS_WRS(insn) \
78
-static bool trans_ ## insn(DisasContext *ctx, arg_ ## insn *a) \
79
-{ \
80
- (void)a; \
81
- return trans_wrs(ctx); \
82
-}
83
+static bool trans_wrs_nto(DisasContext *ctx, arg_wrs_nto *a)
84
+{
85
+ if (!ctx->cfg_ptr->ext_zawrs) {
86
+ return false;
87
+ }
88
89
-GEN_TRANS_WRS(wrs_nto)
90
-GEN_TRANS_WRS(wrs_sto)
91
+ /*
92
+ * Depending on the mode of execution, mstatus.TW and hstatus.VTW, wrs.nto
93
+ * should raise an exception when the implementation-specific bounded time
94
+ * limit has expired. Our time limit is zero, so we either return
95
+ * immediately, as does our implementation of wrs.sto, or raise an
96
+ * exception, as handled by the wrs.nto helper.
97
+ */
98
+#ifndef CONFIG_USER_ONLY
99
+ gen_helper_wrs_nto(tcg_env);
100
+#endif
101
+
102
+ /* We only get here when helper_wrs_nto() doesn't raise an exception. */
103
+ return trans_wrs_sto(ctx, NULL);
104
+}
105
--
84
--
106
2.45.1
85
2.34.1
107
86
108
87
diff view generated by jsdifflib
1
From: Huang Tao <eric.huang@linux.alibaba.com>
1
From: Anup Patel <anup.patel@wdc.com>
2
2
3
In RVV and vcrypto instructions, the masked and tail elements are set to 1s
3
The AIA spec defines programmable 8-bit priority for each local interrupt
4
using vext_set_elems_1s function if the vma/vta bit is set. It is the element
4
at M-level, S-level and VS-level so we extend local interrupt processing
5
agnostic policy.
5
to consider AIA interrupt priorities. The AIA CSRs which help software
6
configure local interrupt priorities will be added by subsequent patches.
6
7
7
However, this function can't deal the big endian situation. This patch fixes
8
Signed-off-by: Anup Patel <anup.patel@wdc.com>
8
the problem by adding handling of such case.
9
Signed-off-by: Anup Patel <anup@brainfault.org>
9
10
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Signed-off-by: Huang Tao <eric.huang@linux.alibaba.com>
11
Message-id: 20220204174700.534953-10-anup@brainfault.org
11
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
13
Cc: qemu-stable <qemu-stable@nongnu.org>
14
Message-ID: <20240325021654.6594-1-eric.huang@linux.alibaba.com>
15
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
16
---
13
---
17
target/riscv/vector_internals.c | 22 ++++++++++++++++++++++
14
target/riscv/cpu.h | 12 ++
18
1 file changed, 22 insertions(+)
15
target/riscv/cpu.c | 19 +++
16
target/riscv/cpu_helper.c | 281 +++++++++++++++++++++++++++++++++++---
17
target/riscv/machine.c | 3 +
18
4 files changed, 294 insertions(+), 21 deletions(-)
19
19
20
diff --git a/target/riscv/vector_internals.c b/target/riscv/vector_internals.c
20
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
21
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/riscv/vector_internals.c
22
--- a/target/riscv/cpu.h
23
+++ b/target/riscv/vector_internals.c
23
+++ b/target/riscv/cpu.h
24
@@ -XXX,XX +XXX,XX @@ void vext_set_elems_1s(void *base, uint32_t is_agnostic, uint32_t cnt,
24
@@ -XXX,XX +XXX,XX @@ struct CPURISCVState {
25
if (tot - cnt == 0) {
25
target_ulong mcause;
26
return ;
26
target_ulong mtval; /* since: priv-1.10.0 */
27
28
+ /* Machine and Supervisor interrupt priorities */
29
+ uint8_t miprio[64];
30
+ uint8_t siprio[64];
31
+
32
/* Hypervisor CSRs */
33
target_ulong hstatus;
34
target_ulong hedeleg;
35
@@ -XXX,XX +XXX,XX @@ struct CPURISCVState {
36
target_ulong hgeip;
37
uint64_t htimedelta;
38
39
+ /* Hypervisor controlled virtual interrupt priorities */
40
+ uint8_t hviprio[64];
41
+
42
/* Upper 64-bits of 128-bit CSRs */
43
uint64_t mscratchh;
44
uint64_t sscratchh;
45
@@ -XXX,XX +XXX,XX @@ int riscv_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
46
int cpuid, void *opaque);
47
int riscv_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
48
int riscv_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
49
+int riscv_cpu_hviprio_index2irq(int index, int *out_irq, int *out_rdzero);
50
+uint8_t riscv_cpu_default_priority(int irq);
51
+int riscv_cpu_mirq_pending(CPURISCVState *env);
52
+int riscv_cpu_sirq_pending(CPURISCVState *env);
53
+int riscv_cpu_vsirq_pending(CPURISCVState *env);
54
bool riscv_cpu_fp_enabled(CPURISCVState *env);
55
target_ulong riscv_cpu_get_geilen(CPURISCVState *env);
56
void riscv_cpu_set_geilen(CPURISCVState *env, target_ulong geilen);
57
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
58
index XXXXXXX..XXXXXXX 100644
59
--- a/target/riscv/cpu.c
60
+++ b/target/riscv/cpu.c
61
@@ -XXX,XX +XXX,XX @@ void restore_state_to_opc(CPURISCVState *env, TranslationBlock *tb,
62
63
static void riscv_cpu_reset(DeviceState *dev)
64
{
65
+#ifndef CONFIG_USER_ONLY
66
+ uint8_t iprio;
67
+ int i, irq, rdzero;
68
+#endif
69
CPUState *cs = CPU(dev);
70
RISCVCPU *cpu = RISCV_CPU(cs);
71
RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cpu);
72
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_reset(DeviceState *dev)
73
env->miclaim = MIP_SGEIP;
74
env->pc = env->resetvec;
75
env->two_stage_lookup = false;
76
+
77
+ /* Initialized default priorities of local interrupts. */
78
+ for (i = 0; i < ARRAY_SIZE(env->miprio); i++) {
79
+ iprio = riscv_cpu_default_priority(i);
80
+ env->miprio[i] = (i == IRQ_M_EXT) ? 0 : iprio;
81
+ env->siprio[i] = (i == IRQ_S_EXT) ? 0 : iprio;
82
+ env->hviprio[i] = 0;
83
+ }
84
+ i = 0;
85
+ while (!riscv_cpu_hviprio_index2irq(i, &irq, &rdzero)) {
86
+ if (!rdzero) {
87
+ env->hviprio[irq] = env->miprio[irq];
88
+ }
89
+ i++;
90
+ }
91
/* mmte is supposed to have pm.current hardwired to 1 */
92
env->mmte |= (PM_EXT_INITIAL | MMTE_M_PM_CURRENT);
93
#endif
94
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
95
index XXXXXXX..XXXXXXX 100644
96
--- a/target/riscv/cpu_helper.c
97
+++ b/target/riscv/cpu_helper.c
98
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_update_mask(CPURISCVState *env)
99
}
100
101
#ifndef CONFIG_USER_ONLY
102
-static int riscv_cpu_local_irq_pending(CPURISCVState *env)
103
+
104
+/*
105
+ * The HS-mode is allowed to configure priority only for the
106
+ * following VS-mode local interrupts:
107
+ *
108
+ * 0 (Reserved interrupt, reads as zero)
109
+ * 1 Supervisor software interrupt
110
+ * 4 (Reserved interrupt, reads as zero)
111
+ * 5 Supervisor timer interrupt
112
+ * 8 (Reserved interrupt, reads as zero)
113
+ * 13 (Reserved interrupt)
114
+ * 14 "
115
+ * 15 "
116
+ * 16 "
117
+ * 18 Debug/trace interrupt
118
+ * 20 (Reserved interrupt)
119
+ * 22 "
120
+ * 24 "
121
+ * 26 "
122
+ * 28 "
123
+ * 30 (Reserved for standard reporting of bus or system errors)
124
+ */
125
+
126
+static const int hviprio_index2irq[] = {
127
+ 0, 1, 4, 5, 8, 13, 14, 15, 16, 18, 20, 22, 24, 26, 28, 30 };
128
+static const int hviprio_index2rdzero[] = {
129
+ 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
130
+
131
+int riscv_cpu_hviprio_index2irq(int index, int *out_irq, int *out_rdzero)
132
+{
133
+ if (index < 0 || ARRAY_SIZE(hviprio_index2irq) <= index) {
134
+ return -EINVAL;
135
+ }
136
+
137
+ if (out_irq) {
138
+ *out_irq = hviprio_index2irq[index];
139
+ }
140
+
141
+ if (out_rdzero) {
142
+ *out_rdzero = hviprio_index2rdzero[index];
143
+ }
144
+
145
+ return 0;
146
+}
147
+
148
+/*
149
+ * Default priorities of local interrupts are defined in the
150
+ * RISC-V Advanced Interrupt Architecture specification.
151
+ *
152
+ * ----------------------------------------------------------------
153
+ * Default |
154
+ * Priority | Major Interrupt Numbers
155
+ * ----------------------------------------------------------------
156
+ * Highest | 63 (3f), 62 (3e), 31 (1f), 30 (1e), 61 (3d), 60 (3c),
157
+ * | 59 (3b), 58 (3a), 29 (1d), 28 (1c), 57 (39), 56 (38),
158
+ * | 55 (37), 54 (36), 27 (1b), 26 (1a), 53 (35), 52 (34),
159
+ * | 51 (33), 50 (32), 25 (19), 24 (18), 49 (31), 48 (30)
160
+ * |
161
+ * | 11 (0b), 3 (03), 7 (07)
162
+ * | 9 (09), 1 (01), 5 (05)
163
+ * | 12 (0c)
164
+ * | 10 (0a), 2 (02), 6 (06)
165
+ * |
166
+ * | 47 (2f), 46 (2e), 23 (17), 22 (16), 45 (2d), 44 (2c),
167
+ * | 43 (2b), 42 (2a), 21 (15), 20 (14), 41 (29), 40 (28),
168
+ * | 39 (27), 38 (26), 19 (13), 18 (12), 37 (25), 36 (24),
169
+ * Lowest | 35 (23), 34 (22), 17 (11), 16 (10), 33 (21), 32 (20)
170
+ * ----------------------------------------------------------------
171
+ */
172
+static const uint8_t default_iprio[64] = {
173
+ [63] = IPRIO_DEFAULT_UPPER,
174
+ [62] = IPRIO_DEFAULT_UPPER + 1,
175
+ [31] = IPRIO_DEFAULT_UPPER + 2,
176
+ [30] = IPRIO_DEFAULT_UPPER + 3,
177
+ [61] = IPRIO_DEFAULT_UPPER + 4,
178
+ [60] = IPRIO_DEFAULT_UPPER + 5,
179
+
180
+ [59] = IPRIO_DEFAULT_UPPER + 6,
181
+ [58] = IPRIO_DEFAULT_UPPER + 7,
182
+ [29] = IPRIO_DEFAULT_UPPER + 8,
183
+ [28] = IPRIO_DEFAULT_UPPER + 9,
184
+ [57] = IPRIO_DEFAULT_UPPER + 10,
185
+ [56] = IPRIO_DEFAULT_UPPER + 11,
186
+
187
+ [55] = IPRIO_DEFAULT_UPPER + 12,
188
+ [54] = IPRIO_DEFAULT_UPPER + 13,
189
+ [27] = IPRIO_DEFAULT_UPPER + 14,
190
+ [26] = IPRIO_DEFAULT_UPPER + 15,
191
+ [53] = IPRIO_DEFAULT_UPPER + 16,
192
+ [52] = IPRIO_DEFAULT_UPPER + 17,
193
+
194
+ [51] = IPRIO_DEFAULT_UPPER + 18,
195
+ [50] = IPRIO_DEFAULT_UPPER + 19,
196
+ [25] = IPRIO_DEFAULT_UPPER + 20,
197
+ [24] = IPRIO_DEFAULT_UPPER + 21,
198
+ [49] = IPRIO_DEFAULT_UPPER + 22,
199
+ [48] = IPRIO_DEFAULT_UPPER + 23,
200
+
201
+ [11] = IPRIO_DEFAULT_M,
202
+ [3] = IPRIO_DEFAULT_M + 1,
203
+ [7] = IPRIO_DEFAULT_M + 2,
204
+
205
+ [9] = IPRIO_DEFAULT_S,
206
+ [1] = IPRIO_DEFAULT_S + 1,
207
+ [5] = IPRIO_DEFAULT_S + 2,
208
+
209
+ [12] = IPRIO_DEFAULT_SGEXT,
210
+
211
+ [10] = IPRIO_DEFAULT_VS,
212
+ [2] = IPRIO_DEFAULT_VS + 1,
213
+ [6] = IPRIO_DEFAULT_VS + 2,
214
+
215
+ [47] = IPRIO_DEFAULT_LOWER,
216
+ [46] = IPRIO_DEFAULT_LOWER + 1,
217
+ [23] = IPRIO_DEFAULT_LOWER + 2,
218
+ [22] = IPRIO_DEFAULT_LOWER + 3,
219
+ [45] = IPRIO_DEFAULT_LOWER + 4,
220
+ [44] = IPRIO_DEFAULT_LOWER + 5,
221
+
222
+ [43] = IPRIO_DEFAULT_LOWER + 6,
223
+ [42] = IPRIO_DEFAULT_LOWER + 7,
224
+ [21] = IPRIO_DEFAULT_LOWER + 8,
225
+ [20] = IPRIO_DEFAULT_LOWER + 9,
226
+ [41] = IPRIO_DEFAULT_LOWER + 10,
227
+ [40] = IPRIO_DEFAULT_LOWER + 11,
228
+
229
+ [39] = IPRIO_DEFAULT_LOWER + 12,
230
+ [38] = IPRIO_DEFAULT_LOWER + 13,
231
+ [19] = IPRIO_DEFAULT_LOWER + 14,
232
+ [18] = IPRIO_DEFAULT_LOWER + 15,
233
+ [37] = IPRIO_DEFAULT_LOWER + 16,
234
+ [36] = IPRIO_DEFAULT_LOWER + 17,
235
+
236
+ [35] = IPRIO_DEFAULT_LOWER + 18,
237
+ [34] = IPRIO_DEFAULT_LOWER + 19,
238
+ [17] = IPRIO_DEFAULT_LOWER + 20,
239
+ [16] = IPRIO_DEFAULT_LOWER + 21,
240
+ [33] = IPRIO_DEFAULT_LOWER + 22,
241
+ [32] = IPRIO_DEFAULT_LOWER + 23,
242
+};
243
+
244
+uint8_t riscv_cpu_default_priority(int irq)
245
{
246
- target_ulong virt_enabled = riscv_cpu_virt_enabled(env);
247
+ if (irq < 0 || irq > 63) {
248
+ return IPRIO_MMAXIPRIO;
249
+ }
250
+
251
+ return default_iprio[irq] ? default_iprio[irq] : IPRIO_MMAXIPRIO;
252
+};
253
254
- target_ulong mstatus_mie = get_field(env->mstatus, MSTATUS_MIE);
255
- target_ulong mstatus_sie = get_field(env->mstatus, MSTATUS_SIE);
256
+static int riscv_cpu_pending_to_irq(CPURISCVState *env,
257
+ int extirq, unsigned int extirq_def_prio,
258
+ uint64_t pending, uint8_t *iprio)
259
+{
260
+ int irq, best_irq = RISCV_EXCP_NONE;
261
+ unsigned int prio, best_prio = UINT_MAX;
262
263
- target_ulong vsgemask =
264
- (target_ulong)1 << get_field(env->hstatus, HSTATUS_VGEIN);
265
- target_ulong vsgein = (env->hgeip & vsgemask) ? MIP_VSEIP : 0;
266
+ if (!pending) {
267
+ return RISCV_EXCP_NONE;
268
+ }
269
270
- target_ulong pending = (env->mip | vsgein) & env->mie;
271
+ irq = ctz64(pending);
272
+ if (!riscv_feature(env, RISCV_FEATURE_AIA)) {
273
+ return irq;
274
+ }
275
276
- target_ulong mie = env->priv < PRV_M ||
277
- (env->priv == PRV_M && mstatus_mie);
278
- target_ulong sie = env->priv < PRV_S ||
279
- (env->priv == PRV_S && mstatus_sie);
280
- target_ulong hsie = virt_enabled || sie;
281
- target_ulong vsie = virt_enabled && sie;
282
+ pending = pending >> irq;
283
+ while (pending) {
284
+ prio = iprio[irq];
285
+ if (!prio) {
286
+ if (irq == extirq) {
287
+ prio = extirq_def_prio;
288
+ } else {
289
+ prio = (riscv_cpu_default_priority(irq) < extirq_def_prio) ?
290
+ 1 : IPRIO_MMAXIPRIO;
291
+ }
292
+ }
293
+ if ((pending & 0x1) && (prio <= best_prio)) {
294
+ best_irq = irq;
295
+ best_prio = prio;
296
+ }
297
+ irq++;
298
+ pending = pending >> 1;
299
+ }
300
301
- target_ulong irqs =
302
- (pending & ~env->mideleg & -mie) |
303
- (pending & env->mideleg & ~env->hideleg & -hsie) |
304
- (pending & env->mideleg & env->hideleg & -vsie);
305
+ return best_irq;
306
+}
307
308
- if (irqs) {
309
- return ctz64(irqs); /* since non-zero */
310
+static uint64_t riscv_cpu_all_pending(CPURISCVState *env)
311
+{
312
+ uint32_t gein = get_field(env->hstatus, HSTATUS_VGEIN);
313
+ uint64_t vsgein = (env->hgeip & (1ULL << gein)) ? MIP_VSEIP : 0;
314
+
315
+ return (env->mip | vsgein) & env->mie;
316
+}
317
+
318
+int riscv_cpu_mirq_pending(CPURISCVState *env)
319
+{
320
+ uint64_t irqs = riscv_cpu_all_pending(env) & ~env->mideleg &
321
+ ~(MIP_SGEIP | MIP_VSSIP | MIP_VSTIP | MIP_VSEIP);
322
+
323
+ return riscv_cpu_pending_to_irq(env, IRQ_M_EXT, IPRIO_DEFAULT_M,
324
+ irqs, env->miprio);
325
+}
326
+
327
+int riscv_cpu_sirq_pending(CPURISCVState *env)
328
+{
329
+ uint64_t irqs = riscv_cpu_all_pending(env) & env->mideleg &
330
+ ~(MIP_VSSIP | MIP_VSTIP | MIP_VSEIP);
331
+
332
+ return riscv_cpu_pending_to_irq(env, IRQ_S_EXT, IPRIO_DEFAULT_S,
333
+ irqs, env->siprio);
334
+}
335
+
336
+int riscv_cpu_vsirq_pending(CPURISCVState *env)
337
+{
338
+ uint64_t irqs = riscv_cpu_all_pending(env) & env->mideleg &
339
+ (MIP_VSSIP | MIP_VSTIP | MIP_VSEIP);
340
+
341
+ return riscv_cpu_pending_to_irq(env, IRQ_S_EXT, IPRIO_DEFAULT_S,
342
+ irqs >> 1, env->hviprio);
343
+}
344
+
345
+static int riscv_cpu_local_irq_pending(CPURISCVState *env)
346
+{
347
+ int virq;
348
+ uint64_t irqs, pending, mie, hsie, vsie;
349
+
350
+ /* Determine interrupt enable state of all privilege modes */
351
+ if (riscv_cpu_virt_enabled(env)) {
352
+ mie = 1;
353
+ hsie = 1;
354
+ vsie = (env->priv < PRV_S) ||
355
+ (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_SIE));
356
} else {
357
- return RISCV_EXCP_NONE; /* indicates no pending interrupt */
358
+ mie = (env->priv < PRV_M) ||
359
+ (env->priv == PRV_M && get_field(env->mstatus, MSTATUS_MIE));
360
+ hsie = (env->priv < PRV_S) ||
361
+ (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_SIE));
362
+ vsie = 0;
363
+ }
364
+
365
+ /* Determine all pending interrupts */
366
+ pending = riscv_cpu_all_pending(env);
367
+
368
+ /* Check M-mode interrupts */
369
+ irqs = pending & ~env->mideleg & -mie;
370
+ if (irqs) {
371
+ return riscv_cpu_pending_to_irq(env, IRQ_M_EXT, IPRIO_DEFAULT_M,
372
+ irqs, env->miprio);
27
}
373
}
28
+
374
+
29
+ if (HOST_BIG_ENDIAN) {
375
+ /* Check HS-mode interrupts */
30
+ /*
376
+ irqs = pending & env->mideleg & ~env->hideleg & -hsie;
31
+ * Deal the situation when the elements are insdie
377
+ if (irqs) {
32
+ * only one uint64 block including setting the
378
+ return riscv_cpu_pending_to_irq(env, IRQ_S_EXT, IPRIO_DEFAULT_S,
33
+ * masked-off element.
379
+ irqs, env->siprio);
34
+ */
380
+ }
35
+ if (((tot - 1) ^ cnt) < 8) {
381
+
36
+ memset(base + H1(tot - 1), -1, tot - cnt);
382
+ /* Check VS-mode interrupts */
37
+ return;
383
+ irqs = pending & env->mideleg & env->hideleg & -vsie;
38
+ }
384
+ if (irqs) {
39
+ /*
385
+ virq = riscv_cpu_pending_to_irq(env, IRQ_S_EXT, IPRIO_DEFAULT_S,
40
+ * Otherwise, at least cross two uint64_t blocks.
386
+ irqs >> 1, env->hviprio);
41
+ * Set first unaligned block.
387
+ return (virq <= 0) ? virq : virq + 1;
42
+ */
388
+ }
43
+ if (cnt % 8 != 0) {
389
+
44
+ uint32_t j = ROUND_UP(cnt, 8);
390
+ /* Indicate no pending interrupt */
45
+ memset(base + H1(j - 1), -1, j - cnt);
391
+ return RISCV_EXCP_NONE;
46
+ cnt = j;
47
+ }
48
+ /* Set other 64bit aligend blocks */
49
+ }
50
memset(base + cnt, -1, tot - cnt);
51
}
392
}
52
393
394
bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
395
diff --git a/target/riscv/machine.c b/target/riscv/machine.c
396
index XXXXXXX..XXXXXXX 100644
397
--- a/target/riscv/machine.c
398
+++ b/target/riscv/machine.c
399
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_hyper = {
400
VMSTATE_UINTTL(env.hgeie, RISCVCPU),
401
VMSTATE_UINTTL(env.hgeip, RISCVCPU),
402
VMSTATE_UINT64(env.htimedelta, RISCVCPU),
403
+ VMSTATE_UINT8_ARRAY(env.hviprio, RISCVCPU, 64),
404
405
VMSTATE_UINT64(env.vsstatus, RISCVCPU),
406
VMSTATE_UINTTL(env.vstvec, RISCVCPU),
407
@@ -XXX,XX +XXX,XX @@ const VMStateDescription vmstate_riscv_cpu = {
408
.fields = (VMStateField[]) {
409
VMSTATE_UINTTL_ARRAY(env.gpr, RISCVCPU, 32),
410
VMSTATE_UINT64_ARRAY(env.fpr, RISCVCPU, 32),
411
+ VMSTATE_UINT8_ARRAY(env.miprio, RISCVCPU, 64),
412
+ VMSTATE_UINT8_ARRAY(env.siprio, RISCVCPU, 64),
413
VMSTATE_UINTTL(env.pc, RISCVCPU),
414
VMSTATE_UINTTL(env.load_res, RISCVCPU),
415
VMSTATE_UINTTL(env.load_val, RISCVCPU),
53
--
416
--
54
2.45.1
417
2.34.1
418
419
diff view generated by jsdifflib
1
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
1
From: Anup Patel <anup.patel@wdc.com>
2
2
3
SBI defines a Debug Console extension "DBCN" that will, in time, replace
3
The AIA specification adds new CSRs for RV32 so that RISC-V hart can
4
the legacy console putchar and getchar SBI extensions.
4
support 64 local interrupts on both RV32 and RV64.
5
5
6
The appeal of the DBCN extension is that it allows multiple bytes to be
6
Signed-off-by: Anup Patel <anup.patel@wdc.com>
7
read/written in the SBI console in a single SBI call.
7
Signed-off-by: Anup Patel <anup@brainfault.org>
8
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
As far as KVM goes, the DBCN calls are forwarded by an in-kernel KVM
9
Reviewed-by: Frank Chang <frank.chang@sifive.com>
10
module to userspace. But this will only happens if the KVM module
10
Message-id: 20220204174700.534953-11-anup@brainfault.org
11
actually supports this SBI extension and we activate it.
12
13
We'll check for DBCN support during init time, checking if get-reg-list
14
is advertising KVM_RISCV_SBI_EXT_DBCN. In that case, we'll enable it via
15
kvm_set_one_reg() during kvm_arch_init_vcpu().
16
17
Finally, change kvm_riscv_handle_sbi() to handle the incoming calls for
18
SBI_EXT_DBCN, reading and writing as required.
19
20
A simple KVM guest with 'earlycon=sbi', running in an emulated RISC-V
21
host, takes around 20 seconds to boot without using DBCN. With this
22
patch we're taking around 14 seconds to boot due to the speed-up in the
23
terminal output. There's no change in boot time if the guest isn't
24
using earlycon.
25
26
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
27
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
28
Message-ID: <20240425155012.581366-1-dbarboza@ventanamicro.com>
29
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
30
---
12
---
31
target/riscv/sbi_ecall_interface.h | 17 +++++
13
target/riscv/cpu.h | 14 +-
32
target/riscv/kvm/kvm-cpu.c | 111 +++++++++++++++++++++++++++++
14
target/riscv/cpu_helper.c | 10 +-
33
2 files changed, 128 insertions(+)
15
target/riscv/csr.c | 560 +++++++++++++++++++++++++++++++-------
16
target/riscv/machine.c | 10 +-
17
4 files changed, 474 insertions(+), 120 deletions(-)
34
18
35
diff --git a/target/riscv/sbi_ecall_interface.h b/target/riscv/sbi_ecall_interface.h
19
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
36
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
37
--- a/target/riscv/sbi_ecall_interface.h
21
--- a/target/riscv/cpu.h
38
+++ b/target/riscv/sbi_ecall_interface.h
22
+++ b/target/riscv/cpu.h
39
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@ struct CPURISCVState {
40
24
*/
41
/* clang-format off */
25
uint64_t mstatus;
42
26
43
+#define SBI_SUCCESS 0
27
- target_ulong mip;
44
+#define SBI_ERR_FAILED -1
28
+ uint64_t mip;
45
+#define SBI_ERR_NOT_SUPPORTED -2
29
46
+#define SBI_ERR_INVALID_PARAM -3
30
- uint32_t miclaim;
47
+#define SBI_ERR_DENIED -4
31
+ uint64_t miclaim;
48
+#define SBI_ERR_INVALID_ADDRESS -5
32
49
+#define SBI_ERR_ALREADY_AVAILABLE -6
33
- target_ulong mie;
50
+#define SBI_ERR_ALREADY_STARTED -7
34
- target_ulong mideleg;
51
+#define SBI_ERR_ALREADY_STOPPED -8
35
+ uint64_t mie;
52
+#define SBI_ERR_NO_SHMEM -9
36
+ uint64_t mideleg;
53
+
37
54
/* SBI Extension IDs */
38
target_ulong satp; /* since: priv-1.10.0 */
55
#define SBI_EXT_0_1_SET_TIMER 0x0
39
target_ulong stval;
56
#define SBI_EXT_0_1_CONSOLE_PUTCHAR 0x1
40
@@ -XXX,XX +XXX,XX @@ struct CPURISCVState {
57
@@ -XXX,XX +XXX,XX @@
41
/* Hypervisor CSRs */
58
#define SBI_EXT_IPI 0x735049
42
target_ulong hstatus;
59
#define SBI_EXT_RFENCE 0x52464E43
43
target_ulong hedeleg;
60
#define SBI_EXT_HSM 0x48534D
44
- target_ulong hideleg;
61
+#define SBI_EXT_DBCN 0x4442434E
45
+ uint64_t hideleg;
62
46
target_ulong hcounteren;
63
/* SBI function IDs for BASE extension */
47
target_ulong htval;
64
#define SBI_EXT_BASE_GET_SPEC_VERSION 0x0
48
target_ulong htinst;
65
@@ -XXX,XX +XXX,XX @@
49
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_list(void);
66
#define SBI_EXT_HSM_HART_STOP 0x1
50
#ifndef CONFIG_USER_ONLY
67
#define SBI_EXT_HSM_HART_GET_STATUS 0x2
51
bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request);
68
52
void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env);
69
+/* SBI function IDs for DBCN extension */
53
-int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint32_t interrupts);
70
+#define SBI_EXT_DBCN_CONSOLE_WRITE 0x0
54
-uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value);
71
+#define SBI_EXT_DBCN_CONSOLE_READ 0x1
55
+int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts);
72
+#define SBI_EXT_DBCN_CONSOLE_WRITE_BYTE 0x2
56
+uint64_t riscv_cpu_update_mip(RISCVCPU *cpu, uint64_t mask, uint64_t value);
73
+
57
#define BOOL_TO_MASK(x) (-!!(x)) /* helper for riscv_cpu_update_mip value */
74
#define SBI_HSM_HART_STATUS_STARTED 0x0
58
void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(uint32_t),
75
#define SBI_HSM_HART_STATUS_STOPPED 0x1
59
uint32_t arg);
76
#define SBI_HSM_HART_STATUS_START_PENDING 0x2
60
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
77
diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
78
index XXXXXXX..XXXXXXX 100644
61
index XXXXXXX..XXXXXXX 100644
79
--- a/target/riscv/kvm/kvm-cpu.c
62
--- a/target/riscv/cpu_helper.c
80
+++ b/target/riscv/kvm/kvm-cpu.c
63
+++ b/target/riscv/cpu_helper.c
81
@@ -XXX,XX +XXX,XX @@ static KVMCPUConfig kvm_v_vlenb = {
64
@@ -XXX,XX +XXX,XX @@ bool riscv_cpu_two_stage_lookup(int mmu_idx)
82
KVM_REG_RISCV_VECTOR_CSR_REG(vlenb)
65
return mmu_idx & TB_FLAGS_PRIV_HYP_ACCESS_MASK;
83
};
66
}
84
67
85
+static KVMCPUConfig kvm_sbi_dbcn = {
68
-int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint32_t interrupts)
86
+ .name = "sbi_dbcn",
69
+int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts)
87
+ .kvm_reg_id = KVM_REG_RISCV | KVM_REG_SIZE_U64 |
88
+ KVM_REG_RISCV_SBI_EXT | KVM_RISCV_SBI_EXT_DBCN
89
+};
90
+
91
static void kvm_riscv_update_cpu_cfg_isa_ext(RISCVCPU *cpu, CPUState *cs)
92
{
70
{
93
CPURISCVState *env = &cpu->env;
71
CPURISCVState *env = &cpu->env;
94
@@ -XXX,XX +XXX,XX @@ static int uint64_cmp(const void *a, const void *b)
72
if (env->miclaim & interrupts) {
95
return 0;
73
@@ -XXX,XX +XXX,XX @@ int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint32_t interrupts)
96
}
74
}
97
75
}
98
+static void kvm_riscv_check_sbi_dbcn_support(RISCVCPU *cpu,
76
99
+ KVMScratchCPU *kvmcpu,
77
-uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value)
100
+ struct kvm_reg_list *reglist)
78
+uint64_t riscv_cpu_update_mip(RISCVCPU *cpu, uint64_t mask, uint64_t value)
101
+{
79
{
102
+ struct kvm_reg_list *reg_search;
80
CPURISCVState *env = &cpu->env;
103
+
81
CPUState *cs = CPU(cpu);
104
+ reg_search = bsearch(&kvm_sbi_dbcn.kvm_reg_id, reglist->reg, reglist->n,
82
- uint32_t gein, vsgein = 0, old = env->mip;
105
+ sizeof(uint64_t), uint64_cmp);
83
+ uint64_t gein, vsgein = 0, old = env->mip;
106
+
84
bool locked = false;
107
+ if (reg_search) {
85
108
+ kvm_sbi_dbcn.supported = true;
86
if (riscv_cpu_virt_enabled(env)) {
109
+ }
87
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_do_interrupt(CPUState *cs)
110
+}
88
*/
111
+
89
bool async = !!(cs->exception_index & RISCV_EXCP_INT_FLAG);
112
static void kvm_riscv_read_vlenb(RISCVCPU *cpu, KVMScratchCPU *kvmcpu,
90
target_ulong cause = cs->exception_index & RISCV_EXCP_INT_MASK;
113
struct kvm_reg_list *reglist)
91
- target_ulong deleg = async ? env->mideleg : env->medeleg;
114
{
92
+ uint64_t deleg = async ? env->mideleg : env->medeleg;
115
@@ -XXX,XX +XXX,XX @@ static void kvm_riscv_init_multiext_cfg(RISCVCPU *cpu, KVMScratchCPU *kvmcpu)
93
target_ulong tval = 0;
116
if (riscv_has_ext(&cpu->env, RVV)) {
94
target_ulong htval = 0;
117
kvm_riscv_read_vlenb(cpu, kvmcpu, reglist);
95
target_ulong mtval2 = 0;
118
}
96
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_do_interrupt(CPUState *cs)
119
+
97
cause < TARGET_LONG_BITS && ((deleg >> cause) & 1)) {
120
+ kvm_riscv_check_sbi_dbcn_support(cpu, kvmcpu, reglist);
98
/* handle the trap in S-mode */
121
}
99
if (riscv_has_ext(env, RVH)) {
122
100
- target_ulong hdeleg = async ? env->hideleg : env->hedeleg;
123
static void riscv_init_kvm_registers(Object *cpu_obj)
101
+ uint64_t hdeleg = async ? env->hideleg : env->hedeleg;
124
@@ -XXX,XX +XXX,XX @@ static int kvm_vcpu_set_machine_ids(RISCVCPU *cpu, CPUState *cs)
102
103
if (riscv_cpu_virt_enabled(env) && ((hdeleg >> cause) & 1)) {
104
/* Trap to VS mode */
105
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
106
index XXXXXXX..XXXXXXX 100644
107
--- a/target/riscv/csr.c
108
+++ b/target/riscv/csr.c
109
@@ -XXX,XX +XXX,XX @@ static RISCVException any32(CPURISCVState *env, int csrno)
110
111
}
112
113
+static int aia_any32(CPURISCVState *env, int csrno)
114
+{
115
+ if (!riscv_feature(env, RISCV_FEATURE_AIA)) {
116
+ return RISCV_EXCP_ILLEGAL_INST;
117
+ }
118
+
119
+ return any32(env, csrno);
120
+}
121
+
122
static RISCVException smode(CPURISCVState *env, int csrno)
123
{
124
if (riscv_has_ext(env, RVS)) {
125
@@ -XXX,XX +XXX,XX @@ static RISCVException smode(CPURISCVState *env, int csrno)
126
return RISCV_EXCP_ILLEGAL_INST;
127
}
128
129
+static int smode32(CPURISCVState *env, int csrno)
130
+{
131
+ if (riscv_cpu_mxl(env) != MXL_RV32) {
132
+ return RISCV_EXCP_ILLEGAL_INST;
133
+ }
134
+
135
+ return smode(env, csrno);
136
+}
137
+
138
+static int aia_smode32(CPURISCVState *env, int csrno)
139
+{
140
+ if (!riscv_feature(env, RISCV_FEATURE_AIA)) {
141
+ return RISCV_EXCP_ILLEGAL_INST;
142
+ }
143
+
144
+ return smode32(env, csrno);
145
+}
146
+
147
static RISCVException hmode(CPURISCVState *env, int csrno)
148
{
149
if (riscv_has_ext(env, RVS) &&
150
@@ -XXX,XX +XXX,XX @@ static RISCVException pointer_masking(CPURISCVState *env, int csrno)
151
return RISCV_EXCP_ILLEGAL_INST;
152
}
153
154
+static int aia_hmode32(CPURISCVState *env, int csrno)
155
+{
156
+ if (!riscv_feature(env, RISCV_FEATURE_AIA)) {
157
+ return RISCV_EXCP_ILLEGAL_INST;
158
+ }
159
+
160
+ return hmode32(env, csrno);
161
+}
162
+
163
static RISCVException pmp(CPURISCVState *env, int csrno)
164
{
165
if (riscv_feature(env, RISCV_FEATURE_PMP)) {
166
@@ -XXX,XX +XXX,XX @@ static RISCVException read_timeh(CPURISCVState *env, int csrno,
167
168
/* Machine constants */
169
170
-#define M_MODE_INTERRUPTS (MIP_MSIP | MIP_MTIP | MIP_MEIP)
171
-#define S_MODE_INTERRUPTS (MIP_SSIP | MIP_STIP | MIP_SEIP)
172
-#define VS_MODE_INTERRUPTS (MIP_VSSIP | MIP_VSTIP | MIP_VSEIP)
173
-#define HS_MODE_INTERRUPTS (MIP_SGEIP | VS_MODE_INTERRUPTS)
174
+#define M_MODE_INTERRUPTS ((uint64_t)(MIP_MSIP | MIP_MTIP | MIP_MEIP))
175
+#define S_MODE_INTERRUPTS ((uint64_t)(MIP_SSIP | MIP_STIP | MIP_SEIP))
176
+#define VS_MODE_INTERRUPTS ((uint64_t)(MIP_VSSIP | MIP_VSTIP | MIP_VSEIP))
177
+#define HS_MODE_INTERRUPTS ((uint64_t)(MIP_SGEIP | VS_MODE_INTERRUPTS))
178
179
-static const target_ulong delegable_ints = S_MODE_INTERRUPTS |
180
+static const uint64_t delegable_ints = S_MODE_INTERRUPTS |
181
VS_MODE_INTERRUPTS;
182
-static const target_ulong vs_delegable_ints = VS_MODE_INTERRUPTS;
183
-static const target_ulong all_ints = M_MODE_INTERRUPTS | S_MODE_INTERRUPTS |
184
+static const uint64_t vs_delegable_ints = VS_MODE_INTERRUPTS;
185
+static const uint64_t all_ints = M_MODE_INTERRUPTS | S_MODE_INTERRUPTS |
186
HS_MODE_INTERRUPTS;
187
#define DELEGABLE_EXCPS ((1ULL << (RISCV_EXCP_INST_ADDR_MIS)) | \
188
(1ULL << (RISCV_EXCP_INST_ACCESS_FAULT)) | \
189
@@ -XXX,XX +XXX,XX @@ static RISCVException write_medeleg(CPURISCVState *env, int csrno,
190
return RISCV_EXCP_NONE;
191
}
192
193
-static RISCVException read_mideleg(CPURISCVState *env, int csrno,
194
- target_ulong *val)
195
+static RISCVException rmw_mideleg64(CPURISCVState *env, int csrno,
196
+ uint64_t *ret_val,
197
+ uint64_t new_val, uint64_t wr_mask)
198
{
199
- *val = env->mideleg;
200
- return RISCV_EXCP_NONE;
201
-}
202
+ uint64_t mask = wr_mask & delegable_ints;
203
+
204
+ if (ret_val) {
205
+ *ret_val = env->mideleg;
206
+ }
207
+
208
+ env->mideleg = (env->mideleg & ~mask) | (new_val & mask);
209
210
-static RISCVException write_mideleg(CPURISCVState *env, int csrno,
211
- target_ulong val)
212
-{
213
- env->mideleg = (env->mideleg & ~delegable_ints) | (val & delegable_ints);
214
if (riscv_has_ext(env, RVH)) {
215
env->mideleg |= HS_MODE_INTERRUPTS;
216
}
217
+
218
return RISCV_EXCP_NONE;
219
}
220
221
-static RISCVException read_mie(CPURISCVState *env, int csrno,
222
- target_ulong *val)
223
+static RISCVException rmw_mideleg(CPURISCVState *env, int csrno,
224
+ target_ulong *ret_val,
225
+ target_ulong new_val, target_ulong wr_mask)
226
{
227
- *val = env->mie;
228
- return RISCV_EXCP_NONE;
229
+ uint64_t rval;
230
+ RISCVException ret;
231
+
232
+ ret = rmw_mideleg64(env, csrno, &rval, new_val, wr_mask);
233
+ if (ret_val) {
234
+ *ret_val = rval;
235
+ }
236
+
237
+ return ret;
238
}
239
240
-static RISCVException write_mie(CPURISCVState *env, int csrno,
241
- target_ulong val)
242
+static RISCVException rmw_midelegh(CPURISCVState *env, int csrno,
243
+ target_ulong *ret_val,
244
+ target_ulong new_val,
245
+ target_ulong wr_mask)
246
{
247
- env->mie = (env->mie & ~all_ints) | (val & all_ints);
248
+ uint64_t rval;
249
+ RISCVException ret;
250
+
251
+ ret = rmw_mideleg64(env, csrno, &rval,
252
+ ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
253
+ if (ret_val) {
254
+ *ret_val = rval >> 32;
255
+ }
256
+
257
+ return ret;
258
+}
259
+
260
+static RISCVException rmw_mie64(CPURISCVState *env, int csrno,
261
+ uint64_t *ret_val,
262
+ uint64_t new_val, uint64_t wr_mask)
263
+{
264
+ uint64_t mask = wr_mask & all_ints;
265
+
266
+ if (ret_val) {
267
+ *ret_val = env->mie;
268
+ }
269
+
270
+ env->mie = (env->mie & ~mask) | (new_val & mask);
271
+
272
if (!riscv_has_ext(env, RVH)) {
273
- env->mie &= ~MIP_SGEIP;
274
+ env->mie &= ~((uint64_t)MIP_SGEIP);
275
}
276
+
277
return RISCV_EXCP_NONE;
278
}
279
280
+static RISCVException rmw_mie(CPURISCVState *env, int csrno,
281
+ target_ulong *ret_val,
282
+ target_ulong new_val, target_ulong wr_mask)
283
+{
284
+ uint64_t rval;
285
+ RISCVException ret;
286
+
287
+ ret = rmw_mie64(env, csrno, &rval, new_val, wr_mask);
288
+ if (ret_val) {
289
+ *ret_val = rval;
290
+ }
291
+
292
+ return ret;
293
+}
294
+
295
+static RISCVException rmw_mieh(CPURISCVState *env, int csrno,
296
+ target_ulong *ret_val,
297
+ target_ulong new_val, target_ulong wr_mask)
298
+{
299
+ uint64_t rval;
300
+ RISCVException ret;
301
+
302
+ ret = rmw_mie64(env, csrno, &rval,
303
+ ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
304
+ if (ret_val) {
305
+ *ret_val = rval >> 32;
306
+ }
307
+
308
+ return ret;
309
+}
310
+
311
static RISCVException read_mtvec(CPURISCVState *env, int csrno,
312
target_ulong *val)
313
{
314
@@ -XXX,XX +XXX,XX @@ static RISCVException write_mtval(CPURISCVState *env, int csrno,
315
return RISCV_EXCP_NONE;
316
}
317
318
-static RISCVException rmw_mip(CPURISCVState *env, int csrno,
319
- target_ulong *ret_value,
320
- target_ulong new_value, target_ulong write_mask)
321
+static RISCVException rmw_mip64(CPURISCVState *env, int csrno,
322
+ uint64_t *ret_val,
323
+ uint64_t new_val, uint64_t wr_mask)
324
{
325
RISCVCPU *cpu = env_archcpu(env);
326
/* Allow software control of delegable interrupts not claimed by hardware */
327
- target_ulong mask = write_mask & delegable_ints & ~env->miclaim;
328
- uint32_t gin, old_mip;
329
+ uint64_t old_mip, mask = wr_mask & delegable_ints & ~env->miclaim;
330
+ uint32_t gin;
331
332
if (mask) {
333
- old_mip = riscv_cpu_update_mip(cpu, mask, (new_value & mask));
334
+ old_mip = riscv_cpu_update_mip(cpu, mask, (new_val & mask));
335
} else {
336
old_mip = env->mip;
337
}
338
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_mip(CPURISCVState *env, int csrno,
339
old_mip |= (env->hgeip & ((target_ulong)1 << gin)) ? MIP_VSEIP : 0;
340
}
341
342
- if (ret_value) {
343
- *ret_value = old_mip;
344
+ if (ret_val) {
345
+ *ret_val = old_mip;
346
}
347
348
return RISCV_EXCP_NONE;
349
}
350
351
+static RISCVException rmw_mip(CPURISCVState *env, int csrno,
352
+ target_ulong *ret_val,
353
+ target_ulong new_val, target_ulong wr_mask)
354
+{
355
+ uint64_t rval;
356
+ RISCVException ret;
357
+
358
+ ret = rmw_mip64(env, csrno, &rval, new_val, wr_mask);
359
+ if (ret_val) {
360
+ *ret_val = rval;
361
+ }
362
+
363
+ return ret;
364
+}
365
+
366
+static RISCVException rmw_miph(CPURISCVState *env, int csrno,
367
+ target_ulong *ret_val,
368
+ target_ulong new_val, target_ulong wr_mask)
369
+{
370
+ uint64_t rval;
371
+ RISCVException ret;
372
+
373
+ ret = rmw_mip64(env, csrno, &rval,
374
+ ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
375
+ if (ret_val) {
376
+ *ret_val = rval >> 32;
377
+ }
378
+
379
+ return ret;
380
+}
381
+
382
/* Supervisor Trap Setup */
383
static RISCVException read_sstatus_i128(CPURISCVState *env, int csrno,
384
Int128 *val)
385
@@ -XXX,XX +XXX,XX @@ static RISCVException write_sstatus(CPURISCVState *env, int csrno,
386
return write_mstatus(env, CSR_MSTATUS, newval);
387
}
388
389
-static RISCVException read_vsie(CPURISCVState *env, int csrno,
390
- target_ulong *val)
391
+static RISCVException rmw_vsie64(CPURISCVState *env, int csrno,
392
+ uint64_t *ret_val,
393
+ uint64_t new_val, uint64_t wr_mask)
394
{
395
- /* Shift the VS bits to their S bit location in vsie */
396
- *val = (env->mie & env->hideleg & VS_MODE_INTERRUPTS) >> 1;
397
- return RISCV_EXCP_NONE;
398
+ RISCVException ret;
399
+ uint64_t rval, vsbits, mask = env->hideleg & VS_MODE_INTERRUPTS;
400
+
401
+ /* Bring VS-level bits to correct position */
402
+ vsbits = new_val & (VS_MODE_INTERRUPTS >> 1);
403
+ new_val &= ~(VS_MODE_INTERRUPTS >> 1);
404
+ new_val |= vsbits << 1;
405
+ vsbits = wr_mask & (VS_MODE_INTERRUPTS >> 1);
406
+ wr_mask &= ~(VS_MODE_INTERRUPTS >> 1);
407
+ wr_mask |= vsbits << 1;
408
+
409
+ ret = rmw_mie64(env, csrno, &rval, new_val, wr_mask & mask);
410
+ if (ret_val) {
411
+ rval &= mask;
412
+ vsbits = rval & VS_MODE_INTERRUPTS;
413
+ rval &= ~VS_MODE_INTERRUPTS;
414
+ *ret_val = rval | (vsbits >> 1);
415
+ }
416
+
417
+ return ret;
418
}
419
420
-static RISCVException read_sie(CPURISCVState *env, int csrno,
421
- target_ulong *val)
422
+static RISCVException rmw_vsie(CPURISCVState *env, int csrno,
423
+ target_ulong *ret_val,
424
+ target_ulong new_val, target_ulong wr_mask)
425
{
426
- if (riscv_cpu_virt_enabled(env)) {
427
- read_vsie(env, CSR_VSIE, val);
428
- } else {
429
- *val = env->mie & env->mideleg;
430
+ uint64_t rval;
431
+ RISCVException ret;
432
+
433
+ ret = rmw_vsie64(env, csrno, &rval, new_val, wr_mask);
434
+ if (ret_val) {
435
+ *ret_val = rval;
436
}
437
- return RISCV_EXCP_NONE;
438
+
439
+ return ret;
440
}
441
442
-static RISCVException write_vsie(CPURISCVState *env, int csrno,
443
- target_ulong val)
444
+static RISCVException rmw_vsieh(CPURISCVState *env, int csrno,
445
+ target_ulong *ret_val,
446
+ target_ulong new_val, target_ulong wr_mask)
447
{
448
- /* Shift the S bits to their VS bit location in mie */
449
- target_ulong newval = (env->mie & ~VS_MODE_INTERRUPTS) |
450
- ((val << 1) & env->hideleg & VS_MODE_INTERRUPTS);
451
- return write_mie(env, CSR_MIE, newval);
452
+ uint64_t rval;
453
+ RISCVException ret;
454
+
455
+ ret = rmw_vsie64(env, csrno, &rval,
456
+ ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
457
+ if (ret_val) {
458
+ *ret_val = rval >> 32;
459
+ }
460
+
461
+ return ret;
462
}
463
464
-static int write_sie(CPURISCVState *env, int csrno, target_ulong val)
465
+static RISCVException rmw_sie64(CPURISCVState *env, int csrno,
466
+ uint64_t *ret_val,
467
+ uint64_t new_val, uint64_t wr_mask)
468
{
469
+ RISCVException ret;
470
+ uint64_t mask = env->mideleg & S_MODE_INTERRUPTS;
471
+
472
if (riscv_cpu_virt_enabled(env)) {
473
- write_vsie(env, CSR_VSIE, val);
474
+ ret = rmw_vsie64(env, CSR_VSIE, ret_val, new_val, wr_mask);
475
} else {
476
- target_ulong newval = (env->mie & ~S_MODE_INTERRUPTS) |
477
- (val & S_MODE_INTERRUPTS);
478
- write_mie(env, CSR_MIE, newval);
479
+ ret = rmw_mie64(env, csrno, ret_val, new_val, wr_mask & mask);
480
}
481
482
- return RISCV_EXCP_NONE;
483
+ if (ret_val) {
484
+ *ret_val &= mask;
485
+ }
486
+
487
+ return ret;
488
+}
489
+
490
+static RISCVException rmw_sie(CPURISCVState *env, int csrno,
491
+ target_ulong *ret_val,
492
+ target_ulong new_val, target_ulong wr_mask)
493
+{
494
+ uint64_t rval;
495
+ RISCVException ret;
496
+
497
+ ret = rmw_sie64(env, csrno, &rval, new_val, wr_mask);
498
+ if (ret_val) {
499
+ *ret_val = rval;
500
+ }
501
+
502
+ return ret;
503
+}
504
+
505
+static RISCVException rmw_sieh(CPURISCVState *env, int csrno,
506
+ target_ulong *ret_val,
507
+ target_ulong new_val, target_ulong wr_mask)
508
+{
509
+ uint64_t rval;
510
+ RISCVException ret;
511
+
512
+ ret = rmw_sie64(env, csrno, &rval,
513
+ ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
514
+ if (ret_val) {
515
+ *ret_val = rval >> 32;
516
+ }
517
+
518
+ return ret;
519
}
520
521
static RISCVException read_stvec(CPURISCVState *env, int csrno,
522
@@ -XXX,XX +XXX,XX @@ static RISCVException write_stval(CPURISCVState *env, int csrno,
523
return RISCV_EXCP_NONE;
524
}
525
526
+static RISCVException rmw_vsip64(CPURISCVState *env, int csrno,
527
+ uint64_t *ret_val,
528
+ uint64_t new_val, uint64_t wr_mask)
529
+{
530
+ RISCVException ret;
531
+ uint64_t rval, vsbits, mask = env->hideleg & vsip_writable_mask;
532
+
533
+ /* Bring VS-level bits to correct position */
534
+ vsbits = new_val & (VS_MODE_INTERRUPTS >> 1);
535
+ new_val &= ~(VS_MODE_INTERRUPTS >> 1);
536
+ new_val |= vsbits << 1;
537
+ vsbits = wr_mask & (VS_MODE_INTERRUPTS >> 1);
538
+ wr_mask &= ~(VS_MODE_INTERRUPTS >> 1);
539
+ wr_mask |= vsbits << 1;
540
+
541
+ ret = rmw_mip64(env, csrno, &rval, new_val, wr_mask & mask);
542
+ if (ret_val) {
543
+ rval &= mask;
544
+ vsbits = rval & VS_MODE_INTERRUPTS;
545
+ rval &= ~VS_MODE_INTERRUPTS;
546
+ *ret_val = rval | (vsbits >> 1);
547
+ }
548
+
549
+ return ret;
550
+}
551
+
552
static RISCVException rmw_vsip(CPURISCVState *env, int csrno,
553
- target_ulong *ret_value,
554
- target_ulong new_value, target_ulong write_mask)
555
+ target_ulong *ret_val,
556
+ target_ulong new_val, target_ulong wr_mask)
557
{
558
- /* Shift the S bits to their VS bit location in mip */
559
- int ret = rmw_mip(env, csrno, ret_value, new_value << 1,
560
- (write_mask << 1) & vsip_writable_mask & env->hideleg);
561
+ uint64_t rval;
562
+ RISCVException ret;
563
564
- if (ret_value) {
565
- *ret_value &= VS_MODE_INTERRUPTS;
566
- /* Shift the VS bits to their S bit location in vsip */
567
- *ret_value >>= 1;
568
+ ret = rmw_vsip64(env, csrno, &rval, new_val, wr_mask);
569
+ if (ret_val) {
570
+ *ret_val = rval;
571
}
572
+
125
return ret;
573
return ret;
126
}
574
}
127
575
128
+static int kvm_vcpu_enable_sbi_dbcn(RISCVCPU *cpu, CPUState *cs)
576
-static RISCVException rmw_sip(CPURISCVState *env, int csrno,
129
+{
577
- target_ulong *ret_value,
130
+ target_ulong reg = 1;
578
- target_ulong new_value, target_ulong write_mask)
131
+
579
+static RISCVException rmw_vsiph(CPURISCVState *env, int csrno,
132
+ if (!kvm_sbi_dbcn.supported) {
580
+ target_ulong *ret_val,
133
+ return 0;
581
+ target_ulong new_val, target_ulong wr_mask)
134
+ }
582
{
135
+
583
- int ret;
136
+ return kvm_set_one_reg(cs, kvm_sbi_dbcn.kvm_reg_id, &reg);
584
+ uint64_t rval;
137
+}
585
+ RISCVException ret;
138
+
586
+
139
int kvm_arch_init_vcpu(CPUState *cs)
587
+ ret = rmw_vsip64(env, csrno, &rval,
140
{
588
+ ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
141
int ret = 0;
589
+ if (ret_val) {
142
@@ -XXX,XX +XXX,XX @@ int kvm_arch_init_vcpu(CPUState *cs)
590
+ *ret_val = rval >> 32;
143
kvm_riscv_update_cpu_misa_ext(cpu, cs);
591
+ }
144
kvm_riscv_update_cpu_cfg_isa_ext(cpu, cs);
592
+
145
593
+ return ret;
146
+ ret = kvm_vcpu_enable_sbi_dbcn(cpu, cs);
594
+}
595
+
596
+static RISCVException rmw_sip64(CPURISCVState *env, int csrno,
597
+ uint64_t *ret_val,
598
+ uint64_t new_val, uint64_t wr_mask)
599
+{
600
+ RISCVException ret;
601
+ uint64_t mask = env->mideleg & sip_writable_mask;
602
603
if (riscv_cpu_virt_enabled(env)) {
604
- ret = rmw_vsip(env, CSR_VSIP, ret_value, new_value, write_mask);
605
+ ret = rmw_vsip64(env, CSR_VSIP, ret_val, new_val, wr_mask);
606
} else {
607
- ret = rmw_mip(env, csrno, ret_value, new_value,
608
- write_mask & env->mideleg & sip_writable_mask);
609
+ ret = rmw_mip64(env, csrno, ret_val, new_val, wr_mask & mask);
610
}
611
612
- if (ret_value) {
613
- *ret_value &= env->mideleg & S_MODE_INTERRUPTS;
614
+ if (ret_val) {
615
+ *ret_val &= env->mideleg & S_MODE_INTERRUPTS;
616
+ }
617
+
618
+ return ret;
619
+}
620
+
621
+static RISCVException rmw_sip(CPURISCVState *env, int csrno,
622
+ target_ulong *ret_val,
623
+ target_ulong new_val, target_ulong wr_mask)
624
+{
625
+ uint64_t rval;
626
+ RISCVException ret;
627
+
628
+ ret = rmw_sip64(env, csrno, &rval, new_val, wr_mask);
629
+ if (ret_val) {
630
+ *ret_val = rval;
631
}
632
+
633
+ return ret;
634
+}
635
+
636
+static RISCVException rmw_siph(CPURISCVState *env, int csrno,
637
+ target_ulong *ret_val,
638
+ target_ulong new_val, target_ulong wr_mask)
639
+{
640
+ uint64_t rval;
641
+ RISCVException ret;
642
+
643
+ ret = rmw_sip64(env, csrno, &rval,
644
+ ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
645
+ if (ret_val) {
646
+ *ret_val = rval >> 32;
647
+ }
147
+
648
+
148
return ret;
649
return ret;
149
}
650
}
150
651
151
@@ -XXX,XX +XXX,XX @@ bool kvm_arch_stop_on_emulation_error(CPUState *cs)
652
@@ -XXX,XX +XXX,XX @@ static RISCVException write_hedeleg(CPURISCVState *env, int csrno,
152
return true;
653
return RISCV_EXCP_NONE;
153
}
654
}
154
655
155
+static void kvm_riscv_handle_sbi_dbcn(CPUState *cs, struct kvm_run *run)
656
-static RISCVException read_hideleg(CPURISCVState *env, int csrno,
156
+{
657
- target_ulong *val)
157
+ g_autofree uint8_t *buf = NULL;
658
+static RISCVException rmw_hideleg64(CPURISCVState *env, int csrno,
158
+ RISCVCPU *cpu = RISCV_CPU(cs);
659
+ uint64_t *ret_val,
159
+ target_ulong num_bytes;
660
+ uint64_t new_val, uint64_t wr_mask)
160
+ uint64_t addr;
661
{
161
+ unsigned char ch;
662
- *val = env->hideleg;
162
+ int ret;
663
+ uint64_t mask = wr_mask & vs_delegable_ints;
163
+
664
+
164
+ switch (run->riscv_sbi.function_id) {
665
+ if (ret_val) {
165
+ case SBI_EXT_DBCN_CONSOLE_READ:
666
+ *ret_val = env->hideleg & vs_delegable_ints;
166
+ case SBI_EXT_DBCN_CONSOLE_WRITE:
667
+ }
167
+ num_bytes = run->riscv_sbi.args[0];
668
+
168
+
669
+ env->hideleg = (env->hideleg & ~mask) | (new_val & mask);
169
+ if (num_bytes == 0) {
670
return RISCV_EXCP_NONE;
170
+ run->riscv_sbi.ret[0] = SBI_SUCCESS;
671
}
171
+ run->riscv_sbi.ret[1] = 0;
672
172
+ break;
673
-static RISCVException write_hideleg(CPURISCVState *env, int csrno,
173
+ }
674
- target_ulong val)
174
+
675
+static RISCVException rmw_hideleg(CPURISCVState *env, int csrno,
175
+ addr = run->riscv_sbi.args[1];
676
+ target_ulong *ret_val,
176
+
677
+ target_ulong new_val, target_ulong wr_mask)
177
+ /*
678
{
178
+ * Handle the case where a 32 bit CPU is running in a
679
- env->hideleg = val & vs_delegable_ints;
179
+ * 64 bit addressing env.
680
- return RISCV_EXCP_NONE;
180
+ */
681
+ uint64_t rval;
181
+ if (riscv_cpu_mxl(&cpu->env) == MXL_RV32) {
682
+ RISCVException ret;
182
+ addr |= (uint64_t)run->riscv_sbi.args[2] << 32;
683
+
183
+ }
684
+ ret = rmw_hideleg64(env, csrno, &rval, new_val, wr_mask);
184
+
685
+ if (ret_val) {
185
+ buf = g_malloc0(num_bytes);
686
+ *ret_val = rval;
186
+
687
+ }
187
+ if (run->riscv_sbi.function_id == SBI_EXT_DBCN_CONSOLE_READ) {
688
+
188
+ ret = qemu_chr_fe_read_all(serial_hd(0)->be, buf, num_bytes);
689
+ return ret;
189
+ if (ret < 0) {
690
+}
190
+ error_report("SBI_EXT_DBCN_CONSOLE_READ: error when "
691
+
191
+ "reading chardev");
692
+static RISCVException rmw_hidelegh(CPURISCVState *env, int csrno,
192
+ exit(1);
693
+ target_ulong *ret_val,
193
+ }
694
+ target_ulong new_val, target_ulong wr_mask)
194
+
695
+{
195
+ cpu_physical_memory_write(addr, buf, ret);
696
+ uint64_t rval;
196
+ } else {
697
+ RISCVException ret;
197
+ cpu_physical_memory_read(addr, buf, num_bytes);
698
+
198
+
699
+ ret = rmw_hideleg64(env, csrno, &rval,
199
+ ret = qemu_chr_fe_write_all(serial_hd(0)->be, buf, num_bytes);
700
+ ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
200
+ if (ret < 0) {
701
+ if (ret_val) {
201
+ error_report("SBI_EXT_DBCN_CONSOLE_WRITE: error when "
702
+ *ret_val = rval >> 32;
202
+ "writing chardev");
703
+ }
203
+ exit(1);
704
+
204
+ }
705
+ return ret;
205
+ }
706
+}
206
+
707
+
207
+ run->riscv_sbi.ret[0] = SBI_SUCCESS;
708
+static RISCVException rmw_hvip64(CPURISCVState *env, int csrno,
208
+ run->riscv_sbi.ret[1] = ret;
709
+ uint64_t *ret_val,
209
+ break;
710
+ uint64_t new_val, uint64_t wr_mask)
210
+ case SBI_EXT_DBCN_CONSOLE_WRITE_BYTE:
711
+{
211
+ ch = run->riscv_sbi.args[0];
712
+ RISCVException ret;
212
+ ret = qemu_chr_fe_write(serial_hd(0)->be, &ch, sizeof(ch));
713
+
213
+
714
+ ret = rmw_mip64(env, csrno, ret_val, new_val,
214
+ if (ret < 0) {
715
+ wr_mask & hvip_writable_mask);
215
+ error_report("SBI_EXT_DBCN_CONSOLE_WRITE_BYTE: error when "
716
+ if (ret_val) {
216
+ "writing chardev");
717
+ *ret_val &= VS_MODE_INTERRUPTS;
217
+ exit(1);
718
+ }
218
+ }
719
+
219
+
720
+ return ret;
220
+ run->riscv_sbi.ret[0] = SBI_SUCCESS;
721
}
221
+ run->riscv_sbi.ret[1] = 0;
722
222
+ break;
723
static RISCVException rmw_hvip(CPURISCVState *env, int csrno,
223
+ default:
724
- target_ulong *ret_value,
224
+ run->riscv_sbi.ret[0] = SBI_ERR_NOT_SUPPORTED;
725
- target_ulong new_value, target_ulong write_mask)
225
+ }
726
+ target_ulong *ret_val,
226
+}
727
+ target_ulong new_val, target_ulong wr_mask)
227
+
728
{
228
static int kvm_riscv_handle_sbi(CPUState *cs, struct kvm_run *run)
729
- int ret = rmw_mip(env, csrno, ret_value, new_value,
229
{
730
- write_mask & hvip_writable_mask);
230
int ret = 0;
731
+ uint64_t rval;
231
@@ -XXX,XX +XXX,XX @@ static int kvm_riscv_handle_sbi(CPUState *cs, struct kvm_run *run)
732
+ RISCVException ret;
232
}
733
233
ret = 0;
734
- if (ret_value) {
234
break;
735
- *ret_value &= VS_MODE_INTERRUPTS;
235
+ case SBI_EXT_DBCN:
736
+ ret = rmw_hvip64(env, csrno, &rval, new_val, wr_mask);
236
+ kvm_riscv_handle_sbi_dbcn(cs, run);
737
+ if (ret_val) {
237
+ break;
738
+ *ret_val = rval;
238
default:
739
+ }
239
qemu_log_mask(LOG_UNIMP,
740
+
240
"%s: un-handled SBI EXIT, specific reasons is %lu\n",
741
+ return ret;
742
+}
743
+
744
+static RISCVException rmw_hviph(CPURISCVState *env, int csrno,
745
+ target_ulong *ret_val,
746
+ target_ulong new_val, target_ulong wr_mask)
747
+{
748
+ uint64_t rval;
749
+ RISCVException ret;
750
+
751
+ ret = rmw_hvip64(env, csrno, &rval,
752
+ ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
753
+ if (ret_val) {
754
+ *ret_val = rval >> 32;
755
}
756
+
757
return ret;
758
}
759
760
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_hip(CPURISCVState *env, int csrno,
761
return ret;
762
}
763
764
-static RISCVException read_hie(CPURISCVState *env, int csrno,
765
- target_ulong *val)
766
+static RISCVException rmw_hie(CPURISCVState *env, int csrno,
767
+ target_ulong *ret_val,
768
+ target_ulong new_val, target_ulong wr_mask)
769
{
770
- *val = env->mie & HS_MODE_INTERRUPTS;
771
- return RISCV_EXCP_NONE;
772
-}
773
+ uint64_t rval;
774
+ RISCVException ret;
775
776
-static RISCVException write_hie(CPURISCVState *env, int csrno,
777
- target_ulong val)
778
-{
779
- target_ulong newval = (env->mie & ~HS_MODE_INTERRUPTS) | (val & HS_MODE_INTERRUPTS);
780
- return write_mie(env, CSR_MIE, newval);
781
+ ret = rmw_mie64(env, csrno, &rval, new_val, wr_mask & HS_MODE_INTERRUPTS);
782
+ if (ret_val) {
783
+ *ret_val = rval & HS_MODE_INTERRUPTS;
784
+ }
785
+
786
+ return ret;
787
}
788
789
static RISCVException read_hcounteren(CPURISCVState *env, int csrno,
790
@@ -XXX,XX +XXX,XX @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
791
read_mstatus_i128 },
792
[CSR_MISA] = { "misa", any, read_misa, write_misa, NULL,
793
read_misa_i128 },
794
- [CSR_MIDELEG] = { "mideleg", any, read_mideleg, write_mideleg },
795
+ [CSR_MIDELEG] = { "mideleg", any, NULL, NULL, rmw_mideleg },
796
[CSR_MEDELEG] = { "medeleg", any, read_medeleg, write_medeleg },
797
- [CSR_MIE] = { "mie", any, read_mie, write_mie },
798
+ [CSR_MIE] = { "mie", any, NULL, NULL, rmw_mie },
799
[CSR_MTVEC] = { "mtvec", any, read_mtvec, write_mtvec },
800
[CSR_MCOUNTEREN] = { "mcounteren", any, read_mcounteren, write_mcounteren },
801
802
@@ -XXX,XX +XXX,XX @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
803
[CSR_MTVAL] = { "mtval", any, read_mtval, write_mtval },
804
[CSR_MIP] = { "mip", any, NULL, NULL, rmw_mip },
805
806
+ /* Machine-Level High-Half CSRs (AIA) */
807
+ [CSR_MIDELEGH] = { "midelegh", aia_any32, NULL, NULL, rmw_midelegh },
808
+ [CSR_MIEH] = { "mieh", aia_any32, NULL, NULL, rmw_mieh },
809
+ [CSR_MIPH] = { "miph", aia_any32, NULL, NULL, rmw_miph },
810
+
811
/* Supervisor Trap Setup */
812
[CSR_SSTATUS] = { "sstatus", smode, read_sstatus, write_sstatus, NULL,
813
read_sstatus_i128 },
814
- [CSR_SIE] = { "sie", smode, read_sie, write_sie },
815
+ [CSR_SIE] = { "sie", smode, NULL, NULL, rmw_sie },
816
[CSR_STVEC] = { "stvec", smode, read_stvec, write_stvec },
817
[CSR_SCOUNTEREN] = { "scounteren", smode, read_scounteren, write_scounteren },
818
819
@@ -XXX,XX +XXX,XX @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
820
/* Supervisor Protection and Translation */
821
[CSR_SATP] = { "satp", smode, read_satp, write_satp },
822
823
+ /* Supervisor-Level High-Half CSRs (AIA) */
824
+ [CSR_SIEH] = { "sieh", aia_smode32, NULL, NULL, rmw_sieh },
825
+ [CSR_SIPH] = { "siph", aia_smode32, NULL, NULL, rmw_siph },
826
+
827
[CSR_HSTATUS] = { "hstatus", hmode, read_hstatus, write_hstatus },
828
[CSR_HEDELEG] = { "hedeleg", hmode, read_hedeleg, write_hedeleg },
829
- [CSR_HIDELEG] = { "hideleg", hmode, read_hideleg, write_hideleg },
830
+ [CSR_HIDELEG] = { "hideleg", hmode, NULL, NULL, rmw_hideleg },
831
[CSR_HVIP] = { "hvip", hmode, NULL, NULL, rmw_hvip },
832
[CSR_HIP] = { "hip", hmode, NULL, NULL, rmw_hip },
833
- [CSR_HIE] = { "hie", hmode, read_hie, write_hie },
834
+ [CSR_HIE] = { "hie", hmode, NULL, NULL, rmw_hie },
835
[CSR_HCOUNTEREN] = { "hcounteren", hmode, read_hcounteren, write_hcounteren },
836
[CSR_HGEIE] = { "hgeie", hmode, read_hgeie, write_hgeie },
837
[CSR_HTVAL] = { "htval", hmode, read_htval, write_htval },
838
@@ -XXX,XX +XXX,XX @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
839
840
[CSR_VSSTATUS] = { "vsstatus", hmode, read_vsstatus, write_vsstatus },
841
[CSR_VSIP] = { "vsip", hmode, NULL, NULL, rmw_vsip },
842
- [CSR_VSIE] = { "vsie", hmode, read_vsie, write_vsie },
843
+ [CSR_VSIE] = { "vsie", hmode, NULL, NULL, rmw_vsie },
844
[CSR_VSTVEC] = { "vstvec", hmode, read_vstvec, write_vstvec },
845
[CSR_VSSCRATCH] = { "vsscratch", hmode, read_vsscratch, write_vsscratch },
846
[CSR_VSEPC] = { "vsepc", hmode, read_vsepc, write_vsepc },
847
@@ -XXX,XX +XXX,XX @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
848
[CSR_MTVAL2] = { "mtval2", hmode, read_mtval2, write_mtval2 },
849
[CSR_MTINST] = { "mtinst", hmode, read_mtinst, write_mtinst },
850
851
+ /* Hypervisor and VS-Level High-Half CSRs (H-extension with AIA) */
852
+ [CSR_HIDELEGH] = { "hidelegh", aia_hmode32, NULL, NULL, rmw_hidelegh },
853
+ [CSR_HVIPH] = { "hviph", aia_hmode32, NULL, NULL, rmw_hviph },
854
+ [CSR_VSIEH] = { "vsieh", aia_hmode32, NULL, NULL, rmw_vsieh },
855
+ [CSR_VSIPH] = { "vsiph", aia_hmode32, NULL, NULL, rmw_vsiph },
856
+
857
/* Physical Memory Protection */
858
[CSR_MSECCFG] = { "mseccfg", epmp, read_mseccfg, write_mseccfg },
859
[CSR_PMPCFG0] = { "pmpcfg0", pmp, read_pmpcfg, write_pmpcfg },
860
diff --git a/target/riscv/machine.c b/target/riscv/machine.c
861
index XXXXXXX..XXXXXXX 100644
862
--- a/target/riscv/machine.c
863
+++ b/target/riscv/machine.c
864
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_hyper = {
865
.fields = (VMStateField[]) {
866
VMSTATE_UINTTL(env.hstatus, RISCVCPU),
867
VMSTATE_UINTTL(env.hedeleg, RISCVCPU),
868
- VMSTATE_UINTTL(env.hideleg, RISCVCPU),
869
+ VMSTATE_UINT64(env.hideleg, RISCVCPU),
870
VMSTATE_UINTTL(env.hcounteren, RISCVCPU),
871
VMSTATE_UINTTL(env.htval, RISCVCPU),
872
VMSTATE_UINTTL(env.htinst, RISCVCPU),
873
@@ -XXX,XX +XXX,XX @@ const VMStateDescription vmstate_riscv_cpu = {
874
VMSTATE_UINTTL(env.resetvec, RISCVCPU),
875
VMSTATE_UINTTL(env.mhartid, RISCVCPU),
876
VMSTATE_UINT64(env.mstatus, RISCVCPU),
877
- VMSTATE_UINTTL(env.mip, RISCVCPU),
878
- VMSTATE_UINT32(env.miclaim, RISCVCPU),
879
- VMSTATE_UINTTL(env.mie, RISCVCPU),
880
- VMSTATE_UINTTL(env.mideleg, RISCVCPU),
881
+ VMSTATE_UINT64(env.mip, RISCVCPU),
882
+ VMSTATE_UINT64(env.miclaim, RISCVCPU),
883
+ VMSTATE_UINT64(env.mie, RISCVCPU),
884
+ VMSTATE_UINT64(env.mideleg, RISCVCPU),
885
VMSTATE_UINTTL(env.satp, RISCVCPU),
886
VMSTATE_UINTTL(env.stval, RISCVCPU),
887
VMSTATE_UINTTL(env.medeleg, RISCVCPU),
241
--
888
--
242
2.45.1
889
2.34.1
890
891
diff view generated by jsdifflib
1
From: Yu-Ming Chang <yumin686@andestech.com>
1
From: Anup Patel <anup.patel@wdc.com>
2
2
3
Both CSRRS and CSRRC always read the addressed CSR and cause any read side
3
The AIA hvictl and hviprioX CSRs allow hypervisor to control
4
effects regardless of rs1 and rd fields. Note that if rs1 specifies a register
4
interrupts visible at VS-level. This patch implements AIA hvictl
5
holding a zero value other than x0, the instruction will still attempt to write
5
and hviprioX CSRs.
6
the unmodified value back to the CSR and will cause any attendant side effects.
6
7
7
Signed-off-by: Anup Patel <anup.patel@wdc.com>
8
So if CSRRS or CSRRC tries to write a read-only CSR with rs1 which specifies
8
Signed-off-by: Anup Patel <anup@brainfault.org>
9
a register holding a zero value, an illegal instruction exception should be
10
raised.
11
12
Signed-off-by: Yu-Ming Chang <yumin686@andestech.com>
13
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
14
Message-ID: <20240403070823.80897-1-yumin686@andestech.com>
10
Reviewed-by: Frank Chang <frank.chang@sifive.com>
11
Message-id: 20220204174700.534953-12-anup@brainfault.org
12
[ Changes by AF:
13
- Fix possible unintilised variable error in rmw_sie()
14
]
15
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
15
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
16
---
16
---
17
target/riscv/cpu.h | 4 ++++
17
target/riscv/cpu.h | 2 +
18
target/riscv/csr.c | 51 ++++++++++++++++++++++++++++++++++++----
18
target/riscv/csr.c | 128 ++++++++++++++++++++++++++++++++++++++++-
19
target/riscv/op_helper.c | 6 ++---
19
target/riscv/machine.c | 2 +
20
3 files changed, 53 insertions(+), 8 deletions(-)
20
3 files changed, 131 insertions(+), 1 deletion(-)
21
21
22
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
22
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
23
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
24
--- a/target/riscv/cpu.h
24
--- a/target/riscv/cpu.h
25
+++ b/target/riscv/cpu.h
25
+++ b/target/riscv/cpu.h
26
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
26
@@ -XXX,XX +XXX,XX @@ struct CPURISCVState {
27
void riscv_cpu_update_mask(CPURISCVState *env);
27
uint64_t htimedelta;
28
bool riscv_cpu_is_32bit(RISCVCPU *cpu);
28
29
29
/* Hypervisor controlled virtual interrupt priorities */
30
+RISCVException riscv_csrr(CPURISCVState *env, int csrno,
30
+ target_ulong hvictl;
31
+ target_ulong *ret_value);
31
uint8_t hviprio[64];
32
RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
32
33
target_ulong *ret_value,
33
/* Upper 64-bits of 128-bit CSRs */
34
target_ulong new_value, target_ulong write_mask);
34
@@ -XXX,XX +XXX,XX @@ static inline RISCVMXL riscv_cpu_mxl(CPURISCVState *env)
35
@@ -XXX,XX +XXX,XX @@ typedef RISCVException (*riscv_csr_op_fn)(CPURISCVState *env, int csrno,
35
return env->misa_mxl;
36
target_ulong new_value,
36
}
37
target_ulong write_mask);
37
#endif
38
38
+#define riscv_cpu_mxl_bits(env) (1UL << (4 + riscv_cpu_mxl(env)))
39
+RISCVException riscv_csrr_i128(CPURISCVState *env, int csrno,
39
40
+ Int128 *ret_value);
40
#if defined(TARGET_RISCV32)
41
RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno,
41
#define cpu_recompute_xl(env) ((void)(env), MXL_RV32)
42
Int128 *ret_value,
43
Int128 new_value, Int128 write_mask);
44
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
42
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
45
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
46
--- a/target/riscv/csr.c
44
--- a/target/riscv/csr.c
47
+++ b/target/riscv/csr.c
45
+++ b/target/riscv/csr.c
48
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_seed(CPURISCVState *env, int csrno,
46
@@ -XXX,XX +XXX,XX @@ static RISCVException pointer_masking(CPURISCVState *env, int csrno)
49
47
return RISCV_EXCP_ILLEGAL_INST;
50
static inline RISCVException riscv_csrrw_check(CPURISCVState *env,
48
}
51
int csrno,
49
52
- bool write_mask)
50
+static int aia_hmode(CPURISCVState *env, int csrno)
53
+ bool write)
51
+{
52
+ if (!riscv_feature(env, RISCV_FEATURE_AIA)) {
53
+ return RISCV_EXCP_ILLEGAL_INST;
54
+ }
55
+
56
+ return hmode(env, csrno);
57
+}
58
+
59
static int aia_hmode32(CPURISCVState *env, int csrno)
54
{
60
{
55
/* check privileges and return RISCV_EXCP_ILLEGAL_INST if check fails */
61
if (!riscv_feature(env, RISCV_FEATURE_AIA)) {
56
bool read_only = get_field(csrno, 0xC00) == 3;
62
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_sie64(CPURISCVState *env, int csrno,
57
@@ -XXX,XX +XXX,XX @@ static inline RISCVException riscv_csrrw_check(CPURISCVState *env,
63
uint64_t mask = env->mideleg & S_MODE_INTERRUPTS;
64
65
if (riscv_cpu_virt_enabled(env)) {
66
+ if (env->hvictl & HVICTL_VTI) {
67
+ return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
68
+ }
69
ret = rmw_vsie64(env, CSR_VSIE, ret_val, new_val, wr_mask);
70
} else {
71
ret = rmw_mie64(env, csrno, ret_val, new_val, wr_mask & mask);
72
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_sie(CPURISCVState *env, int csrno,
73
RISCVException ret;
74
75
ret = rmw_sie64(env, csrno, &rval, new_val, wr_mask);
76
- if (ret_val) {
77
+ if (ret == RISCV_EXCP_NONE && ret_val) {
78
*ret_val = rval;
58
}
79
}
59
80
60
/* read / write check */
81
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_sip64(CPURISCVState *env, int csrno,
61
- if (write_mask && read_only) {
82
uint64_t mask = env->mideleg & sip_writable_mask;
62
+ if (write && read_only) {
83
63
return RISCV_EXCP_ILLEGAL_INST;
84
if (riscv_cpu_virt_enabled(env)) {
64
}
85
+ if (env->hvictl & HVICTL_VTI) {
65
86
+ return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
66
@@ -XXX,XX +XXX,XX @@ static RISCVException riscv_csrrw_do64(CPURISCVState *env, int csrno,
87
+ }
88
ret = rmw_vsip64(env, CSR_VSIP, ret_val, new_val, wr_mask);
89
} else {
90
ret = rmw_mip64(env, csrno, ret_val, new_val, wr_mask & mask);
91
@@ -XXX,XX +XXX,XX @@ static RISCVException write_htimedeltah(CPURISCVState *env, int csrno,
67
return RISCV_EXCP_NONE;
92
return RISCV_EXCP_NONE;
68
}
93
}
69
94
70
+RISCVException riscv_csrr(CPURISCVState *env, int csrno,
95
+static int read_hvictl(CPURISCVState *env, int csrno, target_ulong *val)
71
+ target_ulong *ret_value)
96
+{
72
+{
97
+ *val = env->hvictl;
73
+ RISCVException ret = riscv_csrrw_check(env, csrno, false);
98
+ return RISCV_EXCP_NONE;
74
+ if (ret != RISCV_EXCP_NONE) {
99
+}
75
+ return ret;
100
+
76
+ }
101
+static int write_hvictl(CPURISCVState *env, int csrno, target_ulong val)
77
+
102
+{
78
+ return riscv_csrrw_do64(env, csrno, ret_value, 0, 0);
103
+ env->hvictl = val & HVICTL_VALID_MASK;
79
+}
104
+ return RISCV_EXCP_NONE;
80
+
105
+}
81
RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
106
+
82
target_ulong *ret_value,
107
+static int read_hvipriox(CPURISCVState *env, int first_index,
83
target_ulong new_value, target_ulong write_mask)
108
+ uint8_t *iprio, target_ulong *val)
84
{
109
+{
85
- RISCVException ret = riscv_csrrw_check(env, csrno, write_mask);
110
+ int i, irq, rdzero, num_irqs = 4 * (riscv_cpu_mxl_bits(env) / 32);
86
+ RISCVException ret = riscv_csrrw_check(env, csrno, true);
111
+
87
if (ret != RISCV_EXCP_NONE) {
112
+ /* First index has to be a multiple of number of irqs per register */
88
return ret;
113
+ if (first_index % num_irqs) {
89
}
114
+ return (riscv_cpu_virt_enabled(env)) ?
90
@@ -XXX,XX +XXX,XX @@ static RISCVException riscv_csrrw_do128(CPURISCVState *env, int csrno,
115
+ RISCV_EXCP_VIRT_INSTRUCTION_FAULT : RISCV_EXCP_ILLEGAL_INST;
91
return RISCV_EXCP_NONE;
116
+ }
92
}
117
+
93
118
+ /* Fill-up return value */
94
+RISCVException riscv_csrr_i128(CPURISCVState *env, int csrno,
119
+ *val = 0;
95
+ Int128 *ret_value)
120
+ for (i = 0; i < num_irqs; i++) {
96
+{
121
+ if (riscv_cpu_hviprio_index2irq(first_index + i, &irq, &rdzero)) {
97
+ RISCVException ret;
122
+ continue;
98
+
123
+ }
99
+ ret = riscv_csrrw_check(env, csrno, false);
124
+ if (rdzero) {
100
+ if (ret != RISCV_EXCP_NONE) {
125
+ continue;
101
+ return ret;
126
+ }
102
+ }
127
+ *val |= ((target_ulong)iprio[irq]) << (i * 8);
103
+
128
+ }
104
+ if (csr_ops[csrno].read128) {
129
+
105
+ return riscv_csrrw_do128(env, csrno, ret_value,
130
+ return RISCV_EXCP_NONE;
106
+ int128_zero(), int128_zero());
131
+}
107
+ }
132
+
108
+
133
+static int write_hvipriox(CPURISCVState *env, int first_index,
109
+ /*
134
+ uint8_t *iprio, target_ulong val)
110
+ * Fall back to 64-bit version for now, if the 128-bit alternative isn't
135
+{
111
+ * at all defined.
136
+ int i, irq, rdzero, num_irqs = 4 * (riscv_cpu_mxl_bits(env) / 32);
112
+ * Note, some CSRs don't need to extend to MXLEN (64 upper bits non
137
+
113
+ * significant), for those, this fallback is correctly handling the
138
+ /* First index has to be a multiple of number of irqs per register */
114
+ * accesses
139
+ if (first_index % num_irqs) {
115
+ */
140
+ return (riscv_cpu_virt_enabled(env)) ?
116
+ target_ulong old_value;
141
+ RISCV_EXCP_VIRT_INSTRUCTION_FAULT : RISCV_EXCP_ILLEGAL_INST;
117
+ ret = riscv_csrrw_do64(env, csrno, &old_value,
142
+ }
118
+ (target_ulong)0,
143
+
119
+ (target_ulong)0);
144
+ /* Fill-up priority arrary */
120
+ if (ret == RISCV_EXCP_NONE && ret_value) {
145
+ for (i = 0; i < num_irqs; i++) {
121
+ *ret_value = int128_make64(old_value);
146
+ if (riscv_cpu_hviprio_index2irq(first_index + i, &irq, &rdzero)) {
122
+ }
147
+ continue;
123
+ return ret;
148
+ }
124
+}
149
+ if (rdzero) {
125
+
150
+ iprio[irq] = 0;
126
RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno,
151
+ } else {
127
Int128 *ret_value,
152
+ iprio[irq] = (val >> (i * 8)) & 0xff;
128
Int128 new_value, Int128 write_mask)
153
+ }
129
{
154
+ }
130
RISCVException ret;
155
+
131
156
+ return RISCV_EXCP_NONE;
132
- ret = riscv_csrrw_check(env, csrno, int128_nz(write_mask));
157
+}
133
+ ret = riscv_csrrw_check(env, csrno, true);
158
+
134
if (ret != RISCV_EXCP_NONE) {
159
+static int read_hviprio1(CPURISCVState *env, int csrno, target_ulong *val)
135
return ret;
160
+{
136
}
161
+ return read_hvipriox(env, 0, env->hviprio, val);
137
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
162
+}
163
+
164
+static int write_hviprio1(CPURISCVState *env, int csrno, target_ulong val)
165
+{
166
+ return write_hvipriox(env, 0, env->hviprio, val);
167
+}
168
+
169
+static int read_hviprio1h(CPURISCVState *env, int csrno, target_ulong *val)
170
+{
171
+ return read_hvipriox(env, 4, env->hviprio, val);
172
+}
173
+
174
+static int write_hviprio1h(CPURISCVState *env, int csrno, target_ulong val)
175
+{
176
+ return write_hvipriox(env, 4, env->hviprio, val);
177
+}
178
+
179
+static int read_hviprio2(CPURISCVState *env, int csrno, target_ulong *val)
180
+{
181
+ return read_hvipriox(env, 8, env->hviprio, val);
182
+}
183
+
184
+static int write_hviprio2(CPURISCVState *env, int csrno, target_ulong val)
185
+{
186
+ return write_hvipriox(env, 8, env->hviprio, val);
187
+}
188
+
189
+static int read_hviprio2h(CPURISCVState *env, int csrno, target_ulong *val)
190
+{
191
+ return read_hvipriox(env, 12, env->hviprio, val);
192
+}
193
+
194
+static int write_hviprio2h(CPURISCVState *env, int csrno, target_ulong val)
195
+{
196
+ return write_hvipriox(env, 12, env->hviprio, val);
197
+}
198
+
199
/* Virtual CSR Registers */
200
static RISCVException read_vsstatus(CPURISCVState *env, int csrno,
201
target_ulong *val)
202
@@ -XXX,XX +XXX,XX @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
203
[CSR_MTVAL2] = { "mtval2", hmode, read_mtval2, write_mtval2 },
204
[CSR_MTINST] = { "mtinst", hmode, read_mtinst, write_mtinst },
205
206
+ /* Virtual Interrupts and Interrupt Priorities (H-extension with AIA) */
207
+ [CSR_HVICTL] = { "hvictl", aia_hmode, read_hvictl, write_hvictl },
208
+ [CSR_HVIPRIO1] = { "hviprio1", aia_hmode, read_hviprio1, write_hviprio1 },
209
+ [CSR_HVIPRIO2] = { "hviprio2", aia_hmode, read_hviprio2, write_hviprio2 },
210
+
211
/* Hypervisor and VS-Level High-Half CSRs (H-extension with AIA) */
212
[CSR_HIDELEGH] = { "hidelegh", aia_hmode32, NULL, NULL, rmw_hidelegh },
213
[CSR_HVIPH] = { "hviph", aia_hmode32, NULL, NULL, rmw_hviph },
214
+ [CSR_HVIPRIO1H] = { "hviprio1h", aia_hmode32, read_hviprio1h, write_hviprio1h },
215
+ [CSR_HVIPRIO2H] = { "hviprio2h", aia_hmode32, read_hviprio2h, write_hviprio2h },
216
[CSR_VSIEH] = { "vsieh", aia_hmode32, NULL, NULL, rmw_vsieh },
217
[CSR_VSIPH] = { "vsiph", aia_hmode32, NULL, NULL, rmw_vsiph },
218
219
diff --git a/target/riscv/machine.c b/target/riscv/machine.c
138
index XXXXXXX..XXXXXXX 100644
220
index XXXXXXX..XXXXXXX 100644
139
--- a/target/riscv/op_helper.c
221
--- a/target/riscv/machine.c
140
+++ b/target/riscv/op_helper.c
222
+++ b/target/riscv/machine.c
141
@@ -XXX,XX +XXX,XX @@ target_ulong helper_csrr(CPURISCVState *env, int csr)
223
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_hyper = {
142
}
224
VMSTATE_UINTTL(env.hgeie, RISCVCPU),
143
225
VMSTATE_UINTTL(env.hgeip, RISCVCPU),
144
target_ulong val = 0;
226
VMSTATE_UINT64(env.htimedelta, RISCVCPU),
145
- RISCVException ret = riscv_csrrw(env, csr, &val, 0, 0);
227
+
146
+ RISCVException ret = riscv_csrr(env, csr, &val);
228
+ VMSTATE_UINTTL(env.hvictl, RISCVCPU),
147
229
VMSTATE_UINT8_ARRAY(env.hviprio, RISCVCPU, 64),
148
if (ret != RISCV_EXCP_NONE) {
230
149
riscv_raise_exception(env, ret, GETPC());
231
VMSTATE_UINT64(env.vsstatus, RISCVCPU),
150
@@ -XXX,XX +XXX,XX @@ target_ulong helper_csrrw(CPURISCVState *env, int csr,
151
target_ulong helper_csrr_i128(CPURISCVState *env, int csr)
152
{
153
Int128 rv = int128_zero();
154
- RISCVException ret = riscv_csrrw_i128(env, csr, &rv,
155
- int128_zero(),
156
- int128_zero());
157
+ RISCVException ret = riscv_csrr_i128(env, csr, &rv);
158
159
if (ret != RISCV_EXCP_NONE) {
160
riscv_raise_exception(env, ret, GETPC());
161
--
232
--
162
2.45.1
233
2.34.1
234
235
diff view generated by jsdifflib
1
From: Max Chou <max.chou@sifive.com>
1
From: Anup Patel <anup.patel@wdc.com>
2
2
3
According v spec 18.4, only the vfwcvt.f.f.v and vfncvt.f.f.w
3
The AIA specificaiton adds interrupt filtering support for M-mode
4
instructions will be affected by Zvfhmin extension.
4
and HS-mode. Using AIA interrupt filtering M-mode and H-mode can
5
And the vfwcvt.f.f.v and vfncvt.f.f.w instructions only support the
5
take local interrupt 13 or above and selectively inject same local
6
conversions of
6
interrupt to lower privilege modes.
7
7
8
* From 1*SEW(16/32) to 2*SEW(32/64)
8
At the moment, we don't have any local interrupts above 12 so we
9
* From 2*SEW(32/64) to 1*SEW(16/32)
9
add dummy implementation (i.e. read zero and ignore write) of AIA
10
interrupt filtering CSRs.
10
11
11
Signed-off-by: Max Chou <max.chou@sifive.com>
12
Signed-off-by: Anup Patel <anup.patel@wdc.com>
12
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
13
Signed-off-by: Anup Patel <anup@brainfault.org>
13
Cc: qemu-stable <qemu-stable@nongnu.org>
14
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
14
Message-ID: <20240322092600.1198921-2-max.chou@sifive.com>
15
Reviewed-by: Frank Chang <frank.chang@sifive.com>
16
Message-id: 20220204174700.534953-13-anup@brainfault.org
15
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
17
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
16
---
18
---
17
target/riscv/insn_trans/trans_rvv.c.inc | 20 ++++++++++++++++++--
19
target/riscv/csr.c | 23 +++++++++++++++++++++++
18
1 file changed, 18 insertions(+), 2 deletions(-)
20
1 file changed, 23 insertions(+)
19
21
20
diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc
22
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
21
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
22
--- a/target/riscv/insn_trans/trans_rvv.c.inc
24
--- a/target/riscv/csr.c
23
+++ b/target/riscv/insn_trans/trans_rvv.c.inc
25
+++ b/target/riscv/csr.c
24
@@ -XXX,XX +XXX,XX @@ static bool require_rvf(DisasContext *s)
26
@@ -XXX,XX +XXX,XX @@ static RISCVException any32(CPURISCVState *env, int csrno)
25
}
27
26
}
28
}
27
29
28
+static bool require_rvfmin(DisasContext *s)
30
+static int aia_any(CPURISCVState *env, int csrno)
29
+{
31
+{
30
+ if (s->mstatus_fs == EXT_STATUS_DISABLED) {
32
+ if (!riscv_feature(env, RISCV_FEATURE_AIA)) {
31
+ return false;
33
+ return RISCV_EXCP_ILLEGAL_INST;
32
+ }
34
+ }
33
+
35
+
34
+ switch (s->sew) {
36
+ return any(env, csrno);
35
+ case MO_16:
36
+ return s->cfg_ptr->ext_zvfhmin;
37
+ case MO_32:
38
+ return s->cfg_ptr->ext_zve32f;
39
+ default:
40
+ return false;
41
+ }
42
+}
37
+}
43
+
38
+
44
static bool require_scale_rvf(DisasContext *s)
39
static int aia_any32(CPURISCVState *env, int csrno)
45
{
40
{
46
if (s->mstatus_fs == EXT_STATUS_DISABLED) {
41
if (!riscv_feature(env, RISCV_FEATURE_AIA)) {
47
@@ -XXX,XX +XXX,XX @@ static bool require_scale_rvfmin(DisasContext *s)
42
@@ -XXX,XX +XXX,XX @@ static RISCVException read_zero(CPURISCVState *env, int csrno,
48
}
43
return RISCV_EXCP_NONE;
49
44
}
50
switch (s->sew) {
45
51
- case MO_8:
46
+static RISCVException write_ignore(CPURISCVState *env, int csrno,
52
- return s->cfg_ptr->ext_zvfhmin;
47
+ target_ulong val)
53
case MO_16:
48
+{
54
return s->cfg_ptr->ext_zve32f;
49
+ return RISCV_EXCP_NONE;
55
case MO_32:
50
+}
56
@@ -XXX,XX +XXX,XX @@ static bool opxfv_widen_check(DisasContext *s, arg_rmr *a)
51
+
57
static bool opffv_widen_check(DisasContext *s, arg_rmr *a)
52
static RISCVException read_mhartid(CPURISCVState *env, int csrno,
53
target_ulong *val)
58
{
54
{
59
return opfv_widen_check(s, a) &&
55
@@ -XXX,XX +XXX,XX @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
60
+ require_rvfmin(s) &&
56
[CSR_MTVAL] = { "mtval", any, read_mtval, write_mtval },
61
require_scale_rvfmin(s) &&
57
[CSR_MIP] = { "mip", any, NULL, NULL, rmw_mip },
62
(s->sew != MO_8);
58
63
}
59
+ /* Virtual Interrupts for Supervisor Level (AIA) */
64
@@ -XXX,XX +XXX,XX @@ static bool opfxv_narrow_check(DisasContext *s, arg_rmr *a)
60
+ [CSR_MVIEN] = { "mvien", aia_any, read_zero, write_ignore },
65
static bool opffv_narrow_check(DisasContext *s, arg_rmr *a)
61
+ [CSR_MVIP] = { "mvip", aia_any, read_zero, write_ignore },
66
{
62
+
67
return opfv_narrow_check(s, a) &&
63
/* Machine-Level High-Half CSRs (AIA) */
68
+ require_rvfmin(s) &&
64
[CSR_MIDELEGH] = { "midelegh", aia_any32, NULL, NULL, rmw_midelegh },
69
require_scale_rvfmin(s) &&
65
[CSR_MIEH] = { "mieh", aia_any32, NULL, NULL, rmw_mieh },
70
(s->sew != MO_8);
66
+ [CSR_MVIENH] = { "mvienh", aia_any32, read_zero, write_ignore },
71
}
67
+ [CSR_MVIPH] = { "mviph", aia_any32, read_zero, write_ignore },
68
[CSR_MIPH] = { "miph", aia_any32, NULL, NULL, rmw_miph },
69
70
/* Supervisor Trap Setup */
71
@@ -XXX,XX +XXX,XX @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
72
[CSR_MTINST] = { "mtinst", hmode, read_mtinst, write_mtinst },
73
74
/* Virtual Interrupts and Interrupt Priorities (H-extension with AIA) */
75
+ [CSR_HVIEN] = { "hvien", aia_hmode, read_zero, write_ignore },
76
[CSR_HVICTL] = { "hvictl", aia_hmode, read_hvictl, write_hvictl },
77
[CSR_HVIPRIO1] = { "hviprio1", aia_hmode, read_hviprio1, write_hviprio1 },
78
[CSR_HVIPRIO2] = { "hviprio2", aia_hmode, read_hviprio2, write_hviprio2 },
79
80
/* Hypervisor and VS-Level High-Half CSRs (H-extension with AIA) */
81
[CSR_HIDELEGH] = { "hidelegh", aia_hmode32, NULL, NULL, rmw_hidelegh },
82
+ [CSR_HVIENH] = { "hvienh", aia_hmode32, read_zero, write_ignore },
83
[CSR_HVIPH] = { "hviph", aia_hmode32, NULL, NULL, rmw_hviph },
84
[CSR_HVIPRIO1H] = { "hviprio1h", aia_hmode32, read_hviprio1h, write_hviprio1h },
85
[CSR_HVIPRIO2H] = { "hviprio2h", aia_hmode32, read_hviprio2h, write_hviprio2h },
72
--
86
--
73
2.45.1
87
2.34.1
88
89
diff view generated by jsdifflib
1
From: Alistair Francis <alistair23@gmail.com>
1
From: Anup Patel <anup.patel@wdc.com>
2
2
3
When running the instruction
3
The AIA specification introduces new [m|s|vs]topi CSRs for
4
4
reporting pending local IRQ number and associated IRQ priority.
5
```
5
6
cbo.flush 0(x0)
6
Signed-off-by: Anup Patel <anup.patel@wdc.com>
7
```
7
Signed-off-by: Anup Patel <anup@brainfault.org>
8
8
Reviewed-by: Frank Chang <frank.chang@sifive.com>
9
QEMU would segfault.
9
Message-id: 20220204174700.534953-14-anup@brainfault.org
10
10
[ Changed by AF:
11
The issue was in cpu_gpr[a->rs1] as QEMU does not have cpu_gpr[0]
11
- Fixup indentation
12
allocated.
12
]
13
14
In order to fix this let's use the existing get_address()
15
helper. This also has the benefit of performing pointer mask
16
calculations on the address specified in rs1.
17
18
The pointer masking specificiation specifically states:
19
20
"""
21
Cache Management Operations: All instructions in Zicbom, Zicbop and Zicboz
22
"""
23
24
So this is the correct behaviour and we previously have been incorrectly
25
not masking the address.
26
27
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
28
Reported-by: Fabian Thomas <fabian.thomas@cispa.de>
29
Fixes: e05da09b7cfd ("target/riscv: implement Zicbom extension")
30
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
31
Cc: qemu-stable <qemu-stable@nongnu.org>
32
Message-ID: <20240514023910.301766-1-alistair.francis@wdc.com>
33
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
13
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
34
---
14
---
35
target/riscv/insn_trans/trans_rvzicbo.c.inc | 16 ++++++++++++----
15
target/riscv/csr.c | 156 +++++++++++++++++++++++++++++++++++++++++++++
36
1 file changed, 12 insertions(+), 4 deletions(-)
16
1 file changed, 156 insertions(+)
37
17
38
diff --git a/target/riscv/insn_trans/trans_rvzicbo.c.inc b/target/riscv/insn_trans/trans_rvzicbo.c.inc
18
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
39
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
40
--- a/target/riscv/insn_trans/trans_rvzicbo.c.inc
20
--- a/target/riscv/csr.c
41
+++ b/target/riscv/insn_trans/trans_rvzicbo.c.inc
21
+++ b/target/riscv/csr.c
42
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ static int smode32(CPURISCVState *env, int csrno)
43
static bool trans_cbo_clean(DisasContext *ctx, arg_cbo_clean *a)
23
return smode(env, csrno);
24
}
25
26
+static int aia_smode(CPURISCVState *env, int csrno)
27
+{
28
+ if (!riscv_feature(env, RISCV_FEATURE_AIA)) {
29
+ return RISCV_EXCP_ILLEGAL_INST;
30
+ }
31
+
32
+ return smode(env, csrno);
33
+}
34
+
35
static int aia_smode32(CPURISCVState *env, int csrno)
44
{
36
{
45
REQUIRE_ZICBOM(ctx);
37
if (!riscv_feature(env, RISCV_FEATURE_AIA)) {
46
- gen_helper_cbo_clean_flush(tcg_env, cpu_gpr[a->rs1]);
38
@@ -XXX,XX +XXX,XX @@ static RISCVException read_timeh(CPURISCVState *env, int csrno,
47
+ TCGv src = get_address(ctx, a->rs1, 0);
39
#define VS_MODE_INTERRUPTS ((uint64_t)(MIP_VSSIP | MIP_VSTIP | MIP_VSEIP))
48
+
40
#define HS_MODE_INTERRUPTS ((uint64_t)(MIP_SGEIP | VS_MODE_INTERRUPTS))
49
+ gen_helper_cbo_clean_flush(tcg_env, src);
41
50
return true;
42
+#define VSTOPI_NUM_SRCS 5
43
+
44
static const uint64_t delegable_ints = S_MODE_INTERRUPTS |
45
VS_MODE_INTERRUPTS;
46
static const uint64_t vs_delegable_ints = VS_MODE_INTERRUPTS;
47
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_mieh(CPURISCVState *env, int csrno,
48
return ret;
51
}
49
}
52
50
53
static bool trans_cbo_flush(DisasContext *ctx, arg_cbo_flush *a)
51
+static int read_mtopi(CPURISCVState *env, int csrno, target_ulong *val)
52
+{
53
+ int irq;
54
+ uint8_t iprio;
55
+
56
+ irq = riscv_cpu_mirq_pending(env);
57
+ if (irq <= 0 || irq > 63) {
58
+ *val = 0;
59
+ } else {
60
+ iprio = env->miprio[irq];
61
+ if (!iprio) {
62
+ if (riscv_cpu_default_priority(irq) > IPRIO_DEFAULT_M) {
63
+ iprio = IPRIO_MMAXIPRIO;
64
+ }
65
+ }
66
+ *val = (irq & TOPI_IID_MASK) << TOPI_IID_SHIFT;
67
+ *val |= iprio;
68
+ }
69
+
70
+ return RISCV_EXCP_NONE;
71
+}
72
+
73
static RISCVException read_mtvec(CPURISCVState *env, int csrno,
74
target_ulong *val)
54
{
75
{
55
REQUIRE_ZICBOM(ctx);
76
@@ -XXX,XX +XXX,XX @@ static RISCVException write_satp(CPURISCVState *env, int csrno,
56
- gen_helper_cbo_clean_flush(tcg_env, cpu_gpr[a->rs1]);
77
return RISCV_EXCP_NONE;
57
+ TCGv src = get_address(ctx, a->rs1, 0);
58
+
59
+ gen_helper_cbo_clean_flush(tcg_env, src);
60
return true;
61
}
78
}
62
79
63
static bool trans_cbo_inval(DisasContext *ctx, arg_cbo_inval *a)
80
+static int read_vstopi(CPURISCVState *env, int csrno, target_ulong *val)
64
{
81
+{
65
REQUIRE_ZICBOM(ctx);
82
+ int irq, ret;
66
- gen_helper_cbo_inval(tcg_env, cpu_gpr[a->rs1]);
83
+ target_ulong topei;
67
+ TCGv src = get_address(ctx, a->rs1, 0);
84
+ uint64_t vseip, vsgein;
68
+
85
+ uint32_t iid, iprio, hviid, hviprio, gein;
69
+ gen_helper_cbo_inval(tcg_env, src);
86
+ uint32_t s, scount = 0, siid[VSTOPI_NUM_SRCS], siprio[VSTOPI_NUM_SRCS];
70
return true;
87
+
71
}
88
+ gein = get_field(env->hstatus, HSTATUS_VGEIN);
72
89
+ hviid = get_field(env->hvictl, HVICTL_IID);
73
static bool trans_cbo_zero(DisasContext *ctx, arg_cbo_zero *a)
90
+ hviprio = get_field(env->hvictl, HVICTL_IPRIO);
74
{
91
+
75
REQUIRE_ZICBOZ(ctx);
92
+ if (gein) {
76
- gen_helper_cbo_zero(tcg_env, cpu_gpr[a->rs1]);
93
+ vsgein = (env->hgeip & (1ULL << gein)) ? MIP_VSEIP : 0;
77
+ TCGv src = get_address(ctx, a->rs1, 0);
94
+ vseip = env->mie & (env->mip | vsgein) & MIP_VSEIP;
78
+
95
+ if (gein <= env->geilen && vseip) {
79
+ gen_helper_cbo_zero(tcg_env, src);
96
+ siid[scount] = IRQ_S_EXT;
80
return true;
97
+ siprio[scount] = IPRIO_MMAXIPRIO + 1;
81
}
98
+ if (env->aia_ireg_rmw_fn[PRV_S]) {
99
+ /*
100
+ * Call machine specific IMSIC register emulation for
101
+ * reading TOPEI.
102
+ */
103
+ ret = env->aia_ireg_rmw_fn[PRV_S](
104
+ env->aia_ireg_rmw_fn_arg[PRV_S],
105
+ AIA_MAKE_IREG(ISELECT_IMSIC_TOPEI, PRV_S, true, gein,
106
+ riscv_cpu_mxl_bits(env)),
107
+ &topei, 0, 0);
108
+ if (!ret && topei) {
109
+ siprio[scount] = topei & IMSIC_TOPEI_IPRIO_MASK;
110
+ }
111
+ }
112
+ scount++;
113
+ }
114
+ } else {
115
+ if (hviid == IRQ_S_EXT && hviprio) {
116
+ siid[scount] = IRQ_S_EXT;
117
+ siprio[scount] = hviprio;
118
+ scount++;
119
+ }
120
+ }
121
+
122
+ if (env->hvictl & HVICTL_VTI) {
123
+ if (hviid != IRQ_S_EXT) {
124
+ siid[scount] = hviid;
125
+ siprio[scount] = hviprio;
126
+ scount++;
127
+ }
128
+ } else {
129
+ irq = riscv_cpu_vsirq_pending(env);
130
+ if (irq != IRQ_S_EXT && 0 < irq && irq <= 63) {
131
+ siid[scount] = irq;
132
+ siprio[scount] = env->hviprio[irq];
133
+ scount++;
134
+ }
135
+ }
136
+
137
+ iid = 0;
138
+ iprio = UINT_MAX;
139
+ for (s = 0; s < scount; s++) {
140
+ if (siprio[s] < iprio) {
141
+ iid = siid[s];
142
+ iprio = siprio[s];
143
+ }
144
+ }
145
+
146
+ if (iid) {
147
+ if (env->hvictl & HVICTL_IPRIOM) {
148
+ if (iprio > IPRIO_MMAXIPRIO) {
149
+ iprio = IPRIO_MMAXIPRIO;
150
+ }
151
+ if (!iprio) {
152
+ if (riscv_cpu_default_priority(iid) > IPRIO_DEFAULT_S) {
153
+ iprio = IPRIO_MMAXIPRIO;
154
+ }
155
+ }
156
+ } else {
157
+ iprio = 1;
158
+ }
159
+ } else {
160
+ iprio = 0;
161
+ }
162
+
163
+ *val = (iid & TOPI_IID_MASK) << TOPI_IID_SHIFT;
164
+ *val |= iprio;
165
+ return RISCV_EXCP_NONE;
166
+}
167
+
168
+static int read_stopi(CPURISCVState *env, int csrno, target_ulong *val)
169
+{
170
+ int irq;
171
+ uint8_t iprio;
172
+
173
+ if (riscv_cpu_virt_enabled(env)) {
174
+ return read_vstopi(env, CSR_VSTOPI, val);
175
+ }
176
+
177
+ irq = riscv_cpu_sirq_pending(env);
178
+ if (irq <= 0 || irq > 63) {
179
+ *val = 0;
180
+ } else {
181
+ iprio = env->siprio[irq];
182
+ if (!iprio) {
183
+ if (riscv_cpu_default_priority(irq) > IPRIO_DEFAULT_S) {
184
+ iprio = IPRIO_MMAXIPRIO;
185
+ }
186
+ }
187
+ *val = (irq & TOPI_IID_MASK) << TOPI_IID_SHIFT;
188
+ *val |= iprio;
189
+ }
190
+
191
+ return RISCV_EXCP_NONE;
192
+}
193
+
194
/* Hypervisor Extensions */
195
static RISCVException read_hstatus(CPURISCVState *env, int csrno,
196
target_ulong *val)
197
@@ -XXX,XX +XXX,XX @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
198
[CSR_MTVAL] = { "mtval", any, read_mtval, write_mtval },
199
[CSR_MIP] = { "mip", any, NULL, NULL, rmw_mip },
200
201
+ /* Machine-Level Interrupts (AIA) */
202
+ [CSR_MTOPI] = { "mtopi", aia_any, read_mtopi },
203
+
204
/* Virtual Interrupts for Supervisor Level (AIA) */
205
[CSR_MVIEN] = { "mvien", aia_any, read_zero, write_ignore },
206
[CSR_MVIP] = { "mvip", aia_any, read_zero, write_ignore },
207
@@ -XXX,XX +XXX,XX @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
208
/* Supervisor Protection and Translation */
209
[CSR_SATP] = { "satp", smode, read_satp, write_satp },
210
211
+ /* Supervisor-Level Interrupts (AIA) */
212
+ [CSR_STOPI] = { "stopi", aia_smode, read_stopi },
213
+
214
/* Supervisor-Level High-Half CSRs (AIA) */
215
[CSR_SIEH] = { "sieh", aia_smode32, NULL, NULL, rmw_sieh },
216
[CSR_SIPH] = { "siph", aia_smode32, NULL, NULL, rmw_siph },
217
@@ -XXX,XX +XXX,XX @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
218
[CSR_HVIPRIO1] = { "hviprio1", aia_hmode, read_hviprio1, write_hviprio1 },
219
[CSR_HVIPRIO2] = { "hviprio2", aia_hmode, read_hviprio2, write_hviprio2 },
220
221
+ /* VS-Level Interrupts (H-extension with AIA) */
222
+ [CSR_VSTOPI] = { "vstopi", aia_hmode, read_vstopi },
223
+
224
/* Hypervisor and VS-Level High-Half CSRs (H-extension with AIA) */
225
[CSR_HIDELEGH] = { "hidelegh", aia_hmode32, NULL, NULL, rmw_hidelegh },
226
[CSR_HVIENH] = { "hvienh", aia_hmode32, read_zero, write_ignore },
82
--
227
--
83
2.45.1
228
2.34.1
229
230
diff view generated by jsdifflib
1
From: Andrew Jones <ajones@ventanamicro.com>
1
From: Anup Patel <anup.patel@wdc.com>
2
2
3
The Zkr extension may only be exposed to KVM guests if the VMM
3
The AIA specification defines [m|s|vs]iselect and [m|s|vs]ireg CSRs
4
implements the SEED CSR. Use the same implementation as TCG.
4
which allow indirect access to interrupt priority arrays and per-HART
5
5
IMSIC registers. This patch implements AIA xiselect and xireg CSRs.
6
Without this patch, running with a KVM which does not forward the
6
7
SEED CSR access to QEMU will result in an ILL exception being
7
Signed-off-by: Anup Patel <anup.patel@wdc.com>
8
injected into the guest (this results in Linux guests crashing on
8
Signed-off-by: Anup Patel <anup@brainfault.org>
9
boot). And, when running with a KVM which does forward the access,
9
Reviewed-by: Frank Chang <frank.chang@sifive.com>
10
QEMU will crash, since QEMU doesn't know what to do with the exit.
10
Message-id: 20220204174700.534953-15-anup@brainfault.org
11
12
Fixes: 3108e2f1c69d ("target/riscv/kvm: update KVM exts to Linux 6.8")
13
Signed-off-by: Andrew Jones <ajones@ventanamicro.com>
14
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
15
Cc: qemu-stable <qemu-stable@nongnu.org>
16
Message-ID: <20240422134605.534207-2-ajones@ventanamicro.com>
17
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
18
---
12
---
19
target/riscv/cpu.h | 3 +++
13
target/riscv/cpu.h | 7 ++
20
target/riscv/csr.c | 18 ++++++++++++++----
14
target/riscv/csr.c | 177 +++++++++++++++++++++++++++++++++++++++++
21
target/riscv/kvm/kvm-cpu.c | 25 +++++++++++++++++++++++++
15
target/riscv/machine.c | 3 +
22
3 files changed, 42 insertions(+), 4 deletions(-)
16
3 files changed, 187 insertions(+)
23
17
24
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
18
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
25
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
26
--- a/target/riscv/cpu.h
20
--- a/target/riscv/cpu.h
27
+++ b/target/riscv/cpu.h
21
+++ b/target/riscv/cpu.h
28
@@ -XXX,XX +XXX,XX @@ void riscv_set_csr_ops(int csrno, riscv_csr_operations *ops);
22
@@ -XXX,XX +XXX,XX @@ struct CPURISCVState {
29
23
uint8_t miprio[64];
30
void riscv_cpu_register_gdb_regs_for_features(CPUState *cs);
24
uint8_t siprio[64];
31
25
32
+target_ulong riscv_new_csr_seed(target_ulong new_value,
26
+ /* AIA CSRs */
33
+ target_ulong write_mask);
27
+ target_ulong miselect;
34
+
28
+ target_ulong siselect;
35
uint8_t satp_mode_max_from_map(uint32_t map);
29
+
36
const char *satp_mode_str(uint8_t satp_mode, bool is_32_bit);
30
/* Hypervisor CSRs */
31
target_ulong hstatus;
32
target_ulong hedeleg;
33
@@ -XXX,XX +XXX,XX @@ struct CPURISCVState {
34
target_ulong vstval;
35
target_ulong vsatp;
36
37
+ /* AIA VS-mode CSRs */
38
+ target_ulong vsiselect;
39
+
40
target_ulong mtval2;
41
target_ulong mtinst;
37
42
38
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
43
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
39
index XXXXXXX..XXXXXXX 100644
44
index XXXXXXX..XXXXXXX 100644
40
--- a/target/riscv/csr.c
45
--- a/target/riscv/csr.c
41
+++ b/target/riscv/csr.c
46
+++ b/target/riscv/csr.c
42
@@ -XXX,XX +XXX,XX @@ static RISCVException write_upmbase(CPURISCVState *env, int csrno,
47
@@ -XXX,XX +XXX,XX @@ static int read_mtopi(CPURISCVState *env, int csrno, target_ulong *val)
43
#endif
48
return RISCV_EXCP_NONE;
44
49
}
45
/* Crypto Extension */
50
46
-static RISCVException rmw_seed(CPURISCVState *env, int csrno,
51
+static int aia_xlate_vs_csrno(CPURISCVState *env, int csrno)
47
- target_ulong *ret_value,
52
+{
48
- target_ulong new_value,
53
+ if (!riscv_cpu_virt_enabled(env)) {
49
- target_ulong write_mask)
54
+ return csrno;
50
+target_ulong riscv_new_csr_seed(target_ulong new_value,
55
+ }
51
+ target_ulong write_mask)
56
+
57
+ switch (csrno) {
58
+ case CSR_SISELECT:
59
+ return CSR_VSISELECT;
60
+ case CSR_SIREG:
61
+ return CSR_VSIREG;
62
+ default:
63
+ return csrno;
64
+ };
65
+}
66
+
67
+static int rmw_xiselect(CPURISCVState *env, int csrno, target_ulong *val,
68
+ target_ulong new_val, target_ulong wr_mask)
69
+{
70
+ target_ulong *iselect;
71
+
72
+ /* Translate CSR number for VS-mode */
73
+ csrno = aia_xlate_vs_csrno(env, csrno);
74
+
75
+ /* Find the iselect CSR based on CSR number */
76
+ switch (csrno) {
77
+ case CSR_MISELECT:
78
+ iselect = &env->miselect;
79
+ break;
80
+ case CSR_SISELECT:
81
+ iselect = &env->siselect;
82
+ break;
83
+ case CSR_VSISELECT:
84
+ iselect = &env->vsiselect;
85
+ break;
86
+ default:
87
+ return RISCV_EXCP_ILLEGAL_INST;
88
+ };
89
+
90
+ if (val) {
91
+ *val = *iselect;
92
+ }
93
+
94
+ wr_mask &= ISELECT_MASK;
95
+ if (wr_mask) {
96
+ *iselect = (*iselect & ~wr_mask) | (new_val & wr_mask);
97
+ }
98
+
99
+ return RISCV_EXCP_NONE;
100
+}
101
+
102
+static int rmw_iprio(target_ulong xlen,
103
+ target_ulong iselect, uint8_t *iprio,
104
+ target_ulong *val, target_ulong new_val,
105
+ target_ulong wr_mask, int ext_irq_no)
106
+{
107
+ int i, firq, nirqs;
108
+ target_ulong old_val;
109
+
110
+ if (iselect < ISELECT_IPRIO0 || ISELECT_IPRIO15 < iselect) {
111
+ return -EINVAL;
112
+ }
113
+ if (xlen != 32 && iselect & 0x1) {
114
+ return -EINVAL;
115
+ }
116
+
117
+ nirqs = 4 * (xlen / 32);
118
+ firq = ((iselect - ISELECT_IPRIO0) / (xlen / 32)) * (nirqs);
119
+
120
+ old_val = 0;
121
+ for (i = 0; i < nirqs; i++) {
122
+ old_val |= ((target_ulong)iprio[firq + i]) << (IPRIO_IRQ_BITS * i);
123
+ }
124
+
125
+ if (val) {
126
+ *val = old_val;
127
+ }
128
+
129
+ if (wr_mask) {
130
+ new_val = (old_val & ~wr_mask) | (new_val & wr_mask);
131
+ for (i = 0; i < nirqs; i++) {
132
+ /*
133
+ * M-level and S-level external IRQ priority always read-only
134
+ * zero. This means default priority order is always preferred
135
+ * for M-level and S-level external IRQs.
136
+ */
137
+ if ((firq + i) == ext_irq_no) {
138
+ continue;
139
+ }
140
+ iprio[firq + i] = (new_val >> (IPRIO_IRQ_BITS * i)) & 0xff;
141
+ }
142
+ }
143
+
144
+ return 0;
145
+}
146
+
147
+static int rmw_xireg(CPURISCVState *env, int csrno, target_ulong *val,
148
+ target_ulong new_val, target_ulong wr_mask)
149
+{
150
+ bool virt;
151
+ uint8_t *iprio;
152
+ int ret = -EINVAL;
153
+ target_ulong priv, isel, vgein;
154
+
155
+ /* Translate CSR number for VS-mode */
156
+ csrno = aia_xlate_vs_csrno(env, csrno);
157
+
158
+ /* Decode register details from CSR number */
159
+ virt = false;
160
+ switch (csrno) {
161
+ case CSR_MIREG:
162
+ iprio = env->miprio;
163
+ isel = env->miselect;
164
+ priv = PRV_M;
165
+ break;
166
+ case CSR_SIREG:
167
+ iprio = env->siprio;
168
+ isel = env->siselect;
169
+ priv = PRV_S;
170
+ break;
171
+ case CSR_VSIREG:
172
+ iprio = env->hviprio;
173
+ isel = env->vsiselect;
174
+ priv = PRV_S;
175
+ virt = true;
176
+ break;
177
+ default:
178
+ goto done;
179
+ };
180
+
181
+ /* Find the selected guest interrupt file */
182
+ vgein = (virt) ? get_field(env->hstatus, HSTATUS_VGEIN) : 0;
183
+
184
+ if (ISELECT_IPRIO0 <= isel && isel <= ISELECT_IPRIO15) {
185
+ /* Local interrupt priority registers not available for VS-mode */
186
+ if (!virt) {
187
+ ret = rmw_iprio(riscv_cpu_mxl_bits(env),
188
+ isel, iprio, val, new_val, wr_mask,
189
+ (priv == PRV_M) ? IRQ_M_EXT : IRQ_S_EXT);
190
+ }
191
+ } else if (ISELECT_IMSIC_FIRST <= isel && isel <= ISELECT_IMSIC_LAST) {
192
+ /* IMSIC registers only available when machine implements it. */
193
+ if (env->aia_ireg_rmw_fn[priv]) {
194
+ /* Selected guest interrupt file should not be zero */
195
+ if (virt && (!vgein || env->geilen < vgein)) {
196
+ goto done;
197
+ }
198
+ /* Call machine specific IMSIC register emulation */
199
+ ret = env->aia_ireg_rmw_fn[priv](env->aia_ireg_rmw_fn_arg[priv],
200
+ AIA_MAKE_IREG(isel, priv, virt, vgein,
201
+ riscv_cpu_mxl_bits(env)),
202
+ val, new_val, wr_mask);
203
+ }
204
+ }
205
+
206
+done:
207
+ if (ret) {
208
+ return (riscv_cpu_virt_enabled(env) && virt) ?
209
+ RISCV_EXCP_VIRT_INSTRUCTION_FAULT : RISCV_EXCP_ILLEGAL_INST;
210
+ }
211
+ return RISCV_EXCP_NONE;
212
+}
213
+
214
static RISCVException read_mtvec(CPURISCVState *env, int csrno,
215
target_ulong *val)
52
{
216
{
53
uint16_t random_v;
217
@@ -XXX,XX +XXX,XX @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
54
Error *random_e = NULL;
218
[CSR_MTVAL] = { "mtval", any, read_mtval, write_mtval },
55
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_seed(CPURISCVState *env, int csrno,
219
[CSR_MIP] = { "mip", any, NULL, NULL, rmw_mip },
56
rval = random_v | SEED_OPST_ES16;
220
57
}
221
+ /* Machine-Level Window to Indirectly Accessed Registers (AIA) */
58
222
+ [CSR_MISELECT] = { "miselect", aia_any, NULL, NULL, rmw_xiselect },
59
+ return rval;
223
+ [CSR_MIREG] = { "mireg", aia_any, NULL, NULL, rmw_xireg },
60
+}
224
+
61
+
225
/* Machine-Level Interrupts (AIA) */
62
+static RISCVException rmw_seed(CPURISCVState *env, int csrno,
226
[CSR_MTOPI] = { "mtopi", aia_any, read_mtopi },
63
+ target_ulong *ret_value,
227
64
+ target_ulong new_value,
228
@@ -XXX,XX +XXX,XX @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
65
+ target_ulong write_mask)
229
/* Supervisor Protection and Translation */
66
+{
230
[CSR_SATP] = { "satp", smode, read_satp, write_satp },
67
+ target_ulong rval;
231
68
+
232
+ /* Supervisor-Level Window to Indirectly Accessed Registers (AIA) */
69
+ rval = riscv_new_csr_seed(new_value, write_mask);
233
+ [CSR_SISELECT] = { "siselect", aia_smode, NULL, NULL, rmw_xiselect },
70
+
234
+ [CSR_SIREG] = { "sireg", aia_smode, NULL, NULL, rmw_xireg },
71
if (ret_value) {
235
+
72
*ret_value = rval;
236
/* Supervisor-Level Interrupts (AIA) */
73
}
237
[CSR_STOPI] = { "stopi", aia_smode, read_stopi },
74
diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
238
239
@@ -XXX,XX +XXX,XX @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
240
[CSR_HVIPRIO1] = { "hviprio1", aia_hmode, read_hviprio1, write_hviprio1 },
241
[CSR_HVIPRIO2] = { "hviprio2", aia_hmode, read_hviprio2, write_hviprio2 },
242
243
+ /*
244
+ * VS-Level Window to Indirectly Accessed Registers (H-extension with AIA)
245
+ */
246
+ [CSR_VSISELECT] = { "vsiselect", aia_hmode, NULL, NULL, rmw_xiselect },
247
+ [CSR_VSIREG] = { "vsireg", aia_hmode, NULL, NULL, rmw_xireg },
248
+
249
/* VS-Level Interrupts (H-extension with AIA) */
250
[CSR_VSTOPI] = { "vstopi", aia_hmode, read_vstopi },
251
252
diff --git a/target/riscv/machine.c b/target/riscv/machine.c
75
index XXXXXXX..XXXXXXX 100644
253
index XXXXXXX..XXXXXXX 100644
76
--- a/target/riscv/kvm/kvm-cpu.c
254
--- a/target/riscv/machine.c
77
+++ b/target/riscv/kvm/kvm-cpu.c
255
+++ b/target/riscv/machine.c
78
@@ -XXX,XX +XXX,XX @@ static int kvm_riscv_handle_sbi(CPUState *cs, struct kvm_run *run)
256
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_hyper = {
79
return ret;
257
VMSTATE_UINTTL(env.vscause, RISCVCPU),
80
}
258
VMSTATE_UINTTL(env.vstval, RISCVCPU),
81
259
VMSTATE_UINTTL(env.vsatp, RISCVCPU),
82
+static int kvm_riscv_handle_csr(CPUState *cs, struct kvm_run *run)
260
+ VMSTATE_UINTTL(env.vsiselect, RISCVCPU),
83
+{
261
84
+ target_ulong csr_num = run->riscv_csr.csr_num;
262
VMSTATE_UINTTL(env.mtval2, RISCVCPU),
85
+ target_ulong new_value = run->riscv_csr.new_value;
263
VMSTATE_UINTTL(env.mtinst, RISCVCPU),
86
+ target_ulong write_mask = run->riscv_csr.write_mask;
264
@@ -XXX,XX +XXX,XX @@ const VMStateDescription vmstate_riscv_cpu = {
87
+ int ret = 0;
265
VMSTATE_UINTTL(env.mepc, RISCVCPU),
88
+
266
VMSTATE_UINTTL(env.mcause, RISCVCPU),
89
+ switch (csr_num) {
267
VMSTATE_UINTTL(env.mtval, RISCVCPU),
90
+ case CSR_SEED:
268
+ VMSTATE_UINTTL(env.miselect, RISCVCPU),
91
+ run->riscv_csr.ret_value = riscv_new_csr_seed(new_value, write_mask);
269
+ VMSTATE_UINTTL(env.siselect, RISCVCPU),
92
+ break;
270
VMSTATE_UINTTL(env.scounteren, RISCVCPU),
93
+ default:
271
VMSTATE_UINTTL(env.mcounteren, RISCVCPU),
94
+ qemu_log_mask(LOG_UNIMP,
272
VMSTATE_UINTTL(env.sscratch, RISCVCPU),
95
+ "%s: un-handled CSR EXIT for CSR %lx\n",
96
+ __func__, csr_num);
97
+ ret = -1;
98
+ break;
99
+ }
100
+
101
+ return ret;
102
+}
103
+
104
int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
105
{
106
int ret = 0;
107
@@ -XXX,XX +XXX,XX @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
108
case KVM_EXIT_RISCV_SBI:
109
ret = kvm_riscv_handle_sbi(cs, run);
110
break;
111
+ case KVM_EXIT_RISCV_CSR:
112
+ ret = kvm_riscv_handle_csr(cs, run);
113
+ break;
114
default:
115
qemu_log_mask(LOG_UNIMP, "%s: un-handled exit reason %d\n",
116
__func__, run->exit_reason);
117
--
273
--
118
2.45.1
274
2.34.1
275
276
diff view generated by jsdifflib
1
From: Cheng Yang <yangcheng.work@foxmail.com>
1
From: Anup Patel <anup.patel@wdc.com>
2
2
3
Use qemu_fdt_setprop_u64() instead of qemu_fdt_setprop_cell()
3
The AIA specification defines IMSIC interface CSRs for easy access
4
to set the address of initrd in FDT to support 64-bit address.
4
to the per-HART IMSIC registers without using indirect xiselect and
5
5
xireg CSRs. This patch implements the AIA IMSIC interface CSRs.
6
Signed-off-by: Cheng Yang <yangcheng.work@foxmail.com>
6
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
7
Signed-off-by: Anup Patel <anup.patel@wdc.com>
8
Message-ID: <tencent_A4482251DD0890F312758FA6B33F60815609@qq.com>
8
Signed-off-by: Anup Patel <anup@brainfault.org>
9
Reviewed-by: Frank Chang <frank.chang@sifive.com>
10
Message-id: 20220204174700.534953-16-anup@brainfault.org
9
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
10
---
12
---
11
hw/riscv/boot.c | 4 ++--
13
target/riscv/csr.c | 203 +++++++++++++++++++++++++++++++++++++++++++++
12
1 file changed, 2 insertions(+), 2 deletions(-)
14
1 file changed, 203 insertions(+)
13
15
14
diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
16
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/riscv/boot.c
18
--- a/target/riscv/csr.c
17
+++ b/hw/riscv/boot.c
19
+++ b/target/riscv/csr.c
18
@@ -XXX,XX +XXX,XX @@ static void riscv_load_initrd(MachineState *machine, uint64_t kernel_entry)
20
@@ -XXX,XX +XXX,XX @@ static int aia_xlate_vs_csrno(CPURISCVState *env, int csrno)
19
/* Some RISC-V machines (e.g. opentitan) don't have a fdt. */
21
return CSR_VSISELECT;
20
if (fdt) {
22
case CSR_SIREG:
21
end = start + size;
23
return CSR_VSIREG;
22
- qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start", start);
24
+ case CSR_SSETEIPNUM:
23
- qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end", end);
25
+ return CSR_VSSETEIPNUM;
24
+ qemu_fdt_setprop_u64(fdt, "/chosen", "linux,initrd-start", start);
26
+ case CSR_SCLREIPNUM:
25
+ qemu_fdt_setprop_u64(fdt, "/chosen", "linux,initrd-end", end);
27
+ return CSR_VSCLREIPNUM;
26
}
28
+ case CSR_SSETEIENUM:
29
+ return CSR_VSSETEIENUM;
30
+ case CSR_SCLREIENUM:
31
+ return CSR_VSCLREIENUM;
32
+ case CSR_STOPEI:
33
+ return CSR_VSTOPEI;
34
default:
35
return csrno;
36
};
37
@@ -XXX,XX +XXX,XX @@ done:
38
return RISCV_EXCP_NONE;
27
}
39
}
28
40
41
+static int rmw_xsetclreinum(CPURISCVState *env, int csrno, target_ulong *val,
42
+ target_ulong new_val, target_ulong wr_mask)
43
+{
44
+ int ret = -EINVAL;
45
+ bool set, pend, virt;
46
+ target_ulong priv, isel, vgein, xlen, nval, wmask;
47
+
48
+ /* Translate CSR number for VS-mode */
49
+ csrno = aia_xlate_vs_csrno(env, csrno);
50
+
51
+ /* Decode register details from CSR number */
52
+ virt = set = pend = false;
53
+ switch (csrno) {
54
+ case CSR_MSETEIPNUM:
55
+ priv = PRV_M;
56
+ set = true;
57
+ pend = true;
58
+ break;
59
+ case CSR_MCLREIPNUM:
60
+ priv = PRV_M;
61
+ pend = true;
62
+ break;
63
+ case CSR_MSETEIENUM:
64
+ priv = PRV_M;
65
+ set = true;
66
+ break;
67
+ case CSR_MCLREIENUM:
68
+ priv = PRV_M;
69
+ break;
70
+ case CSR_SSETEIPNUM:
71
+ priv = PRV_S;
72
+ set = true;
73
+ pend = true;
74
+ break;
75
+ case CSR_SCLREIPNUM:
76
+ priv = PRV_S;
77
+ pend = true;
78
+ break;
79
+ case CSR_SSETEIENUM:
80
+ priv = PRV_S;
81
+ set = true;
82
+ break;
83
+ case CSR_SCLREIENUM:
84
+ priv = PRV_S;
85
+ break;
86
+ case CSR_VSSETEIPNUM:
87
+ priv = PRV_S;
88
+ virt = true;
89
+ set = true;
90
+ pend = true;
91
+ break;
92
+ case CSR_VSCLREIPNUM:
93
+ priv = PRV_S;
94
+ virt = true;
95
+ pend = true;
96
+ break;
97
+ case CSR_VSSETEIENUM:
98
+ priv = PRV_S;
99
+ virt = true;
100
+ set = true;
101
+ break;
102
+ case CSR_VSCLREIENUM:
103
+ priv = PRV_S;
104
+ virt = true;
105
+ break;
106
+ default:
107
+ goto done;
108
+ };
109
+
110
+ /* IMSIC CSRs only available when machine implements IMSIC. */
111
+ if (!env->aia_ireg_rmw_fn[priv]) {
112
+ goto done;
113
+ }
114
+
115
+ /* Find the selected guest interrupt file */
116
+ vgein = (virt) ? get_field(env->hstatus, HSTATUS_VGEIN) : 0;
117
+
118
+ /* Selected guest interrupt file should be valid */
119
+ if (virt && (!vgein || env->geilen < vgein)) {
120
+ goto done;
121
+ }
122
+
123
+ /* Set/Clear CSRs always read zero */
124
+ if (val) {
125
+ *val = 0;
126
+ }
127
+
128
+ if (wr_mask) {
129
+ /* Get interrupt number */
130
+ new_val &= wr_mask;
131
+
132
+ /* Find target interrupt pending/enable register */
133
+ xlen = riscv_cpu_mxl_bits(env);
134
+ isel = (new_val / xlen);
135
+ isel *= (xlen / IMSIC_EIPx_BITS);
136
+ isel += (pend) ? ISELECT_IMSIC_EIP0 : ISELECT_IMSIC_EIE0;
137
+
138
+ /* Find the interrupt bit to be set/clear */
139
+ wmask = ((target_ulong)1) << (new_val % xlen);
140
+ nval = (set) ? wmask : 0;
141
+
142
+ /* Call machine specific IMSIC register emulation */
143
+ ret = env->aia_ireg_rmw_fn[priv](env->aia_ireg_rmw_fn_arg[priv],
144
+ AIA_MAKE_IREG(isel, priv, virt,
145
+ vgein, xlen),
146
+ NULL, nval, wmask);
147
+ } else {
148
+ ret = 0;
149
+ }
150
+
151
+done:
152
+ if (ret) {
153
+ return (riscv_cpu_virt_enabled(env) && virt) ?
154
+ RISCV_EXCP_VIRT_INSTRUCTION_FAULT : RISCV_EXCP_ILLEGAL_INST;
155
+ }
156
+ return RISCV_EXCP_NONE;
157
+}
158
+
159
+static int rmw_xtopei(CPURISCVState *env, int csrno, target_ulong *val,
160
+ target_ulong new_val, target_ulong wr_mask)
161
+{
162
+ bool virt;
163
+ int ret = -EINVAL;
164
+ target_ulong priv, vgein;
165
+
166
+ /* Translate CSR number for VS-mode */
167
+ csrno = aia_xlate_vs_csrno(env, csrno);
168
+
169
+ /* Decode register details from CSR number */
170
+ virt = false;
171
+ switch (csrno) {
172
+ case CSR_MTOPEI:
173
+ priv = PRV_M;
174
+ break;
175
+ case CSR_STOPEI:
176
+ priv = PRV_S;
177
+ break;
178
+ case CSR_VSTOPEI:
179
+ priv = PRV_S;
180
+ virt = true;
181
+ break;
182
+ default:
183
+ goto done;
184
+ };
185
+
186
+ /* IMSIC CSRs only available when machine implements IMSIC. */
187
+ if (!env->aia_ireg_rmw_fn[priv]) {
188
+ goto done;
189
+ }
190
+
191
+ /* Find the selected guest interrupt file */
192
+ vgein = (virt) ? get_field(env->hstatus, HSTATUS_VGEIN) : 0;
193
+
194
+ /* Selected guest interrupt file should be valid */
195
+ if (virt && (!vgein || env->geilen < vgein)) {
196
+ goto done;
197
+ }
198
+
199
+ /* Call machine specific IMSIC register emulation for TOPEI */
200
+ ret = env->aia_ireg_rmw_fn[priv](env->aia_ireg_rmw_fn_arg[priv],
201
+ AIA_MAKE_IREG(ISELECT_IMSIC_TOPEI, priv, virt, vgein,
202
+ riscv_cpu_mxl_bits(env)),
203
+ val, new_val, wr_mask);
204
+
205
+done:
206
+ if (ret) {
207
+ return (riscv_cpu_virt_enabled(env) && virt) ?
208
+ RISCV_EXCP_VIRT_INSTRUCTION_FAULT : RISCV_EXCP_ILLEGAL_INST;
209
+ }
210
+ return RISCV_EXCP_NONE;
211
+}
212
+
213
static RISCVException read_mtvec(CPURISCVState *env, int csrno,
214
target_ulong *val)
215
{
216
@@ -XXX,XX +XXX,XX @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
217
/* Machine-Level Interrupts (AIA) */
218
[CSR_MTOPI] = { "mtopi", aia_any, read_mtopi },
219
220
+ /* Machine-Level IMSIC Interface (AIA) */
221
+ [CSR_MSETEIPNUM] = { "mseteipnum", aia_any, NULL, NULL, rmw_xsetclreinum },
222
+ [CSR_MCLREIPNUM] = { "mclreipnum", aia_any, NULL, NULL, rmw_xsetclreinum },
223
+ [CSR_MSETEIENUM] = { "mseteienum", aia_any, NULL, NULL, rmw_xsetclreinum },
224
+ [CSR_MCLREIENUM] = { "mclreienum", aia_any, NULL, NULL, rmw_xsetclreinum },
225
+ [CSR_MTOPEI] = { "mtopei", aia_any, NULL, NULL, rmw_xtopei },
226
+
227
/* Virtual Interrupts for Supervisor Level (AIA) */
228
[CSR_MVIEN] = { "mvien", aia_any, read_zero, write_ignore },
229
[CSR_MVIP] = { "mvip", aia_any, read_zero, write_ignore },
230
@@ -XXX,XX +XXX,XX @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
231
/* Supervisor-Level Interrupts (AIA) */
232
[CSR_STOPI] = { "stopi", aia_smode, read_stopi },
233
234
+ /* Supervisor-Level IMSIC Interface (AIA) */
235
+ [CSR_SSETEIPNUM] = { "sseteipnum", aia_smode, NULL, NULL, rmw_xsetclreinum },
236
+ [CSR_SCLREIPNUM] = { "sclreipnum", aia_smode, NULL, NULL, rmw_xsetclreinum },
237
+ [CSR_SSETEIENUM] = { "sseteienum", aia_smode, NULL, NULL, rmw_xsetclreinum },
238
+ [CSR_SCLREIENUM] = { "sclreienum", aia_smode, NULL, NULL, rmw_xsetclreinum },
239
+ [CSR_STOPEI] = { "stopei", aia_smode, NULL, NULL, rmw_xtopei },
240
+
241
/* Supervisor-Level High-Half CSRs (AIA) */
242
[CSR_SIEH] = { "sieh", aia_smode32, NULL, NULL, rmw_sieh },
243
[CSR_SIPH] = { "siph", aia_smode32, NULL, NULL, rmw_siph },
244
@@ -XXX,XX +XXX,XX @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
245
/* VS-Level Interrupts (H-extension with AIA) */
246
[CSR_VSTOPI] = { "vstopi", aia_hmode, read_vstopi },
247
248
+ /* VS-Level IMSIC Interface (H-extension with AIA) */
249
+ [CSR_VSSETEIPNUM] = { "vsseteipnum", aia_hmode, NULL, NULL, rmw_xsetclreinum },
250
+ [CSR_VSCLREIPNUM] = { "vsclreipnum", aia_hmode, NULL, NULL, rmw_xsetclreinum },
251
+ [CSR_VSSETEIENUM] = { "vsseteienum", aia_hmode, NULL, NULL, rmw_xsetclreinum },
252
+ [CSR_VSCLREIENUM] = { "vsclreienum", aia_hmode, NULL, NULL, rmw_xsetclreinum },
253
+ [CSR_VSTOPEI] = { "vstopei", aia_hmode, NULL, NULL, rmw_xtopei },
254
+
255
/* Hypervisor and VS-Level High-Half CSRs (H-extension with AIA) */
256
[CSR_HIDELEGH] = { "hidelegh", aia_hmode32, NULL, NULL, rmw_hidelegh },
257
[CSR_HVIENH] = { "hvienh", aia_hmode32, read_zero, write_ignore },
29
--
258
--
30
2.45.1
259
2.34.1
260
261
diff view generated by jsdifflib
New patch
1
From: Anup Patel <anup.patel@wdc.com>
1
2
3
We should use the AIA INTC compatible string in the CPU INTC
4
DT nodes when the CPUs support AIA feature. This will allow
5
Linux INTC driver to use AIA local interrupt CSRs.
6
7
Signed-off-by: Anup Patel <anup.patel@wdc.com>
8
Signed-off-by: Anup Patel <anup@brainfault.org>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Reviewed-by: Frank Chang <frank.chang@sifive.com>
11
Message-id: 20220204174700.534953-17-anup@brainfault.org
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
13
---
14
hw/riscv/virt.c | 13 +++++++++++--
15
1 file changed, 11 insertions(+), 2 deletions(-)
16
17
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/riscv/virt.c
20
+++ b/hw/riscv/virt.c
21
@@ -XXX,XX +XXX,XX @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int socket,
22
qemu_fdt_add_subnode(mc->fdt, intc_name);
23
qemu_fdt_setprop_cell(mc->fdt, intc_name, "phandle",
24
intc_phandles[cpu]);
25
- qemu_fdt_setprop_string(mc->fdt, intc_name, "compatible",
26
- "riscv,cpu-intc");
27
+ if (riscv_feature(&s->soc[socket].harts[cpu].env,
28
+ RISCV_FEATURE_AIA)) {
29
+ static const char * const compat[2] = {
30
+ "riscv,cpu-intc-aia", "riscv,cpu-intc"
31
+ };
32
+ qemu_fdt_setprop_string_array(mc->fdt, intc_name, "compatible",
33
+ (char **)&compat, ARRAY_SIZE(compat));
34
+ } else {
35
+ qemu_fdt_setprop_string(mc->fdt, intc_name, "compatible",
36
+ "riscv,cpu-intc");
37
+ }
38
qemu_fdt_setprop(mc->fdt, intc_name, "interrupt-controller", NULL, 0);
39
qemu_fdt_setprop_cell(mc->fdt, intc_name, "#interrupt-cells", 1);
40
41
--
42
2.34.1
43
44
diff view generated by jsdifflib
1
From: Yong-Xuan Wang <yongxuan.wang@sifive.com>
1
From: Anup Patel <anup.patel@wdc.com>
2
2
3
In AIA spec, each hart (or each hart within a group) has a unique hart
3
We add "x-aia" command-line option for RISC-V HART using which
4
number to locate the memory pages of interrupt files in the address
4
allows users to force enable CPU AIA CSRs without changing the
5
space. The number of bits required to represent any hart number is equal
5
interrupt controller available in RISC-V machine.
6
to ceil(log2(hmax + 1)), where hmax is the largest hart number among
7
groups.
8
6
9
However, if the largest hart number among groups is a power of 2, QEMU
7
Signed-off-by: Anup Patel <anup.patel@wdc.com>
10
will pass an inaccurate hart-index-bit setting to Linux. For example, when
8
Signed-off-by: Anup Patel <anup@brainfault.org>
11
the guest OS has 4 harts, only ceil(log2(3 + 1)) = 2 bits are sufficient
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
12
to represent 4 harts, but we passes 3 to Linux. The code needs to be
10
Reviewed-by: Frank Chang <frank.chang@sifive.com>
13
updated to ensure accurate hart-index-bit settings.
11
Message-id: 20220204174700.534953-18-anup@brainfault.org
14
15
Additionally, a Linux patch[1] is necessary to correctly recover the hart
16
index when the guest OS has only 1 hart, where the hart-index-bit is 0.
17
18
[1] https://lore.kernel.org/lkml/20240415064905.25184-1-yongxuan.wang@sifive.com/t/
19
20
Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com>
21
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
22
Cc: qemu-stable <qemu-stable@nongnu.org>
23
Message-ID: <20240515091129.28116-1-yongxuan.wang@sifive.com>
24
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
25
---
13
---
26
target/riscv/kvm/kvm-cpu.c | 9 ++++++++-
14
target/riscv/cpu.h | 1 +
27
1 file changed, 8 insertions(+), 1 deletion(-)
15
target/riscv/cpu.c | 5 +++++
16
2 files changed, 6 insertions(+)
28
17
29
diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
18
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
30
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
31
--- a/target/riscv/kvm/kvm-cpu.c
20
--- a/target/riscv/cpu.h
32
+++ b/target/riscv/kvm/kvm-cpu.c
21
+++ b/target/riscv/cpu.h
33
@@ -XXX,XX +XXX,XX @@ void kvm_riscv_aia_create(MachineState *machine, uint64_t group_shift,
22
@@ -XXX,XX +XXX,XX @@ struct RISCVCPUConfig {
23
bool mmu;
24
bool pmp;
25
bool epmp;
26
+ bool aia;
27
uint64_t resetvec;
28
};
29
30
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/target/riscv/cpu.c
33
+++ b/target/riscv/cpu.c
34
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
34
}
35
}
35
}
36
}
36
37
37
- hart_bits = find_last_bit(&max_hart_per_socket, BITS_PER_LONG) + 1;
38
+ if (cpu->cfg.aia) {
38
+
39
+ riscv_set_feature(env, RISCV_FEATURE_AIA);
39
+ if (max_hart_per_socket > 1) {
40
+ max_hart_per_socket--;
41
+ hart_bits = find_last_bit(&max_hart_per_socket, BITS_PER_LONG) + 1;
42
+ } else {
43
+ hart_bits = 0;
44
+ }
40
+ }
45
+
41
+
46
ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
42
set_resetvec(env, cpu->cfg.resetvec);
47
KVM_DEV_RISCV_AIA_CONFIG_HART_BITS,
43
48
&hart_bits, true, NULL);
44
/* Validate that MISA_MXL is set properly. */
45
@@ -XXX,XX +XXX,XX @@ static Property riscv_cpu_properties[] = {
46
DEFINE_PROP_BOOL("x-j", RISCVCPU, cfg.ext_j, false),
47
/* ePMP 0.9.3 */
48
DEFINE_PROP_BOOL("x-epmp", RISCVCPU, cfg.epmp, false),
49
+ DEFINE_PROP_BOOL("x-aia", RISCVCPU, cfg.aia, false),
50
51
DEFINE_PROP_UINT64("resetvec", RISCVCPU, cfg.resetvec, DEFAULT_RSTVEC),
52
DEFINE_PROP_END_OF_LIST(),
49
--
53
--
50
2.45.1
54
2.34.1
55
56
diff view generated by jsdifflib
1
From: "yang.zhang" <yang.zhang@hexintek.com>
1
From: Anup Patel <anup.patel@wdc.com>
2
2
3
Since only root APLICs can have hw IRQ lines, aplic->parent should
3
The RISC-V AIA (Advanced Interrupt Architecture) defines a new
4
be initialized first.
4
interrupt controller for wired interrupts called APLIC (Advanced
5
Platform Level Interrupt Controller). The APLIC is capabable of
6
forwarding wired interupts to RISC-V HARTs directly or as MSIs
7
(Message Signaled Interupts).
5
8
6
Fixes: e8f79343cf ("hw/intc: Add RISC-V AIA APLIC device emulation")
9
This patch adds device emulation for RISC-V AIA APLIC.
7
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
10
8
Signed-off-by: yang.zhang <yang.zhang@hexintek.com>
11
Signed-off-by: Anup Patel <anup.patel@wdc.com>
9
Cc: qemu-stable <qemu-stable@nongnu.org>
12
Signed-off-by: Anup Patel <anup@brainfault.org>
10
Message-ID: <20240409014445.278-1-gaoshanliukou@163.com>
13
Reviewed-by: Frank Chang <frank.chang@sifive.com>
14
Message-id: 20220204174700.534953-19-anup@brainfault.org
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
15
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
---
16
---
13
hw/intc/riscv_aplic.c | 8 ++++----
17
include/hw/intc/riscv_aplic.h | 79 +++
14
1 file changed, 4 insertions(+), 4 deletions(-)
18
hw/intc/riscv_aplic.c | 978 ++++++++++++++++++++++++++++++++++
19
hw/intc/Kconfig | 3 +
20
hw/intc/meson.build | 1 +
21
4 files changed, 1061 insertions(+)
22
create mode 100644 include/hw/intc/riscv_aplic.h
23
create mode 100644 hw/intc/riscv_aplic.c
15
24
25
diff --git a/include/hw/intc/riscv_aplic.h b/include/hw/intc/riscv_aplic.h
26
new file mode 100644
27
index XXXXXXX..XXXXXXX
28
--- /dev/null
29
+++ b/include/hw/intc/riscv_aplic.h
30
@@ -XXX,XX +XXX,XX @@
31
+/*
32
+ * RISC-V APLIC (Advanced Platform Level Interrupt Controller) interface
33
+ *
34
+ * Copyright (c) 2021 Western Digital Corporation or its affiliates.
35
+ *
36
+ * This program is free software; you can redistribute it and/or modify it
37
+ * under the terms and conditions of the GNU General Public License,
38
+ * version 2 or later, as published by the Free Software Foundation.
39
+ *
40
+ * This program is distributed in the hope it will be useful, but WITHOUT
41
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
42
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
43
+ * more details.
44
+ *
45
+ * You should have received a copy of the GNU General Public License along with
46
+ * this program. If not, see <http://www.gnu.org/licenses/>.
47
+ */
48
+
49
+#ifndef HW_RISCV_APLIC_H
50
+#define HW_RISCV_APLIC_H
51
+
52
+#include "hw/sysbus.h"
53
+#include "qom/object.h"
54
+
55
+#define TYPE_RISCV_APLIC "riscv.aplic"
56
+
57
+typedef struct RISCVAPLICState RISCVAPLICState;
58
+DECLARE_INSTANCE_CHECKER(RISCVAPLICState, RISCV_APLIC, TYPE_RISCV_APLIC)
59
+
60
+#define APLIC_MIN_SIZE 0x4000
61
+#define APLIC_SIZE_ALIGN(__x) (((__x) + (APLIC_MIN_SIZE - 1)) & \
62
+ ~(APLIC_MIN_SIZE - 1))
63
+#define APLIC_SIZE(__num_harts) (APLIC_MIN_SIZE + \
64
+ APLIC_SIZE_ALIGN(32 * (__num_harts)))
65
+
66
+struct RISCVAPLICState {
67
+ /*< private >*/
68
+ SysBusDevice parent_obj;
69
+ qemu_irq *external_irqs;
70
+
71
+ /*< public >*/
72
+ MemoryRegion mmio;
73
+ uint32_t bitfield_words;
74
+ uint32_t domaincfg;
75
+ uint32_t mmsicfgaddr;
76
+ uint32_t mmsicfgaddrH;
77
+ uint32_t smsicfgaddr;
78
+ uint32_t smsicfgaddrH;
79
+ uint32_t genmsi;
80
+ uint32_t *sourcecfg;
81
+ uint32_t *state;
82
+ uint32_t *target;
83
+ uint32_t *idelivery;
84
+ uint32_t *iforce;
85
+ uint32_t *ithreshold;
86
+
87
+ /* topology */
88
+#define QEMU_APLIC_MAX_CHILDREN 16
89
+ struct RISCVAPLICState *parent;
90
+ struct RISCVAPLICState *children[QEMU_APLIC_MAX_CHILDREN];
91
+ uint16_t num_children;
92
+
93
+ /* config */
94
+ uint32_t aperture_size;
95
+ uint32_t hartid_base;
96
+ uint32_t num_harts;
97
+ uint32_t iprio_mask;
98
+ uint32_t num_irqs;
99
+ bool msimode;
100
+ bool mmode;
101
+};
102
+
103
+void riscv_aplic_add_child(DeviceState *parent, DeviceState *child);
104
+
105
+DeviceState *riscv_aplic_create(hwaddr addr, hwaddr size,
106
+ uint32_t hartid_base, uint32_t num_harts, uint32_t num_sources,
107
+ uint32_t iprio_bits, bool msimode, bool mmode, DeviceState *parent);
108
+
109
+#endif
16
diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
110
diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
17
index XXXXXXX..XXXXXXX 100644
111
new file mode 100644
18
--- a/hw/intc/riscv_aplic.c
112
index XXXXXXX..XXXXXXX
113
--- /dev/null
19
+++ b/hw/intc/riscv_aplic.c
114
+++ b/hw/intc/riscv_aplic.c
20
@@ -XXX,XX +XXX,XX @@ DeviceState *riscv_aplic_create(hwaddr addr, hwaddr size,
115
@@ -XXX,XX +XXX,XX @@
21
qdev_prop_set_bit(dev, "msimode", msimode);
116
+/*
22
qdev_prop_set_bit(dev, "mmode", mmode);
117
+ * RISC-V APLIC (Advanced Platform Level Interrupt Controller)
23
118
+ *
119
+ * Copyright (c) 2021 Western Digital Corporation or its affiliates.
120
+ *
121
+ * This program is free software; you can redistribute it and/or modify it
122
+ * under the terms and conditions of the GNU General Public License,
123
+ * version 2 or later, as published by the Free Software Foundation.
124
+ *
125
+ * This program is distributed in the hope it will be useful, but WITHOUT
126
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
127
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
128
+ * more details.
129
+ *
130
+ * You should have received a copy of the GNU General Public License along with
131
+ * this program. If not, see <http://www.gnu.org/licenses/>.
132
+ */
133
+
134
+#include "qemu/osdep.h"
135
+#include "qapi/error.h"
136
+#include "qemu/log.h"
137
+#include "qemu/module.h"
138
+#include "qemu/error-report.h"
139
+#include "qemu/bswap.h"
140
+#include "exec/address-spaces.h"
141
+#include "hw/sysbus.h"
142
+#include "hw/pci/msi.h"
143
+#include "hw/boards.h"
144
+#include "hw/qdev-properties.h"
145
+#include "hw/intc/riscv_aplic.h"
146
+#include "hw/irq.h"
147
+#include "target/riscv/cpu.h"
148
+#include "sysemu/sysemu.h"
149
+#include "migration/vmstate.h"
150
+
151
+#define APLIC_MAX_IDC (1UL << 14)
152
+#define APLIC_MAX_SOURCE 1024
153
+#define APLIC_MIN_IPRIO_BITS 1
154
+#define APLIC_MAX_IPRIO_BITS 8
155
+#define APLIC_MAX_CHILDREN 1024
156
+
157
+#define APLIC_DOMAINCFG 0x0000
158
+#define APLIC_DOMAINCFG_RDONLY 0x80000000
159
+#define APLIC_DOMAINCFG_IE (1 << 8)
160
+#define APLIC_DOMAINCFG_DM (1 << 2)
161
+#define APLIC_DOMAINCFG_BE (1 << 0)
162
+
163
+#define APLIC_SOURCECFG_BASE 0x0004
164
+#define APLIC_SOURCECFG_D (1 << 10)
165
+#define APLIC_SOURCECFG_CHILDIDX_MASK 0x000003ff
166
+#define APLIC_SOURCECFG_SM_MASK 0x00000007
167
+#define APLIC_SOURCECFG_SM_INACTIVE 0x0
168
+#define APLIC_SOURCECFG_SM_DETACH 0x1
169
+#define APLIC_SOURCECFG_SM_EDGE_RISE 0x4
170
+#define APLIC_SOURCECFG_SM_EDGE_FALL 0x5
171
+#define APLIC_SOURCECFG_SM_LEVEL_HIGH 0x6
172
+#define APLIC_SOURCECFG_SM_LEVEL_LOW 0x7
173
+
174
+#define APLIC_MMSICFGADDR 0x1bc0
175
+#define APLIC_MMSICFGADDRH 0x1bc4
176
+#define APLIC_SMSICFGADDR 0x1bc8
177
+#define APLIC_SMSICFGADDRH 0x1bcc
178
+
179
+#define APLIC_xMSICFGADDRH_L (1UL << 31)
180
+#define APLIC_xMSICFGADDRH_HHXS_MASK 0x1f
181
+#define APLIC_xMSICFGADDRH_HHXS_SHIFT 24
182
+#define APLIC_xMSICFGADDRH_LHXS_MASK 0x7
183
+#define APLIC_xMSICFGADDRH_LHXS_SHIFT 20
184
+#define APLIC_xMSICFGADDRH_HHXW_MASK 0x7
185
+#define APLIC_xMSICFGADDRH_HHXW_SHIFT 16
186
+#define APLIC_xMSICFGADDRH_LHXW_MASK 0xf
187
+#define APLIC_xMSICFGADDRH_LHXW_SHIFT 12
188
+#define APLIC_xMSICFGADDRH_BAPPN_MASK 0xfff
189
+
190
+#define APLIC_xMSICFGADDR_PPN_SHIFT 12
191
+
192
+#define APLIC_xMSICFGADDR_PPN_HART(__lhxs) \
193
+ ((1UL << (__lhxs)) - 1)
194
+
195
+#define APLIC_xMSICFGADDR_PPN_LHX_MASK(__lhxw) \
196
+ ((1UL << (__lhxw)) - 1)
197
+#define APLIC_xMSICFGADDR_PPN_LHX_SHIFT(__lhxs) \
198
+ ((__lhxs))
199
+#define APLIC_xMSICFGADDR_PPN_LHX(__lhxw, __lhxs) \
200
+ (APLIC_xMSICFGADDR_PPN_LHX_MASK(__lhxw) << \
201
+ APLIC_xMSICFGADDR_PPN_LHX_SHIFT(__lhxs))
202
+
203
+#define APLIC_xMSICFGADDR_PPN_HHX_MASK(__hhxw) \
204
+ ((1UL << (__hhxw)) - 1)
205
+#define APLIC_xMSICFGADDR_PPN_HHX_SHIFT(__hhxs) \
206
+ ((__hhxs) + APLIC_xMSICFGADDR_PPN_SHIFT)
207
+#define APLIC_xMSICFGADDR_PPN_HHX(__hhxw, __hhxs) \
208
+ (APLIC_xMSICFGADDR_PPN_HHX_MASK(__hhxw) << \
209
+ APLIC_xMSICFGADDR_PPN_HHX_SHIFT(__hhxs))
210
+
211
+#define APLIC_xMSICFGADDRH_VALID_MASK \
212
+ (APLIC_xMSICFGADDRH_L | \
213
+ (APLIC_xMSICFGADDRH_HHXS_MASK << APLIC_xMSICFGADDRH_HHXS_SHIFT) | \
214
+ (APLIC_xMSICFGADDRH_LHXS_MASK << APLIC_xMSICFGADDRH_LHXS_SHIFT) | \
215
+ (APLIC_xMSICFGADDRH_HHXW_MASK << APLIC_xMSICFGADDRH_HHXW_SHIFT) | \
216
+ (APLIC_xMSICFGADDRH_LHXW_MASK << APLIC_xMSICFGADDRH_LHXW_SHIFT) | \
217
+ APLIC_xMSICFGADDRH_BAPPN_MASK)
218
+
219
+#define APLIC_SETIP_BASE 0x1c00
220
+#define APLIC_SETIPNUM 0x1cdc
221
+
222
+#define APLIC_CLRIP_BASE 0x1d00
223
+#define APLIC_CLRIPNUM 0x1ddc
224
+
225
+#define APLIC_SETIE_BASE 0x1e00
226
+#define APLIC_SETIENUM 0x1edc
227
+
228
+#define APLIC_CLRIE_BASE 0x1f00
229
+#define APLIC_CLRIENUM 0x1fdc
230
+
231
+#define APLIC_SETIPNUM_LE 0x2000
232
+#define APLIC_SETIPNUM_BE 0x2004
233
+
234
+#define APLIC_ISTATE_PENDING (1U << 0)
235
+#define APLIC_ISTATE_ENABLED (1U << 1)
236
+#define APLIC_ISTATE_ENPEND (APLIC_ISTATE_ENABLED | \
237
+ APLIC_ISTATE_PENDING)
238
+#define APLIC_ISTATE_INPUT (1U << 8)
239
+
240
+#define APLIC_GENMSI 0x3000
241
+
242
+#define APLIC_TARGET_BASE 0x3004
243
+#define APLIC_TARGET_HART_IDX_SHIFT 18
244
+#define APLIC_TARGET_HART_IDX_MASK 0x3fff
245
+#define APLIC_TARGET_GUEST_IDX_SHIFT 12
246
+#define APLIC_TARGET_GUEST_IDX_MASK 0x3f
247
+#define APLIC_TARGET_IPRIO_MASK 0xff
248
+#define APLIC_TARGET_EIID_MASK 0x7ff
249
+
250
+#define APLIC_IDC_BASE 0x4000
251
+#define APLIC_IDC_SIZE 32
252
+
253
+#define APLIC_IDC_IDELIVERY 0x00
254
+
255
+#define APLIC_IDC_IFORCE 0x04
256
+
257
+#define APLIC_IDC_ITHRESHOLD 0x08
258
+
259
+#define APLIC_IDC_TOPI 0x18
260
+#define APLIC_IDC_TOPI_ID_SHIFT 16
261
+#define APLIC_IDC_TOPI_ID_MASK 0x3ff
262
+#define APLIC_IDC_TOPI_PRIO_MASK 0xff
263
+
264
+#define APLIC_IDC_CLAIMI 0x1c
265
+
266
+static uint32_t riscv_aplic_read_input_word(RISCVAPLICState *aplic,
267
+ uint32_t word)
268
+{
269
+ uint32_t i, irq, ret = 0;
270
+
271
+ for (i = 0; i < 32; i++) {
272
+ irq = word * 32 + i;
273
+ if (!irq || aplic->num_irqs <= irq) {
274
+ continue;
275
+ }
276
+
277
+ ret |= ((aplic->state[irq] & APLIC_ISTATE_INPUT) ? 1 : 0) << i;
278
+ }
279
+
280
+ return ret;
281
+}
282
+
283
+static uint32_t riscv_aplic_read_pending_word(RISCVAPLICState *aplic,
284
+ uint32_t word)
285
+{
286
+ uint32_t i, irq, ret = 0;
287
+
288
+ for (i = 0; i < 32; i++) {
289
+ irq = word * 32 + i;
290
+ if (!irq || aplic->num_irqs <= irq) {
291
+ continue;
292
+ }
293
+
294
+ ret |= ((aplic->state[irq] & APLIC_ISTATE_PENDING) ? 1 : 0) << i;
295
+ }
296
+
297
+ return ret;
298
+}
299
+
300
+static void riscv_aplic_set_pending_raw(RISCVAPLICState *aplic,
301
+ uint32_t irq, bool pending)
302
+{
303
+ if (pending) {
304
+ aplic->state[irq] |= APLIC_ISTATE_PENDING;
305
+ } else {
306
+ aplic->state[irq] &= ~APLIC_ISTATE_PENDING;
307
+ }
308
+}
309
+
310
+static void riscv_aplic_set_pending(RISCVAPLICState *aplic,
311
+ uint32_t irq, bool pending)
312
+{
313
+ uint32_t sourcecfg, sm;
314
+
315
+ if ((irq <= 0) || (aplic->num_irqs <= irq)) {
316
+ return;
317
+ }
318
+
319
+ sourcecfg = aplic->sourcecfg[irq];
320
+ if (sourcecfg & APLIC_SOURCECFG_D) {
321
+ return;
322
+ }
323
+
324
+ sm = sourcecfg & APLIC_SOURCECFG_SM_MASK;
325
+ if ((sm == APLIC_SOURCECFG_SM_INACTIVE) ||
326
+ ((!aplic->msimode || (aplic->msimode && !pending)) &&
327
+ ((sm == APLIC_SOURCECFG_SM_LEVEL_HIGH) ||
328
+ (sm == APLIC_SOURCECFG_SM_LEVEL_LOW)))) {
329
+ return;
330
+ }
331
+
332
+ riscv_aplic_set_pending_raw(aplic, irq, pending);
333
+}
334
+
335
+static void riscv_aplic_set_pending_word(RISCVAPLICState *aplic,
336
+ uint32_t word, uint32_t value,
337
+ bool pending)
338
+{
339
+ uint32_t i, irq;
340
+
341
+ for (i = 0; i < 32; i++) {
342
+ irq = word * 32 + i;
343
+ if (!irq || aplic->num_irqs <= irq) {
344
+ continue;
345
+ }
346
+
347
+ if (value & (1U << i)) {
348
+ riscv_aplic_set_pending(aplic, irq, pending);
349
+ }
350
+ }
351
+}
352
+
353
+static uint32_t riscv_aplic_read_enabled_word(RISCVAPLICState *aplic,
354
+ int word)
355
+{
356
+ uint32_t i, irq, ret = 0;
357
+
358
+ for (i = 0; i < 32; i++) {
359
+ irq = word * 32 + i;
360
+ if (!irq || aplic->num_irqs <= irq) {
361
+ continue;
362
+ }
363
+
364
+ ret |= ((aplic->state[irq] & APLIC_ISTATE_ENABLED) ? 1 : 0) << i;
365
+ }
366
+
367
+ return ret;
368
+}
369
+
370
+static void riscv_aplic_set_enabled_raw(RISCVAPLICState *aplic,
371
+ uint32_t irq, bool enabled)
372
+{
373
+ if (enabled) {
374
+ aplic->state[irq] |= APLIC_ISTATE_ENABLED;
375
+ } else {
376
+ aplic->state[irq] &= ~APLIC_ISTATE_ENABLED;
377
+ }
378
+}
379
+
380
+static void riscv_aplic_set_enabled(RISCVAPLICState *aplic,
381
+ uint32_t irq, bool enabled)
382
+{
383
+ uint32_t sourcecfg, sm;
384
+
385
+ if ((irq <= 0) || (aplic->num_irqs <= irq)) {
386
+ return;
387
+ }
388
+
389
+ sourcecfg = aplic->sourcecfg[irq];
390
+ if (sourcecfg & APLIC_SOURCECFG_D) {
391
+ return;
392
+ }
393
+
394
+ sm = sourcecfg & APLIC_SOURCECFG_SM_MASK;
395
+ if (sm == APLIC_SOURCECFG_SM_INACTIVE) {
396
+ return;
397
+ }
398
+
399
+ riscv_aplic_set_enabled_raw(aplic, irq, enabled);
400
+}
401
+
402
+static void riscv_aplic_set_enabled_word(RISCVAPLICState *aplic,
403
+ uint32_t word, uint32_t value,
404
+ bool enabled)
405
+{
406
+ uint32_t i, irq;
407
+
408
+ for (i = 0; i < 32; i++) {
409
+ irq = word * 32 + i;
410
+ if (!irq || aplic->num_irqs <= irq) {
411
+ continue;
412
+ }
413
+
414
+ if (value & (1U << i)) {
415
+ riscv_aplic_set_enabled(aplic, irq, enabled);
416
+ }
417
+ }
418
+}
419
+
420
+static void riscv_aplic_msi_send(RISCVAPLICState *aplic,
421
+ uint32_t hart_idx, uint32_t guest_idx,
422
+ uint32_t eiid)
423
+{
424
+ uint64_t addr;
425
+ MemTxResult result;
426
+ RISCVAPLICState *aplic_m;
427
+ uint32_t lhxs, lhxw, hhxs, hhxw, group_idx, msicfgaddr, msicfgaddrH;
428
+
429
+ aplic_m = aplic;
430
+ while (aplic_m && !aplic_m->mmode) {
431
+ aplic_m = aplic_m->parent;
432
+ }
433
+ if (!aplic_m) {
434
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: m-level APLIC not found\n",
435
+ __func__);
436
+ return;
437
+ }
438
+
439
+ if (aplic->mmode) {
440
+ msicfgaddr = aplic_m->mmsicfgaddr;
441
+ msicfgaddrH = aplic_m->mmsicfgaddrH;
442
+ } else {
443
+ msicfgaddr = aplic_m->smsicfgaddr;
444
+ msicfgaddrH = aplic_m->smsicfgaddrH;
445
+ }
446
+
447
+ lhxs = (msicfgaddrH >> APLIC_xMSICFGADDRH_LHXS_SHIFT) &
448
+ APLIC_xMSICFGADDRH_LHXS_MASK;
449
+ lhxw = (msicfgaddrH >> APLIC_xMSICFGADDRH_LHXW_SHIFT) &
450
+ APLIC_xMSICFGADDRH_LHXW_MASK;
451
+ hhxs = (msicfgaddrH >> APLIC_xMSICFGADDRH_HHXS_SHIFT) &
452
+ APLIC_xMSICFGADDRH_HHXS_MASK;
453
+ hhxw = (msicfgaddrH >> APLIC_xMSICFGADDRH_HHXW_SHIFT) &
454
+ APLIC_xMSICFGADDRH_HHXW_MASK;
455
+
456
+ group_idx = hart_idx >> lhxw;
457
+ hart_idx &= APLIC_xMSICFGADDR_PPN_LHX_MASK(lhxw);
458
+
459
+ addr = msicfgaddr;
460
+ addr |= ((uint64_t)(msicfgaddrH & APLIC_xMSICFGADDRH_BAPPN_MASK)) << 32;
461
+ addr |= ((uint64_t)(group_idx & APLIC_xMSICFGADDR_PPN_HHX_MASK(hhxw))) <<
462
+ APLIC_xMSICFGADDR_PPN_HHX_SHIFT(hhxs);
463
+ addr |= ((uint64_t)(hart_idx & APLIC_xMSICFGADDR_PPN_LHX_MASK(lhxw))) <<
464
+ APLIC_xMSICFGADDR_PPN_LHX_SHIFT(lhxs);
465
+ addr |= (uint64_t)(guest_idx & APLIC_xMSICFGADDR_PPN_HART(lhxs));
466
+ addr <<= APLIC_xMSICFGADDR_PPN_SHIFT;
467
+
468
+ address_space_stl_le(&address_space_memory, addr,
469
+ eiid, MEMTXATTRS_UNSPECIFIED, &result);
470
+ if (result != MEMTX_OK) {
471
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: MSI write failed for "
472
+ "hart_index=%d guest_index=%d eiid=%d\n",
473
+ __func__, hart_idx, guest_idx, eiid);
474
+ }
475
+}
476
+
477
+static void riscv_aplic_msi_irq_update(RISCVAPLICState *aplic, uint32_t irq)
478
+{
479
+ uint32_t hart_idx, guest_idx, eiid;
480
+
481
+ if (!aplic->msimode || (aplic->num_irqs <= irq) ||
482
+ !(aplic->domaincfg & APLIC_DOMAINCFG_IE)) {
483
+ return;
484
+ }
485
+
486
+ if ((aplic->state[irq] & APLIC_ISTATE_ENPEND) != APLIC_ISTATE_ENPEND) {
487
+ return;
488
+ }
489
+
490
+ riscv_aplic_set_pending_raw(aplic, irq, false);
491
+
492
+ hart_idx = aplic->target[irq] >> APLIC_TARGET_HART_IDX_SHIFT;
493
+ hart_idx &= APLIC_TARGET_HART_IDX_MASK;
494
+ if (aplic->mmode) {
495
+ /* M-level APLIC ignores guest_index */
496
+ guest_idx = 0;
497
+ } else {
498
+ guest_idx = aplic->target[irq] >> APLIC_TARGET_GUEST_IDX_SHIFT;
499
+ guest_idx &= APLIC_TARGET_GUEST_IDX_MASK;
500
+ }
501
+ eiid = aplic->target[irq] & APLIC_TARGET_EIID_MASK;
502
+ riscv_aplic_msi_send(aplic, hart_idx, guest_idx, eiid);
503
+}
504
+
505
+static uint32_t riscv_aplic_idc_topi(RISCVAPLICState *aplic, uint32_t idc)
506
+{
507
+ uint32_t best_irq, best_iprio;
508
+ uint32_t irq, iprio, ihartidx, ithres;
509
+
510
+ if (aplic->num_harts <= idc) {
511
+ return 0;
512
+ }
513
+
514
+ ithres = aplic->ithreshold[idc];
515
+ best_irq = best_iprio = UINT32_MAX;
516
+ for (irq = 1; irq < aplic->num_irqs; irq++) {
517
+ if ((aplic->state[irq] & APLIC_ISTATE_ENPEND) !=
518
+ APLIC_ISTATE_ENPEND) {
519
+ continue;
520
+ }
521
+
522
+ ihartidx = aplic->target[irq] >> APLIC_TARGET_HART_IDX_SHIFT;
523
+ ihartidx &= APLIC_TARGET_HART_IDX_MASK;
524
+ if (ihartidx != idc) {
525
+ continue;
526
+ }
527
+
528
+ iprio = aplic->target[irq] & aplic->iprio_mask;
529
+ if (ithres && iprio >= ithres) {
530
+ continue;
531
+ }
532
+
533
+ if (iprio < best_iprio) {
534
+ best_irq = irq;
535
+ best_iprio = iprio;
536
+ }
537
+ }
538
+
539
+ if (best_irq < aplic->num_irqs && best_iprio <= aplic->iprio_mask) {
540
+ return (best_irq << APLIC_IDC_TOPI_ID_SHIFT) | best_iprio;
541
+ }
542
+
543
+ return 0;
544
+}
545
+
546
+static void riscv_aplic_idc_update(RISCVAPLICState *aplic, uint32_t idc)
547
+{
548
+ uint32_t topi;
549
+
550
+ if (aplic->msimode || aplic->num_harts <= idc) {
551
+ return;
552
+ }
553
+
554
+ topi = riscv_aplic_idc_topi(aplic, idc);
555
+ if ((aplic->domaincfg & APLIC_DOMAINCFG_IE) &&
556
+ aplic->idelivery[idc] &&
557
+ (aplic->iforce[idc] || topi)) {
558
+ qemu_irq_raise(aplic->external_irqs[idc]);
559
+ } else {
560
+ qemu_irq_lower(aplic->external_irqs[idc]);
561
+ }
562
+}
563
+
564
+static uint32_t riscv_aplic_idc_claimi(RISCVAPLICState *aplic, uint32_t idc)
565
+{
566
+ uint32_t irq, state, sm, topi = riscv_aplic_idc_topi(aplic, idc);
567
+
568
+ if (!topi) {
569
+ aplic->iforce[idc] = 0;
570
+ return 0;
571
+ }
572
+
573
+ irq = (topi >> APLIC_IDC_TOPI_ID_SHIFT) & APLIC_IDC_TOPI_ID_MASK;
574
+ sm = aplic->sourcecfg[irq] & APLIC_SOURCECFG_SM_MASK;
575
+ state = aplic->state[irq];
576
+ riscv_aplic_set_pending_raw(aplic, irq, false);
577
+ if ((sm == APLIC_SOURCECFG_SM_LEVEL_HIGH) &&
578
+ (state & APLIC_ISTATE_INPUT)) {
579
+ riscv_aplic_set_pending_raw(aplic, irq, true);
580
+ } else if ((sm == APLIC_SOURCECFG_SM_LEVEL_LOW) &&
581
+ !(state & APLIC_ISTATE_INPUT)) {
582
+ riscv_aplic_set_pending_raw(aplic, irq, true);
583
+ }
584
+ riscv_aplic_idc_update(aplic, idc);
585
+
586
+ return topi;
587
+}
588
+
589
+static void riscv_aplic_request(void *opaque, int irq, int level)
590
+{
591
+ bool update = false;
592
+ RISCVAPLICState *aplic = opaque;
593
+ uint32_t sourcecfg, childidx, state, idc;
594
+
595
+ assert((0 < irq) && (irq < aplic->num_irqs));
596
+
597
+ sourcecfg = aplic->sourcecfg[irq];
598
+ if (sourcecfg & APLIC_SOURCECFG_D) {
599
+ childidx = sourcecfg & APLIC_SOURCECFG_CHILDIDX_MASK;
600
+ if (childidx < aplic->num_children) {
601
+ riscv_aplic_request(aplic->children[childidx], irq, level);
602
+ }
603
+ return;
604
+ }
605
+
606
+ state = aplic->state[irq];
607
+ switch (sourcecfg & APLIC_SOURCECFG_SM_MASK) {
608
+ case APLIC_SOURCECFG_SM_EDGE_RISE:
609
+ if ((level > 0) && !(state & APLIC_ISTATE_INPUT) &&
610
+ !(state & APLIC_ISTATE_PENDING)) {
611
+ riscv_aplic_set_pending_raw(aplic, irq, true);
612
+ update = true;
613
+ }
614
+ break;
615
+ case APLIC_SOURCECFG_SM_EDGE_FALL:
616
+ if ((level <= 0) && (state & APLIC_ISTATE_INPUT) &&
617
+ !(state & APLIC_ISTATE_PENDING)) {
618
+ riscv_aplic_set_pending_raw(aplic, irq, true);
619
+ update = true;
620
+ }
621
+ break;
622
+ case APLIC_SOURCECFG_SM_LEVEL_HIGH:
623
+ if ((level > 0) && !(state & APLIC_ISTATE_PENDING)) {
624
+ riscv_aplic_set_pending_raw(aplic, irq, true);
625
+ update = true;
626
+ }
627
+ break;
628
+ case APLIC_SOURCECFG_SM_LEVEL_LOW:
629
+ if ((level <= 0) && !(state & APLIC_ISTATE_PENDING)) {
630
+ riscv_aplic_set_pending_raw(aplic, irq, true);
631
+ update = true;
632
+ }
633
+ break;
634
+ default:
635
+ break;
636
+ }
637
+
638
+ if (level <= 0) {
639
+ aplic->state[irq] &= ~APLIC_ISTATE_INPUT;
640
+ } else {
641
+ aplic->state[irq] |= APLIC_ISTATE_INPUT;
642
+ }
643
+
644
+ if (update) {
645
+ if (aplic->msimode) {
646
+ riscv_aplic_msi_irq_update(aplic, irq);
647
+ } else {
648
+ idc = aplic->target[irq] >> APLIC_TARGET_HART_IDX_SHIFT;
649
+ idc &= APLIC_TARGET_HART_IDX_MASK;
650
+ riscv_aplic_idc_update(aplic, idc);
651
+ }
652
+ }
653
+}
654
+
655
+static uint64_t riscv_aplic_read(void *opaque, hwaddr addr, unsigned size)
656
+{
657
+ uint32_t irq, word, idc;
658
+ RISCVAPLICState *aplic = opaque;
659
+
660
+ /* Reads must be 4 byte words */
661
+ if ((addr & 0x3) != 0) {
662
+ goto err;
663
+ }
664
+
665
+ if (addr == APLIC_DOMAINCFG) {
666
+ return APLIC_DOMAINCFG_RDONLY | aplic->domaincfg |
667
+ (aplic->msimode ? APLIC_DOMAINCFG_DM : 0);
668
+ } else if ((APLIC_SOURCECFG_BASE <= addr) &&
669
+ (addr < (APLIC_SOURCECFG_BASE + (aplic->num_irqs - 1) * 4))) {
670
+ irq = ((addr - APLIC_SOURCECFG_BASE) >> 2) + 1;
671
+ return aplic->sourcecfg[irq];
672
+ } else if (aplic->mmode && aplic->msimode &&
673
+ (addr == APLIC_MMSICFGADDR)) {
674
+ return aplic->mmsicfgaddr;
675
+ } else if (aplic->mmode && aplic->msimode &&
676
+ (addr == APLIC_MMSICFGADDRH)) {
677
+ return aplic->mmsicfgaddrH;
678
+ } else if (aplic->mmode && aplic->msimode &&
679
+ (addr == APLIC_SMSICFGADDR)) {
680
+ /*
681
+ * Registers SMSICFGADDR and SMSICFGADDRH are implemented only if:
682
+ * (a) the interrupt domain is at machine level
683
+ * (b) the domain's harts implement supervisor mode
684
+ * (c) the domain has one or more child supervisor-level domains
685
+ * that support MSI delivery mode (domaincfg.DM is not read-
686
+ * only zero in at least one of the supervisor-level child
687
+ * domains).
688
+ */
689
+ return (aplic->num_children) ? aplic->smsicfgaddr : 0;
690
+ } else if (aplic->mmode && aplic->msimode &&
691
+ (addr == APLIC_SMSICFGADDRH)) {
692
+ return (aplic->num_children) ? aplic->smsicfgaddrH : 0;
693
+ } else if ((APLIC_SETIP_BASE <= addr) &&
694
+ (addr < (APLIC_SETIP_BASE + aplic->bitfield_words * 4))) {
695
+ word = (addr - APLIC_SETIP_BASE) >> 2;
696
+ return riscv_aplic_read_pending_word(aplic, word);
697
+ } else if (addr == APLIC_SETIPNUM) {
698
+ return 0;
699
+ } else if ((APLIC_CLRIP_BASE <= addr) &&
700
+ (addr < (APLIC_CLRIP_BASE + aplic->bitfield_words * 4))) {
701
+ word = (addr - APLIC_CLRIP_BASE) >> 2;
702
+ return riscv_aplic_read_input_word(aplic, word);
703
+ } else if (addr == APLIC_CLRIPNUM) {
704
+ return 0;
705
+ } else if ((APLIC_SETIE_BASE <= addr) &&
706
+ (addr < (APLIC_SETIE_BASE + aplic->bitfield_words * 4))) {
707
+ word = (addr - APLIC_SETIE_BASE) >> 2;
708
+ return riscv_aplic_read_enabled_word(aplic, word);
709
+ } else if (addr == APLIC_SETIENUM) {
710
+ return 0;
711
+ } else if ((APLIC_CLRIE_BASE <= addr) &&
712
+ (addr < (APLIC_CLRIE_BASE + aplic->bitfield_words * 4))) {
713
+ return 0;
714
+ } else if (addr == APLIC_CLRIENUM) {
715
+ return 0;
716
+ } else if (addr == APLIC_SETIPNUM_LE) {
717
+ return 0;
718
+ } else if (addr == APLIC_SETIPNUM_BE) {
719
+ return 0;
720
+ } else if (addr == APLIC_GENMSI) {
721
+ return (aplic->msimode) ? aplic->genmsi : 0;
722
+ } else if ((APLIC_TARGET_BASE <= addr) &&
723
+ (addr < (APLIC_TARGET_BASE + (aplic->num_irqs - 1) * 4))) {
724
+ irq = ((addr - APLIC_TARGET_BASE) >> 2) + 1;
725
+ return aplic->target[irq];
726
+ } else if (!aplic->msimode && (APLIC_IDC_BASE <= addr) &&
727
+ (addr < (APLIC_IDC_BASE + aplic->num_harts * APLIC_IDC_SIZE))) {
728
+ idc = (addr - APLIC_IDC_BASE) / APLIC_IDC_SIZE;
729
+ switch (addr - (APLIC_IDC_BASE + idc * APLIC_IDC_SIZE)) {
730
+ case APLIC_IDC_IDELIVERY:
731
+ return aplic->idelivery[idc];
732
+ case APLIC_IDC_IFORCE:
733
+ return aplic->iforce[idc];
734
+ case APLIC_IDC_ITHRESHOLD:
735
+ return aplic->ithreshold[idc];
736
+ case APLIC_IDC_TOPI:
737
+ return riscv_aplic_idc_topi(aplic, idc);
738
+ case APLIC_IDC_CLAIMI:
739
+ return riscv_aplic_idc_claimi(aplic, idc);
740
+ default:
741
+ goto err;
742
+ };
743
+ }
744
+
745
+err:
746
+ qemu_log_mask(LOG_GUEST_ERROR,
747
+ "%s: Invalid register read 0x%" HWADDR_PRIx "\n",
748
+ __func__, addr);
749
+ return 0;
750
+}
751
+
752
+static void riscv_aplic_write(void *opaque, hwaddr addr, uint64_t value,
753
+ unsigned size)
754
+{
755
+ RISCVAPLICState *aplic = opaque;
756
+ uint32_t irq, word, idc = UINT32_MAX;
757
+
758
+ /* Writes must be 4 byte words */
759
+ if ((addr & 0x3) != 0) {
760
+ goto err;
761
+ }
762
+
763
+ if (addr == APLIC_DOMAINCFG) {
764
+ /* Only IE bit writeable at the moment */
765
+ value &= APLIC_DOMAINCFG_IE;
766
+ aplic->domaincfg = value;
767
+ } else if ((APLIC_SOURCECFG_BASE <= addr) &&
768
+ (addr < (APLIC_SOURCECFG_BASE + (aplic->num_irqs - 1) * 4))) {
769
+ irq = ((addr - APLIC_SOURCECFG_BASE) >> 2) + 1;
770
+ if (!aplic->num_children && (value & APLIC_SOURCECFG_D)) {
771
+ value = 0;
772
+ }
773
+ if (value & APLIC_SOURCECFG_D) {
774
+ value &= (APLIC_SOURCECFG_D | APLIC_SOURCECFG_CHILDIDX_MASK);
775
+ } else {
776
+ value &= (APLIC_SOURCECFG_D | APLIC_SOURCECFG_SM_MASK);
777
+ }
778
+ aplic->sourcecfg[irq] = value;
779
+ if ((aplic->sourcecfg[irq] & APLIC_SOURCECFG_D) ||
780
+ (aplic->sourcecfg[irq] == 0)) {
781
+ riscv_aplic_set_pending_raw(aplic, irq, false);
782
+ riscv_aplic_set_enabled_raw(aplic, irq, false);
783
+ }
784
+ } else if (aplic->mmode && aplic->msimode &&
785
+ (addr == APLIC_MMSICFGADDR)) {
786
+ if (!(aplic->mmsicfgaddrH & APLIC_xMSICFGADDRH_L)) {
787
+ aplic->mmsicfgaddr = value;
788
+ }
789
+ } else if (aplic->mmode && aplic->msimode &&
790
+ (addr == APLIC_MMSICFGADDRH)) {
791
+ if (!(aplic->mmsicfgaddrH & APLIC_xMSICFGADDRH_L)) {
792
+ aplic->mmsicfgaddrH = value & APLIC_xMSICFGADDRH_VALID_MASK;
793
+ }
794
+ } else if (aplic->mmode && aplic->msimode &&
795
+ (addr == APLIC_SMSICFGADDR)) {
796
+ /*
797
+ * Registers SMSICFGADDR and SMSICFGADDRH are implemented only if:
798
+ * (a) the interrupt domain is at machine level
799
+ * (b) the domain's harts implement supervisor mode
800
+ * (c) the domain has one or more child supervisor-level domains
801
+ * that support MSI delivery mode (domaincfg.DM is not read-
802
+ * only zero in at least one of the supervisor-level child
803
+ * domains).
804
+ */
805
+ if (aplic->num_children &&
806
+ !(aplic->smsicfgaddrH & APLIC_xMSICFGADDRH_L)) {
807
+ aplic->smsicfgaddr = value;
808
+ }
809
+ } else if (aplic->mmode && aplic->msimode &&
810
+ (addr == APLIC_SMSICFGADDRH)) {
811
+ if (aplic->num_children &&
812
+ !(aplic->smsicfgaddrH & APLIC_xMSICFGADDRH_L)) {
813
+ aplic->smsicfgaddrH = value & APLIC_xMSICFGADDRH_VALID_MASK;
814
+ }
815
+ } else if ((APLIC_SETIP_BASE <= addr) &&
816
+ (addr < (APLIC_SETIP_BASE + aplic->bitfield_words * 4))) {
817
+ word = (addr - APLIC_SETIP_BASE) >> 2;
818
+ riscv_aplic_set_pending_word(aplic, word, value, true);
819
+ } else if (addr == APLIC_SETIPNUM) {
820
+ riscv_aplic_set_pending(aplic, value, true);
821
+ } else if ((APLIC_CLRIP_BASE <= addr) &&
822
+ (addr < (APLIC_CLRIP_BASE + aplic->bitfield_words * 4))) {
823
+ word = (addr - APLIC_CLRIP_BASE) >> 2;
824
+ riscv_aplic_set_pending_word(aplic, word, value, false);
825
+ } else if (addr == APLIC_CLRIPNUM) {
826
+ riscv_aplic_set_pending(aplic, value, false);
827
+ } else if ((APLIC_SETIE_BASE <= addr) &&
828
+ (addr < (APLIC_SETIE_BASE + aplic->bitfield_words * 4))) {
829
+ word = (addr - APLIC_SETIE_BASE) >> 2;
830
+ riscv_aplic_set_enabled_word(aplic, word, value, true);
831
+ } else if (addr == APLIC_SETIENUM) {
832
+ riscv_aplic_set_enabled(aplic, value, true);
833
+ } else if ((APLIC_CLRIE_BASE <= addr) &&
834
+ (addr < (APLIC_CLRIE_BASE + aplic->bitfield_words * 4))) {
835
+ word = (addr - APLIC_CLRIE_BASE) >> 2;
836
+ riscv_aplic_set_enabled_word(aplic, word, value, false);
837
+ } else if (addr == APLIC_CLRIENUM) {
838
+ riscv_aplic_set_enabled(aplic, value, false);
839
+ } else if (addr == APLIC_SETIPNUM_LE) {
840
+ riscv_aplic_set_pending(aplic, value, true);
841
+ } else if (addr == APLIC_SETIPNUM_BE) {
842
+ riscv_aplic_set_pending(aplic, bswap32(value), true);
843
+ } else if (addr == APLIC_GENMSI) {
844
+ if (aplic->msimode) {
845
+ aplic->genmsi = value & ~(APLIC_TARGET_GUEST_IDX_MASK <<
846
+ APLIC_TARGET_GUEST_IDX_SHIFT);
847
+ riscv_aplic_msi_send(aplic,
848
+ value >> APLIC_TARGET_HART_IDX_SHIFT,
849
+ 0,
850
+ value & APLIC_TARGET_EIID_MASK);
851
+ }
852
+ } else if ((APLIC_TARGET_BASE <= addr) &&
853
+ (addr < (APLIC_TARGET_BASE + (aplic->num_irqs - 1) * 4))) {
854
+ irq = ((addr - APLIC_TARGET_BASE) >> 2) + 1;
855
+ if (aplic->msimode) {
856
+ aplic->target[irq] = value;
857
+ } else {
858
+ aplic->target[irq] = (value & ~APLIC_TARGET_IPRIO_MASK) |
859
+ ((value & aplic->iprio_mask) ?
860
+ (value & aplic->iprio_mask) : 1);
861
+ }
862
+ } else if (!aplic->msimode && (APLIC_IDC_BASE <= addr) &&
863
+ (addr < (APLIC_IDC_BASE + aplic->num_harts * APLIC_IDC_SIZE))) {
864
+ idc = (addr - APLIC_IDC_BASE) / APLIC_IDC_SIZE;
865
+ switch (addr - (APLIC_IDC_BASE + idc * APLIC_IDC_SIZE)) {
866
+ case APLIC_IDC_IDELIVERY:
867
+ aplic->idelivery[idc] = value & 0x1;
868
+ break;
869
+ case APLIC_IDC_IFORCE:
870
+ aplic->iforce[idc] = value & 0x1;
871
+ break;
872
+ case APLIC_IDC_ITHRESHOLD:
873
+ aplic->ithreshold[idc] = value & aplic->iprio_mask;
874
+ break;
875
+ default:
876
+ goto err;
877
+ };
878
+ } else {
879
+ goto err;
880
+ }
881
+
882
+ if (aplic->msimode) {
883
+ for (irq = 1; irq < aplic->num_irqs; irq++) {
884
+ riscv_aplic_msi_irq_update(aplic, irq);
885
+ }
886
+ } else {
887
+ if (idc == UINT32_MAX) {
888
+ for (idc = 0; idc < aplic->num_harts; idc++) {
889
+ riscv_aplic_idc_update(aplic, idc);
890
+ }
891
+ } else {
892
+ riscv_aplic_idc_update(aplic, idc);
893
+ }
894
+ }
895
+
896
+ return;
897
+
898
+err:
899
+ qemu_log_mask(LOG_GUEST_ERROR,
900
+ "%s: Invalid register write 0x%" HWADDR_PRIx "\n",
901
+ __func__, addr);
902
+}
903
+
904
+static const MemoryRegionOps riscv_aplic_ops = {
905
+ .read = riscv_aplic_read,
906
+ .write = riscv_aplic_write,
907
+ .endianness = DEVICE_LITTLE_ENDIAN,
908
+ .valid = {
909
+ .min_access_size = 4,
910
+ .max_access_size = 4
911
+ }
912
+};
913
+
914
+static void riscv_aplic_realize(DeviceState *dev, Error **errp)
915
+{
916
+ uint32_t i;
917
+ RISCVAPLICState *aplic = RISCV_APLIC(dev);
918
+
919
+ aplic->bitfield_words = (aplic->num_irqs + 31) >> 5;
920
+ aplic->sourcecfg = g_new0(uint32_t, aplic->num_irqs);
921
+ aplic->state = g_new(uint32_t, aplic->num_irqs);
922
+ aplic->target = g_new0(uint32_t, aplic->num_irqs);
923
+ if (!aplic->msimode) {
924
+ for (i = 0; i < aplic->num_irqs; i++) {
925
+ aplic->target[i] = 1;
926
+ }
927
+ }
928
+ aplic->idelivery = g_new0(uint32_t, aplic->num_harts);
929
+ aplic->iforce = g_new0(uint32_t, aplic->num_harts);
930
+ aplic->ithreshold = g_new0(uint32_t, aplic->num_harts);
931
+
932
+ memory_region_init_io(&aplic->mmio, OBJECT(dev), &riscv_aplic_ops, aplic,
933
+ TYPE_RISCV_APLIC, aplic->aperture_size);
934
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &aplic->mmio);
935
+
936
+ /*
937
+ * Only root APLICs have hardware IRQ lines. All non-root APLICs
938
+ * have IRQ lines delegated by their parent APLIC.
939
+ */
940
+ if (!aplic->parent) {
941
+ qdev_init_gpio_in(dev, riscv_aplic_request, aplic->num_irqs);
942
+ }
943
+
944
+ /* Create output IRQ lines for non-MSI mode */
945
+ if (!aplic->msimode) {
946
+ aplic->external_irqs = g_malloc(sizeof(qemu_irq) * aplic->num_harts);
947
+ qdev_init_gpio_out(dev, aplic->external_irqs, aplic->num_harts);
948
+
949
+ /* Claim the CPU interrupt to be triggered by this APLIC */
950
+ for (i = 0; i < aplic->num_harts; i++) {
951
+ RISCVCPU *cpu = RISCV_CPU(qemu_get_cpu(aplic->hartid_base + i));
952
+ if (riscv_cpu_claim_interrupts(cpu,
953
+ (aplic->mmode) ? MIP_MEIP : MIP_SEIP) < 0) {
954
+ error_report("%s already claimed",
955
+ (aplic->mmode) ? "MEIP" : "SEIP");
956
+ exit(1);
957
+ }
958
+ }
959
+ }
960
+
961
+ msi_nonbroken = true;
962
+}
963
+
964
+static Property riscv_aplic_properties[] = {
965
+ DEFINE_PROP_UINT32("aperture-size", RISCVAPLICState, aperture_size, 0),
966
+ DEFINE_PROP_UINT32("hartid-base", RISCVAPLICState, hartid_base, 0),
967
+ DEFINE_PROP_UINT32("num-harts", RISCVAPLICState, num_harts, 0),
968
+ DEFINE_PROP_UINT32("iprio-mask", RISCVAPLICState, iprio_mask, 0),
969
+ DEFINE_PROP_UINT32("num-irqs", RISCVAPLICState, num_irqs, 0),
970
+ DEFINE_PROP_BOOL("msimode", RISCVAPLICState, msimode, 0),
971
+ DEFINE_PROP_BOOL("mmode", RISCVAPLICState, mmode, 0),
972
+ DEFINE_PROP_END_OF_LIST(),
973
+};
974
+
975
+static const VMStateDescription vmstate_riscv_aplic = {
976
+ .name = "riscv_aplic",
977
+ .version_id = 1,
978
+ .minimum_version_id = 1,
979
+ .fields = (VMStateField[]) {
980
+ VMSTATE_UINT32(domaincfg, RISCVAPLICState),
981
+ VMSTATE_UINT32(mmsicfgaddr, RISCVAPLICState),
982
+ VMSTATE_UINT32(mmsicfgaddrH, RISCVAPLICState),
983
+ VMSTATE_UINT32(smsicfgaddr, RISCVAPLICState),
984
+ VMSTATE_UINT32(smsicfgaddrH, RISCVAPLICState),
985
+ VMSTATE_UINT32(genmsi, RISCVAPLICState),
986
+ VMSTATE_VARRAY_UINT32(sourcecfg, RISCVAPLICState,
987
+ num_irqs, 0,
988
+ vmstate_info_uint32, uint32_t),
989
+ VMSTATE_VARRAY_UINT32(state, RISCVAPLICState,
990
+ num_irqs, 0,
991
+ vmstate_info_uint32, uint32_t),
992
+ VMSTATE_VARRAY_UINT32(target, RISCVAPLICState,
993
+ num_irqs, 0,
994
+ vmstate_info_uint32, uint32_t),
995
+ VMSTATE_VARRAY_UINT32(idelivery, RISCVAPLICState,
996
+ num_harts, 0,
997
+ vmstate_info_uint32, uint32_t),
998
+ VMSTATE_VARRAY_UINT32(iforce, RISCVAPLICState,
999
+ num_harts, 0,
1000
+ vmstate_info_uint32, uint32_t),
1001
+ VMSTATE_VARRAY_UINT32(ithreshold, RISCVAPLICState,
1002
+ num_harts, 0,
1003
+ vmstate_info_uint32, uint32_t),
1004
+ VMSTATE_END_OF_LIST()
1005
+ }
1006
+};
1007
+
1008
+static void riscv_aplic_class_init(ObjectClass *klass, void *data)
1009
+{
1010
+ DeviceClass *dc = DEVICE_CLASS(klass);
1011
+
1012
+ device_class_set_props(dc, riscv_aplic_properties);
1013
+ dc->realize = riscv_aplic_realize;
1014
+ dc->vmsd = &vmstate_riscv_aplic;
1015
+}
1016
+
1017
+static const TypeInfo riscv_aplic_info = {
1018
+ .name = TYPE_RISCV_APLIC,
1019
+ .parent = TYPE_SYS_BUS_DEVICE,
1020
+ .instance_size = sizeof(RISCVAPLICState),
1021
+ .class_init = riscv_aplic_class_init,
1022
+};
1023
+
1024
+static void riscv_aplic_register_types(void)
1025
+{
1026
+ type_register_static(&riscv_aplic_info);
1027
+}
1028
+
1029
+type_init(riscv_aplic_register_types)
1030
+
1031
+/*
1032
+ * Add a APLIC device to another APLIC device as child for
1033
+ * interrupt delegation.
1034
+ */
1035
+void riscv_aplic_add_child(DeviceState *parent, DeviceState *child)
1036
+{
1037
+ RISCVAPLICState *caplic, *paplic;
1038
+
1039
+ assert(parent && child);
1040
+ caplic = RISCV_APLIC(child);
1041
+ paplic = RISCV_APLIC(parent);
1042
+
1043
+ assert(paplic->num_irqs == caplic->num_irqs);
1044
+ assert(paplic->num_children <= QEMU_APLIC_MAX_CHILDREN);
1045
+
1046
+ caplic->parent = paplic;
1047
+ paplic->children[paplic->num_children] = caplic;
1048
+ paplic->num_children++;
1049
+}
1050
+
1051
+/*
1052
+ * Create APLIC device.
1053
+ */
1054
+DeviceState *riscv_aplic_create(hwaddr addr, hwaddr size,
1055
+ uint32_t hartid_base, uint32_t num_harts, uint32_t num_sources,
1056
+ uint32_t iprio_bits, bool msimode, bool mmode, DeviceState *parent)
1057
+{
1058
+ DeviceState *dev = qdev_new(TYPE_RISCV_APLIC);
1059
+ uint32_t i;
1060
+
1061
+ assert(num_harts < APLIC_MAX_IDC);
1062
+ assert((APLIC_IDC_BASE + (num_harts * APLIC_IDC_SIZE)) <= size);
1063
+ assert(num_sources < APLIC_MAX_SOURCE);
1064
+ assert(APLIC_MIN_IPRIO_BITS <= iprio_bits);
1065
+ assert(iprio_bits <= APLIC_MAX_IPRIO_BITS);
1066
+
1067
+ qdev_prop_set_uint32(dev, "aperture-size", size);
1068
+ qdev_prop_set_uint32(dev, "hartid-base", hartid_base);
1069
+ qdev_prop_set_uint32(dev, "num-harts", num_harts);
1070
+ qdev_prop_set_uint32(dev, "iprio-mask", ((1U << iprio_bits) - 1));
1071
+ qdev_prop_set_uint32(dev, "num-irqs", num_sources + 1);
1072
+ qdev_prop_set_bit(dev, "msimode", msimode);
1073
+ qdev_prop_set_bit(dev, "mmode", mmode);
1074
+
1075
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
1076
+ sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
1077
+
24
+ if (parent) {
1078
+ if (parent) {
25
+ riscv_aplic_add_child(parent, dev);
1079
+ riscv_aplic_add_child(parent, dev);
26
+ }
1080
+ }
27
+
1081
+
28
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
1082
+ if (!msimode) {
29
1083
+ for (i = 0; i < num_harts; i++) {
30
if (!is_kvm_aia(msimode)) {
1084
+ CPUState *cpu = qemu_get_cpu(hartid_base + i);
31
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
1085
+
32
}
1086
+ qdev_connect_gpio_out_named(dev, NULL, i,
33
1087
+ qdev_get_gpio_in(DEVICE(cpu),
34
- if (parent) {
1088
+ (mmode) ? IRQ_M_EXT : IRQ_S_EXT));
35
- riscv_aplic_add_child(parent, dev);
1089
+ }
36
- }
1090
+ }
37
-
1091
+
38
if (!msimode) {
1092
+ return dev;
39
for (i = 0; i < num_harts; i++) {
1093
+}
40
CPUState *cpu = cpu_by_arch_id(hartid_base + i);
1094
diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
1095
index XXXXXXX..XXXXXXX 100644
1096
--- a/hw/intc/Kconfig
1097
+++ b/hw/intc/Kconfig
1098
@@ -XXX,XX +XXX,XX @@ config LOONGSON_LIOINTC
1099
config RISCV_ACLINT
1100
bool
1101
1102
+config RISCV_APLIC
1103
+ bool
1104
+
1105
config SIFIVE_PLIC
1106
bool
1107
1108
diff --git a/hw/intc/meson.build b/hw/intc/meson.build
1109
index XXXXXXX..XXXXXXX 100644
1110
--- a/hw/intc/meson.build
1111
+++ b/hw/intc/meson.build
1112
@@ -XXX,XX +XXX,XX @@ specific_ss.add(when: 'CONFIG_S390_FLIC', if_true: files('s390_flic.c'))
1113
specific_ss.add(when: 'CONFIG_S390_FLIC_KVM', if_true: files('s390_flic_kvm.c'))
1114
specific_ss.add(when: 'CONFIG_SH_INTC', if_true: files('sh_intc.c'))
1115
specific_ss.add(when: 'CONFIG_RISCV_ACLINT', if_true: files('riscv_aclint.c'))
1116
+specific_ss.add(when: 'CONFIG_RISCV_APLIC', if_true: files('riscv_aplic.c'))
1117
specific_ss.add(when: 'CONFIG_SIFIVE_PLIC', if_true: files('sifive_plic.c'))
1118
specific_ss.add(when: 'CONFIG_XICS', if_true: files('xics.c'))
1119
specific_ss.add(when: ['CONFIG_KVM', 'CONFIG_XICS'],
41
--
1120
--
42
2.45.1
1121
2.34.1
1122
1123
1124
diff view generated by jsdifflib
1
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
1
From: Guo Ren <ren_guo@c-sky.com>
2
2
3
raise_mmu_exception(), as is today, is prioritizing guest page faults by
3
Highest bits of PTE has been used for svpbmt, ref: [1], [2], so we
4
checking first if virt_enabled && !first_stage, and then considering the
4
need to ignore them. They cannot be a part of ppn.
5
regular inst/load/store faults.
6
5
7
There's no mention in the spec about guest page fault being a higher
6
1: The RISC-V Instruction Set Manual, Volume II: Privileged Architecture
8
priority that PMP faults. In fact, privileged spec section 3.7.1 says:
7
4.4 Sv39: Page-Based 39-bit Virtual-Memory System
8
4.5 Sv48: Page-Based 48-bit Virtual-Memory System
9
9
10
"Attempting to fetch an instruction from a PMP region that does not have
10
2: https://github.com/riscv/virtual-memory/blob/main/specs/663-Svpbmt-diff.pdf
11
execute permissions raises an instruction access-fault exception.
12
Attempting to execute a load or load-reserved instruction which accesses
13
a physical address within a PMP region without read permissions raises a
14
load access-fault exception. Attempting to execute a store,
15
store-conditional, or AMO instruction which accesses a physical address
16
within a PMP region without write permissions raises a store
17
access-fault exception."
18
11
19
So, in fact, we're doing it wrong - PMP faults should always be thrown,
12
Signed-off-by: Guo Ren <ren_guo@c-sky.com>
20
regardless of also being a first or second stage fault.
13
Reviewed-by: Liu Zhiwei <zhiwei_liu@c-sky.com>
21
22
The way riscv_cpu_tlb_fill() and get_physical_address() work is
23
adequate: a TRANSLATE_PMP_FAIL error is immediately reported and
24
reflected in the 'pmp_violation' flag. What we need is to change
25
raise_mmu_exception() to prioritize it.
26
27
Reported-by: Joseph Chan <jchan@ventanamicro.com>
28
Fixes: 82d53adfbb ("target/riscv/cpu_helper.c: Invalid exception on MMU translation stage")
29
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
30
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
14
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
31
Message-ID: <20240413105929.7030-1-alexei.filippov@syntacore.com>
15
Cc: Bin Meng <bmeng.cn@gmail.com>
32
Cc: qemu-stable <qemu-stable@nongnu.org>
16
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
17
Message-Id: <20220204022658.18097-2-liweiwei@iscas.ac.cn>
33
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
18
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
34
---
19
---
35
target/riscv/cpu_helper.c | 22 ++++++++++++----------
20
target/riscv/cpu.h | 15 +++++++++++++++
36
1 file changed, 12 insertions(+), 10 deletions(-)
21
target/riscv/cpu_bits.h | 3 +++
22
target/riscv/cpu_helper.c | 13 ++++++++++++-
23
3 files changed, 30 insertions(+), 1 deletion(-)
37
24
25
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
26
index XXXXXXX..XXXXXXX 100644
27
--- a/target/riscv/cpu.h
28
+++ b/target/riscv/cpu.h
29
@@ -XXX,XX +XXX,XX @@ struct RISCVCPUConfig {
30
bool ext_counters;
31
bool ext_ifencei;
32
bool ext_icsr;
33
+ bool ext_svnapot;
34
+ bool ext_svpbmt;
35
bool ext_zfh;
36
bool ext_zfhmin;
37
bool ext_zve32f;
38
@@ -XXX,XX +XXX,XX @@ static inline int riscv_cpu_xlen(CPURISCVState *env)
39
return 16 << env->xl;
40
}
41
42
+#ifdef TARGET_RISCV32
43
+#define riscv_cpu_sxl(env) ((void)(env), MXL_RV32)
44
+#else
45
+static inline RISCVMXL riscv_cpu_sxl(CPURISCVState *env)
46
+{
47
+#ifdef CONFIG_USER_ONLY
48
+ return env->misa_mxl;
49
+#else
50
+ return get_field(env->mstatus, MSTATUS64_SXL);
51
+#endif
52
+}
53
+#endif
54
+
55
/*
56
* Encode LMUL to lmul as follows:
57
* LMUL vlmul lmul
58
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
59
index XXXXXXX..XXXXXXX 100644
60
--- a/target/riscv/cpu_bits.h
61
+++ b/target/riscv/cpu_bits.h
62
@@ -XXX,XX +XXX,XX @@ typedef enum {
63
/* Page table PPN shift amount */
64
#define PTE_PPN_SHIFT 10
65
66
+/* Page table PPN mask */
67
+#define PTE_PPN_MASK 0x3FFFFFFFFFFC00ULL
68
+
69
/* Leaf page shift amount */
70
#define PGSHIFT 12
71
38
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
72
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
39
index XXXXXXX..XXXXXXX 100644
73
index XXXXXXX..XXXXXXX 100644
40
--- a/target/riscv/cpu_helper.c
74
--- a/target/riscv/cpu_helper.c
41
+++ b/target/riscv/cpu_helper.c
75
+++ b/target/riscv/cpu_helper.c
42
@@ -XXX,XX +XXX,XX @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
76
@@ -XXX,XX +XXX,XX @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
43
77
MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
44
switch (access_type) {
78
int mode = mmu_idx & TB_FLAGS_PRIV_MMU_MASK;
45
case MMU_INST_FETCH:
79
bool use_background = false;
46
- if (env->virt_enabled && !first_stage) {
80
+ hwaddr ppn;
47
+ if (pmp_violation) {
81
+ RISCVCPU *cpu = env_archcpu(env);
48
+ cs->exception_index = RISCV_EXCP_INST_ACCESS_FAULT;
82
49
+ } else if (env->virt_enabled && !first_stage) {
83
/*
50
cs->exception_index = RISCV_EXCP_INST_GUEST_PAGE_FAULT;
84
* Check if we should use the background registers for the two
51
} else {
85
@@ -XXX,XX +XXX,XX @@ restart:
52
- cs->exception_index = pmp_violation ?
86
return TRANSLATE_FAIL;
53
- RISCV_EXCP_INST_ACCESS_FAULT : RISCV_EXCP_INST_PAGE_FAULT;
54
+ cs->exception_index = RISCV_EXCP_INST_PAGE_FAULT;
55
}
87
}
56
break;
88
57
case MMU_DATA_LOAD:
89
- hwaddr ppn = pte >> PTE_PPN_SHIFT;
58
- if (two_stage && !first_stage) {
90
+ if (riscv_cpu_sxl(env) == MXL_RV32) {
59
+ if (pmp_violation) {
91
+ ppn = pte >> PTE_PPN_SHIFT;
60
+ cs->exception_index = RISCV_EXCP_LOAD_ACCESS_FAULT;
92
+ } else if (cpu->cfg.ext_svpbmt || cpu->cfg.ext_svnapot) {
61
+ } else if (two_stage && !first_stage) {
93
+ ppn = (pte & (target_ulong)PTE_PPN_MASK) >> PTE_PPN_SHIFT;
62
cs->exception_index = RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT;
94
+ } else {
63
} else {
95
+ ppn = pte >> PTE_PPN_SHIFT;
64
- cs->exception_index = pmp_violation ?
96
+ if ((pte & ~(target_ulong)PTE_PPN_MASK) >> PTE_PPN_SHIFT) {
65
- RISCV_EXCP_LOAD_ACCESS_FAULT : RISCV_EXCP_LOAD_PAGE_FAULT;
97
+ return TRANSLATE_FAIL;
66
+ cs->exception_index = RISCV_EXCP_LOAD_PAGE_FAULT;
98
+ }
67
}
99
+ }
68
break;
100
69
case MMU_DATA_STORE:
101
if (!(pte & PTE_V)) {
70
- if (two_stage && !first_stage) {
102
/* Invalid PTE */
71
+ if (pmp_violation) {
72
+ cs->exception_index = RISCV_EXCP_STORE_AMO_ACCESS_FAULT;
73
+ } else if (two_stage && !first_stage) {
74
cs->exception_index = RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT;
75
} else {
76
- cs->exception_index = pmp_violation ?
77
- RISCV_EXCP_STORE_AMO_ACCESS_FAULT :
78
- RISCV_EXCP_STORE_PAGE_FAULT;
79
+ cs->exception_index = RISCV_EXCP_STORE_PAGE_FAULT;
80
}
81
break;
82
default:
83
--
103
--
84
2.45.1
104
2.34.1
105
106
diff view generated by jsdifflib
1
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
1
From: Weiwei Li <liweiwei@iscas.ac.cn>
2
2
3
We're not setting (s/m)tval when triggering breakpoints of type 2
3
For non-leaf PTEs, the D, A, and U bits are reserved for future standard use.
4
(mcontrol) and 6 (mcontrol6). According to the debug spec section
5
5.7.12, "Match Control Type 6":
6
4
7
"The Privileged Spec says that breakpoint exceptions that occur on
5
Signed-off-by: Weiwei Li <liweiwei@iscas.ac.cn>
8
instruction fetches, loads, or stores update the tval CSR with either
6
Signed-off-by: Junqiang Wang <wangjunqiang@iscas.ac.cn>
9
zero or the faulting virtual address. The faulting virtual address for
7
Reviewed-by: Anup Patel <anup@brainfault.org>
10
an mcontrol6 trigger with action = 0 is the address being accessed and
11
which caused that trigger to fire."
12
13
A similar text is also found in the Debug spec section 5.7.11 w.r.t.
14
mcontrol.
15
16
Note that what we're doing ATM is not violating the spec, but it's
17
simple enough to set mtval/stval and it makes life easier for any
18
software that relies on this info.
19
20
Given that we always use action = 0, save the faulting address for the
21
mcontrol and mcontrol6 trigger breakpoints into env->badaddr, which is
22
used as as scratch area for traps with address information. 'tval' is
23
then set during riscv_cpu_do_interrupt().
24
25
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
26
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
27
Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
9
Message-Id: <20220204022658.18097-3-liweiwei@iscas.ac.cn>
28
Message-ID: <20240416230437.1869024-2-dbarboza@ventanamicro.com>
29
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
30
---
11
---
31
target/riscv/cpu_helper.c | 1 +
12
target/riscv/cpu_helper.c | 3 +++
32
target/riscv/debug.c | 3 +++
13
1 file changed, 3 insertions(+)
33
2 files changed, 4 insertions(+)
34
14
35
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
15
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
36
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
37
--- a/target/riscv/cpu_helper.c
17
--- a/target/riscv/cpu_helper.c
38
+++ b/target/riscv/cpu_helper.c
18
+++ b/target/riscv/cpu_helper.c
39
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_do_interrupt(CPUState *cs)
19
@@ -XXX,XX +XXX,XX @@ restart:
40
tval = env->bins;
20
return TRANSLATE_FAIL;
41
break;
21
} else if (!(pte & (PTE_R | PTE_W | PTE_X))) {
42
case RISCV_EXCP_BREAKPOINT:
22
/* Inner PTE, continue walking */
43
+ tval = env->badaddr;
23
+ if (pte & (PTE_D | PTE_A | PTE_U)) {
44
if (cs->watchpoint_hit) {
24
+ return TRANSLATE_FAIL;
45
tval = cs->watchpoint_hit->hitaddr;
25
+ }
46
cs->watchpoint_hit = NULL;
26
base = ppn << PGSHIFT;
47
diff --git a/target/riscv/debug.c b/target/riscv/debug.c
27
} else if ((pte & (PTE_R | PTE_W | PTE_X)) == PTE_W) {
48
index XXXXXXX..XXXXXXX 100644
28
/* Reserved leaf PTE flags: PTE_W */
49
--- a/target/riscv/debug.c
50
+++ b/target/riscv/debug.c
51
@@ -XXX,XX +XXX,XX @@ bool riscv_cpu_debug_check_breakpoint(CPUState *cs)
52
if ((ctrl & TYPE2_EXEC) && (bp->pc == pc)) {
53
/* check U/S/M bit against current privilege level */
54
if ((ctrl >> 3) & BIT(env->priv)) {
55
+ env->badaddr = pc;
56
return true;
57
}
58
}
59
@@ -XXX,XX +XXX,XX @@ bool riscv_cpu_debug_check_breakpoint(CPUState *cs)
60
if (env->virt_enabled) {
61
/* check VU/VS bit against current privilege level */
62
if ((ctrl >> 23) & BIT(env->priv)) {
63
+ env->badaddr = pc;
64
return true;
65
}
66
} else {
67
/* check U/S/M bit against current privilege level */
68
if ((ctrl >> 3) & BIT(env->priv)) {
69
+ env->badaddr = pc;
70
return true;
71
}
72
}
73
--
29
--
74
2.45.1
30
2.34.1
31
32
diff view generated by jsdifflib
1
From: Rob Bradford <rbradford@rivosinc.com>
1
From: Weiwei Li <liweiwei@iscas.ac.cn>
2
2
3
This extension has now been ratified:
3
- add PTE_N bit
4
https://jira.riscv.org/browse/RVS-2006 so the "x-" prefix can be
4
- add PTE_N bit check for inner PTE
5
removed.
5
- update address translation to support 64KiB continuous region (napot_bits = 4)
6
6
7
Since this is now a ratified extension add it to the list of extensions
7
Signed-off-by: Weiwei Li <liweiwei@iscas.ac.cn>
8
included in the "max" CPU variant.
8
Signed-off-by: Junqiang Wang <wangjunqiang@iscas.ac.cn>
9
9
Reviewed-by: Anup Patel <anup@brainfault.org>
10
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
11
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
12
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
13
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
11
Message-Id: <20220204022658.18097-4-liweiwei@iscas.ac.cn>
14
Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
15
Message-ID: <20240514110217.22516-1-rbradford@rivosinc.com>
16
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
17
---
13
---
18
target/riscv/cpu.c | 2 +-
14
target/riscv/cpu_bits.h | 1 +
19
target/riscv/tcg/tcg-cpu.c | 2 +-
15
target/riscv/cpu.c | 2 ++
20
2 files changed, 2 insertions(+), 2 deletions(-)
16
target/riscv/cpu_helper.c | 18 +++++++++++++++---
17
3 files changed, 18 insertions(+), 3 deletions(-)
21
18
19
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/riscv/cpu_bits.h
22
+++ b/target/riscv/cpu_bits.h
23
@@ -XXX,XX +XXX,XX @@ typedef enum {
24
#define PTE_A 0x040 /* Accessed */
25
#define PTE_D 0x080 /* Dirty */
26
#define PTE_SOFT 0x300 /* Reserved for Software */
27
+#define PTE_N 0x8000000000000000ULL /* NAPOT translation */
28
29
/* Page table PPN shift amount */
30
#define PTE_PPN_SHIFT 10
22
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
31
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
23
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
24
--- a/target/riscv/cpu.c
33
--- a/target/riscv/cpu.c
25
+++ b/target/riscv/cpu.c
34
+++ b/target/riscv/cpu.c
26
@@ -XXX,XX +XXX,XX @@ static const MISAExtInfo misa_ext_info_arr[] = {
35
@@ -XXX,XX +XXX,XX @@ static Property riscv_cpu_properties[] = {
27
MISA_EXT_INFO(RVJ, "x-j", "Dynamic translated languages"),
36
DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128),
28
MISA_EXT_INFO(RVV, "v", "Vector operations"),
37
DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
29
MISA_EXT_INFO(RVG, "g", "General purpose (IMAFD_Zicsr_Zifencei)"),
38
30
- MISA_EXT_INFO(RVB, "x-b", "Bit manipulation (Zba_Zbb_Zbs)")
39
+ DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false),
31
+ MISA_EXT_INFO(RVB, "b", "Bit manipulation (Zba_Zbb_Zbs)")
40
+
32
};
41
DEFINE_PROP_BOOL("zba", RISCVCPU, cfg.ext_zba, true),
33
42
DEFINE_PROP_BOOL("zbb", RISCVCPU, cfg.ext_zbb, true),
34
static void riscv_cpu_validate_misa_mxl(RISCVCPUClass *mcc)
43
DEFINE_PROP_BOOL("zbc", RISCVCPU, cfg.ext_zbc, true),
35
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
44
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
36
index XXXXXXX..XXXXXXX 100644
45
index XXXXXXX..XXXXXXX 100644
37
--- a/target/riscv/tcg/tcg-cpu.c
46
--- a/target/riscv/cpu_helper.c
38
+++ b/target/riscv/tcg/tcg-cpu.c
47
+++ b/target/riscv/cpu_helper.c
39
@@ -XXX,XX +XXX,XX @@ static void riscv_init_max_cpu_extensions(Object *obj)
48
@@ -XXX,XX +XXX,XX @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
40
const RISCVCPUMultiExtConfig *prop;
49
bool use_background = false;
41
50
hwaddr ppn;
42
/* Enable RVG, RVJ and RVV that are disabled by default */
51
RISCVCPU *cpu = env_archcpu(env);
43
- riscv_cpu_set_misa_ext(env, env->misa_ext | RVG | RVJ | RVV);
52
+ int napot_bits = 0;
44
+ riscv_cpu_set_misa_ext(env, env->misa_ext | RVB | RVG | RVJ | RVV);
53
+ target_ulong napot_mask;
45
54
46
for (prop = riscv_cpu_extensions; prop && prop->name; prop++) {
55
/*
47
isa_ext_update_enabled(cpu, prop->offset, true);
56
* Check if we should use the background registers for the two
57
@@ -XXX,XX +XXX,XX @@ restart:
58
return TRANSLATE_FAIL;
59
} else if (!(pte & (PTE_R | PTE_W | PTE_X))) {
60
/* Inner PTE, continue walking */
61
- if (pte & (PTE_D | PTE_A | PTE_U)) {
62
+ if (pte & (PTE_D | PTE_A | PTE_U | PTE_N)) {
63
return TRANSLATE_FAIL;
64
}
65
base = ppn << PGSHIFT;
66
@@ -XXX,XX +XXX,XX @@ restart:
67
/* for superpage mappings, make a fake leaf PTE for the TLB's
68
benefit. */
69
target_ulong vpn = addr >> PGSHIFT;
70
- *physical = ((ppn | (vpn & ((1L << ptshift) - 1))) << PGSHIFT) |
71
- (addr & ~TARGET_PAGE_MASK);
72
+
73
+ if (cpu->cfg.ext_svnapot && (pte & PTE_N)) {
74
+ napot_bits = ctzl(ppn) + 1;
75
+ if ((i != (levels - 1)) || (napot_bits != 4)) {
76
+ return TRANSLATE_FAIL;
77
+ }
78
+ }
79
+
80
+ napot_mask = (1 << napot_bits) - 1;
81
+ *physical = (((ppn & ~napot_mask) | (vpn & napot_mask) |
82
+ (vpn & (((target_ulong)1 << ptshift) - 1))
83
+ ) << PGSHIFT) | (addr & ~TARGET_PAGE_MASK);
84
85
/* set permissions on the TLB entry */
86
if ((pte & PTE_R) || ((pte & PTE_X) && mxr)) {
48
--
87
--
49
2.45.1
88
2.34.1
89
90
diff view generated by jsdifflib
1
From: Huang Tao <eric.huang@linux.alibaba.com>
1
From: Weiwei Li <liweiwei@iscas.ac.cn>
2
2
3
In this patch, we modify the decoder to be a freely composable data
3
- sinval.vma, hinval.vvma and hinval.gvma do the same as sfence.vma, hfence.vvma and hfence.gvma except extension check
4
structure instead of a hardcoded one. It can be dynamically builded up
4
- do nothing other than extension check for sfence.w.inval and sfence.inval.ir
5
according to the extensions.
6
This approach has several benefits:
7
1. Provides support for heterogeneous cpu architectures. As we add decoder in
8
RISCVCPU, each cpu can have their own decoder, and the decoders can be
9
different due to cpu's features.
10
2. Improve the decoding efficiency. We run the guard_func to see if the decoder
11
can be added to the dynamic_decoder when building up the decoder. Therefore,
12
there is no need to run the guard_func when decoding each instruction. It can
13
improve the decoding efficiency
14
3. For vendor or dynamic cpus, it allows them to customize their own decoder
15
functions to improve decoding efficiency, especially when vendor-defined
16
instruction sets increase. Because of dynamic building up, it can skip the other
17
decoder guard functions when decoding.
18
4. Pre patch for allowing adding a vendor decoder before decode_insn32() with minimal
19
overhead for users that don't need this particular vendor decoder.
20
5
21
Signed-off-by: Huang Tao <eric.huang@linux.alibaba.com>
6
Signed-off-by: Weiwei Li <liweiwei@iscas.ac.cn>
22
Suggested-by: Christoph Muellner <christoph.muellner@vrull.eu>
7
Signed-off-by: Junqiang Wang <wangjunqiang@iscas.ac.cn>
23
Co-authored-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
8
Reviewed-by: Anup Patel <anup@brainfault.org>
24
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
25
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
26
Message-ID: <20240506023607.29544-1-eric.huang@linux.alibaba.com>
10
Message-Id: <20220204022658.18097-5-liweiwei@iscas.ac.cn>
27
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
28
---
12
---
29
target/riscv/cpu.h | 1 +
13
target/riscv/cpu.h | 1 +
30
target/riscv/tcg/tcg-cpu.h | 15 +++++++++++++++
14
target/riscv/insn32.decode | 7 ++
31
target/riscv/cpu.c | 1 +
15
target/riscv/cpu.c | 1 +
32
target/riscv/tcg/tcg-cpu.c | 15 +++++++++++++++
16
target/riscv/translate.c | 1 +
33
target/riscv/translate.c | 31 +++++++++++++++----------------
17
target/riscv/insn_trans/trans_svinval.c.inc | 75 +++++++++++++++++++++
34
5 files changed, 47 insertions(+), 16 deletions(-)
18
5 files changed, 85 insertions(+)
19
create mode 100644 target/riscv/insn_trans/trans_svinval.c.inc
35
20
36
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
21
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
37
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
38
--- a/target/riscv/cpu.h
23
--- a/target/riscv/cpu.h
39
+++ b/target/riscv/cpu.h
24
+++ b/target/riscv/cpu.h
40
@@ -XXX,XX +XXX,XX @@ struct ArchCPU {
25
@@ -XXX,XX +XXX,XX @@ struct RISCVCPUConfig {
41
uint32_t pmu_avail_ctrs;
26
bool ext_counters;
42
/* Mapping of events to counters */
27
bool ext_ifencei;
43
GHashTable *pmu_event_ctr_map;
28
bool ext_icsr;
44
+ const GPtrArray *decoders;
29
+ bool ext_svinval;
45
};
30
bool ext_svnapot;
46
31
bool ext_svpbmt;
47
/**
32
bool ext_zfh;
48
diff --git a/target/riscv/tcg/tcg-cpu.h b/target/riscv/tcg/tcg-cpu.h
33
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
49
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
50
--- a/target/riscv/tcg/tcg-cpu.h
35
--- a/target/riscv/insn32.decode
51
+++ b/target/riscv/tcg/tcg-cpu.h
36
+++ b/target/riscv/insn32.decode
52
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp);
37
@@ -XXX,XX +XXX,XX @@ fcvt_l_h 1100010 00010 ..... ... ..... 1010011 @r2_rm
53
void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp);
38
fcvt_lu_h 1100010 00011 ..... ... ..... 1010011 @r2_rm
54
bool riscv_cpu_tcg_compatible(RISCVCPU *cpu);
39
fcvt_h_l 1101010 00010 ..... ... ..... 1010011 @r2_rm
55
40
fcvt_h_lu 1101010 00011 ..... ... ..... 1010011 @r2_rm
56
+struct DisasContext;
57
+struct RISCVCPUConfig;
58
+typedef struct RISCVDecoder {
59
+ bool (*guard_func)(const struct RISCVCPUConfig *);
60
+ bool (*riscv_cpu_decode_fn)(struct DisasContext *, uint32_t);
61
+} RISCVDecoder;
62
+
41
+
63
+typedef bool (*riscv_cpu_decode_fn)(struct DisasContext *, uint32_t);
42
+# *** Svinval Standard Extension ***
64
+
43
+sinval_vma 0001011 ..... ..... 000 00000 1110011 @sfence_vma
65
+extern const size_t decoder_table_size;
44
+sfence_w_inval 0001100 00000 00000 000 00000 1110011
66
+
45
+sfence_inval_ir 0001100 00001 00000 000 00000 1110011
67
+extern const RISCVDecoder decoder_table[];
46
+hinval_vvma 0010011 ..... ..... 000 00000 1110011 @hfence_vvma
68
+
47
+hinval_gvma 0110011 ..... ..... 000 00000 1110011 @hfence_gvma
69
+void riscv_tcg_cpu_finalize_dynamic_decoder(RISCVCPU *cpu);
70
+
71
#endif
72
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
48
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
73
index XXXXXXX..XXXXXXX 100644
49
index XXXXXXX..XXXXXXX 100644
74
--- a/target/riscv/cpu.c
50
--- a/target/riscv/cpu.c
75
+++ b/target/riscv/cpu.c
51
+++ b/target/riscv/cpu.c
76
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_finalize_features(RISCVCPU *cpu, Error **errp)
52
@@ -XXX,XX +XXX,XX @@ static Property riscv_cpu_properties[] = {
77
error_propagate(errp, local_err);
53
DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128),
78
return;
54
DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
79
}
55
80
+ riscv_tcg_cpu_finalize_dynamic_decoder(cpu);
56
+ DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false),
81
} else if (kvm_enabled()) {
57
DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false),
82
riscv_kvm_cpu_finalize_features(cpu, &local_err);
58
83
if (local_err != NULL) {
59
DEFINE_PROP_BOOL("zba", RISCVCPU, cfg.ext_zba, true),
84
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
85
index XXXXXXX..XXXXXXX 100644
86
--- a/target/riscv/tcg/tcg-cpu.c
87
+++ b/target/riscv/tcg/tcg-cpu.c
88
@@ -XXX,XX +XXX,XX @@ void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp)
89
}
90
}
91
92
+void riscv_tcg_cpu_finalize_dynamic_decoder(RISCVCPU *cpu)
93
+{
94
+ GPtrArray *dynamic_decoders;
95
+ dynamic_decoders = g_ptr_array_sized_new(decoder_table_size);
96
+ for (size_t i = 0; i < decoder_table_size; ++i) {
97
+ if (decoder_table[i].guard_func &&
98
+ decoder_table[i].guard_func(&cpu->cfg)) {
99
+ g_ptr_array_add(dynamic_decoders,
100
+ (gpointer)decoder_table[i].riscv_cpu_decode_fn);
101
+ }
102
+ }
103
+
104
+ cpu->decoders = dynamic_decoders;
105
+}
106
+
107
bool riscv_cpu_tcg_compatible(RISCVCPU *cpu)
108
{
109
return object_dynamic_cast(OBJECT(cpu), TYPE_RISCV_CPU_HOST) == NULL;
110
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
60
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
111
index XXXXXXX..XXXXXXX 100644
61
index XXXXXXX..XXXXXXX 100644
112
--- a/target/riscv/translate.c
62
--- a/target/riscv/translate.c
113
+++ b/target/riscv/translate.c
63
+++ b/target/riscv/translate.c
64
@@ -XXX,XX +XXX,XX @@ static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
65
#include "insn_trans/trans_rvb.c.inc"
66
#include "insn_trans/trans_rvzfh.c.inc"
67
#include "insn_trans/trans_privileged.c.inc"
68
+#include "insn_trans/trans_svinval.c.inc"
69
#include "insn_trans/trans_xventanacondops.c.inc"
70
71
/* Include the auto-generated decoder for 16 bit insn */
72
diff --git a/target/riscv/insn_trans/trans_svinval.c.inc b/target/riscv/insn_trans/trans_svinval.c.inc
73
new file mode 100644
74
index XXXXXXX..XXXXXXX
75
--- /dev/null
76
+++ b/target/riscv/insn_trans/trans_svinval.c.inc
114
@@ -XXX,XX +XXX,XX @@
77
@@ -XXX,XX +XXX,XX @@
115
#include "exec/helper-info.c.inc"
78
+/*
116
#undef HELPER_H
79
+ * RISC-V translation routines for the Svinval Standard Instruction Set.
117
80
+ *
118
+#include "tcg/tcg-cpu.h"
81
+ * Copyright (c) 2020-2022 PLCT lab
82
+ *
83
+ * This program is free software; you can redistribute it and/or modify it
84
+ * under the terms and conditions of the GNU General Public License,
85
+ * version 2 or later, as published by the Free Software Foundation.
86
+ *
87
+ * This program is distributed in the hope it will be useful, but WITHOUT
88
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
89
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
90
+ * more details.
91
+ *
92
+ * You should have received a copy of the GNU General Public License along with
93
+ * this program. If not, see <http://www.gnu.org/licenses/>.
94
+ */
119
+
95
+
120
/* global register indices */
96
+#define REQUIRE_SVINVAL(ctx) do { \
121
static TCGv cpu_gpr[32], cpu_gprh[32], cpu_pc, cpu_vl, cpu_vstart;
97
+ if (!ctx->cfg_ptr->ext_svinval) { \
122
static TCGv_i64 cpu_fpr[32]; /* assume F and D extensions */
98
+ return false; \
123
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
99
+ } \
124
/* FRM is known to contain a valid value. */
100
+} while (0)
125
bool frm_valid;
126
bool insn_start_updated;
127
+ const GPtrArray *decoders;
128
} DisasContext;
129
130
static inline bool has_ext(DisasContext *ctx, uint32_t ext)
131
@@ -XXX,XX +XXX,XX @@ static inline int insn_len(uint16_t first_word)
132
return (first_word & 3) == 3 ? 4 : 2;
133
}
134
135
+const RISCVDecoder decoder_table[] = {
136
+ { always_true_p, decode_insn32 },
137
+ { has_xthead_p, decode_xthead},
138
+ { has_XVentanaCondOps_p, decode_XVentanaCodeOps},
139
+};
140
+
101
+
141
+const size_t decoder_table_size = ARRAY_SIZE(decoder_table);
102
+static bool trans_sinval_vma(DisasContext *ctx, arg_sinval_vma *a)
103
+{
104
+ REQUIRE_SVINVAL(ctx);
105
+ /* Do the same as sfence.vma currently */
106
+ REQUIRE_EXT(ctx, RVS);
107
+#ifndef CONFIG_USER_ONLY
108
+ gen_helper_tlb_flush(cpu_env);
109
+ return true;
110
+#endif
111
+ return false;
112
+}
142
+
113
+
143
static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
114
+static bool trans_sfence_w_inval(DisasContext *ctx, arg_sfence_w_inval *a)
144
{
115
+{
145
- /*
116
+ REQUIRE_SVINVAL(ctx);
146
- * A table with predicate (i.e., guard) functions and decoder functions
117
+ REQUIRE_EXT(ctx, RVS);
147
- * that are tested in-order until a decoder matches onto the opcode.
118
+ /* Do nothing currently */
148
- */
119
+ return true;
149
- static const struct {
120
+}
150
- bool (*guard_func)(const RISCVCPUConfig *);
121
+
151
- bool (*decode_func)(DisasContext *, uint32_t);
122
+static bool trans_sfence_inval_ir(DisasContext *ctx, arg_sfence_inval_ir *a)
152
- } decoders[] = {
123
+{
153
- { always_true_p, decode_insn32 },
124
+ REQUIRE_SVINVAL(ctx);
154
- { has_xthead_p, decode_xthead },
125
+ REQUIRE_EXT(ctx, RVS);
155
- { has_XVentanaCondOps_p, decode_XVentanaCodeOps },
126
+ /* Do nothing currently */
156
- };
127
+ return true;
157
-
128
+}
158
ctx->virt_inst_excp = false;
129
+
159
ctx->cur_insn_len = insn_len(opcode);
130
+static bool trans_hinval_vvma(DisasContext *ctx, arg_hinval_vvma *a)
160
/* Check for compressed insn */
131
+{
161
@@ -XXX,XX +XXX,XX @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
132
+ REQUIRE_SVINVAL(ctx);
162
ctx->base.pc_next + 2));
133
+ /* Do the same as hfence.vvma currently */
163
ctx->opcode = opcode32;
134
+ REQUIRE_EXT(ctx, RVH);
164
135
+#ifndef CONFIG_USER_ONLY
165
- for (size_t i = 0; i < ARRAY_SIZE(decoders); ++i) {
136
+ gen_helper_hyp_tlb_flush(cpu_env);
166
- if (decoders[i].guard_func(ctx->cfg_ptr) &&
137
+ return true;
167
- decoders[i].decode_func(ctx, opcode32)) {
138
+#endif
168
+ for (guint i = 0; i < ctx->decoders->len; ++i) {
139
+ return false;
169
+ riscv_cpu_decode_fn func = g_ptr_array_index(ctx->decoders, i);
140
+}
170
+ if (func(ctx, opcode32)) {
141
+
171
return;
142
+static bool trans_hinval_gvma(DisasContext *ctx, arg_hinval_gvma *a)
172
}
143
+{
173
}
144
+ REQUIRE_SVINVAL(ctx);
174
@@ -XXX,XX +XXX,XX @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
145
+ /* Do the same as hfence.gvma currently */
175
ctx->itrigger = FIELD_EX32(tb_flags, TB_FLAGS, ITRIGGER);
146
+ REQUIRE_EXT(ctx, RVH);
176
ctx->zero = tcg_constant_tl(0);
147
+#ifndef CONFIG_USER_ONLY
177
ctx->virt_inst_excp = false;
148
+ gen_helper_hyp_gvma_tlb_flush(cpu_env);
178
+ ctx->decoders = cpu->decoders;
149
+ return true;
179
}
150
+#endif
180
151
+ return false;
181
static void riscv_tr_tb_start(DisasContextBase *db, CPUState *cpu)
152
+}
182
--
153
--
183
2.45.1
154
2.34.1
155
156
diff view generated by jsdifflib
1
From: Yangyu Chen <cyy@cyyself.name>
1
From: Weiwei Li <liweiwei@iscas.ac.cn>
2
2
3
This code has a typo that writes zvkb to zvkg, causing users can't
3
- add PTE_PBMT bits: It uses two PTE bits, but otherwise has no effect on QEMU, since QEMU is sequentially consistent and doesn't model PMAs currently
4
enable zvkb through the config. This patch gets this fixed.
4
- add PTE_PBMT bit check for inner PTE
5
5
6
Signed-off-by: Yangyu Chen <cyy@cyyself.name>
6
Signed-off-by: Weiwei Li <liweiwei@iscas.ac.cn>
7
Fixes: ea61ef7097d0 ("target/riscv: Move vector crypto extensions to riscv_cpu_extensions")
7
Signed-off-by: Junqiang Wang <wangjunqiang@iscas.ac.cn>
8
Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
8
Reviewed-by: Anup Patel <anup@brainfault.org>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Reviewed-by: Max Chou <max.chou@sifive.com>
10
Message-Id: <20220204022658.18097-6-liweiwei@iscas.ac.cn>
11
Reviewed-by:  Weiwei Li <liwei1518@gmail.com>
12
Message-ID: <tencent_7E34EEF0F90B9A68BF38BEE09EC6D4877C0A@qq.com>
13
Cc: qemu-stable <qemu-stable@nongnu.org>
14
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
15
---
12
---
16
target/riscv/cpu.c | 2 +-
13
target/riscv/cpu_bits.h | 2 ++
17
1 file changed, 1 insertion(+), 1 deletion(-)
14
target/riscv/cpu.c | 1 +
15
target/riscv/cpu_helper.c | 4 +++-
16
3 files changed, 6 insertions(+), 1 deletion(-)
18
17
18
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/riscv/cpu_bits.h
21
+++ b/target/riscv/cpu_bits.h
22
@@ -XXX,XX +XXX,XX @@ typedef enum {
23
#define PTE_A 0x040 /* Accessed */
24
#define PTE_D 0x080 /* Dirty */
25
#define PTE_SOFT 0x300 /* Reserved for Software */
26
+#define PTE_PBMT 0x6000000000000000ULL /* Page-based memory types */
27
#define PTE_N 0x8000000000000000ULL /* NAPOT translation */
28
+#define PTE_ATTR (PTE_N | PTE_PBMT) /* All attributes bits */
29
30
/* Page table PPN shift amount */
31
#define PTE_PPN_SHIFT 10
19
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
32
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
20
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
21
--- a/target/riscv/cpu.c
34
--- a/target/riscv/cpu.c
22
+++ b/target/riscv/cpu.c
35
+++ b/target/riscv/cpu.c
23
@@ -XXX,XX +XXX,XX @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
36
@@ -XXX,XX +XXX,XX @@ static Property riscv_cpu_properties[] = {
24
/* Vector cryptography extensions */
37
25
MULTI_EXT_CFG_BOOL("zvbb", ext_zvbb, false),
38
DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false),
26
MULTI_EXT_CFG_BOOL("zvbc", ext_zvbc, false),
39
DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false),
27
- MULTI_EXT_CFG_BOOL("zvkb", ext_zvkg, false),
40
+ DEFINE_PROP_BOOL("svpbmt", RISCVCPU, cfg.ext_svpbmt, false),
28
+ MULTI_EXT_CFG_BOOL("zvkb", ext_zvkb, false),
41
29
MULTI_EXT_CFG_BOOL("zvkg", ext_zvkg, false),
42
DEFINE_PROP_BOOL("zba", RISCVCPU, cfg.ext_zba, true),
30
MULTI_EXT_CFG_BOOL("zvkned", ext_zvkned, false),
43
DEFINE_PROP_BOOL("zbb", RISCVCPU, cfg.ext_zbb, true),
31
MULTI_EXT_CFG_BOOL("zvknha", ext_zvknha, false),
44
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/target/riscv/cpu_helper.c
47
+++ b/target/riscv/cpu_helper.c
48
@@ -XXX,XX +XXX,XX @@ restart:
49
if (!(pte & PTE_V)) {
50
/* Invalid PTE */
51
return TRANSLATE_FAIL;
52
+ } else if (!cpu->cfg.ext_svpbmt && (pte & PTE_PBMT)) {
53
+ return TRANSLATE_FAIL;
54
} else if (!(pte & (PTE_R | PTE_W | PTE_X))) {
55
/* Inner PTE, continue walking */
56
- if (pte & (PTE_D | PTE_A | PTE_U | PTE_N)) {
57
+ if (pte & (PTE_D | PTE_A | PTE_U | PTE_ATTR)) {
58
return TRANSLATE_FAIL;
59
}
60
base = ppn << PGSHIFT;
32
--
61
--
33
2.45.1
62
2.34.1
34
63
35
64
diff view generated by jsdifflib
1
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
1
From: Yu Li <liyu.yukiteru@bytedance.com>
2
2
3
Commit 33a24910ae changed 'reg_width' to use 'vlenb', i.e. vector length
3
Since the hypervisor extension been non experimental and enabled for
4
in bytes, when in this context we want 'reg_width' as the length in
4
default CPU, the previous command is no longer available and the
5
bits.
5
option `x-h=true` or `h=true` is also no longer required.
6
6
7
Fix 'reg_width' back to the value in bits like 7cb59921c05a
7
Signed-off-by: Yu Li <liyu.yukiteru@bytedance.com>
8
("target/riscv/gdbstub.c: use 'vlenb' instead of shifting 'vlen'") set
9
beforehand.
10
11
While we're at it, rename 'reg_width' to 'bitsize' to provide a bit more
12
clarity about what the variable represents. 'bitsize' is also used in
13
riscv_gen_dynamic_csr_feature() with the same purpose, i.e. as an input to
14
gdb_feature_builder_append_reg().
15
16
Cc: Akihiko Odaki <akihiko.odaki@daynix.com>
17
Cc: Alex Bennée <alex.bennee@linaro.org>
18
Reported-by: Robin Dapp <rdapp.gcc@gmail.com>
19
Fixes: 33a24910ae ("target/riscv: Use GDBFeature for dynamic XML")
20
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
21
Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
22
Acked-by: Alex Bennée <alex.bennee@linaro.org>
23
Reviewed-by: Akihiko Odaki <akihiko.odaki@daynix.com>
24
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
25
Cc: qemu-stable <qemu-stable@nongnu.org>
9
Message-Id: <9040401e-8f87-ef4a-d840-6703f08d068c@bytedance.com>
26
Message-ID: <20240517203054.880861-2-dbarboza@ventanamicro.com>
27
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
28
---
11
---
29
target/riscv/gdbstub.c | 6 +++---
12
docs/system/riscv/virt.rst | 6 +++---
30
1 file changed, 3 insertions(+), 3 deletions(-)
13
1 file changed, 3 insertions(+), 3 deletions(-)
31
14
32
diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
15
diff --git a/docs/system/riscv/virt.rst b/docs/system/riscv/virt.rst
33
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
34
--- a/target/riscv/gdbstub.c
17
--- a/docs/system/riscv/virt.rst
35
+++ b/target/riscv/gdbstub.c
18
+++ b/docs/system/riscv/virt.rst
36
@@ -XXX,XX +XXX,XX @@ static GDBFeature *riscv_gen_dynamic_csr_feature(CPUState *cs, int base_reg)
19
@@ -XXX,XX +XXX,XX @@ The ``virt`` machine supports the following devices:
37
static GDBFeature *ricsv_gen_dynamic_vector_feature(CPUState *cs, int base_reg)
20
* 1 generic PCIe host bridge
38
{
21
* The fw_cfg device that allows a guest to obtain data from QEMU
39
RISCVCPU *cpu = RISCV_CPU(cs);
22
40
- int reg_width = cpu->cfg.vlenb;
23
-Note that the default CPU is a generic RV32GC/RV64GC. Optional extensions
41
+ int bitsize = cpu->cfg.vlenb << 3;
24
-can be enabled via command line parameters, e.g.: ``-cpu rv64,x-h=true``
42
GDBFeatureBuilder builder;
25
-enables the hypervisor extension for RV64.
43
int i;
26
+The hypervisor extension has been enabled for the default CPU, so virtual
44
27
+machines with hypervisor extension can simply be used without explicitly
45
@@ -XXX,XX +XXX,XX @@ static GDBFeature *ricsv_gen_dynamic_vector_feature(CPUState *cs, int base_reg)
28
+declaring.
46
29
47
/* First define types and totals in a whole VL */
30
Hardware configuration information
48
for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
31
----------------------------------
49
- int count = reg_width / vec_lanes[i].size;
50
+ int count = bitsize / vec_lanes[i].size;
51
gdb_feature_builder_append_tag(
52
&builder, "<vector id=\"%s\" type=\"%s\" count=\"%d\"/>",
53
vec_lanes[i].id, vec_lanes[i].gdb_type, count);
54
@@ -XXX,XX +XXX,XX @@ static GDBFeature *ricsv_gen_dynamic_vector_feature(CPUState *cs, int base_reg)
55
/* Define vector registers */
56
for (i = 0; i < 32; i++) {
57
gdb_feature_builder_append_reg(&builder, g_strdup_printf("v%d", i),
58
- reg_width, i, "riscv_vector", "vector");
59
+ bitsize, i, "riscv_vector", "vector");
60
}
61
62
gdb_feature_builder_end(&builder);
63
--
32
--
64
2.45.1
33
2.34.1
65
34
66
35
diff view generated by jsdifflib