1
From: Alistair Francis <alistair.francis@wdc.com>
1
From: Alistair Francis <alistair.francis@wdc.com>
2
2
3
The following changes since commit c5fbdd60cf1fb52f01bdfe342b6fa65d5343e1b1:
3
The following changes since commit 0a301624c2f4ced3331ffd5bce85b4274fe132af:
4
4
5
Merge tag 'qemu-sparc-20211121' of git://github.com/mcayland/qemu into staging (2021-11-21 14:12:25 +0100)
5
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20220208' into staging (2022-02-08 11:40:08 +0000)
6
6
7
are available in the Git repository at:
7
are available in the Git repository at:
8
8
9
git@github.com:alistair23/qemu.git tags/pull-riscv-to-apply-20211122
9
git@github.com:alistair23/qemu.git tags/pull-riscv-to-apply-20220212
10
10
11
for you to fetch changes up to 526e7443027c71fe7b04c29df529e1f9f425f9e3:
11
for you to fetch changes up to 31d69b66ed89fa0f66d4e5a15e9664c92c3ed8f8:
12
12
13
hw/misc/sifive_u_otp: Do not reset OTP content on hardware reset (2021-11-22 10:46:22 +1000)
13
docs/system: riscv: Update description of CPU (2022-02-11 18:31:29 +1000)
14
14
15
----------------------------------------------------------------
15
----------------------------------------------------------------
16
Seventh RISC-V PR for QEMU 6.2
16
Fourth RISC-V PR for QEMU 7.0
17
17
18
- Deprecate IF_NONE for SiFive OTP
18
* Remove old Ibex PLIC header file
19
- Don't reset SiFive OTP content
19
* Allow writing 8 bytes with generic loader
20
* Fixes for RV128
21
* Refactor RISC-V CPU configs
22
* Initial support for XVentanaCondOps custom extension
23
* Fix for vill field in vtype
24
* Fix trap cause for RV32 HS-mode CSR access from RV64 HS-mode
25
* RISC-V AIA support for virt machine
26
* Support for svnapot, svinval and svpbmt extensions
20
27
21
----------------------------------------------------------------
28
----------------------------------------------------------------
22
Philippe Mathieu-Daudé (1):
29
Anup Patel (23):
23
hw/misc/sifive_u_otp: Do not reset OTP content on hardware reset
30
target/riscv: Fix trap cause for RV32 HS-mode CSR access from RV64 HS-mode
31
target/riscv: Implement SGEIP bit in hip and hie CSRs
32
target/riscv: Implement hgeie and hgeip CSRs
33
target/riscv: Improve delivery of guest external interrupts
34
target/riscv: Allow setting CPU feature from machine/device emulation
35
target/riscv: Add AIA cpu feature
36
target/riscv: Add defines for AIA CSRs
37
target/riscv: Allow AIA device emulation to set ireg rmw callback
38
target/riscv: Implement AIA local interrupt priorities
39
target/riscv: Implement AIA CSRs for 64 local interrupts on RV32
40
target/riscv: Implement AIA hvictl and hviprioX CSRs
41
target/riscv: Implement AIA interrupt filtering CSRs
42
target/riscv: Implement AIA mtopi, stopi, and vstopi CSRs
43
target/riscv: Implement AIA xiselect and xireg CSRs
44
target/riscv: Implement AIA IMSIC interface CSRs
45
hw/riscv: virt: Use AIA INTC compatible string when available
46
target/riscv: Allow users to force enable AIA CSRs in HART
47
hw/intc: Add RISC-V AIA APLIC device emulation
48
hw/riscv: virt: Add optional AIA APLIC support to virt machine
49
hw/intc: Add RISC-V AIA IMSIC device emulation
50
hw/riscv: virt: Add optional AIA IMSIC support to virt machine
51
docs/system: riscv: Document AIA options for virt machine
52
hw/riscv: virt: Increase maximum number of allowed CPUs
24
53
25
Thomas Huth (1):
54
Frédéric Pétrot (1):
26
hw/misc/sifive_u_otp: Use IF_PFLASH for the OTP device instead of IF_NONE
55
target/riscv: correct "code should not be reached" for x-rv128
27
56
28
docs/about/deprecated.rst | 6 ++++++
57
Guo Ren (1):
29
hw/misc/sifive_u_otp.c | 22 +++++++++++++---------
58
target/riscv: Ignore reserved bits in PTE for RV64
30
2 files changed, 19 insertions(+), 9 deletions(-)
31
59
60
LIU Zhiwei (1):
61
target/riscv: Fix vill field write in vtype
62
63
Petr Tesarik (1):
64
Allow setting up to 8 bytes with the generic loader
65
66
Philipp Tomsich (7):
67
target/riscv: refactor (anonymous struct) RISCVCPU.cfg into 'struct RISCVCPUConfig'
68
target/riscv: riscv_tr_init_disas_context: copy pointer-to-cfg into cfg_ptr
69
target/riscv: access configuration through cfg_ptr in DisasContext
70
target/riscv: access cfg structure through DisasContext
71
target/riscv: iterate over a table of decoders
72
target/riscv: Add XVentanaCondOps custom extension
73
target/riscv: add a MAINTAINERS entry for XVentanaCondOps
74
75
Weiwei Li (4):
76
target/riscv: add PTE_A/PTE_D/PTE_U bits check for inner PTE
77
target/riscv: add support for svnapot extension
78
target/riscv: add support for svinval extension
79
target/riscv: add support for svpbmt extension
80
81
Wilfred Mallawa (1):
82
include: hw: remove ibex_plic.h
83
84
Yu Li (1):
85
docs/system: riscv: Update description of CPU
86
87
docs/system/riscv/virt.rst | 22 +-
88
include/hw/intc/ibex_plic.h | 67 -
89
include/hw/intc/riscv_aplic.h | 79 ++
90
include/hw/intc/riscv_imsic.h | 68 ++
91
include/hw/riscv/virt.h | 41 +-
92
target/riscv/cpu.h | 169 ++-
93
target/riscv/cpu_bits.h | 129 ++
94
target/riscv/XVentanaCondOps.decode | 25 +
95
target/riscv/insn32.decode | 7 +
96
hw/core/generic-loader.c | 2 +-
97
hw/intc/riscv_aplic.c | 978 +++++++++++++++
98
hw/intc/riscv_imsic.c | 448 +++++++
99
hw/riscv/virt.c | 712 +++++++++--
100
target/riscv/cpu.c | 113 +-
101
target/riscv/cpu_helper.c | 377 +++++-
102
target/riscv/csr.c | 1282 ++++++++++++++++++--
103
target/riscv/gdbstub.c | 3 +
104
target/riscv/machine.c | 24 +-
105
target/riscv/translate.c | 61 +-
106
target/riscv/vector_helper.c | 1 +
107
target/riscv/insn_trans/trans_rvb.c.inc | 8 +-
108
target/riscv/insn_trans/trans_rvi.c.inc | 2 +-
109
target/riscv/insn_trans/trans_rvv.c.inc | 146 ++-
110
target/riscv/insn_trans/trans_rvzfh.c.inc | 4 +-
111
target/riscv/insn_trans/trans_svinval.c.inc | 75 ++
112
.../riscv/insn_trans/trans_xventanacondops.c.inc | 39 +
113
MAINTAINERS | 7 +
114
hw/intc/Kconfig | 6 +
115
hw/intc/meson.build | 2 +
116
hw/riscv/Kconfig | 2 +
117
target/riscv/meson.build | 1 +
118
31 files changed, 4409 insertions(+), 491 deletions(-)
119
delete mode 100644 include/hw/intc/ibex_plic.h
120
create mode 100644 include/hw/intc/riscv_aplic.h
121
create mode 100644 include/hw/intc/riscv_imsic.h
122
create mode 100644 target/riscv/XVentanaCondOps.decode
123
create mode 100644 hw/intc/riscv_aplic.c
124
create mode 100644 hw/intc/riscv_imsic.c
125
create mode 100644 target/riscv/insn_trans/trans_svinval.c.inc
126
create mode 100644 target/riscv/insn_trans/trans_xventanacondops.c.inc
127
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
New patch
1
From: Frédéric Pétrot <frederic.petrot@univ-grenoble-alpes.fr>
1
2
3
The addition of uxl support in gdbstub adds a few checks on the maximum
4
register length, but omitted MXL_RV128, an experimental feature.
5
This patch makes rv128 react as rv64, as previously.
6
7
Signed-off-by: Frédéric Pétrot <frederic.petrot@univ-grenoble-alpes.fr>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: LIU Zhiwei <zhiwei_liu@c-sky.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>
13
---
14
target/riscv/cpu.c | 3 +--
15
target/riscv/gdbstub.c | 3 +++
16
2 files changed, 4 insertions(+), 2 deletions(-)
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:
33
diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/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 {
53
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
54
1, "riscv-32bit-virtual.xml", 0);
55
break;
56
case MXL_RV64:
57
+ case MXL_RV128:
58
gdb_register_coprocessor(cs, riscv_gdb_get_virtual,
59
riscv_gdb_set_virtual,
60
1, "riscv-64bit-virtual.xml", 0);
61
--
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
New patch
1
From: Philipp Tomsich <philipp.tomsich@vrull.eu>
1
2
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.
6
7
This adds an extra indirection when checking for the availability of
8
an extension (compared to copying the fields into DisasContext).
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.
12
13
Signed-off-by: Philipp Tomsich <philipp.tomsich@vrull.eu>
14
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
15
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-Id: <20220202005249.3566542-3-philipp.tomsich@vrull.eu>
18
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
19
---
20
target/riscv/translate.c | 2 ++
21
1 file changed, 2 insertions(+)
22
23
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
24
index XXXXXXX..XXXXXXX 100644
25
--- a/target/riscv/translate.c
26
+++ b/target/riscv/translate.c
27
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
28
int frm;
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
@@ -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;
43
--
44
2.34.1
45
46
diff view generated by jsdifflib
New patch
1
From: Philipp Tomsich <philipp.tomsich@vrull.eu>
1
2
3
The implementation in trans_{rvi,rvv,rvzfh}.c.inc accesses the shallow
4
copies (in DisasContext) of some of the elements available in the
5
RISCVCPUConfig structure. This commit redirects accesses to use the
6
cfg_ptr copied into DisasContext and removes the shallow copies.
7
8
Signed-off-by: Philipp Tomsich <philipp.tomsich@vrull.eu>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-Id: <20220202005249.3566542-4-philipp.tomsich@vrull.eu>
13
[ Changes by AF:
14
- Fixup checkpatch failures
15
]
16
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
17
---
18
target/riscv/translate.c | 14 ---
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(-)
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
76
diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc
77
index XXXXXXX..XXXXXXX 100644
78
--- a/target/riscv/insn_trans/trans_rvv.c.inc
79
+++ b/target/riscv/insn_trans/trans_rvv.c.inc
80
@@ -XXX,XX +XXX,XX @@ static bool require_zve32f(DisasContext *s)
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)
139
{
140
- return offsetof(CPURISCVState, vreg) + reg * s->vlen / 8;
141
+ return offsetof(CPURISCVState, vreg) + reg * s->cfg_ptr->vlen / 8;
142
}
143
144
/* check functions */
145
@@ -XXX,XX +XXX,XX @@ static bool vext_check_st_index(DisasContext *s, int vd, int vs2, int nf,
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)
156
{
157
return (s->lmul <= 2) &&
158
(s->sew < MO_64) &&
159
- ((s->sew + 1) <= (s->elen >> 4)) &&
160
+ ((s->sew + 1) <= (s->cfg_ptr->elen >> 4)) &&
161
require_align(vd, s->lmul + 1) &&
162
require_vm(vm, vd);
163
}
164
@@ -XXX,XX +XXX,XX @@ static bool vext_narrow_check_common(DisasContext *s, int vd, int vs2,
165
{
166
return (s->lmul <= 2) &&
167
(s->sew < MO_64) &&
168
- ((s->sew + 1) <= (s->elen >> 4)) &&
169
+ ((s->sew + 1) <= (s->cfg_ptr->elen >> 4)) &&
170
require_align(vs2, s->lmul + 1) &&
171
require_align(vd, s->lmul) &&
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)
225
{
226
int scale = s->lmul - 3;
227
- return scale < 0 ? s->vlen >> -scale : s->vlen << scale;
228
+ return scale < 0 ? s->cfg_ptr->vlen >> -scale : s->cfg_ptr->vlen << scale;
229
}
230
231
static bool opivv_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)
474
{
475
return reduction_check(s, a) && (s->sew < MO_64) &&
476
- ((s->sew + 1) <= (s->elen >> 4));
477
+ ((s->sew + 1) <= (s->cfg_ptr->elen >> 4));
478
}
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)
610
--
611
2.34.1
612
613
diff view generated by jsdifflib
New patch
1
From: Philipp Tomsich <philipp.tomsich@vrull.eu>
1
2
3
The Zb[abcs] support code still uses the RISCV_CPU macros to access
4
the configuration information (i.e., check whether an extension is
5
available/enabled). Now that we provide this information directly
6
from DisasContext, we can access this directly via the cfg_ptr field.
7
8
Signed-off-by: Philipp Tomsich <philipp.tomsich@vrull.eu>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-Id: <20220202005249.3566542-5-philipp.tomsich@vrull.eu>
13
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
14
---
15
target/riscv/insn_trans/trans_rvb.c.inc | 8 ++++----
16
1 file changed, 4 insertions(+), 4 deletions(-)
17
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
20
--- a/target/riscv/insn_trans/trans_rvb.c.inc
21
+++ b/target/riscv/insn_trans/trans_rvb.c.inc
22
@@ -XXX,XX +XXX,XX @@
23
*/
24
25
#define REQUIRE_ZBA(ctx) do { \
26
- if (!RISCV_CPU(ctx->cs)->cfg.ext_zba) { \
27
+ if (ctx->cfg_ptr->ext_zba) { \
28
return false; \
29
} \
30
} while (0)
31
32
#define REQUIRE_ZBB(ctx) do { \
33
- if (!RISCV_CPU(ctx->cs)->cfg.ext_zbb) { \
34
+ if (ctx->cfg_ptr->ext_zbb) { \
35
return false; \
36
} \
37
} while (0)
38
39
#define REQUIRE_ZBC(ctx) do { \
40
- if (!RISCV_CPU(ctx->cs)->cfg.ext_zbc) { \
41
+ if (ctx->cfg_ptr->ext_zbc) { \
42
return false; \
43
} \
44
} while (0)
45
46
#define REQUIRE_ZBS(ctx) do { \
47
- if (!RISCV_CPU(ctx->cs)->cfg.ext_zbs) { \
48
+ if (ctx->cfg_ptr->ext_zbs) { \
49
return false; \
50
} \
51
} while (0)
52
--
53
2.34.1
54
55
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Philipp Tomsich <philipp.tomsich@vrull.eu>
2
2
3
Once a "One Time Programmable" is programmed, it shouldn't be reset.
3
To split up the decoder into multiple functions (both to support
4
vendor-specific opcodes in separate files and to simplify maintenance
5
of orthogonal extensions), this changes decode_op to iterate over a
6
table of decoders predicated on guard functions.
4
7
5
Do not re-initialize the OTP content in the DeviceReset handler,
8
This commit only adds the new structure and the table, allowing for
6
initialize it once in the DeviceRealize one.
9
the easy addition of additional decoders in the future.
7
10
8
Fixes: 9fb45c62ae8 ("riscv: sifive: Implement a model for SiFive FU540 OTP")
11
Signed-off-by: Philipp Tomsich <philipp.tomsich@vrull.eu>
9
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
13
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
11
Message-Id: <20211119104757.331579-1-f4bug@amsat.org>
14
Message-Id: <20220202005249.3566542-6-philipp.tomsich@vrull.eu>
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
15
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
13
---
16
---
14
hw/misc/sifive_u_otp.c | 13 +++++--------
17
target/riscv/translate.c | 32 +++++++++++++++++++++++++++-----
15
1 file changed, 5 insertions(+), 8 deletions(-)
18
1 file changed, 27 insertions(+), 5 deletions(-)
16
19
17
diff --git a/hw/misc/sifive_u_otp.c b/hw/misc/sifive_u_otp.c
20
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
18
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/misc/sifive_u_otp.c
22
--- a/target/riscv/translate.c
20
+++ b/hw/misc/sifive_u_otp.c
23
+++ b/target/riscv/translate.c
21
@@ -XXX,XX +XXX,XX @@ static void sifive_u_otp_realize(DeviceState *dev, Error **errp)
24
@@ -XXX,XX +XXX,XX @@ static inline bool has_ext(DisasContext *ctx, uint32_t ext)
22
25
return ctx->misa_ext & ext;
23
if (blk_pread(s->blk, 0, s->fuse, filesize) != filesize) {
26
}
24
error_setg(errp, "failed to read the initial flash content");
27
28
+static bool always_true_p(DisasContext *ctx __attribute__((__unused__)))
29
+{
30
+ return true;
31
+}
32
+
33
#ifdef TARGET_RISCV32
34
#define get_xl(ctx) MXL_RV32
35
#elif defined(CONFIG_USER_ONLY)
36
@@ -XXX,XX +XXX,XX @@ static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
37
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)) {
25
+ return;
62
+ return;
26
}
63
}
27
}
64
}
28
}
65
} else {
29
-}
66
@@ -XXX,XX +XXX,XX @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
30
-
67
ctx->base.pc_next + 2));
31
-static void sifive_u_otp_reset(DeviceState *dev)
68
ctx->opcode = opcode32;
32
-{
69
ctx->pc_succ_insn = ctx->base.pc_next + 4;
33
- SiFiveUOTPState *s = SIFIVE_U_OTP(dev);
70
- if (!decode_insn32(ctx, opcode32)) {
34
71
- gen_exception_illegal(ctx);
35
/* Initialize all fuses' initial value to 0xFFs */
72
+
36
memset(s->fuse, 0xff, sizeof(s->fuse));
73
+ for (size_t i = 0; i < ARRAY_SIZE(decoders); ++i) {
37
@@ -XXX,XX +XXX,XX @@ static void sifive_u_otp_reset(DeviceState *dev)
74
+ if (decoders[i].guard_func(ctx) &&
38
serial_data = s->serial;
75
+ decoders[i].decode_func(ctx, opcode32)) {
39
if (blk_pwrite(s->blk, index * SIFIVE_U_OTP_FUSE_WORD,
76
+ return;
40
&serial_data, SIFIVE_U_OTP_FUSE_WORD, 0) < 0) {
77
+ }
41
- error_report("write error index<%d>", index);
42
+ error_setg(errp, "failed to write index<%d>", index);
43
+ return;
44
}
45
46
serial_data = ~(s->serial);
47
if (blk_pwrite(s->blk, (index + 1) * SIFIVE_U_OTP_FUSE_WORD,
48
&serial_data, SIFIVE_U_OTP_FUSE_WORD, 0) < 0) {
49
- error_report("write error index<%d>", index + 1);
50
+ error_setg(errp, "failed to write index<%d>", index + 1);
51
+ return;
52
}
78
}
53
}
79
}
54
80
+
55
@@ -XXX,XX +XXX,XX @@ static void sifive_u_otp_class_init(ObjectClass *klass, void *data)
81
+ gen_exception_illegal(ctx);
56
57
device_class_set_props(dc, sifive_u_otp_properties);
58
dc->realize = sifive_u_otp_realize;
59
- dc->reset = sifive_u_otp_reset;
60
}
82
}
61
83
62
static const TypeInfo sifive_u_otp_info = {
84
static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
63
--
85
--
64
2.31.1
86
2.34.1
65
87
66
88
diff view generated by jsdifflib
New patch
1
From: Philipp Tomsich <philipp.tomsich@vrull.eu>
1
2
3
This adds the decoder and translation for the XVentanaCondOps custom
4
extension (vendor-defined by Ventana Micro Systems), which is
5
documented at https://github.com/ventanamicro/ventana-custom-extensions/releases/download/v1.0.0/ventana-custom-extensions-v1.0.0.pdf
6
7
This commit then also adds a guard-function (has_XVentanaCondOps_p)
8
and the decoder function to the table of decoders, enabling the
9
support for the XVentanaCondOps extension.
10
11
Signed-off-by: Philipp Tomsich <philipp.tomsich@vrull.eu>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
14
Message-Id: <20220202005249.3566542-7-philipp.tomsich@vrull.eu>
15
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
16
---
17
target/riscv/cpu.h | 3 ++
18
target/riscv/XVentanaCondOps.decode | 25 ++++++++++++
19
target/riscv/cpu.c | 3 ++
20
target/riscv/translate.c | 12 ++++++
21
.../insn_trans/trans_xventanacondops.c.inc | 39 +++++++++++++++++++
22
target/riscv/meson.build | 1 +
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
26
27
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
28
index XXXXXXX..XXXXXXX 100644
29
--- a/target/riscv/cpu.h
30
+++ b/target/riscv/cpu.h
31
@@ -XXX,XX +XXX,XX @@ struct RISCVCPUConfig {
32
bool ext_zve32f;
33
bool ext_zve64f;
34
35
+ /* Vendor-specific custom extensions */
36
+ bool ext_XVentanaCondOps;
37
+
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
72
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
73
index XXXXXXX..XXXXXXX 100644
74
--- a/target/riscv/cpu.c
75
+++ b/target/riscv/cpu.c
76
@@ -XXX,XX +XXX,XX @@ static Property riscv_cpu_properties[] = {
77
DEFINE_PROP_BOOL("zbc", RISCVCPU, cfg.ext_zbc, true),
78
DEFINE_PROP_BOOL("zbs", RISCVCPU, cfg.ext_zbs, true),
79
80
+ /* Vendor-specific custom extensions */
81
+ DEFINE_PROP_BOOL("xventanacondops", RISCVCPU, cfg.ext_XVentanaCondOps, false),
82
+
83
/* These are experimental so mark with 'x-' */
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
127
new file mode 100644
128
index XXXXXXX..XXXXXXX
129
--- /dev/null
130
+++ b/target/riscv/insn_trans/trans_xventanacondops.c.inc
131
@@ -XXX,XX +XXX,XX @@
132
+/*
133
+ * RISC-V translation routines for the XVentanaCondOps extension.
134
+ *
135
+ * Copyright (c) 2021-2022 VRULL GmbH.
136
+ *
137
+ * This program is free software; you can redistribute it and/or modify it
138
+ * under the terms and conditions of the GNU General Public License,
139
+ * version 2 or later, as published by the Free Software Foundation.
140
+ *
141
+ * This program is distributed in the hope it will be useful, but WITHOUT
142
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
143
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
144
+ * more details.
145
+ *
146
+ * You should have received a copy of the GNU General Public License along with
147
+ * this program. If not, see <http://www.gnu.org/licenses/>.
148
+ */
149
+
150
+static bool gen_vt_condmask(DisasContext *ctx, arg_r *a, TCGCond cond)
151
+{
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);
155
+
156
+ tcg_gen_movcond_tl(cond, dest, src2, ctx->zero, src1, ctx->zero);
157
+
158
+ gen_set_gpr(ctx, a->rd, dest);
159
+ return true;
160
+}
161
+
162
+static bool trans_vt_maskc(DisasContext *ctx, arg_r *a)
163
+{
164
+ return gen_vt_condmask(ctx, a, TCG_COND_NE);
165
+}
166
+
167
+static bool trans_vt_maskcn(DisasContext *ctx, arg_r *a)
168
+{
169
+ return gen_vt_condmask(ctx, a, TCG_COND_EQ);
170
+}
171
diff --git a/target/riscv/meson.build b/target/riscv/meson.build
172
index XXXXXXX..XXXXXXX 100644
173
--- a/target/riscv/meson.build
174
+++ b/target/riscv/meson.build
175
@@ -XXX,XX +XXX,XX @@ dir = meson.current_source_dir()
176
gen = [
177
decodetree.process('insn16.decode', extra_args: ['--static-decode=decode_insn16', '--insnwidth=16']),
178
decodetree.process('insn32.decode', extra_args: '--static-decode=decode_insn32'),
179
+ decodetree.process('XVentanaCondOps.decode', extra_args: '--static-decode=decode_XVentanaCodeOps'),
180
]
181
182
riscv_ss = ss.source_set()
183
--
184
2.34.1
185
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
New patch
1
From: LIU Zhiwei <zhiwei_liu@c-sky.com>
1
2
3
The guest should be able to set the vill bit as part of vsetvl.
4
5
Currently we may set env->vill to 1 in the vsetvl helper, but there
6
is nowhere that we set it to 0, so once it transitions to 1 it's stuck
7
there until the system is reset.
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>
13
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
14
---
15
target/riscv/vector_helper.c | 1 +
16
1 file changed, 1 insertion(+)
17
18
diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/riscv/vector_helper.c
21
+++ b/target/riscv/vector_helper.c
22
@@ -XXX,XX +XXX,XX @@ target_ulong HELPER(vsetvl)(CPURISCVState *env, target_ulong s1,
23
env->vl = vl;
24
env->vtype = s2;
25
env->vstart = 0;
26
+ env->vill = 0;
27
return vl;
28
}
29
30
--
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
New patch
1
From: Anup Patel <anup.patel@wdc.com>
1
2
3
A hypervisor can optionally take guest external interrupts using
4
SGEIP bit of hip and hie CSRs.
5
6
Signed-off-by: Anup Patel <anup.patel@wdc.com>
7
Signed-off-by: Anup Patel <anup@brainfault.org>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.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>
12
---
13
target/riscv/cpu_bits.h | 3 +++
14
target/riscv/cpu.c | 3 ++-
15
target/riscv/csr.c | 18 +++++++++++-------
16
3 files changed, 16 insertions(+), 8 deletions(-)
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 RISCVException {
23
#define IRQ_S_EXT 9
24
#define IRQ_VS_EXT 10
25
#define IRQ_M_EXT 11
26
+#define IRQ_S_GEXT 12
27
+#define IRQ_LOCAL_MAX 16
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 */
58
}
59
60
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/target/riscv/csr.c
63
+++ b/target/riscv/csr.c
64
@@ -XXX,XX +XXX,XX @@ static RISCVException read_timeh(CPURISCVState *env, int csrno,
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;
87
}
88
@@ -XXX,XX +XXX,XX @@ static RISCVException write_mie(CPURISCVState *env, int csrno,
89
target_ulong val)
90
{
91
env->mie = (env->mie & ~all_ints) | (val & all_ints);
92
+ if (!riscv_has_ext(env, RVH)) {
93
+ env->mie &= ~MIP_SGEIP;
94
+ }
95
return RISCV_EXCP_NONE;
96
}
97
98
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_sip(CPURISCVState *env, int csrno,
99
}
100
101
if (ret_value) {
102
- *ret_value &= env->mideleg;
103
+ *ret_value &= env->mideleg & S_MODE_INTERRUPTS;
104
}
105
return ret;
106
}
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)
128
{
129
- *val = env->mie & VS_MODE_INTERRUPTS;
130
+ *val = env->mie & HS_MODE_INTERRUPTS;
131
return RISCV_EXCP_NONE;
132
}
133
134
static RISCVException write_hie(CPURISCVState *env, int csrno,
135
target_ulong val)
136
{
137
- target_ulong newval = (env->mie & ~VS_MODE_INTERRUPTS) | (val & VS_MODE_INTERRUPTS);
138
+ target_ulong newval = (env->mie & ~HS_MODE_INTERRUPTS) | (val & HS_MODE_INTERRUPTS);
139
return write_mie(env, CSR_MIE, newval);
140
}
141
142
--
143
2.34.1
144
145
diff view generated by jsdifflib
New patch
1
1
From: Anup Patel <anup.patel@wdc.com>
2
3
The hgeie and hgeip CSRs are required for emulating an external
4
interrupt controller capable of injecting virtual external interrupt
5
to Guest/VM running at VS-level.
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-4-anup@brainfault.org
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
13
---
14
target/riscv/cpu.h | 5 +++
15
target/riscv/cpu_bits.h | 1 +
16
target/riscv/cpu.c | 67 +++++++++++++++++++++++++++------------
17
target/riscv/cpu_helper.c | 37 +++++++++++++++++++--
18
target/riscv/csr.c | 43 +++++++++++++++++--------
19
target/riscv/machine.c | 6 ++--
20
6 files changed, 121 insertions(+), 38 deletions(-)
21
22
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
23
index XXXXXXX..XXXXXXX 100644
24
--- a/target/riscv/cpu.h
25
+++ b/target/riscv/cpu.h
26
@@ -XXX,XX +XXX,XX @@ struct CPURISCVState {
27
target_ulong priv;
28
/* This contains QEMU specific information about the virt state. */
29
target_ulong virt;
30
+ target_ulong geilen;
31
target_ulong resetvec;
32
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)
64
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/target/riscv/cpu.c
67
+++ b/target/riscv/cpu.c
68
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
69
static void riscv_cpu_set_irq(void *opaque, int irq, int level)
70
{
71
RISCVCPU *cpu = RISCV_CPU(opaque);
72
+ CPURISCVState *env = &cpu->env;
73
74
- switch (irq) {
75
- case IRQ_U_SOFT:
76
- case IRQ_S_SOFT:
77
- case IRQ_VS_SOFT:
78
- case IRQ_M_SOFT:
79
- case IRQ_U_TIMER:
80
- case IRQ_S_TIMER:
81
- case IRQ_VS_TIMER:
82
- case IRQ_M_TIMER:
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
151
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
152
index XXXXXXX..XXXXXXX 100644
153
--- a/target/riscv/cpu_helper.c
154
+++ b/target/riscv/cpu_helper.c
155
@@ -XXX,XX +XXX,XX @@ static int riscv_cpu_local_irq_pending(CPURISCVState *env)
156
target_ulong mstatus_mie = get_field(env->mstatus, MSTATUS_MIE);
157
target_ulong mstatus_sie = get_field(env->mstatus, MSTATUS_SIE);
158
159
- target_ulong pending = env->mip & env->mie;
160
+ target_ulong vsgemask =
161
+ (target_ulong)1 << get_field(env->hstatus, HSTATUS_VGEIN);
162
+ target_ulong vsgein = (env->hgeip & vsgemask) ? MIP_VSEIP : 0;
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);
222
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
223
index XXXXXXX..XXXXXXX 100644
224
--- a/target/riscv/csr.c
225
+++ b/target/riscv/csr.c
226
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_mip(CPURISCVState *env, int csrno,
227
RISCVCPU *cpu = env_archcpu(env);
228
/* Allow software control of delegable interrupts not claimed by hardware */
229
target_ulong mask = write_mask & delegable_ints & ~env->miclaim;
230
- uint32_t old_mip;
231
+ uint32_t gin, old_mip;
232
233
if (mask) {
234
old_mip = riscv_cpu_update_mip(cpu, mask, (new_value & mask));
235
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_mip(CPURISCVState *env, int csrno,
236
old_mip = env->mip;
237
}
238
239
+ if (csrno != CSR_HVIP) {
240
+ gin = get_field(env->hstatus, HSTATUS_VGEIN);
241
+ old_mip |= (env->hgeip & ((target_ulong)1 << gin)) ? MIP_VSEIP : 0;
242
+ }
243
+
244
if (ret_value) {
245
*ret_value = old_mip;
246
}
247
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_vsip(CPURISCVState *env, int csrno,
248
target_ulong new_value, target_ulong write_mask)
249
{
250
/* Shift the S bits to their VS bit location in mip */
251
- int ret = rmw_mip(env, 0, ret_value, new_value << 1,
252
+ int ret = rmw_mip(env, csrno, ret_value, new_value << 1,
253
(write_mask << 1) & vsip_writable_mask & env->hideleg);
254
255
if (ret_value) {
256
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_sip(CPURISCVState *env, int csrno,
257
if (riscv_cpu_virt_enabled(env)) {
258
ret = rmw_vsip(env, CSR_VSIP, ret_value, new_value, write_mask);
259
} else {
260
- ret = rmw_mip(env, CSR_MSTATUS, ret_value, new_value,
261
+ ret = rmw_mip(env, csrno, ret_value, new_value,
262
write_mask & env->mideleg & sip_writable_mask);
263
}
264
265
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_hvip(CPURISCVState *env, int csrno,
266
target_ulong *ret_value,
267
target_ulong new_value, target_ulong write_mask)
268
{
269
- int ret = rmw_mip(env, 0, ret_value, new_value,
270
+ int ret = rmw_mip(env, csrno, ret_value, new_value,
271
write_mask & hvip_writable_mask);
272
273
if (ret_value) {
274
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_hip(CPURISCVState *env, int csrno,
275
target_ulong *ret_value,
276
target_ulong new_value, target_ulong write_mask)
277
{
278
- int ret = rmw_mip(env, 0, ret_value, new_value,
279
+ int ret = rmw_mip(env, csrno, ret_value, new_value,
280
write_mask & hip_writable_mask);
281
282
if (ret_value) {
283
@@ -XXX,XX +XXX,XX @@ static RISCVException write_hcounteren(CPURISCVState *env, int csrno,
284
return RISCV_EXCP_NONE;
285
}
286
287
-static RISCVException write_hgeie(CPURISCVState *env, int csrno,
288
- target_ulong val)
289
+static RISCVException read_hgeie(CPURISCVState *env, int csrno,
290
+ target_ulong *val)
291
{
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),
366
--
367
2.34.1
368
369
diff view generated by jsdifflib
New patch
1
From: Anup Patel <anup.patel@wdc.com>
1
2
3
The guest external interrupts from an interrupt controller are
4
delivered only when the Guest/VM is running (i.e. V=1). This means
5
any guest external interrupt which is triggered while the Guest/VM
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.
8
9
To solve this, we check and inject interrupt after setting V=1.
10
11
Signed-off-by: Anup Patel <anup.patel@wdc.com>
12
Signed-off-by: Anup Patel <anup@brainfault.org>
13
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
14
Reviewed-by: Frank Chang <frank.chang@sifive.com>
15
Message-id: 20220204174700.534953-5-anup@brainfault.org
16
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
17
---
18
target/riscv/cpu_helper.c | 13 +++++++++++++
19
1 file changed, 13 insertions(+)
20
21
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/target/riscv/cpu_helper.c
24
+++ b/target/riscv/cpu_helper.c
25
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable)
26
}
27
28
env->virt = set_field(env->virt, VIRT_ONOFF, enable);
29
+
30
+ if (enable) {
31
+ /*
32
+ * The guest external interrupts from an interrupt controller are
33
+ * delivered only when the Guest/VM is running (i.e. V=1). This means
34
+ * any guest external interrupt which is triggered while the Guest/VM
35
+ * is not running (i.e. V=0) will be missed on QEMU resulting in guest
36
+ * with sluggish response to serial console input and other I/O events.
37
+ *
38
+ * To solve this, we check and inject interrupt after setting V=1.
39
+ */
40
+ riscv_cpu_update_mip(env_archcpu(env), 0, 0);
41
+ }
42
}
43
44
bool riscv_cpu_two_stage_lookup(int mmu_idx)
45
--
46
2.34.1
47
48
diff view generated by jsdifflib
New patch
1
From: Anup Patel <anup.patel@wdc.com>
1
2
3
The machine or device emulation should be able to force set certain
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.
9
10
Signed-off-by: Anup Patel <anup.patel@wdc.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>
14
Reviewed-by: Frank Chang <frank.chang@sifive.com>
15
Message-id: 20220204174700.534953-6-anup@brainfault.org
16
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
17
---
18
target/riscv/cpu.h | 5 +++++
19
target/riscv/cpu.c | 11 +++--------
20
2 files changed, 8 insertions(+), 8 deletions(-)
21
22
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
23
index XXXXXXX..XXXXXXX 100644
24
--- a/target/riscv/cpu.h
25
+++ b/target/riscv/cpu.h
26
@@ -XXX,XX +XXX,XX @@ static inline bool riscv_feature(CPURISCVState *env, int feature)
27
return env->features & (1ULL << feature);
28
}
29
30
+static inline void riscv_set_feature(CPURISCVState *env, int feature)
31
+{
32
+ env->features |= (1ULL << feature);
33
+}
34
+
35
#include "cpu_user.h"
36
37
extern const char * const riscv_int_regnames[];
38
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/target/riscv/cpu.c
41
+++ b/target/riscv/cpu.c
42
@@ -XXX,XX +XXX,XX @@ static void set_vext_version(CPURISCVState *env, int vext_ver)
43
env->vext_ver = vext_ver;
44
}
45
46
-static void set_feature(CPURISCVState *env, int feature)
47
-{
48
- env->features |= (1ULL << feature);
49
-}
50
-
51
static void set_resetvec(CPURISCVState *env, target_ulong resetvec)
52
{
53
#ifndef CONFIG_USER_ONLY
54
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
55
}
56
57
if (cpu->cfg.mmu) {
58
- set_feature(env, RISCV_FEATURE_MMU);
59
+ riscv_set_feature(env, RISCV_FEATURE_MMU);
60
}
61
62
if (cpu->cfg.pmp) {
63
- set_feature(env, RISCV_FEATURE_PMP);
64
+ riscv_set_feature(env, RISCV_FEATURE_PMP);
65
66
/*
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
}
74
}
75
76
--
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
New patch
1
From: Anup Patel <anup.patel@wdc.com>
1
2
3
The RISC-V AIA specification extends RISC-V local interrupts and
4
introduces new CSRs. This patch adds defines for the new AIA CSRs.
5
6
Signed-off-by: Anup Patel <anup.patel@wdc.com>
7
Signed-off-by: Anup Patel <anup@brainfault.org>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Reviewed-by: Frank Chang <frank.chang@sifive.com>
10
Message-id: 20220204174700.534953-8-anup@brainfault.org
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
---
13
target/riscv/cpu_bits.h | 119 ++++++++++++++++++++++++++++++++++++++++
14
1 file changed, 119 insertions(+)
15
16
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/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
113
@@ -XXX,XX +XXX,XX @@ typedef enum RISCVException {
114
#define UMTE_U_PM_INSN U_PM_INSN
115
#define UMTE_MASK (UMTE_U_PM_ENABLE | MMTE_U_PM_CURRENT | UMTE_U_PM_INSN)
116
117
+/* MISELECT, SISELECT, and VSISELECT bits (AIA) */
118
+#define ISELECT_IPRIO0 0x30
119
+#define ISELECT_IPRIO15 0x3f
120
+#define ISELECT_IMSIC_EIDELIVERY 0x70
121
+#define ISELECT_IMSIC_EITHRESHOLD 0x72
122
+#define ISELECT_IMSIC_EIP0 0x80
123
+#define ISELECT_IMSIC_EIP63 0xbf
124
+#define ISELECT_IMSIC_EIE0 0xc0
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
165
--
166
2.34.1
167
168
diff view generated by jsdifflib
New patch
1
From: Anup Patel <anup.patel@wdc.com>
1
2
3
The AIA device emulation (such as AIA IMSIC) should be able to set
4
(or provide) AIA ireg read-modify-write callback for each privilege
5
level of a RISC-V HART.
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-9-anup@brainfault.org
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
13
---
14
target/riscv/cpu.h | 23 +++++++++++++++++++++++
15
target/riscv/cpu_helper.c | 14 ++++++++++++++
16
2 files changed, 37 insertions(+)
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 @@ struct CPURISCVState {
23
uint64_t (*rdtime_fn)(uint32_t);
24
uint32_t rdtime_fn_arg;
25
26
+ /* machine specific AIA ireg read-modify-write callback */
27
+#define AIA_MAKE_IREG(__isel, __priv, __virt, __vgein, __xlen) \
28
+ ((((__xlen) & 0xff) << 24) | \
29
+ (((__vgein) & 0x3f) << 20) | \
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
60
index XXXXXXX..XXXXXXX 100644
61
--- a/target/riscv/cpu_helper.c
62
+++ b/target/riscv/cpu_helper.c
63
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(uint32_t),
64
env->rdtime_fn_arg = arg;
65
}
66
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)
74
+{
75
+ if (priv <= PRV_M) {
76
+ env->aia_ireg_rmw_fn[priv] = rmw_fn;
77
+ env->aia_ireg_rmw_fn_arg[priv] = rmw_fn_arg;
78
+ }
79
+}
80
+
81
void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv)
82
{
83
if (newpriv > PRV_M) {
84
--
85
2.34.1
86
87
diff view generated by jsdifflib
New patch
1
From: Anup Patel <anup.patel@wdc.com>
1
2
3
The AIA spec defines programmable 8-bit priority for each local interrupt
4
at M-level, S-level and VS-level so we extend local interrupt processing
5
to consider AIA interrupt priorities. The AIA CSRs which help software
6
configure local interrupt priorities will be added by subsequent patches.
7
8
Signed-off-by: Anup Patel <anup.patel@wdc.com>
9
Signed-off-by: Anup Patel <anup@brainfault.org>
10
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
11
Message-id: 20220204174700.534953-10-anup@brainfault.org
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
13
---
14
target/riscv/cpu.h | 12 ++
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
20
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/riscv/cpu.h
23
+++ b/target/riscv/cpu.h
24
@@ -XXX,XX +XXX,XX @@ struct CPURISCVState {
25
target_ulong mcause;
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);
373
}
374
+
375
+ /* Check HS-mode interrupts */
376
+ irqs = pending & env->mideleg & ~env->hideleg & -hsie;
377
+ if (irqs) {
378
+ return riscv_cpu_pending_to_irq(env, IRQ_S_EXT, IPRIO_DEFAULT_S,
379
+ irqs, env->siprio);
380
+ }
381
+
382
+ /* Check VS-mode interrupts */
383
+ irqs = pending & env->mideleg & env->hideleg & -vsie;
384
+ if (irqs) {
385
+ virq = riscv_cpu_pending_to_irq(env, IRQ_S_EXT, IPRIO_DEFAULT_S,
386
+ irqs >> 1, env->hviprio);
387
+ return (virq <= 0) ? virq : virq + 1;
388
+ }
389
+
390
+ /* Indicate no pending interrupt */
391
+ return RISCV_EXCP_NONE;
392
}
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),
416
--
417
2.34.1
418
419
diff view generated by jsdifflib
New patch
1
From: Anup Patel <anup.patel@wdc.com>
1
2
3
The AIA specification adds new CSRs for RV32 so that RISC-V hart can
4
support 64 local interrupts on both RV32 and RV64.
5
6
Signed-off-by: Anup Patel <anup.patel@wdc.com>
7
Signed-off-by: Anup Patel <anup@brainfault.org>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Reviewed-by: Frank Chang <frank.chang@sifive.com>
10
Message-id: 20220204174700.534953-11-anup@brainfault.org
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
---
13
target/riscv/cpu.h | 14 +-
14
target/riscv/cpu_helper.c | 10 +-
15
target/riscv/csr.c | 560 +++++++++++++++++++++++++++++++-------
16
target/riscv/machine.c | 10 +-
17
4 files changed, 474 insertions(+), 120 deletions(-)
18
19
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/riscv/cpu.h
22
+++ b/target/riscv/cpu.h
23
@@ -XXX,XX +XXX,XX @@ struct CPURISCVState {
24
*/
25
uint64_t mstatus;
26
27
- target_ulong mip;
28
+ uint64_t mip;
29
30
- uint32_t miclaim;
31
+ uint64_t miclaim;
32
33
- target_ulong mie;
34
- target_ulong mideleg;
35
+ uint64_t mie;
36
+ uint64_t mideleg;
37
38
target_ulong satp; /* since: priv-1.10.0 */
39
target_ulong stval;
40
@@ -XXX,XX +XXX,XX @@ struct CPURISCVState {
41
/* Hypervisor CSRs */
42
target_ulong hstatus;
43
target_ulong hedeleg;
44
- target_ulong hideleg;
45
+ uint64_t hideleg;
46
target_ulong hcounteren;
47
target_ulong htval;
48
target_ulong htinst;
49
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_list(void);
50
#ifndef CONFIG_USER_ONLY
51
bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request);
52
void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env);
53
-int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint32_t interrupts);
54
-uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value);
55
+int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts);
56
+uint64_t riscv_cpu_update_mip(RISCVCPU *cpu, uint64_t mask, uint64_t value);
57
#define BOOL_TO_MASK(x) (-!!(x)) /* helper for riscv_cpu_update_mip value */
58
void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(uint32_t),
59
uint32_t arg);
60
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/target/riscv/cpu_helper.c
63
+++ b/target/riscv/cpu_helper.c
64
@@ -XXX,XX +XXX,XX @@ bool riscv_cpu_two_stage_lookup(int mmu_idx)
65
return mmu_idx & TB_FLAGS_PRIV_HYP_ACCESS_MASK;
66
}
67
68
-int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint32_t interrupts)
69
+int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts)
70
{
71
CPURISCVState *env = &cpu->env;
72
if (env->miclaim & interrupts) {
73
@@ -XXX,XX +XXX,XX @@ int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint32_t interrupts)
74
}
75
}
76
77
-uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value)
78
+uint64_t riscv_cpu_update_mip(RISCVCPU *cpu, uint64_t mask, uint64_t value)
79
{
80
CPURISCVState *env = &cpu->env;
81
CPUState *cs = CPU(cpu);
82
- uint32_t gein, vsgein = 0, old = env->mip;
83
+ uint64_t gein, vsgein = 0, old = env->mip;
84
bool locked = false;
85
86
if (riscv_cpu_virt_enabled(env)) {
87
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_do_interrupt(CPUState *cs)
88
*/
89
bool async = !!(cs->exception_index & RISCV_EXCP_INT_FLAG);
90
target_ulong cause = cs->exception_index & RISCV_EXCP_INT_MASK;
91
- target_ulong deleg = async ? env->mideleg : env->medeleg;
92
+ uint64_t deleg = async ? env->mideleg : env->medeleg;
93
target_ulong tval = 0;
94
target_ulong htval = 0;
95
target_ulong mtval2 = 0;
96
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_do_interrupt(CPUState *cs)
97
cause < TARGET_LONG_BITS && ((deleg >> cause) & 1)) {
98
/* handle the trap in S-mode */
99
if (riscv_has_ext(env, RVH)) {
100
- target_ulong hdeleg = async ? env->hideleg : env->hedeleg;
101
+ uint64_t hdeleg = async ? env->hideleg : env->hedeleg;
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
+
573
return ret;
574
}
575
576
-static RISCVException rmw_sip(CPURISCVState *env, int csrno,
577
- target_ulong *ret_value,
578
- target_ulong new_value, target_ulong write_mask)
579
+static RISCVException rmw_vsiph(CPURISCVState *env, int csrno,
580
+ target_ulong *ret_val,
581
+ target_ulong new_val, target_ulong wr_mask)
582
{
583
- int ret;
584
+ uint64_t rval;
585
+ RISCVException ret;
586
+
587
+ ret = rmw_vsip64(env, csrno, &rval,
588
+ ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
589
+ if (ret_val) {
590
+ *ret_val = rval >> 32;
591
+ }
592
+
593
+ return ret;
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
+ }
648
+
649
return ret;
650
}
651
652
@@ -XXX,XX +XXX,XX @@ static RISCVException write_hedeleg(CPURISCVState *env, int csrno,
653
return RISCV_EXCP_NONE;
654
}
655
656
-static RISCVException read_hideleg(CPURISCVState *env, int csrno,
657
- target_ulong *val)
658
+static RISCVException rmw_hideleg64(CPURISCVState *env, int csrno,
659
+ uint64_t *ret_val,
660
+ uint64_t new_val, uint64_t wr_mask)
661
{
662
- *val = env->hideleg;
663
+ uint64_t mask = wr_mask & vs_delegable_ints;
664
+
665
+ if (ret_val) {
666
+ *ret_val = env->hideleg & vs_delegable_ints;
667
+ }
668
+
669
+ env->hideleg = (env->hideleg & ~mask) | (new_val & mask);
670
return RISCV_EXCP_NONE;
671
}
672
673
-static RISCVException write_hideleg(CPURISCVState *env, int csrno,
674
- target_ulong val)
675
+static RISCVException rmw_hideleg(CPURISCVState *env, int csrno,
676
+ target_ulong *ret_val,
677
+ target_ulong new_val, target_ulong wr_mask)
678
{
679
- env->hideleg = val & vs_delegable_ints;
680
- return RISCV_EXCP_NONE;
681
+ uint64_t rval;
682
+ RISCVException ret;
683
+
684
+ ret = rmw_hideleg64(env, csrno, &rval, new_val, wr_mask);
685
+ if (ret_val) {
686
+ *ret_val = rval;
687
+ }
688
+
689
+ return ret;
690
+}
691
+
692
+static RISCVException rmw_hidelegh(CPURISCVState *env, int csrno,
693
+ target_ulong *ret_val,
694
+ target_ulong new_val, target_ulong wr_mask)
695
+{
696
+ uint64_t rval;
697
+ RISCVException ret;
698
+
699
+ ret = rmw_hideleg64(env, csrno, &rval,
700
+ ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
701
+ if (ret_val) {
702
+ *ret_val = rval >> 32;
703
+ }
704
+
705
+ return ret;
706
+}
707
+
708
+static RISCVException rmw_hvip64(CPURISCVState *env, int csrno,
709
+ uint64_t *ret_val,
710
+ uint64_t new_val, uint64_t wr_mask)
711
+{
712
+ RISCVException ret;
713
+
714
+ ret = rmw_mip64(env, csrno, ret_val, new_val,
715
+ wr_mask & hvip_writable_mask);
716
+ if (ret_val) {
717
+ *ret_val &= VS_MODE_INTERRUPTS;
718
+ }
719
+
720
+ return ret;
721
}
722
723
static RISCVException rmw_hvip(CPURISCVState *env, int csrno,
724
- target_ulong *ret_value,
725
- target_ulong new_value, target_ulong write_mask)
726
+ target_ulong *ret_val,
727
+ target_ulong new_val, target_ulong wr_mask)
728
{
729
- int ret = rmw_mip(env, csrno, ret_value, new_value,
730
- write_mask & hvip_writable_mask);
731
+ uint64_t rval;
732
+ RISCVException ret;
733
734
- if (ret_value) {
735
- *ret_value &= VS_MODE_INTERRUPTS;
736
+ ret = rmw_hvip64(env, csrno, &rval, new_val, wr_mask);
737
+ if (ret_val) {
738
+ *ret_val = rval;
739
+ }
740
+
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),
888
--
889
2.34.1
890
891
diff view generated by jsdifflib
New patch
1
1
From: Anup Patel <anup.patel@wdc.com>
2
3
The AIA hvictl and hviprioX CSRs allow hypervisor to control
4
interrupts visible at VS-level. This patch implements AIA hvictl
5
and hviprioX 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-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>
16
---
17
target/riscv/cpu.h | 2 +
18
target/riscv/csr.c | 128 ++++++++++++++++++++++++++++++++++++++++-
19
target/riscv/machine.c | 2 +
20
3 files changed, 131 insertions(+), 1 deletion(-)
21
22
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
23
index XXXXXXX..XXXXXXX 100644
24
--- a/target/riscv/cpu.h
25
+++ b/target/riscv/cpu.h
26
@@ -XXX,XX +XXX,XX @@ struct CPURISCVState {
27
uint64_t htimedelta;
28
29
/* Hypervisor controlled virtual interrupt priorities */
30
+ target_ulong hvictl;
31
uint8_t hviprio[64];
32
33
/* Upper 64-bits of 128-bit CSRs */
34
@@ -XXX,XX +XXX,XX @@ static inline RISCVMXL riscv_cpu_mxl(CPURISCVState *env)
35
return env->misa_mxl;
36
}
37
#endif
38
+#define riscv_cpu_mxl_bits(env) (1UL << (4 + riscv_cpu_mxl(env)))
39
40
#if defined(TARGET_RISCV32)
41
#define cpu_recompute_xl(env) ((void)(env), MXL_RV32)
42
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/riscv/csr.c
45
+++ b/target/riscv/csr.c
46
@@ -XXX,XX +XXX,XX @@ static RISCVException pointer_masking(CPURISCVState *env, int csrno)
47
return RISCV_EXCP_ILLEGAL_INST;
48
}
49
50
+static int aia_hmode(CPURISCVState *env, int csrno)
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)
60
{
61
if (!riscv_feature(env, RISCV_FEATURE_AIA)) {
62
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_sie64(CPURISCVState *env, int csrno,
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;
79
}
80
81
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_sip64(CPURISCVState *env, int csrno,
82
uint64_t mask = env->mideleg & sip_writable_mask;
83
84
if (riscv_cpu_virt_enabled(env)) {
85
+ if (env->hvictl & HVICTL_VTI) {
86
+ return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
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,
92
return RISCV_EXCP_NONE;
93
}
94
95
+static int read_hvictl(CPURISCVState *env, int csrno, target_ulong *val)
96
+{
97
+ *val = env->hvictl;
98
+ return RISCV_EXCP_NONE;
99
+}
100
+
101
+static int write_hvictl(CPURISCVState *env, int csrno, target_ulong val)
102
+{
103
+ env->hvictl = val & HVICTL_VALID_MASK;
104
+ return RISCV_EXCP_NONE;
105
+}
106
+
107
+static int read_hvipriox(CPURISCVState *env, int first_index,
108
+ uint8_t *iprio, target_ulong *val)
109
+{
110
+ int i, irq, rdzero, num_irqs = 4 * (riscv_cpu_mxl_bits(env) / 32);
111
+
112
+ /* First index has to be a multiple of number of irqs per register */
113
+ if (first_index % num_irqs) {
114
+ return (riscv_cpu_virt_enabled(env)) ?
115
+ RISCV_EXCP_VIRT_INSTRUCTION_FAULT : RISCV_EXCP_ILLEGAL_INST;
116
+ }
117
+
118
+ /* Fill-up return value */
119
+ *val = 0;
120
+ for (i = 0; i < num_irqs; i++) {
121
+ if (riscv_cpu_hviprio_index2irq(first_index + i, &irq, &rdzero)) {
122
+ continue;
123
+ }
124
+ if (rdzero) {
125
+ continue;
126
+ }
127
+ *val |= ((target_ulong)iprio[irq]) << (i * 8);
128
+ }
129
+
130
+ return RISCV_EXCP_NONE;
131
+}
132
+
133
+static int write_hvipriox(CPURISCVState *env, int first_index,
134
+ uint8_t *iprio, target_ulong val)
135
+{
136
+ int i, irq, rdzero, num_irqs = 4 * (riscv_cpu_mxl_bits(env) / 32);
137
+
138
+ /* First index has to be a multiple of number of irqs per register */
139
+ if (first_index % num_irqs) {
140
+ return (riscv_cpu_virt_enabled(env)) ?
141
+ RISCV_EXCP_VIRT_INSTRUCTION_FAULT : RISCV_EXCP_ILLEGAL_INST;
142
+ }
143
+
144
+ /* Fill-up priority arrary */
145
+ for (i = 0; i < num_irqs; i++) {
146
+ if (riscv_cpu_hviprio_index2irq(first_index + i, &irq, &rdzero)) {
147
+ continue;
148
+ }
149
+ if (rdzero) {
150
+ iprio[irq] = 0;
151
+ } else {
152
+ iprio[irq] = (val >> (i * 8)) & 0xff;
153
+ }
154
+ }
155
+
156
+ return RISCV_EXCP_NONE;
157
+}
158
+
159
+static int read_hviprio1(CPURISCVState *env, int csrno, target_ulong *val)
160
+{
161
+ return read_hvipriox(env, 0, env->hviprio, val);
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
220
index XXXXXXX..XXXXXXX 100644
221
--- a/target/riscv/machine.c
222
+++ b/target/riscv/machine.c
223
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_hyper = {
224
VMSTATE_UINTTL(env.hgeie, RISCVCPU),
225
VMSTATE_UINTTL(env.hgeip, RISCVCPU),
226
VMSTATE_UINT64(env.htimedelta, RISCVCPU),
227
+
228
+ VMSTATE_UINTTL(env.hvictl, RISCVCPU),
229
VMSTATE_UINT8_ARRAY(env.hviprio, RISCVCPU, 64),
230
231
VMSTATE_UINT64(env.vsstatus, RISCVCPU),
232
--
233
2.34.1
234
235
diff view generated by jsdifflib
New patch
1
From: Anup Patel <anup.patel@wdc.com>
1
2
3
The AIA specificaiton adds interrupt filtering support for M-mode
4
and HS-mode. Using AIA interrupt filtering M-mode and H-mode can
5
take local interrupt 13 or above and selectively inject same local
6
interrupt to lower privilege modes.
7
8
At the moment, we don't have any local interrupts above 12 so we
9
add dummy implementation (i.e. read zero and ignore write) of AIA
10
interrupt filtering CSRs.
11
12
Signed-off-by: Anup Patel <anup.patel@wdc.com>
13
Signed-off-by: Anup Patel <anup@brainfault.org>
14
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
15
Reviewed-by: Frank Chang <frank.chang@sifive.com>
16
Message-id: 20220204174700.534953-13-anup@brainfault.org
17
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
18
---
19
target/riscv/csr.c | 23 +++++++++++++++++++++++
20
1 file changed, 23 insertions(+)
21
22
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/target/riscv/csr.c
25
+++ b/target/riscv/csr.c
26
@@ -XXX,XX +XXX,XX @@ static RISCVException any32(CPURISCVState *env, int csrno)
27
28
}
29
30
+static int aia_any(CPURISCVState *env, int csrno)
31
+{
32
+ if (!riscv_feature(env, RISCV_FEATURE_AIA)) {
33
+ return RISCV_EXCP_ILLEGAL_INST;
34
+ }
35
+
36
+ return any(env, csrno);
37
+}
38
+
39
static int aia_any32(CPURISCVState *env, int csrno)
40
{
41
if (!riscv_feature(env, RISCV_FEATURE_AIA)) {
42
@@ -XXX,XX +XXX,XX @@ static RISCVException read_zero(CPURISCVState *env, int csrno,
43
return RISCV_EXCP_NONE;
44
}
45
46
+static RISCVException write_ignore(CPURISCVState *env, int csrno,
47
+ target_ulong val)
48
+{
49
+ return RISCV_EXCP_NONE;
50
+}
51
+
52
static RISCVException read_mhartid(CPURISCVState *env, int csrno,
53
target_ulong *val)
54
{
55
@@ -XXX,XX +XXX,XX @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
56
[CSR_MTVAL] = { "mtval", any, read_mtval, write_mtval },
57
[CSR_MIP] = { "mip", any, NULL, NULL, rmw_mip },
58
59
+ /* Virtual Interrupts for Supervisor Level (AIA) */
60
+ [CSR_MVIEN] = { "mvien", aia_any, read_zero, write_ignore },
61
+ [CSR_MVIP] = { "mvip", aia_any, read_zero, write_ignore },
62
+
63
/* Machine-Level High-Half CSRs (AIA) */
64
[CSR_MIDELEGH] = { "midelegh", aia_any32, NULL, NULL, rmw_midelegh },
65
[CSR_MIEH] = { "mieh", aia_any32, NULL, NULL, rmw_mieh },
66
+ [CSR_MVIENH] = { "mvienh", aia_any32, read_zero, write_ignore },
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 },
86
--
87
2.34.1
88
89
diff view generated by jsdifflib
New patch
1
1
From: Anup Patel <anup.patel@wdc.com>
2
3
The AIA specification introduces new [m|s|vs]topi CSRs for
4
reporting pending local IRQ number and associated IRQ priority.
5
6
Signed-off-by: Anup Patel <anup.patel@wdc.com>
7
Signed-off-by: Anup Patel <anup@brainfault.org>
8
Reviewed-by: Frank Chang <frank.chang@sifive.com>
9
Message-id: 20220204174700.534953-14-anup@brainfault.org
10
[ Changed by AF:
11
- Fixup indentation
12
]
13
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
14
---
15
target/riscv/csr.c | 156 +++++++++++++++++++++++++++++++++++++++++++++
16
1 file changed, 156 insertions(+)
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 int smode32(CPURISCVState *env, int csrno)
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)
36
{
37
if (!riscv_feature(env, RISCV_FEATURE_AIA)) {
38
@@ -XXX,XX +XXX,XX @@ static RISCVException read_timeh(CPURISCVState *env, int csrno,
39
#define VS_MODE_INTERRUPTS ((uint64_t)(MIP_VSSIP | MIP_VSTIP | MIP_VSEIP))
40
#define HS_MODE_INTERRUPTS ((uint64_t)(MIP_SGEIP | VS_MODE_INTERRUPTS))
41
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;
49
}
50
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)
75
{
76
@@ -XXX,XX +XXX,XX @@ static RISCVException write_satp(CPURISCVState *env, int csrno,
77
return RISCV_EXCP_NONE;
78
}
79
80
+static int read_vstopi(CPURISCVState *env, int csrno, target_ulong *val)
81
+{
82
+ int irq, ret;
83
+ target_ulong topei;
84
+ uint64_t vseip, vsgein;
85
+ uint32_t iid, iprio, hviid, hviprio, gein;
86
+ uint32_t s, scount = 0, siid[VSTOPI_NUM_SRCS], siprio[VSTOPI_NUM_SRCS];
87
+
88
+ gein = get_field(env->hstatus, HSTATUS_VGEIN);
89
+ hviid = get_field(env->hvictl, HVICTL_IID);
90
+ hviprio = get_field(env->hvictl, HVICTL_IPRIO);
91
+
92
+ if (gein) {
93
+ vsgein = (env->hgeip & (1ULL << gein)) ? MIP_VSEIP : 0;
94
+ vseip = env->mie & (env->mip | vsgein) & MIP_VSEIP;
95
+ if (gein <= env->geilen && vseip) {
96
+ siid[scount] = IRQ_S_EXT;
97
+ siprio[scount] = IPRIO_MMAXIPRIO + 1;
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 },
227
--
228
2.34.1
229
230
diff view generated by jsdifflib
New patch
1
1
From: Anup Patel <anup.patel@wdc.com>
2
3
The AIA specification defines [m|s|vs]iselect and [m|s|vs]ireg CSRs
4
which allow indirect access to interrupt priority arrays and per-HART
5
IMSIC registers. This patch implements AIA xiselect and xireg CSRs.
6
7
Signed-off-by: Anup Patel <anup.patel@wdc.com>
8
Signed-off-by: Anup Patel <anup@brainfault.org>
9
Reviewed-by: Frank Chang <frank.chang@sifive.com>
10
Message-id: 20220204174700.534953-15-anup@brainfault.org
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
---
13
target/riscv/cpu.h | 7 ++
14
target/riscv/csr.c | 177 +++++++++++++++++++++++++++++++++++++++++
15
target/riscv/machine.c | 3 +
16
3 files changed, 187 insertions(+)
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 @@ struct CPURISCVState {
23
uint8_t miprio[64];
24
uint8_t siprio[64];
25
26
+ /* AIA CSRs */
27
+ target_ulong miselect;
28
+ target_ulong siselect;
29
+
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;
42
43
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/target/riscv/csr.c
46
+++ b/target/riscv/csr.c
47
@@ -XXX,XX +XXX,XX @@ static int read_mtopi(CPURISCVState *env, int csrno, target_ulong *val)
48
return RISCV_EXCP_NONE;
49
}
50
51
+static int aia_xlate_vs_csrno(CPURISCVState *env, int csrno)
52
+{
53
+ if (!riscv_cpu_virt_enabled(env)) {
54
+ return csrno;
55
+ }
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)
216
{
217
@@ -XXX,XX +XXX,XX @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
218
[CSR_MTVAL] = { "mtval", any, read_mtval, write_mtval },
219
[CSR_MIP] = { "mip", any, NULL, NULL, rmw_mip },
220
221
+ /* Machine-Level Window to Indirectly Accessed Registers (AIA) */
222
+ [CSR_MISELECT] = { "miselect", aia_any, NULL, NULL, rmw_xiselect },
223
+ [CSR_MIREG] = { "mireg", aia_any, NULL, NULL, rmw_xireg },
224
+
225
/* Machine-Level Interrupts (AIA) */
226
[CSR_MTOPI] = { "mtopi", aia_any, read_mtopi },
227
228
@@ -XXX,XX +XXX,XX @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
229
/* Supervisor Protection and Translation */
230
[CSR_SATP] = { "satp", smode, read_satp, write_satp },
231
232
+ /* Supervisor-Level Window to Indirectly Accessed Registers (AIA) */
233
+ [CSR_SISELECT] = { "siselect", aia_smode, NULL, NULL, rmw_xiselect },
234
+ [CSR_SIREG] = { "sireg", aia_smode, NULL, NULL, rmw_xireg },
235
+
236
/* Supervisor-Level Interrupts (AIA) */
237
[CSR_STOPI] = { "stopi", aia_smode, read_stopi },
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
253
index XXXXXXX..XXXXXXX 100644
254
--- a/target/riscv/machine.c
255
+++ b/target/riscv/machine.c
256
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_hyper = {
257
VMSTATE_UINTTL(env.vscause, RISCVCPU),
258
VMSTATE_UINTTL(env.vstval, RISCVCPU),
259
VMSTATE_UINTTL(env.vsatp, RISCVCPU),
260
+ VMSTATE_UINTTL(env.vsiselect, RISCVCPU),
261
262
VMSTATE_UINTTL(env.mtval2, RISCVCPU),
263
VMSTATE_UINTTL(env.mtinst, RISCVCPU),
264
@@ -XXX,XX +XXX,XX @@ const VMStateDescription vmstate_riscv_cpu = {
265
VMSTATE_UINTTL(env.mepc, RISCVCPU),
266
VMSTATE_UINTTL(env.mcause, RISCVCPU),
267
VMSTATE_UINTTL(env.mtval, RISCVCPU),
268
+ VMSTATE_UINTTL(env.miselect, RISCVCPU),
269
+ VMSTATE_UINTTL(env.siselect, RISCVCPU),
270
VMSTATE_UINTTL(env.scounteren, RISCVCPU),
271
VMSTATE_UINTTL(env.mcounteren, RISCVCPU),
272
VMSTATE_UINTTL(env.sscratch, RISCVCPU),
273
--
274
2.34.1
275
276
diff view generated by jsdifflib
New patch
1
1
From: Anup Patel <anup.patel@wdc.com>
2
3
The AIA specification defines IMSIC interface CSRs for easy access
4
to the per-HART IMSIC registers without using indirect xiselect and
5
xireg CSRs. This patch implements the AIA IMSIC interface CSRs.
6
7
Signed-off-by: Anup Patel <anup.patel@wdc.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
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
---
13
target/riscv/csr.c | 203 +++++++++++++++++++++++++++++++++++++++++++++
14
1 file changed, 203 insertions(+)
15
16
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/riscv/csr.c
19
+++ b/target/riscv/csr.c
20
@@ -XXX,XX +XXX,XX @@ static int aia_xlate_vs_csrno(CPURISCVState *env, int csrno)
21
return CSR_VSISELECT;
22
case CSR_SIREG:
23
return CSR_VSIREG;
24
+ case CSR_SSETEIPNUM:
25
+ return CSR_VSSETEIPNUM;
26
+ case CSR_SCLREIPNUM:
27
+ return CSR_VSCLREIPNUM;
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;
39
}
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 },
258
--
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
New patch
1
From: Anup Patel <anup.patel@wdc.com>
1
2
3
We add "x-aia" command-line option for RISC-V HART using which
4
allows users to force enable CPU AIA CSRs without changing the
5
interrupt controller available in RISC-V machine.
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-18-anup@brainfault.org
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
13
---
14
target/riscv/cpu.h | 1 +
15
target/riscv/cpu.c | 5 +++++
16
2 files changed, 6 insertions(+)
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 @@ 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)
35
}
36
}
37
38
+ if (cpu->cfg.aia) {
39
+ riscv_set_feature(env, RISCV_FEATURE_AIA);
40
+ }
41
+
42
set_resetvec(env, cpu->cfg.resetvec);
43
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(),
53
--
54
2.34.1
55
56
diff view generated by jsdifflib
New patch
1
From: Anup Patel <anup.patel@wdc.com>
1
2
3
The RISC-V AIA (Advanced Interrupt Architecture) defines a new
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).
8
9
This patch adds device emulation for RISC-V AIA APLIC.
10
11
Signed-off-by: Anup Patel <anup.patel@wdc.com>
12
Signed-off-by: Anup Patel <anup@brainfault.org>
13
Reviewed-by: Frank Chang <frank.chang@sifive.com>
14
Message-id: 20220204174700.534953-19-anup@brainfault.org
15
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
16
---
17
include/hw/intc/riscv_aplic.h | 79 +++
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
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
110
diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
111
new file mode 100644
112
index XXXXXXX..XXXXXXX
113
--- /dev/null
114
+++ b/hw/intc/riscv_aplic.c
115
@@ -XXX,XX +XXX,XX @@
116
+/*
117
+ * RISC-V APLIC (Advanced Platform Level Interrupt Controller)
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
+
1078
+ if (parent) {
1079
+ riscv_aplic_add_child(parent, dev);
1080
+ }
1081
+
1082
+ if (!msimode) {
1083
+ for (i = 0; i < num_harts; i++) {
1084
+ CPUState *cpu = qemu_get_cpu(hartid_base + i);
1085
+
1086
+ qdev_connect_gpio_out_named(dev, NULL, i,
1087
+ qdev_get_gpio_in(DEVICE(cpu),
1088
+ (mmode) ? IRQ_M_EXT : IRQ_S_EXT));
1089
+ }
1090
+ }
1091
+
1092
+ return dev;
1093
+}
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'],
1120
--
1121
2.34.1
1122
1123
1124
diff view generated by jsdifflib
New patch
1
From: Anup Patel <anup.patel@wdc.com>
1
2
3
We extend virt machine to emulate AIA APLIC devices only when
4
"aia=aplic" parameter is passed along with machine name in QEMU
5
command-line. When "aia=none" or not specified then we fallback
6
to original PLIC device emulation.
7
8
Signed-off-by: Anup Patel <anup.patel@wdc.com>
9
Signed-off-by: Anup Patel <anup@brainfault.org>
10
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
11
Message-id: 20220204174700.534953-20-anup@brainfault.org
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
13
---
14
include/hw/riscv/virt.h | 26 +++-
15
hw/riscv/virt.c | 291 ++++++++++++++++++++++++++++++++--------
16
hw/riscv/Kconfig | 1 +
17
3 files changed, 259 insertions(+), 59 deletions(-)
18
19
diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/include/hw/riscv/virt.h
22
+++ b/include/hw/riscv/virt.h
23
@@ -XXX,XX +XXX,XX @@ typedef struct RISCVVirtState RISCVVirtState;
24
DECLARE_INSTANCE_CHECKER(RISCVVirtState, RISCV_VIRT_MACHINE,
25
TYPE_RISCV_VIRT_MACHINE)
26
27
+typedef enum RISCVVirtAIAType {
28
+ VIRT_AIA_TYPE_NONE = 0,
29
+ VIRT_AIA_TYPE_APLIC,
30
+} RISCVVirtAIAType;
31
+
32
struct RISCVVirtState {
33
/*< private >*/
34
MachineState parent;
35
36
/*< public >*/
37
RISCVHartArrayState soc[VIRT_SOCKETS_MAX];
38
- DeviceState *plic[VIRT_SOCKETS_MAX];
39
+ DeviceState *irqchip[VIRT_SOCKETS_MAX];
40
PFlashCFI01 *flash[2];
41
FWCfgState *fw_cfg;
42
43
int fdt_size;
44
bool have_aclint;
45
+ RISCVVirtAIAType aia_type;
46
};
47
48
enum {
49
@@ -XXX,XX +XXX,XX @@ enum {
50
VIRT_CLINT,
51
VIRT_ACLINT_SSWI,
52
VIRT_PLIC,
53
+ VIRT_APLIC_M,
54
+ VIRT_APLIC_S,
55
VIRT_UART0,
56
VIRT_VIRTIO,
57
VIRT_FW_CFG,
58
@@ -XXX,XX +XXX,XX @@ enum {
59
VIRTIO_NDEV = 0x35 /* Arbitrary maximum number of interrupts */
60
};
61
62
-#define VIRT_PLIC_NUM_SOURCES 127
63
-#define VIRT_PLIC_NUM_PRIORITIES 7
64
+#define VIRT_IRQCHIP_NUM_SOURCES 127
65
+#define VIRT_IRQCHIP_NUM_PRIO_BITS 3
66
+
67
#define VIRT_PLIC_PRIORITY_BASE 0x04
68
#define VIRT_PLIC_PENDING_BASE 0x1000
69
#define VIRT_PLIC_ENABLE_BASE 0x2000
70
@@ -XXX,XX +XXX,XX @@ enum {
71
72
#define FDT_PCI_ADDR_CELLS 3
73
#define FDT_PCI_INT_CELLS 1
74
-#define FDT_PLIC_ADDR_CELLS 0
75
#define FDT_PLIC_INT_CELLS 1
76
-#define FDT_INT_MAP_WIDTH (FDT_PCI_ADDR_CELLS + FDT_PCI_INT_CELLS + 1 + \
77
- FDT_PLIC_ADDR_CELLS + FDT_PLIC_INT_CELLS)
78
+#define FDT_APLIC_INT_CELLS 2
79
+#define FDT_MAX_INT_CELLS 2
80
+#define FDT_MAX_INT_MAP_WIDTH (FDT_PCI_ADDR_CELLS + FDT_PCI_INT_CELLS + \
81
+ 1 + FDT_MAX_INT_CELLS)
82
+#define FDT_PLIC_INT_MAP_WIDTH (FDT_PCI_ADDR_CELLS + FDT_PCI_INT_CELLS + \
83
+ 1 + FDT_PLIC_INT_CELLS)
84
+#define FDT_APLIC_INT_MAP_WIDTH (FDT_PCI_ADDR_CELLS + FDT_PCI_INT_CELLS + \
85
+ 1 + FDT_APLIC_INT_CELLS)
86
87
#endif
88
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
89
index XXXXXXX..XXXXXXX 100644
90
--- a/hw/riscv/virt.c
91
+++ b/hw/riscv/virt.c
92
@@ -XXX,XX +XXX,XX @@
93
#include "hw/riscv/boot.h"
94
#include "hw/riscv/numa.h"
95
#include "hw/intc/riscv_aclint.h"
96
+#include "hw/intc/riscv_aplic.h"
97
#include "hw/intc/sifive_plic.h"
98
#include "hw/misc/sifive_test.h"
99
#include "chardev/char.h"
100
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry virt_memmap[] = {
101
[VIRT_ACLINT_SSWI] = { 0x2F00000, 0x4000 },
102
[VIRT_PCIE_PIO] = { 0x3000000, 0x10000 },
103
[VIRT_PLIC] = { 0xc000000, VIRT_PLIC_SIZE(VIRT_CPUS_MAX * 2) },
104
+ [VIRT_APLIC_M] = { 0xc000000, APLIC_SIZE(VIRT_CPUS_MAX) },
105
+ [VIRT_APLIC_S] = { 0xd000000, APLIC_SIZE(VIRT_CPUS_MAX) },
106
[VIRT_UART0] = { 0x10000000, 0x100 },
107
[VIRT_VIRTIO] = { 0x10001000, 0x1000 },
108
[VIRT_FW_CFG] = { 0x10100000, 0x18 },
109
@@ -XXX,XX +XXX,XX @@ static void virt_flash_map(RISCVVirtState *s,
110
sysmem);
111
}
112
113
-static void create_pcie_irq_map(void *fdt, char *nodename,
114
- uint32_t plic_phandle)
115
+static void create_pcie_irq_map(RISCVVirtState *s, void *fdt, char *nodename,
116
+ uint32_t irqchip_phandle)
117
{
118
int pin, dev;
119
- uint32_t
120
- full_irq_map[GPEX_NUM_IRQS * GPEX_NUM_IRQS * FDT_INT_MAP_WIDTH] = {};
121
+ uint32_t irq_map_stride = 0;
122
+ uint32_t full_irq_map[GPEX_NUM_IRQS * GPEX_NUM_IRQS *
123
+ FDT_MAX_INT_MAP_WIDTH] = {};
124
uint32_t *irq_map = full_irq_map;
125
126
/* This code creates a standard swizzle of interrupts such that
127
@@ -XXX,XX +XXX,XX @@ static void create_pcie_irq_map(void *fdt, char *nodename,
128
int irq_nr = PCIE_IRQ + ((pin + PCI_SLOT(devfn)) % GPEX_NUM_IRQS);
129
int i = 0;
130
131
+ /* Fill PCI address cells */
132
irq_map[i] = cpu_to_be32(devfn << 8);
133
-
134
i += FDT_PCI_ADDR_CELLS;
135
- irq_map[i] = cpu_to_be32(pin + 1);
136
137
+ /* Fill PCI Interrupt cells */
138
+ irq_map[i] = cpu_to_be32(pin + 1);
139
i += FDT_PCI_INT_CELLS;
140
- irq_map[i++] = cpu_to_be32(plic_phandle);
141
142
- i += FDT_PLIC_ADDR_CELLS;
143
- irq_map[i] = cpu_to_be32(irq_nr);
144
+ /* Fill interrupt controller phandle and cells */
145
+ irq_map[i++] = cpu_to_be32(irqchip_phandle);
146
+ irq_map[i++] = cpu_to_be32(irq_nr);
147
+ if (s->aia_type != VIRT_AIA_TYPE_NONE) {
148
+ irq_map[i++] = cpu_to_be32(0x4);
149
+ }
150
151
- irq_map += FDT_INT_MAP_WIDTH;
152
+ if (!irq_map_stride) {
153
+ irq_map_stride = i;
154
+ }
155
+ irq_map += irq_map_stride;
156
}
157
}
158
159
- qemu_fdt_setprop(fdt, nodename, "interrupt-map",
160
- full_irq_map, sizeof(full_irq_map));
161
+ qemu_fdt_setprop(fdt, nodename, "interrupt-map", full_irq_map,
162
+ GPEX_NUM_IRQS * GPEX_NUM_IRQS *
163
+ irq_map_stride * sizeof(uint32_t));
164
165
qemu_fdt_setprop_cells(fdt, nodename, "interrupt-map-mask",
166
0x1800, 0, 0, 0x7);
167
@@ -XXX,XX +XXX,XX @@ static void create_fdt_socket_plic(RISCVVirtState *s,
168
plic_addr = memmap[VIRT_PLIC].base + (memmap[VIRT_PLIC].size * socket);
169
plic_name = g_strdup_printf("/soc/plic@%lx", plic_addr);
170
qemu_fdt_add_subnode(mc->fdt, plic_name);
171
- qemu_fdt_setprop_cell(mc->fdt, plic_name,
172
- "#address-cells", FDT_PLIC_ADDR_CELLS);
173
qemu_fdt_setprop_cell(mc->fdt, plic_name,
174
"#interrupt-cells", FDT_PLIC_INT_CELLS);
175
qemu_fdt_setprop_string_array(mc->fdt, plic_name, "compatible",
176
@@ -XXX,XX +XXX,XX @@ static void create_fdt_socket_plic(RISCVVirtState *s,
177
g_free(plic_cells);
178
}
179
180
+static void create_fdt_socket_aia(RISCVVirtState *s,
181
+ const MemMapEntry *memmap, int socket,
182
+ uint32_t *phandle, uint32_t *intc_phandles,
183
+ uint32_t *aplic_phandles)
184
+{
185
+ int cpu;
186
+ char *aplic_name;
187
+ uint32_t *aplic_cells;
188
+ unsigned long aplic_addr;
189
+ MachineState *mc = MACHINE(s);
190
+ uint32_t aplic_m_phandle, aplic_s_phandle;
191
+
192
+ aplic_m_phandle = (*phandle)++;
193
+ aplic_s_phandle = (*phandle)++;
194
+ aplic_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2);
195
+
196
+ /* M-level APLIC node */
197
+ for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) {
198
+ aplic_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
199
+ aplic_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_M_EXT);
200
+ }
201
+ aplic_addr = memmap[VIRT_APLIC_M].base +
202
+ (memmap[VIRT_APLIC_M].size * socket);
203
+ aplic_name = g_strdup_printf("/soc/aplic@%lx", aplic_addr);
204
+ qemu_fdt_add_subnode(mc->fdt, aplic_name);
205
+ qemu_fdt_setprop_string(mc->fdt, aplic_name, "compatible", "riscv,aplic");
206
+ qemu_fdt_setprop_cell(mc->fdt, aplic_name,
207
+ "#interrupt-cells", FDT_APLIC_INT_CELLS);
208
+ qemu_fdt_setprop(mc->fdt, aplic_name, "interrupt-controller", NULL, 0);
209
+ qemu_fdt_setprop(mc->fdt, aplic_name, "interrupts-extended",
210
+ aplic_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 2);
211
+ qemu_fdt_setprop_cells(mc->fdt, aplic_name, "reg",
212
+ 0x0, aplic_addr, 0x0, memmap[VIRT_APLIC_M].size);
213
+ qemu_fdt_setprop_cell(mc->fdt, aplic_name, "riscv,num-sources",
214
+ VIRT_IRQCHIP_NUM_SOURCES);
215
+ qemu_fdt_setprop_cell(mc->fdt, aplic_name, "riscv,children",
216
+ aplic_s_phandle);
217
+ qemu_fdt_setprop_cells(mc->fdt, aplic_name, "riscv,delegate",
218
+ aplic_s_phandle, 0x1, VIRT_IRQCHIP_NUM_SOURCES);
219
+ riscv_socket_fdt_write_id(mc, mc->fdt, aplic_name, socket);
220
+ qemu_fdt_setprop_cell(mc->fdt, aplic_name, "phandle", aplic_m_phandle);
221
+ g_free(aplic_name);
222
+
223
+ /* S-level APLIC node */
224
+ for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) {
225
+ aplic_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
226
+ aplic_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_S_EXT);
227
+ }
228
+ aplic_addr = memmap[VIRT_APLIC_S].base +
229
+ (memmap[VIRT_APLIC_S].size * socket);
230
+ aplic_name = g_strdup_printf("/soc/aplic@%lx", aplic_addr);
231
+ qemu_fdt_add_subnode(mc->fdt, aplic_name);
232
+ qemu_fdt_setprop_string(mc->fdt, aplic_name, "compatible", "riscv,aplic");
233
+ qemu_fdt_setprop_cell(mc->fdt, aplic_name,
234
+ "#interrupt-cells", FDT_APLIC_INT_CELLS);
235
+ qemu_fdt_setprop(mc->fdt, aplic_name, "interrupt-controller", NULL, 0);
236
+ qemu_fdt_setprop(mc->fdt, aplic_name, "interrupts-extended",
237
+ aplic_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 2);
238
+ qemu_fdt_setprop_cells(mc->fdt, aplic_name, "reg",
239
+ 0x0, aplic_addr, 0x0, memmap[VIRT_APLIC_S].size);
240
+ qemu_fdt_setprop_cell(mc->fdt, aplic_name, "riscv,num-sources",
241
+ VIRT_IRQCHIP_NUM_SOURCES);
242
+ riscv_socket_fdt_write_id(mc, mc->fdt, aplic_name, socket);
243
+ qemu_fdt_setprop_cell(mc->fdt, aplic_name, "phandle", aplic_s_phandle);
244
+ g_free(aplic_name);
245
+
246
+ g_free(aplic_cells);
247
+ aplic_phandles[socket] = aplic_s_phandle;
248
+}
249
+
250
static void create_fdt_sockets(RISCVVirtState *s, const MemMapEntry *memmap,
251
bool is_32_bit, uint32_t *phandle,
252
uint32_t *irq_mmio_phandle,
253
@@ -XXX,XX +XXX,XX @@ static void create_fdt_sockets(RISCVVirtState *s, const MemMapEntry *memmap,
254
}
255
}
256
257
- create_fdt_socket_plic(s, memmap, socket, phandle,
258
- intc_phandles, xplic_phandles);
259
+ if (s->aia_type == VIRT_AIA_TYPE_NONE) {
260
+ create_fdt_socket_plic(s, memmap, socket, phandle,
261
+ intc_phandles, xplic_phandles);
262
+ } else {
263
+ create_fdt_socket_aia(s, memmap, socket, phandle,
264
+ intc_phandles, xplic_phandles);
265
+ }
266
267
g_free(intc_phandles);
268
g_free(clust_name);
269
@@ -XXX,XX +XXX,XX @@ static void create_fdt_virtio(RISCVVirtState *s, const MemMapEntry *memmap,
270
0x0, memmap[VIRT_VIRTIO].size);
271
qemu_fdt_setprop_cell(mc->fdt, name, "interrupt-parent",
272
irq_virtio_phandle);
273
- qemu_fdt_setprop_cell(mc->fdt, name, "interrupts", VIRTIO_IRQ + i);
274
+ if (s->aia_type == VIRT_AIA_TYPE_NONE) {
275
+ qemu_fdt_setprop_cell(mc->fdt, name, "interrupts",
276
+ VIRTIO_IRQ + i);
277
+ } else {
278
+ qemu_fdt_setprop_cells(mc->fdt, name, "interrupts",
279
+ VIRTIO_IRQ + i, 0x4);
280
+ }
281
g_free(name);
282
}
283
}
284
@@ -XXX,XX +XXX,XX @@ static void create_fdt_pcie(RISCVVirtState *s, const MemMapEntry *memmap,
285
2, virt_high_pcie_memmap.base,
286
2, virt_high_pcie_memmap.base, 2, virt_high_pcie_memmap.size);
287
288
- create_pcie_irq_map(mc->fdt, name, irq_pcie_phandle);
289
+ create_pcie_irq_map(s, mc->fdt, name, irq_pcie_phandle);
290
g_free(name);
291
}
292
293
@@ -XXX,XX +XXX,XX @@ static void create_fdt_uart(RISCVVirtState *s, const MemMapEntry *memmap,
294
0x0, memmap[VIRT_UART0].size);
295
qemu_fdt_setprop_cell(mc->fdt, name, "clock-frequency", 3686400);
296
qemu_fdt_setprop_cell(mc->fdt, name, "interrupt-parent", irq_mmio_phandle);
297
- qemu_fdt_setprop_cell(mc->fdt, name, "interrupts", UART0_IRQ);
298
+ if (s->aia_type == VIRT_AIA_TYPE_NONE) {
299
+ qemu_fdt_setprop_cell(mc->fdt, name, "interrupts", UART0_IRQ);
300
+ } else {
301
+ qemu_fdt_setprop_cells(mc->fdt, name, "interrupts", UART0_IRQ, 0x4);
302
+ }
303
304
qemu_fdt_add_subnode(mc->fdt, "/chosen");
305
qemu_fdt_setprop_string(mc->fdt, "/chosen", "stdout-path", name);
306
@@ -XXX,XX +XXX,XX @@ static void create_fdt_rtc(RISCVVirtState *s, const MemMapEntry *memmap,
307
0x0, memmap[VIRT_RTC].base, 0x0, memmap[VIRT_RTC].size);
308
qemu_fdt_setprop_cell(mc->fdt, name, "interrupt-parent",
309
irq_mmio_phandle);
310
- qemu_fdt_setprop_cell(mc->fdt, name, "interrupts", RTC_IRQ);
311
+ if (s->aia_type == VIRT_AIA_TYPE_NONE) {
312
+ qemu_fdt_setprop_cell(mc->fdt, name, "interrupts", RTC_IRQ);
313
+ } else {
314
+ qemu_fdt_setprop_cells(mc->fdt, name, "interrupts", RTC_IRQ, 0x4);
315
+ }
316
g_free(name);
317
}
318
319
@@ -XXX,XX +XXX,XX @@ static inline DeviceState *gpex_pcie_init(MemoryRegion *sys_mem,
320
hwaddr high_mmio_base,
321
hwaddr high_mmio_size,
322
hwaddr pio_base,
323
- DeviceState *plic)
324
+ DeviceState *irqchip)
325
{
326
DeviceState *dev;
327
MemoryRegion *ecam_alias, *ecam_reg;
328
@@ -XXX,XX +XXX,XX @@ static inline DeviceState *gpex_pcie_init(MemoryRegion *sys_mem,
329
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, pio_base);
330
331
for (i = 0; i < GPEX_NUM_IRQS; i++) {
332
- irq = qdev_get_gpio_in(plic, PCIE_IRQ + i);
333
+ irq = qdev_get_gpio_in(irqchip, PCIE_IRQ + i);
334
335
sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, irq);
336
gpex_set_irq_num(GPEX_HOST(dev), i, PCIE_IRQ + i);
337
@@ -XXX,XX +XXX,XX @@ static FWCfgState *create_fw_cfg(const MachineState *mc)
338
return fw_cfg;
339
}
340
341
+static DeviceState *virt_create_plic(const MemMapEntry *memmap, int socket,
342
+ int base_hartid, int hart_count)
343
+{
344
+ DeviceState *ret;
345
+ char *plic_hart_config;
346
+
347
+ /* Per-socket PLIC hart topology configuration string */
348
+ plic_hart_config = riscv_plic_hart_config_string(hart_count);
349
+
350
+ /* Per-socket PLIC */
351
+ ret = sifive_plic_create(
352
+ memmap[VIRT_PLIC].base + socket * memmap[VIRT_PLIC].size,
353
+ plic_hart_config, hart_count, base_hartid,
354
+ VIRT_IRQCHIP_NUM_SOURCES,
355
+ ((1U << VIRT_IRQCHIP_NUM_PRIO_BITS) - 1),
356
+ VIRT_PLIC_PRIORITY_BASE,
357
+ VIRT_PLIC_PENDING_BASE,
358
+ VIRT_PLIC_ENABLE_BASE,
359
+ VIRT_PLIC_ENABLE_STRIDE,
360
+ VIRT_PLIC_CONTEXT_BASE,
361
+ VIRT_PLIC_CONTEXT_STRIDE,
362
+ memmap[VIRT_PLIC].size);
363
+
364
+ g_free(plic_hart_config);
365
+
366
+ return ret;
367
+}
368
+
369
+static DeviceState *virt_create_aia(RISCVVirtAIAType aia_type,
370
+ const MemMapEntry *memmap, int socket,
371
+ int base_hartid, int hart_count)
372
+{
373
+ DeviceState *aplic_m;
374
+
375
+ /* Per-socket M-level APLIC */
376
+ aplic_m = riscv_aplic_create(
377
+ memmap[VIRT_APLIC_M].base + socket * memmap[VIRT_APLIC_M].size,
378
+ memmap[VIRT_APLIC_M].size,
379
+ base_hartid, hart_count,
380
+ VIRT_IRQCHIP_NUM_SOURCES,
381
+ VIRT_IRQCHIP_NUM_PRIO_BITS,
382
+ false, true, NULL);
383
+
384
+ if (aplic_m) {
385
+ /* Per-socket S-level APLIC */
386
+ riscv_aplic_create(
387
+ memmap[VIRT_APLIC_S].base + socket * memmap[VIRT_APLIC_S].size,
388
+ memmap[VIRT_APLIC_S].size,
389
+ base_hartid, hart_count,
390
+ VIRT_IRQCHIP_NUM_SOURCES,
391
+ VIRT_IRQCHIP_NUM_PRIO_BITS,
392
+ false, false, aplic_m);
393
+ }
394
+
395
+ return aplic_m;
396
+}
397
+
398
static void virt_machine_init(MachineState *machine)
399
{
400
const MemMapEntry *memmap = virt_memmap;
401
RISCVVirtState *s = RISCV_VIRT_MACHINE(machine);
402
MemoryRegion *system_memory = get_system_memory();
403
MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
404
- char *plic_hart_config, *soc_name;
405
+ char *soc_name;
406
target_ulong start_addr = memmap[VIRT_DRAM].base;
407
target_ulong firmware_end_addr, kernel_start_addr;
408
uint32_t fdt_load_addr;
409
uint64_t kernel_entry;
410
- DeviceState *mmio_plic, *virtio_plic, *pcie_plic;
411
+ DeviceState *mmio_irqchip, *virtio_irqchip, *pcie_irqchip;
412
int i, base_hartid, hart_count;
413
414
/* Check socket count limit */
415
@@ -XXX,XX +XXX,XX @@ static void virt_machine_init(MachineState *machine)
416
}
417
418
/* Initialize sockets */
419
- mmio_plic = virtio_plic = pcie_plic = NULL;
420
+ mmio_irqchip = virtio_irqchip = pcie_irqchip = NULL;
421
for (i = 0; i < riscv_socket_count(machine); i++) {
422
if (!riscv_socket_check_hartids(machine, i)) {
423
error_report("discontinuous hartids in socket%d", i);
424
@@ -XXX,XX +XXX,XX @@ static void virt_machine_init(MachineState *machine)
425
}
426
}
427
428
- /* Per-socket PLIC hart topology configuration string */
429
- plic_hart_config = riscv_plic_hart_config_string(hart_count);
430
-
431
- /* Per-socket PLIC */
432
- s->plic[i] = sifive_plic_create(
433
- memmap[VIRT_PLIC].base + i * memmap[VIRT_PLIC].size,
434
- plic_hart_config, hart_count, base_hartid,
435
- VIRT_PLIC_NUM_SOURCES,
436
- VIRT_PLIC_NUM_PRIORITIES,
437
- VIRT_PLIC_PRIORITY_BASE,
438
- VIRT_PLIC_PENDING_BASE,
439
- VIRT_PLIC_ENABLE_BASE,
440
- VIRT_PLIC_ENABLE_STRIDE,
441
- VIRT_PLIC_CONTEXT_BASE,
442
- VIRT_PLIC_CONTEXT_STRIDE,
443
- memmap[VIRT_PLIC].size);
444
- g_free(plic_hart_config);
445
+ /* Per-socket interrupt controller */
446
+ if (s->aia_type == VIRT_AIA_TYPE_NONE) {
447
+ s->irqchip[i] = virt_create_plic(memmap, i,
448
+ base_hartid, hart_count);
449
+ } else {
450
+ s->irqchip[i] = virt_create_aia(s->aia_type, memmap, i,
451
+ base_hartid, hart_count);
452
+ }
453
454
- /* Try to use different PLIC instance based device type */
455
+ /* Try to use different IRQCHIP instance based device type */
456
if (i == 0) {
457
- mmio_plic = s->plic[i];
458
- virtio_plic = s->plic[i];
459
- pcie_plic = s->plic[i];
460
+ mmio_irqchip = s->irqchip[i];
461
+ virtio_irqchip = s->irqchip[i];
462
+ pcie_irqchip = s->irqchip[i];
463
}
464
if (i == 1) {
465
- virtio_plic = s->plic[i];
466
- pcie_plic = s->plic[i];
467
+ virtio_irqchip = s->irqchip[i];
468
+ pcie_irqchip = s->irqchip[i];
469
}
470
if (i == 2) {
471
- pcie_plic = s->plic[i];
472
+ pcie_irqchip = s->irqchip[i];
473
}
474
}
475
476
@@ -XXX,XX +XXX,XX @@ static void virt_machine_init(MachineState *machine)
477
for (i = 0; i < VIRTIO_COUNT; i++) {
478
sysbus_create_simple("virtio-mmio",
479
memmap[VIRT_VIRTIO].base + i * memmap[VIRT_VIRTIO].size,
480
- qdev_get_gpio_in(DEVICE(virtio_plic), VIRTIO_IRQ + i));
481
+ qdev_get_gpio_in(DEVICE(virtio_irqchip), VIRTIO_IRQ + i));
482
}
483
484
gpex_pcie_init(system_memory,
485
@@ -XXX,XX +XXX,XX @@ static void virt_machine_init(MachineState *machine)
486
virt_high_pcie_memmap.base,
487
virt_high_pcie_memmap.size,
488
memmap[VIRT_PCIE_PIO].base,
489
- DEVICE(pcie_plic));
490
+ DEVICE(pcie_irqchip));
491
492
serial_mm_init(system_memory, memmap[VIRT_UART0].base,
493
- 0, qdev_get_gpio_in(DEVICE(mmio_plic), UART0_IRQ), 399193,
494
+ 0, qdev_get_gpio_in(DEVICE(mmio_irqchip), UART0_IRQ), 399193,
495
serial_hd(0), DEVICE_LITTLE_ENDIAN);
496
497
sysbus_create_simple("goldfish_rtc", memmap[VIRT_RTC].base,
498
- qdev_get_gpio_in(DEVICE(mmio_plic), RTC_IRQ));
499
+ qdev_get_gpio_in(DEVICE(mmio_irqchip), RTC_IRQ));
500
501
virt_flash_create(s);
502
503
@@ -XXX,XX +XXX,XX @@ static void virt_machine_instance_init(Object *obj)
504
{
505
}
506
507
+static char *virt_get_aia(Object *obj, Error **errp)
508
+{
509
+ RISCVVirtState *s = RISCV_VIRT_MACHINE(obj);
510
+ const char *val;
511
+
512
+ switch (s->aia_type) {
513
+ case VIRT_AIA_TYPE_APLIC:
514
+ val = "aplic";
515
+ break;
516
+ default:
517
+ val = "none";
518
+ break;
519
+ };
520
+
521
+ return g_strdup(val);
522
+}
523
+
524
+static void virt_set_aia(Object *obj, const char *val, Error **errp)
525
+{
526
+ RISCVVirtState *s = RISCV_VIRT_MACHINE(obj);
527
+
528
+ if (!strcmp(val, "none")) {
529
+ s->aia_type = VIRT_AIA_TYPE_NONE;
530
+ } else if (!strcmp(val, "aplic")) {
531
+ s->aia_type = VIRT_AIA_TYPE_APLIC;
532
+ } else {
533
+ error_setg(errp, "Invalid AIA interrupt controller type");
534
+ error_append_hint(errp, "Valid values are none, and aplic.\n");
535
+ }
536
+}
537
+
538
static bool virt_get_aclint(Object *obj, Error **errp)
539
{
540
MachineState *ms = MACHINE(obj);
541
@@ -XXX,XX +XXX,XX @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
542
object_class_property_set_description(oc, "aclint",
543
"Set on/off to enable/disable "
544
"emulating ACLINT devices");
545
+
546
+ object_class_property_add_str(oc, "aia", virt_get_aia,
547
+ virt_set_aia);
548
+ object_class_property_set_description(oc, "aia",
549
+ "Set type of AIA interrupt "
550
+ "conttoller. Valid values are "
551
+ "none, and aplic.");
552
}
553
554
static const TypeInfo virt_machine_typeinfo = {
555
diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
556
index XXXXXXX..XXXXXXX 100644
557
--- a/hw/riscv/Kconfig
558
+++ b/hw/riscv/Kconfig
559
@@ -XXX,XX +XXX,XX @@ config RISCV_VIRT
560
select PFLASH_CFI01
561
select SERIAL
562
select RISCV_ACLINT
563
+ select RISCV_APLIC
564
select SIFIVE_PLIC
565
select SIFIVE_TEST
566
select VIRTIO_MMIO
567
--
568
2.34.1
569
570
diff view generated by jsdifflib
New patch
1
From: Anup Patel <anup.patel@wdc.com>
1
2
3
The RISC-V AIA (Advanced Interrupt Architecture) defines a new
4
interrupt controller for MSIs (message signal interrupts) called
5
IMSIC (Incoming Message Signal Interrupt Controller). The IMSIC
6
is per-HART device and also suppport virtualizaiton of MSIs using
7
dedicated VS-level guest interrupt files.
8
9
This patch adds device emulation for RISC-V AIA IMSIC which
10
supports M-level, S-level, and VS-level MSIs.
11
12
Signed-off-by: Anup Patel <anup.patel@wdc.com>
13
Signed-off-by: Anup Patel <anup@brainfault.org>
14
Reviewed-by: Frank Chang <frank.chang@sifive.com>
15
Message-id: 20220204174700.534953-21-anup@brainfault.org
16
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
17
---
18
include/hw/intc/riscv_imsic.h | 68 ++++++
19
hw/intc/riscv_imsic.c | 448 ++++++++++++++++++++++++++++++++++
20
hw/intc/Kconfig | 3 +
21
hw/intc/meson.build | 1 +
22
4 files changed, 520 insertions(+)
23
create mode 100644 include/hw/intc/riscv_imsic.h
24
create mode 100644 hw/intc/riscv_imsic.c
25
26
diff --git a/include/hw/intc/riscv_imsic.h b/include/hw/intc/riscv_imsic.h
27
new file mode 100644
28
index XXXXXXX..XXXXXXX
29
--- /dev/null
30
+++ b/include/hw/intc/riscv_imsic.h
31
@@ -XXX,XX +XXX,XX @@
32
+/*
33
+ * RISC-V IMSIC (Incoming Message Signal Interrupt Controller) interface
34
+ *
35
+ * Copyright (c) 2021 Western Digital Corporation or its affiliates.
36
+ *
37
+ * This program is free software; you can redistribute it and/or modify it
38
+ * under the terms and conditions of the GNU General Public License,
39
+ * version 2 or later, as published by the Free Software Foundation.
40
+ *
41
+ * This program is distributed in the hope it will be useful, but WITHOUT
42
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
43
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
44
+ * more details.
45
+ *
46
+ * You should have received a copy of the GNU General Public License along with
47
+ * this program. If not, see <http://www.gnu.org/licenses/>.
48
+ */
49
+
50
+#ifndef HW_RISCV_IMSIC_H
51
+#define HW_RISCV_IMSIC_H
52
+
53
+#include "hw/sysbus.h"
54
+#include "qom/object.h"
55
+
56
+#define TYPE_RISCV_IMSIC "riscv.imsic"
57
+
58
+typedef struct RISCVIMSICState RISCVIMSICState;
59
+DECLARE_INSTANCE_CHECKER(RISCVIMSICState, RISCV_IMSIC, TYPE_RISCV_IMSIC)
60
+
61
+#define IMSIC_MMIO_PAGE_SHIFT 12
62
+#define IMSIC_MMIO_PAGE_SZ (1UL << IMSIC_MMIO_PAGE_SHIFT)
63
+#define IMSIC_MMIO_SIZE(__num_pages) ((__num_pages) * IMSIC_MMIO_PAGE_SZ)
64
+
65
+#define IMSIC_MMIO_HART_GUEST_MAX_BTIS 6
66
+#define IMSIC_MMIO_GROUP_MIN_SHIFT 24
67
+
68
+#define IMSIC_HART_NUM_GUESTS(__guest_bits) \
69
+ (1U << (__guest_bits))
70
+#define IMSIC_HART_SIZE(__guest_bits) \
71
+ (IMSIC_HART_NUM_GUESTS(__guest_bits) * IMSIC_MMIO_PAGE_SZ)
72
+#define IMSIC_GROUP_NUM_HARTS(__hart_bits) \
73
+ (1U << (__hart_bits))
74
+#define IMSIC_GROUP_SIZE(__hart_bits, __guest_bits) \
75
+ (IMSIC_GROUP_NUM_HARTS(__hart_bits) * IMSIC_HART_SIZE(__guest_bits))
76
+
77
+struct RISCVIMSICState {
78
+ /*< private >*/
79
+ SysBusDevice parent_obj;
80
+ qemu_irq *external_irqs;
81
+
82
+ /*< public >*/
83
+ MemoryRegion mmio;
84
+ uint32_t num_eistate;
85
+ uint32_t *eidelivery;
86
+ uint32_t *eithreshold;
87
+ uint32_t *eistate;
88
+
89
+ /* config */
90
+ bool mmode;
91
+ uint32_t hartid;
92
+ uint32_t num_pages;
93
+ uint32_t num_irqs;
94
+};
95
+
96
+DeviceState *riscv_imsic_create(hwaddr addr, uint32_t hartid, bool mmode,
97
+ uint32_t num_pages, uint32_t num_ids);
98
+
99
+#endif
100
diff --git a/hw/intc/riscv_imsic.c b/hw/intc/riscv_imsic.c
101
new file mode 100644
102
index XXXXXXX..XXXXXXX
103
--- /dev/null
104
+++ b/hw/intc/riscv_imsic.c
105
@@ -XXX,XX +XXX,XX @@
106
+/*
107
+ * RISC-V IMSIC (Incoming Message Signaled Interrupt Controller)
108
+ *
109
+ * Copyright (c) 2021 Western Digital Corporation or its affiliates.
110
+ *
111
+ * This program is free software; you can redistribute it and/or modify it
112
+ * under the terms and conditions of the GNU General Public License,
113
+ * version 2 or later, as published by the Free Software Foundation.
114
+ *
115
+ * This program is distributed in the hope it will be useful, but WITHOUT
116
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
117
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
118
+ * more details.
119
+ *
120
+ * You should have received a copy of the GNU General Public License along with
121
+ * this program. If not, see <http://www.gnu.org/licenses/>.
122
+ */
123
+
124
+#include "qemu/osdep.h"
125
+#include "qapi/error.h"
126
+#include "qemu/log.h"
127
+#include "qemu/module.h"
128
+#include "qemu/error-report.h"
129
+#include "qemu/bswap.h"
130
+#include "exec/address-spaces.h"
131
+#include "hw/sysbus.h"
132
+#include "hw/pci/msi.h"
133
+#include "hw/boards.h"
134
+#include "hw/qdev-properties.h"
135
+#include "hw/intc/riscv_imsic.h"
136
+#include "hw/irq.h"
137
+#include "target/riscv/cpu.h"
138
+#include "target/riscv/cpu_bits.h"
139
+#include "sysemu/sysemu.h"
140
+#include "migration/vmstate.h"
141
+
142
+#define IMSIC_MMIO_PAGE_LE 0x00
143
+#define IMSIC_MMIO_PAGE_BE 0x04
144
+
145
+#define IMSIC_MIN_ID ((IMSIC_EIPx_BITS * 2) - 1)
146
+#define IMSIC_MAX_ID (IMSIC_TOPEI_IID_MASK)
147
+
148
+#define IMSIC_EISTATE_PENDING (1U << 0)
149
+#define IMSIC_EISTATE_ENABLED (1U << 1)
150
+#define IMSIC_EISTATE_ENPEND (IMSIC_EISTATE_ENABLED | \
151
+ IMSIC_EISTATE_PENDING)
152
+
153
+static uint32_t riscv_imsic_topei(RISCVIMSICState *imsic, uint32_t page)
154
+{
155
+ uint32_t i, max_irq, base;
156
+
157
+ base = page * imsic->num_irqs;
158
+ max_irq = (imsic->eithreshold[page] &&
159
+ (imsic->eithreshold[page] <= imsic->num_irqs)) ?
160
+ imsic->eithreshold[page] : imsic->num_irqs;
161
+ for (i = 1; i < max_irq; i++) {
162
+ if ((imsic->eistate[base + i] & IMSIC_EISTATE_ENPEND) ==
163
+ IMSIC_EISTATE_ENPEND) {
164
+ return (i << IMSIC_TOPEI_IID_SHIFT) | i;
165
+ }
166
+ }
167
+
168
+ return 0;
169
+}
170
+
171
+static void riscv_imsic_update(RISCVIMSICState *imsic, uint32_t page)
172
+{
173
+ if (imsic->eidelivery[page] && riscv_imsic_topei(imsic, page)) {
174
+ qemu_irq_raise(imsic->external_irqs[page]);
175
+ } else {
176
+ qemu_irq_lower(imsic->external_irqs[page]);
177
+ }
178
+}
179
+
180
+static int riscv_imsic_eidelivery_rmw(RISCVIMSICState *imsic, uint32_t page,
181
+ target_ulong *val,
182
+ target_ulong new_val,
183
+ target_ulong wr_mask)
184
+{
185
+ target_ulong old_val = imsic->eidelivery[page];
186
+
187
+ if (val) {
188
+ *val = old_val;
189
+ }
190
+
191
+ wr_mask &= 0x1;
192
+ imsic->eidelivery[page] = (old_val & ~wr_mask) | (new_val & wr_mask);
193
+
194
+ riscv_imsic_update(imsic, page);
195
+ return 0;
196
+}
197
+
198
+static int riscv_imsic_eithreshold_rmw(RISCVIMSICState *imsic, uint32_t page,
199
+ target_ulong *val,
200
+ target_ulong new_val,
201
+ target_ulong wr_mask)
202
+{
203
+ target_ulong old_val = imsic->eithreshold[page];
204
+
205
+ if (val) {
206
+ *val = old_val;
207
+ }
208
+
209
+ wr_mask &= IMSIC_MAX_ID;
210
+ imsic->eithreshold[page] = (old_val & ~wr_mask) | (new_val & wr_mask);
211
+
212
+ riscv_imsic_update(imsic, page);
213
+ return 0;
214
+}
215
+
216
+static int riscv_imsic_topei_rmw(RISCVIMSICState *imsic, uint32_t page,
217
+ target_ulong *val, target_ulong new_val,
218
+ target_ulong wr_mask)
219
+{
220
+ uint32_t base, topei = riscv_imsic_topei(imsic, page);
221
+
222
+ /* Read pending and enabled interrupt with highest priority */
223
+ if (val) {
224
+ *val = topei;
225
+ }
226
+
227
+ /* Writes ignore value and clear top pending interrupt */
228
+ if (topei && wr_mask) {
229
+ topei >>= IMSIC_TOPEI_IID_SHIFT;
230
+ base = page * imsic->num_irqs;
231
+ if (topei) {
232
+ imsic->eistate[base + topei] &= ~IMSIC_EISTATE_PENDING;
233
+ }
234
+
235
+ riscv_imsic_update(imsic, page);
236
+ }
237
+
238
+ return 0;
239
+}
240
+
241
+static int riscv_imsic_eix_rmw(RISCVIMSICState *imsic,
242
+ uint32_t xlen, uint32_t page,
243
+ uint32_t num, bool pend, target_ulong *val,
244
+ target_ulong new_val, target_ulong wr_mask)
245
+{
246
+ uint32_t i, base;
247
+ target_ulong mask;
248
+ uint32_t state = (pend) ? IMSIC_EISTATE_PENDING : IMSIC_EISTATE_ENABLED;
249
+
250
+ if (xlen != 32) {
251
+ if (num & 0x1) {
252
+ return -EINVAL;
253
+ }
254
+ num >>= 1;
255
+ }
256
+ if (num >= (imsic->num_irqs / xlen)) {
257
+ return -EINVAL;
258
+ }
259
+
260
+ base = (page * imsic->num_irqs) + (num * xlen);
261
+
262
+ if (val) {
263
+ *val = 0;
264
+ for (i = 0; i < xlen; i++) {
265
+ mask = (target_ulong)1 << i;
266
+ *val |= (imsic->eistate[base + i] & state) ? mask : 0;
267
+ }
268
+ }
269
+
270
+ for (i = 0; i < xlen; i++) {
271
+ /* Bit0 of eip0 and eie0 are read-only zero */
272
+ if (!num && !i) {
273
+ continue;
274
+ }
275
+
276
+ mask = (target_ulong)1 << i;
277
+ if (wr_mask & mask) {
278
+ if (new_val & mask) {
279
+ imsic->eistate[base + i] |= state;
280
+ } else {
281
+ imsic->eistate[base + i] &= ~state;
282
+ }
283
+ }
284
+ }
285
+
286
+ riscv_imsic_update(imsic, page);
287
+ return 0;
288
+}
289
+
290
+static int riscv_imsic_rmw(void *arg, target_ulong reg, target_ulong *val,
291
+ target_ulong new_val, target_ulong wr_mask)
292
+{
293
+ RISCVIMSICState *imsic = arg;
294
+ uint32_t isel, priv, virt, vgein, xlen, page;
295
+
296
+ priv = AIA_IREG_PRIV(reg);
297
+ virt = AIA_IREG_VIRT(reg);
298
+ isel = AIA_IREG_ISEL(reg);
299
+ vgein = AIA_IREG_VGEIN(reg);
300
+ xlen = AIA_IREG_XLEN(reg);
301
+
302
+ if (imsic->mmode) {
303
+ if (priv == PRV_M && !virt) {
304
+ page = 0;
305
+ } else {
306
+ goto err;
307
+ }
308
+ } else {
309
+ if (priv == PRV_S) {
310
+ if (virt) {
311
+ if (vgein && vgein < imsic->num_pages) {
312
+ page = vgein;
313
+ } else {
314
+ goto err;
315
+ }
316
+ } else {
317
+ page = 0;
318
+ }
319
+ } else {
320
+ goto err;
321
+ }
322
+ }
323
+
324
+ switch (isel) {
325
+ case ISELECT_IMSIC_EIDELIVERY:
326
+ return riscv_imsic_eidelivery_rmw(imsic, page, val,
327
+ new_val, wr_mask);
328
+ case ISELECT_IMSIC_EITHRESHOLD:
329
+ return riscv_imsic_eithreshold_rmw(imsic, page, val,
330
+ new_val, wr_mask);
331
+ case ISELECT_IMSIC_TOPEI:
332
+ return riscv_imsic_topei_rmw(imsic, page, val, new_val, wr_mask);
333
+ case ISELECT_IMSIC_EIP0 ... ISELECT_IMSIC_EIP63:
334
+ return riscv_imsic_eix_rmw(imsic, xlen, page,
335
+ isel - ISELECT_IMSIC_EIP0,
336
+ true, val, new_val, wr_mask);
337
+ case ISELECT_IMSIC_EIE0 ... ISELECT_IMSIC_EIE63:
338
+ return riscv_imsic_eix_rmw(imsic, xlen, page,
339
+ isel - ISELECT_IMSIC_EIE0,
340
+ false, val, new_val, wr_mask);
341
+ default:
342
+ break;
343
+ };
344
+
345
+err:
346
+ qemu_log_mask(LOG_GUEST_ERROR,
347
+ "%s: Invalid register priv=%d virt=%d isel=%d vgein=%d\n",
348
+ __func__, priv, virt, isel, vgein);
349
+ return -EINVAL;
350
+}
351
+
352
+static uint64_t riscv_imsic_read(void *opaque, hwaddr addr, unsigned size)
353
+{
354
+ RISCVIMSICState *imsic = opaque;
355
+
356
+ /* Reads must be 4 byte words */
357
+ if ((addr & 0x3) != 0) {
358
+ goto err;
359
+ }
360
+
361
+ /* Reads cannot be out of range */
362
+ if (addr > IMSIC_MMIO_SIZE(imsic->num_pages)) {
363
+ goto err;
364
+ }
365
+
366
+ return 0;
367
+
368
+err:
369
+ qemu_log_mask(LOG_GUEST_ERROR,
370
+ "%s: Invalid register read 0x%" HWADDR_PRIx "\n",
371
+ __func__, addr);
372
+ return 0;
373
+}
374
+
375
+static void riscv_imsic_write(void *opaque, hwaddr addr, uint64_t value,
376
+ unsigned size)
377
+{
378
+ RISCVIMSICState *imsic = opaque;
379
+ uint32_t page;
380
+
381
+ /* Writes must be 4 byte words */
382
+ if ((addr & 0x3) != 0) {
383
+ goto err;
384
+ }
385
+
386
+ /* Writes cannot be out of range */
387
+ if (addr > IMSIC_MMIO_SIZE(imsic->num_pages)) {
388
+ goto err;
389
+ }
390
+
391
+ /* Writes only supported for MSI little-endian registers */
392
+ page = addr >> IMSIC_MMIO_PAGE_SHIFT;
393
+ if ((addr & (IMSIC_MMIO_PAGE_SZ - 1)) == IMSIC_MMIO_PAGE_LE) {
394
+ if (value && (value < imsic->num_irqs)) {
395
+ imsic->eistate[(page * imsic->num_irqs) + value] |=
396
+ IMSIC_EISTATE_PENDING;
397
+ }
398
+ }
399
+
400
+ /* Update CPU external interrupt status */
401
+ riscv_imsic_update(imsic, page);
402
+
403
+ return;
404
+
405
+err:
406
+ qemu_log_mask(LOG_GUEST_ERROR,
407
+ "%s: Invalid register write 0x%" HWADDR_PRIx "\n",
408
+ __func__, addr);
409
+}
410
+
411
+static const MemoryRegionOps riscv_imsic_ops = {
412
+ .read = riscv_imsic_read,
413
+ .write = riscv_imsic_write,
414
+ .endianness = DEVICE_LITTLE_ENDIAN,
415
+ .valid = {
416
+ .min_access_size = 4,
417
+ .max_access_size = 4
418
+ }
419
+};
420
+
421
+static void riscv_imsic_realize(DeviceState *dev, Error **errp)
422
+{
423
+ RISCVIMSICState *imsic = RISCV_IMSIC(dev);
424
+ RISCVCPU *rcpu = RISCV_CPU(qemu_get_cpu(imsic->hartid));
425
+ CPUState *cpu = qemu_get_cpu(imsic->hartid);
426
+ CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
427
+
428
+ imsic->num_eistate = imsic->num_pages * imsic->num_irqs;
429
+ imsic->eidelivery = g_new0(uint32_t, imsic->num_pages);
430
+ imsic->eithreshold = g_new0(uint32_t, imsic->num_pages);
431
+ imsic->eistate = g_new0(uint32_t, imsic->num_eistate);
432
+
433
+ memory_region_init_io(&imsic->mmio, OBJECT(dev), &riscv_imsic_ops,
434
+ imsic, TYPE_RISCV_IMSIC,
435
+ IMSIC_MMIO_SIZE(imsic->num_pages));
436
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &imsic->mmio);
437
+
438
+ /* Claim the CPU interrupt to be triggered by this IMSIC */
439
+ if (riscv_cpu_claim_interrupts(rcpu,
440
+ (imsic->mmode) ? MIP_MEIP : MIP_SEIP) < 0) {
441
+ error_setg(errp, "%s already claimed",
442
+ (imsic->mmode) ? "MEIP" : "SEIP");
443
+ return;
444
+ }
445
+
446
+ /* Create output IRQ lines */
447
+ imsic->external_irqs = g_malloc(sizeof(qemu_irq) * imsic->num_pages);
448
+ qdev_init_gpio_out(dev, imsic->external_irqs, imsic->num_pages);
449
+
450
+ /* Force select AIA feature and setup CSR read-modify-write callback */
451
+ if (env) {
452
+ riscv_set_feature(env, RISCV_FEATURE_AIA);
453
+ if (!imsic->mmode) {
454
+ riscv_cpu_set_geilen(env, imsic->num_pages - 1);
455
+ }
456
+ riscv_cpu_set_aia_ireg_rmw_fn(env, (imsic->mmode) ? PRV_M : PRV_S,
457
+ riscv_imsic_rmw, imsic);
458
+ }
459
+
460
+ msi_nonbroken = true;
461
+}
462
+
463
+static Property riscv_imsic_properties[] = {
464
+ DEFINE_PROP_BOOL("mmode", RISCVIMSICState, mmode, 0),
465
+ DEFINE_PROP_UINT32("hartid", RISCVIMSICState, hartid, 0),
466
+ DEFINE_PROP_UINT32("num-pages", RISCVIMSICState, num_pages, 0),
467
+ DEFINE_PROP_UINT32("num-irqs", RISCVIMSICState, num_irqs, 0),
468
+ DEFINE_PROP_END_OF_LIST(),
469
+};
470
+
471
+static const VMStateDescription vmstate_riscv_imsic = {
472
+ .name = "riscv_imsic",
473
+ .version_id = 1,
474
+ .minimum_version_id = 1,
475
+ .fields = (VMStateField[]) {
476
+ VMSTATE_VARRAY_UINT32(eidelivery, RISCVIMSICState,
477
+ num_pages, 0,
478
+ vmstate_info_uint32, uint32_t),
479
+ VMSTATE_VARRAY_UINT32(eithreshold, RISCVIMSICState,
480
+ num_pages, 0,
481
+ vmstate_info_uint32, uint32_t),
482
+ VMSTATE_VARRAY_UINT32(eistate, RISCVIMSICState,
483
+ num_eistate, 0,
484
+ vmstate_info_uint32, uint32_t),
485
+ VMSTATE_END_OF_LIST()
486
+ }
487
+};
488
+
489
+static void riscv_imsic_class_init(ObjectClass *klass, void *data)
490
+{
491
+ DeviceClass *dc = DEVICE_CLASS(klass);
492
+
493
+ device_class_set_props(dc, riscv_imsic_properties);
494
+ dc->realize = riscv_imsic_realize;
495
+ dc->vmsd = &vmstate_riscv_imsic;
496
+}
497
+
498
+static const TypeInfo riscv_imsic_info = {
499
+ .name = TYPE_RISCV_IMSIC,
500
+ .parent = TYPE_SYS_BUS_DEVICE,
501
+ .instance_size = sizeof(RISCVIMSICState),
502
+ .class_init = riscv_imsic_class_init,
503
+};
504
+
505
+static void riscv_imsic_register_types(void)
506
+{
507
+ type_register_static(&riscv_imsic_info);
508
+}
509
+
510
+type_init(riscv_imsic_register_types)
511
+
512
+/*
513
+ * Create IMSIC device.
514
+ */
515
+DeviceState *riscv_imsic_create(hwaddr addr, uint32_t hartid, bool mmode,
516
+ uint32_t num_pages, uint32_t num_ids)
517
+{
518
+ DeviceState *dev = qdev_new(TYPE_RISCV_IMSIC);
519
+ CPUState *cpu = qemu_get_cpu(hartid);
520
+ uint32_t i;
521
+
522
+ assert(!(addr & (IMSIC_MMIO_PAGE_SZ - 1)));
523
+ if (mmode) {
524
+ assert(num_pages == 1);
525
+ } else {
526
+ assert(num_pages >= 1 && num_pages <= (IRQ_LOCAL_GUEST_MAX + 1));
527
+ }
528
+ assert(IMSIC_MIN_ID <= num_ids);
529
+ assert(num_ids <= IMSIC_MAX_ID);
530
+ assert((num_ids & IMSIC_MIN_ID) == IMSIC_MIN_ID);
531
+
532
+ qdev_prop_set_bit(dev, "mmode", mmode);
533
+ qdev_prop_set_uint32(dev, "hartid", hartid);
534
+ qdev_prop_set_uint32(dev, "num-pages", num_pages);
535
+ qdev_prop_set_uint32(dev, "num-irqs", num_ids + 1);
536
+
537
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
538
+ sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
539
+
540
+ for (i = 0; i < num_pages; i++) {
541
+ if (!i) {
542
+ qdev_connect_gpio_out_named(dev, NULL, i,
543
+ qdev_get_gpio_in(DEVICE(cpu),
544
+ (mmode) ? IRQ_M_EXT : IRQ_S_EXT));
545
+ } else {
546
+ qdev_connect_gpio_out_named(dev, NULL, i,
547
+ qdev_get_gpio_in(DEVICE(cpu),
548
+ IRQ_LOCAL_MAX + i - 1));
549
+ }
550
+ }
551
+
552
+ return dev;
553
+}
554
diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
555
index XXXXXXX..XXXXXXX 100644
556
--- a/hw/intc/Kconfig
557
+++ b/hw/intc/Kconfig
558
@@ -XXX,XX +XXX,XX @@ config RISCV_ACLINT
559
config RISCV_APLIC
560
bool
561
562
+config RISCV_IMSIC
563
+ bool
564
+
565
config SIFIVE_PLIC
566
bool
567
568
diff --git a/hw/intc/meson.build b/hw/intc/meson.build
569
index XXXXXXX..XXXXXXX 100644
570
--- a/hw/intc/meson.build
571
+++ b/hw/intc/meson.build
572
@@ -XXX,XX +XXX,XX @@ specific_ss.add(when: 'CONFIG_S390_FLIC_KVM', if_true: files('s390_flic_kvm.c'))
573
specific_ss.add(when: 'CONFIG_SH_INTC', if_true: files('sh_intc.c'))
574
specific_ss.add(when: 'CONFIG_RISCV_ACLINT', if_true: files('riscv_aclint.c'))
575
specific_ss.add(when: 'CONFIG_RISCV_APLIC', if_true: files('riscv_aplic.c'))
576
+specific_ss.add(when: 'CONFIG_RISCV_IMSIC', if_true: files('riscv_imsic.c'))
577
specific_ss.add(when: 'CONFIG_SIFIVE_PLIC', if_true: files('sifive_plic.c'))
578
specific_ss.add(when: 'CONFIG_XICS', if_true: files('xics.c'))
579
specific_ss.add(when: ['CONFIG_KVM', 'CONFIG_XICS'],
580
--
581
2.34.1
582
583
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
From: Anup Patel <anup.patel@wdc.com>
2
2
3
Configuring a drive with "if=none" is meant for creation of a backend
3
We extend virt machine to emulate both AIA IMSIC and AIA APLIC
4
only, it should not get automatically assigned to a device frontend.
4
devices only when "aia=aplic-imsic" parameter is passed along
5
Use "if=pflash" for the One-Time-Programmable device instead (like
5
with machine name in the QEMU command-line. The AIA IMSIC is
6
it is e.g. also done for the efuse device in hw/arm/xlnx-zcu102.c).
6
only a per-HART MSI controller so we use AIA APLIC in MSI-mode
7
to forward all wired interrupts as MSIs to the AIA IMSIC.
7
8
8
Since the old way of configuring the device has already been published
9
We also provide "aia-guests=<xyz>" parameter which can be used
9
with the previous QEMU versions, we cannot remove this immediately, but
10
to specify number of VS-level AIA IMSIC Guests MMIO pages for
10
have to deprecate it and support it for at least two more releases.
11
each HART.
11
12
12
Signed-off-by: Thomas Huth <thuth@redhat.com>
13
Signed-off-by: Anup Patel <anup.patel@wdc.com>
13
Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com>
14
Signed-off-by: Anup Patel <anup@brainfault.org>
14
Reviewed-by: Markus Armbruster <armbru@redhat.com>
15
Acked-by: Alistair Francis <alistair.francis@wdc.com>
15
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
16
Message-id: 20220204174700.534953-22-anup@brainfault.org
16
Message-id: 20211119102549.217755-1-thuth@redhat.com
17
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
17
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
18
---
18
---
19
docs/about/deprecated.rst | 6 ++++++
19
include/hw/riscv/virt.h | 17 +-
20
hw/misc/sifive_u_otp.c | 9 ++++++++-
20
hw/riscv/virt.c | 440 ++++++++++++++++++++++++++++++++--------
21
2 files changed, 14 insertions(+), 1 deletion(-)
21
hw/riscv/Kconfig | 1 +
22
3 files changed, 374 insertions(+), 84 deletions(-)
22
23
23
diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
24
diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
24
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
25
--- a/docs/about/deprecated.rst
26
--- a/include/hw/riscv/virt.h
26
+++ b/docs/about/deprecated.rst
27
+++ b/include/hw/riscv/virt.h
27
@@ -XXX,XX +XXX,XX @@ as short-form boolean values, and passed to plugins as ``arg_name=on``.
28
@@ -XXX,XX +XXX,XX @@
28
However, short-form booleans are deprecated and full explicit ``arg_name=on``
29
#include "hw/block/flash.h"
29
form is preferred.
30
#include "qom/object.h"
30
31
31
+``-drive if=none`` for the sifive_u OTP device (since 6.2)
32
-#define VIRT_CPUS_MAX 32
32
+''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
33
-#define VIRT_SOCKETS_MAX 8
33
+
34
+#define VIRT_CPUS_MAX_BITS 3
34
+Using ``-drive if=none`` to configure the OTP device of the sifive_u
35
+#define VIRT_CPUS_MAX (1 << VIRT_CPUS_MAX_BITS)
35
+RISC-V machine is deprecated. Use ``-drive if=pflash`` instead.
36
+#define VIRT_SOCKETS_MAX_BITS 2
36
+
37
+#define VIRT_SOCKETS_MAX (1 << VIRT_SOCKETS_MAX_BITS)
37
38
38
QEMU Machine Protocol (QMP) commands
39
#define TYPE_RISCV_VIRT_MACHINE MACHINE_TYPE_NAME("virt")
39
------------------------------------
40
typedef struct RISCVVirtState RISCVVirtState;
40
diff --git a/hw/misc/sifive_u_otp.c b/hw/misc/sifive_u_otp.c
41
@@ -XXX,XX +XXX,XX @@ DECLARE_INSTANCE_CHECKER(RISCVVirtState, RISCV_VIRT_MACHINE,
42
typedef enum RISCVVirtAIAType {
43
VIRT_AIA_TYPE_NONE = 0,
44
VIRT_AIA_TYPE_APLIC,
45
+ VIRT_AIA_TYPE_APLIC_IMSIC,
46
} RISCVVirtAIAType;
47
48
struct RISCVVirtState {
49
@@ -XXX,XX +XXX,XX @@ struct RISCVVirtState {
50
int fdt_size;
51
bool have_aclint;
52
RISCVVirtAIAType aia_type;
53
+ int aia_guests;
54
};
55
56
enum {
57
@@ -XXX,XX +XXX,XX @@ enum {
58
VIRT_UART0,
59
VIRT_VIRTIO,
60
VIRT_FW_CFG,
61
+ VIRT_IMSIC_M,
62
+ VIRT_IMSIC_S,
63
VIRT_FLASH,
64
VIRT_DRAM,
65
VIRT_PCIE_MMIO,
66
@@ -XXX,XX +XXX,XX @@ enum {
67
VIRTIO_NDEV = 0x35 /* Arbitrary maximum number of interrupts */
68
};
69
70
-#define VIRT_IRQCHIP_NUM_SOURCES 127
71
+#define VIRT_IRQCHIP_IPI_MSI 1
72
+#define VIRT_IRQCHIP_NUM_MSIS 255
73
+#define VIRT_IRQCHIP_NUM_SOURCES VIRTIO_NDEV
74
#define VIRT_IRQCHIP_NUM_PRIO_BITS 3
75
+#define VIRT_IRQCHIP_MAX_GUESTS_BITS 3
76
+#define VIRT_IRQCHIP_MAX_GUESTS ((1U << VIRT_IRQCHIP_MAX_GUESTS_BITS) - 1U)
77
78
#define VIRT_PLIC_PRIORITY_BASE 0x04
79
#define VIRT_PLIC_PENDING_BASE 0x1000
80
@@ -XXX,XX +XXX,XX @@ enum {
81
#define FDT_PCI_INT_CELLS 1
82
#define FDT_PLIC_INT_CELLS 1
83
#define FDT_APLIC_INT_CELLS 2
84
+#define FDT_IMSIC_INT_CELLS 0
85
#define FDT_MAX_INT_CELLS 2
86
#define FDT_MAX_INT_MAP_WIDTH (FDT_PCI_ADDR_CELLS + FDT_PCI_INT_CELLS + \
87
1 + FDT_MAX_INT_CELLS)
88
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
41
index XXXXXXX..XXXXXXX 100644
89
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/misc/sifive_u_otp.c
90
--- a/hw/riscv/virt.c
43
+++ b/hw/misc/sifive_u_otp.c
91
+++ b/hw/riscv/virt.c
44
@@ -XXX,XX +XXX,XX @@ static void sifive_u_otp_realize(DeviceState *dev, Error **errp)
92
@@ -XXX,XX +XXX,XX @@
45
TYPE_SIFIVE_U_OTP, SIFIVE_U_OTP_REG_SIZE);
93
#include "hw/riscv/numa.h"
46
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
94
#include "hw/intc/riscv_aclint.h"
47
95
#include "hw/intc/riscv_aplic.h"
48
- dinfo = drive_get_next(IF_NONE);
96
+#include "hw/intc/riscv_imsic.h"
49
+ dinfo = drive_get_next(IF_PFLASH);
97
#include "hw/intc/sifive_plic.h"
50
+ if (!dinfo) {
98
#include "hw/misc/sifive_test.h"
51
+ dinfo = drive_get_next(IF_NONE);
99
#include "chardev/char.h"
52
+ if (dinfo) {
100
@@ -XXX,XX +XXX,XX @@
53
+ warn_report("using \"-drive if=none\" for the OTP is deprecated, "
101
#include "hw/pci-host/gpex.h"
54
+ "use \"-drive if=pflash\" instead.");
102
#include "hw/display/ramfb.h"
103
104
+#define VIRT_IMSIC_GROUP_MAX_SIZE (1U << IMSIC_MMIO_GROUP_MIN_SHIFT)
105
+#if VIRT_IMSIC_GROUP_MAX_SIZE < \
106
+ IMSIC_GROUP_SIZE(VIRT_CPUS_MAX_BITS, VIRT_IRQCHIP_MAX_GUESTS_BITS)
107
+#error "Can't accomodate single IMSIC group in address space"
108
+#endif
109
+
110
+#define VIRT_IMSIC_MAX_SIZE (VIRT_SOCKETS_MAX * \
111
+ VIRT_IMSIC_GROUP_MAX_SIZE)
112
+#if 0x4000000 < VIRT_IMSIC_MAX_SIZE
113
+#error "Can't accomodate all IMSIC groups in address space"
114
+#endif
115
+
116
static const MemMapEntry virt_memmap[] = {
117
[VIRT_DEBUG] = { 0x0, 0x100 },
118
[VIRT_MROM] = { 0x1000, 0xf000 },
119
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry virt_memmap[] = {
120
[VIRT_VIRTIO] = { 0x10001000, 0x1000 },
121
[VIRT_FW_CFG] = { 0x10100000, 0x18 },
122
[VIRT_FLASH] = { 0x20000000, 0x4000000 },
123
+ [VIRT_IMSIC_M] = { 0x24000000, VIRT_IMSIC_MAX_SIZE },
124
+ [VIRT_IMSIC_S] = { 0x28000000, VIRT_IMSIC_MAX_SIZE },
125
[VIRT_PCIE_ECAM] = { 0x30000000, 0x10000000 },
126
[VIRT_PCIE_MMIO] = { 0x40000000, 0x40000000 },
127
[VIRT_DRAM] = { 0x80000000, 0x0 },
128
@@ -XXX,XX +XXX,XX @@ static void create_fdt_socket_aclint(RISCVVirtState *s,
129
{
130
int cpu;
131
char *name;
132
- unsigned long addr;
133
+ unsigned long addr, size;
134
uint32_t aclint_cells_size;
135
uint32_t *aclint_mswi_cells;
136
uint32_t *aclint_sswi_cells;
137
@@ -XXX,XX +XXX,XX @@ static void create_fdt_socket_aclint(RISCVVirtState *s,
138
}
139
aclint_cells_size = s->soc[socket].num_harts * sizeof(uint32_t) * 2;
140
141
- addr = memmap[VIRT_CLINT].base + (memmap[VIRT_CLINT].size * socket);
142
- name = g_strdup_printf("/soc/mswi@%lx", addr);
143
- qemu_fdt_add_subnode(mc->fdt, name);
144
- qemu_fdt_setprop_string(mc->fdt, name, "compatible", "riscv,aclint-mswi");
145
- qemu_fdt_setprop_cells(mc->fdt, name, "reg",
146
- 0x0, addr, 0x0, RISCV_ACLINT_SWI_SIZE);
147
- qemu_fdt_setprop(mc->fdt, name, "interrupts-extended",
148
- aclint_mswi_cells, aclint_cells_size);
149
- qemu_fdt_setprop(mc->fdt, name, "interrupt-controller", NULL, 0);
150
- qemu_fdt_setprop_cell(mc->fdt, name, "#interrupt-cells", 0);
151
- riscv_socket_fdt_write_id(mc, mc->fdt, name, socket);
152
- g_free(name);
153
+ if (s->aia_type != VIRT_AIA_TYPE_APLIC_IMSIC) {
154
+ addr = memmap[VIRT_CLINT].base + (memmap[VIRT_CLINT].size * socket);
155
+ name = g_strdup_printf("/soc/mswi@%lx", addr);
156
+ qemu_fdt_add_subnode(mc->fdt, name);
157
+ qemu_fdt_setprop_string(mc->fdt, name, "compatible",
158
+ "riscv,aclint-mswi");
159
+ qemu_fdt_setprop_cells(mc->fdt, name, "reg",
160
+ 0x0, addr, 0x0, RISCV_ACLINT_SWI_SIZE);
161
+ qemu_fdt_setprop(mc->fdt, name, "interrupts-extended",
162
+ aclint_mswi_cells, aclint_cells_size);
163
+ qemu_fdt_setprop(mc->fdt, name, "interrupt-controller", NULL, 0);
164
+ qemu_fdt_setprop_cell(mc->fdt, name, "#interrupt-cells", 0);
165
+ riscv_socket_fdt_write_id(mc, mc->fdt, name, socket);
166
+ g_free(name);
167
+ }
168
169
- addr = memmap[VIRT_CLINT].base + RISCV_ACLINT_SWI_SIZE +
170
- (memmap[VIRT_CLINT].size * socket);
171
+ if (s->aia_type == VIRT_AIA_TYPE_APLIC_IMSIC) {
172
+ addr = memmap[VIRT_CLINT].base +
173
+ (RISCV_ACLINT_DEFAULT_MTIMER_SIZE * socket);
174
+ size = RISCV_ACLINT_DEFAULT_MTIMER_SIZE;
175
+ } else {
176
+ addr = memmap[VIRT_CLINT].base + RISCV_ACLINT_SWI_SIZE +
177
+ (memmap[VIRT_CLINT].size * socket);
178
+ size = memmap[VIRT_CLINT].size - RISCV_ACLINT_SWI_SIZE;
179
+ }
180
name = g_strdup_printf("/soc/mtimer@%lx", addr);
181
qemu_fdt_add_subnode(mc->fdt, name);
182
qemu_fdt_setprop_string(mc->fdt, name, "compatible",
183
"riscv,aclint-mtimer");
184
qemu_fdt_setprop_cells(mc->fdt, name, "reg",
185
0x0, addr + RISCV_ACLINT_DEFAULT_MTIME,
186
- 0x0, memmap[VIRT_CLINT].size - RISCV_ACLINT_SWI_SIZE -
187
- RISCV_ACLINT_DEFAULT_MTIME,
188
+ 0x0, size - RISCV_ACLINT_DEFAULT_MTIME,
189
0x0, addr + RISCV_ACLINT_DEFAULT_MTIMECMP,
190
0x0, RISCV_ACLINT_DEFAULT_MTIME);
191
qemu_fdt_setprop(mc->fdt, name, "interrupts-extended",
192
@@ -XXX,XX +XXX,XX @@ static void create_fdt_socket_aclint(RISCVVirtState *s,
193
riscv_socket_fdt_write_id(mc, mc->fdt, name, socket);
194
g_free(name);
195
196
- addr = memmap[VIRT_ACLINT_SSWI].base +
197
- (memmap[VIRT_ACLINT_SSWI].size * socket);
198
- name = g_strdup_printf("/soc/sswi@%lx", addr);
199
- qemu_fdt_add_subnode(mc->fdt, name);
200
- qemu_fdt_setprop_string(mc->fdt, name, "compatible", "riscv,aclint-sswi");
201
- qemu_fdt_setprop_cells(mc->fdt, name, "reg",
202
- 0x0, addr, 0x0, memmap[VIRT_ACLINT_SSWI].size);
203
- qemu_fdt_setprop(mc->fdt, name, "interrupts-extended",
204
- aclint_sswi_cells, aclint_cells_size);
205
- qemu_fdt_setprop(mc->fdt, name, "interrupt-controller", NULL, 0);
206
- qemu_fdt_setprop_cell(mc->fdt, name, "#interrupt-cells", 0);
207
- riscv_socket_fdt_write_id(mc, mc->fdt, name, socket);
208
- g_free(name);
209
+ if (s->aia_type != VIRT_AIA_TYPE_APLIC_IMSIC) {
210
+ addr = memmap[VIRT_ACLINT_SSWI].base +
211
+ (memmap[VIRT_ACLINT_SSWI].size * socket);
212
+ name = g_strdup_printf("/soc/sswi@%lx", addr);
213
+ qemu_fdt_add_subnode(mc->fdt, name);
214
+ qemu_fdt_setprop_string(mc->fdt, name, "compatible",
215
+ "riscv,aclint-sswi");
216
+ qemu_fdt_setprop_cells(mc->fdt, name, "reg",
217
+ 0x0, addr, 0x0, memmap[VIRT_ACLINT_SSWI].size);
218
+ qemu_fdt_setprop(mc->fdt, name, "interrupts-extended",
219
+ aclint_sswi_cells, aclint_cells_size);
220
+ qemu_fdt_setprop(mc->fdt, name, "interrupt-controller", NULL, 0);
221
+ qemu_fdt_setprop_cell(mc->fdt, name, "#interrupt-cells", 0);
222
+ riscv_socket_fdt_write_id(mc, mc->fdt, name, socket);
223
+ g_free(name);
224
+ }
225
226
g_free(aclint_mswi_cells);
227
g_free(aclint_mtimer_cells);
228
@@ -XXX,XX +XXX,XX @@ static void create_fdt_socket_plic(RISCVVirtState *s,
229
g_free(plic_cells);
230
}
231
232
-static void create_fdt_socket_aia(RISCVVirtState *s,
233
- const MemMapEntry *memmap, int socket,
234
- uint32_t *phandle, uint32_t *intc_phandles,
235
- uint32_t *aplic_phandles)
236
+static uint32_t imsic_num_bits(uint32_t count)
237
+{
238
+ uint32_t ret = 0;
239
+
240
+ while (BIT(ret) < count) {
241
+ ret++;
242
+ }
243
+
244
+ return ret;
245
+}
246
+
247
+static void create_fdt_imsic(RISCVVirtState *s, const MemMapEntry *memmap,
248
+ uint32_t *phandle, uint32_t *intc_phandles,
249
+ uint32_t *msi_m_phandle, uint32_t *msi_s_phandle)
250
+{
251
+ int cpu, socket;
252
+ char *imsic_name;
253
+ MachineState *mc = MACHINE(s);
254
+ uint32_t imsic_max_hart_per_socket, imsic_guest_bits;
255
+ uint32_t *imsic_cells, *imsic_regs, imsic_addr, imsic_size;
256
+
257
+ *msi_m_phandle = (*phandle)++;
258
+ *msi_s_phandle = (*phandle)++;
259
+ imsic_cells = g_new0(uint32_t, mc->smp.cpus * 2);
260
+ imsic_regs = g_new0(uint32_t, riscv_socket_count(mc) * 4);
261
+
262
+ /* M-level IMSIC node */
263
+ for (cpu = 0; cpu < mc->smp.cpus; cpu++) {
264
+ imsic_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
265
+ imsic_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_M_EXT);
266
+ }
267
+ imsic_max_hart_per_socket = 0;
268
+ for (socket = 0; socket < riscv_socket_count(mc); socket++) {
269
+ imsic_addr = memmap[VIRT_IMSIC_M].base +
270
+ socket * VIRT_IMSIC_GROUP_MAX_SIZE;
271
+ imsic_size = IMSIC_HART_SIZE(0) * s->soc[socket].num_harts;
272
+ imsic_regs[socket * 4 + 0] = 0;
273
+ imsic_regs[socket * 4 + 1] = cpu_to_be32(imsic_addr);
274
+ imsic_regs[socket * 4 + 2] = 0;
275
+ imsic_regs[socket * 4 + 3] = cpu_to_be32(imsic_size);
276
+ if (imsic_max_hart_per_socket < s->soc[socket].num_harts) {
277
+ imsic_max_hart_per_socket = s->soc[socket].num_harts;
55
+ }
278
+ }
56
+ }
279
+ }
57
if (dinfo) {
280
+ imsic_name = g_strdup_printf("/soc/imsics@%lx",
58
int ret;
281
+ memmap[VIRT_IMSIC_M].base);
59
uint64_t perm;
282
+ qemu_fdt_add_subnode(mc->fdt, imsic_name);
283
+ qemu_fdt_setprop_string(mc->fdt, imsic_name, "compatible",
284
+ "riscv,imsics");
285
+ qemu_fdt_setprop_cell(mc->fdt, imsic_name, "#interrupt-cells",
286
+ FDT_IMSIC_INT_CELLS);
287
+ qemu_fdt_setprop(mc->fdt, imsic_name, "interrupt-controller",
288
+ NULL, 0);
289
+ qemu_fdt_setprop(mc->fdt, imsic_name, "msi-controller",
290
+ NULL, 0);
291
+ qemu_fdt_setprop(mc->fdt, imsic_name, "interrupts-extended",
292
+ imsic_cells, mc->smp.cpus * sizeof(uint32_t) * 2);
293
+ qemu_fdt_setprop(mc->fdt, imsic_name, "reg", imsic_regs,
294
+ riscv_socket_count(mc) * sizeof(uint32_t) * 4);
295
+ qemu_fdt_setprop_cell(mc->fdt, imsic_name, "riscv,num-ids",
296
+ VIRT_IRQCHIP_NUM_MSIS);
297
+ qemu_fdt_setprop_cells(mc->fdt, imsic_name, "riscv,ipi-id",
298
+ VIRT_IRQCHIP_IPI_MSI);
299
+ if (riscv_socket_count(mc) > 1) {
300
+ qemu_fdt_setprop_cell(mc->fdt, imsic_name, "riscv,hart-index-bits",
301
+ imsic_num_bits(imsic_max_hart_per_socket));
302
+ qemu_fdt_setprop_cell(mc->fdt, imsic_name, "riscv,group-index-bits",
303
+ imsic_num_bits(riscv_socket_count(mc)));
304
+ qemu_fdt_setprop_cell(mc->fdt, imsic_name, "riscv,group-index-shift",
305
+ IMSIC_MMIO_GROUP_MIN_SHIFT);
306
+ }
307
+ qemu_fdt_setprop_cell(mc->fdt, imsic_name, "phandle", *msi_m_phandle);
308
+ g_free(imsic_name);
309
+
310
+ /* S-level IMSIC node */
311
+ for (cpu = 0; cpu < mc->smp.cpus; cpu++) {
312
+ imsic_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
313
+ imsic_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_S_EXT);
314
+ }
315
+ imsic_guest_bits = imsic_num_bits(s->aia_guests + 1);
316
+ imsic_max_hart_per_socket = 0;
317
+ for (socket = 0; socket < riscv_socket_count(mc); socket++) {
318
+ imsic_addr = memmap[VIRT_IMSIC_S].base +
319
+ socket * VIRT_IMSIC_GROUP_MAX_SIZE;
320
+ imsic_size = IMSIC_HART_SIZE(imsic_guest_bits) *
321
+ s->soc[socket].num_harts;
322
+ imsic_regs[socket * 4 + 0] = 0;
323
+ imsic_regs[socket * 4 + 1] = cpu_to_be32(imsic_addr);
324
+ imsic_regs[socket * 4 + 2] = 0;
325
+ imsic_regs[socket * 4 + 3] = cpu_to_be32(imsic_size);
326
+ if (imsic_max_hart_per_socket < s->soc[socket].num_harts) {
327
+ imsic_max_hart_per_socket = s->soc[socket].num_harts;
328
+ }
329
+ }
330
+ imsic_name = g_strdup_printf("/soc/imsics@%lx",
331
+ memmap[VIRT_IMSIC_S].base);
332
+ qemu_fdt_add_subnode(mc->fdt, imsic_name);
333
+ qemu_fdt_setprop_string(mc->fdt, imsic_name, "compatible",
334
+ "riscv,imsics");
335
+ qemu_fdt_setprop_cell(mc->fdt, imsic_name, "#interrupt-cells",
336
+ FDT_IMSIC_INT_CELLS);
337
+ qemu_fdt_setprop(mc->fdt, imsic_name, "interrupt-controller",
338
+ NULL, 0);
339
+ qemu_fdt_setprop(mc->fdt, imsic_name, "msi-controller",
340
+ NULL, 0);
341
+ qemu_fdt_setprop(mc->fdt, imsic_name, "interrupts-extended",
342
+ imsic_cells, mc->smp.cpus * sizeof(uint32_t) * 2);
343
+ qemu_fdt_setprop(mc->fdt, imsic_name, "reg", imsic_regs,
344
+ riscv_socket_count(mc) * sizeof(uint32_t) * 4);
345
+ qemu_fdt_setprop_cell(mc->fdt, imsic_name, "riscv,num-ids",
346
+ VIRT_IRQCHIP_NUM_MSIS);
347
+ qemu_fdt_setprop_cells(mc->fdt, imsic_name, "riscv,ipi-id",
348
+ VIRT_IRQCHIP_IPI_MSI);
349
+ if (imsic_guest_bits) {
350
+ qemu_fdt_setprop_cell(mc->fdt, imsic_name, "riscv,guest-index-bits",
351
+ imsic_guest_bits);
352
+ }
353
+ if (riscv_socket_count(mc) > 1) {
354
+ qemu_fdt_setprop_cell(mc->fdt, imsic_name, "riscv,hart-index-bits",
355
+ imsic_num_bits(imsic_max_hart_per_socket));
356
+ qemu_fdt_setprop_cell(mc->fdt, imsic_name, "riscv,group-index-bits",
357
+ imsic_num_bits(riscv_socket_count(mc)));
358
+ qemu_fdt_setprop_cell(mc->fdt, imsic_name, "riscv,group-index-shift",
359
+ IMSIC_MMIO_GROUP_MIN_SHIFT);
360
+ }
361
+ qemu_fdt_setprop_cell(mc->fdt, imsic_name, "phandle", *msi_s_phandle);
362
+ g_free(imsic_name);
363
+
364
+ g_free(imsic_regs);
365
+ g_free(imsic_cells);
366
+}
367
+
368
+static void create_fdt_socket_aplic(RISCVVirtState *s,
369
+ const MemMapEntry *memmap, int socket,
370
+ uint32_t msi_m_phandle,
371
+ uint32_t msi_s_phandle,
372
+ uint32_t *phandle,
373
+ uint32_t *intc_phandles,
374
+ uint32_t *aplic_phandles)
375
{
376
int cpu;
377
char *aplic_name;
378
@@ -XXX,XX +XXX,XX @@ static void create_fdt_socket_aia(RISCVVirtState *s,
379
qemu_fdt_setprop_cell(mc->fdt, aplic_name,
380
"#interrupt-cells", FDT_APLIC_INT_CELLS);
381
qemu_fdt_setprop(mc->fdt, aplic_name, "interrupt-controller", NULL, 0);
382
- qemu_fdt_setprop(mc->fdt, aplic_name, "interrupts-extended",
383
- aplic_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 2);
384
+ if (s->aia_type == VIRT_AIA_TYPE_APLIC) {
385
+ qemu_fdt_setprop(mc->fdt, aplic_name, "interrupts-extended",
386
+ aplic_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 2);
387
+ } else {
388
+ qemu_fdt_setprop_cell(mc->fdt, aplic_name, "msi-parent",
389
+ msi_m_phandle);
390
+ }
391
qemu_fdt_setprop_cells(mc->fdt, aplic_name, "reg",
392
0x0, aplic_addr, 0x0, memmap[VIRT_APLIC_M].size);
393
qemu_fdt_setprop_cell(mc->fdt, aplic_name, "riscv,num-sources",
394
@@ -XXX,XX +XXX,XX @@ static void create_fdt_socket_aia(RISCVVirtState *s,
395
qemu_fdt_setprop_cell(mc->fdt, aplic_name,
396
"#interrupt-cells", FDT_APLIC_INT_CELLS);
397
qemu_fdt_setprop(mc->fdt, aplic_name, "interrupt-controller", NULL, 0);
398
- qemu_fdt_setprop(mc->fdt, aplic_name, "interrupts-extended",
399
- aplic_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 2);
400
+ if (s->aia_type == VIRT_AIA_TYPE_APLIC) {
401
+ qemu_fdt_setprop(mc->fdt, aplic_name, "interrupts-extended",
402
+ aplic_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 2);
403
+ } else {
404
+ qemu_fdt_setprop_cell(mc->fdt, aplic_name, "msi-parent",
405
+ msi_s_phandle);
406
+ }
407
qemu_fdt_setprop_cells(mc->fdt, aplic_name, "reg",
408
0x0, aplic_addr, 0x0, memmap[VIRT_APLIC_S].size);
409
qemu_fdt_setprop_cell(mc->fdt, aplic_name, "riscv,num-sources",
410
@@ -XXX,XX +XXX,XX @@ static void create_fdt_sockets(RISCVVirtState *s, const MemMapEntry *memmap,
411
bool is_32_bit, uint32_t *phandle,
412
uint32_t *irq_mmio_phandle,
413
uint32_t *irq_pcie_phandle,
414
- uint32_t *irq_virtio_phandle)
415
+ uint32_t *irq_virtio_phandle,
416
+ uint32_t *msi_pcie_phandle)
417
{
418
- int socket;
419
char *clust_name;
420
- uint32_t *intc_phandles;
421
+ int socket, phandle_pos;
422
MachineState *mc = MACHINE(s);
423
- uint32_t xplic_phandles[MAX_NODES];
424
+ uint32_t msi_m_phandle = 0, msi_s_phandle = 0;
425
+ uint32_t *intc_phandles, xplic_phandles[MAX_NODES];
426
427
qemu_fdt_add_subnode(mc->fdt, "/cpus");
428
qemu_fdt_setprop_cell(mc->fdt, "/cpus", "timebase-frequency",
429
@@ -XXX,XX +XXX,XX @@ static void create_fdt_sockets(RISCVVirtState *s, const MemMapEntry *memmap,
430
qemu_fdt_setprop_cell(mc->fdt, "/cpus", "#address-cells", 0x1);
431
qemu_fdt_add_subnode(mc->fdt, "/cpus/cpu-map");
432
433
+ intc_phandles = g_new0(uint32_t, mc->smp.cpus);
434
+
435
+ phandle_pos = mc->smp.cpus;
436
for (socket = (riscv_socket_count(mc) - 1); socket >= 0; socket--) {
437
+ phandle_pos -= s->soc[socket].num_harts;
438
+
439
clust_name = g_strdup_printf("/cpus/cpu-map/cluster%d", socket);
440
qemu_fdt_add_subnode(mc->fdt, clust_name);
441
442
- intc_phandles = g_new0(uint32_t, s->soc[socket].num_harts);
443
-
444
create_fdt_socket_cpus(s, socket, clust_name, phandle,
445
- is_32_bit, intc_phandles);
446
+ is_32_bit, &intc_phandles[phandle_pos]);
447
448
create_fdt_socket_memory(s, memmap, socket);
449
450
+ g_free(clust_name);
451
+
452
if (!kvm_enabled()) {
453
if (s->have_aclint) {
454
- create_fdt_socket_aclint(s, memmap, socket, intc_phandles);
455
+ create_fdt_socket_aclint(s, memmap, socket,
456
+ &intc_phandles[phandle_pos]);
457
} else {
458
- create_fdt_socket_clint(s, memmap, socket, intc_phandles);
459
+ create_fdt_socket_clint(s, memmap, socket,
460
+ &intc_phandles[phandle_pos]);
461
}
462
}
463
+ }
464
+
465
+ if (s->aia_type == VIRT_AIA_TYPE_APLIC_IMSIC) {
466
+ create_fdt_imsic(s, memmap, phandle, intc_phandles,
467
+ &msi_m_phandle, &msi_s_phandle);
468
+ *msi_pcie_phandle = msi_s_phandle;
469
+ }
470
+
471
+ phandle_pos = mc->smp.cpus;
472
+ for (socket = (riscv_socket_count(mc) - 1); socket >= 0; socket--) {
473
+ phandle_pos -= s->soc[socket].num_harts;
474
475
if (s->aia_type == VIRT_AIA_TYPE_NONE) {
476
create_fdt_socket_plic(s, memmap, socket, phandle,
477
- intc_phandles, xplic_phandles);
478
+ &intc_phandles[phandle_pos], xplic_phandles);
479
} else {
480
- create_fdt_socket_aia(s, memmap, socket, phandle,
481
- intc_phandles, xplic_phandles);
482
+ create_fdt_socket_aplic(s, memmap, socket,
483
+ msi_m_phandle, msi_s_phandle, phandle,
484
+ &intc_phandles[phandle_pos], xplic_phandles);
485
}
486
-
487
- g_free(intc_phandles);
488
- g_free(clust_name);
489
}
490
491
+ g_free(intc_phandles);
492
+
493
for (socket = 0; socket < riscv_socket_count(mc); socket++) {
494
if (socket == 0) {
495
*irq_mmio_phandle = xplic_phandles[socket];
496
@@ -XXX,XX +XXX,XX @@ static void create_fdt_virtio(RISCVVirtState *s, const MemMapEntry *memmap,
497
}
498
499
static void create_fdt_pcie(RISCVVirtState *s, const MemMapEntry *memmap,
500
- uint32_t irq_pcie_phandle)
501
+ uint32_t irq_pcie_phandle,
502
+ uint32_t msi_pcie_phandle)
503
{
504
char *name;
505
MachineState *mc = MACHINE(s);
506
@@ -XXX,XX +XXX,XX @@ static void create_fdt_pcie(RISCVVirtState *s, const MemMapEntry *memmap,
507
qemu_fdt_setprop_cells(mc->fdt, name, "bus-range", 0,
508
memmap[VIRT_PCIE_ECAM].size / PCIE_MMCFG_SIZE_MIN - 1);
509
qemu_fdt_setprop(mc->fdt, name, "dma-coherent", NULL, 0);
510
+ if (s->aia_type == VIRT_AIA_TYPE_APLIC_IMSIC) {
511
+ qemu_fdt_setprop_cell(mc->fdt, name, "msi-parent", msi_pcie_phandle);
512
+ }
513
qemu_fdt_setprop_cells(mc->fdt, name, "reg", 0,
514
memmap[VIRT_PCIE_ECAM].base, 0, memmap[VIRT_PCIE_ECAM].size);
515
qemu_fdt_setprop_sized_cells(mc->fdt, name, "ranges",
516
@@ -XXX,XX +XXX,XX @@ static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap,
517
uint64_t mem_size, const char *cmdline, bool is_32_bit)
518
{
519
MachineState *mc = MACHINE(s);
520
- uint32_t phandle = 1, irq_mmio_phandle = 1;
521
+ uint32_t phandle = 1, irq_mmio_phandle = 1, msi_pcie_phandle = 1;
522
uint32_t irq_pcie_phandle = 1, irq_virtio_phandle = 1;
523
524
if (mc->dtb) {
525
@@ -XXX,XX +XXX,XX @@ static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap,
526
qemu_fdt_setprop_cell(mc->fdt, "/soc", "#address-cells", 0x2);
527
528
create_fdt_sockets(s, memmap, is_32_bit, &phandle,
529
- &irq_mmio_phandle, &irq_pcie_phandle, &irq_virtio_phandle);
530
+ &irq_mmio_phandle, &irq_pcie_phandle, &irq_virtio_phandle,
531
+ &msi_pcie_phandle);
532
533
create_fdt_virtio(s, memmap, irq_virtio_phandle);
534
535
- create_fdt_pcie(s, memmap, irq_pcie_phandle);
536
+ create_fdt_pcie(s, memmap, irq_pcie_phandle, msi_pcie_phandle);
537
538
create_fdt_reset(s, memmap, &phandle);
539
540
@@ -XXX,XX +XXX,XX @@ static DeviceState *virt_create_plic(const MemMapEntry *memmap, int socket,
541
return ret;
542
}
543
544
-static DeviceState *virt_create_aia(RISCVVirtAIAType aia_type,
545
+static DeviceState *virt_create_aia(RISCVVirtAIAType aia_type, int aia_guests,
546
const MemMapEntry *memmap, int socket,
547
int base_hartid, int hart_count)
548
{
549
+ int i;
550
+ hwaddr addr;
551
+ uint32_t guest_bits;
552
DeviceState *aplic_m;
553
+ bool msimode = (aia_type == VIRT_AIA_TYPE_APLIC_IMSIC) ? true : false;
554
+
555
+ if (msimode) {
556
+ /* Per-socket M-level IMSICs */
557
+ addr = memmap[VIRT_IMSIC_M].base + socket * VIRT_IMSIC_GROUP_MAX_SIZE;
558
+ for (i = 0; i < hart_count; i++) {
559
+ riscv_imsic_create(addr + i * IMSIC_HART_SIZE(0),
560
+ base_hartid + i, true, 1,
561
+ VIRT_IRQCHIP_NUM_MSIS);
562
+ }
563
+
564
+ /* Per-socket S-level IMSICs */
565
+ guest_bits = imsic_num_bits(aia_guests + 1);
566
+ addr = memmap[VIRT_IMSIC_S].base + socket * VIRT_IMSIC_GROUP_MAX_SIZE;
567
+ for (i = 0; i < hart_count; i++) {
568
+ riscv_imsic_create(addr + i * IMSIC_HART_SIZE(guest_bits),
569
+ base_hartid + i, false, 1 + aia_guests,
570
+ VIRT_IRQCHIP_NUM_MSIS);
571
+ }
572
+ }
573
574
/* Per-socket M-level APLIC */
575
aplic_m = riscv_aplic_create(
576
memmap[VIRT_APLIC_M].base + socket * memmap[VIRT_APLIC_M].size,
577
memmap[VIRT_APLIC_M].size,
578
- base_hartid, hart_count,
579
+ (msimode) ? 0 : base_hartid,
580
+ (msimode) ? 0 : hart_count,
581
VIRT_IRQCHIP_NUM_SOURCES,
582
VIRT_IRQCHIP_NUM_PRIO_BITS,
583
- false, true, NULL);
584
+ msimode, true, NULL);
585
586
if (aplic_m) {
587
/* Per-socket S-level APLIC */
588
riscv_aplic_create(
589
memmap[VIRT_APLIC_S].base + socket * memmap[VIRT_APLIC_S].size,
590
memmap[VIRT_APLIC_S].size,
591
- base_hartid, hart_count,
592
+ (msimode) ? 0 : base_hartid,
593
+ (msimode) ? 0 : hart_count,
594
VIRT_IRQCHIP_NUM_SOURCES,
595
VIRT_IRQCHIP_NUM_PRIO_BITS,
596
- false, false, aplic_m);
597
+ msimode, false, aplic_m);
598
}
599
600
return aplic_m;
601
@@ -XXX,XX +XXX,XX @@ static void virt_machine_init(MachineState *machine)
602
sysbus_realize(SYS_BUS_DEVICE(&s->soc[i]), &error_abort);
603
604
if (!kvm_enabled()) {
605
- /* Per-socket CLINT */
606
- riscv_aclint_swi_create(
607
- memmap[VIRT_CLINT].base + i * memmap[VIRT_CLINT].size,
608
- base_hartid, hart_count, false);
609
- riscv_aclint_mtimer_create(
610
- memmap[VIRT_CLINT].base + i * memmap[VIRT_CLINT].size +
611
- RISCV_ACLINT_SWI_SIZE,
612
- RISCV_ACLINT_DEFAULT_MTIMER_SIZE, base_hartid, hart_count,
613
- RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME,
614
- RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ, true);
615
-
616
- /* Per-socket ACLINT SSWI */
617
if (s->have_aclint) {
618
+ if (s->aia_type == VIRT_AIA_TYPE_APLIC_IMSIC) {
619
+ /* Per-socket ACLINT MTIMER */
620
+ riscv_aclint_mtimer_create(memmap[VIRT_CLINT].base +
621
+ i * RISCV_ACLINT_DEFAULT_MTIMER_SIZE,
622
+ RISCV_ACLINT_DEFAULT_MTIMER_SIZE,
623
+ base_hartid, hart_count,
624
+ RISCV_ACLINT_DEFAULT_MTIMECMP,
625
+ RISCV_ACLINT_DEFAULT_MTIME,
626
+ RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ, true);
627
+ } else {
628
+ /* Per-socket ACLINT MSWI, MTIMER, and SSWI */
629
+ riscv_aclint_swi_create(memmap[VIRT_CLINT].base +
630
+ i * memmap[VIRT_CLINT].size,
631
+ base_hartid, hart_count, false);
632
+ riscv_aclint_mtimer_create(memmap[VIRT_CLINT].base +
633
+ i * memmap[VIRT_CLINT].size + RISCV_ACLINT_SWI_SIZE,
634
+ RISCV_ACLINT_DEFAULT_MTIMER_SIZE,
635
+ base_hartid, hart_count,
636
+ RISCV_ACLINT_DEFAULT_MTIMECMP,
637
+ RISCV_ACLINT_DEFAULT_MTIME,
638
+ RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ, true);
639
+ riscv_aclint_swi_create(memmap[VIRT_ACLINT_SSWI].base +
640
+ i * memmap[VIRT_ACLINT_SSWI].size,
641
+ base_hartid, hart_count, true);
642
+ }
643
+ } else {
644
+ /* Per-socket SiFive CLINT */
645
riscv_aclint_swi_create(
646
- memmap[VIRT_ACLINT_SSWI].base +
647
- i * memmap[VIRT_ACLINT_SSWI].size,
648
- base_hartid, hart_count, true);
649
+ memmap[VIRT_CLINT].base + i * memmap[VIRT_CLINT].size,
650
+ base_hartid, hart_count, false);
651
+ riscv_aclint_mtimer_create(memmap[VIRT_CLINT].base +
652
+ i * memmap[VIRT_CLINT].size + RISCV_ACLINT_SWI_SIZE,
653
+ RISCV_ACLINT_DEFAULT_MTIMER_SIZE,
654
+ base_hartid, hart_count,
655
+ RISCV_ACLINT_DEFAULT_MTIMECMP,
656
+ RISCV_ACLINT_DEFAULT_MTIME,
657
+ RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ, true);
658
}
659
}
660
661
@@ -XXX,XX +XXX,XX @@ static void virt_machine_init(MachineState *machine)
662
s->irqchip[i] = virt_create_plic(memmap, i,
663
base_hartid, hart_count);
664
} else {
665
- s->irqchip[i] = virt_create_aia(s->aia_type, memmap, i,
666
- base_hartid, hart_count);
667
+ s->irqchip[i] = virt_create_aia(s->aia_type, s->aia_guests,
668
+ memmap, i, base_hartid,
669
+ hart_count);
670
}
671
672
/* Try to use different IRQCHIP instance based device type */
673
@@ -XXX,XX +XXX,XX @@ static void virt_machine_instance_init(Object *obj)
674
{
675
}
676
677
+static char *virt_get_aia_guests(Object *obj, Error **errp)
678
+{
679
+ RISCVVirtState *s = RISCV_VIRT_MACHINE(obj);
680
+ char val[32];
681
+
682
+ sprintf(val, "%d", s->aia_guests);
683
+ return g_strdup(val);
684
+}
685
+
686
+static void virt_set_aia_guests(Object *obj, const char *val, Error **errp)
687
+{
688
+ RISCVVirtState *s = RISCV_VIRT_MACHINE(obj);
689
+
690
+ s->aia_guests = atoi(val);
691
+ if (s->aia_guests < 0 || s->aia_guests > VIRT_IRQCHIP_MAX_GUESTS) {
692
+ error_setg(errp, "Invalid number of AIA IMSIC guests");
693
+ error_append_hint(errp, "Valid values be between 0 and %d.\n",
694
+ VIRT_IRQCHIP_MAX_GUESTS);
695
+ }
696
+}
697
+
698
static char *virt_get_aia(Object *obj, Error **errp)
699
{
700
RISCVVirtState *s = RISCV_VIRT_MACHINE(obj);
701
@@ -XXX,XX +XXX,XX @@ static char *virt_get_aia(Object *obj, Error **errp)
702
case VIRT_AIA_TYPE_APLIC:
703
val = "aplic";
704
break;
705
+ case VIRT_AIA_TYPE_APLIC_IMSIC:
706
+ val = "aplic-imsic";
707
+ break;
708
default:
709
val = "none";
710
break;
711
@@ -XXX,XX +XXX,XX @@ static void virt_set_aia(Object *obj, const char *val, Error **errp)
712
s->aia_type = VIRT_AIA_TYPE_NONE;
713
} else if (!strcmp(val, "aplic")) {
714
s->aia_type = VIRT_AIA_TYPE_APLIC;
715
+ } else if (!strcmp(val, "aplic-imsic")) {
716
+ s->aia_type = VIRT_AIA_TYPE_APLIC_IMSIC;
717
} else {
718
error_setg(errp, "Invalid AIA interrupt controller type");
719
- error_append_hint(errp, "Valid values are none, and aplic.\n");
720
+ error_append_hint(errp, "Valid values are none, aplic, and "
721
+ "aplic-imsic.\n");
722
}
723
}
724
725
@@ -XXX,XX +XXX,XX @@ static void virt_set_aclint(Object *obj, bool value, Error **errp)
726
727
static void virt_machine_class_init(ObjectClass *oc, void *data)
728
{
729
+ char str[128];
730
MachineClass *mc = MACHINE_CLASS(oc);
731
732
mc->desc = "RISC-V VirtIO board";
733
@@ -XXX,XX +XXX,XX @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
734
object_class_property_set_description(oc, "aia",
735
"Set type of AIA interrupt "
736
"conttoller. Valid values are "
737
- "none, and aplic.");
738
+ "none, aplic, and aplic-imsic.");
739
+
740
+ object_class_property_add_str(oc, "aia-guests",
741
+ virt_get_aia_guests,
742
+ virt_set_aia_guests);
743
+ sprintf(str, "Set number of guest MMIO pages for AIA IMSIC. Valid value "
744
+ "should be between 0 and %d.", VIRT_IRQCHIP_MAX_GUESTS);
745
+ object_class_property_set_description(oc, "aia-guests", str);
746
}
747
748
static const TypeInfo virt_machine_typeinfo = {
749
diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
750
index XXXXXXX..XXXXXXX 100644
751
--- a/hw/riscv/Kconfig
752
+++ b/hw/riscv/Kconfig
753
@@ -XXX,XX +XXX,XX @@ config RISCV_VIRT
754
select SERIAL
755
select RISCV_ACLINT
756
select RISCV_APLIC
757
+ select RISCV_IMSIC
758
select SIFIVE_PLIC
759
select SIFIVE_TEST
760
select VIRTIO_MMIO
60
--
761
--
61
2.31.1
762
2.34.1
62
763
63
764
diff view generated by jsdifflib
New patch
1
From: Anup Patel <anup.patel@wdc.com>
1
2
3
We have two new machine options "aia" and "aia-guests" available
4
for the RISC-V virt machine so let's document these options.
5
6
Signed-off-by: Anup Patel <anup.patel@wdc.com>
7
Signed-off-by: Anup Patel <anup@brainfault.org>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Reviewed-by: Frank Chang <frank.chang@sifive.com>
10
Message-id: 20220204174700.534953-23-anup@brainfault.org
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
---
13
docs/system/riscv/virt.rst | 16 ++++++++++++++++
14
1 file changed, 16 insertions(+)
15
16
diff --git a/docs/system/riscv/virt.rst b/docs/system/riscv/virt.rst
17
index XXXXXXX..XXXXXXX 100644
18
--- a/docs/system/riscv/virt.rst
19
+++ b/docs/system/riscv/virt.rst
20
@@ -XXX,XX +XXX,XX @@ The following machine-specific options are supported:
21
When this option is "on", ACLINT devices will be emulated instead of
22
SiFive CLINT. When not specified, this option is assumed to be "off".
23
24
+- aia=[none|aplic|aplic-imsic]
25
+
26
+ This option allows selecting interrupt controller defined by the AIA
27
+ (advanced interrupt architecture) specification. The "aia=aplic" selects
28
+ APLIC (advanced platform level interrupt controller) to handle wired
29
+ interrupts whereas the "aia=aplic-imsic" selects APLIC and IMSIC (incoming
30
+ message signaled interrupt controller) to handle both wired interrupts and
31
+ MSIs. When not specified, this option is assumed to be "none" which selects
32
+ SiFive PLIC to handle wired interrupts.
33
+
34
+- aia-guests=nnn
35
+
36
+ The number of per-HART VS-level AIA IMSIC pages to be emulated for a guest
37
+ having AIA IMSIC (i.e. "aia=aplic-imsic" selected). When not specified,
38
+ the default number of per-HART VS-level AIA IMSIC pages is 0.
39
+
40
Running Linux kernel
41
--------------------
42
43
--
44
2.34.1
45
46
diff view generated by jsdifflib
New patch
1
From: Anup Patel <anup.patel@wdc.com>
1
2
3
To facilitate software development of RISC-V systems with large number
4
of HARTs, we increase the maximum number of allowed CPUs to 512 (2^9).
5
6
We also add a detailed source level comments about limit defines which
7
impact the physical address space utilization.
8
9
Signed-off-by: Anup Patel <anup.patel@wdc.com>
10
Signed-off-by: Anup Patel <anup@brainfault.org>
11
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
12
Reviewed-by: Frank Chang <frank.chang@sifive.com>
13
Message-id: 20220204174700.534953-24-anup@brainfault.org
14
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
15
---
16
include/hw/riscv/virt.h | 2 +-
17
hw/riscv/virt.c | 10 ++++++++++
18
2 files changed, 11 insertions(+), 1 deletion(-)
19
20
diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
21
index XXXXXXX..XXXXXXX 100644
22
--- a/include/hw/riscv/virt.h
23
+++ b/include/hw/riscv/virt.h
24
@@ -XXX,XX +XXX,XX @@
25
#include "hw/block/flash.h"
26
#include "qom/object.h"
27
28
-#define VIRT_CPUS_MAX_BITS 3
29
+#define VIRT_CPUS_MAX_BITS 9
30
#define VIRT_CPUS_MAX (1 << VIRT_CPUS_MAX_BITS)
31
#define VIRT_SOCKETS_MAX_BITS 2
32
#define VIRT_SOCKETS_MAX (1 << VIRT_SOCKETS_MAX_BITS)
33
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/riscv/virt.c
36
+++ b/hw/riscv/virt.c
37
@@ -XXX,XX +XXX,XX @@
38
#include "hw/pci-host/gpex.h"
39
#include "hw/display/ramfb.h"
40
41
+/*
42
+ * The virt machine physical address space used by some of the devices
43
+ * namely ACLINT, PLIC, APLIC, and IMSIC depend on number of Sockets,
44
+ * number of CPUs, and number of IMSIC guest files.
45
+ *
46
+ * Various limits defined by VIRT_SOCKETS_MAX_BITS, VIRT_CPUS_MAX_BITS,
47
+ * and VIRT_IRQCHIP_MAX_GUESTS_BITS are tuned for maximum utilization
48
+ * of virt machine physical address space.
49
+ */
50
+
51
#define VIRT_IMSIC_GROUP_MAX_SIZE (1U << IMSIC_MMIO_GROUP_MIN_SHIFT)
52
#if VIRT_IMSIC_GROUP_MAX_SIZE < \
53
IMSIC_GROUP_SIZE(VIRT_CPUS_MAX_BITS, VIRT_IRQCHIP_MAX_GUESTS_BITS)
54
--
55
2.34.1
56
57
diff view generated by jsdifflib
New patch
1
From: Guo Ren <ren_guo@c-sky.com>
1
2
3
Highest bits of PTE has been used for svpbmt, ref: [1], [2], so we
4
need to ignore them. They cannot be a part of ppn.
5
6
1: The RISC-V Instruction Set Manual, Volume II: Privileged Architecture
7
4.4 Sv39: Page-Based 39-bit Virtual-Memory System
8
4.5 Sv48: Page-Based 48-bit Virtual-Memory System
9
10
2: https://github.com/riscv/virtual-memory/blob/main/specs/663-Svpbmt-diff.pdf
11
12
Signed-off-by: Guo Ren <ren_guo@c-sky.com>
13
Reviewed-by: Liu Zhiwei <zhiwei_liu@c-sky.com>
14
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
15
Cc: Bin Meng <bmeng.cn@gmail.com>
16
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
17
Message-Id: <20220204022658.18097-2-liweiwei@iscas.ac.cn>
18
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
19
---
20
target/riscv/cpu.h | 15 +++++++++++++++
21
target/riscv/cpu_bits.h | 3 +++
22
target/riscv/cpu_helper.c | 13 ++++++++++++-
23
3 files changed, 30 insertions(+), 1 deletion(-)
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
72
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
73
index XXXXXXX..XXXXXXX 100644
74
--- a/target/riscv/cpu_helper.c
75
+++ b/target/riscv/cpu_helper.c
76
@@ -XXX,XX +XXX,XX @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
77
MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
78
int mode = mmu_idx & TB_FLAGS_PRIV_MMU_MASK;
79
bool use_background = false;
80
+ hwaddr ppn;
81
+ RISCVCPU *cpu = env_archcpu(env);
82
83
/*
84
* Check if we should use the background registers for the two
85
@@ -XXX,XX +XXX,XX @@ restart:
86
return TRANSLATE_FAIL;
87
}
88
89
- hwaddr ppn = pte >> PTE_PPN_SHIFT;
90
+ if (riscv_cpu_sxl(env) == MXL_RV32) {
91
+ ppn = pte >> PTE_PPN_SHIFT;
92
+ } else if (cpu->cfg.ext_svpbmt || cpu->cfg.ext_svnapot) {
93
+ ppn = (pte & (target_ulong)PTE_PPN_MASK) >> PTE_PPN_SHIFT;
94
+ } else {
95
+ ppn = pte >> PTE_PPN_SHIFT;
96
+ if ((pte & ~(target_ulong)PTE_PPN_MASK) >> PTE_PPN_SHIFT) {
97
+ return TRANSLATE_FAIL;
98
+ }
99
+ }
100
101
if (!(pte & PTE_V)) {
102
/* Invalid PTE */
103
--
104
2.34.1
105
106
diff view generated by jsdifflib
New patch
1
From: Weiwei Li <liweiwei@iscas.ac.cn>
1
2
3
For non-leaf PTEs, the D, A, and U bits are reserved for future standard use.
4
5
Signed-off-by: Weiwei Li <liweiwei@iscas.ac.cn>
6
Signed-off-by: Junqiang Wang <wangjunqiang@iscas.ac.cn>
7
Reviewed-by: Anup Patel <anup@brainfault.org>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Message-Id: <20220204022658.18097-3-liweiwei@iscas.ac.cn>
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
---
12
target/riscv/cpu_helper.c | 3 +++
13
1 file changed, 3 insertions(+)
14
15
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/riscv/cpu_helper.c
18
+++ b/target/riscv/cpu_helper.c
19
@@ -XXX,XX +XXX,XX @@ restart:
20
return TRANSLATE_FAIL;
21
} else if (!(pte & (PTE_R | PTE_W | PTE_X))) {
22
/* Inner PTE, continue walking */
23
+ if (pte & (PTE_D | PTE_A | PTE_U)) {
24
+ return TRANSLATE_FAIL;
25
+ }
26
base = ppn << PGSHIFT;
27
} else if ((pte & (PTE_R | PTE_W | PTE_X)) == PTE_W) {
28
/* Reserved leaf PTE flags: PTE_W */
29
--
30
2.34.1
31
32
diff view generated by jsdifflib
New patch
1
From: Weiwei Li <liweiwei@iscas.ac.cn>
1
2
3
- add PTE_N bit
4
- add PTE_N bit check for inner PTE
5
- update address translation to support 64KiB continuous region (napot_bits = 4)
6
7
Signed-off-by: Weiwei Li <liweiwei@iscas.ac.cn>
8
Signed-off-by: Junqiang Wang <wangjunqiang@iscas.ac.cn>
9
Reviewed-by: Anup Patel <anup@brainfault.org>
10
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
11
Message-Id: <20220204022658.18097-4-liweiwei@iscas.ac.cn>
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
13
---
14
target/riscv/cpu_bits.h | 1 +
15
target/riscv/cpu.c | 2 ++
16
target/riscv/cpu_helper.c | 18 +++++++++++++++---
17
3 files changed, 18 insertions(+), 3 deletions(-)
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
31
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/target/riscv/cpu.c
34
+++ b/target/riscv/cpu.c
35
@@ -XXX,XX +XXX,XX @@ static Property riscv_cpu_properties[] = {
36
DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128),
37
DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
38
39
+ DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false),
40
+
41
DEFINE_PROP_BOOL("zba", RISCVCPU, cfg.ext_zba, true),
42
DEFINE_PROP_BOOL("zbb", RISCVCPU, cfg.ext_zbb, true),
43
DEFINE_PROP_BOOL("zbc", RISCVCPU, cfg.ext_zbc, true),
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 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
49
bool use_background = false;
50
hwaddr ppn;
51
RISCVCPU *cpu = env_archcpu(env);
52
+ int napot_bits = 0;
53
+ target_ulong napot_mask;
54
55
/*
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)) {
87
--
88
2.34.1
89
90
diff view generated by jsdifflib
New patch
1
From: Weiwei Li <liweiwei@iscas.ac.cn>
1
2
3
- sinval.vma, hinval.vvma and hinval.gvma do the same as sfence.vma, hfence.vvma and hfence.gvma except extension check
4
- do nothing other than extension check for sfence.w.inval and sfence.inval.ir
5
6
Signed-off-by: Weiwei Li <liweiwei@iscas.ac.cn>
7
Signed-off-by: Junqiang Wang <wangjunqiang@iscas.ac.cn>
8
Reviewed-by: Anup Patel <anup@brainfault.org>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Message-Id: <20220204022658.18097-5-liweiwei@iscas.ac.cn>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
---
13
target/riscv/cpu.h | 1 +
14
target/riscv/insn32.decode | 7 ++
15
target/riscv/cpu.c | 1 +
16
target/riscv/translate.c | 1 +
17
target/riscv/insn_trans/trans_svinval.c.inc | 75 +++++++++++++++++++++
18
5 files changed, 85 insertions(+)
19
create mode 100644 target/riscv/insn_trans/trans_svinval.c.inc
20
21
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
22
index XXXXXXX..XXXXXXX 100644
23
--- a/target/riscv/cpu.h
24
+++ b/target/riscv/cpu.h
25
@@ -XXX,XX +XXX,XX @@ struct RISCVCPUConfig {
26
bool ext_counters;
27
bool ext_ifencei;
28
bool ext_icsr;
29
+ bool ext_svinval;
30
bool ext_svnapot;
31
bool ext_svpbmt;
32
bool ext_zfh;
33
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/riscv/insn32.decode
36
+++ b/target/riscv/insn32.decode
37
@@ -XXX,XX +XXX,XX @@ fcvt_l_h 1100010 00010 ..... ... ..... 1010011 @r2_rm
38
fcvt_lu_h 1100010 00011 ..... ... ..... 1010011 @r2_rm
39
fcvt_h_l 1101010 00010 ..... ... ..... 1010011 @r2_rm
40
fcvt_h_lu 1101010 00011 ..... ... ..... 1010011 @r2_rm
41
+
42
+# *** Svinval Standard Extension ***
43
+sinval_vma 0001011 ..... ..... 000 00000 1110011 @sfence_vma
44
+sfence_w_inval 0001100 00000 00000 000 00000 1110011
45
+sfence_inval_ir 0001100 00001 00000 000 00000 1110011
46
+hinval_vvma 0010011 ..... ..... 000 00000 1110011 @hfence_vvma
47
+hinval_gvma 0110011 ..... ..... 000 00000 1110011 @hfence_gvma
48
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/target/riscv/cpu.c
51
+++ b/target/riscv/cpu.c
52
@@ -XXX,XX +XXX,XX @@ static Property riscv_cpu_properties[] = {
53
DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128),
54
DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
55
56
+ DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false),
57
DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false),
58
59
DEFINE_PROP_BOOL("zba", RISCVCPU, cfg.ext_zba, true),
60
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/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
77
@@ -XXX,XX +XXX,XX @@
78
+/*
79
+ * RISC-V translation routines for the Svinval Standard Instruction Set.
80
+ *
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
+ */
95
+
96
+#define REQUIRE_SVINVAL(ctx) do { \
97
+ if (!ctx->cfg_ptr->ext_svinval) { \
98
+ return false; \
99
+ } \
100
+} while (0)
101
+
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
+}
113
+
114
+static bool trans_sfence_w_inval(DisasContext *ctx, arg_sfence_w_inval *a)
115
+{
116
+ REQUIRE_SVINVAL(ctx);
117
+ REQUIRE_EXT(ctx, RVS);
118
+ /* Do nothing currently */
119
+ return true;
120
+}
121
+
122
+static bool trans_sfence_inval_ir(DisasContext *ctx, arg_sfence_inval_ir *a)
123
+{
124
+ REQUIRE_SVINVAL(ctx);
125
+ REQUIRE_EXT(ctx, RVS);
126
+ /* Do nothing currently */
127
+ return true;
128
+}
129
+
130
+static bool trans_hinval_vvma(DisasContext *ctx, arg_hinval_vvma *a)
131
+{
132
+ REQUIRE_SVINVAL(ctx);
133
+ /* Do the same as hfence.vvma currently */
134
+ REQUIRE_EXT(ctx, RVH);
135
+#ifndef CONFIG_USER_ONLY
136
+ gen_helper_hyp_tlb_flush(cpu_env);
137
+ return true;
138
+#endif
139
+ return false;
140
+}
141
+
142
+static bool trans_hinval_gvma(DisasContext *ctx, arg_hinval_gvma *a)
143
+{
144
+ REQUIRE_SVINVAL(ctx);
145
+ /* Do the same as hfence.gvma currently */
146
+ REQUIRE_EXT(ctx, RVH);
147
+#ifndef CONFIG_USER_ONLY
148
+ gen_helper_hyp_gvma_tlb_flush(cpu_env);
149
+ return true;
150
+#endif
151
+ return false;
152
+}
153
--
154
2.34.1
155
156
diff view generated by jsdifflib
New patch
1
From: Weiwei Li <liweiwei@iscas.ac.cn>
1
2
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
- add PTE_PBMT bit check for inner PTE
5
6
Signed-off-by: Weiwei Li <liweiwei@iscas.ac.cn>
7
Signed-off-by: Junqiang Wang <wangjunqiang@iscas.ac.cn>
8
Reviewed-by: Anup Patel <anup@brainfault.org>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Message-Id: <20220204022658.18097-6-liweiwei@iscas.ac.cn>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
---
13
target/riscv/cpu_bits.h | 2 ++
14
target/riscv/cpu.c | 1 +
15
target/riscv/cpu_helper.c | 4 +++-
16
3 files changed, 6 insertions(+), 1 deletion(-)
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
32
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/riscv/cpu.c
35
+++ b/target/riscv/cpu.c
36
@@ -XXX,XX +XXX,XX @@ static Property riscv_cpu_properties[] = {
37
38
DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false),
39
DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false),
40
+ DEFINE_PROP_BOOL("svpbmt", RISCVCPU, cfg.ext_svpbmt, false),
41
42
DEFINE_PROP_BOOL("zba", RISCVCPU, cfg.ext_zba, true),
43
DEFINE_PROP_BOOL("zbb", RISCVCPU, cfg.ext_zbb, true),
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;
61
--
62
2.34.1
63
64
diff view generated by jsdifflib
New patch
1
From: Yu Li <liyu.yukiteru@bytedance.com>
1
2
3
Since the hypervisor extension been non experimental and enabled for
4
default CPU, the previous command is no longer available and the
5
option `x-h=true` or `h=true` is also no longer required.
6
7
Signed-off-by: Yu Li <liyu.yukiteru@bytedance.com>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Message-Id: <9040401e-8f87-ef4a-d840-6703f08d068c@bytedance.com>
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
---
12
docs/system/riscv/virt.rst | 6 +++---
13
1 file changed, 3 insertions(+), 3 deletions(-)
14
15
diff --git a/docs/system/riscv/virt.rst b/docs/system/riscv/virt.rst
16
index XXXXXXX..XXXXXXX 100644
17
--- a/docs/system/riscv/virt.rst
18
+++ b/docs/system/riscv/virt.rst
19
@@ -XXX,XX +XXX,XX @@ The ``virt`` machine supports the following devices:
20
* 1 generic PCIe host bridge
21
* The fw_cfg device that allows a guest to obtain data from QEMU
22
23
-Note that the default CPU is a generic RV32GC/RV64GC. Optional extensions
24
-can be enabled via command line parameters, e.g.: ``-cpu rv64,x-h=true``
25
-enables the hypervisor extension for RV64.
26
+The hypervisor extension has been enabled for the default CPU, so virtual
27
+machines with hypervisor extension can simply be used without explicitly
28
+declaring.
29
30
Hardware configuration information
31
----------------------------------
32
--
33
2.34.1
34
35
diff view generated by jsdifflib