1
From: Alistair Francis <alistair.francis@wdc.com>
1
The following changes since commit ad10b4badc1dd5b28305f9b9f1168cf0aa3ae946:
2
2
3
The following changes since commit 0a301624c2f4ced3331ffd5bce85b4274fe132af:
3
Merge tag 'pull-error-2024-05-27' of https://repo.or.cz/qemu/armbru into staging (2024-05-27 06:40:42 -0700)
4
5
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20220208' into staging (2022-02-08 11:40:08 +0000)
6
4
7
are available in the Git repository at:
5
are available in the Git repository at:
8
6
9
git@github.com:alistair23/qemu.git tags/pull-riscv-to-apply-20220212
7
https://github.com/alistair23/qemu.git tags/pull-riscv-to-apply-20240528
10
8
11
for you to fetch changes up to 31d69b66ed89fa0f66d4e5a15e9664c92c3ed8f8:
9
for you to fetch changes up to 1806da76cb81088ea026ca3441551782b850e393:
12
10
13
docs/system: riscv: Update description of CPU (2022-02-11 18:31:29 +1000)
11
target/riscv: raise an exception when CSRRS/CSRRC writes a read-only CSR (2024-05-28 12:20:27 +1000)
14
12
15
----------------------------------------------------------------
13
----------------------------------------------------------------
16
Fourth RISC-V PR for QEMU 7.0
14
RISC-V PR for 9.1
17
15
18
* Remove old Ibex PLIC header file
16
* APLICs add child earlier than realize
19
* Allow writing 8 bytes with generic loader
17
* Fix exposure of Zkr
20
* Fixes for RV128
18
* Raise exceptions on wrs.nto
21
* Refactor RISC-V CPU configs
19
* Implement SBI debug console (DBCN) calls for KVM
22
* Initial support for XVentanaCondOps custom extension
20
* Support 64-bit addresses for initrd
23
* Fix for vill field in vtype
21
* Change RISCV_EXCP_SEMIHOST exception number to 63
24
* Fix trap cause for RV32 HS-mode CSR access from RV64 HS-mode
22
* Tolerate KVM disable ext errors
25
* RISC-V AIA support for virt machine
23
* Set tval in breakpoints
26
* Support for svnapot, svinval and svpbmt extensions
24
* Add support for Zve32x extension
25
* Add support for Zve64x extension
26
* Relax vector register check in RISCV gdbstub
27
* Fix the element agnostic Vector function problem
28
* Fix Zvkb extension config
29
* Implement dynamic establishment of custom decoder
30
* Add th.sxstatus CSR emulation
31
* Fix Zvfhmin checking for vfwcvt.f.f.v and vfncvt.f.f.w instructions
32
* Check single width operator for vector fp widen instructions
33
* Check single width operator for vfncvt.rod.f.f.w
34
* Remove redudant SEW checking for vector fp narrow/widen instructions
35
* Prioritize pmp errors in raise_mmu_exception()
36
* Do not set mtval2 for non guest-page faults
37
* Remove experimental prefix from "B" extension
38
* Fixup CBO extension register calculation
39
* Fix the hart bit setting of AIA
40
* Fix reg_width in ricsv_gen_dynamic_vector_feature()
41
* Decode all of the pmpcfg and pmpaddr CSRs
42
* Raise an exception when CSRRS/CSRRC writes a read-only CSR
27
43
28
----------------------------------------------------------------
44
----------------------------------------------------------------
29
Anup Patel (23):
45
Alexei Filippov (1):
30
target/riscv: Fix trap cause for RV32 HS-mode CSR access from RV64 HS-mode
46
target/riscv: do not set mtval2 for non guest-page faults
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
53
47
54
Frédéric Pétrot (1):
48
Alistair Francis (2):
55
target/riscv: correct "code should not be reached" for x-rv128
49
target/riscv: rvzicbo: Fixup CBO extension register calculation
50
disas/riscv: Decode all of the pmpcfg and pmpaddr CSRs
56
51
57
Guo Ren (1):
52
Andrew Jones (2):
58
target/riscv: Ignore reserved bits in PTE for RV64
53
target/riscv/kvm: Fix exposure of Zkr
54
target/riscv: Raise exceptions on wrs.nto
59
55
60
LIU Zhiwei (1):
56
Cheng Yang (1):
61
target/riscv: Fix vill field write in vtype
57
hw/riscv/boot.c: Support 64-bit address for initrd
62
58
63
Petr Tesarik (1):
59
Christoph Müllner (1):
64
Allow setting up to 8 bytes with the generic loader
60
riscv: thead: Add th.sxstatus CSR emulation
65
61
66
Philipp Tomsich (7):
62
Clément Léger (1):
67
target/riscv: refactor (anonymous struct) RISCVCPU.cfg into 'struct RISCVCPUConfig'
63
target/riscv: change RISCV_EXCP_SEMIHOST exception number to 63
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
64
75
Weiwei Li (4):
65
Daniel Henrique Barboza (6):
76
target/riscv: add PTE_A/PTE_D/PTE_U bits check for inner PTE
66
target/riscv/kvm: implement SBI debug console (DBCN) calls
77
target/riscv: add support for svnapot extension
67
target/riscv/kvm: tolerate KVM disable ext errors
78
target/riscv: add support for svinval extension
68
target/riscv/debug: set tval=pc in breakpoint exceptions
79
target/riscv: add support for svpbmt extension
69
trans_privileged.c.inc: set (m|s)tval on ebreak breakpoint
70
target/riscv: prioritize pmp errors in raise_mmu_exception()
71
riscv, gdbstub.c: fix reg_width in ricsv_gen_dynamic_vector_feature()
80
72
81
Wilfred Mallawa (1):
73
Huang Tao (2):
82
include: hw: remove ibex_plic.h
74
target/riscv: Fix the element agnostic function problem
75
target/riscv: Implement dynamic establishment of custom decoder
83
76
84
Yu Li (1):
77
Jason Chien (3):
85
docs/system: riscv: Update description of CPU
78
target/riscv: Add support for Zve32x extension
79
target/riscv: Add support for Zve64x extension
80
target/riscv: Relax vector register check in RISCV gdbstub
86
81
87
docs/system/riscv/virt.rst | 22 +-
82
Max Chou (4):
88
include/hw/intc/ibex_plic.h | 67 -
83
target/riscv: rvv: Fix Zvfhmin checking for vfwcvt.f.f.v and vfncvt.f.f.w instructions
89
include/hw/intc/riscv_aplic.h | 79 ++
84
target/riscv: rvv: Check single width operator for vector fp widen instructions
90
include/hw/intc/riscv_imsic.h | 68 ++
85
target/riscv: rvv: Check single width operator for vfncvt.rod.f.f.w
91
include/hw/riscv/virt.h | 41 +-
86
target/riscv: rvv: Remove redudant SEW checking for vector fp narrow/widen instructions
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
87
88
Rob Bradford (1):
89
target/riscv: Remove experimental prefix from "B" extension
90
91
Yangyu Chen (1):
92
target/riscv/cpu.c: fix Zvkb extension config
93
94
Yong-Xuan Wang (1):
95
target/riscv/kvm.c: Fix the hart bit setting of AIA
96
97
Yu-Ming Chang (1):
98
target/riscv: raise an exception when CSRRS/CSRRC writes a read-only CSR
99
100
yang.zhang (1):
101
hw/intc/riscv_aplic: APLICs should add child earlier than realize
102
103
MAINTAINERS | 1 +
104
target/riscv/cpu.h | 11 ++
105
target/riscv/cpu_bits.h | 2 +-
106
target/riscv/cpu_cfg.h | 2 +
107
target/riscv/helper.h | 1 +
108
target/riscv/sbi_ecall_interface.h | 17 +++
109
target/riscv/tcg/tcg-cpu.h | 15 +++
110
disas/riscv.c | 65 +++++++++-
111
hw/intc/riscv_aplic.c | 8 +-
112
hw/riscv/boot.c | 4 +-
113
target/riscv/cpu.c | 10 +-
114
target/riscv/cpu_helper.c | 37 +++---
115
target/riscv/csr.c | 71 +++++++++--
116
target/riscv/debug.c | 3 +
117
target/riscv/gdbstub.c | 8 +-
118
target/riscv/kvm/kvm-cpu.c | 157 ++++++++++++++++++++++++-
119
target/riscv/op_helper.c | 17 ++-
120
target/riscv/tcg/tcg-cpu.c | 50 +++++---
121
target/riscv/th_csr.c | 79 +++++++++++++
122
target/riscv/translate.c | 31 +++--
123
target/riscv/vector_internals.c | 22 ++++
124
target/riscv/insn_trans/trans_privileged.c.inc | 2 +
125
target/riscv/insn_trans/trans_rvv.c.inc | 46 +++++---
126
target/riscv/insn_trans/trans_rvzawrs.c.inc | 29 +++--
127
target/riscv/insn_trans/trans_rvzicbo.c.inc | 16 ++-
128
target/riscv/meson.build | 1 +
129
26 files changed, 596 insertions(+), 109 deletions(-)
130
create mode 100644 target/riscv/th_csr.c
131
diff view generated by jsdifflib
Deleted patch
1
From: Wilfred Mallawa <wilfred.mallawa@wdc.com>
2
1
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
Deleted patch
1
From: Petr Tesarik <ptesarik@suse.com>
2
1
3
The documentation for the generic loader says that "the maximum size of
4
the data is 8 bytes". However, attempts to set data-len=8 trigger the
5
following assertion failure:
6
7
../hw/core/generic-loader.c:59: generic_loader_reset: Assertion `s->data_len < sizeof(s->data)' failed.
8
9
The type of s->data is uint64_t (i.e. 8 bytes long), so I believe this
10
assert should use <= instead of <.
11
12
Fixes: e481a1f63c93 ("generic-loader: Add a generic loader")
13
Signed-off-by: Petr Tesarik <ptesarik@suse.com>
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
16
Message-id: 20220120092715.7805-1-ptesarik@suse.com
17
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
18
---
19
hw/core/generic-loader.c | 2 +-
20
1 file changed, 1 insertion(+), 1 deletion(-)
21
22
diff --git a/hw/core/generic-loader.c b/hw/core/generic-loader.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/hw/core/generic-loader.c
25
+++ b/hw/core/generic-loader.c
26
@@ -XXX,XX +XXX,XX @@ static void generic_loader_reset(void *opaque)
27
}
28
29
if (s->data_len) {
30
- assert(s->data_len < sizeof(s->data));
31
+ assert(s->data_len <= sizeof(s->data));
32
dma_memory_write(s->cpu->as, s->addr, &s->data, s->data_len,
33
MEMTXATTRS_UNSPECIFIED);
34
}
35
--
36
2.34.1
37
38
diff view generated by jsdifflib
1
From: Anup Patel <anup.patel@wdc.com>
1
From: "yang.zhang" <yang.zhang@hexintek.com>
2
2
3
The RISC-V AIA (Advanced Interrupt Architecture) defines a new
3
Since only root APLICs can have hw IRQ lines, aplic->parent should
4
interrupt controller for wired interrupts called APLIC (Advanced
4
be initialized first.
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
5
9
This patch adds device emulation for RISC-V AIA APLIC.
6
Fixes: e8f79343cf ("hw/intc: Add RISC-V AIA APLIC device emulation")
10
7
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
11
Signed-off-by: Anup Patel <anup.patel@wdc.com>
8
Signed-off-by: yang.zhang <yang.zhang@hexintek.com>
12
Signed-off-by: Anup Patel <anup@brainfault.org>
9
Cc: qemu-stable <qemu-stable@nongnu.org>
13
Reviewed-by: Frank Chang <frank.chang@sifive.com>
10
Message-ID: <20240409014445.278-1-gaoshanliukou@163.com>
14
Message-id: 20220204174700.534953-19-anup@brainfault.org
15
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
16
---
12
---
17
include/hw/intc/riscv_aplic.h | 79 +++
13
hw/intc/riscv_aplic.c | 8 ++++----
18
hw/intc/riscv_aplic.c | 978 ++++++++++++++++++++++++++++++++++
14
1 file changed, 4 insertions(+), 4 deletions(-)
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
15
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
16
diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
111
new file mode 100644
17
index XXXXXXX..XXXXXXX 100644
112
index XXXXXXX..XXXXXXX
18
--- a/hw/intc/riscv_aplic.c
113
--- /dev/null
114
+++ b/hw/intc/riscv_aplic.c
19
+++ b/hw/intc/riscv_aplic.c
115
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ DeviceState *riscv_aplic_create(hwaddr addr, hwaddr size,
116
+/*
21
qdev_prop_set_bit(dev, "msimode", msimode);
117
+ * RISC-V APLIC (Advanced Platform Level Interrupt Controller)
22
qdev_prop_set_bit(dev, "mmode", mmode);
118
+ *
23
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) {
24
+ if (parent) {
1079
+ riscv_aplic_add_child(parent, dev);
25
+ riscv_aplic_add_child(parent, dev);
1080
+ }
26
+ }
1081
+
27
+
1082
+ if (!msimode) {
28
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
1083
+ for (i = 0; i < num_harts; i++) {
29
1084
+ CPUState *cpu = qemu_get_cpu(hartid_base + i);
30
if (!is_kvm_aia(msimode)) {
1085
+
31
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
1086
+ qdev_connect_gpio_out_named(dev, NULL, i,
32
}
1087
+ qdev_get_gpio_in(DEVICE(cpu),
33
1088
+ (mmode) ? IRQ_M_EXT : IRQ_S_EXT));
34
- if (parent) {
1089
+ }
35
- riscv_aplic_add_child(parent, dev);
1090
+ }
36
- }
1091
+
37
-
1092
+ return dev;
38
if (!msimode) {
1093
+}
39
for (i = 0; i < num_harts; i++) {
1094
diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
40
CPUState *cpu = cpu_by_arch_id(hartid_base + i);
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
--
41
--
1121
2.34.1
42
2.45.1
1122
1123
1124
diff view generated by jsdifflib
1
From: Anup Patel <anup.patel@wdc.com>
1
From: Andrew Jones <ajones@ventanamicro.com>
2
2
3
The AIA specification adds new CSRs for RV32 so that RISC-V hart can
3
The Zkr extension may only be exposed to KVM guests if the VMM
4
support 64 local interrupts on both RV32 and RV64.
4
implements the SEED CSR. Use the same implementation as TCG.
5
5
6
Signed-off-by: Anup Patel <anup.patel@wdc.com>
6
Without this patch, running with a KVM which does not forward the
7
Signed-off-by: Anup Patel <anup@brainfault.org>
7
SEED CSR access to QEMU will result in an ILL exception being
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
injected into the guest (this results in Linux guests crashing on
9
Reviewed-by: Frank Chang <frank.chang@sifive.com>
9
boot). And, when running with a KVM which does forward the access,
10
Message-id: 20220204174700.534953-11-anup@brainfault.org
10
QEMU will crash, since QEMU doesn't know what to do with the exit.
11
12
Fixes: 3108e2f1c69d ("target/riscv/kvm: update KVM exts to Linux 6.8")
13
Signed-off-by: Andrew Jones <ajones@ventanamicro.com>
14
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
15
Cc: qemu-stable <qemu-stable@nongnu.org>
16
Message-ID: <20240422134605.534207-2-ajones@ventanamicro.com>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
17
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
---
18
---
13
target/riscv/cpu.h | 14 +-
19
target/riscv/cpu.h | 3 +++
14
target/riscv/cpu_helper.c | 10 +-
20
target/riscv/csr.c | 18 ++++++++++++++----
15
target/riscv/csr.c | 560 +++++++++++++++++++++++++++++++-------
21
target/riscv/kvm/kvm-cpu.c | 25 +++++++++++++++++++++++++
16
target/riscv/machine.c | 10 +-
22
3 files changed, 42 insertions(+), 4 deletions(-)
17
4 files changed, 474 insertions(+), 120 deletions(-)
18
23
19
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
24
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
20
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
21
--- a/target/riscv/cpu.h
26
--- a/target/riscv/cpu.h
22
+++ b/target/riscv/cpu.h
27
+++ b/target/riscv/cpu.h
23
@@ -XXX,XX +XXX,XX @@ struct CPURISCVState {
28
@@ -XXX,XX +XXX,XX @@ void riscv_set_csr_ops(int csrno, riscv_csr_operations *ops);
24
*/
29
25
uint64_t mstatus;
30
void riscv_cpu_register_gdb_regs_for_features(CPUState *cs);
26
31
27
- target_ulong mip;
32
+target_ulong riscv_new_csr_seed(target_ulong new_value,
28
+ uint64_t mip;
33
+ target_ulong write_mask);
29
34
+
30
- uint32_t miclaim;
35
uint8_t satp_mode_max_from_map(uint32_t map);
31
+ uint64_t miclaim;
36
const char *satp_mode_str(uint8_t satp_mode, bool is_32_bit);
32
37
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
38
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
106
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
107
--- a/target/riscv/csr.c
40
--- a/target/riscv/csr.c
108
+++ b/target/riscv/csr.c
41
+++ b/target/riscv/csr.c
109
@@ -XXX,XX +XXX,XX @@ static RISCVException any32(CPURISCVState *env, int csrno)
42
@@ -XXX,XX +XXX,XX @@ static RISCVException write_upmbase(CPURISCVState *env, int csrno,
110
43
#endif
111
}
44
112
45
/* Crypto Extension */
113
+static int aia_any32(CPURISCVState *env, int csrno)
46
-static RISCVException rmw_seed(CPURISCVState *env, int csrno,
114
+{
47
- target_ulong *ret_value,
115
+ if (!riscv_feature(env, RISCV_FEATURE_AIA)) {
48
- target_ulong new_value,
116
+ return RISCV_EXCP_ILLEGAL_INST;
49
- target_ulong write_mask)
117
+ }
50
+target_ulong riscv_new_csr_seed(target_ulong new_value,
118
+
51
+ target_ulong write_mask)
119
+ return any32(env, csrno);
52
{
53
uint16_t random_v;
54
Error *random_e = NULL;
55
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_seed(CPURISCVState *env, int csrno,
56
rval = random_v | SEED_OPST_ES16;
57
}
58
59
+ return rval;
120
+}
60
+}
121
+
61
+
122
static RISCVException smode(CPURISCVState *env, int csrno)
62
+static RISCVException rmw_seed(CPURISCVState *env, int csrno,
123
{
63
+ target_ulong *ret_value,
124
if (riscv_has_ext(env, RVS)) {
64
+ target_ulong new_value,
125
@@ -XXX,XX +XXX,XX @@ static RISCVException smode(CPURISCVState *env, int csrno)
65
+ target_ulong write_mask)
126
return RISCV_EXCP_ILLEGAL_INST;
66
+{
67
+ target_ulong rval;
68
+
69
+ rval = riscv_new_csr_seed(new_value, write_mask);
70
+
71
if (ret_value) {
72
*ret_value = rval;
73
}
74
diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
75
index XXXXXXX..XXXXXXX 100644
76
--- a/target/riscv/kvm/kvm-cpu.c
77
+++ b/target/riscv/kvm/kvm-cpu.c
78
@@ -XXX,XX +XXX,XX @@ static int kvm_riscv_handle_sbi(CPUState *cs, struct kvm_run *run)
79
return ret;
127
}
80
}
128
81
129
+static int smode32(CPURISCVState *env, int csrno)
82
+static int kvm_riscv_handle_csr(CPUState *cs, struct kvm_run *run)
130
+{
83
+{
131
+ if (riscv_cpu_mxl(env) != MXL_RV32) {
84
+ target_ulong csr_num = run->riscv_csr.csr_num;
132
+ return RISCV_EXCP_ILLEGAL_INST;
85
+ target_ulong new_value = run->riscv_csr.new_value;
133
+ }
86
+ target_ulong write_mask = run->riscv_csr.write_mask;
87
+ int ret = 0;
134
+
88
+
135
+ return smode(env, csrno);
89
+ switch (csr_num) {
136
+}
90
+ case CSR_SEED:
137
+
91
+ run->riscv_csr.ret_value = riscv_new_csr_seed(new_value, write_mask);
138
+static int aia_smode32(CPURISCVState *env, int csrno)
92
+ break;
139
+{
93
+ default:
140
+ if (!riscv_feature(env, RISCV_FEATURE_AIA)) {
94
+ qemu_log_mask(LOG_UNIMP,
141
+ return RISCV_EXCP_ILLEGAL_INST;
95
+ "%s: un-handled CSR EXIT for CSR %lx\n",
142
+ }
96
+ __func__, csr_num);
143
+
97
+ ret = -1;
144
+ return smode32(env, csrno);
98
+ break;
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
+ }
99
+ }
256
+
100
+
257
+ return ret;
101
+ return ret;
258
+}
102
+}
259
+
103
+
260
+static RISCVException rmw_mie64(CPURISCVState *env, int csrno,
104
int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
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
{
105
{
314
@@ -XXX,XX +XXX,XX @@ static RISCVException write_mtval(CPURISCVState *env, int csrno,
106
int ret = 0;
315
return RISCV_EXCP_NONE;
107
@@ -XXX,XX +XXX,XX @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
316
}
108
case KVM_EXIT_RISCV_SBI:
317
109
ret = kvm_riscv_handle_sbi(cs, run);
318
-static RISCVException rmw_mip(CPURISCVState *env, int csrno,
110
break;
319
- target_ulong *ret_value,
111
+ case KVM_EXIT_RISCV_CSR:
320
- target_ulong new_value, target_ulong write_mask)
112
+ ret = kvm_riscv_handle_csr(cs, run);
321
+static RISCVException rmw_mip64(CPURISCVState *env, int csrno,
113
+ break;
322
+ uint64_t *ret_val,
114
default:
323
+ uint64_t new_val, uint64_t wr_mask)
115
qemu_log_mask(LOG_UNIMP, "%s: un-handled exit reason %d\n",
324
{
116
__func__, run->exit_reason);
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
--
117
--
889
2.34.1
118
2.45.1
890
891
diff view generated by jsdifflib
1
From: Anup Patel <anup.patel@wdc.com>
1
From: Andrew Jones <ajones@ventanamicro.com>
2
2
3
We extend virt machine to emulate both AIA IMSIC and AIA APLIC
3
Implementing wrs.nto to always just return is consistent with the
4
devices only when "aia=aplic-imsic" parameter is passed along
4
specification, as the instruction is permitted to terminate the
5
with machine name in the QEMU command-line. The AIA IMSIC is
5
stall for any reason, but it's not useful for virtualization, where
6
only a per-HART MSI controller so we use AIA APLIC in MSI-mode
6
we'd like the guest to trap to the hypervisor in order to allow
7
to forward all wired interrupts as MSIs to the AIA IMSIC.
7
scheduling of the lock holding VCPU. Change to always immediately
8
raise exceptions when the appropriate conditions are present,
9
otherwise continue to just return. Note, immediately raising
10
exceptions is also consistent with the specification since the
11
time limit that should expire prior to the exception is
12
implementation-specific.
8
13
9
We also provide "aia-guests=<xyz>" parameter which can be used
14
Signed-off-by: Andrew Jones <ajones@ventanamicro.com>
10
to specify number of VS-level AIA IMSIC Guests MMIO pages for
15
Reviewed-by: Christoph Müllner <christoph.muellner@vrull.eu>
11
each HART.
16
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
12
17
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
13
Signed-off-by: Anup Patel <anup.patel@wdc.com>
18
Message-ID: <20240424142808.62936-2-ajones@ventanamicro.com>
14
Signed-off-by: Anup Patel <anup@brainfault.org>
15
Acked-by: Alistair Francis <alistair.francis@wdc.com>
16
Message-id: 20220204174700.534953-22-anup@brainfault.org
17
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
19
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
18
---
20
---
19
include/hw/riscv/virt.h | 17 +-
21
target/riscv/helper.h | 1 +
20
hw/riscv/virt.c | 440 ++++++++++++++++++++++++++++++++--------
22
target/riscv/op_helper.c | 11 ++++++++
21
hw/riscv/Kconfig | 1 +
23
target/riscv/insn_trans/trans_rvzawrs.c.inc | 29 ++++++++++++++-------
22
3 files changed, 374 insertions(+), 84 deletions(-)
24
3 files changed, 32 insertions(+), 9 deletions(-)
23
25
24
diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
26
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
25
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
26
--- a/include/hw/riscv/virt.h
28
--- a/target/riscv/helper.h
27
+++ b/include/hw/riscv/virt.h
29
+++ b/target/riscv/helper.h
28
@@ -XXX,XX +XXX,XX @@
30
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_6(csrrw_i128, tl, env, int, tl, tl, tl, tl)
29
#include "hw/block/flash.h"
31
DEF_HELPER_1(sret, tl, env)
30
#include "qom/object.h"
32
DEF_HELPER_1(mret, tl, env)
31
33
DEF_HELPER_1(wfi, void, env)
32
-#define VIRT_CPUS_MAX 32
34
+DEF_HELPER_1(wrs_nto, void, env)
33
-#define VIRT_SOCKETS_MAX 8
35
DEF_HELPER_1(tlb_flush, void, env)
34
+#define VIRT_CPUS_MAX_BITS 3
36
DEF_HELPER_1(tlb_flush_all, void, env)
35
+#define VIRT_CPUS_MAX (1 << VIRT_CPUS_MAX_BITS)
37
/* Native Debug */
36
+#define VIRT_SOCKETS_MAX_BITS 2
38
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
37
+#define VIRT_SOCKETS_MAX (1 << VIRT_SOCKETS_MAX_BITS)
38
39
#define TYPE_RISCV_VIRT_MACHINE MACHINE_TYPE_NAME("virt")
40
typedef struct RISCVVirtState RISCVVirtState;
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
89
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
90
--- a/hw/riscv/virt.c
40
--- a/target/riscv/op_helper.c
91
+++ b/hw/riscv/virt.c
41
+++ b/target/riscv/op_helper.c
92
@@ -XXX,XX +XXX,XX @@
42
@@ -XXX,XX +XXX,XX @@ void helper_wfi(CPURISCVState *env)
93
#include "hw/riscv/numa.h"
94
#include "hw/intc/riscv_aclint.h"
95
#include "hw/intc/riscv_aplic.h"
96
+#include "hw/intc/riscv_imsic.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 @@
101
#include "hw/pci-host/gpex.h"
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
}
43
}
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
}
44
}
231
45
232
-static void create_fdt_socket_aia(RISCVVirtState *s,
46
+void helper_wrs_nto(CPURISCVState *env)
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
+{
47
+{
238
+ uint32_t ret = 0;
48
+ if (env->virt_enabled && (env->priv == PRV_S || env->priv == PRV_U) &&
239
+
49
+ get_field(env->hstatus, HSTATUS_VTW) &&
240
+ while (BIT(ret) < count) {
50
+ !get_field(env->mstatus, MSTATUS_TW)) {
241
+ ret++;
51
+ riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC());
242
+ }
52
+ } else if (env->priv != PRV_M && get_field(env->mstatus, MSTATUS_TW)) {
243
+
53
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
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;
278
+ }
279
+ }
280
+ imsic_name = g_strdup_printf("/soc/imsics@%lx",
281
+ memmap[VIRT_IMSIC_M].base);
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
+ }
54
+ }
696
+}
55
+}
697
+
56
+
698
static char *virt_get_aia(Object *obj, Error **errp)
57
void helper_tlb_flush(CPURISCVState *env)
699
{
58
{
700
RISCVVirtState *s = RISCV_VIRT_MACHINE(obj);
59
CPUState *cs = env_cpu(env);
701
@@ -XXX,XX +XXX,XX @@ static char *virt_get_aia(Object *obj, Error **errp)
60
diff --git a/target/riscv/insn_trans/trans_rvzawrs.c.inc b/target/riscv/insn_trans/trans_rvzawrs.c.inc
702
case VIRT_AIA_TYPE_APLIC:
61
index XXXXXXX..XXXXXXX 100644
703
val = "aplic";
62
--- a/target/riscv/insn_trans/trans_rvzawrs.c.inc
704
break;
63
+++ b/target/riscv/insn_trans/trans_rvzawrs.c.inc
705
+ case VIRT_AIA_TYPE_APLIC_IMSIC:
64
@@ -XXX,XX +XXX,XX @@
706
+ val = "aplic-imsic";
65
* this program. If not, see <http://www.gnu.org/licenses/>.
707
+ break;
66
*/
708
default:
67
709
val = "none";
68
-static bool trans_wrs(DisasContext *ctx)
710
break;
69
+static bool trans_wrs_sto(DisasContext *ctx, arg_wrs_sto *a)
711
@@ -XXX,XX +XXX,XX @@ static void virt_set_aia(Object *obj, const char *val, Error **errp)
70
{
712
s->aia_type = VIRT_AIA_TYPE_NONE;
71
if (!ctx->cfg_ptr->ext_zawrs) {
713
} else if (!strcmp(val, "aplic")) {
72
return false;
714
s->aia_type = VIRT_AIA_TYPE_APLIC;
73
@@ -XXX,XX +XXX,XX @@ static bool trans_wrs(DisasContext *ctx)
715
+ } else if (!strcmp(val, "aplic-imsic")) {
74
return true;
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
}
75
}
724
76
725
@@ -XXX,XX +XXX,XX @@ static void virt_set_aclint(Object *obj, bool value, Error **errp)
77
-#define GEN_TRANS_WRS(insn) \
726
78
-static bool trans_ ## insn(DisasContext *ctx, arg_ ## insn *a) \
727
static void virt_machine_class_init(ObjectClass *oc, void *data)
79
-{ \
728
{
80
- (void)a; \
729
+ char str[128];
81
- return trans_wrs(ctx); \
730
MachineClass *mc = MACHINE_CLASS(oc);
82
-}
731
83
+static bool trans_wrs_nto(DisasContext *ctx, arg_wrs_nto *a)
732
mc->desc = "RISC-V VirtIO board";
84
+{
733
@@ -XXX,XX +XXX,XX @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
85
+ if (!ctx->cfg_ptr->ext_zawrs) {
734
object_class_property_set_description(oc, "aia",
86
+ return false;
735
"Set type of AIA interrupt "
87
+ }
736
"conttoller. Valid values are "
88
737
- "none, and aplic.");
89
-GEN_TRANS_WRS(wrs_nto)
738
+ "none, aplic, and aplic-imsic.");
90
-GEN_TRANS_WRS(wrs_sto)
91
+ /*
92
+ * Depending on the mode of execution, mstatus.TW and hstatus.VTW, wrs.nto
93
+ * should raise an exception when the implementation-specific bounded time
94
+ * limit has expired. Our time limit is zero, so we either return
95
+ * immediately, as does our implementation of wrs.sto, or raise an
96
+ * exception, as handled by the wrs.nto helper.
97
+ */
98
+#ifndef CONFIG_USER_ONLY
99
+ gen_helper_wrs_nto(tcg_env);
100
+#endif
739
+
101
+
740
+ object_class_property_add_str(oc, "aia-guests",
102
+ /* We only get here when helper_wrs_nto() doesn't raise an exception. */
741
+ virt_get_aia_guests,
103
+ return trans_wrs_sto(ctx, NULL);
742
+ virt_set_aia_guests);
104
+}
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
761
--
105
--
762
2.34.1
106
2.45.1
763
107
764
108
diff view generated by jsdifflib
1
From: Anup Patel <anup.patel@wdc.com>
1
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
2
2
3
The RISC-V AIA (Advanced Interrupt Architecture) defines a new
3
SBI defines a Debug Console extension "DBCN" that will, in time, replace
4
interrupt controller for MSIs (message signal interrupts) called
4
the legacy console putchar and getchar SBI extensions.
5
IMSIC (Incoming Message Signal Interrupt Controller). The IMSIC
5
6
is per-HART device and also suppport virtualizaiton of MSIs using
6
The appeal of the DBCN extension is that it allows multiple bytes to be
7
dedicated VS-level guest interrupt files.
7
read/written in the SBI console in a single SBI call.
8
8
9
This patch adds device emulation for RISC-V AIA IMSIC which
9
As far as KVM goes, the DBCN calls are forwarded by an in-kernel KVM
10
supports M-level, S-level, and VS-level MSIs.
10
module to userspace. But this will only happens if the KVM module
11
11
actually supports this SBI extension and we activate it.
12
Signed-off-by: Anup Patel <anup.patel@wdc.com>
12
13
Signed-off-by: Anup Patel <anup@brainfault.org>
13
We'll check for DBCN support during init time, checking if get-reg-list
14
Reviewed-by: Frank Chang <frank.chang@sifive.com>
14
is advertising KVM_RISCV_SBI_EXT_DBCN. In that case, we'll enable it via
15
Message-id: 20220204174700.534953-21-anup@brainfault.org
15
kvm_set_one_reg() during kvm_arch_init_vcpu().
16
17
Finally, change kvm_riscv_handle_sbi() to handle the incoming calls for
18
SBI_EXT_DBCN, reading and writing as required.
19
20
A simple KVM guest with 'earlycon=sbi', running in an emulated RISC-V
21
host, takes around 20 seconds to boot without using DBCN. With this
22
patch we're taking around 14 seconds to boot due to the speed-up in the
23
terminal output. There's no change in boot time if the guest isn't
24
using earlycon.
25
26
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
27
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
28
Message-ID: <20240425155012.581366-1-dbarboza@ventanamicro.com>
16
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
29
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
17
---
30
---
18
include/hw/intc/riscv_imsic.h | 68 ++++++
31
target/riscv/sbi_ecall_interface.h | 17 +++++
19
hw/intc/riscv_imsic.c | 448 ++++++++++++++++++++++++++++++++++
32
target/riscv/kvm/kvm-cpu.c | 111 +++++++++++++++++++++++++++++
20
hw/intc/Kconfig | 3 +
33
2 files changed, 128 insertions(+)
21
hw/intc/meson.build | 1 +
34
22
4 files changed, 520 insertions(+)
35
diff --git a/target/riscv/sbi_ecall_interface.h b/target/riscv/sbi_ecall_interface.h
23
create mode 100644 include/hw/intc/riscv_imsic.h
36
index XXXXXXX..XXXXXXX 100644
24
create mode 100644 hw/intc/riscv_imsic.c
37
--- a/target/riscv/sbi_ecall_interface.h
25
38
+++ b/target/riscv/sbi_ecall_interface.h
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 @@
39
@@ -XXX,XX +XXX,XX @@
32
+/*
40
33
+ * RISC-V IMSIC (Incoming Message Signal Interrupt Controller) interface
41
/* clang-format off */
34
+ *
42
35
+ * Copyright (c) 2021 Western Digital Corporation or its affiliates.
43
+#define SBI_SUCCESS 0
36
+ *
44
+#define SBI_ERR_FAILED -1
37
+ * This program is free software; you can redistribute it and/or modify it
45
+#define SBI_ERR_NOT_SUPPORTED -2
38
+ * under the terms and conditions of the GNU General Public License,
46
+#define SBI_ERR_INVALID_PARAM -3
39
+ * version 2 or later, as published by the Free Software Foundation.
47
+#define SBI_ERR_DENIED -4
40
+ *
48
+#define SBI_ERR_INVALID_ADDRESS -5
41
+ * This program is distributed in the hope it will be useful, but WITHOUT
49
+#define SBI_ERR_ALREADY_AVAILABLE -6
42
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
50
+#define SBI_ERR_ALREADY_STARTED -7
43
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
51
+#define SBI_ERR_ALREADY_STOPPED -8
44
+ * more details.
52
+#define SBI_ERR_NO_SHMEM -9
45
+ *
53
+
46
+ * You should have received a copy of the GNU General Public License along with
54
/* SBI Extension IDs */
47
+ * this program. If not, see <http://www.gnu.org/licenses/>.
55
#define SBI_EXT_0_1_SET_TIMER 0x0
48
+ */
56
#define SBI_EXT_0_1_CONSOLE_PUTCHAR 0x1
49
+
57
@@ -XXX,XX +XXX,XX @@
50
+#ifndef HW_RISCV_IMSIC_H
58
#define SBI_EXT_IPI 0x735049
51
+#define HW_RISCV_IMSIC_H
59
#define SBI_EXT_RFENCE 0x52464E43
52
+
60
#define SBI_EXT_HSM 0x48534D
53
+#include "hw/sysbus.h"
61
+#define SBI_EXT_DBCN 0x4442434E
54
+#include "qom/object.h"
62
55
+
63
/* SBI function IDs for BASE extension */
56
+#define TYPE_RISCV_IMSIC "riscv.imsic"
64
#define SBI_EXT_BASE_GET_SPEC_VERSION 0x0
57
+
65
@@ -XXX,XX +XXX,XX @@
58
+typedef struct RISCVIMSICState RISCVIMSICState;
66
#define SBI_EXT_HSM_HART_STOP 0x1
59
+DECLARE_INSTANCE_CHECKER(RISCVIMSICState, RISCV_IMSIC, TYPE_RISCV_IMSIC)
67
#define SBI_EXT_HSM_HART_GET_STATUS 0x2
60
+
68
61
+#define IMSIC_MMIO_PAGE_SHIFT 12
69
+/* SBI function IDs for DBCN extension */
62
+#define IMSIC_MMIO_PAGE_SZ (1UL << IMSIC_MMIO_PAGE_SHIFT)
70
+#define SBI_EXT_DBCN_CONSOLE_WRITE 0x0
63
+#define IMSIC_MMIO_SIZE(__num_pages) ((__num_pages) * IMSIC_MMIO_PAGE_SZ)
71
+#define SBI_EXT_DBCN_CONSOLE_READ 0x1
64
+
72
+#define SBI_EXT_DBCN_CONSOLE_WRITE_BYTE 0x2
65
+#define IMSIC_MMIO_HART_GUEST_MAX_BTIS 6
73
+
66
+#define IMSIC_MMIO_GROUP_MIN_SHIFT 24
74
#define SBI_HSM_HART_STATUS_STARTED 0x0
67
+
75
#define SBI_HSM_HART_STATUS_STOPPED 0x1
68
+#define IMSIC_HART_NUM_GUESTS(__guest_bits) \
76
#define SBI_HSM_HART_STATUS_START_PENDING 0x2
69
+ (1U << (__guest_bits))
77
diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
70
+#define IMSIC_HART_SIZE(__guest_bits) \
78
index XXXXXXX..XXXXXXX 100644
71
+ (IMSIC_HART_NUM_GUESTS(__guest_bits) * IMSIC_MMIO_PAGE_SZ)
79
--- a/target/riscv/kvm/kvm-cpu.c
72
+#define IMSIC_GROUP_NUM_HARTS(__hart_bits) \
80
+++ b/target/riscv/kvm/kvm-cpu.c
73
+ (1U << (__hart_bits))
81
@@ -XXX,XX +XXX,XX @@ static KVMCPUConfig kvm_v_vlenb = {
74
+#define IMSIC_GROUP_SIZE(__hart_bits, __guest_bits) \
82
KVM_REG_RISCV_VECTOR_CSR_REG(vlenb)
75
+ (IMSIC_GROUP_NUM_HARTS(__hart_bits) * IMSIC_HART_SIZE(__guest_bits))
83
};
76
+
84
77
+struct RISCVIMSICState {
85
+static KVMCPUConfig kvm_sbi_dbcn = {
78
+ /*< private >*/
86
+ .name = "sbi_dbcn",
79
+ SysBusDevice parent_obj;
87
+ .kvm_reg_id = KVM_REG_RISCV | KVM_REG_SIZE_U64 |
80
+ qemu_irq *external_irqs;
88
+ KVM_REG_RISCV_SBI_EXT | KVM_RISCV_SBI_EXT_DBCN
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
+};
89
+};
95
+
90
+
96
+DeviceState *riscv_imsic_create(hwaddr addr, uint32_t hartid, bool mmode,
91
static void kvm_riscv_update_cpu_cfg_isa_ext(RISCVCPU *cpu, CPUState *cs)
97
+ uint32_t num_pages, uint32_t num_ids);
92
{
98
+
93
CPURISCVState *env = &cpu->env;
99
+#endif
94
@@ -XXX,XX +XXX,XX @@ static int uint64_cmp(const void *a, const void *b)
100
diff --git a/hw/intc/riscv_imsic.c b/hw/intc/riscv_imsic.c
95
return 0;
101
new file mode 100644
96
}
102
index XXXXXXX..XXXXXXX
97
103
--- /dev/null
98
+static void kvm_riscv_check_sbi_dbcn_support(RISCVCPU *cpu,
104
+++ b/hw/intc/riscv_imsic.c
99
+ KVMScratchCPU *kvmcpu,
105
@@ -XXX,XX +XXX,XX @@
100
+ struct kvm_reg_list *reglist)
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
+{
101
+{
155
+ uint32_t i, max_irq, base;
102
+ struct kvm_reg_list *reg_search;
156
+
103
+
157
+ base = page * imsic->num_irqs;
104
+ reg_search = bsearch(&kvm_sbi_dbcn.kvm_reg_id, reglist->reg, reglist->n,
158
+ max_irq = (imsic->eithreshold[page] &&
105
+ sizeof(uint64_t), uint64_cmp);
159
+ (imsic->eithreshold[page] <= imsic->num_irqs)) ?
106
+
160
+ imsic->eithreshold[page] : imsic->num_irqs;
107
+ if (reg_search) {
161
+ for (i = 1; i < max_irq; i++) {
108
+ kvm_sbi_dbcn.supported = true;
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
+ }
109
+ }
178
+}
110
+}
179
+
111
+
180
+static int riscv_imsic_eidelivery_rmw(RISCVIMSICState *imsic, uint32_t page,
112
static void kvm_riscv_read_vlenb(RISCVCPU *cpu, KVMScratchCPU *kvmcpu,
181
+ target_ulong *val,
113
struct kvm_reg_list *reglist)
182
+ target_ulong new_val,
114
{
183
+ target_ulong wr_mask)
115
@@ -XXX,XX +XXX,XX @@ static void kvm_riscv_init_multiext_cfg(RISCVCPU *cpu, KVMScratchCPU *kvmcpu)
116
if (riscv_has_ext(&cpu->env, RVV)) {
117
kvm_riscv_read_vlenb(cpu, kvmcpu, reglist);
118
}
119
+
120
+ kvm_riscv_check_sbi_dbcn_support(cpu, kvmcpu, reglist);
121
}
122
123
static void riscv_init_kvm_registers(Object *cpu_obj)
124
@@ -XXX,XX +XXX,XX @@ static int kvm_vcpu_set_machine_ids(RISCVCPU *cpu, CPUState *cs)
125
return ret;
126
}
127
128
+static int kvm_vcpu_enable_sbi_dbcn(RISCVCPU *cpu, CPUState *cs)
184
+{
129
+{
185
+ target_ulong old_val = imsic->eidelivery[page];
130
+ target_ulong reg = 1;
186
+
131
+
187
+ if (val) {
132
+ if (!kvm_sbi_dbcn.supported) {
188
+ *val = old_val;
133
+ return 0;
189
+ }
134
+ }
190
+
135
+
191
+ wr_mask &= 0x1;
136
+ return kvm_set_one_reg(cs, kvm_sbi_dbcn.kvm_reg_id, &reg);
192
+ imsic->eidelivery[page] = (old_val & ~wr_mask) | (new_val & wr_mask);
193
+
194
+ riscv_imsic_update(imsic, page);
195
+ return 0;
196
+}
137
+}
197
+
138
+
198
+static int riscv_imsic_eithreshold_rmw(RISCVIMSICState *imsic, uint32_t page,
139
int kvm_arch_init_vcpu(CPUState *cs)
199
+ target_ulong *val,
140
{
200
+ target_ulong new_val,
141
int ret = 0;
201
+ target_ulong wr_mask)
142
@@ -XXX,XX +XXX,XX @@ int kvm_arch_init_vcpu(CPUState *cs)
143
kvm_riscv_update_cpu_misa_ext(cpu, cs);
144
kvm_riscv_update_cpu_cfg_isa_ext(cpu, cs);
145
146
+ ret = kvm_vcpu_enable_sbi_dbcn(cpu, cs);
147
+
148
return ret;
149
}
150
151
@@ -XXX,XX +XXX,XX @@ bool kvm_arch_stop_on_emulation_error(CPUState *cs)
152
return true;
153
}
154
155
+static void kvm_riscv_handle_sbi_dbcn(CPUState *cs, struct kvm_run *run)
202
+{
156
+{
203
+ target_ulong old_val = imsic->eithreshold[page];
157
+ g_autofree uint8_t *buf = NULL;
204
+
158
+ RISCVCPU *cpu = RISCV_CPU(cs);
205
+ if (val) {
159
+ target_ulong num_bytes;
206
+ *val = old_val;
160
+ uint64_t addr;
161
+ unsigned char ch;
162
+ int ret;
163
+
164
+ switch (run->riscv_sbi.function_id) {
165
+ case SBI_EXT_DBCN_CONSOLE_READ:
166
+ case SBI_EXT_DBCN_CONSOLE_WRITE:
167
+ num_bytes = run->riscv_sbi.args[0];
168
+
169
+ if (num_bytes == 0) {
170
+ run->riscv_sbi.ret[0] = SBI_SUCCESS;
171
+ run->riscv_sbi.ret[1] = 0;
172
+ break;
173
+ }
174
+
175
+ addr = run->riscv_sbi.args[1];
176
+
177
+ /*
178
+ * Handle the case where a 32 bit CPU is running in a
179
+ * 64 bit addressing env.
180
+ */
181
+ if (riscv_cpu_mxl(&cpu->env) == MXL_RV32) {
182
+ addr |= (uint64_t)run->riscv_sbi.args[2] << 32;
183
+ }
184
+
185
+ buf = g_malloc0(num_bytes);
186
+
187
+ if (run->riscv_sbi.function_id == SBI_EXT_DBCN_CONSOLE_READ) {
188
+ ret = qemu_chr_fe_read_all(serial_hd(0)->be, buf, num_bytes);
189
+ if (ret < 0) {
190
+ error_report("SBI_EXT_DBCN_CONSOLE_READ: error when "
191
+ "reading chardev");
192
+ exit(1);
193
+ }
194
+
195
+ cpu_physical_memory_write(addr, buf, ret);
196
+ } else {
197
+ cpu_physical_memory_read(addr, buf, num_bytes);
198
+
199
+ ret = qemu_chr_fe_write_all(serial_hd(0)->be, buf, num_bytes);
200
+ if (ret < 0) {
201
+ error_report("SBI_EXT_DBCN_CONSOLE_WRITE: error when "
202
+ "writing chardev");
203
+ exit(1);
204
+ }
205
+ }
206
+
207
+ run->riscv_sbi.ret[0] = SBI_SUCCESS;
208
+ run->riscv_sbi.ret[1] = ret;
209
+ break;
210
+ case SBI_EXT_DBCN_CONSOLE_WRITE_BYTE:
211
+ ch = run->riscv_sbi.args[0];
212
+ ret = qemu_chr_fe_write(serial_hd(0)->be, &ch, sizeof(ch));
213
+
214
+ if (ret < 0) {
215
+ error_report("SBI_EXT_DBCN_CONSOLE_WRITE_BYTE: error when "
216
+ "writing chardev");
217
+ exit(1);
218
+ }
219
+
220
+ run->riscv_sbi.ret[0] = SBI_SUCCESS;
221
+ run->riscv_sbi.ret[1] = 0;
222
+ break;
223
+ default:
224
+ run->riscv_sbi.ret[0] = SBI_ERR_NOT_SUPPORTED;
207
+ }
225
+ }
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
+}
226
+}
215
+
227
+
216
+static int riscv_imsic_topei_rmw(RISCVIMSICState *imsic, uint32_t page,
228
static int kvm_riscv_handle_sbi(CPUState *cs, struct kvm_run *run)
217
+ target_ulong *val, target_ulong new_val,
229
{
218
+ target_ulong wr_mask)
230
int ret = 0;
219
+{
231
@@ -XXX,XX +XXX,XX @@ static int kvm_riscv_handle_sbi(CPUState *cs, struct kvm_run *run)
220
+ uint32_t base, topei = riscv_imsic_topei(imsic, page);
232
}
221
+
233
ret = 0;
222
+ /* Read pending and enabled interrupt with highest priority */
234
break;
223
+ if (val) {
235
+ case SBI_EXT_DBCN:
224
+ *val = topei;
236
+ kvm_riscv_handle_sbi_dbcn(cs, run);
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;
237
+ break;
343
+ };
238
default:
344
+
239
qemu_log_mask(LOG_UNIMP,
345
+err:
240
"%s: un-handled SBI EXIT, specific reasons is %lu\n",
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
--
241
--
581
2.34.1
242
2.45.1
582
583
diff view generated by jsdifflib
1
From: Guo Ren <ren_guo@c-sky.com>
1
From: Cheng Yang <yangcheng.work@foxmail.com>
2
2
3
Highest bits of PTE has been used for svpbmt, ref: [1], [2], so we
3
Use qemu_fdt_setprop_u64() instead of qemu_fdt_setprop_cell()
4
need to ignore them. They cannot be a part of ppn.
4
to set the address of initrd in FDT to support 64-bit address.
5
5
6
1: The RISC-V Instruction Set Manual, Volume II: Privileged Architecture
6
Signed-off-by: Cheng Yang <yangcheng.work@foxmail.com>
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>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
15
Cc: Bin Meng <bmeng.cn@gmail.com>
8
Message-ID: <tencent_A4482251DD0890F312758FA6B33F60815609@qq.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>
9
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
19
---
10
---
20
target/riscv/cpu.h | 15 +++++++++++++++
11
hw/riscv/boot.c | 4 ++--
21
target/riscv/cpu_bits.h | 3 +++
12
1 file changed, 2 insertions(+), 2 deletions(-)
22
target/riscv/cpu_helper.c | 13 ++++++++++++-
23
3 files changed, 30 insertions(+), 1 deletion(-)
24
13
25
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
14
diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
26
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
27
--- a/target/riscv/cpu.h
16
--- a/hw/riscv/boot.c
28
+++ b/target/riscv/cpu.h
17
+++ b/hw/riscv/boot.c
29
@@ -XXX,XX +XXX,XX @@ struct RISCVCPUConfig {
18
@@ -XXX,XX +XXX,XX @@ static void riscv_load_initrd(MachineState *machine, uint64_t kernel_entry)
30
bool ext_counters;
19
/* Some RISC-V machines (e.g. opentitan) don't have a fdt. */
31
bool ext_ifencei;
20
if (fdt) {
32
bool ext_icsr;
21
end = start + size;
33
+ bool ext_svnapot;
22
- qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start", start);
34
+ bool ext_svpbmt;
23
- qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end", end);
35
bool ext_zfh;
24
+ qemu_fdt_setprop_u64(fdt, "/chosen", "linux,initrd-start", start);
36
bool ext_zfhmin;
25
+ qemu_fdt_setprop_u64(fdt, "/chosen", "linux,initrd-end", end);
37
bool ext_zve32f;
26
}
38
@@ -XXX,XX +XXX,XX @@ static inline int riscv_cpu_xlen(CPURISCVState *env)
39
return 16 << env->xl;
40
}
27
}
41
28
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
--
29
--
104
2.34.1
30
2.45.1
105
106
diff view generated by jsdifflib
1
From: Weiwei Li <liweiwei@iscas.ac.cn>
1
From: Clément Léger <cleger@rivosinc.com>
2
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
3
The current semihost exception number (16) is a reserved number (range
4
- add PTE_PBMT bit check for inner PTE
4
[16-17]). The upcoming double trap specification uses that number for
5
the double trap exception. Since the privileged spec (Table 22) defines
6
ranges for custom uses change the semihosting exception number to 63
7
which belongs to the range [48-63] in order to avoid any future
8
collisions with reserved exception.
5
9
6
Signed-off-by: Weiwei Li <liweiwei@iscas.ac.cn>
10
Signed-off-by: Clément Léger <cleger@rivosinc.com>
7
Signed-off-by: Junqiang Wang <wangjunqiang@iscas.ac.cn>
11
8
Reviewed-by: Anup Patel <anup@brainfault.org>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
12
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Message-Id: <20220204022658.18097-6-liweiwei@iscas.ac.cn>
13
Message-ID: <20240422135840.1959967-1-cleger@rivosinc.com>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
14
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
---
15
---
13
target/riscv/cpu_bits.h | 2 ++
16
target/riscv/cpu_bits.h | 2 +-
14
target/riscv/cpu.c | 1 +
17
1 file changed, 1 insertion(+), 1 deletion(-)
15
target/riscv/cpu_helper.c | 4 +++-
16
3 files changed, 6 insertions(+), 1 deletion(-)
17
18
18
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
19
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
19
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
20
--- a/target/riscv/cpu_bits.h
21
--- a/target/riscv/cpu_bits.h
21
+++ b/target/riscv/cpu_bits.h
22
+++ b/target/riscv/cpu_bits.h
22
@@ -XXX,XX +XXX,XX @@ typedef enum {
23
@@ -XXX,XX +XXX,XX @@ typedef enum RISCVException {
23
#define PTE_A 0x040 /* Accessed */
24
RISCV_EXCP_INST_PAGE_FAULT = 0xc, /* since: priv-1.10.0 */
24
#define PTE_D 0x080 /* Dirty */
25
RISCV_EXCP_LOAD_PAGE_FAULT = 0xd, /* since: priv-1.10.0 */
25
#define PTE_SOFT 0x300 /* Reserved for Software */
26
RISCV_EXCP_STORE_PAGE_FAULT = 0xf, /* since: priv-1.10.0 */
26
+#define PTE_PBMT 0x6000000000000000ULL /* Page-based memory types */
27
- RISCV_EXCP_SEMIHOST = 0x10,
27
#define PTE_N 0x8000000000000000ULL /* NAPOT translation */
28
RISCV_EXCP_INST_GUEST_PAGE_FAULT = 0x14,
28
+#define PTE_ATTR (PTE_N | PTE_PBMT) /* All attributes bits */
29
RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT = 0x15,
29
30
RISCV_EXCP_VIRT_INSTRUCTION_FAULT = 0x16,
30
/* Page table PPN shift amount */
31
RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT = 0x17,
31
#define PTE_PPN_SHIFT 10
32
+ RISCV_EXCP_SEMIHOST = 0x3f,
32
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
33
} RISCVException;
33
index XXXXXXX..XXXXXXX 100644
34
34
--- a/target/riscv/cpu.c
35
#define RISCV_EXCP_INT_FLAG 0x80000000
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
--
36
--
62
2.34.1
37
2.45.1
63
38
64
39
diff view generated by jsdifflib
1
From: Philipp Tomsich <philipp.tomsich@vrull.eu>
1
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
2
2
3
To split up the decoder into multiple functions (both to support
3
Running a KVM guest using a 6.9-rc3 kernel, in a 6.8 host that has zkr
4
vendor-specific opcodes in separate files and to simplify maintenance
4
enabled, will fail with a kernel oops SIGILL right at the start. The
5
of orthogonal extensions), this changes decode_op to iterate over a
5
reason is that we can't expose zkr without implementing the SEED CSR.
6
table of decoders predicated on guard functions.
6
Disabling zkr in the guest would be a workaround, but if the KVM doesn't
7
allow it we'll error out and never boot.
7
8
8
This commit only adds the new structure and the table, allowing for
9
In hindsight this is too strict. If we keep proceeding, despite not
9
the easy addition of additional decoders in the future.
10
disabling the extension in the KVM vcpu, we'll not add the extension in
11
the riscv,isa. The guest kernel will be unaware of the extension, i.e.
12
it doesn't matter if the KVM vcpu has it enabled underneath or not. So
13
it's ok to keep booting in this case.
10
14
11
Signed-off-by: Philipp Tomsich <philipp.tomsich@vrull.eu>
15
Change our current logic to not error out if we fail to disable an
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
extension in kvm_set_one_reg(), but show a warning and keep booting. It
13
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
17
is important to throw a warning because we must make the user aware that
14
Message-Id: <20220202005249.3566542-6-philipp.tomsich@vrull.eu>
18
the extension is still available in the vcpu, meaning that an
19
ill-behaved guest can ignore the riscv,isa settings and use the
20
extension.
21
22
The case we're handling happens with an EINVAL error code. If we fail to
23
disable the extension in KVM for any other reason, error out.
24
25
We'll also keep erroring out when we fail to enable an extension in KVM,
26
since adding the extension in riscv,isa at this point will cause a guest
27
malfunction because the extension isn't enabled in the vcpu.
28
29
Suggested-by: Andrew Jones <ajones@ventanamicro.com>
30
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
31
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
32
Cc: qemu-stable <qemu-stable@nongnu.org>
33
Message-ID: <20240422171425.333037-2-dbarboza@ventanamicro.com>
15
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
34
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
16
---
35
---
17
target/riscv/translate.c | 32 +++++++++++++++++++++++++++-----
36
target/riscv/kvm/kvm-cpu.c | 12 ++++++++----
18
1 file changed, 27 insertions(+), 5 deletions(-)
37
1 file changed, 8 insertions(+), 4 deletions(-)
19
38
20
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
39
diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
21
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
22
--- a/target/riscv/translate.c
41
--- a/target/riscv/kvm/kvm-cpu.c
23
+++ b/target/riscv/translate.c
42
+++ b/target/riscv/kvm/kvm-cpu.c
24
@@ -XXX,XX +XXX,XX @@ static inline bool has_ext(DisasContext *ctx, uint32_t ext)
43
@@ -XXX,XX +XXX,XX @@ static void kvm_riscv_update_cpu_cfg_isa_ext(RISCVCPU *cpu, CPUState *cs)
25
return ctx->misa_ext & ext;
44
reg = kvm_cpu_cfg_get(cpu, multi_ext_cfg);
26
}
45
ret = kvm_set_one_reg(cs, id, &reg);
27
46
if (ret != 0) {
28
+static bool always_true_p(DisasContext *ctx __attribute__((__unused__)))
47
- error_report("Unable to %s extension %s in KVM, error %d",
29
+{
48
- reg ? "enable" : "disable",
30
+ return true;
49
- multi_ext_cfg->name, ret);
31
+}
50
- exit(EXIT_FAILURE);
32
+
51
+ if (!reg && ret == -EINVAL) {
33
#ifdef TARGET_RISCV32
52
+ warn_report("KVM cannot disable extension %s",
34
#define get_xl(ctx) MXL_RV32
53
+ multi_ext_cfg->name);
35
#elif defined(CONFIG_USER_ONLY)
54
+ } else {
36
@@ -XXX,XX +XXX,XX @@ static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
55
+ error_report("Unable to enable extension %s in KVM, error %d",
37
56
+ multi_ext_cfg->name, ret);
38
static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
57
+ exit(EXIT_FAILURE);
39
{
40
- /* check for compressed insn */
41
+ /*
42
+ * A table with predicate (i.e., guard) functions and decoder functions
43
+ * that are tested in-order until a decoder matches onto the opcode.
44
+ */
45
+ static const struct {
46
+ bool (*guard_func)(DisasContext *);
47
+ bool (*decode_func)(DisasContext *, uint32_t);
48
+ } decoders[] = {
49
+ { always_true_p, decode_insn32 },
50
+ };
51
+
52
+ /* Check for compressed insn */
53
if (extract16(opcode, 0, 2) != 3) {
54
if (!has_ext(ctx, RVC)) {
55
gen_exception_illegal(ctx);
56
} else {
57
ctx->opcode = opcode;
58
ctx->pc_succ_insn = ctx->base.pc_next + 2;
59
- if (!decode_insn16(ctx, opcode)) {
60
- gen_exception_illegal(ctx);
61
+ if (decode_insn16(ctx, opcode)) {
62
+ return;
63
}
64
}
65
} else {
66
@@ -XXX,XX +XXX,XX @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
67
ctx->base.pc_next + 2));
68
ctx->opcode = opcode32;
69
ctx->pc_succ_insn = ctx->base.pc_next + 4;
70
- if (!decode_insn32(ctx, opcode32)) {
71
- gen_exception_illegal(ctx);
72
+
73
+ for (size_t i = 0; i < ARRAY_SIZE(decoders); ++i) {
74
+ if (decoders[i].guard_func(ctx) &&
75
+ decoders[i].decode_func(ctx, opcode32)) {
76
+ return;
77
+ }
58
+ }
78
}
59
}
79
}
60
}
80
+
81
+ gen_exception_illegal(ctx);
82
}
61
}
83
84
static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
85
--
62
--
86
2.34.1
63
2.45.1
87
88
diff view generated by jsdifflib
1
From: Anup Patel <anup.patel@wdc.com>
1
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
2
2
3
The AIA device emulation (such as AIA IMSIC) should be able to set
3
We're not setting (s/m)tval when triggering breakpoints of type 2
4
(or provide) AIA ireg read-modify-write callback for each privilege
4
(mcontrol) and 6 (mcontrol6). According to the debug spec section
5
level of a RISC-V HART.
5
5.7.12, "Match Control Type 6":
6
6
7
Signed-off-by: Anup Patel <anup.patel@wdc.com>
7
"The Privileged Spec says that breakpoint exceptions that occur on
8
Signed-off-by: Anup Patel <anup@brainfault.org>
8
instruction fetches, loads, or stores update the tval CSR with either
9
zero or the faulting virtual address. The faulting virtual address for
10
an mcontrol6 trigger with action = 0 is the address being accessed and
11
which caused that trigger to fire."
12
13
A similar text is also found in the Debug spec section 5.7.11 w.r.t.
14
mcontrol.
15
16
Note that what we're doing ATM is not violating the spec, but it's
17
simple enough to set mtval/stval and it makes life easier for any
18
software that relies on this info.
19
20
Given that we always use action = 0, save the faulting address for the
21
mcontrol and mcontrol6 trigger breakpoints into env->badaddr, which is
22
used as as scratch area for traps with address information. 'tval' is
23
then set during riscv_cpu_do_interrupt().
24
25
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
26
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Reviewed-by: Frank Chang <frank.chang@sifive.com>
27
Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
11
Message-id: 20220204174700.534953-9-anup@brainfault.org
28
Message-ID: <20240416230437.1869024-2-dbarboza@ventanamicro.com>
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
29
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
13
---
30
---
14
target/riscv/cpu.h | 23 +++++++++++++++++++++++
31
target/riscv/cpu_helper.c | 1 +
15
target/riscv/cpu_helper.c | 14 ++++++++++++++
32
target/riscv/debug.c | 3 +++
16
2 files changed, 37 insertions(+)
33
2 files changed, 4 insertions(+)
17
34
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
35
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
60
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
61
--- a/target/riscv/cpu_helper.c
37
--- a/target/riscv/cpu_helper.c
62
+++ b/target/riscv/cpu_helper.c
38
+++ b/target/riscv/cpu_helper.c
63
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(uint32_t),
39
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_do_interrupt(CPUState *cs)
64
env->rdtime_fn_arg = arg;
40
tval = env->bins;
65
}
41
break;
66
42
case RISCV_EXCP_BREAKPOINT:
67
+void riscv_cpu_set_aia_ireg_rmw_fn(CPURISCVState *env, uint32_t priv,
43
+ tval = env->badaddr;
68
+ int (*rmw_fn)(void *arg,
44
if (cs->watchpoint_hit) {
69
+ target_ulong reg,
45
tval = cs->watchpoint_hit->hitaddr;
70
+ target_ulong *val,
46
cs->watchpoint_hit = NULL;
71
+ target_ulong new_val,
47
diff --git a/target/riscv/debug.c b/target/riscv/debug.c
72
+ target_ulong write_mask),
48
index XXXXXXX..XXXXXXX 100644
73
+ void *rmw_fn_arg)
49
--- a/target/riscv/debug.c
74
+{
50
+++ b/target/riscv/debug.c
75
+ if (priv <= PRV_M) {
51
@@ -XXX,XX +XXX,XX @@ bool riscv_cpu_debug_check_breakpoint(CPUState *cs)
76
+ env->aia_ireg_rmw_fn[priv] = rmw_fn;
52
if ((ctrl & TYPE2_EXEC) && (bp->pc == pc)) {
77
+ env->aia_ireg_rmw_fn_arg[priv] = rmw_fn_arg;
53
/* check U/S/M bit against current privilege level */
78
+ }
54
if ((ctrl >> 3) & BIT(env->priv)) {
79
+}
55
+ env->badaddr = pc;
80
+
56
return true;
81
void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv)
57
}
82
{
58
}
83
if (newpriv > PRV_M) {
59
@@ -XXX,XX +XXX,XX @@ bool riscv_cpu_debug_check_breakpoint(CPUState *cs)
60
if (env->virt_enabled) {
61
/* check VU/VS bit against current privilege level */
62
if ((ctrl >> 23) & BIT(env->priv)) {
63
+ env->badaddr = pc;
64
return true;
65
}
66
} else {
67
/* check U/S/M bit against current privilege level */
68
if ((ctrl >> 3) & BIT(env->priv)) {
69
+ env->badaddr = pc;
70
return true;
71
}
72
}
84
--
73
--
85
2.34.1
74
2.45.1
86
87
diff view generated by jsdifflib
1
From: Philipp Tomsich <philipp.tomsich@vrull.eu>
1
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
2
2
3
As the number of extensions is growing, copying them individiually
3
Privileged spec section 4.1.9 mentions:
4
into the DisasContext will scale less and less... instead we populate
5
a pointer to the RISCVCPUConfig structure in the DisasContext.
6
4
7
This adds an extra indirection when checking for the availability of
5
"When a trap is taken into S-mode, stval is written with
8
an extension (compared to copying the fields into DisasContext).
6
exception-specific information to assist software in handling the trap.
9
While not a performance problem today, we can always (shallow) copy
7
(...)
10
the entire structure into the DisasContext (instead of putting a
11
pointer to it) if this is ever deemed necessary.
12
8
13
Signed-off-by: Philipp Tomsich <philipp.tomsich@vrull.eu>
9
If stval is written with a nonzero value when a breakpoint,
10
address-misaligned, access-fault, or page-fault exception occurs on an
11
instruction fetch, load, or store, then stval will contain the faulting
12
virtual address."
13
14
A similar text is found for mtval in section 3.1.16.
15
16
Setting mtval/stval in this scenario is optional, but some softwares read
17
these regs when handling ebreaks.
18
19
Write 'badaddr' in all ebreak breakpoints to write the appropriate
20
'tval' during riscv_do_cpu_interrrupt().
21
22
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
14
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
23
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
15
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
24
Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
25
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-Id: <20220202005249.3566542-3-philipp.tomsich@vrull.eu>
26
Message-ID: <20240416230437.1869024-3-dbarboza@ventanamicro.com>
18
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
27
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
19
---
28
---
20
target/riscv/translate.c | 2 ++
29
target/riscv/insn_trans/trans_privileged.c.inc | 2 ++
21
1 file changed, 2 insertions(+)
30
1 file changed, 2 insertions(+)
22
31
23
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
32
diff --git a/target/riscv/insn_trans/trans_privileged.c.inc b/target/riscv/insn_trans/trans_privileged.c.inc
24
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
25
--- a/target/riscv/translate.c
34
--- a/target/riscv/insn_trans/trans_privileged.c.inc
26
+++ b/target/riscv/translate.c
35
+++ b/target/riscv/insn_trans/trans_privileged.c.inc
27
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
36
@@ -XXX,XX +XXX,XX @@ static bool trans_ebreak(DisasContext *ctx, arg_ebreak *a)
28
int frm;
37
if (pre == 0x01f01013 && ebreak == 0x00100073 && post == 0x40705013) {
29
RISCVMXL ol;
38
generate_exception(ctx, RISCV_EXCP_SEMIHOST);
30
bool virt_enabled;
39
} else {
31
+ const RISCVCPUConfig *cfg_ptr;
40
+ tcg_gen_st_tl(tcg_constant_tl(ebreak_addr), tcg_env,
32
bool ext_ifencei;
41
+ offsetof(CPURISCVState, badaddr));
33
bool ext_zfh;
42
generate_exception(ctx, RISCV_EXCP_BREAKPOINT);
34
bool ext_zfhmin;
43
}
35
@@ -XXX,XX +XXX,XX @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
44
return true;
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
--
45
--
44
2.34.1
46
2.45.1
45
46
diff view generated by jsdifflib
1
From: Anup Patel <anup.patel@wdc.com>
1
From: Jason Chien <jason.chien@sifive.com>
2
2
3
The hgeie and hgeip CSRs are required for emulating an external
3
Add support for Zve32x extension and replace some checks for Zve32f with
4
interrupt controller capable of injecting virtual external interrupt
4
Zve32x, since Zve32f depends on Zve32x.
5
to Guest/VM running at VS-level.
6
5
7
Signed-off-by: Anup Patel <anup.patel@wdc.com>
6
Signed-off-by: Jason Chien <jason.chien@sifive.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>
7
Reviewed-by: Frank Chang <frank.chang@sifive.com>
11
Message-id: 20220204174700.534953-4-anup@brainfault.org
8
Reviewed-by: Max Chou <max.chou@sifive.com>
9
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
10
Message-ID: <20240328022343.6871-2-jason.chien@sifive.com>
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
13
---
12
---
14
target/riscv/cpu.h | 5 +++
13
target/riscv/cpu_cfg.h | 1 +
15
target/riscv/cpu_bits.h | 1 +
14
target/riscv/cpu.c | 2 ++
16
target/riscv/cpu.c | 67 +++++++++++++++++++++++++++------------
15
target/riscv/cpu_helper.c | 2 +-
17
target/riscv/cpu_helper.c | 37 +++++++++++++++++++--
16
target/riscv/csr.c | 2 +-
18
target/riscv/csr.c | 43 +++++++++++++++++--------
17
target/riscv/tcg/tcg-cpu.c | 16 ++++++++--------
19
target/riscv/machine.c | 6 ++--
18
target/riscv/insn_trans/trans_rvv.c.inc | 4 ++--
20
6 files changed, 121 insertions(+), 38 deletions(-)
19
6 files changed, 15 insertions(+), 12 deletions(-)
21
20
22
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
21
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
23
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
24
--- a/target/riscv/cpu.h
23
--- a/target/riscv/cpu_cfg.h
25
+++ b/target/riscv/cpu.h
24
+++ b/target/riscv/cpu_cfg.h
26
@@ -XXX,XX +XXX,XX @@ struct CPURISCVState {
25
@@ -XXX,XX +XXX,XX @@ struct RISCVCPUConfig {
27
target_ulong priv;
26
bool ext_zhinx;
28
/* This contains QEMU specific information about the virt state. */
27
bool ext_zhinxmin;
29
target_ulong virt;
28
bool ext_zve32f;
30
+ target_ulong geilen;
29
+ bool ext_zve32x;
31
target_ulong resetvec;
30
bool ext_zve64f;
32
31
bool ext_zve64d;
33
target_ulong mhartid;
32
bool ext_zvbb;
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
33
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
65
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
66
--- a/target/riscv/cpu.c
35
--- a/target/riscv/cpu.c
67
+++ b/target/riscv/cpu.c
36
+++ b/target/riscv/cpu.c
68
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
37
@@ -XXX,XX +XXX,XX @@ const RISCVIsaExtData isa_edata_arr[] = {
69
static void riscv_cpu_set_irq(void *opaque, int irq, int level)
38
ISA_EXT_DATA_ENTRY(zvbb, PRIV_VERSION_1_12_0, ext_zvbb),
70
{
39
ISA_EXT_DATA_ENTRY(zvbc, PRIV_VERSION_1_12_0, ext_zvbc),
71
RISCVCPU *cpu = RISCV_CPU(opaque);
40
ISA_EXT_DATA_ENTRY(zve32f, PRIV_VERSION_1_10_0, ext_zve32f),
72
+ CPURISCVState *env = &cpu->env;
41
+ ISA_EXT_DATA_ENTRY(zve32x, PRIV_VERSION_1_10_0, ext_zve32x),
73
42
ISA_EXT_DATA_ENTRY(zve64f, PRIV_VERSION_1_10_0, ext_zve64f),
74
- switch (irq) {
43
ISA_EXT_DATA_ENTRY(zve64d, PRIV_VERSION_1_10_0, ext_zve64d),
75
- case IRQ_U_SOFT:
44
ISA_EXT_DATA_ENTRY(zvfbfmin, PRIV_VERSION_1_12_0, ext_zvfbfmin),
76
- case IRQ_S_SOFT:
45
@@ -XXX,XX +XXX,XX @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
77
- case IRQ_VS_SOFT:
46
MULTI_EXT_CFG_BOOL("zfh", ext_zfh, false),
78
- case IRQ_M_SOFT:
47
MULTI_EXT_CFG_BOOL("zfhmin", ext_zfhmin, false),
79
- case IRQ_U_TIMER:
48
MULTI_EXT_CFG_BOOL("zve32f", ext_zve32f, false),
80
- case IRQ_S_TIMER:
49
+ MULTI_EXT_CFG_BOOL("zve32x", ext_zve32x, false),
81
- case IRQ_VS_TIMER:
50
MULTI_EXT_CFG_BOOL("zve64f", ext_zve64f, false),
82
- case IRQ_M_TIMER:
51
MULTI_EXT_CFG_BOOL("zve64d", ext_zve64d, false),
83
- case IRQ_U_EXT:
52
MULTI_EXT_CFG_BOOL("zvfbfmin", ext_zvfbfmin, false),
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
53
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
152
index XXXXXXX..XXXXXXX 100644
54
index XXXXXXX..XXXXXXX 100644
153
--- a/target/riscv/cpu_helper.c
55
--- a/target/riscv/cpu_helper.c
154
+++ b/target/riscv/cpu_helper.c
56
+++ b/target/riscv/cpu_helper.c
155
@@ -XXX,XX +XXX,XX @@ static int riscv_cpu_local_irq_pending(CPURISCVState *env)
57
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
156
target_ulong mstatus_mie = get_field(env->mstatus, MSTATUS_MIE);
58
*pc = env->xl == MXL_RV32 ? env->pc & UINT32_MAX : env->pc;
157
target_ulong mstatus_sie = get_field(env->mstatus, MSTATUS_SIE);
59
*cs_base = 0;
158
60
159
- target_ulong pending = env->mip & env->mie;
61
- if (cpu->cfg.ext_zve32f) {
160
+ target_ulong vsgemask =
62
+ if (cpu->cfg.ext_zve32x) {
161
+ (target_ulong)1 << get_field(env->hstatus, HSTATUS_VGEIN);
63
/*
162
+ target_ulong vsgein = (env->hgeip & vsgemask) ? MIP_VSEIP : 0;
64
* If env->vl equals to VLMAX, we can use generic vector operation
163
+
65
* expanders (GVEC) to accerlate the vector operations.
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
66
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
223
index XXXXXXX..XXXXXXX 100644
67
index XXXXXXX..XXXXXXX 100644
224
--- a/target/riscv/csr.c
68
--- a/target/riscv/csr.c
225
+++ b/target/riscv/csr.c
69
+++ b/target/riscv/csr.c
226
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_mip(CPURISCVState *env, int csrno,
70
@@ -XXX,XX +XXX,XX @@ static RISCVException fs(CPURISCVState *env, int csrno)
227
RISCVCPU *cpu = env_archcpu(env);
71
228
/* Allow software control of delegable interrupts not claimed by hardware */
72
static RISCVException vs(CPURISCVState *env, int csrno)
229
target_ulong mask = write_mask & delegable_ints & ~env->miclaim;
73
{
230
- uint32_t old_mip;
74
- if (riscv_cpu_cfg(env)->ext_zve32f) {
231
+ uint32_t gin, old_mip;
75
+ if (riscv_cpu_cfg(env)->ext_zve32x) {
232
76
#if !defined(CONFIG_USER_ONLY)
233
if (mask) {
77
if (!env->debugger && !riscv_cpu_vector_enabled(env)) {
234
old_mip = riscv_cpu_update_mip(cpu, mask, (new_value & mask));
78
return RISCV_EXCP_ILLEGAL_INST;
235
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_mip(CPURISCVState *env, int csrno,
79
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
236
old_mip = env->mip;
80
index XXXXXXX..XXXXXXX 100644
81
--- a/target/riscv/tcg/tcg-cpu.c
82
+++ b/target/riscv/tcg/tcg-cpu.c
83
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
84
return;
237
}
85
}
238
86
239
+ if (csrno != CSR_HVIP) {
87
- if (cpu->cfg.ext_zve32f && !riscv_has_ext(env, RVF)) {
240
+ gin = get_field(env->hstatus, HSTATUS_VGEIN);
88
- error_setg(errp, "Zve32f/Zve64f extensions require F extension");
241
+ old_mip |= (env->hgeip & ((target_ulong)1 << gin)) ? MIP_VSEIP : 0;
89
- return;
242
+ }
90
+ /* The Zve32f extension depends on the Zve32x extension */
243
+
91
+ if (cpu->cfg.ext_zve32f) {
244
if (ret_value) {
92
+ if (!riscv_has_ext(env, RVF)) {
245
*ret_value = old_mip;
93
+ error_setg(errp, "Zve32f/Zve64f extensions require F extension");
94
+ return;
95
+ }
96
+ cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve32x), true);
246
}
97
}
247
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_vsip(CPURISCVState *env, int csrno,
98
248
target_ulong new_value, target_ulong write_mask)
99
if (cpu->cfg.ext_zvfh) {
100
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
101
cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvbc), true);
102
}
103
104
- /*
105
- * In principle Zve*x would also suffice here, were they supported
106
- * in qemu
107
- */
108
if ((cpu->cfg.ext_zvbb || cpu->cfg.ext_zvkb || cpu->cfg.ext_zvkg ||
109
cpu->cfg.ext_zvkned || cpu->cfg.ext_zvknha || cpu->cfg.ext_zvksed ||
110
- cpu->cfg.ext_zvksh) && !cpu->cfg.ext_zve32f) {
111
+ cpu->cfg.ext_zvksh) && !cpu->cfg.ext_zve32x) {
112
error_setg(errp,
113
"Vector crypto extensions require V or Zve* extensions");
114
return;
115
diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc
116
index XXXXXXX..XXXXXXX 100644
117
--- a/target/riscv/insn_trans/trans_rvv.c.inc
118
+++ b/target/riscv/insn_trans/trans_rvv.c.inc
119
@@ -XXX,XX +XXX,XX @@ static bool do_vsetvl(DisasContext *s, int rd, int rs1, TCGv s2)
249
{
120
{
250
/* Shift the S bits to their VS bit location in mip */
121
TCGv s1, dst;
251
- int ret = rmw_mip(env, 0, ret_value, new_value << 1,
122
252
+ int ret = rmw_mip(env, csrno, ret_value, new_value << 1,
123
- if (!require_rvv(s) || !s->cfg_ptr->ext_zve32f) {
253
(write_mask << 1) & vsip_writable_mask & env->hideleg);
124
+ if (!require_rvv(s) || !s->cfg_ptr->ext_zve32x) {
254
125
return false;
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
}
126
}
264
127
265
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_hvip(CPURISCVState *env, int csrno,
128
@@ -XXX,XX +XXX,XX @@ static bool do_vsetivli(DisasContext *s, int rd, TCGv s1, TCGv s2)
266
target_ulong *ret_value,
267
target_ulong new_value, target_ulong write_mask)
268
{
129
{
269
- int ret = rmw_mip(env, 0, ret_value, new_value,
130
TCGv dst;
270
+ int ret = rmw_mip(env, csrno, ret_value, new_value,
131
271
write_mask & hvip_writable_mask);
132
- if (!require_rvv(s) || !s->cfg_ptr->ext_zve32f) {
272
133
+ if (!require_rvv(s) || !s->cfg_ptr->ext_zve32x) {
273
if (ret_value) {
134
return false;
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
}
135
}
296
return RISCV_EXCP_NONE;
136
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
--
137
--
367
2.34.1
138
2.45.1
368
369
diff view generated by jsdifflib
1
From: Anup Patel <anup.patel@wdc.com>
1
From: Jason Chien <jason.chien@sifive.com>
2
2
3
The machine or device emulation should be able to force set certain
3
Add support for Zve64x extension. Enabling Zve64f enables Zve64x and
4
CPU features because:
4
enabling Zve64x enables Zve32x according to their dependency.
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
5
10
Signed-off-by: Anup Patel <anup.patel@wdc.com>
6
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2107
11
Signed-off-by: Anup Patel <anup@brainfault.org>
7
Signed-off-by: Jason Chien <jason.chien@sifive.com>
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>
8
Reviewed-by: Frank Chang <frank.chang@sifive.com>
15
Message-id: 20220204174700.534953-6-anup@brainfault.org
9
Reviewed-by: Max Chou <max.chou@sifive.com>
10
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
11
Message-ID: <20240328022343.6871-3-jason.chien@sifive.com>
16
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
17
---
13
---
18
target/riscv/cpu.h | 5 +++++
14
target/riscv/cpu_cfg.h | 1 +
19
target/riscv/cpu.c | 11 +++--------
15
target/riscv/cpu.c | 2 ++
20
2 files changed, 8 insertions(+), 8 deletions(-)
16
target/riscv/tcg/tcg-cpu.c | 17 +++++++++++------
17
3 files changed, 14 insertions(+), 6 deletions(-)
21
18
22
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
19
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
23
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
24
--- a/target/riscv/cpu.h
21
--- a/target/riscv/cpu_cfg.h
25
+++ b/target/riscv/cpu.h
22
+++ b/target/riscv/cpu_cfg.h
26
@@ -XXX,XX +XXX,XX @@ static inline bool riscv_feature(CPURISCVState *env, int feature)
23
@@ -XXX,XX +XXX,XX @@ struct RISCVCPUConfig {
27
return env->features & (1ULL << feature);
24
bool ext_zve32x;
28
}
25
bool ext_zve64f;
29
26
bool ext_zve64d;
30
+static inline void riscv_set_feature(CPURISCVState *env, int feature)
27
+ bool ext_zve64x;
31
+{
28
bool ext_zvbb;
32
+ env->features |= (1ULL << feature);
29
bool ext_zvbc;
33
+}
30
bool ext_zvkb;
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
31
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
39
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
40
--- a/target/riscv/cpu.c
33
--- a/target/riscv/cpu.c
41
+++ b/target/riscv/cpu.c
34
+++ b/target/riscv/cpu.c
42
@@ -XXX,XX +XXX,XX @@ static void set_vext_version(CPURISCVState *env, int vext_ver)
35
@@ -XXX,XX +XXX,XX @@ const RISCVIsaExtData isa_edata_arr[] = {
43
env->vext_ver = vext_ver;
36
ISA_EXT_DATA_ENTRY(zve32x, PRIV_VERSION_1_10_0, ext_zve32x),
44
}
37
ISA_EXT_DATA_ENTRY(zve64f, PRIV_VERSION_1_10_0, ext_zve64f),
45
38
ISA_EXT_DATA_ENTRY(zve64d, PRIV_VERSION_1_10_0, ext_zve64d),
46
-static void set_feature(CPURISCVState *env, int feature)
39
+ ISA_EXT_DATA_ENTRY(zve64x, PRIV_VERSION_1_10_0, ext_zve64x),
47
-{
40
ISA_EXT_DATA_ENTRY(zvfbfmin, PRIV_VERSION_1_12_0, ext_zvfbfmin),
48
- env->features |= (1ULL << feature);
41
ISA_EXT_DATA_ENTRY(zvfbfwma, PRIV_VERSION_1_12_0, ext_zvfbfwma),
49
-}
42
ISA_EXT_DATA_ENTRY(zvfh, PRIV_VERSION_1_12_0, ext_zvfh),
50
-
43
@@ -XXX,XX +XXX,XX @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
51
static void set_resetvec(CPURISCVState *env, target_ulong resetvec)
44
MULTI_EXT_CFG_BOOL("zve32x", ext_zve32x, false),
52
{
45
MULTI_EXT_CFG_BOOL("zve64f", ext_zve64f, false),
53
#ifndef CONFIG_USER_ONLY
46
MULTI_EXT_CFG_BOOL("zve64d", ext_zve64d, false),
54
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
47
+ MULTI_EXT_CFG_BOOL("zve64x", ext_zve64x, false),
48
MULTI_EXT_CFG_BOOL("zvfbfmin", ext_zvfbfmin, false),
49
MULTI_EXT_CFG_BOOL("zvfbfwma", ext_zvfbfwma, false),
50
MULTI_EXT_CFG_BOOL("zvfh", ext_zvfh, false),
51
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/riscv/tcg/tcg-cpu.c
54
+++ b/target/riscv/tcg/tcg-cpu.c
55
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
56
57
/* The Zve64d extension depends on the Zve64f extension */
58
if (cpu->cfg.ext_zve64d) {
59
+ if (!riscv_has_ext(env, RVD)) {
60
+ error_setg(errp, "Zve64d/V extensions require D extension");
61
+ return;
62
+ }
63
cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve64f), true);
55
}
64
}
56
65
57
if (cpu->cfg.mmu) {
66
- /* The Zve64f extension depends on the Zve32f extension */
58
- set_feature(env, RISCV_FEATURE_MMU);
67
+ /* The Zve64f extension depends on the Zve64x and Zve32f extensions */
59
+ riscv_set_feature(env, RISCV_FEATURE_MMU);
68
if (cpu->cfg.ext_zve64f) {
69
+ cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve64x), true);
70
cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve32f), true);
60
}
71
}
61
72
62
if (cpu->cfg.pmp) {
73
- if (cpu->cfg.ext_zve64d && !riscv_has_ext(env, RVD)) {
63
- set_feature(env, RISCV_FEATURE_PMP);
74
- error_setg(errp, "Zve64d/V extensions require D extension");
64
+ riscv_set_feature(env, RISCV_FEATURE_PMP);
75
- return;
65
76
+ /* The Zve64x extension depends on the Zve32x extension */
66
/*
77
+ if (cpu->cfg.ext_zve64x) {
67
* Enhanced PMP should only be available
78
+ cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve32x), true);
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
}
79
}
75
80
81
/* The Zve32f extension depends on the Zve32x extension */
82
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
83
return;
84
}
85
86
- if ((cpu->cfg.ext_zvbc || cpu->cfg.ext_zvknhb) && !cpu->cfg.ext_zve64f) {
87
+ if ((cpu->cfg.ext_zvbc || cpu->cfg.ext_zvknhb) && !cpu->cfg.ext_zve64x) {
88
error_setg(
89
errp,
90
- "Zvbc and Zvknhb extensions require V or Zve64{f,d} extensions");
91
+ "Zvbc and Zvknhb extensions require V or Zve64x extensions");
92
return;
93
}
94
76
--
95
--
77
2.34.1
96
2.45.1
78
79
diff view generated by jsdifflib
1
From: Frédéric Pétrot <frederic.petrot@univ-grenoble-alpes.fr>
1
From: Jason Chien <jason.chien@sifive.com>
2
2
3
The addition of uxl support in gdbstub adds a few checks on the maximum
3
In current implementation, the gdbstub allows reading vector registers
4
register length, but omitted MXL_RV128, an experimental feature.
4
only if V extension is supported. However, all vector extensions and
5
This patch makes rv128 react as rv64, as previously.
5
vector crypto extensions have the vector registers and they all depend
6
on Zve32x. The gdbstub should check for Zve32x instead.
6
7
7
Signed-off-by: Frédéric Pétrot <frederic.petrot@univ-grenoble-alpes.fr>
8
Signed-off-by: Jason Chien <jason.chien@sifive.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Frank Chang <frank.chang@sifive.com>
9
Reviewed-by: LIU Zhiwei <zhiwei_liu@c-sky.com>
10
Reviewed-by: Max Chou <max.chou@sifive.com>
10
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
11
Message-ID: <20240328022343.6871-4-jason.chien@sifive.com>
11
Message-id: 20220124202456.420258-1-frederic.petrot@univ-grenoble-alpes.fr
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
13
---
13
---
14
target/riscv/cpu.c | 3 +--
14
target/riscv/gdbstub.c | 2 +-
15
target/riscv/gdbstub.c | 3 +++
15
1 file changed, 1 insertion(+), 1 deletion(-)
16
2 files changed, 4 insertions(+), 2 deletions(-)
17
16
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
17
diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
34
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
35
--- a/target/riscv/gdbstub.c
19
--- a/target/riscv/gdbstub.c
36
+++ b/target/riscv/gdbstub.c
20
+++ 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)
21
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
54
1, "riscv-32bit-virtual.xml", 0);
22
gdb_find_static_feature("riscv-32bit-fpu.xml"),
55
break;
23
0);
56
case MXL_RV64:
24
}
57
+ case MXL_RV128:
25
- if (env->misa_ext & RVV) {
58
gdb_register_coprocessor(cs, riscv_gdb_get_virtual,
26
+ if (cpu->cfg.ext_zve32x) {
59
riscv_gdb_set_virtual,
27
gdb_register_coprocessor(cs, riscv_gdb_get_vector,
60
1, "riscv-64bit-virtual.xml", 0);
28
riscv_gdb_set_vector,
29
ricsv_gen_dynamic_vector_feature(cs, cs->gdb_num_regs),
61
--
30
--
62
2.34.1
31
2.45.1
63
64
diff view generated by jsdifflib
Deleted patch
1
From: Philipp Tomsich <philipp.tomsich@vrull.eu>
2
1
3
Signed-off-by: Philipp Tomsich <philipp.tomsich@vrull.eu>
4
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
5
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-Id: <20220202005249.3566542-2-philipp.tomsich@vrull.eu>
8
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
9
---
10
target/riscv/cpu.h | 78 ++++++++++++++++++++++++----------------------
11
1 file changed, 41 insertions(+), 37 deletions(-)
12
13
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/riscv/cpu.h
16
+++ b/target/riscv/cpu.h
17
@@ -XXX,XX +XXX,XX @@ struct RISCVCPUClass {
18
DeviceReset parent_reset;
19
};
20
21
+struct RISCVCPUConfig {
22
+ bool ext_i;
23
+ bool ext_e;
24
+ bool ext_g;
25
+ bool ext_m;
26
+ bool ext_a;
27
+ bool ext_f;
28
+ bool ext_d;
29
+ bool ext_c;
30
+ bool ext_s;
31
+ bool ext_u;
32
+ bool ext_h;
33
+ bool ext_j;
34
+ bool ext_v;
35
+ bool ext_zba;
36
+ bool ext_zbb;
37
+ bool ext_zbc;
38
+ bool ext_zbs;
39
+ bool ext_counters;
40
+ bool ext_ifencei;
41
+ bool ext_icsr;
42
+ bool ext_zfh;
43
+ bool ext_zfhmin;
44
+ bool ext_zve32f;
45
+ bool ext_zve64f;
46
+
47
+ char *priv_spec;
48
+ char *user_spec;
49
+ char *bext_spec;
50
+ char *vext_spec;
51
+ uint16_t vlen;
52
+ uint16_t elen;
53
+ bool mmu;
54
+ bool pmp;
55
+ bool epmp;
56
+ uint64_t resetvec;
57
+};
58
+
59
+typedef struct RISCVCPUConfig RISCVCPUConfig;
60
+
61
/**
62
* RISCVCPU:
63
* @env: #CPURISCVState
64
@@ -XXX,XX +XXX,XX @@ struct RISCVCPU {
65
char *dyn_vreg_xml;
66
67
/* Configuration Settings */
68
- struct {
69
- bool ext_i;
70
- bool ext_e;
71
- bool ext_g;
72
- bool ext_m;
73
- bool ext_a;
74
- bool ext_f;
75
- bool ext_d;
76
- bool ext_c;
77
- bool ext_s;
78
- bool ext_u;
79
- bool ext_h;
80
- bool ext_j;
81
- bool ext_v;
82
- bool ext_zba;
83
- bool ext_zbb;
84
- bool ext_zbc;
85
- bool ext_zbs;
86
- bool ext_counters;
87
- bool ext_ifencei;
88
- bool ext_icsr;
89
- bool ext_zfh;
90
- bool ext_zfhmin;
91
- bool ext_zve32f;
92
- bool ext_zve64f;
93
-
94
- char *priv_spec;
95
- char *user_spec;
96
- char *bext_spec;
97
- char *vext_spec;
98
- uint16_t vlen;
99
- uint16_t elen;
100
- bool mmu;
101
- bool pmp;
102
- bool epmp;
103
- uint64_t resetvec;
104
- } cfg;
105
+ RISCVCPUConfig cfg;
106
};
107
108
static inline int riscv_has_ext(CPURISCVState *env, target_ulong ext)
109
--
110
2.34.1
111
112
diff view generated by jsdifflib
1
From: LIU Zhiwei <zhiwei_liu@c-sky.com>
1
From: Huang Tao <eric.huang@linux.alibaba.com>
2
2
3
The guest should be able to set the vill bit as part of vsetvl.
3
In RVV and vcrypto instructions, the masked and tail elements are set to 1s
4
using vext_set_elems_1s function if the vma/vta bit is set. It is the element
5
agnostic policy.
4
6
5
Currently we may set env->vill to 1 in the vsetvl helper, but there
7
However, this function can't deal the big endian situation. This patch fixes
6
is nowhere that we set it to 0, so once it transitions to 1 it's stuck
8
the problem by adding handling of such case.
7
there until the system is reset.
8
9
9
Signed-off-by: LIU Zhiwei <zhiwei_liu@c-sky.com>
10
Signed-off-by: Huang Tao <eric.huang@linux.alibaba.com>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
12
Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
12
Message-Id: <20220201064601.41143-1-zhiwei_liu@c-sky.com>
13
Cc: qemu-stable <qemu-stable@nongnu.org>
14
Message-ID: <20240325021654.6594-1-eric.huang@linux.alibaba.com>
13
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
15
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
14
---
16
---
15
target/riscv/vector_helper.c | 1 +
17
target/riscv/vector_internals.c | 22 ++++++++++++++++++++++
16
1 file changed, 1 insertion(+)
18
1 file changed, 22 insertions(+)
17
19
18
diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
20
diff --git a/target/riscv/vector_internals.c b/target/riscv/vector_internals.c
19
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
20
--- a/target/riscv/vector_helper.c
22
--- a/target/riscv/vector_internals.c
21
+++ b/target/riscv/vector_helper.c
23
+++ b/target/riscv/vector_internals.c
22
@@ -XXX,XX +XXX,XX @@ target_ulong HELPER(vsetvl)(CPURISCVState *env, target_ulong s1,
24
@@ -XXX,XX +XXX,XX @@ void vext_set_elems_1s(void *base, uint32_t is_agnostic, uint32_t cnt,
23
env->vl = vl;
25
if (tot - cnt == 0) {
24
env->vtype = s2;
26
return ;
25
env->vstart = 0;
27
}
26
+ env->vill = 0;
28
+
27
return vl;
29
+ if (HOST_BIG_ENDIAN) {
30
+ /*
31
+ * Deal the situation when the elements are insdie
32
+ * only one uint64 block including setting the
33
+ * masked-off element.
34
+ */
35
+ if (((tot - 1) ^ cnt) < 8) {
36
+ memset(base + H1(tot - 1), -1, tot - cnt);
37
+ return;
38
+ }
39
+ /*
40
+ * Otherwise, at least cross two uint64_t blocks.
41
+ * Set first unaligned block.
42
+ */
43
+ if (cnt % 8 != 0) {
44
+ uint32_t j = ROUND_UP(cnt, 8);
45
+ memset(base + H1(j - 1), -1, j - cnt);
46
+ cnt = j;
47
+ }
48
+ /* Set other 64bit aligend blocks */
49
+ }
50
memset(base + cnt, -1, tot - cnt);
28
}
51
}
29
52
30
--
53
--
31
2.34.1
54
2.45.1
32
33
diff view generated by jsdifflib
1
From: Weiwei Li <liweiwei@iscas.ac.cn>
1
From: Yangyu Chen <cyy@cyyself.name>
2
2
3
- sinval.vma, hinval.vvma and hinval.gvma do the same as sfence.vma, hfence.vvma and hfence.gvma except extension check
3
This code has a typo that writes zvkb to zvkg, causing users can't
4
- do nothing other than extension check for sfence.w.inval and sfence.inval.ir
4
enable zvkb through the config. This patch gets this fixed.
5
5
6
Signed-off-by: Weiwei Li <liweiwei@iscas.ac.cn>
6
Signed-off-by: Yangyu Chen <cyy@cyyself.name>
7
Signed-off-by: Junqiang Wang <wangjunqiang@iscas.ac.cn>
7
Fixes: ea61ef7097d0 ("target/riscv: Move vector crypto extensions to riscv_cpu_extensions")
8
Reviewed-by: Anup Patel <anup@brainfault.org>
8
Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Message-Id: <20220204022658.18097-5-liweiwei@iscas.ac.cn>
10
Reviewed-by: Max Chou <max.chou@sifive.com>
11
Reviewed-by:  Weiwei Li <liwei1518@gmail.com>
12
Message-ID: <tencent_7E34EEF0F90B9A68BF38BEE09EC6D4877C0A@qq.com>
13
Cc: qemu-stable <qemu-stable@nongnu.org>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
14
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
---
15
---
13
target/riscv/cpu.h | 1 +
16
target/riscv/cpu.c | 2 +-
14
target/riscv/insn32.decode | 7 ++
17
1 file changed, 1 insertion(+), 1 deletion(-)
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
18
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
19
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
49
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
50
--- a/target/riscv/cpu.c
21
--- a/target/riscv/cpu.c
51
+++ b/target/riscv/cpu.c
22
+++ b/target/riscv/cpu.c
52
@@ -XXX,XX +XXX,XX @@ static Property riscv_cpu_properties[] = {
23
@@ -XXX,XX +XXX,XX @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
53
DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128),
24
/* Vector cryptography extensions */
54
DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
25
MULTI_EXT_CFG_BOOL("zvbb", ext_zvbb, false),
55
26
MULTI_EXT_CFG_BOOL("zvbc", ext_zvbc, false),
56
+ DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false),
27
- MULTI_EXT_CFG_BOOL("zvkb", ext_zvkg, false),
57
DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false),
28
+ MULTI_EXT_CFG_BOOL("zvkb", ext_zvkb, false),
58
29
MULTI_EXT_CFG_BOOL("zvkg", ext_zvkg, false),
59
DEFINE_PROP_BOOL("zba", RISCVCPU, cfg.ext_zba, true),
30
MULTI_EXT_CFG_BOOL("zvkned", ext_zvkned, false),
60
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
31
MULTI_EXT_CFG_BOOL("zvknha", ext_zvknha, false),
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
--
32
--
154
2.34.1
33
2.45.1
155
34
156
35
diff view generated by jsdifflib
1
From: Anup Patel <anup.patel@wdc.com>
1
From: Huang Tao <eric.huang@linux.alibaba.com>
2
2
3
The AIA spec defines programmable 8-bit priority for each local interrupt
3
In this patch, we modify the decoder to be a freely composable data
4
at M-level, S-level and VS-level so we extend local interrupt processing
4
structure instead of a hardcoded one. It can be dynamically builded up
5
to consider AIA interrupt priorities. The AIA CSRs which help software
5
according to the extensions.
6
configure local interrupt priorities will be added by subsequent patches.
6
This approach has several benefits:
7
1. Provides support for heterogeneous cpu architectures. As we add decoder in
8
RISCVCPU, each cpu can have their own decoder, and the decoders can be
9
different due to cpu's features.
10
2. Improve the decoding efficiency. We run the guard_func to see if the decoder
11
can be added to the dynamic_decoder when building up the decoder. Therefore,
12
there is no need to run the guard_func when decoding each instruction. It can
13
improve the decoding efficiency
14
3. For vendor or dynamic cpus, it allows them to customize their own decoder
15
functions to improve decoding efficiency, especially when vendor-defined
16
instruction sets increase. Because of dynamic building up, it can skip the other
17
decoder guard functions when decoding.
18
4. Pre patch for allowing adding a vendor decoder before decode_insn32() with minimal
19
overhead for users that don't need this particular vendor decoder.
7
20
8
Signed-off-by: Anup Patel <anup.patel@wdc.com>
21
Signed-off-by: Huang Tao <eric.huang@linux.alibaba.com>
9
Signed-off-by: Anup Patel <anup@brainfault.org>
22
Suggested-by: Christoph Muellner <christoph.muellner@vrull.eu>
23
Co-authored-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
24
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
25
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
11
Message-id: 20220204174700.534953-10-anup@brainfault.org
26
Message-ID: <20240506023607.29544-1-eric.huang@linux.alibaba.com>
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
27
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
13
---
28
---
14
target/riscv/cpu.h | 12 ++
29
target/riscv/cpu.h | 1 +
15
target/riscv/cpu.c | 19 +++
30
target/riscv/tcg/tcg-cpu.h | 15 +++++++++++++++
16
target/riscv/cpu_helper.c | 281 +++++++++++++++++++++++++++++++++++---
31
target/riscv/cpu.c | 1 +
17
target/riscv/machine.c | 3 +
32
target/riscv/tcg/tcg-cpu.c | 15 +++++++++++++++
18
4 files changed, 294 insertions(+), 21 deletions(-)
33
target/riscv/translate.c | 31 +++++++++++++++----------------
34
5 files changed, 47 insertions(+), 16 deletions(-)
19
35
20
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
36
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
21
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
22
--- a/target/riscv/cpu.h
38
--- a/target/riscv/cpu.h
23
+++ b/target/riscv/cpu.h
39
+++ b/target/riscv/cpu.h
24
@@ -XXX,XX +XXX,XX @@ struct CPURISCVState {
40
@@ -XXX,XX +XXX,XX @@ struct ArchCPU {
25
target_ulong mcause;
41
uint32_t pmu_avail_ctrs;
26
target_ulong mtval; /* since: priv-1.10.0 */
42
/* Mapping of events to counters */
27
43
GHashTable *pmu_event_ctr_map;
28
+ /* Machine and Supervisor interrupt priorities */
44
+ const GPtrArray *decoders;
29
+ uint8_t miprio[64];
45
};
30
+ uint8_t siprio[64];
46
47
/**
48
diff --git a/target/riscv/tcg/tcg-cpu.h b/target/riscv/tcg/tcg-cpu.h
49
index XXXXXXX..XXXXXXX 100644
50
--- a/target/riscv/tcg/tcg-cpu.h
51
+++ b/target/riscv/tcg/tcg-cpu.h
52
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp);
53
void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp);
54
bool riscv_cpu_tcg_compatible(RISCVCPU *cpu);
55
56
+struct DisasContext;
57
+struct RISCVCPUConfig;
58
+typedef struct RISCVDecoder {
59
+ bool (*guard_func)(const struct RISCVCPUConfig *);
60
+ bool (*riscv_cpu_decode_fn)(struct DisasContext *, uint32_t);
61
+} RISCVDecoder;
31
+
62
+
32
/* Hypervisor CSRs */
63
+typedef bool (*riscv_cpu_decode_fn)(struct DisasContext *, uint32_t);
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
+
64
+
42
/* Upper 64-bits of 128-bit CSRs */
65
+extern const size_t decoder_table_size;
43
uint64_t mscratchh;
66
+
44
uint64_t sscratchh;
67
+extern const RISCVDecoder decoder_table[];
45
@@ -XXX,XX +XXX,XX @@ int riscv_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
68
+
46
int cpuid, void *opaque);
69
+void riscv_tcg_cpu_finalize_dynamic_decoder(RISCVCPU *cpu);
47
int riscv_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
70
+
48
int riscv_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
71
#endif
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
72
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
58
index XXXXXXX..XXXXXXX 100644
73
index XXXXXXX..XXXXXXX 100644
59
--- a/target/riscv/cpu.c
74
--- a/target/riscv/cpu.c
60
+++ b/target/riscv/cpu.c
75
+++ b/target/riscv/cpu.c
61
@@ -XXX,XX +XXX,XX @@ void restore_state_to_opc(CPURISCVState *env, TranslationBlock *tb,
76
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_finalize_features(RISCVCPU *cpu, Error **errp)
62
77
error_propagate(errp, local_err);
63
static void riscv_cpu_reset(DeviceState *dev)
78
return;
64
{
79
}
65
+#ifndef CONFIG_USER_ONLY
80
+ riscv_tcg_cpu_finalize_dynamic_decoder(cpu);
66
+ uint8_t iprio;
81
} else if (kvm_enabled()) {
67
+ int i, irq, rdzero;
82
riscv_kvm_cpu_finalize_features(cpu, &local_err);
68
+#endif
83
if (local_err != NULL) {
69
CPUState *cs = CPU(dev);
84
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
70
RISCVCPU *cpu = RISCV_CPU(cs);
85
index XXXXXXX..XXXXXXX 100644
71
RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cpu);
86
--- a/target/riscv/tcg/tcg-cpu.c
72
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_reset(DeviceState *dev)
87
+++ b/target/riscv/tcg/tcg-cpu.c
73
env->miclaim = MIP_SGEIP;
88
@@ -XXX,XX +XXX,XX @@ void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp)
74
env->pc = env->resetvec;
89
}
75
env->two_stage_lookup = false;
90
}
76
+
91
77
+ /* Initialized default priorities of local interrupts. */
92
+void riscv_tcg_cpu_finalize_dynamic_decoder(RISCVCPU *cpu)
78
+ for (i = 0; i < ARRAY_SIZE(env->miprio); i++) {
93
+{
79
+ iprio = riscv_cpu_default_priority(i);
94
+ GPtrArray *dynamic_decoders;
80
+ env->miprio[i] = (i == IRQ_M_EXT) ? 0 : iprio;
95
+ dynamic_decoders = g_ptr_array_sized_new(decoder_table_size);
81
+ env->siprio[i] = (i == IRQ_S_EXT) ? 0 : iprio;
96
+ for (size_t i = 0; i < decoder_table_size; ++i) {
82
+ env->hviprio[i] = 0;
97
+ if (decoder_table[i].guard_func &&
83
+ }
98
+ decoder_table[i].guard_func(&cpu->cfg)) {
84
+ i = 0;
99
+ g_ptr_array_add(dynamic_decoders,
85
+ while (!riscv_cpu_hviprio_index2irq(i, &irq, &rdzero)) {
100
+ (gpointer)decoder_table[i].riscv_cpu_decode_fn);
86
+ if (!rdzero) {
87
+ env->hviprio[irq] = env->miprio[irq];
88
+ }
101
+ }
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
+ }
102
+ }
136
+
103
+
137
+ if (out_irq) {
104
+ cpu->decoders = dynamic_decoders;
138
+ *out_irq = hviprio_index2irq[index];
139
+ }
140
+
141
+ if (out_rdzero) {
142
+ *out_rdzero = hviprio_index2rdzero[index];
143
+ }
144
+
145
+ return 0;
146
+}
105
+}
147
+
106
+
148
+/*
107
bool riscv_cpu_tcg_compatible(RISCVCPU *cpu)
149
+ * Default priorities of local interrupts are defined in the
108
{
150
+ * RISC-V Advanced Interrupt Architecture specification.
109
return object_dynamic_cast(OBJECT(cpu), TYPE_RISCV_CPU_HOST) == NULL;
151
+ *
110
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
152
+ * ----------------------------------------------------------------
111
index XXXXXXX..XXXXXXX 100644
153
+ * Default |
112
--- a/target/riscv/translate.c
154
+ * Priority | Major Interrupt Numbers
113
+++ b/target/riscv/translate.c
155
+ * ----------------------------------------------------------------
114
@@ -XXX,XX +XXX,XX @@
156
+ * Highest | 63 (3f), 62 (3e), 31 (1f), 30 (1e), 61 (3d), 60 (3c),
115
#include "exec/helper-info.c.inc"
157
+ * | 59 (3b), 58 (3a), 29 (1d), 28 (1c), 57 (39), 56 (38),
116
#undef HELPER_H
158
+ * | 55 (37), 54 (36), 27 (1b), 26 (1a), 53 (35), 52 (34),
117
159
+ * | 51 (33), 50 (32), 25 (19), 24 (18), 49 (31), 48 (30)
118
+#include "tcg/tcg-cpu.h"
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
+
119
+
180
+ [59] = IPRIO_DEFAULT_UPPER + 6,
120
/* global register indices */
181
+ [58] = IPRIO_DEFAULT_UPPER + 7,
121
static TCGv cpu_gpr[32], cpu_gprh[32], cpu_pc, cpu_vl, cpu_vstart;
182
+ [29] = IPRIO_DEFAULT_UPPER + 8,
122
static TCGv_i64 cpu_fpr[32]; /* assume F and D extensions */
183
+ [28] = IPRIO_DEFAULT_UPPER + 9,
123
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
184
+ [57] = IPRIO_DEFAULT_UPPER + 10,
124
/* FRM is known to contain a valid value. */
185
+ [56] = IPRIO_DEFAULT_UPPER + 11,
125
bool frm_valid;
186
+
126
bool insn_start_updated;
187
+ [55] = IPRIO_DEFAULT_UPPER + 12,
127
+ const GPtrArray *decoders;
188
+ [54] = IPRIO_DEFAULT_UPPER + 13,
128
} DisasContext;
189
+ [27] = IPRIO_DEFAULT_UPPER + 14,
129
190
+ [26] = IPRIO_DEFAULT_UPPER + 15,
130
static inline bool has_ext(DisasContext *ctx, uint32_t ext)
191
+ [53] = IPRIO_DEFAULT_UPPER + 16,
131
@@ -XXX,XX +XXX,XX @@ static inline int insn_len(uint16_t first_word)
192
+ [52] = IPRIO_DEFAULT_UPPER + 17,
132
return (first_word & 3) == 3 ? 4 : 2;
193
+
133
}
194
+ [51] = IPRIO_DEFAULT_UPPER + 18,
134
195
+ [50] = IPRIO_DEFAULT_UPPER + 19,
135
+const RISCVDecoder decoder_table[] = {
196
+ [25] = IPRIO_DEFAULT_UPPER + 20,
136
+ { always_true_p, decode_insn32 },
197
+ [24] = IPRIO_DEFAULT_UPPER + 21,
137
+ { has_xthead_p, decode_xthead},
198
+ [49] = IPRIO_DEFAULT_UPPER + 22,
138
+ { has_XVentanaCondOps_p, decode_XVentanaCodeOps},
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
+};
139
+};
243
+
140
+
244
+uint8_t riscv_cpu_default_priority(int irq)
141
+const size_t decoder_table_size = ARRAY_SIZE(decoder_table);
142
+
143
static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
245
{
144
{
246
- target_ulong virt_enabled = riscv_cpu_virt_enabled(env);
145
- /*
247
+ if (irq < 0 || irq > 63) {
146
- * A table with predicate (i.e., guard) functions and decoder functions
248
+ return IPRIO_MMAXIPRIO;
147
- * that are tested in-order until a decoder matches onto the opcode.
249
+ }
148
- */
250
+
149
- static const struct {
251
+ return default_iprio[irq] ? default_iprio[irq] : IPRIO_MMAXIPRIO;
150
- bool (*guard_func)(const RISCVCPUConfig *);
252
+};
151
- bool (*decode_func)(DisasContext *, uint32_t);
253
152
- } decoders[] = {
254
- target_ulong mstatus_mie = get_field(env->mstatus, MSTATUS_MIE);
153
- { always_true_p, decode_insn32 },
255
- target_ulong mstatus_sie = get_field(env->mstatus, MSTATUS_SIE);
154
- { has_xthead_p, decode_xthead },
256
+static int riscv_cpu_pending_to_irq(CPURISCVState *env,
155
- { has_XVentanaCondOps_p, decode_XVentanaCodeOps },
257
+ int extirq, unsigned int extirq_def_prio,
156
- };
258
+ uint64_t pending, uint8_t *iprio)
157
-
259
+{
158
ctx->virt_inst_excp = false;
260
+ int irq, best_irq = RISCV_EXCP_NONE;
159
ctx->cur_insn_len = insn_len(opcode);
261
+ unsigned int prio, best_prio = UINT_MAX;
160
/* Check for compressed insn */
262
161
@@ -XXX,XX +XXX,XX @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
263
- target_ulong vsgemask =
162
ctx->base.pc_next + 2));
264
- (target_ulong)1 << get_field(env->hstatus, HSTATUS_VGEIN);
163
ctx->opcode = opcode32;
265
- target_ulong vsgein = (env->hgeip & vsgemask) ? MIP_VSEIP : 0;
164
266
+ if (!pending) {
165
- for (size_t i = 0; i < ARRAY_SIZE(decoders); ++i) {
267
+ return RISCV_EXCP_NONE;
166
- if (decoders[i].guard_func(ctx->cfg_ptr) &&
268
+ }
167
- decoders[i].decode_func(ctx, opcode32)) {
269
168
+ for (guint i = 0; i < ctx->decoders->len; ++i) {
270
- target_ulong pending = (env->mip | vsgein) & env->mie;
169
+ riscv_cpu_decode_fn func = g_ptr_array_index(ctx->decoders, i);
271
+ irq = ctz64(pending);
170
+ if (func(ctx, opcode32)) {
272
+ if (!riscv_feature(env, RISCV_FEATURE_AIA)) {
171
return;
273
+ return irq;
172
}
274
+ }
173
}
275
174
@@ -XXX,XX +XXX,XX @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
276
- target_ulong mie = env->priv < PRV_M ||
175
ctx->itrigger = FIELD_EX32(tb_flags, TB_FLAGS, ITRIGGER);
277
- (env->priv == PRV_M && mstatus_mie);
176
ctx->zero = tcg_constant_tl(0);
278
- target_ulong sie = env->priv < PRV_S ||
177
ctx->virt_inst_excp = false;
279
- (env->priv == PRV_S && mstatus_sie);
178
+ ctx->decoders = cpu->decoders;
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
}
179
}
393
180
394
bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
181
static void riscv_tr_tb_start(DisasContextBase *db, CPUState *cpu)
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
--
182
--
417
2.34.1
183
2.45.1
418
419
diff view generated by jsdifflib
1
From: Philipp Tomsich <philipp.tomsich@vrull.eu>
1
From: Christoph Müllner <christoph.muellner@vrull.eu>
2
2
3
This adds the decoder and translation for the XVentanaCondOps custom
3
The th.sxstatus CSR can be used to identify available custom extension
4
extension (vendor-defined by Ventana Micro Systems), which is
4
on T-Head CPUs. The CSR is documented here:
5
documented at https://github.com/ventanamicro/ventana-custom-extensions/releases/download/v1.0.0/ventana-custom-extensions-v1.0.0.pdf
5
https://github.com/T-head-Semi/thead-extension-spec/blob/master/xtheadsxstatus.adoc
6
6
7
This commit then also adds a guard-function (has_XVentanaCondOps_p)
7
An important property of this patch is, that the th.sxstatus MAEE field
8
and the decoder function to the table of decoders, enabling the
8
is not set (indicating that XTheadMae is not available).
9
support for the XVentanaCondOps extension.
9
XTheadMae is a memory attribute extension (similar to Svpbmt) which is
10
implemented in many T-Head CPUs (C906, C910, etc.) and utilizes bits
11
in PTEs that are marked as reserved. QEMU maintainers prefer to not
12
implement XTheadMae, so we need give kernels a mechanism to identify
13
if XTheadMae is available in a system or not. And this patch introduces
14
this mechanism in QEMU in a way that's compatible with real HW
15
(i.e., probing the th.sxstatus.MAEE bit).
10
16
11
Signed-off-by: Philipp Tomsich <philipp.tomsich@vrull.eu>
17
Further context can be found on the list:
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
https://lists.gnu.org/archive/html/qemu-devel/2024-02/msg00775.html
19
20
Reviewed-by: LIU Zhiwei <zhiwe_liu@linux.alibaba.com>
13
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
21
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
14
Message-Id: <20220202005249.3566542-7-philipp.tomsich@vrull.eu>
22
Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
23
Message-ID: <20240429073656.2486732-1-christoph.muellner@vrull.eu>
15
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
24
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
16
---
25
---
17
target/riscv/cpu.h | 3 ++
26
MAINTAINERS | 1 +
18
target/riscv/XVentanaCondOps.decode | 25 ++++++++++++
27
target/riscv/cpu.h | 3 ++
19
target/riscv/cpu.c | 3 ++
28
target/riscv/cpu.c | 1 +
20
target/riscv/translate.c | 12 ++++++
29
target/riscv/th_csr.c | 79 ++++++++++++++++++++++++++++++++++++++++
21
.../insn_trans/trans_xventanacondops.c.inc | 39 +++++++++++++++++++
30
target/riscv/meson.build | 1 +
22
target/riscv/meson.build | 1 +
31
5 files changed, 85 insertions(+)
23
6 files changed, 83 insertions(+)
32
create mode 100644 target/riscv/th_csr.c
24
create mode 100644 target/riscv/XVentanaCondOps.decode
25
create mode 100644 target/riscv/insn_trans/trans_xventanacondops.c.inc
26
33
34
diff --git a/MAINTAINERS b/MAINTAINERS
35
index XXXXXXX..XXXXXXX 100644
36
--- a/MAINTAINERS
37
+++ b/MAINTAINERS
38
@@ -XXX,XX +XXX,XX @@ L: qemu-riscv@nongnu.org
39
S: Supported
40
F: target/riscv/insn_trans/trans_xthead.c.inc
41
F: target/riscv/xthead*.decode
42
+F: target/riscv/th_*
43
F: disas/riscv-xthead*
44
45
RISC-V XVentanaCondOps extension
27
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
46
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
28
index XXXXXXX..XXXXXXX 100644
47
index XXXXXXX..XXXXXXX 100644
29
--- a/target/riscv/cpu.h
48
--- a/target/riscv/cpu.h
30
+++ b/target/riscv/cpu.h
49
+++ b/target/riscv/cpu.h
31
@@ -XXX,XX +XXX,XX @@ struct RISCVCPUConfig {
50
@@ -XXX,XX +XXX,XX @@ target_ulong riscv_new_csr_seed(target_ulong new_value,
32
bool ext_zve32f;
51
uint8_t satp_mode_max_from_map(uint32_t map);
33
bool ext_zve64f;
52
const char *satp_mode_str(uint8_t satp_mode, bool is_32_bit);
34
53
35
+ /* Vendor-specific custom extensions */
54
+/* Implemented in th_csr.c */
36
+ bool ext_XVentanaCondOps;
55
+void th_register_custom_csrs(RISCVCPU *cpu);
37
+
56
+
38
char *priv_spec;
57
#endif /* RISCV_CPU_H */
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
58
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
73
index XXXXXXX..XXXXXXX 100644
59
index XXXXXXX..XXXXXXX 100644
74
--- a/target/riscv/cpu.c
60
--- a/target/riscv/cpu.c
75
+++ b/target/riscv/cpu.c
61
+++ b/target/riscv/cpu.c
76
@@ -XXX,XX +XXX,XX @@ static Property riscv_cpu_properties[] = {
62
@@ -XXX,XX +XXX,XX @@ static void rv64_thead_c906_cpu_init(Object *obj)
77
DEFINE_PROP_BOOL("zbc", RISCVCPU, cfg.ext_zbc, true),
63
cpu->cfg.mvendorid = THEAD_VENDOR_ID;
78
DEFINE_PROP_BOOL("zbs", RISCVCPU, cfg.ext_zbs, true),
64
#ifndef CONFIG_USER_ONLY
79
65
set_satp_mode_max_supported(cpu, VM_1_10_SV39);
80
+ /* Vendor-specific custom extensions */
66
+ th_register_custom_csrs(cpu);
81
+ DEFINE_PROP_BOOL("xventanacondops", RISCVCPU, cfg.ext_XVentanaCondOps, false),
67
#endif
82
+
68
83
/* These are experimental so mark with 'x-' */
69
/* inherited from parent obj via riscv_cpu_init() */
84
DEFINE_PROP_BOOL("x-j", RISCVCPU, cfg.ext_j, false),
70
diff --git a/target/riscv/th_csr.c b/target/riscv/th_csr.c
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
71
new file mode 100644
128
index XXXXXXX..XXXXXXX
72
index XXXXXXX..XXXXXXX
129
--- /dev/null
73
--- /dev/null
130
+++ b/target/riscv/insn_trans/trans_xventanacondops.c.inc
74
+++ b/target/riscv/th_csr.c
131
@@ -XXX,XX +XXX,XX @@
75
@@ -XXX,XX +XXX,XX @@
132
+/*
76
+/*
133
+ * RISC-V translation routines for the XVentanaCondOps extension.
77
+ * T-Head-specific CSRs.
134
+ *
78
+ *
135
+ * Copyright (c) 2021-2022 VRULL GmbH.
79
+ * Copyright (c) 2024 VRULL GmbH
136
+ *
80
+ *
137
+ * This program is free software; you can redistribute it and/or modify it
81
+ * 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,
82
+ * under the terms and conditions of the GNU General Public License,
139
+ * version 2 or later, as published by the Free Software Foundation.
83
+ * version 2 or later, as published by the Free Software Foundation.
140
+ *
84
+ *
...
...
145
+ *
89
+ *
146
+ * You should have received a copy of the GNU General Public License along with
90
+ * 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/>.
91
+ * this program. If not, see <http://www.gnu.org/licenses/>.
148
+ */
92
+ */
149
+
93
+
150
+static bool gen_vt_condmask(DisasContext *ctx, arg_r *a, TCGCond cond)
94
+#include "qemu/osdep.h"
95
+#include "cpu.h"
96
+#include "cpu_vendorid.h"
97
+
98
+#define CSR_TH_SXSTATUS 0x5c0
99
+
100
+/* TH_SXSTATUS bits */
101
+#define TH_SXSTATUS_UCME BIT(16)
102
+#define TH_SXSTATUS_MAEE BIT(21)
103
+#define TH_SXSTATUS_THEADISAEE BIT(22)
104
+
105
+typedef struct {
106
+ int csrno;
107
+ int (*insertion_test)(RISCVCPU *cpu);
108
+ riscv_csr_operations csr_ops;
109
+} riscv_csr;
110
+
111
+static RISCVException smode(CPURISCVState *env, int csrno)
151
+{
112
+{
152
+ TCGv dest = dest_gpr(ctx, a->rd);
113
+ if (riscv_has_ext(env, RVS)) {
153
+ TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);
114
+ return RISCV_EXCP_NONE;
154
+ TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
115
+ }
155
+
116
+
156
+ tcg_gen_movcond_tl(cond, dest, src2, ctx->zero, src1, ctx->zero);
117
+ return RISCV_EXCP_ILLEGAL_INST;
157
+
158
+ gen_set_gpr(ctx, a->rd, dest);
159
+ return true;
160
+}
118
+}
161
+
119
+
162
+static bool trans_vt_maskc(DisasContext *ctx, arg_r *a)
120
+static int test_thead_mvendorid(RISCVCPU *cpu)
163
+{
121
+{
164
+ return gen_vt_condmask(ctx, a, TCG_COND_NE);
122
+ if (cpu->cfg.mvendorid != THEAD_VENDOR_ID) {
123
+ return -1;
124
+ }
125
+
126
+ return 0;
165
+}
127
+}
166
+
128
+
167
+static bool trans_vt_maskcn(DisasContext *ctx, arg_r *a)
129
+static RISCVException read_th_sxstatus(CPURISCVState *env, int csrno,
130
+ target_ulong *val)
168
+{
131
+{
169
+ return gen_vt_condmask(ctx, a, TCG_COND_EQ);
132
+ /* We don't set MAEE here, because QEMU does not implement MAEE. */
133
+ *val = TH_SXSTATUS_UCME | TH_SXSTATUS_THEADISAEE;
134
+ return RISCV_EXCP_NONE;
135
+}
136
+
137
+static riscv_csr th_csr_list[] = {
138
+ {
139
+ .csrno = CSR_TH_SXSTATUS,
140
+ .insertion_test = test_thead_mvendorid,
141
+ .csr_ops = { "th.sxstatus", smode, read_th_sxstatus }
142
+ }
143
+};
144
+
145
+void th_register_custom_csrs(RISCVCPU *cpu)
146
+{
147
+ for (size_t i = 0; i < ARRAY_SIZE(th_csr_list); i++) {
148
+ int csrno = th_csr_list[i].csrno;
149
+ riscv_csr_operations *csr_ops = &th_csr_list[i].csr_ops;
150
+ if (!th_csr_list[i].insertion_test(cpu)) {
151
+ riscv_set_csr_ops(csrno, csr_ops);
152
+ }
153
+ }
170
+}
154
+}
171
diff --git a/target/riscv/meson.build b/target/riscv/meson.build
155
diff --git a/target/riscv/meson.build b/target/riscv/meson.build
172
index XXXXXXX..XXXXXXX 100644
156
index XXXXXXX..XXXXXXX 100644
173
--- a/target/riscv/meson.build
157
--- a/target/riscv/meson.build
174
+++ b/target/riscv/meson.build
158
+++ b/target/riscv/meson.build
175
@@ -XXX,XX +XXX,XX @@ dir = meson.current_source_dir()
159
@@ -XXX,XX +XXX,XX @@ riscv_system_ss.add(files(
176
gen = [
160
'monitor.c',
177
decodetree.process('insn16.decode', extra_args: ['--static-decode=decode_insn16', '--insnwidth=16']),
161
'machine.c',
178
decodetree.process('insn32.decode', extra_args: '--static-decode=decode_insn32'),
162
'pmu.c',
179
+ decodetree.process('XVentanaCondOps.decode', extra_args: '--static-decode=decode_XVentanaCodeOps'),
163
+ 'th_csr.c',
180
]
164
'time_helper.c',
181
165
'riscv-qmp-cmds.c',
182
riscv_ss = ss.source_set()
166
))
183
--
167
--
184
2.34.1
168
2.45.1
185
169
186
170
diff view generated by jsdifflib
1
From: Anup Patel <anup.patel@wdc.com>
1
From: Max Chou <max.chou@sifive.com>
2
2
3
We extend virt machine to emulate AIA APLIC devices only when
3
According v spec 18.4, only the vfwcvt.f.f.v and vfncvt.f.f.w
4
"aia=aplic" parameter is passed along with machine name in QEMU
4
instructions will be affected by Zvfhmin extension.
5
command-line. When "aia=none" or not specified then we fallback
5
And the vfwcvt.f.f.v and vfncvt.f.f.w instructions only support the
6
to original PLIC device emulation.
6
conversions of
7
7
8
Signed-off-by: Anup Patel <anup.patel@wdc.com>
8
* From 1*SEW(16/32) to 2*SEW(32/64)
9
Signed-off-by: Anup Patel <anup@brainfault.org>
9
* From 2*SEW(32/64) to 1*SEW(16/32)
10
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
11
Message-id: 20220204174700.534953-20-anup@brainfault.org
11
Signed-off-by: Max Chou <max.chou@sifive.com>
12
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
13
Cc: qemu-stable <qemu-stable@nongnu.org>
14
Message-ID: <20240322092600.1198921-2-max.chou@sifive.com>
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
15
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
13
---
16
---
14
include/hw/riscv/virt.h | 26 +++-
17
target/riscv/insn_trans/trans_rvv.c.inc | 20 ++++++++++++++++++--
15
hw/riscv/virt.c | 291 ++++++++++++++++++++++++++++++++--------
18
1 file changed, 18 insertions(+), 2 deletions(-)
16
hw/riscv/Kconfig | 1 +
17
3 files changed, 259 insertions(+), 59 deletions(-)
18
19
19
diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
20
diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc
20
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
21
--- a/include/hw/riscv/virt.h
22
--- a/target/riscv/insn_trans/trans_rvv.c.inc
22
+++ b/include/hw/riscv/virt.h
23
+++ b/target/riscv/insn_trans/trans_rvv.c.inc
23
@@ -XXX,XX +XXX,XX @@ typedef struct RISCVVirtState RISCVVirtState;
24
@@ -XXX,XX +XXX,XX @@ static bool require_rvf(DisasContext *s)
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
}
25
}
283
}
26
}
284
@@ -XXX,XX +XXX,XX @@ static void create_fdt_pcie(RISCVVirtState *s, const MemMapEntry *memmap,
27
285
2, virt_high_pcie_memmap.base,
28
+static bool require_rvfmin(DisasContext *s)
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
+{
29
+{
344
+ DeviceState *ret;
30
+ if (s->mstatus_fs == EXT_STATUS_DISABLED) {
345
+ char *plic_hart_config;
31
+ return false;
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
+ }
32
+ }
394
+
33
+
395
+ return aplic_m;
34
+ switch (s->sew) {
396
+}
35
+ case MO_16:
397
+
36
+ return s->cfg_ptr->ext_zvfhmin;
398
static void virt_machine_init(MachineState *machine)
37
+ case MO_32:
399
{
38
+ return s->cfg_ptr->ext_zve32f;
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:
39
+ default:
517
+ val = "none";
40
+ return false;
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
+ }
41
+ }
536
+}
42
+}
537
+
43
+
538
static bool virt_get_aclint(Object *obj, Error **errp)
44
static bool require_scale_rvf(DisasContext *s)
539
{
45
{
540
MachineState *ms = MACHINE(obj);
46
if (s->mstatus_fs == EXT_STATUS_DISABLED) {
541
@@ -XXX,XX +XXX,XX @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
47
@@ -XXX,XX +XXX,XX @@ static bool require_scale_rvfmin(DisasContext *s)
542
object_class_property_set_description(oc, "aclint",
48
}
543
"Set on/off to enable/disable "
49
544
"emulating ACLINT devices");
50
switch (s->sew) {
545
+
51
- case MO_8:
546
+ object_class_property_add_str(oc, "aia", virt_get_aia,
52
- return s->cfg_ptr->ext_zvfhmin;
547
+ virt_set_aia);
53
case MO_16:
548
+ object_class_property_set_description(oc, "aia",
54
return s->cfg_ptr->ext_zve32f;
549
+ "Set type of AIA interrupt "
55
case MO_32:
550
+ "conttoller. Valid values are "
56
@@ -XXX,XX +XXX,XX @@ static bool opxfv_widen_check(DisasContext *s, arg_rmr *a)
551
+ "none, and aplic.");
57
static bool opffv_widen_check(DisasContext *s, arg_rmr *a)
58
{
59
return opfv_widen_check(s, a) &&
60
+ require_rvfmin(s) &&
61
require_scale_rvfmin(s) &&
62
(s->sew != MO_8);
552
}
63
}
553
64
@@ -XXX,XX +XXX,XX @@ static bool opfxv_narrow_check(DisasContext *s, arg_rmr *a)
554
static const TypeInfo virt_machine_typeinfo = {
65
static bool opffv_narrow_check(DisasContext *s, arg_rmr *a)
555
diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
66
{
556
index XXXXXXX..XXXXXXX 100644
67
return opfv_narrow_check(s, a) &&
557
--- a/hw/riscv/Kconfig
68
+ require_rvfmin(s) &&
558
+++ b/hw/riscv/Kconfig
69
require_scale_rvfmin(s) &&
559
@@ -XXX,XX +XXX,XX @@ config RISCV_VIRT
70
(s->sew != MO_8);
560
select PFLASH_CFI01
71
}
561
select SERIAL
562
select RISCV_ACLINT
563
+ select RISCV_APLIC
564
select SIFIVE_PLIC
565
select SIFIVE_TEST
566
select VIRTIO_MMIO
567
--
72
--
568
2.34.1
73
2.45.1
569
570
diff view generated by jsdifflib
1
From: Yu Li <liyu.yukiteru@bytedance.com>
1
From: Max Chou <max.chou@sifive.com>
2
2
3
Since the hypervisor extension been non experimental and enabled for
3
The require_scale_rvf function only checks the double width operator for
4
default CPU, the previous command is no longer available and the
4
the vector floating point widen instructions, so most of the widen
5
option `x-h=true` or `h=true` is also no longer required.
5
checking functions need to add require_rvf for single width operator.
6
6
7
Signed-off-by: Yu Li <liyu.yukiteru@bytedance.com>
7
The vfwcvt.f.x.v and vfwcvt.f.xu.v instructions convert single width
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
integer to double width float, so the opfxv_widen_check function doesn’t
9
Message-Id: <9040401e-8f87-ef4a-d840-6703f08d068c@bytedance.com>
9
need require_rvf for the single width operator(integer).
10
11
Signed-off-by: Max Chou <max.chou@sifive.com>
12
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
13
Cc: qemu-stable <qemu-stable@nongnu.org>
14
Message-ID: <20240322092600.1198921-3-max.chou@sifive.com>
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
15
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
---
16
---
12
docs/system/riscv/virt.rst | 6 +++---
17
target/riscv/insn_trans/trans_rvv.c.inc | 5 +++++
13
1 file changed, 3 insertions(+), 3 deletions(-)
18
1 file changed, 5 insertions(+)
14
19
15
diff --git a/docs/system/riscv/virt.rst b/docs/system/riscv/virt.rst
20
diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc
16
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
17
--- a/docs/system/riscv/virt.rst
22
--- a/target/riscv/insn_trans/trans_rvv.c.inc
18
+++ b/docs/system/riscv/virt.rst
23
+++ b/target/riscv/insn_trans/trans_rvv.c.inc
19
@@ -XXX,XX +XXX,XX @@ The ``virt`` machine supports the following devices:
24
@@ -XXX,XX +XXX,XX @@ GEN_OPFVF_TRANS(vfrsub_vf, opfvf_check)
20
* 1 generic PCIe host bridge
25
static bool opfvv_widen_check(DisasContext *s, arg_rmrr *a)
21
* The fw_cfg device that allows a guest to obtain data from QEMU
26
{
22
27
return require_rvv(s) &&
23
-Note that the default CPU is a generic RV32GC/RV64GC. Optional extensions
28
+ require_rvf(s) &&
24
-can be enabled via command line parameters, e.g.: ``-cpu rv64,x-h=true``
29
require_scale_rvf(s) &&
25
-enables the hypervisor extension for RV64.
30
(s->sew != MO_8) &&
26
+The hypervisor extension has been enabled for the default CPU, so virtual
31
vext_check_isa_ill(s) &&
27
+machines with hypervisor extension can simply be used without explicitly
32
@@ -XXX,XX +XXX,XX @@ GEN_OPFVV_WIDEN_TRANS(vfwsub_vv, opfvv_widen_check)
28
+declaring.
33
static bool opfvf_widen_check(DisasContext *s, arg_rmrr *a)
29
34
{
30
Hardware configuration information
35
return require_rvv(s) &&
31
----------------------------------
36
+ require_rvf(s) &&
37
require_scale_rvf(s) &&
38
(s->sew != MO_8) &&
39
vext_check_isa_ill(s) &&
40
@@ -XXX,XX +XXX,XX @@ GEN_OPFVF_WIDEN_TRANS(vfwsub_vf)
41
static bool opfwv_widen_check(DisasContext *s, arg_rmrr *a)
42
{
43
return require_rvv(s) &&
44
+ require_rvf(s) &&
45
require_scale_rvf(s) &&
46
(s->sew != MO_8) &&
47
vext_check_isa_ill(s) &&
48
@@ -XXX,XX +XXX,XX @@ GEN_OPFWV_WIDEN_TRANS(vfwsub_wv)
49
static bool opfwf_widen_check(DisasContext *s, arg_rmrr *a)
50
{
51
return require_rvv(s) &&
52
+ require_rvf(s) &&
53
require_scale_rvf(s) &&
54
(s->sew != MO_8) &&
55
vext_check_isa_ill(s) &&
56
@@ -XXX,XX +XXX,XX @@ GEN_OPFVV_TRANS(vfredmin_vs, freduction_check)
57
static bool freduction_widen_check(DisasContext *s, arg_rmrr *a)
58
{
59
return reduction_widen_check(s, a) &&
60
+ require_rvf(s) &&
61
require_scale_rvf(s) &&
62
(s->sew != MO_8);
63
}
32
--
64
--
33
2.34.1
65
2.45.1
34
66
35
67
diff view generated by jsdifflib
1
From: Anup Patel <anup.patel@wdc.com>
1
From: Max Chou <max.chou@sifive.com>
2
2
3
To facilitate software development of RISC-V systems with large number
3
The opfv_narrow_check needs to check the single width float operator by
4
of HARTs, we increase the maximum number of allowed CPUs to 512 (2^9).
4
require_rvf.
5
5
6
We also add a detailed source level comments about limit defines which
6
Signed-off-by: Max Chou <max.chou@sifive.com>
7
impact the physical address space utilization.
7
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
8
8
Cc: qemu-stable <qemu-stable@nongnu.org>
9
Signed-off-by: Anup Patel <anup.patel@wdc.com>
9
Message-ID: <20240322092600.1198921-4-max.chou@sifive.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>
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
15
---
11
---
16
include/hw/riscv/virt.h | 2 +-
12
target/riscv/insn_trans/trans_rvv.c.inc | 1 +
17
hw/riscv/virt.c | 10 ++++++++++
13
1 file changed, 1 insertion(+)
18
2 files changed, 11 insertions(+), 1 deletion(-)
19
14
20
diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
15
diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc
21
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
22
--- a/include/hw/riscv/virt.h
17
--- a/target/riscv/insn_trans/trans_rvv.c.inc
23
+++ b/include/hw/riscv/virt.h
18
+++ b/target/riscv/insn_trans/trans_rvv.c.inc
24
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ static bool opffv_narrow_check(DisasContext *s, arg_rmr *a)
25
#include "hw/block/flash.h"
20
static bool opffv_rod_narrow_check(DisasContext *s, arg_rmr *a)
26
#include "qom/object.h"
21
{
27
22
return opfv_narrow_check(s, a) &&
28
-#define VIRT_CPUS_MAX_BITS 3
23
+ require_rvf(s) &&
29
+#define VIRT_CPUS_MAX_BITS 9
24
require_scale_rvf(s) &&
30
#define VIRT_CPUS_MAX (1 << VIRT_CPUS_MAX_BITS)
25
(s->sew != MO_8);
31
#define VIRT_SOCKETS_MAX_BITS 2
26
}
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
--
27
--
55
2.34.1
28
2.45.1
56
57
diff view generated by jsdifflib
1
From: Philipp Tomsich <philipp.tomsich@vrull.eu>
1
From: Max Chou <max.chou@sifive.com>
2
2
3
The implementation in trans_{rvi,rvv,rvzfh}.c.inc accesses the shallow
3
If the checking functions check both the single and double width
4
copies (in DisasContext) of some of the elements available in the
4
operators at the same time, then the single width operator checking
5
RISCVCPUConfig structure. This commit redirects accesses to use the
5
functions (require_rvf[min]) will check whether the SEW is 8.
6
cfg_ptr copied into DisasContext and removes the shallow copies.
7
6
8
Signed-off-by: Philipp Tomsich <philipp.tomsich@vrull.eu>
7
Signed-off-by: Max Chou <max.chou@sifive.com>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
10
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
9
Cc: qemu-stable <qemu-stable@nongnu.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-ID: <20240322092600.1198921-5-max.chou@sifive.com>
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>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
17
---
12
---
18
target/riscv/translate.c | 14 ---
13
target/riscv/insn_trans/trans_rvv.c.inc | 16 ++++------------
19
target/riscv/insn_trans/trans_rvi.c.inc | 2 +-
14
1 file changed, 4 insertions(+), 12 deletions(-)
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
15
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
16
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
17
index XXXXXXX..XXXXXXX 100644
78
--- a/target/riscv/insn_trans/trans_rvv.c.inc
18
--- a/target/riscv/insn_trans/trans_rvv.c.inc
79
+++ b/target/riscv/insn_trans/trans_rvv.c.inc
19
+++ b/target/riscv/insn_trans/trans_rvv.c.inc
80
@@ -XXX,XX +XXX,XX @@ static bool require_zve32f(DisasContext *s)
20
@@ -XXX,XX +XXX,XX @@ static bool opfvv_widen_check(DisasContext *s, arg_rmrr *a)
81
}
21
return require_rvv(s) &&
82
22
require_rvf(s) &&
83
/* Zve32f doesn't support FP64. (Section 18.2) */
23
require_scale_rvf(s) &&
84
- return s->ext_zve32f ? s->sew <= MO_32 : true;
24
- (s->sew != MO_8) &&
85
+ return s->cfg_ptr->ext_zve32f ? s->sew <= MO_32 : true;
25
vext_check_isa_ill(s) &&
26
vext_check_dss(s, a->rd, a->rs1, a->rs2, a->vm);
86
}
27
}
87
28
@@ -XXX,XX +XXX,XX @@ static bool opfvf_widen_check(DisasContext *s, arg_rmrr *a)
88
static bool require_scale_zve32f(DisasContext *s)
29
return require_rvv(s) &&
89
@@ -XXX,XX +XXX,XX @@ static bool require_scale_zve32f(DisasContext *s)
30
require_rvf(s) &&
90
}
31
require_scale_rvf(s) &&
91
32
- (s->sew != MO_8) &&
92
/* Zve32f doesn't support FP64. (Section 18.2) */
33
vext_check_isa_ill(s) &&
93
- return s->ext_zve64f ? s->sew <= MO_16 : true;
34
vext_check_ds(s, a->rd, a->rs2, a->vm);
94
+ return s->cfg_ptr->ext_zve64f ? s->sew <= MO_16 : true;
95
}
35
}
96
36
@@ -XXX,XX +XXX,XX @@ static bool opfwv_widen_check(DisasContext *s, arg_rmrr *a)
97
static bool require_zve64f(DisasContext *s)
37
return require_rvv(s) &&
98
@@ -XXX,XX +XXX,XX @@ static bool require_zve64f(DisasContext *s)
38
require_rvf(s) &&
99
}
39
require_scale_rvf(s) &&
100
40
- (s->sew != MO_8) &&
101
/* Zve64f doesn't support FP64. (Section 18.2) */
41
vext_check_isa_ill(s) &&
102
- return s->ext_zve64f ? s->sew <= MO_32 : true;
42
vext_check_dds(s, a->rd, a->rs1, a->rs2, a->vm);
103
+ return s->cfg_ptr->ext_zve64f ? s->sew <= MO_32 : true;
104
}
43
}
105
44
@@ -XXX,XX +XXX,XX @@ static bool opfwf_widen_check(DisasContext *s, arg_rmrr *a)
106
static bool require_scale_zve64f(DisasContext *s)
45
return require_rvv(s) &&
107
@@ -XXX,XX +XXX,XX @@ static bool require_scale_zve64f(DisasContext *s)
46
require_rvf(s) &&
108
}
47
require_scale_rvf(s) &&
109
48
- (s->sew != MO_8) &&
110
/* Zve64f doesn't support FP64. (Section 18.2) */
49
vext_check_isa_ill(s) &&
111
- return s->ext_zve64f ? s->sew <= MO_16 : true;
50
vext_check_dd(s, a->rd, a->rs2, a->vm);
112
+ return s->cfg_ptr->ext_zve64f ? s->sew <= MO_16 : true;
113
}
51
}
114
52
@@ -XXX,XX +XXX,XX @@ static bool opffv_widen_check(DisasContext *s, arg_rmr *a)
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
{
53
{
140
- return offsetof(CPURISCVState, vreg) + reg * s->vlen / 8;
54
return opfv_widen_check(s, a) &&
141
+ return offsetof(CPURISCVState, vreg) + reg * s->cfg_ptr->vlen / 8;
55
require_rvfmin(s) &&
56
- require_scale_rvfmin(s) &&
57
- (s->sew != MO_8);
58
+ require_scale_rvfmin(s);
142
}
59
}
143
60
144
/* check functions */
61
#define GEN_OPFV_WIDEN_TRANS(NAME, CHECK, HELPER, FRM) \
145
@@ -XXX,XX +XXX,XX @@ static bool vext_check_st_index(DisasContext *s, int vd, int vs2, int nf,
62
@@ -XXX,XX +XXX,XX @@ static bool opffv_narrow_check(DisasContext *s, arg_rmr *a)
146
* when XLEN=32. (Section 18.2)
147
*/
148
if (get_xl(s) == MXL_RV32) {
149
- ret &= (!has_ext(s, RVV) && s->ext_zve64f ? eew != MO_64 : true);
150
+ ret &= (!has_ext(s, RVV) &&
151
+ s->cfg_ptr->ext_zve64f ? eew != MO_64 : true);
152
}
153
154
return ret;
155
@@ -XXX,XX +XXX,XX @@ static bool vext_wide_check_common(DisasContext *s, int vd, int vm)
156
{
63
{
157
return (s->lmul <= 2) &&
64
return opfv_narrow_check(s, a) &&
158
(s->sew < MO_64) &&
65
require_rvfmin(s) &&
159
- ((s->sew + 1) <= (s->elen >> 4)) &&
66
- require_scale_rvfmin(s) &&
160
+ ((s->sew + 1) <= (s->cfg_ptr->elen >> 4)) &&
67
- (s->sew != MO_8);
161
require_align(vd, s->lmul + 1) &&
68
+ require_scale_rvfmin(s);
162
require_vm(vm, vd);
163
}
69
}
164
@@ -XXX,XX +XXX,XX @@ static bool vext_narrow_check_common(DisasContext *s, int vd, int vs2,
70
71
static bool opffv_rod_narrow_check(DisasContext *s, arg_rmr *a)
165
{
72
{
166
return (s->lmul <= 2) &&
73
return opfv_narrow_check(s, a) &&
167
(s->sew < MO_64) &&
74
require_rvf(s) &&
168
- ((s->sew + 1) <= (s->elen >> 4)) &&
75
- require_scale_rvf(s) &&
169
+ ((s->sew + 1) <= (s->cfg_ptr->elen >> 4)) &&
76
- (s->sew != MO_8);
170
require_align(vs2, s->lmul + 1) &&
77
+ require_scale_rvf(s);
171
require_align(vd, s->lmul) &&
78
}
172
require_vm(vm, vd);
79
173
@@ -XXX,XX +XXX,XX @@ static bool ldst_us_trans(uint32_t vd, uint32_t rs1, uint32_t data,
80
#define GEN_OPFV_NARROW_TRANS(NAME, CHECK, HELPER, FRM) \
174
* The first part is vlen in bytes, encoded in maxsz of simd_desc.
81
@@ -XXX,XX +XXX,XX @@ static bool freduction_widen_check(DisasContext *s, arg_rmrr *a)
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
{
82
{
226
int scale = s->lmul - 3;
83
return reduction_widen_check(s, a) &&
227
- return scale < 0 ? s->vlen >> -scale : s->vlen << scale;
84
require_rvf(s) &&
228
+ return scale < 0 ? s->cfg_ptr->vlen >> -scale : s->cfg_ptr->vlen << scale;
85
- require_scale_rvf(s) &&
86
- (s->sew != MO_8);
87
+ require_scale_rvf(s);
229
}
88
}
230
89
231
static bool opivv_check(DisasContext *s, arg_rmrr *a)
90
GEN_OPFVV_WIDEN_TRANS(vfwredusum_vs, freduction_widen_check)
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
--
91
--
611
2.34.1
92
2.45.1
612
613
diff view generated by jsdifflib
Deleted patch
1
From: Philipp Tomsich <philipp.tomsich@vrull.eu>
2
1
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
Deleted patch
1
From: Philipp Tomsich <philipp.tomsich@vrull.eu>
2
1
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
Deleted patch
1
From: Anup Patel <anup.patel@wdc.com>
2
1
3
We should be returning illegal instruction trap when RV64 HS-mode tries
4
to access RV32 HS-mode CSR.
5
6
Fixes: d6f20dacea51 ("target/riscv: Fix 32-bit HS mode access permissions")
7
Signed-off-by: Anup Patel <anup.patel@wdc.com>
8
Signed-off-by: Anup Patel <anup@brainfault.org>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
11
Reviewed-by: Frank Chang <frank.chang@sifive.com>
12
Message-id: 20220204174700.534953-2-anup@brainfault.org
13
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
14
---
15
target/riscv/csr.c | 2 +-
16
1 file changed, 1 insertion(+), 1 deletion(-)
17
18
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/riscv/csr.c
21
+++ b/target/riscv/csr.c
22
@@ -XXX,XX +XXX,XX @@ static RISCVException hmode(CPURISCVState *env, int csrno)
23
static RISCVException hmode32(CPURISCVState *env, int csrno)
24
{
25
if (riscv_cpu_mxl(env) != MXL_RV32) {
26
- if (riscv_cpu_virt_enabled(env)) {
27
+ if (!riscv_cpu_virt_enabled(env)) {
28
return RISCV_EXCP_ILLEGAL_INST;
29
} else {
30
return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
31
--
32
2.34.1
33
34
diff view generated by jsdifflib
1
From: Weiwei Li <liweiwei@iscas.ac.cn>
1
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
2
2
3
For non-leaf PTEs, the D, A, and U bits are reserved for future standard use.
3
raise_mmu_exception(), as is today, is prioritizing guest page faults by
4
checking first if virt_enabled && !first_stage, and then considering the
5
regular inst/load/store faults.
4
6
5
Signed-off-by: Weiwei Li <liweiwei@iscas.ac.cn>
7
There's no mention in the spec about guest page fault being a higher
6
Signed-off-by: Junqiang Wang <wangjunqiang@iscas.ac.cn>
8
priority that PMP faults. In fact, privileged spec section 3.7.1 says:
7
Reviewed-by: Anup Patel <anup@brainfault.org>
9
10
"Attempting to fetch an instruction from a PMP region that does not have
11
execute permissions raises an instruction access-fault exception.
12
Attempting to execute a load or load-reserved instruction which accesses
13
a physical address within a PMP region without read permissions raises a
14
load access-fault exception. Attempting to execute a store,
15
store-conditional, or AMO instruction which accesses a physical address
16
within a PMP region without write permissions raises a store
17
access-fault exception."
18
19
So, in fact, we're doing it wrong - PMP faults should always be thrown,
20
regardless of also being a first or second stage fault.
21
22
The way riscv_cpu_tlb_fill() and get_physical_address() work is
23
adequate: a TRANSLATE_PMP_FAIL error is immediately reported and
24
reflected in the 'pmp_violation' flag. What we need is to change
25
raise_mmu_exception() to prioritize it.
26
27
Reported-by: Joseph Chan <jchan@ventanamicro.com>
28
Fixes: 82d53adfbb ("target/riscv/cpu_helper.c: Invalid exception on MMU translation stage")
29
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
30
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Message-Id: <20220204022658.18097-3-liweiwei@iscas.ac.cn>
31
Message-ID: <20240413105929.7030-1-alexei.filippov@syntacore.com>
32
Cc: qemu-stable <qemu-stable@nongnu.org>
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
33
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
---
34
---
12
target/riscv/cpu_helper.c | 3 +++
35
target/riscv/cpu_helper.c | 22 ++++++++++++----------
13
1 file changed, 3 insertions(+)
36
1 file changed, 12 insertions(+), 10 deletions(-)
14
37
15
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
38
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
16
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
17
--- a/target/riscv/cpu_helper.c
40
--- a/target/riscv/cpu_helper.c
18
+++ b/target/riscv/cpu_helper.c
41
+++ b/target/riscv/cpu_helper.c
19
@@ -XXX,XX +XXX,XX @@ restart:
42
@@ -XXX,XX +XXX,XX @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
20
return TRANSLATE_FAIL;
43
21
} else if (!(pte & (PTE_R | PTE_W | PTE_X))) {
44
switch (access_type) {
22
/* Inner PTE, continue walking */
45
case MMU_INST_FETCH:
23
+ if (pte & (PTE_D | PTE_A | PTE_U)) {
46
- if (env->virt_enabled && !first_stage) {
24
+ return TRANSLATE_FAIL;
47
+ if (pmp_violation) {
25
+ }
48
+ cs->exception_index = RISCV_EXCP_INST_ACCESS_FAULT;
26
base = ppn << PGSHIFT;
49
+ } else if (env->virt_enabled && !first_stage) {
27
} else if ((pte & (PTE_R | PTE_W | PTE_X)) == PTE_W) {
50
cs->exception_index = RISCV_EXCP_INST_GUEST_PAGE_FAULT;
28
/* Reserved leaf PTE flags: PTE_W */
51
} else {
52
- cs->exception_index = pmp_violation ?
53
- RISCV_EXCP_INST_ACCESS_FAULT : RISCV_EXCP_INST_PAGE_FAULT;
54
+ cs->exception_index = RISCV_EXCP_INST_PAGE_FAULT;
55
}
56
break;
57
case MMU_DATA_LOAD:
58
- if (two_stage && !first_stage) {
59
+ if (pmp_violation) {
60
+ cs->exception_index = RISCV_EXCP_LOAD_ACCESS_FAULT;
61
+ } else if (two_stage && !first_stage) {
62
cs->exception_index = RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT;
63
} else {
64
- cs->exception_index = pmp_violation ?
65
- RISCV_EXCP_LOAD_ACCESS_FAULT : RISCV_EXCP_LOAD_PAGE_FAULT;
66
+ cs->exception_index = RISCV_EXCP_LOAD_PAGE_FAULT;
67
}
68
break;
69
case MMU_DATA_STORE:
70
- if (two_stage && !first_stage) {
71
+ if (pmp_violation) {
72
+ cs->exception_index = RISCV_EXCP_STORE_AMO_ACCESS_FAULT;
73
+ } else if (two_stage && !first_stage) {
74
cs->exception_index = RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT;
75
} else {
76
- cs->exception_index = pmp_violation ?
77
- RISCV_EXCP_STORE_AMO_ACCESS_FAULT :
78
- RISCV_EXCP_STORE_PAGE_FAULT;
79
+ cs->exception_index = RISCV_EXCP_STORE_PAGE_FAULT;
80
}
81
break;
82
default:
29
--
83
--
30
2.34.1
84
2.45.1
31
32
diff view generated by jsdifflib
1
From: Anup Patel <anup.patel@wdc.com>
1
From: Alexei Filippov <alexei.filippov@syntacore.com>
2
2
3
The guest external interrupts from an interrupt controller are
3
Previous patch fixed the PMP priority in raise_mmu_exception() but we're still
4
delivered only when the Guest/VM is running (i.e. V=1). This means
4
setting mtval2 incorrectly. In riscv_cpu_tlb_fill(), after pmp check in 2 stage
5
any guest external interrupt which is triggered while the Guest/VM
5
translation part, mtval2 will be set in case of successes 2 stage translation but
6
is not running (i.e. V=0) will be missed on QEMU resulting in Guest
6
failed pmp check.
7
with sluggish response to serial console input and other I/O events.
8
7
9
To solve this, we check and inject interrupt after setting V=1.
8
In this case we gonna set mtval2 via env->guest_phys_fault_addr in context of
9
riscv_cpu_tlb_fill(), as this was a guest-page-fault, but it didn't and mtval2
10
should be zero, according to RISCV privileged spec sect. 9.4.4: When a guest
11
page-fault is taken into M-mode, mtval2 is written with either zero or guest
12
physical address that faulted, shifted by 2 bits. *For other traps, mtval2
13
is set to zero...*
10
14
11
Signed-off-by: Anup Patel <anup.patel@wdc.com>
15
Signed-off-by: Alexei Filippov <alexei.filippov@syntacore.com>
12
Signed-off-by: Anup Patel <anup@brainfault.org>
16
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
13
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
17
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
14
Reviewed-by: Frank Chang <frank.chang@sifive.com>
18
Message-ID: <20240503103052.6819-1-alexei.filippov@syntacore.com>
15
Message-id: 20220204174700.534953-5-anup@brainfault.org
19
Cc: qemu-stable <qemu-stable@nongnu.org>
16
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
20
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
17
---
21
---
18
target/riscv/cpu_helper.c | 13 +++++++++++++
22
target/riscv/cpu_helper.c | 12 ++++++------
19
1 file changed, 13 insertions(+)
23
1 file changed, 6 insertions(+), 6 deletions(-)
20
24
21
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
25
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
22
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
23
--- a/target/riscv/cpu_helper.c
27
--- a/target/riscv/cpu_helper.c
24
+++ b/target/riscv/cpu_helper.c
28
+++ b/target/riscv/cpu_helper.c
25
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable)
29
@@ -XXX,XX +XXX,XX @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
26
}
30
__func__, pa, ret, prot_pmp, tlb_size);
27
31
28
env->virt = set_field(env->virt, VIRT_ONOFF, enable);
32
prot &= prot_pmp;
29
+
33
- }
30
+ if (enable) {
34
-
31
+ /*
35
- if (ret != TRANSLATE_SUCCESS) {
32
+ * The guest external interrupts from an interrupt controller are
36
+ } else {
33
+ * delivered only when the Guest/VM is running (i.e. V=1). This means
37
/*
34
+ * any guest external interrupt which is triggered while the Guest/VM
38
* Guest physical address translation failed, this is a HS
35
+ * is not running (i.e. V=0) will be missed on QEMU resulting in guest
39
* level exception
36
+ * with sluggish response to serial console input and other I/O events.
40
*/
37
+ *
41
first_stage_error = false;
38
+ * To solve this, we check and inject interrupt after setting V=1.
42
- env->guest_phys_fault_addr = (im_address |
39
+ */
43
- (address &
40
+ riscv_cpu_update_mip(env_archcpu(env), 0, 0);
44
- (TARGET_PAGE_SIZE - 1))) >> 2;
41
+ }
45
+ if (ret != TRANSLATE_PMP_FAIL) {
42
}
46
+ env->guest_phys_fault_addr = (im_address |
43
47
+ (address &
44
bool riscv_cpu_two_stage_lookup(int mmu_idx)
48
+ (TARGET_PAGE_SIZE - 1))) >> 2;
49
+ }
50
}
51
}
52
} else {
45
--
53
--
46
2.34.1
54
2.45.1
47
48
diff view generated by jsdifflib
1
From: Weiwei Li <liweiwei@iscas.ac.cn>
1
From: Rob Bradford <rbradford@rivosinc.com>
2
2
3
- add PTE_N bit
3
This extension has now been ratified:
4
- add PTE_N bit check for inner PTE
4
https://jira.riscv.org/browse/RVS-2006 so the "x-" prefix can be
5
- update address translation to support 64KiB continuous region (napot_bits = 4)
5
removed.
6
6
7
Signed-off-by: Weiwei Li <liweiwei@iscas.ac.cn>
7
Since this is now a ratified extension add it to the list of extensions
8
Signed-off-by: Junqiang Wang <wangjunqiang@iscas.ac.cn>
8
included in the "max" CPU variant.
9
Reviewed-by: Anup Patel <anup@brainfault.org>
9
10
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
11
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
10
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
12
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
11
Message-Id: <20220204022658.18097-4-liweiwei@iscas.ac.cn>
13
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
14
Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
15
Message-ID: <20240514110217.22516-1-rbradford@rivosinc.com>
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
16
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
13
---
17
---
14
target/riscv/cpu_bits.h | 1 +
18
target/riscv/cpu.c | 2 +-
15
target/riscv/cpu.c | 2 ++
19
target/riscv/tcg/tcg-cpu.c | 2 +-
16
target/riscv/cpu_helper.c | 18 +++++++++++++++---
20
2 files changed, 2 insertions(+), 2 deletions(-)
17
3 files changed, 18 insertions(+), 3 deletions(-)
18
21
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
22
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
32
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
33
--- a/target/riscv/cpu.c
24
--- a/target/riscv/cpu.c
34
+++ b/target/riscv/cpu.c
25
+++ b/target/riscv/cpu.c
35
@@ -XXX,XX +XXX,XX @@ static Property riscv_cpu_properties[] = {
26
@@ -XXX,XX +XXX,XX @@ static const MISAExtInfo misa_ext_info_arr[] = {
36
DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128),
27
MISA_EXT_INFO(RVJ, "x-j", "Dynamic translated languages"),
37
DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
28
MISA_EXT_INFO(RVV, "v", "Vector operations"),
38
29
MISA_EXT_INFO(RVG, "g", "General purpose (IMAFD_Zicsr_Zifencei)"),
39
+ DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false),
30
- MISA_EXT_INFO(RVB, "x-b", "Bit manipulation (Zba_Zbb_Zbs)")
40
+
31
+ MISA_EXT_INFO(RVB, "b", "Bit manipulation (Zba_Zbb_Zbs)")
41
DEFINE_PROP_BOOL("zba", RISCVCPU, cfg.ext_zba, true),
32
};
42
DEFINE_PROP_BOOL("zbb", RISCVCPU, cfg.ext_zbb, true),
33
43
DEFINE_PROP_BOOL("zbc", RISCVCPU, cfg.ext_zbc, true),
34
static void riscv_cpu_validate_misa_mxl(RISCVCPUClass *mcc)
44
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
35
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
45
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
46
--- a/target/riscv/cpu_helper.c
37
--- a/target/riscv/tcg/tcg-cpu.c
47
+++ b/target/riscv/cpu_helper.c
38
+++ b/target/riscv/tcg/tcg-cpu.c
48
@@ -XXX,XX +XXX,XX @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
39
@@ -XXX,XX +XXX,XX @@ static void riscv_init_max_cpu_extensions(Object *obj)
49
bool use_background = false;
40
const RISCVCPUMultiExtConfig *prop;
50
hwaddr ppn;
41
51
RISCVCPU *cpu = env_archcpu(env);
42
/* Enable RVG, RVJ and RVV that are disabled by default */
52
+ int napot_bits = 0;
43
- riscv_cpu_set_misa_ext(env, env->misa_ext | RVG | RVJ | RVV);
53
+ target_ulong napot_mask;
44
+ riscv_cpu_set_misa_ext(env, env->misa_ext | RVB | RVG | RVJ | RVV);
54
45
55
/*
46
for (prop = riscv_cpu_extensions; prop && prop->name; prop++) {
56
* Check if we should use the background registers for the two
47
isa_ext_update_enabled(cpu, prop->offset, true);
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
--
48
--
88
2.34.1
49
2.45.1
89
90
diff view generated by jsdifflib
1
From: Anup Patel <anup.patel@wdc.com>
1
From: Alistair Francis <alistair23@gmail.com>
2
2
3
A hypervisor can optionally take guest external interrupts using
3
When running the instruction
4
SGEIP bit of hip and hie CSRs.
5
4
6
Signed-off-by: Anup Patel <anup.patel@wdc.com>
5
```
7
Signed-off-by: Anup Patel <anup@brainfault.org>
6
cbo.flush 0(x0)
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
7
```
9
Reviewed-by: Frank Chang <frank.chang@sifive.com>
8
10
Message-id: 20220204174700.534953-3-anup@brainfault.org
9
QEMU would segfault.
10
11
The issue was in cpu_gpr[a->rs1] as QEMU does not have cpu_gpr[0]
12
allocated.
13
14
In order to fix this let's use the existing get_address()
15
helper. This also has the benefit of performing pointer mask
16
calculations on the address specified in rs1.
17
18
The pointer masking specificiation specifically states:
19
20
"""
21
Cache Management Operations: All instructions in Zicbom, Zicbop and Zicboz
22
"""
23
24
So this is the correct behaviour and we previously have been incorrectly
25
not masking the address.
26
27
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
28
Reported-by: Fabian Thomas <fabian.thomas@cispa.de>
29
Fixes: e05da09b7cfd ("target/riscv: implement Zicbom extension")
30
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
31
Cc: qemu-stable <qemu-stable@nongnu.org>
32
Message-ID: <20240514023910.301766-1-alistair.francis@wdc.com>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
33
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
---
34
---
13
target/riscv/cpu_bits.h | 3 +++
35
target/riscv/insn_trans/trans_rvzicbo.c.inc | 16 ++++++++++++----
14
target/riscv/cpu.c | 3 ++-
36
1 file changed, 12 insertions(+), 4 deletions(-)
15
target/riscv/csr.c | 18 +++++++++++-------
16
3 files changed, 16 insertions(+), 8 deletions(-)
17
37
18
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
38
diff --git a/target/riscv/insn_trans/trans_rvzicbo.c.inc b/target/riscv/insn_trans/trans_rvzicbo.c.inc
19
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
20
--- a/target/riscv/cpu_bits.h
40
--- a/target/riscv/insn_trans/trans_rvzicbo.c.inc
21
+++ b/target/riscv/cpu_bits.h
41
+++ b/target/riscv/insn_trans/trans_rvzicbo.c.inc
22
@@ -XXX,XX +XXX,XX @@ typedef enum RISCVException {
42
@@ -XXX,XX +XXX,XX @@
23
#define IRQ_S_EXT 9
43
static bool trans_cbo_clean(DisasContext *ctx, arg_cbo_clean *a)
24
#define IRQ_VS_EXT 10
44
{
25
#define IRQ_M_EXT 11
45
REQUIRE_ZICBOM(ctx);
26
+#define IRQ_S_GEXT 12
46
- gen_helper_cbo_clean_flush(tcg_env, cpu_gpr[a->rs1]);
27
+#define IRQ_LOCAL_MAX 16
47
+ TCGv src = get_address(ctx, a->rs1, 0);
28
48
+
29
/* mip masks */
49
+ gen_helper_cbo_clean_flush(tcg_env, src);
30
#define MIP_USIP (1 << IRQ_U_SOFT)
50
return true;
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
}
51
}
59
52
60
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
53
static bool trans_cbo_flush(DisasContext *ctx, arg_cbo_flush *a)
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
{
54
{
81
env->mideleg = (env->mideleg & ~delegable_ints) | (val & delegable_ints);
55
REQUIRE_ZICBOM(ctx);
82
if (riscv_has_ext(env, RVH)) {
56
- gen_helper_cbo_clean_flush(tcg_env, cpu_gpr[a->rs1]);
83
- env->mideleg |= VS_MODE_INTERRUPTS;
57
+ TCGv src = get_address(ctx, a->rs1, 0);
84
+ env->mideleg |= HS_MODE_INTERRUPTS;
58
+
85
}
59
+ gen_helper_cbo_clean_flush(tcg_env, src);
86
return RISCV_EXCP_NONE;
60
return true;
87
}
61
}
88
@@ -XXX,XX +XXX,XX @@ static RISCVException write_mie(CPURISCVState *env, int csrno,
62
89
target_ulong val)
63
static bool trans_cbo_inval(DisasContext *ctx, arg_cbo_inval *a)
90
{
64
{
91
env->mie = (env->mie & ~all_ints) | (val & all_ints);
65
REQUIRE_ZICBOM(ctx);
92
+ if (!riscv_has_ext(env, RVH)) {
66
- gen_helper_cbo_inval(tcg_env, cpu_gpr[a->rs1]);
93
+ env->mie &= ~MIP_SGEIP;
67
+ TCGv src = get_address(ctx, a->rs1, 0);
94
+ }
68
+
95
return RISCV_EXCP_NONE;
69
+ gen_helper_cbo_inval(tcg_env, src);
70
return true;
96
}
71
}
97
72
98
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_sip(CPURISCVState *env, int csrno,
73
static bool trans_cbo_zero(DisasContext *ctx, arg_cbo_zero *a)
99
}
74
{
100
75
REQUIRE_ZICBOZ(ctx);
101
if (ret_value) {
76
- gen_helper_cbo_zero(tcg_env, cpu_gpr[a->rs1]);
102
- *ret_value &= env->mideleg;
77
+ TCGv src = get_address(ctx, a->rs1, 0);
103
+ *ret_value &= env->mideleg & S_MODE_INTERRUPTS;
78
+
104
}
79
+ gen_helper_cbo_zero(tcg_env, src);
105
return ret;
80
return true;
106
}
81
}
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
--
82
--
143
2.34.1
83
2.45.1
144
145
diff view generated by jsdifflib
Deleted patch
1
From: Anup Patel <anup.patel@wdc.com>
2
1
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
Deleted patch
1
From: Anup Patel <anup.patel@wdc.com>
2
1
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
1
From: Anup Patel <anup.patel@wdc.com>
1
From: Yong-Xuan Wang <yongxuan.wang@sifive.com>
2
2
3
We add "x-aia" command-line option for RISC-V HART using which
3
In AIA spec, each hart (or each hart within a group) has a unique hart
4
allows users to force enable CPU AIA CSRs without changing the
4
number to locate the memory pages of interrupt files in the address
5
interrupt controller available in RISC-V machine.
5
space. The number of bits required to represent any hart number is equal
6
to ceil(log2(hmax + 1)), where hmax is the largest hart number among
7
groups.
6
8
7
Signed-off-by: Anup Patel <anup.patel@wdc.com>
9
However, if the largest hart number among groups is a power of 2, QEMU
8
Signed-off-by: Anup Patel <anup@brainfault.org>
10
will pass an inaccurate hart-index-bit setting to Linux. For example, when
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
11
the guest OS has 4 harts, only ceil(log2(3 + 1)) = 2 bits are sufficient
10
Reviewed-by: Frank Chang <frank.chang@sifive.com>
12
to represent 4 harts, but we passes 3 to Linux. The code needs to be
11
Message-id: 20220204174700.534953-18-anup@brainfault.org
13
updated to ensure accurate hart-index-bit settings.
14
15
Additionally, a Linux patch[1] is necessary to correctly recover the hart
16
index when the guest OS has only 1 hart, where the hart-index-bit is 0.
17
18
[1] https://lore.kernel.org/lkml/20240415064905.25184-1-yongxuan.wang@sifive.com/t/
19
20
Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com>
21
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
22
Cc: qemu-stable <qemu-stable@nongnu.org>
23
Message-ID: <20240515091129.28116-1-yongxuan.wang@sifive.com>
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
24
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
13
---
25
---
14
target/riscv/cpu.h | 1 +
26
target/riscv/kvm/kvm-cpu.c | 9 ++++++++-
15
target/riscv/cpu.c | 5 +++++
27
1 file changed, 8 insertions(+), 1 deletion(-)
16
2 files changed, 6 insertions(+)
17
28
18
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
29
diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
19
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
20
--- a/target/riscv/cpu.h
31
--- a/target/riscv/kvm/kvm-cpu.c
21
+++ b/target/riscv/cpu.h
32
+++ b/target/riscv/kvm/kvm-cpu.c
22
@@ -XXX,XX +XXX,XX @@ struct RISCVCPUConfig {
33
@@ -XXX,XX +XXX,XX @@ void kvm_riscv_aia_create(MachineState *machine, uint64_t group_shift,
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
}
34
}
36
}
35
}
37
36
38
+ if (cpu->cfg.aia) {
37
- hart_bits = find_last_bit(&max_hart_per_socket, BITS_PER_LONG) + 1;
39
+ riscv_set_feature(env, RISCV_FEATURE_AIA);
38
+
39
+ if (max_hart_per_socket > 1) {
40
+ max_hart_per_socket--;
41
+ hart_bits = find_last_bit(&max_hart_per_socket, BITS_PER_LONG) + 1;
42
+ } else {
43
+ hart_bits = 0;
40
+ }
44
+ }
41
+
45
+
42
set_resetvec(env, cpu->cfg.resetvec);
46
ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
43
47
KVM_DEV_RISCV_AIA_CONFIG_HART_BITS,
44
/* Validate that MISA_MXL is set properly. */
48
&hart_bits, true, NULL);
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
--
49
--
54
2.34.1
50
2.45.1
55
56
diff view generated by jsdifflib
1
From: Anup Patel <anup.patel@wdc.com>
1
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
2
2
3
The AIA hvictl and hviprioX CSRs allow hypervisor to control
3
Commit 33a24910ae changed 'reg_width' to use 'vlenb', i.e. vector length
4
interrupts visible at VS-level. This patch implements AIA hvictl
4
in bytes, when in this context we want 'reg_width' as the length in
5
and hviprioX CSRs.
5
bits.
6
6
7
Signed-off-by: Anup Patel <anup.patel@wdc.com>
7
Fix 'reg_width' back to the value in bits like 7cb59921c05a
8
Signed-off-by: Anup Patel <anup@brainfault.org>
8
("target/riscv/gdbstub.c: use 'vlenb' instead of shifting 'vlen'") set
9
beforehand.
10
11
While we're at it, rename 'reg_width' to 'bitsize' to provide a bit more
12
clarity about what the variable represents. 'bitsize' is also used in
13
riscv_gen_dynamic_csr_feature() with the same purpose, i.e. as an input to
14
gdb_feature_builder_append_reg().
15
16
Cc: Akihiko Odaki <akihiko.odaki@daynix.com>
17
Cc: Alex Bennée <alex.bennee@linaro.org>
18
Reported-by: Robin Dapp <rdapp.gcc@gmail.com>
19
Fixes: 33a24910ae ("target/riscv: Use GDBFeature for dynamic XML")
20
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
21
Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
22
Acked-by: Alex Bennée <alex.bennee@linaro.org>
23
Reviewed-by: Akihiko Odaki <akihiko.odaki@daynix.com>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
24
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Reviewed-by: Frank Chang <frank.chang@sifive.com>
25
Cc: qemu-stable <qemu-stable@nongnu.org>
11
Message-id: 20220204174700.534953-12-anup@brainfault.org
26
Message-ID: <20240517203054.880861-2-dbarboza@ventanamicro.com>
12
[ Changes by AF:
13
- Fix possible unintilised variable error in rmw_sie()
14
]
15
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
27
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
16
---
28
---
17
target/riscv/cpu.h | 2 +
29
target/riscv/gdbstub.c | 6 +++---
18
target/riscv/csr.c | 128 ++++++++++++++++++++++++++++++++++++++++-
30
1 file changed, 3 insertions(+), 3 deletions(-)
19
target/riscv/machine.c | 2 +
20
3 files changed, 131 insertions(+), 1 deletion(-)
21
31
22
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
32
diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
23
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
24
--- a/target/riscv/cpu.h
34
--- a/target/riscv/gdbstub.c
25
+++ b/target/riscv/cpu.h
35
+++ b/target/riscv/gdbstub.c
26
@@ -XXX,XX +XXX,XX @@ struct CPURISCVState {
36
@@ -XXX,XX +XXX,XX @@ static GDBFeature *riscv_gen_dynamic_csr_feature(CPUState *cs, int base_reg)
27
uint64_t htimedelta;
37
static GDBFeature *ricsv_gen_dynamic_vector_feature(CPUState *cs, int base_reg)
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
{
38
{
61
if (!riscv_feature(env, RISCV_FEATURE_AIA)) {
39
RISCVCPU *cpu = RISCV_CPU(cs);
62
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_sie64(CPURISCVState *env, int csrno,
40
- int reg_width = cpu->cfg.vlenb;
63
uint64_t mask = env->mideleg & S_MODE_INTERRUPTS;
41
+ int bitsize = cpu->cfg.vlenb << 3;
64
42
GDBFeatureBuilder builder;
65
if (riscv_cpu_virt_enabled(env)) {
43
int i;
66
+ if (env->hvictl & HVICTL_VTI) {
44
67
+ return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
45
@@ -XXX,XX +XXX,XX @@ static GDBFeature *ricsv_gen_dynamic_vector_feature(CPUState *cs, int base_reg)
68
+ }
46
69
ret = rmw_vsie64(env, CSR_VSIE, ret_val, new_val, wr_mask);
47
/* First define types and totals in a whole VL */
70
} else {
48
for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
71
ret = rmw_mie64(env, csrno, ret_val, new_val, wr_mask & mask);
49
- int count = reg_width / vec_lanes[i].size;
72
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_sie(CPURISCVState *env, int csrno,
50
+ int count = bitsize / vec_lanes[i].size;
73
RISCVException ret;
51
gdb_feature_builder_append_tag(
74
52
&builder, "<vector id=\"%s\" type=\"%s\" count=\"%d\"/>",
75
ret = rmw_sie64(env, csrno, &rval, new_val, wr_mask);
53
vec_lanes[i].id, vec_lanes[i].gdb_type, count);
76
- if (ret_val) {
54
@@ -XXX,XX +XXX,XX @@ static GDBFeature *ricsv_gen_dynamic_vector_feature(CPUState *cs, int base_reg)
77
+ if (ret == RISCV_EXCP_NONE && ret_val) {
55
/* Define vector registers */
78
*ret_val = rval;
56
for (i = 0; i < 32; i++) {
57
gdb_feature_builder_append_reg(&builder, g_strdup_printf("v%d", i),
58
- reg_width, i, "riscv_vector", "vector");
59
+ bitsize, i, "riscv_vector", "vector");
79
}
60
}
80
61
81
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_sip64(CPURISCVState *env, int csrno,
62
gdb_feature_builder_end(&builder);
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
--
63
--
233
2.34.1
64
2.45.1
234
65
235
66
diff view generated by jsdifflib
Deleted patch
1
From: Anup Patel <anup.patel@wdc.com>
2
1
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
Deleted patch
1
From: Anup Patel <anup.patel@wdc.com>
2
1
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
1
From: Anup Patel <anup.patel@wdc.com>
1
From: Alistair Francis <alistair23@gmail.com>
2
2
3
We have two new machine options "aia" and "aia-guests" available
3
Previously we only listed a single pmpcfg CSR and the first 16 pmpaddr
4
for the RISC-V virt machine so let's document these options.
4
CSRs. This patch fixes this to list all 16 pmpcfg and all 64 pmpaddr
5
CSRs are part of the disassembly.
5
6
6
Signed-off-by: Anup Patel <anup.patel@wdc.com>
7
Reported-by: Eric DeVolder <eric_devolder@yahoo.com>
7
Signed-off-by: Anup Patel <anup@brainfault.org>
8
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Fixes: ea10325917 ("RISC-V Disassembler")
9
Reviewed-by: Frank Chang <frank.chang@sifive.com>
10
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
10
Message-id: 20220204174700.534953-23-anup@brainfault.org
11
Cc: qemu-stable <qemu-stable@nongnu.org>
12
Message-ID: <20240514051615.330979-1-alistair.francis@wdc.com>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
13
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
---
14
---
13
docs/system/riscv/virt.rst | 16 ++++++++++++++++
15
disas/riscv.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++-
14
1 file changed, 16 insertions(+)
16
1 file changed, 64 insertions(+), 1 deletion(-)
15
17
16
diff --git a/docs/system/riscv/virt.rst b/docs/system/riscv/virt.rst
18
diff --git a/disas/riscv.c b/disas/riscv.c
17
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
18
--- a/docs/system/riscv/virt.rst
20
--- a/disas/riscv.c
19
+++ b/docs/system/riscv/virt.rst
21
+++ b/disas/riscv.c
20
@@ -XXX,XX +XXX,XX @@ The following machine-specific options are supported:
22
@@ -XXX,XX +XXX,XX @@ static const char *csr_name(int csrno)
21
When this option is "on", ACLINT devices will be emulated instead of
23
case 0x0383: return "mibound";
22
SiFive CLINT. When not specified, this option is assumed to be "off".
24
case 0x0384: return "mdbase";
23
25
case 0x0385: return "mdbound";
24
+- aia=[none|aplic|aplic-imsic]
26
- case 0x03a0: return "pmpcfg3";
25
+
27
+ case 0x03a0: return "pmpcfg0";
26
+ This option allows selecting interrupt controller defined by the AIA
28
+ case 0x03a1: return "pmpcfg1";
27
+ (advanced interrupt architecture) specification. The "aia=aplic" selects
29
+ case 0x03a2: return "pmpcfg2";
28
+ APLIC (advanced platform level interrupt controller) to handle wired
30
+ case 0x03a3: return "pmpcfg3";
29
+ interrupts whereas the "aia=aplic-imsic" selects APLIC and IMSIC (incoming
31
+ case 0x03a4: return "pmpcfg4";
30
+ message signaled interrupt controller) to handle both wired interrupts and
32
+ case 0x03a5: return "pmpcfg5";
31
+ MSIs. When not specified, this option is assumed to be "none" which selects
33
+ case 0x03a6: return "pmpcfg6";
32
+ SiFive PLIC to handle wired interrupts.
34
+ case 0x03a7: return "pmpcfg7";
33
+
35
+ case 0x03a8: return "pmpcfg8";
34
+- aia-guests=nnn
36
+ case 0x03a9: return "pmpcfg9";
35
+
37
+ case 0x03aa: return "pmpcfg10";
36
+ The number of per-HART VS-level AIA IMSIC pages to be emulated for a guest
38
+ case 0x03ab: return "pmpcfg11";
37
+ having AIA IMSIC (i.e. "aia=aplic-imsic" selected). When not specified,
39
+ case 0x03ac: return "pmpcfg12";
38
+ the default number of per-HART VS-level AIA IMSIC pages is 0.
40
+ case 0x03ad: return "pmpcfg13";
39
+
41
+ case 0x03ae: return "pmpcfg14";
40
Running Linux kernel
42
+ case 0x03af: return "pmpcfg15";
41
--------------------
43
case 0x03b0: return "pmpaddr0";
42
44
case 0x03b1: return "pmpaddr1";
45
case 0x03b2: return "pmpaddr2";
46
@@ -XXX,XX +XXX,XX @@ static const char *csr_name(int csrno)
47
case 0x03bd: return "pmpaddr13";
48
case 0x03be: return "pmpaddr14";
49
case 0x03bf: return "pmpaddr15";
50
+ case 0x03c0: return "pmpaddr16";
51
+ case 0x03c1: return "pmpaddr17";
52
+ case 0x03c2: return "pmpaddr18";
53
+ case 0x03c3: return "pmpaddr19";
54
+ case 0x03c4: return "pmpaddr20";
55
+ case 0x03c5: return "pmpaddr21";
56
+ case 0x03c6: return "pmpaddr22";
57
+ case 0x03c7: return "pmpaddr23";
58
+ case 0x03c8: return "pmpaddr24";
59
+ case 0x03c9: return "pmpaddr25";
60
+ case 0x03ca: return "pmpaddr26";
61
+ case 0x03cb: return "pmpaddr27";
62
+ case 0x03cc: return "pmpaddr28";
63
+ case 0x03cd: return "pmpaddr29";
64
+ case 0x03ce: return "pmpaddr30";
65
+ case 0x03cf: return "pmpaddr31";
66
+ case 0x03d0: return "pmpaddr32";
67
+ case 0x03d1: return "pmpaddr33";
68
+ case 0x03d2: return "pmpaddr34";
69
+ case 0x03d3: return "pmpaddr35";
70
+ case 0x03d4: return "pmpaddr36";
71
+ case 0x03d5: return "pmpaddr37";
72
+ case 0x03d6: return "pmpaddr38";
73
+ case 0x03d7: return "pmpaddr39";
74
+ case 0x03d8: return "pmpaddr40";
75
+ case 0x03d9: return "pmpaddr41";
76
+ case 0x03da: return "pmpaddr42";
77
+ case 0x03db: return "pmpaddr43";
78
+ case 0x03dc: return "pmpaddr44";
79
+ case 0x03dd: return "pmpaddr45";
80
+ case 0x03de: return "pmpaddr46";
81
+ case 0x03df: return "pmpaddr47";
82
+ case 0x03e0: return "pmpaddr48";
83
+ case 0x03e1: return "pmpaddr49";
84
+ case 0x03e2: return "pmpaddr50";
85
+ case 0x03e3: return "pmpaddr51";
86
+ case 0x03e4: return "pmpaddr52";
87
+ case 0x03e5: return "pmpaddr53";
88
+ case 0x03e6: return "pmpaddr54";
89
+ case 0x03e7: return "pmpaddr55";
90
+ case 0x03e8: return "pmpaddr56";
91
+ case 0x03e9: return "pmpaddr57";
92
+ case 0x03ea: return "pmpaddr58";
93
+ case 0x03eb: return "pmpaddr59";
94
+ case 0x03ec: return "pmpaddr60";
95
+ case 0x03ed: return "pmpaddr61";
96
+ case 0x03ee: return "pmpaddr62";
97
+ case 0x03ef: return "pmpaddr63";
98
case 0x0780: return "mtohost";
99
case 0x0781: return "mfromhost";
100
case 0x0782: return "mreset";
43
--
101
--
44
2.34.1
102
2.45.1
45
46
diff view generated by jsdifflib
1
From: Anup Patel <anup.patel@wdc.com>
1
From: Yu-Ming Chang <yumin686@andestech.com>
2
2
3
The AIA specification defines [m|s|vs]iselect and [m|s|vs]ireg CSRs
3
Both CSRRS and CSRRC always read the addressed CSR and cause any read side
4
which allow indirect access to interrupt priority arrays and per-HART
4
effects regardless of rs1 and rd fields. Note that if rs1 specifies a register
5
IMSIC registers. This patch implements AIA xiselect and xireg CSRs.
5
holding a zero value other than x0, the instruction will still attempt to write
6
the unmodified value back to the CSR and will cause any attendant side effects.
6
7
7
Signed-off-by: Anup Patel <anup.patel@wdc.com>
8
So if CSRRS or CSRRC tries to write a read-only CSR with rs1 which specifies
8
Signed-off-by: Anup Patel <anup@brainfault.org>
9
a register holding a zero value, an illegal instruction exception should be
9
Reviewed-by: Frank Chang <frank.chang@sifive.com>
10
raised.
10
Message-id: 20220204174700.534953-15-anup@brainfault.org
11
12
Signed-off-by: Yu-Ming Chang <yumin686@andestech.com>
13
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
14
Message-ID: <20240403070823.80897-1-yumin686@andestech.com>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
15
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
---
16
---
13
target/riscv/cpu.h | 7 ++
17
target/riscv/cpu.h | 4 ++++
14
target/riscv/csr.c | 177 +++++++++++++++++++++++++++++++++++++++++
18
target/riscv/csr.c | 51 ++++++++++++++++++++++++++++++++++++----
15
target/riscv/machine.c | 3 +
19
target/riscv/op_helper.c | 6 ++---
16
3 files changed, 187 insertions(+)
20
3 files changed, 53 insertions(+), 8 deletions(-)
17
21
18
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
22
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
19
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
20
--- a/target/riscv/cpu.h
24
--- a/target/riscv/cpu.h
21
+++ b/target/riscv/cpu.h
25
+++ b/target/riscv/cpu.h
22
@@ -XXX,XX +XXX,XX @@ struct CPURISCVState {
26
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
23
uint8_t miprio[64];
27
void riscv_cpu_update_mask(CPURISCVState *env);
24
uint8_t siprio[64];
28
bool riscv_cpu_is_32bit(RISCVCPU *cpu);
25
29
26
+ /* AIA CSRs */
30
+RISCVException riscv_csrr(CPURISCVState *env, int csrno,
27
+ target_ulong miselect;
31
+ target_ulong *ret_value);
28
+ target_ulong siselect;
32
RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
29
+
33
target_ulong *ret_value,
30
/* Hypervisor CSRs */
34
target_ulong new_value, target_ulong write_mask);
31
target_ulong hstatus;
35
@@ -XXX,XX +XXX,XX @@ typedef RISCVException (*riscv_csr_op_fn)(CPURISCVState *env, int csrno,
32
target_ulong hedeleg;
36
target_ulong new_value,
33
@@ -XXX,XX +XXX,XX @@ struct CPURISCVState {
37
target_ulong write_mask);
34
target_ulong vstval;
38
35
target_ulong vsatp;
39
+RISCVException riscv_csrr_i128(CPURISCVState *env, int csrno,
36
40
+ Int128 *ret_value);
37
+ /* AIA VS-mode CSRs */
41
RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno,
38
+ target_ulong vsiselect;
42
Int128 *ret_value,
39
+
43
Int128 new_value, Int128 write_mask);
40
target_ulong mtval2;
41
target_ulong mtinst;
42
43
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
44
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
44
index XXXXXXX..XXXXXXX 100644
45
index XXXXXXX..XXXXXXX 100644
45
--- a/target/riscv/csr.c
46
--- a/target/riscv/csr.c
46
+++ b/target/riscv/csr.c
47
+++ b/target/riscv/csr.c
47
@@ -XXX,XX +XXX,XX @@ static int read_mtopi(CPURISCVState *env, int csrno, target_ulong *val)
48
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_seed(CPURISCVState *env, int csrno,
49
50
static inline RISCVException riscv_csrrw_check(CPURISCVState *env,
51
int csrno,
52
- bool write_mask)
53
+ bool write)
54
{
55
/* check privileges and return RISCV_EXCP_ILLEGAL_INST if check fails */
56
bool read_only = get_field(csrno, 0xC00) == 3;
57
@@ -XXX,XX +XXX,XX @@ static inline RISCVException riscv_csrrw_check(CPURISCVState *env,
58
}
59
60
/* read / write check */
61
- if (write_mask && read_only) {
62
+ if (write && read_only) {
63
return RISCV_EXCP_ILLEGAL_INST;
64
}
65
66
@@ -XXX,XX +XXX,XX @@ static RISCVException riscv_csrrw_do64(CPURISCVState *env, int csrno,
48
return RISCV_EXCP_NONE;
67
return RISCV_EXCP_NONE;
49
}
68
}
50
69
51
+static int aia_xlate_vs_csrno(CPURISCVState *env, int csrno)
70
+RISCVException riscv_csrr(CPURISCVState *env, int csrno,
71
+ target_ulong *ret_value)
52
+{
72
+{
53
+ if (!riscv_cpu_virt_enabled(env)) {
73
+ RISCVException ret = riscv_csrrw_check(env, csrno, false);
54
+ return csrno;
74
+ if (ret != RISCV_EXCP_NONE) {
75
+ return ret;
55
+ }
76
+ }
56
+
77
+
57
+ switch (csrno) {
78
+ return riscv_csrrw_do64(env, csrno, ret_value, 0, 0);
58
+ case CSR_SISELECT:
59
+ return CSR_VSISELECT;
60
+ case CSR_SIREG:
61
+ return CSR_VSIREG;
62
+ default:
63
+ return csrno;
64
+ };
65
+}
79
+}
66
+
80
+
67
+static int rmw_xiselect(CPURISCVState *env, int csrno, target_ulong *val,
81
RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
68
+ target_ulong new_val, target_ulong wr_mask)
82
target_ulong *ret_value,
83
target_ulong new_value, target_ulong write_mask)
84
{
85
- RISCVException ret = riscv_csrrw_check(env, csrno, write_mask);
86
+ RISCVException ret = riscv_csrrw_check(env, csrno, true);
87
if (ret != RISCV_EXCP_NONE) {
88
return ret;
89
}
90
@@ -XXX,XX +XXX,XX @@ static RISCVException riscv_csrrw_do128(CPURISCVState *env, int csrno,
91
return RISCV_EXCP_NONE;
92
}
93
94
+RISCVException riscv_csrr_i128(CPURISCVState *env, int csrno,
95
+ Int128 *ret_value)
69
+{
96
+{
70
+ target_ulong *iselect;
97
+ RISCVException ret;
71
+
98
+
72
+ /* Translate CSR number for VS-mode */
99
+ ret = riscv_csrrw_check(env, csrno, false);
73
+ csrno = aia_xlate_vs_csrno(env, csrno);
100
+ if (ret != RISCV_EXCP_NONE) {
74
+
101
+ return ret;
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
+ }
102
+ }
93
+
103
+
94
+ wr_mask &= ISELECT_MASK;
104
+ if (csr_ops[csrno].read128) {
95
+ if (wr_mask) {
105
+ return riscv_csrrw_do128(env, csrno, ret_value,
96
+ *iselect = (*iselect & ~wr_mask) | (new_val & wr_mask);
106
+ int128_zero(), int128_zero());
97
+ }
107
+ }
98
+
108
+
99
+ return RISCV_EXCP_NONE;
109
+ /*
110
+ * Fall back to 64-bit version for now, if the 128-bit alternative isn't
111
+ * at all defined.
112
+ * Note, some CSRs don't need to extend to MXLEN (64 upper bits non
113
+ * significant), for those, this fallback is correctly handling the
114
+ * accesses
115
+ */
116
+ target_ulong old_value;
117
+ ret = riscv_csrrw_do64(env, csrno, &old_value,
118
+ (target_ulong)0,
119
+ (target_ulong)0);
120
+ if (ret == RISCV_EXCP_NONE && ret_value) {
121
+ *ret_value = int128_make64(old_value);
122
+ }
123
+ return ret;
100
+}
124
+}
101
+
125
+
102
+static int rmw_iprio(target_ulong xlen,
126
RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno,
103
+ target_ulong iselect, uint8_t *iprio,
127
Int128 *ret_value,
104
+ target_ulong *val, target_ulong new_val,
128
Int128 new_value, Int128 write_mask)
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
{
129
{
217
@@ -XXX,XX +XXX,XX @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
130
RISCVException ret;
218
[CSR_MTVAL] = { "mtval", any, read_mtval, write_mtval },
131
219
[CSR_MIP] = { "mip", any, NULL, NULL, rmw_mip },
132
- ret = riscv_csrrw_check(env, csrno, int128_nz(write_mask));
220
133
+ ret = riscv_csrrw_check(env, csrno, true);
221
+ /* Machine-Level Window to Indirectly Accessed Registers (AIA) */
134
if (ret != RISCV_EXCP_NONE) {
222
+ [CSR_MISELECT] = { "miselect", aia_any, NULL, NULL, rmw_xiselect },
135
return ret;
223
+ [CSR_MIREG] = { "mireg", aia_any, NULL, NULL, rmw_xireg },
136
}
224
+
137
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
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
138
index XXXXXXX..XXXXXXX 100644
254
--- a/target/riscv/machine.c
139
--- a/target/riscv/op_helper.c
255
+++ b/target/riscv/machine.c
140
+++ b/target/riscv/op_helper.c
256
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_hyper = {
141
@@ -XXX,XX +XXX,XX @@ target_ulong helper_csrr(CPURISCVState *env, int csr)
257
VMSTATE_UINTTL(env.vscause, RISCVCPU),
142
}
258
VMSTATE_UINTTL(env.vstval, RISCVCPU),
143
259
VMSTATE_UINTTL(env.vsatp, RISCVCPU),
144
target_ulong val = 0;
260
+ VMSTATE_UINTTL(env.vsiselect, RISCVCPU),
145
- RISCVException ret = riscv_csrrw(env, csr, &val, 0, 0);
261
146
+ RISCVException ret = riscv_csrr(env, csr, &val);
262
VMSTATE_UINTTL(env.mtval2, RISCVCPU),
147
263
VMSTATE_UINTTL(env.mtinst, RISCVCPU),
148
if (ret != RISCV_EXCP_NONE) {
264
@@ -XXX,XX +XXX,XX @@ const VMStateDescription vmstate_riscv_cpu = {
149
riscv_raise_exception(env, ret, GETPC());
265
VMSTATE_UINTTL(env.mepc, RISCVCPU),
150
@@ -XXX,XX +XXX,XX @@ target_ulong helper_csrrw(CPURISCVState *env, int csr,
266
VMSTATE_UINTTL(env.mcause, RISCVCPU),
151
target_ulong helper_csrr_i128(CPURISCVState *env, int csr)
267
VMSTATE_UINTTL(env.mtval, RISCVCPU),
152
{
268
+ VMSTATE_UINTTL(env.miselect, RISCVCPU),
153
Int128 rv = int128_zero();
269
+ VMSTATE_UINTTL(env.siselect, RISCVCPU),
154
- RISCVException ret = riscv_csrrw_i128(env, csr, &rv,
270
VMSTATE_UINTTL(env.scounteren, RISCVCPU),
155
- int128_zero(),
271
VMSTATE_UINTTL(env.mcounteren, RISCVCPU),
156
- int128_zero());
272
VMSTATE_UINTTL(env.sscratch, RISCVCPU),
157
+ RISCVException ret = riscv_csrr_i128(env, csr, &rv);
158
159
if (ret != RISCV_EXCP_NONE) {
160
riscv_raise_exception(env, ret, GETPC());
273
--
161
--
274
2.34.1
162
2.45.1
275
276
diff view generated by jsdifflib
Deleted patch
1
From: Anup Patel <anup.patel@wdc.com>
2
1
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
Deleted patch
1
From: Anup Patel <anup.patel@wdc.com>
2
1
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