1
The following changes since commit ad10b4badc1dd5b28305f9b9f1168cf0aa3ae946:
1
From: Alistair Francis <alistair.francis@wdc.com>
2
2
3
Merge tag 'pull-error-2024-05-27' of https://repo.or.cz/qemu/armbru into staging (2024-05-27 06:40:42 -0700)
3
The following changes since commit 326ff8dd09556fc2e257196c49f35009700794ac:
4
5
Merge remote-tracking branch 'remotes/jasowang/tags/net-pull-request' into staging (2021-09-20 16:17:05 +0100)
4
6
5
are available in the Git repository at:
7
are available in the Git repository at:
6
8
7
https://github.com/alistair23/qemu.git tags/pull-riscv-to-apply-20240528
9
git@github.com:alistair23/qemu.git tags/pull-riscv-to-apply-20210921
8
10
9
for you to fetch changes up to 1806da76cb81088ea026ca3441551782b850e393:
11
for you to fetch changes up to ed481d9837250aa682f5156528bc923e1b214f76:
10
12
11
target/riscv: raise an exception when CSRRS/CSRRC writes a read-only CSR (2024-05-28 12:20:27 +1000)
13
hw/riscv: opentitan: Correct the USB Dev address (2021-09-21 12:10:47 +1000)
12
14
13
----------------------------------------------------------------
15
----------------------------------------------------------------
14
RISC-V PR for 9.1
16
Second RISC-V PR for QEMU 6.2
15
17
16
* APLICs add child earlier than realize
18
- ePMP CSR address updates
17
* Fix exposure of Zkr
19
- Convert internal interrupts to use QEMU GPIO lines
18
* Raise exceptions on wrs.nto
20
- SiFive PWM support
19
* Implement SBI debug console (DBCN) calls for KVM
21
- Support for RISC-V ACLINT
20
* Support 64-bit addresses for initrd
22
- SiFive PDMA fixes
21
* Change RISCV_EXCP_SEMIHOST exception number to 63
23
- Update to u-boot instructions for sifive_u
22
* Tolerate KVM disable ext errors
24
- mstatus.SD bug fix for hypervisor extensions
23
* Set tval in breakpoints
25
- OpenTitan fix for USB dev address
24
* Add support for Zve32x extension
25
* Add support for Zve64x extension
26
* Relax vector register check in RISCV gdbstub
27
* Fix the element agnostic Vector function problem
28
* Fix Zvkb extension config
29
* Implement dynamic establishment of custom decoder
30
* Add th.sxstatus CSR emulation
31
* Fix Zvfhmin checking for vfwcvt.f.f.v and vfncvt.f.f.w instructions
32
* Check single width operator for vector fp widen instructions
33
* Check single width operator for vfncvt.rod.f.f.w
34
* Remove redudant SEW checking for vector fp narrow/widen instructions
35
* Prioritize pmp errors in raise_mmu_exception()
36
* Do not set mtval2 for non guest-page faults
37
* Remove experimental prefix from "B" extension
38
* Fixup CBO extension register calculation
39
* Fix the hart bit setting of AIA
40
* Fix reg_width in ricsv_gen_dynamic_vector_feature()
41
* Decode all of the pmpcfg and pmpaddr CSRs
42
* Raise an exception when CSRRS/CSRRC writes a read-only CSR
43
26
44
----------------------------------------------------------------
27
----------------------------------------------------------------
45
Alexei Filippov (1):
28
Alistair Francis (9):
46
target/riscv: do not set mtval2 for non guest-page faults
29
target/riscv: Update the ePMP CSR address
30
target/riscv: Expose interrupt pending bits as GPIO lines
31
hw/intc: sifive_clint: Use RISC-V CPU GPIO lines
32
hw/intc: ibex_plic: Convert the PLIC to use RISC-V CPU GPIO lines
33
hw/intc: sifive_plic: Convert the PLIC to use RISC-V CPU GPIO lines
34
hw/intc: ibex_timer: Convert the timer to use RISC-V CPU GPIO lines
35
hw/timer: Add SiFive PWM support
36
sifive_u: Connect the SiFive PWM device
37
hw/riscv: opentitan: Correct the USB Dev address
47
38
48
Alistair Francis (2):
39
Anup Patel (4):
49
target/riscv: rvzicbo: Fixup CBO extension register calculation
40
hw/intc: Rename sifive_clint sources to riscv_aclint sources
50
disas/riscv: Decode all of the pmpcfg and pmpaddr CSRs
41
hw/intc: Upgrade the SiFive CLINT implementation to RISC-V ACLINT
42
hw/riscv: virt: Re-factor FDT generation
43
hw/riscv: virt: Add optional ACLINT support to virt machine
51
44
52
Andrew Jones (2):
45
Bin Meng (2):
53
target/riscv/kvm: Fix exposure of Zkr
46
docs/system/riscv: sifive_u: Update U-Boot instructions
54
target/riscv: Raise exceptions on wrs.nto
47
target/riscv: csr: Rename HCOUNTEREN_CY and friends
55
48
56
Cheng Yang (1):
49
Frank Chang (4):
57
hw/riscv/boot.c: Support 64-bit address for initrd
50
hw/dma: sifive_pdma: reset Next* registers when Control.claim is set
51
hw/dma: sifive_pdma: claim bit must be set before DMA transactions
52
hw/dma: sifive_pdma: don't set Control.error if 0 bytes to transfer
53
target/riscv: Backup/restore mstatus.SD bit when virtual register swapped
58
54
59
Christoph Müllner (1):
55
Green Wan (1):
60
riscv: thead: Add th.sxstatus CSR emulation
56
hw/dma: sifive_pdma: allow non-multiple transaction size transactions
61
57
62
Clément Léger (1):
58
LIU Zhiwei (1):
63
target/riscv: change RISCV_EXCP_SEMIHOST exception number to 63
59
target/riscv: Fix satp write
64
60
65
Daniel Henrique Barboza (6):
61
docs/system/riscv/sifive_u.rst | 50 ++--
66
target/riscv/kvm: implement SBI debug console (DBCN) calls
62
docs/system/riscv/virt.rst | 10 +
67
target/riscv/kvm: tolerate KVM disable ext errors
63
include/hw/intc/ibex_plic.h | 2 +
68
target/riscv/debug: set tval=pc in breakpoint exceptions
64
include/hw/intc/riscv_aclint.h | 80 +++++
69
trans_privileged.c.inc: set (m|s)tval on ebreak breakpoint
65
include/hw/intc/sifive_clint.h | 60 ----
70
target/riscv: prioritize pmp errors in raise_mmu_exception()
66
include/hw/intc/sifive_plic.h | 4 +
71
riscv, gdbstub.c: fix reg_width in ricsv_gen_dynamic_vector_feature()
67
include/hw/riscv/sifive_u.h | 14 +-
68
include/hw/riscv/virt.h | 2 +
69
include/hw/timer/ibex_timer.h | 2 +
70
include/hw/timer/sifive_pwm.h | 62 ++++
71
target/riscv/cpu_bits.h | 12 +-
72
hw/dma/sifive_pdma.c | 54 +++-
73
hw/intc/ibex_plic.c | 17 +-
74
hw/intc/riscv_aclint.c | 460 +++++++++++++++++++++++++++++
75
hw/intc/sifive_clint.c | 287 ------------------
76
hw/intc/sifive_plic.c | 30 +-
77
hw/riscv/microchip_pfsoc.c | 13 +-
78
hw/riscv/opentitan.c | 13 +-
79
hw/riscv/shakti_c.c | 16 +-
80
hw/riscv/sifive_e.c | 15 +-
81
hw/riscv/sifive_u.c | 68 ++++-
82
hw/riscv/spike.c | 16 +-
83
hw/riscv/virt.c | 654 ++++++++++++++++++++++++++++-------------
84
hw/timer/ibex_timer.c | 17 +-
85
hw/timer/sifive_pwm.c | 468 +++++++++++++++++++++++++++++
86
target/riscv/cpu.c | 31 ++
87
target/riscv/cpu_helper.c | 3 +-
88
target/riscv/csr.c | 26 +-
89
hw/intc/Kconfig | 2 +-
90
hw/intc/meson.build | 2 +-
91
hw/riscv/Kconfig | 13 +-
92
hw/timer/Kconfig | 3 +
93
hw/timer/meson.build | 1 +
94
hw/timer/trace-events | 6 +
95
34 files changed, 1844 insertions(+), 669 deletions(-)
96
create mode 100644 include/hw/intc/riscv_aclint.h
97
delete mode 100644 include/hw/intc/sifive_clint.h
98
create mode 100644 include/hw/timer/sifive_pwm.h
99
create mode 100644 hw/intc/riscv_aclint.c
100
delete mode 100644 hw/intc/sifive_clint.c
101
create mode 100644 hw/timer/sifive_pwm.c
72
102
73
Huang Tao (2):
74
target/riscv: Fix the element agnostic function problem
75
target/riscv: Implement dynamic establishment of custom decoder
76
77
Jason Chien (3):
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
81
82
Max Chou (4):
83
target/riscv: rvv: Fix Zvfhmin checking for vfwcvt.f.f.v and vfncvt.f.f.w instructions
84
target/riscv: rvv: Check single width operator for vector fp widen instructions
85
target/riscv: rvv: Check single width operator for vfncvt.rod.f.f.w
86
target/riscv: rvv: Remove redudant SEW checking for vector fp narrow/widen instructions
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: "yang.zhang" <yang.zhang@hexintek.com>
2
1
3
Since only root APLICs can have hw IRQ lines, aplic->parent should
4
be initialized first.
5
6
Fixes: e8f79343cf ("hw/intc: Add RISC-V AIA APLIC device emulation")
7
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
8
Signed-off-by: yang.zhang <yang.zhang@hexintek.com>
9
Cc: qemu-stable <qemu-stable@nongnu.org>
10
Message-ID: <20240409014445.278-1-gaoshanliukou@163.com>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
---
13
hw/intc/riscv_aplic.c | 8 ++++----
14
1 file changed, 4 insertions(+), 4 deletions(-)
15
16
diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/intc/riscv_aplic.c
19
+++ b/hw/intc/riscv_aplic.c
20
@@ -XXX,XX +XXX,XX @@ DeviceState *riscv_aplic_create(hwaddr addr, hwaddr size,
21
qdev_prop_set_bit(dev, "msimode", msimode);
22
qdev_prop_set_bit(dev, "mmode", mmode);
23
24
+ if (parent) {
25
+ riscv_aplic_add_child(parent, dev);
26
+ }
27
+
28
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
29
30
if (!is_kvm_aia(msimode)) {
31
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
32
}
33
34
- if (parent) {
35
- riscv_aplic_add_child(parent, dev);
36
- }
37
-
38
if (!msimode) {
39
for (i = 0; i < num_harts; i++) {
40
CPUState *cpu = cpu_by_arch_id(hartid_base + i);
41
--
42
2.45.1
diff view generated by jsdifflib
1
From: Rob Bradford <rbradford@rivosinc.com>
1
From: Alistair Francis <alistair.francis@wdc.com>
2
2
3
This extension has now been ratified:
3
Update the ePMP CSRs to match the 0.9.3 ePMP spec
4
https://jira.riscv.org/browse/RVS-2006 so the "x-" prefix can be
4
https://github.com/riscv/riscv-tee/blob/61455747230a26002d741f64879dd78cc9689323/Smepmp/Smepmp.pdf
5
removed.
6
5
7
Since this is now a ratified extension add it to the list of extensions
6
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
8
included in the "max" CPU variant.
7
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
8
Message-id: 28c908de60b9b04fa20e63d113885c98586053f3.1630543194.git.alistair.francis@wdc.com
9
---
10
target/riscv/cpu_bits.h | 4 ++--
11
target/riscv/cpu.c | 1 +
12
2 files changed, 3 insertions(+), 2 deletions(-)
9
13
10
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
14
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
11
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
15
index XXXXXXX..XXXXXXX 100644
12
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
16
--- a/target/riscv/cpu_bits.h
13
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
17
+++ b/target/riscv/cpu_bits.h
14
Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
18
@@ -XXX,XX +XXX,XX @@
15
Message-ID: <20240514110217.22516-1-rbradford@rivosinc.com>
19
#define CSR_MTVAL2 0x34b
16
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
20
17
---
21
/* Enhanced Physical Memory Protection (ePMP) */
18
target/riscv/cpu.c | 2 +-
22
-#define CSR_MSECCFG 0x390
19
target/riscv/tcg/tcg-cpu.c | 2 +-
23
-#define CSR_MSECCFGH 0x391
20
2 files changed, 2 insertions(+), 2 deletions(-)
24
+#define CSR_MSECCFG 0x747
21
25
+#define CSR_MSECCFGH 0x757
26
/* Physical Memory Protection */
27
#define CSR_PMPCFG0 0x3a0
28
#define CSR_PMPCFG1 0x3a1
22
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
29
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
23
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
24
--- a/target/riscv/cpu.c
31
--- a/target/riscv/cpu.c
25
+++ b/target/riscv/cpu.c
32
+++ b/target/riscv/cpu.c
26
@@ -XXX,XX +XXX,XX @@ static const MISAExtInfo misa_ext_info_arr[] = {
33
@@ -XXX,XX +XXX,XX @@ static Property riscv_cpu_properties[] = {
27
MISA_EXT_INFO(RVJ, "x-j", "Dynamic translated languages"),
34
DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
28
MISA_EXT_INFO(RVV, "v", "Vector operations"),
35
DEFINE_PROP_BOOL("mmu", RISCVCPU, cfg.mmu, true),
29
MISA_EXT_INFO(RVG, "g", "General purpose (IMAFD_Zicsr_Zifencei)"),
36
DEFINE_PROP_BOOL("pmp", RISCVCPU, cfg.pmp, true),
30
- MISA_EXT_INFO(RVB, "x-b", "Bit manipulation (Zba_Zbb_Zbs)")
37
+ /* ePMP 0.9.3 */
31
+ MISA_EXT_INFO(RVB, "b", "Bit manipulation (Zba_Zbb_Zbs)")
38
DEFINE_PROP_BOOL("x-epmp", RISCVCPU, cfg.epmp, false),
32
};
39
33
40
DEFINE_PROP_UINT64("resetvec", RISCVCPU, cfg.resetvec, DEFAULT_RSTVEC),
34
static void riscv_cpu_validate_misa_mxl(RISCVCPUClass *mcc)
35
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/riscv/tcg/tcg-cpu.c
38
+++ b/target/riscv/tcg/tcg-cpu.c
39
@@ -XXX,XX +XXX,XX @@ static void riscv_init_max_cpu_extensions(Object *obj)
40
const RISCVCPUMultiExtConfig *prop;
41
42
/* Enable RVG, RVJ and RVV that are disabled by default */
43
- riscv_cpu_set_misa_ext(env, env->misa_ext | RVG | RVJ | RVV);
44
+ riscv_cpu_set_misa_ext(env, env->misa_ext | RVB | RVG | RVJ | RVV);
45
46
for (prop = riscv_cpu_extensions; prop && prop->name; prop++) {
47
isa_ext_update_enabled(cpu, prop->offset, true);
48
--
41
--
49
2.45.1
42
2.31.1
43
44
diff view generated by jsdifflib
1
From: Andrew Jones <ajones@ventanamicro.com>
1
From: LIU Zhiwei <zhiwei_liu@c-sky.com>
2
2
3
The Zkr extension may only be exposed to KVM guests if the VMM
3
These variables should be target_ulong. If truncated to int,
4
implements the SEED CSR. Use the same implementation as TCG.
4
the bool conditions they indicate will be wrong.
5
5
6
Without this patch, running with a KVM which does not forward the
6
As satp is very important for Linux, this bug almost fails every boot.
7
SEED CSR access to QEMU will result in an ILL exception being
8
injected into the guest (this results in Linux guests crashing on
9
boot). And, when running with a KVM which does forward the access,
10
QEMU will crash, since QEMU doesn't know what to do with the exit.
11
7
12
Fixes: 3108e2f1c69d ("target/riscv/kvm: update KVM exts to Linux 6.8")
8
Signed-off-by: LIU Zhiwei <zhiwei_liu@c-sky.com>
13
Signed-off-by: Andrew Jones <ajones@ventanamicro.com>
9
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
14
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
10
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
15
Cc: qemu-stable <qemu-stable@nongnu.org>
11
Message-id: 20210901124539.222868-1-zhiwei_liu@c-sky.com
16
Message-ID: <20240422134605.534207-2-ajones@ventanamicro.com>
17
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
18
---
13
---
19
target/riscv/cpu.h | 3 +++
14
target/riscv/csr.c | 2 +-
20
target/riscv/csr.c | 18 ++++++++++++++----
15
1 file changed, 1 insertion(+), 1 deletion(-)
21
target/riscv/kvm/kvm-cpu.c | 25 +++++++++++++++++++++++++
22
3 files changed, 42 insertions(+), 4 deletions(-)
23
16
24
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
25
index XXXXXXX..XXXXXXX 100644
26
--- a/target/riscv/cpu.h
27
+++ b/target/riscv/cpu.h
28
@@ -XXX,XX +XXX,XX @@ void riscv_set_csr_ops(int csrno, riscv_csr_operations *ops);
29
30
void riscv_cpu_register_gdb_regs_for_features(CPUState *cs);
31
32
+target_ulong riscv_new_csr_seed(target_ulong new_value,
33
+ target_ulong write_mask);
34
+
35
uint8_t satp_mode_max_from_map(uint32_t map);
36
const char *satp_mode_str(uint8_t satp_mode, bool is_32_bit);
37
38
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
17
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
39
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
40
--- a/target/riscv/csr.c
19
--- a/target/riscv/csr.c
41
+++ b/target/riscv/csr.c
20
+++ b/target/riscv/csr.c
42
@@ -XXX,XX +XXX,XX @@ static RISCVException write_upmbase(CPURISCVState *env, int csrno,
21
@@ -XXX,XX +XXX,XX @@ static RISCVException read_satp(CPURISCVState *env, int csrno,
43
#endif
22
static RISCVException write_satp(CPURISCVState *env, int csrno,
44
23
target_ulong val)
45
/* Crypto Extension */
46
-static RISCVException rmw_seed(CPURISCVState *env, int csrno,
47
- target_ulong *ret_value,
48
- target_ulong new_value,
49
- target_ulong write_mask)
50
+target_ulong riscv_new_csr_seed(target_ulong new_value,
51
+ target_ulong write_mask)
52
{
24
{
53
uint16_t random_v;
25
- int vm, mask, asid;
54
Error *random_e = NULL;
26
+ target_ulong vm, mask, asid;
55
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_seed(CPURISCVState *env, int csrno,
27
56
rval = random_v | SEED_OPST_ES16;
28
if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
57
}
29
return RISCV_EXCP_NONE;
58
59
+ return rval;
60
+}
61
+
62
+static RISCVException rmw_seed(CPURISCVState *env, int csrno,
63
+ target_ulong *ret_value,
64
+ target_ulong new_value,
65
+ target_ulong write_mask)
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;
80
}
81
82
+static int kvm_riscv_handle_csr(CPUState *cs, struct kvm_run *run)
83
+{
84
+ target_ulong csr_num = run->riscv_csr.csr_num;
85
+ target_ulong new_value = run->riscv_csr.new_value;
86
+ target_ulong write_mask = run->riscv_csr.write_mask;
87
+ int ret = 0;
88
+
89
+ switch (csr_num) {
90
+ case CSR_SEED:
91
+ run->riscv_csr.ret_value = riscv_new_csr_seed(new_value, write_mask);
92
+ break;
93
+ default:
94
+ qemu_log_mask(LOG_UNIMP,
95
+ "%s: un-handled CSR EXIT for CSR %lx\n",
96
+ __func__, csr_num);
97
+ ret = -1;
98
+ break;
99
+ }
100
+
101
+ return ret;
102
+}
103
+
104
int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
105
{
106
int ret = 0;
107
@@ -XXX,XX +XXX,XX @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
108
case KVM_EXIT_RISCV_SBI:
109
ret = kvm_riscv_handle_sbi(cs, run);
110
break;
111
+ case KVM_EXIT_RISCV_CSR:
112
+ ret = kvm_riscv_handle_csr(cs, run);
113
+ break;
114
default:
115
qemu_log_mask(LOG_UNIMP, "%s: un-handled exit reason %d\n",
116
__func__, run->exit_reason);
117
--
30
--
118
2.45.1
31
2.31.1
32
33
diff view generated by jsdifflib
1
From: Yangyu Chen <cyy@cyyself.name>
1
From: Alistair Francis <alistair.francis@wdc.com>
2
2
3
This code has a typo that writes zvkb to zvkg, causing users can't
3
Expose the 12 interrupt pending bits in MIP as GPIO lines.
4
enable zvkb through the config. This patch gets this fixed.
5
4
6
Signed-off-by: Yangyu Chen <cyy@cyyself.name>
7
Fixes: ea61ef7097d0 ("target/riscv: Move vector crypto extensions to riscv_cpu_extensions")
8
Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
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>
14
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
5
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
9
Tested-by: Bin Meng <bmeng.cn@gmail.com>
10
Message-id: 069d6162f0bc2f4a4f5a44e73f6442b11c703c53.1630301632.git.alistair.francis@wdc.com
15
---
11
---
16
target/riscv/cpu.c | 2 +-
12
target/riscv/cpu.c | 30 ++++++++++++++++++++++++++++++
17
1 file changed, 1 insertion(+), 1 deletion(-)
13
1 file changed, 30 insertions(+)
18
14
19
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
15
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
20
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
21
--- a/target/riscv/cpu.c
17
--- a/target/riscv/cpu.c
22
+++ b/target/riscv/cpu.c
18
+++ b/target/riscv/cpu.c
23
@@ -XXX,XX +XXX,XX @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
19
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
24
/* Vector cryptography extensions */
20
mcc->parent_realize(dev, errp);
25
MULTI_EXT_CFG_BOOL("zvbb", ext_zvbb, false),
21
}
26
MULTI_EXT_CFG_BOOL("zvbc", ext_zvbc, false),
22
27
- MULTI_EXT_CFG_BOOL("zvkb", ext_zvkg, false),
23
+#ifndef CONFIG_USER_ONLY
28
+ MULTI_EXT_CFG_BOOL("zvkb", ext_zvkb, false),
24
+static void riscv_cpu_set_irq(void *opaque, int irq, int level)
29
MULTI_EXT_CFG_BOOL("zvkg", ext_zvkg, false),
25
+{
30
MULTI_EXT_CFG_BOOL("zvkned", ext_zvkned, false),
26
+ RISCVCPU *cpu = RISCV_CPU(opaque);
31
MULTI_EXT_CFG_BOOL("zvknha", ext_zvknha, false),
27
+
28
+ switch (irq) {
29
+ case IRQ_U_SOFT:
30
+ case IRQ_S_SOFT:
31
+ case IRQ_VS_SOFT:
32
+ case IRQ_M_SOFT:
33
+ case IRQ_U_TIMER:
34
+ case IRQ_S_TIMER:
35
+ case IRQ_VS_TIMER:
36
+ case IRQ_M_TIMER:
37
+ case IRQ_U_EXT:
38
+ case IRQ_S_EXT:
39
+ case IRQ_VS_EXT:
40
+ case IRQ_M_EXT:
41
+ riscv_cpu_update_mip(cpu, 1 << irq, BOOL_TO_MASK(level));
42
+ break;
43
+ default:
44
+ g_assert_not_reached();
45
+ }
46
+}
47
+#endif /* CONFIG_USER_ONLY */
48
+
49
static void riscv_cpu_init(Object *obj)
50
{
51
RISCVCPU *cpu = RISCV_CPU(obj);
52
53
cpu_set_cpustate_pointers(cpu);
54
+
55
+#ifndef CONFIG_USER_ONLY
56
+ qdev_init_gpio_in(DEVICE(cpu), riscv_cpu_set_irq, 12);
57
+#endif /* CONFIG_USER_ONLY */
58
}
59
60
static Property riscv_cpu_properties[] = {
32
--
61
--
33
2.45.1
62
2.31.1
34
63
35
64
diff view generated by jsdifflib
1
From: Jason Chien <jason.chien@sifive.com>
1
From: Alistair Francis <alistair.francis@wdc.com>
2
2
3
Add support for Zve32x extension and replace some checks for Zve32f with
3
Instead of using riscv_cpu_update_mip() let's instead use the new RISC-V
4
Zve32x, since Zve32f depends on Zve32x.
4
CPU GPIO lines to set the timer and soft MIP bits.
5
5
6
Signed-off-by: Jason Chien <jason.chien@sifive.com>
7
Reviewed-by: Frank Chang <frank.chang@sifive.com>
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>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
6
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
7
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
8
Tested-by: Bin Meng <bmeng.cn@gmail.com>
9
Reviewed-by: LIU Zhiwei <zhiwei_liu@c-sky.com>
10
Message-id: 946e1ef5e268b24084c7ddad84c146de62a56736.1630301632.git.alistair.francis@wdc.com
12
---
11
---
13
target/riscv/cpu_cfg.h | 1 +
12
include/hw/intc/sifive_clint.h | 2 +
14
target/riscv/cpu.c | 2 ++
13
hw/intc/sifive_clint.c | 68 ++++++++++++++++++++++++----------
15
target/riscv/cpu_helper.c | 2 +-
14
2 files changed, 50 insertions(+), 20 deletions(-)
16
target/riscv/csr.c | 2 +-
17
target/riscv/tcg/tcg-cpu.c | 16 ++++++++--------
18
target/riscv/insn_trans/trans_rvv.c.inc | 4 ++--
19
6 files changed, 15 insertions(+), 12 deletions(-)
20
15
21
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
16
diff --git a/include/hw/intc/sifive_clint.h b/include/hw/intc/sifive_clint.h
22
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
23
--- a/target/riscv/cpu_cfg.h
18
--- a/include/hw/intc/sifive_clint.h
24
+++ b/target/riscv/cpu_cfg.h
19
+++ b/include/hw/intc/sifive_clint.h
25
@@ -XXX,XX +XXX,XX @@ struct RISCVCPUConfig {
20
@@ -XXX,XX +XXX,XX @@ typedef struct SiFiveCLINTState {
26
bool ext_zhinx;
21
uint32_t time_base;
27
bool ext_zhinxmin;
22
uint32_t aperture_size;
28
bool ext_zve32f;
23
uint32_t timebase_freq;
29
+ bool ext_zve32x;
24
+ qemu_irq *timer_irqs;
30
bool ext_zve64f;
25
+ qemu_irq *soft_irqs;
31
bool ext_zve64d;
26
} SiFiveCLINTState;
32
bool ext_zvbb;
27
33
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
28
DeviceState *sifive_clint_create(hwaddr addr, hwaddr size,
29
diff --git a/hw/intc/sifive_clint.c b/hw/intc/sifive_clint.c
34
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
35
--- a/target/riscv/cpu.c
31
--- a/hw/intc/sifive_clint.c
36
+++ b/target/riscv/cpu.c
32
+++ b/hw/intc/sifive_clint.c
37
@@ -XXX,XX +XXX,XX @@ const RISCVIsaExtData isa_edata_arr[] = {
33
@@ -XXX,XX +XXX,XX @@
38
ISA_EXT_DATA_ENTRY(zvbb, PRIV_VERSION_1_12_0, ext_zvbb),
34
#include "hw/qdev-properties.h"
39
ISA_EXT_DATA_ENTRY(zvbc, PRIV_VERSION_1_12_0, ext_zvbc),
35
#include "hw/intc/sifive_clint.h"
40
ISA_EXT_DATA_ENTRY(zve32f, PRIV_VERSION_1_10_0, ext_zve32f),
36
#include "qemu/timer.h"
41
+ ISA_EXT_DATA_ENTRY(zve32x, PRIV_VERSION_1_10_0, ext_zve32x),
37
+#include "hw/irq.h"
42
ISA_EXT_DATA_ENTRY(zve64f, PRIV_VERSION_1_10_0, ext_zve64f),
38
+
43
ISA_EXT_DATA_ENTRY(zve64d, PRIV_VERSION_1_10_0, ext_zve64d),
39
+typedef struct sifive_clint_callback {
44
ISA_EXT_DATA_ENTRY(zvfbfmin, PRIV_VERSION_1_12_0, ext_zvfbfmin),
40
+ SiFiveCLINTState *s;
45
@@ -XXX,XX +XXX,XX @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
41
+ int num;
46
MULTI_EXT_CFG_BOOL("zfh", ext_zfh, false),
42
+} sifive_clint_callback;
47
MULTI_EXT_CFG_BOOL("zfhmin", ext_zfhmin, false),
43
48
MULTI_EXT_CFG_BOOL("zve32f", ext_zve32f, false),
44
static uint64_t cpu_riscv_read_rtc(uint32_t timebase_freq)
49
+ MULTI_EXT_CFG_BOOL("zve32x", ext_zve32x, false),
50
MULTI_EXT_CFG_BOOL("zve64f", ext_zve64f, false),
51
MULTI_EXT_CFG_BOOL("zve64d", ext_zve64d, false),
52
MULTI_EXT_CFG_BOOL("zvfbfmin", ext_zvfbfmin, false),
53
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
54
index XXXXXXX..XXXXXXX 100644
55
--- a/target/riscv/cpu_helper.c
56
+++ b/target/riscv/cpu_helper.c
57
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
58
*pc = env->xl == MXL_RV32 ? env->pc & UINT32_MAX : env->pc;
59
*cs_base = 0;
60
61
- if (cpu->cfg.ext_zve32f) {
62
+ if (cpu->cfg.ext_zve32x) {
63
/*
64
* If env->vl equals to VLMAX, we can use generic vector operation
65
* expanders (GVEC) to accerlate the vector operations.
66
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/target/riscv/csr.c
69
+++ b/target/riscv/csr.c
70
@@ -XXX,XX +XXX,XX @@ static RISCVException fs(CPURISCVState *env, int csrno)
71
72
static RISCVException vs(CPURISCVState *env, int csrno)
73
{
45
{
74
- if (riscv_cpu_cfg(env)->ext_zve32f) {
46
@@ -XXX,XX +XXX,XX @@ static uint64_t cpu_riscv_read_rtc(uint32_t timebase_freq)
75
+ if (riscv_cpu_cfg(env)->ext_zve32x) {
47
* Called when timecmp is written to update the QEMU timer or immediately
76
#if !defined(CONFIG_USER_ONLY)
48
* trigger timer interrupt if mtimecmp <= current timer value.
77
if (!env->debugger && !riscv_cpu_vector_enabled(env)) {
49
*/
78
return RISCV_EXCP_ILLEGAL_INST;
50
-static void sifive_clint_write_timecmp(RISCVCPU *cpu, uint64_t value,
79
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
51
+static void sifive_clint_write_timecmp(SiFiveCLINTState *s, RISCVCPU *cpu,
80
index XXXXXXX..XXXXXXX 100644
52
+ int hartid,
81
--- a/target/riscv/tcg/tcg-cpu.c
53
+ uint64_t value,
82
+++ b/target/riscv/tcg/tcg-cpu.c
54
uint32_t timebase_freq)
83
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
55
{
56
uint64_t next;
57
@@ -XXX,XX +XXX,XX @@ static void sifive_clint_write_timecmp(RISCVCPU *cpu, uint64_t value,
58
if (cpu->env.timecmp <= rtc_r) {
59
/* if we're setting an MTIMECMP value in the "past",
60
immediately raise the timer interrupt */
61
- riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(1));
62
+ qemu_irq_raise(s->timer_irqs[hartid - s->hartid_base]);
84
return;
63
return;
85
}
64
}
86
65
87
- if (cpu->cfg.ext_zve32f && !riscv_has_ext(env, RVF)) {
66
/* otherwise, set up the future timer interrupt */
88
- error_setg(errp, "Zve32f/Zve64f extensions require F extension");
67
- riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(0));
89
- return;
68
+ qemu_irq_lower(s->timer_irqs[hartid - s->hartid_base]);
90
+ /* The Zve32f extension depends on the Zve32x extension */
69
diff = cpu->env.timecmp - rtc_r;
91
+ if (cpu->cfg.ext_zve32f) {
70
/* back to ns (note args switched in muldiv64) */
92
+ if (!riscv_has_ext(env, RVF)) {
71
uint64_t ns_diff = muldiv64(diff, NANOSECONDS_PER_SECOND, timebase_freq);
93
+ error_setg(errp, "Zve32f/Zve64f extensions require F extension");
72
@@ -XXX,XX +XXX,XX @@ static void sifive_clint_write_timecmp(RISCVCPU *cpu, uint64_t value,
94
+ return;
73
*/
95
+ }
74
static void sifive_clint_timer_cb(void *opaque)
96
+ cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve32x), true);
75
{
76
- RISCVCPU *cpu = opaque;
77
- riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(1));
78
+ sifive_clint_callback *state = opaque;
79
+
80
+ qemu_irq_raise(state->s->timer_irqs[state->num]);
81
}
82
83
/* CPU wants to read rtc or timecmp register */
84
@@ -XXX,XX +XXX,XX @@ static void sifive_clint_write(void *opaque, hwaddr addr, uint64_t value,
85
if (!env) {
86
error_report("clint: invalid timecmp hartid: %zu", hartid);
87
} else if ((addr & 0x3) == 0) {
88
- riscv_cpu_update_mip(RISCV_CPU(cpu), MIP_MSIP, BOOL_TO_MASK(value));
89
+ qemu_set_irq(clint->soft_irqs[hartid - clint->hartid_base], value);
90
} else {
91
error_report("clint: invalid sip write: %08x", (uint32_t)addr);
92
}
93
@@ -XXX,XX +XXX,XX @@ static void sifive_clint_write(void *opaque, hwaddr addr, uint64_t value,
94
} else if ((addr & 0x7) == 0) {
95
/* timecmp_lo */
96
uint64_t timecmp_hi = env->timecmp >> 32;
97
- sifive_clint_write_timecmp(RISCV_CPU(cpu),
98
+ sifive_clint_write_timecmp(clint, RISCV_CPU(cpu), hartid,
99
timecmp_hi << 32 | (value & 0xFFFFFFFF), clint->timebase_freq);
100
return;
101
} else if ((addr & 0x7) == 4) {
102
/* timecmp_hi */
103
uint64_t timecmp_lo = env->timecmp;
104
- sifive_clint_write_timecmp(RISCV_CPU(cpu),
105
+ sifive_clint_write_timecmp(clint, RISCV_CPU(cpu), hartid,
106
value << 32 | (timecmp_lo & 0xFFFFFFFF), clint->timebase_freq);
107
} else {
108
error_report("clint: invalid timecmp write: %08x", (uint32_t)addr);
109
@@ -XXX,XX +XXX,XX @@ static void sifive_clint_realize(DeviceState *dev, Error **errp)
110
memory_region_init_io(&s->mmio, OBJECT(dev), &sifive_clint_ops, s,
111
TYPE_SIFIVE_CLINT, s->aperture_size);
112
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
113
+
114
+ s->timer_irqs = g_malloc(sizeof(qemu_irq) * s->num_harts);
115
+ qdev_init_gpio_out(dev, s->timer_irqs, s->num_harts);
116
+
117
+ s->soft_irqs = g_malloc(sizeof(qemu_irq) * s->num_harts);
118
+ qdev_init_gpio_out(dev, s->soft_irqs, s->num_harts);
119
}
120
121
static void sifive_clint_class_init(ObjectClass *klass, void *data)
122
@@ -XXX,XX +XXX,XX @@ static void sifive_clint_register_types(void)
123
124
type_init(sifive_clint_register_types)
125
126
-
127
/*
128
* Create CLINT device.
129
*/
130
@@ -XXX,XX +XXX,XX @@ DeviceState *sifive_clint_create(hwaddr addr, hwaddr size,
131
bool provide_rdtime)
132
{
133
int i;
134
+
135
+ DeviceState *dev = qdev_new(TYPE_SIFIVE_CLINT);
136
+ qdev_prop_set_uint32(dev, "hartid-base", hartid_base);
137
+ qdev_prop_set_uint32(dev, "num-harts", num_harts);
138
+ qdev_prop_set_uint32(dev, "sip-base", sip_base);
139
+ qdev_prop_set_uint32(dev, "timecmp-base", timecmp_base);
140
+ qdev_prop_set_uint32(dev, "time-base", time_base);
141
+ qdev_prop_set_uint32(dev, "aperture-size", size);
142
+ qdev_prop_set_uint32(dev, "timebase-freq", timebase_freq);
143
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
144
+ sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
145
+
146
for (i = 0; i < num_harts; i++) {
147
CPUState *cpu = qemu_get_cpu(hartid_base + i);
148
+ RISCVCPU *rvcpu = RISCV_CPU(cpu);
149
CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
150
+ sifive_clint_callback *cb = g_malloc0(sizeof(sifive_clint_callback));
151
+
152
if (!env) {
153
+ g_free(cb);
154
continue;
155
}
156
if (provide_rdtime) {
157
riscv_cpu_set_rdtime_fn(env, cpu_riscv_read_rtc, timebase_freq);
158
}
159
+
160
+ cb->s = SIFIVE_CLINT(dev);
161
+ cb->num = i;
162
env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
163
- &sifive_clint_timer_cb, cpu);
164
+ &sifive_clint_timer_cb, cb);
165
env->timecmp = 0;
166
+
167
+ qdev_connect_gpio_out(dev, i,
168
+ qdev_get_gpio_in(DEVICE(rvcpu), IRQ_M_TIMER));
169
+ qdev_connect_gpio_out(dev, num_harts + i,
170
+ qdev_get_gpio_in(DEVICE(rvcpu), IRQ_M_SOFT));
97
}
171
}
98
172
99
if (cpu->cfg.ext_zvfh) {
173
- DeviceState *dev = qdev_new(TYPE_SIFIVE_CLINT);
100
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
174
- qdev_prop_set_uint32(dev, "hartid-base", hartid_base);
101
cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvbc), true);
175
- qdev_prop_set_uint32(dev, "num-harts", num_harts);
102
}
176
- qdev_prop_set_uint32(dev, "sip-base", sip_base);
103
177
- qdev_prop_set_uint32(dev, "timecmp-base", timecmp_base);
104
- /*
178
- qdev_prop_set_uint32(dev, "time-base", time_base);
105
- * In principle Zve*x would also suffice here, were they supported
179
- qdev_prop_set_uint32(dev, "aperture-size", size);
106
- * in qemu
180
- qdev_prop_set_uint32(dev, "timebase-freq", timebase_freq);
107
- */
181
- sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
108
if ((cpu->cfg.ext_zvbb || cpu->cfg.ext_zvkb || cpu->cfg.ext_zvkg ||
182
- sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
109
cpu->cfg.ext_zvkned || cpu->cfg.ext_zvknha || cpu->cfg.ext_zvksed ||
183
return dev;
110
- cpu->cfg.ext_zvksh) && !cpu->cfg.ext_zve32f) {
184
}
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)
120
{
121
TCGv s1, dst;
122
123
- if (!require_rvv(s) || !s->cfg_ptr->ext_zve32f) {
124
+ if (!require_rvv(s) || !s->cfg_ptr->ext_zve32x) {
125
return false;
126
}
127
128
@@ -XXX,XX +XXX,XX @@ static bool do_vsetivli(DisasContext *s, int rd, TCGv s1, TCGv s2)
129
{
130
TCGv dst;
131
132
- if (!require_rvv(s) || !s->cfg_ptr->ext_zve32f) {
133
+ if (!require_rvv(s) || !s->cfg_ptr->ext_zve32x) {
134
return false;
135
}
136
137
--
185
--
138
2.45.1
186
2.31.1
187
188
diff view generated by jsdifflib
1
From: Huang Tao <eric.huang@linux.alibaba.com>
1
From: Alistair Francis <alistair.francis@wdc.com>
2
2
3
In this patch, we modify the decoder to be a freely composable data
3
Instead of using riscv_cpu_update_mip() let's instead use the new RISC-V
4
structure instead of a hardcoded one. It can be dynamically builded up
4
CPU GPIO lines to set the external MIP bits.
5
according to the extensions.
6
This approach has several benefits:
7
1. Provides support for heterogeneous cpu architectures. As we add decoder in
8
RISCVCPU, each cpu can have their own decoder, and the decoders can be
9
different due to cpu's features.
10
2. Improve the decoding efficiency. We run the guard_func to see if the decoder
11
can be added to the dynamic_decoder when building up the decoder. Therefore,
12
there is no need to run the guard_func when decoding each instruction. It can
13
improve the decoding efficiency
14
3. For vendor or dynamic cpus, it allows them to customize their own decoder
15
functions to improve decoding efficiency, especially when vendor-defined
16
instruction sets increase. Because of dynamic building up, it can skip the other
17
decoder guard functions when decoding.
18
4. Pre patch for allowing adding a vendor decoder before decode_insn32() with minimal
19
overhead for users that don't need this particular vendor decoder.
20
5
21
Signed-off-by: Huang Tao <eric.huang@linux.alibaba.com>
6
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
22
Suggested-by: Christoph Muellner <christoph.muellner@vrull.eu>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
23
Co-authored-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
24
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
25
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Message-id: 0a76946981852f5bd15f0c37ab35b253371027a8.1630301632.git.alistair.francis@wdc.com
26
Message-ID: <20240506023607.29544-1-eric.huang@linux.alibaba.com>
27
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
28
---
10
---
29
target/riscv/cpu.h | 1 +
11
include/hw/intc/ibex_plic.h | 2 ++
30
target/riscv/tcg/tcg-cpu.h | 15 +++++++++++++++
12
hw/intc/ibex_plic.c | 17 ++++++-----------
31
target/riscv/cpu.c | 1 +
13
hw/riscv/opentitan.c | 8 ++++++++
32
target/riscv/tcg/tcg-cpu.c | 15 +++++++++++++++
14
3 files changed, 16 insertions(+), 11 deletions(-)
33
target/riscv/translate.c | 31 +++++++++++++++----------------
34
5 files changed, 47 insertions(+), 16 deletions(-)
35
15
36
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
16
diff --git a/include/hw/intc/ibex_plic.h b/include/hw/intc/ibex_plic.h
37
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
38
--- a/target/riscv/cpu.h
18
--- a/include/hw/intc/ibex_plic.h
39
+++ b/target/riscv/cpu.h
19
+++ b/include/hw/intc/ibex_plic.h
40
@@ -XXX,XX +XXX,XX @@ struct ArchCPU {
20
@@ -XXX,XX +XXX,XX @@ struct IbexPlicState {
41
uint32_t pmu_avail_ctrs;
21
uint32_t threshold_base;
42
/* Mapping of events to counters */
22
43
GHashTable *pmu_event_ctr_map;
23
uint32_t claim_base;
44
+ const GPtrArray *decoders;
24
+
25
+ qemu_irq *external_irqs;
45
};
26
};
46
27
47
/**
28
#endif /* HW_IBEX_PLIC_H */
48
diff --git a/target/riscv/tcg/tcg-cpu.h b/target/riscv/tcg/tcg-cpu.h
29
diff --git a/hw/intc/ibex_plic.c b/hw/intc/ibex_plic.c
49
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
50
--- a/target/riscv/tcg/tcg-cpu.h
31
--- a/hw/intc/ibex_plic.c
51
+++ b/target/riscv/tcg/tcg-cpu.h
32
+++ b/hw/intc/ibex_plic.c
52
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp);
33
@@ -XXX,XX +XXX,XX @@
53
void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp);
34
#include "target/riscv/cpu_bits.h"
54
bool riscv_cpu_tcg_compatible(RISCVCPU *cpu);
35
#include "target/riscv/cpu.h"
55
36
#include "hw/intc/ibex_plic.h"
56
+struct DisasContext;
37
+#include "hw/irq.h"
57
+struct RISCVCPUConfig;
38
58
+typedef struct RISCVDecoder {
39
static bool addr_between(uint32_t addr, uint32_t base, uint32_t num)
59
+ bool (*guard_func)(const struct RISCVCPUConfig *);
40
{
60
+ bool (*riscv_cpu_decode_fn)(struct DisasContext *, uint32_t);
41
@@ -XXX,XX +XXX,XX @@ static bool ibex_plic_irqs_pending(IbexPlicState *s, uint32_t context)
61
+} RISCVDecoder;
42
62
+
43
static void ibex_plic_update(IbexPlicState *s)
63
+typedef bool (*riscv_cpu_decode_fn)(struct DisasContext *, uint32_t);
44
{
64
+
45
- CPUState *cpu;
65
+extern const size_t decoder_table_size;
46
- int level, i;
66
+
47
+ int i;
67
+extern const RISCVDecoder decoder_table[];
48
68
+
49
for (i = 0; i < s->num_cpus; i++) {
69
+void riscv_tcg_cpu_finalize_dynamic_decoder(RISCVCPU *cpu);
50
- cpu = qemu_get_cpu(i);
70
+
51
-
71
#endif
52
- if (!cpu) {
72
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
53
- continue;
73
index XXXXXXX..XXXXXXX 100644
54
- }
74
--- a/target/riscv/cpu.c
55
-
75
+++ b/target/riscv/cpu.c
56
- level = ibex_plic_irqs_pending(s, 0);
76
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_finalize_features(RISCVCPU *cpu, Error **errp)
57
-
77
error_propagate(errp, local_err);
58
- riscv_cpu_update_mip(RISCV_CPU(cpu), MIP_MEIP, BOOL_TO_MASK(level));
78
return;
59
+ qemu_set_irq(s->external_irqs[i], ibex_plic_irqs_pending(s, 0));
79
}
80
+ riscv_tcg_cpu_finalize_dynamic_decoder(cpu);
81
} else if (kvm_enabled()) {
82
riscv_kvm_cpu_finalize_features(cpu, &local_err);
83
if (local_err != NULL) {
84
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
85
index XXXXXXX..XXXXXXX 100644
86
--- a/target/riscv/tcg/tcg-cpu.c
87
+++ b/target/riscv/tcg/tcg-cpu.c
88
@@ -XXX,XX +XXX,XX @@ void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp)
89
}
60
}
90
}
61
}
91
62
92
+void riscv_tcg_cpu_finalize_dynamic_decoder(RISCVCPU *cpu)
63
@@ -XXX,XX +XXX,XX @@ static void ibex_plic_realize(DeviceState *dev, Error **errp)
93
+{
64
94
+ GPtrArray *dynamic_decoders;
65
qdev_init_gpio_in(dev, ibex_plic_irq_request, s->num_sources);
95
+ dynamic_decoders = g_ptr_array_sized_new(decoder_table_size);
66
96
+ for (size_t i = 0; i < decoder_table_size; ++i) {
67
+ s->external_irqs = g_malloc(sizeof(qemu_irq) * s->num_cpus);
97
+ if (decoder_table[i].guard_func &&
68
+ qdev_init_gpio_out(dev, s->external_irqs, s->num_cpus);
98
+ decoder_table[i].guard_func(&cpu->cfg)) {
69
+
99
+ g_ptr_array_add(dynamic_decoders,
70
/*
100
+ (gpointer)decoder_table[i].riscv_cpu_decode_fn);
71
* We can't allow the supervisor to control SEIP as this would allow the
101
+ }
72
* supervisor to clear a pending external interrupt which will result in
73
diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/hw/riscv/opentitan.c
76
+++ b/hw/riscv/opentitan.c
77
@@ -XXX,XX +XXX,XX @@ static void lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp)
78
MachineState *ms = MACHINE(qdev_get_machine());
79
LowRISCIbexSoCState *s = RISCV_IBEX_SOC(dev_soc);
80
MemoryRegion *sys_mem = get_system_memory();
81
+ int i;
82
83
object_property_set_str(OBJECT(&s->cpus), "cpu-type", ms->cpu_type,
84
&error_abort);
85
@@ -XXX,XX +XXX,XX @@ static void lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp)
86
}
87
sysbus_mmio_map(SYS_BUS_DEVICE(&s->plic), 0, memmap[IBEX_DEV_PLIC].base);
88
89
+ for (i = 0; i < ms->smp.cpus; i++) {
90
+ CPUState *cpu = qemu_get_cpu(i);
91
+
92
+ qdev_connect_gpio_out(DEVICE(&s->plic), i,
93
+ qdev_get_gpio_in(DEVICE(cpu), IRQ_M_EXT));
102
+ }
94
+ }
103
+
95
+
104
+ cpu->decoders = dynamic_decoders;
96
/* UART */
105
+}
97
qdev_prop_set_chr(DEVICE(&(s->uart)), "chardev", serial_hd(0));
106
+
98
if (!sysbus_realize(SYS_BUS_DEVICE(&s->uart), errp)) {
107
bool riscv_cpu_tcg_compatible(RISCVCPU *cpu)
108
{
109
return object_dynamic_cast(OBJECT(cpu), TYPE_RISCV_CPU_HOST) == NULL;
110
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
111
index XXXXXXX..XXXXXXX 100644
112
--- a/target/riscv/translate.c
113
+++ b/target/riscv/translate.c
114
@@ -XXX,XX +XXX,XX @@
115
#include "exec/helper-info.c.inc"
116
#undef HELPER_H
117
118
+#include "tcg/tcg-cpu.h"
119
+
120
/* global register indices */
121
static TCGv cpu_gpr[32], cpu_gprh[32], cpu_pc, cpu_vl, cpu_vstart;
122
static TCGv_i64 cpu_fpr[32]; /* assume F and D extensions */
123
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
124
/* FRM is known to contain a valid value. */
125
bool frm_valid;
126
bool insn_start_updated;
127
+ const GPtrArray *decoders;
128
} DisasContext;
129
130
static inline bool has_ext(DisasContext *ctx, uint32_t ext)
131
@@ -XXX,XX +XXX,XX @@ static inline int insn_len(uint16_t first_word)
132
return (first_word & 3) == 3 ? 4 : 2;
133
}
134
135
+const RISCVDecoder decoder_table[] = {
136
+ { always_true_p, decode_insn32 },
137
+ { has_xthead_p, decode_xthead},
138
+ { has_XVentanaCondOps_p, decode_XVentanaCodeOps},
139
+};
140
+
141
+const size_t decoder_table_size = ARRAY_SIZE(decoder_table);
142
+
143
static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
144
{
145
- /*
146
- * A table with predicate (i.e., guard) functions and decoder functions
147
- * that are tested in-order until a decoder matches onto the opcode.
148
- */
149
- static const struct {
150
- bool (*guard_func)(const RISCVCPUConfig *);
151
- bool (*decode_func)(DisasContext *, uint32_t);
152
- } decoders[] = {
153
- { always_true_p, decode_insn32 },
154
- { has_xthead_p, decode_xthead },
155
- { has_XVentanaCondOps_p, decode_XVentanaCodeOps },
156
- };
157
-
158
ctx->virt_inst_excp = false;
159
ctx->cur_insn_len = insn_len(opcode);
160
/* Check for compressed insn */
161
@@ -XXX,XX +XXX,XX @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
162
ctx->base.pc_next + 2));
163
ctx->opcode = opcode32;
164
165
- for (size_t i = 0; i < ARRAY_SIZE(decoders); ++i) {
166
- if (decoders[i].guard_func(ctx->cfg_ptr) &&
167
- decoders[i].decode_func(ctx, opcode32)) {
168
+ for (guint i = 0; i < ctx->decoders->len; ++i) {
169
+ riscv_cpu_decode_fn func = g_ptr_array_index(ctx->decoders, i);
170
+ if (func(ctx, opcode32)) {
171
return;
172
}
173
}
174
@@ -XXX,XX +XXX,XX @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
175
ctx->itrigger = FIELD_EX32(tb_flags, TB_FLAGS, ITRIGGER);
176
ctx->zero = tcg_constant_tl(0);
177
ctx->virt_inst_excp = false;
178
+ ctx->decoders = cpu->decoders;
179
}
180
181
static void riscv_tr_tb_start(DisasContextBase *db, CPUState *cpu)
182
--
99
--
183
2.45.1
100
2.31.1
101
102
diff view generated by jsdifflib
1
From: Yong-Xuan Wang <yongxuan.wang@sifive.com>
1
From: Alistair Francis <alistair.francis@wdc.com>
2
2
3
In AIA spec, each hart (or each hart within a group) has a unique hart
3
Instead of using riscv_cpu_update_mip() let's instead use the new RISC-V
4
number to locate the memory pages of interrupt files in the address
4
CPU GPIO lines to set the external MIP bits.
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.
8
5
9
However, if the largest hart number among groups is a power of 2, QEMU
6
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
10
will pass an inaccurate hart-index-bit setting to Linux. For example, when
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
the guest OS has 4 harts, only ceil(log2(3 + 1)) = 2 bits are sufficient
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
to represent 4 harts, but we passes 3 to Linux. The code needs to be
9
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
13
updated to ensure accurate hart-index-bit settings.
10
Tested-by: Bin Meng <bmeng.cn@gmail.com>
11
Message-id: 0364190bfa935058a845c0fa1ecf650328840ad5.1630301632.git.alistair.francis@wdc.com
12
---
13
include/hw/intc/sifive_plic.h | 4 ++++
14
hw/intc/sifive_plic.c | 30 +++++++++++++++++++++++-------
15
hw/riscv/microchip_pfsoc.c | 2 +-
16
hw/riscv/shakti_c.c | 3 ++-
17
hw/riscv/sifive_e.c | 2 +-
18
hw/riscv/sifive_u.c | 2 +-
19
hw/riscv/virt.c | 2 +-
20
7 files changed, 33 insertions(+), 12 deletions(-)
14
21
15
Additionally, a Linux patch[1] is necessary to correctly recover the hart
22
diff --git a/include/hw/intc/sifive_plic.h b/include/hw/intc/sifive_plic.h
16
index when the guest OS has only 1 hart, where the hart-index-bit is 0.
17
18
[1] https://lore.kernel.org/lkml/20240415064905.25184-1-yongxuan.wang@sifive.com/t/
19
20
Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com>
21
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
22
Cc: qemu-stable <qemu-stable@nongnu.org>
23
Message-ID: <20240515091129.28116-1-yongxuan.wang@sifive.com>
24
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
25
---
26
target/riscv/kvm/kvm-cpu.c | 9 ++++++++-
27
1 file changed, 8 insertions(+), 1 deletion(-)
28
29
diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
30
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
31
--- a/target/riscv/kvm/kvm-cpu.c
24
--- a/include/hw/intc/sifive_plic.h
32
+++ b/target/riscv/kvm/kvm-cpu.c
25
+++ b/include/hw/intc/sifive_plic.h
33
@@ -XXX,XX +XXX,XX @@ void kvm_riscv_aia_create(MachineState *machine, uint64_t group_shift,
26
@@ -XXX,XX +XXX,XX @@ struct SiFivePLICState {
34
}
27
uint32_t context_base;
35
}
28
uint32_t context_stride;
36
29
uint32_t aperture_size;
37
- hart_bits = find_last_bit(&max_hart_per_socket, BITS_PER_LONG) + 1;
38
+
30
+
39
+ if (max_hart_per_socket > 1) {
31
+ qemu_irq *m_external_irqs;
40
+ max_hart_per_socket--;
32
+ qemu_irq *s_external_irqs;
41
+ hart_bits = find_last_bit(&max_hart_per_socket, BITS_PER_LONG) + 1;
33
};
42
+ } else {
34
43
+ hart_bits = 0;
35
DeviceState *sifive_plic_create(hwaddr addr, char *hart_config,
36
+ uint32_t num_harts,
37
uint32_t hartid_base, uint32_t num_sources,
38
uint32_t num_priorities, uint32_t priority_base,
39
uint32_t pending_base, uint32_t enable_base,
40
diff --git a/hw/intc/sifive_plic.c b/hw/intc/sifive_plic.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/intc/sifive_plic.c
43
+++ b/hw/intc/sifive_plic.c
44
@@ -XXX,XX +XXX,XX @@
45
#include "hw/intc/sifive_plic.h"
46
#include "target/riscv/cpu.h"
47
#include "migration/vmstate.h"
48
+#include "hw/irq.h"
49
50
#define RISCV_DEBUG_PLIC 0
51
52
@@ -XXX,XX +XXX,XX @@ static void sifive_plic_update(SiFivePLICState *plic)
53
for (addrid = 0; addrid < plic->num_addrs; addrid++) {
54
uint32_t hartid = plic->addr_config[addrid].hartid;
55
PLICMode mode = plic->addr_config[addrid].mode;
56
- CPUState *cpu = qemu_get_cpu(hartid);
57
- CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
58
- if (!env) {
59
- continue;
60
- }
61
int level = sifive_plic_irqs_pending(plic, addrid);
62
+
63
switch (mode) {
64
case PLICMode_M:
65
- riscv_cpu_update_mip(RISCV_CPU(cpu), MIP_MEIP, BOOL_TO_MASK(level));
66
+ qemu_set_irq(plic->m_external_irqs[hartid - plic->hartid_base], level);
67
break;
68
case PLICMode_S:
69
- riscv_cpu_update_mip(RISCV_CPU(cpu), MIP_SEIP, BOOL_TO_MASK(level));
70
+ qemu_set_irq(plic->s_external_irqs[hartid - plic->hartid_base], level);
71
break;
72
default:
73
break;
74
@@ -XXX,XX +XXX,XX @@ static void sifive_plic_realize(DeviceState *dev, Error **errp)
75
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &plic->mmio);
76
qdev_init_gpio_in(dev, sifive_plic_irq_request, plic->num_sources);
77
78
+ plic->s_external_irqs = g_malloc(sizeof(qemu_irq) * plic->num_harts);
79
+ qdev_init_gpio_out(dev, plic->s_external_irqs, plic->num_harts);
80
+
81
+ plic->m_external_irqs = g_malloc(sizeof(qemu_irq) * plic->num_harts);
82
+ qdev_init_gpio_out(dev, plic->m_external_irqs, plic->num_harts);
83
+
84
/* We can't allow the supervisor to control SEIP as this would allow the
85
* supervisor to clear a pending external interrupt which will result in
86
* lost a interrupt in the case a PLIC is attached. The SEIP bit must be
87
@@ -XXX,XX +XXX,XX @@ type_init(sifive_plic_register_types)
88
* Create PLIC device.
89
*/
90
DeviceState *sifive_plic_create(hwaddr addr, char *hart_config,
91
+ uint32_t num_harts,
92
uint32_t hartid_base, uint32_t num_sources,
93
uint32_t num_priorities, uint32_t priority_base,
94
uint32_t pending_base, uint32_t enable_base,
95
@@ -XXX,XX +XXX,XX @@ DeviceState *sifive_plic_create(hwaddr addr, char *hart_config,
96
uint32_t context_stride, uint32_t aperture_size)
97
{
98
DeviceState *dev = qdev_new(TYPE_SIFIVE_PLIC);
99
+ int i;
100
+
101
assert(enable_stride == (enable_stride & -enable_stride));
102
assert(context_stride == (context_stride & -context_stride));
103
qdev_prop_set_string(dev, "hart-config", hart_config);
104
@@ -XXX,XX +XXX,XX @@ DeviceState *sifive_plic_create(hwaddr addr, char *hart_config,
105
qdev_prop_set_uint32(dev, "aperture-size", aperture_size);
106
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
107
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
108
+
109
+ for (i = 0; i < num_harts; i++) {
110
+ CPUState *cpu = qemu_get_cpu(hartid_base + i);
111
+
112
+ qdev_connect_gpio_out(dev, i,
113
+ qdev_get_gpio_in(DEVICE(cpu), IRQ_S_EXT));
114
+ qdev_connect_gpio_out(dev, num_harts + i,
115
+ qdev_get_gpio_in(DEVICE(cpu), IRQ_M_EXT));
44
+ }
116
+ }
45
+
117
+
46
ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
118
return dev;
47
KVM_DEV_RISCV_AIA_CONFIG_HART_BITS,
119
}
48
&hart_bits, true, NULL);
120
diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
121
index XXXXXXX..XXXXXXX 100644
122
--- a/hw/riscv/microchip_pfsoc.c
123
+++ b/hw/riscv/microchip_pfsoc.c
124
@@ -XXX,XX +XXX,XX @@ static void microchip_pfsoc_soc_realize(DeviceState *dev, Error **errp)
125
126
/* PLIC */
127
s->plic = sifive_plic_create(memmap[MICROCHIP_PFSOC_PLIC].base,
128
- plic_hart_config, 0,
129
+ plic_hart_config, ms->smp.cpus, 0,
130
MICROCHIP_PFSOC_PLIC_NUM_SOURCES,
131
MICROCHIP_PFSOC_PLIC_NUM_PRIORITIES,
132
MICROCHIP_PFSOC_PLIC_PRIORITY_BASE,
133
diff --git a/hw/riscv/shakti_c.c b/hw/riscv/shakti_c.c
134
index XXXXXXX..XXXXXXX 100644
135
--- a/hw/riscv/shakti_c.c
136
+++ b/hw/riscv/shakti_c.c
137
@@ -XXX,XX +XXX,XX @@ type_init(shakti_c_machine_type_info_register)
138
139
static void shakti_c_soc_state_realize(DeviceState *dev, Error **errp)
140
{
141
+ MachineState *ms = MACHINE(qdev_get_machine());
142
ShaktiCSoCState *sss = RISCV_SHAKTI_SOC(dev);
143
MemoryRegion *system_memory = get_system_memory();
144
145
sysbus_realize(SYS_BUS_DEVICE(&sss->cpus), &error_abort);
146
147
sss->plic = sifive_plic_create(shakti_c_memmap[SHAKTI_C_PLIC].base,
148
- (char *)SHAKTI_C_PLIC_HART_CONFIG, 0,
149
+ (char *)SHAKTI_C_PLIC_HART_CONFIG, ms->smp.cpus, 0,
150
SHAKTI_C_PLIC_NUM_SOURCES,
151
SHAKTI_C_PLIC_NUM_PRIORITIES,
152
SHAKTI_C_PLIC_PRIORITY_BASE,
153
diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
154
index XXXXXXX..XXXXXXX 100644
155
--- a/hw/riscv/sifive_e.c
156
+++ b/hw/riscv/sifive_e.c
157
@@ -XXX,XX +XXX,XX @@ static void sifive_e_soc_realize(DeviceState *dev, Error **errp)
158
159
/* MMIO */
160
s->plic = sifive_plic_create(memmap[SIFIVE_E_DEV_PLIC].base,
161
- (char *)SIFIVE_E_PLIC_HART_CONFIG, 0,
162
+ (char *)SIFIVE_E_PLIC_HART_CONFIG, ms->smp.cpus, 0,
163
SIFIVE_E_PLIC_NUM_SOURCES,
164
SIFIVE_E_PLIC_NUM_PRIORITIES,
165
SIFIVE_E_PLIC_PRIORITY_BASE,
166
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
167
index XXXXXXX..XXXXXXX 100644
168
--- a/hw/riscv/sifive_u.c
169
+++ b/hw/riscv/sifive_u.c
170
@@ -XXX,XX +XXX,XX @@ static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
171
172
/* MMIO */
173
s->plic = sifive_plic_create(memmap[SIFIVE_U_DEV_PLIC].base,
174
- plic_hart_config, 0,
175
+ plic_hart_config, ms->smp.cpus, 0,
176
SIFIVE_U_PLIC_NUM_SOURCES,
177
SIFIVE_U_PLIC_NUM_PRIORITIES,
178
SIFIVE_U_PLIC_PRIORITY_BASE,
179
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
180
index XXXXXXX..XXXXXXX 100644
181
--- a/hw/riscv/virt.c
182
+++ b/hw/riscv/virt.c
183
@@ -XXX,XX +XXX,XX @@ static void virt_machine_init(MachineState *machine)
184
/* Per-socket PLIC */
185
s->plic[i] = sifive_plic_create(
186
memmap[VIRT_PLIC].base + i * memmap[VIRT_PLIC].size,
187
- plic_hart_config, base_hartid,
188
+ plic_hart_config, hart_count, base_hartid,
189
VIRT_PLIC_NUM_SOURCES,
190
VIRT_PLIC_NUM_PRIORITIES,
191
VIRT_PLIC_PRIORITY_BASE,
49
--
192
--
50
2.45.1
193
2.31.1
194
195
diff view generated by jsdifflib
1
From: Andrew Jones <ajones@ventanamicro.com>
1
From: Alistair Francis <alistair.francis@wdc.com>
2
2
3
Implementing wrs.nto to always just return is consistent with the
3
Instead of using riscv_cpu_update_mip() let's instead use the new RISC-V
4
specification, as the instruction is permitted to terminate the
4
CPU GPIO lines to set the timer MIP bits.
5
stall for any reason, but it's not useful for virtualization, where
6
we'd like the guest to trap to the hypervisor in order to allow
7
scheduling of the lock holding VCPU. Change to always immediately
8
raise exceptions when the appropriate conditions are present,
9
otherwise continue to just return. Note, immediately raising
10
exceptions is also consistent with the specification since the
11
time limit that should expire prior to the exception is
12
implementation-specific.
13
5
14
Signed-off-by: Andrew Jones <ajones@ventanamicro.com>
15
Reviewed-by: Christoph Müllner <christoph.muellner@vrull.eu>
16
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
17
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
18
Message-ID: <20240424142808.62936-2-ajones@ventanamicro.com>
19
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
6
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 84d5b1d5783d2e79eee69a2f7ac480cc0c070db3.1630301632.git.alistair.francis@wdc.com
20
---
10
---
21
target/riscv/helper.h | 1 +
11
include/hw/timer/ibex_timer.h | 2 ++
22
target/riscv/op_helper.c | 11 ++++++++
12
hw/riscv/opentitan.c | 3 +++
23
target/riscv/insn_trans/trans_rvzawrs.c.inc | 29 ++++++++++++++-------
13
hw/timer/ibex_timer.c | 17 ++++++++++++-----
24
3 files changed, 32 insertions(+), 9 deletions(-)
14
3 files changed, 17 insertions(+), 5 deletions(-)
25
15
26
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
16
diff --git a/include/hw/timer/ibex_timer.h b/include/hw/timer/ibex_timer.h
27
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
28
--- a/target/riscv/helper.h
18
--- a/include/hw/timer/ibex_timer.h
29
+++ b/target/riscv/helper.h
19
+++ b/include/hw/timer/ibex_timer.h
30
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_6(csrrw_i128, tl, env, int, tl, tl, tl, tl)
20
@@ -XXX,XX +XXX,XX @@ struct IbexTimerState {
31
DEF_HELPER_1(sret, tl, env)
21
uint32_t timebase_freq;
32
DEF_HELPER_1(mret, tl, env)
22
33
DEF_HELPER_1(wfi, void, env)
23
qemu_irq irq;
34
+DEF_HELPER_1(wrs_nto, void, env)
24
+
35
DEF_HELPER_1(tlb_flush, void, env)
25
+ qemu_irq m_timer_irq;
36
DEF_HELPER_1(tlb_flush_all, void, env)
26
};
37
/* Native Debug */
27
#endif /* HW_IBEX_TIMER_H */
38
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
28
diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c
39
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
40
--- a/target/riscv/op_helper.c
30
--- a/hw/riscv/opentitan.c
41
+++ b/target/riscv/op_helper.c
31
+++ b/hw/riscv/opentitan.c
42
@@ -XXX,XX +XXX,XX @@ void helper_wfi(CPURISCVState *env)
32
@@ -XXX,XX +XXX,XX @@ static void lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp)
33
sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer),
34
0, qdev_get_gpio_in(DEVICE(&s->plic),
35
IBEX_TIMER_TIMEREXPIRED0_0));
36
+ qdev_connect_gpio_out(DEVICE(&s->timer), 0,
37
+ qdev_get_gpio_in(DEVICE(qemu_get_cpu(0)),
38
+ IRQ_M_TIMER));
39
40
create_unimplemented_device("riscv.lowrisc.ibex.gpio",
41
memmap[IBEX_DEV_GPIO].base, memmap[IBEX_DEV_GPIO].size);
42
diff --git a/hw/timer/ibex_timer.c b/hw/timer/ibex_timer.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/timer/ibex_timer.c
45
+++ b/hw/timer/ibex_timer.c
46
@@ -XXX,XX +XXX,XX @@ static void ibex_timer_update_irqs(IbexTimerState *s)
47
/*
48
* If the mtimecmp was in the past raise the interrupt now.
49
*/
50
- riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(1));
51
+ qemu_irq_raise(s->m_timer_irq);
52
if (s->timer_intr_enable & R_INTR_ENABLE_IE_0_MASK) {
53
s->timer_intr_state |= R_INTR_STATE_IS_0_MASK;
54
qemu_set_irq(s->irq, true);
55
@@ -XXX,XX +XXX,XX @@ static void ibex_timer_update_irqs(IbexTimerState *s)
43
}
56
}
57
58
/* Setup a timer to trigger the interrupt in the future */
59
- riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(0));
60
+ qemu_irq_lower(s->m_timer_irq);
61
qemu_set_irq(s->irq, false);
62
63
diff = cpu->env.timecmp - now;
64
@@ -XXX,XX +XXX,XX @@ static void ibex_timer_update_irqs(IbexTimerState *s)
65
static void ibex_timer_cb(void *opaque)
66
{
67
IbexTimerState *s = opaque;
68
- CPUState *cs = qemu_get_cpu(0);
69
- RISCVCPU *cpu = RISCV_CPU(cs);
70
71
- riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(1));
72
+ qemu_irq_raise(s->m_timer_irq);
73
if (s->timer_intr_enable & R_INTR_ENABLE_IE_0_MASK) {
74
s->timer_intr_state |= R_INTR_STATE_IS_0_MASK;
75
qemu_set_irq(s->irq, true);
76
@@ -XXX,XX +XXX,XX @@ static void ibex_timer_init(Object *obj)
77
sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
44
}
78
}
45
79
46
+void helper_wrs_nto(CPURISCVState *env)
80
+static void ibex_timer_realize(DeviceState *dev, Error **errp)
47
+{
81
+{
48
+ if (env->virt_enabled && (env->priv == PRV_S || env->priv == PRV_U) &&
82
+ IbexTimerState *s = IBEX_TIMER(dev);
49
+ get_field(env->hstatus, HSTATUS_VTW) &&
83
+
50
+ !get_field(env->mstatus, MSTATUS_TW)) {
84
+ qdev_init_gpio_out(dev, &s->m_timer_irq, 1);
51
+ riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC());
52
+ } else if (env->priv != PRV_M && get_field(env->mstatus, MSTATUS_TW)) {
53
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
54
+ }
55
+}
85
+}
56
+
86
+
57
void helper_tlb_flush(CPURISCVState *env)
87
+
88
static void ibex_timer_class_init(ObjectClass *klass, void *data)
58
{
89
{
59
CPUState *cs = env_cpu(env);
90
DeviceClass *dc = DEVICE_CLASS(klass);
60
diff --git a/target/riscv/insn_trans/trans_rvzawrs.c.inc b/target/riscv/insn_trans/trans_rvzawrs.c.inc
91
61
index XXXXXXX..XXXXXXX 100644
92
dc->reset = ibex_timer_reset;
62
--- a/target/riscv/insn_trans/trans_rvzawrs.c.inc
93
dc->vmsd = &vmstate_ibex_timer;
63
+++ b/target/riscv/insn_trans/trans_rvzawrs.c.inc
94
+ dc->realize = ibex_timer_realize;
64
@@ -XXX,XX +XXX,XX @@
95
device_class_set_props(dc, ibex_timer_properties);
65
* this program. If not, see <http://www.gnu.org/licenses/>.
66
*/
67
68
-static bool trans_wrs(DisasContext *ctx)
69
+static bool trans_wrs_sto(DisasContext *ctx, arg_wrs_sto *a)
70
{
71
if (!ctx->cfg_ptr->ext_zawrs) {
72
return false;
73
@@ -XXX,XX +XXX,XX @@ static bool trans_wrs(DisasContext *ctx)
74
return true;
75
}
96
}
76
97
77
-#define GEN_TRANS_WRS(insn) \
78
-static bool trans_ ## insn(DisasContext *ctx, arg_ ## insn *a) \
79
-{ \
80
- (void)a; \
81
- return trans_wrs(ctx); \
82
-}
83
+static bool trans_wrs_nto(DisasContext *ctx, arg_wrs_nto *a)
84
+{
85
+ if (!ctx->cfg_ptr->ext_zawrs) {
86
+ return false;
87
+ }
88
89
-GEN_TRANS_WRS(wrs_nto)
90
-GEN_TRANS_WRS(wrs_sto)
91
+ /*
92
+ * Depending on the mode of execution, mstatus.TW and hstatus.VTW, wrs.nto
93
+ * should raise an exception when the implementation-specific bounded time
94
+ * limit has expired. Our time limit is zero, so we either return
95
+ * immediately, as does our implementation of wrs.sto, or raise an
96
+ * exception, as handled by the wrs.nto helper.
97
+ */
98
+#ifndef CONFIG_USER_ONLY
99
+ gen_helper_wrs_nto(tcg_env);
100
+#endif
101
+
102
+ /* We only get here when helper_wrs_nto() doesn't raise an exception. */
103
+ return trans_wrs_sto(ctx, NULL);
104
+}
105
--
98
--
106
2.45.1
99
2.31.1
107
100
108
101
diff view generated by jsdifflib
1
From: Christoph Müllner <christoph.muellner@vrull.eu>
1
From: Alistair Francis <alistair.francis@wdc.com>
2
2
3
The th.sxstatus CSR can be used to identify available custom extension
3
This is the initial commit of the SiFive PWM timer. This is used by
4
on T-Head CPUs. The CSR is documented here:
4
guest software as a timer and is included in the SiFive FU540 SoC.
5
https://github.com/T-head-Semi/thead-extension-spec/blob/master/xtheadsxstatus.adoc
6
5
7
An important property of this patch is, that the th.sxstatus MAEE field
6
Signed-off-by: Justin Restivo <jrestivo@draper.com>
8
is not set (indicating that XTheadMae is not available).
7
Signed-off-by: Alexandra Clifford <aclifford@draper.com>
9
XTheadMae is a memory attribute extension (similar to Svpbmt) which is
8
Signed-off-by: Amanda Strnad <astrnad@draper.com>
10
implemented in many T-Head CPUs (C906, C910, etc.) and utilizes bits
9
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
in PTEs that are marked as reserved. QEMU maintainers prefer to not
10
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
12
implement XTheadMae, so we need give kernels a mechanism to identify
11
Message-id: 9f70a210acbfaf0e1ea6ad311ab892ac69134d8b.1631159656.git.alistair.francis@wdc.com
13
if XTheadMae is available in a system or not. And this patch introduces
12
---
14
this mechanism in QEMU in a way that's compatible with real HW
13
include/hw/timer/sifive_pwm.h | 62 +++++
15
(i.e., probing the th.sxstatus.MAEE bit).
14
hw/timer/sifive_pwm.c | 468 ++++++++++++++++++++++++++++++++++
15
hw/timer/Kconfig | 3 +
16
hw/timer/meson.build | 1 +
17
hw/timer/trace-events | 6 +
18
5 files changed, 540 insertions(+)
19
create mode 100644 include/hw/timer/sifive_pwm.h
20
create mode 100644 hw/timer/sifive_pwm.c
16
21
17
Further context can be found on the list:
22
diff --git a/include/hw/timer/sifive_pwm.h b/include/hw/timer/sifive_pwm.h
18
https://lists.gnu.org/archive/html/qemu-devel/2024-02/msg00775.html
19
20
Reviewed-by: LIU Zhiwei <zhiwe_liu@linux.alibaba.com>
21
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
22
Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
23
Message-ID: <20240429073656.2486732-1-christoph.muellner@vrull.eu>
24
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
25
---
26
MAINTAINERS | 1 +
27
target/riscv/cpu.h | 3 ++
28
target/riscv/cpu.c | 1 +
29
target/riscv/th_csr.c | 79 ++++++++++++++++++++++++++++++++++++++++
30
target/riscv/meson.build | 1 +
31
5 files changed, 85 insertions(+)
32
create mode 100644 target/riscv/th_csr.c
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
46
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/riscv/cpu.h
49
+++ b/target/riscv/cpu.h
50
@@ -XXX,XX +XXX,XX @@ target_ulong riscv_new_csr_seed(target_ulong new_value,
51
uint8_t satp_mode_max_from_map(uint32_t map);
52
const char *satp_mode_str(uint8_t satp_mode, bool is_32_bit);
53
54
+/* Implemented in th_csr.c */
55
+void th_register_custom_csrs(RISCVCPU *cpu);
56
+
57
#endif /* RISCV_CPU_H */
58
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
59
index XXXXXXX..XXXXXXX 100644
60
--- a/target/riscv/cpu.c
61
+++ b/target/riscv/cpu.c
62
@@ -XXX,XX +XXX,XX @@ static void rv64_thead_c906_cpu_init(Object *obj)
63
cpu->cfg.mvendorid = THEAD_VENDOR_ID;
64
#ifndef CONFIG_USER_ONLY
65
set_satp_mode_max_supported(cpu, VM_1_10_SV39);
66
+ th_register_custom_csrs(cpu);
67
#endif
68
69
/* inherited from parent obj via riscv_cpu_init() */
70
diff --git a/target/riscv/th_csr.c b/target/riscv/th_csr.c
71
new file mode 100644
23
new file mode 100644
72
index XXXXXXX..XXXXXXX
24
index XXXXXXX..XXXXXXX
73
--- /dev/null
25
--- /dev/null
74
+++ b/target/riscv/th_csr.c
26
+++ b/include/hw/timer/sifive_pwm.h
75
@@ -XXX,XX +XXX,XX @@
27
@@ -XXX,XX +XXX,XX @@
76
+/*
28
+/*
77
+ * T-Head-specific CSRs.
29
+ * SiFive PWM
78
+ *
30
+ *
79
+ * Copyright (c) 2024 VRULL GmbH
31
+ * Copyright (c) 2020 Western Digital
80
+ *
32
+ *
81
+ * This program is free software; you can redistribute it and/or modify it
33
+ * Author: Alistair Francis <alistair.francis@wdc.com>
82
+ * under the terms and conditions of the GNU General Public License,
34
+ *
83
+ * version 2 or later, as published by the Free Software Foundation.
35
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
84
+ *
36
+ * of this software and associated documentation files (the "Software"), to deal
85
+ * This program is distributed in the hope it will be useful, but WITHOUT
37
+ * in the Software without restriction, including without limitation the rights
86
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
38
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
87
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
39
+ * copies of the Software, and to permit persons to whom the Software is
88
+ * more details.
40
+ * furnished to do so, subject to the following conditions:
89
+ *
41
+ *
90
+ * You should have received a copy of the GNU General Public License along with
42
+ * The above copyright notice and this permission notice shall be included in
91
+ * this program. If not, see <http://www.gnu.org/licenses/>.
43
+ * all copies or substantial portions of the Software.
44
+ *
45
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
46
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
47
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
48
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
49
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
50
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
51
+ * THE SOFTWARE.
92
+ */
52
+ */
93
+
53
+
54
+#ifndef HW_SIFIVE_PWM_H
55
+#define HW_SIFIVE_PWM_H
56
+
57
+#include "hw/sysbus.h"
58
+#include "qemu/timer.h"
59
+#include "qom/object.h"
60
+
61
+#define TYPE_SIFIVE_PWM "sifive-pwm"
62
+
63
+#define SIFIVE_PWM(obj) \
64
+ OBJECT_CHECK(SiFivePwmState, (obj), TYPE_SIFIVE_PWM)
65
+
66
+#define SIFIVE_PWM_CHANS 4
67
+#define SIFIVE_PWM_IRQS SIFIVE_PWM_CHANS
68
+
69
+typedef struct SiFivePwmState {
70
+ /* <private> */
71
+ SysBusDevice parent_obj;
72
+
73
+ /* <public> */
74
+ MemoryRegion mmio;
75
+ QEMUTimer timer[SIFIVE_PWM_CHANS];
76
+ /*
77
+ * if en bit(s) set, is the number of ticks when pwmcount was 0
78
+ * if en bit(s) not set, is the number of ticks in pwmcount
79
+ */
80
+ uint64_t tick_offset;
81
+ uint64_t freq_hz;
82
+
83
+ uint32_t pwmcfg;
84
+ uint32_t pwmcmp[SIFIVE_PWM_CHANS];
85
+
86
+ qemu_irq irqs[SIFIVE_PWM_IRQS];
87
+} SiFivePwmState;
88
+
89
+#endif /* HW_SIFIVE_PWM_H */
90
diff --git a/hw/timer/sifive_pwm.c b/hw/timer/sifive_pwm.c
91
new file mode 100644
92
index XXXXXXX..XXXXXXX
93
--- /dev/null
94
+++ b/hw/timer/sifive_pwm.c
95
@@ -XXX,XX +XXX,XX @@
96
+/*
97
+ * SiFive PWM
98
+ *
99
+ * Copyright (c) 2020 Western Digital
100
+ *
101
+ * Author: Alistair Francis <alistair.francis@wdc.com>
102
+ *
103
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
104
+ * of this software and associated documentation files (the "Software"), to deal
105
+ * in the Software without restriction, including without limitation the rights
106
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
107
+ * copies of the Software, and to permit persons to whom the Software is
108
+ * furnished to do so, subject to the following conditions:
109
+ *
110
+ * The above copyright notice and this permission notice shall be included in
111
+ * all copies or substantial portions of the Software.
112
+ *
113
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
114
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
115
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
116
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
117
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
118
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
119
+ * THE SOFTWARE.
120
+ */
121
+
94
+#include "qemu/osdep.h"
122
+#include "qemu/osdep.h"
95
+#include "cpu.h"
123
+#include "trace.h"
96
+#include "cpu_vendorid.h"
124
+#include "hw/irq.h"
97
+
125
+#include "hw/timer/sifive_pwm.h"
98
+#define CSR_TH_SXSTATUS 0x5c0
126
+#include "hw/qdev-properties.h"
99
+
127
+#include "hw/registerfields.h"
100
+/* TH_SXSTATUS bits */
128
+#include "migration/vmstate.h"
101
+#define TH_SXSTATUS_UCME BIT(16)
129
+#include "qemu/log.h"
102
+#define TH_SXSTATUS_MAEE BIT(21)
130
+#include "qemu/module.h"
103
+#define TH_SXSTATUS_THEADISAEE BIT(22)
131
+
104
+
132
+#define HAS_PWM_EN_BITS(cfg) ((cfg & R_CONFIG_ENONESHOT_MASK) || \
105
+typedef struct {
133
+ (cfg & R_CONFIG_ENALWAYS_MASK))
106
+ int csrno;
134
+
107
+ int (*insertion_test)(RISCVCPU *cpu);
135
+#define PWMCMP_MASK 0xFFFF
108
+ riscv_csr_operations csr_ops;
136
+#define PWMCOUNT_MASK 0x7FFFFFFF
109
+} riscv_csr;
137
+
110
+
138
+REG32(CONFIG, 0x00)
111
+static RISCVException smode(CPURISCVState *env, int csrno)
139
+ FIELD(CONFIG, SCALE, 0, 4)
112
+{
140
+ FIELD(CONFIG, STICKY, 8, 1)
113
+ if (riscv_has_ext(env, RVS)) {
141
+ FIELD(CONFIG, ZEROCMP, 9, 1)
114
+ return RISCV_EXCP_NONE;
142
+ FIELD(CONFIG, DEGLITCH, 10, 1)
115
+ }
143
+ FIELD(CONFIG, ENALWAYS, 12, 1)
116
+
144
+ FIELD(CONFIG, ENONESHOT, 13, 1)
117
+ return RISCV_EXCP_ILLEGAL_INST;
145
+ FIELD(CONFIG, CMP0CENTER, 16, 1)
118
+}
146
+ FIELD(CONFIG, CMP1CENTER, 17, 1)
119
+
147
+ FIELD(CONFIG, CMP2CENTER, 18, 1)
120
+static int test_thead_mvendorid(RISCVCPU *cpu)
148
+ FIELD(CONFIG, CMP3CENTER, 19, 1)
121
+{
149
+ FIELD(CONFIG, CMP0GANG, 24, 1)
122
+ if (cpu->cfg.mvendorid != THEAD_VENDOR_ID) {
150
+ FIELD(CONFIG, CMP1GANG, 25, 1)
123
+ return -1;
151
+ FIELD(CONFIG, CMP2GANG, 26, 1)
152
+ FIELD(CONFIG, CMP3GANG, 27, 1)
153
+ FIELD(CONFIG, CMP0IP, 28, 1)
154
+ FIELD(CONFIG, CMP1IP, 29, 1)
155
+ FIELD(CONFIG, CMP2IP, 30, 1)
156
+ FIELD(CONFIG, CMP3IP, 31, 1)
157
+REG32(COUNT, 0x08)
158
+REG32(PWMS, 0x10)
159
+REG32(PWMCMP0, 0x20)
160
+REG32(PWMCMP1, 0x24)
161
+REG32(PWMCMP2, 0x28)
162
+REG32(PWMCMP3, 0x2C)
163
+
164
+static inline uint64_t sifive_pwm_ns_to_ticks(SiFivePwmState *s,
165
+ uint64_t time)
166
+{
167
+ return muldiv64(time, s->freq_hz, NANOSECONDS_PER_SECOND);
168
+}
169
+
170
+static inline uint64_t sifive_pwm_ticks_to_ns(SiFivePwmState *s,
171
+ uint64_t ticks)
172
+{
173
+ return muldiv64(ticks, NANOSECONDS_PER_SECOND, s->freq_hz);
174
+}
175
+
176
+static inline uint64_t sifive_pwm_compute_scale(SiFivePwmState *s)
177
+{
178
+ return s->pwmcfg & R_CONFIG_SCALE_MASK;
179
+}
180
+
181
+static void sifive_pwm_set_alarms(SiFivePwmState *s)
182
+{
183
+ uint64_t now_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
184
+
185
+ if (HAS_PWM_EN_BITS(s->pwmcfg)) {
186
+ /*
187
+ * Subtract ticks from number of ticks when the timer was zero
188
+ * and mask to the register width.
189
+ */
190
+ uint64_t pwmcount = (sifive_pwm_ns_to_ticks(s, now_ns) -
191
+ s->tick_offset) & PWMCOUNT_MASK;
192
+ uint64_t scale = sifive_pwm_compute_scale(s);
193
+ /* PWMs only contains PWMCMP_MASK bits starting at scale */
194
+ uint64_t pwms = (pwmcount & (PWMCMP_MASK << scale)) >> scale;
195
+
196
+ for (int i = 0; i < SIFIVE_PWM_CHANS; i++) {
197
+ uint64_t pwmcmp = s->pwmcmp[i] & PWMCMP_MASK;
198
+ uint64_t pwmcmp_ticks = pwmcmp << scale;
199
+
200
+ /*
201
+ * Per circuit diagram and spec, both cases raises corresponding
202
+ * IP bit one clock cycle after time expires.
203
+ */
204
+ if (pwmcmp > pwms) {
205
+ uint64_t offset = pwmcmp_ticks - pwmcount + 1;
206
+ uint64_t when_to_fire = now_ns +
207
+ sifive_pwm_ticks_to_ns(s, offset);
208
+
209
+ trace_sifive_pwm_set_alarm(when_to_fire, now_ns);
210
+ timer_mod(&s->timer[i], when_to_fire);
211
+ } else {
212
+ /* Schedule interrupt for next cycle */
213
+ trace_sifive_pwm_set_alarm(now_ns + 1, now_ns);
214
+ timer_mod(&s->timer[i], now_ns + 1);
215
+ }
216
+
217
+ }
218
+ } else {
219
+ /*
220
+ * If timer incrementing disabled, just do pwms > pwmcmp check since
221
+ * a write may have happened to PWMs.
222
+ */
223
+ uint64_t pwmcount = (s->tick_offset) & PWMCOUNT_MASK;
224
+ uint64_t scale = sifive_pwm_compute_scale(s);
225
+ uint64_t pwms = (pwmcount & (PWMCMP_MASK << scale)) >> scale;
226
+
227
+ for (int i = 0; i < SIFIVE_PWM_CHANS; i++) {
228
+ uint64_t pwmcmp = s->pwmcmp[i] & PWMCMP_MASK;
229
+
230
+ if (pwms >= pwmcmp) {
231
+ trace_sifive_pwm_set_alarm(now_ns + 1, now_ns);
232
+ timer_mod(&s->timer[i], now_ns + 1);
233
+ } else {
234
+ /* Effectively disable timer by scheduling far in future. */
235
+ trace_sifive_pwm_set_alarm(0xFFFFFFFFFFFFFF, now_ns);
236
+ timer_mod(&s->timer[i], 0xFFFFFFFFFFFFFF);
237
+ }
238
+ }
239
+ }
240
+}
241
+
242
+static void sifive_pwm_interrupt(SiFivePwmState *s, int num)
243
+{
244
+ uint64_t now = sifive_pwm_ns_to_ticks(s,
245
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
246
+ bool was_incrementing = HAS_PWM_EN_BITS(s->pwmcfg);
247
+
248
+ trace_sifive_pwm_interrupt(num);
249
+
250
+ s->pwmcfg |= R_CONFIG_CMP0IP_MASK << num;
251
+ qemu_irq_raise(s->irqs[num]);
252
+
253
+ /*
254
+ * If the zerocmp is set and pwmcmp0 raised the interrupt
255
+ * reset the zero ticks.
256
+ */
257
+ if ((s->pwmcfg & R_CONFIG_ZEROCMP_MASK) && (num == 0)) {
258
+ /* If reset signal conditions, disable ENONESHOT. */
259
+ s->pwmcfg &= ~R_CONFIG_ENONESHOT_MASK;
260
+
261
+ if (was_incrementing) {
262
+ /* If incrementing, time in ticks is when pwmcount is zero */
263
+ s->tick_offset = now;
264
+ } else {
265
+ /* If not incrementing, pwmcount = 0 */
266
+ s->tick_offset = 0;
267
+ }
268
+ }
269
+
270
+ /*
271
+ * If carryout bit set, which we discern via looking for overflow,
272
+ * also reset ENONESHOT.
273
+ */
274
+ if (was_incrementing &&
275
+ ((now & PWMCOUNT_MASK) < (s->tick_offset & PWMCOUNT_MASK))) {
276
+ s->pwmcfg &= ~R_CONFIG_ENONESHOT_MASK;
277
+ }
278
+
279
+ /* Schedule or disable interrupts */
280
+ sifive_pwm_set_alarms(s);
281
+
282
+ /* If was enabled, and now not enabled, switch tick rep */
283
+ if (was_incrementing && !HAS_PWM_EN_BITS(s->pwmcfg)) {
284
+ s->tick_offset = (now - s->tick_offset) & PWMCOUNT_MASK;
285
+ }
286
+}
287
+
288
+static void sifive_pwm_interrupt_0(void *opaque)
289
+{
290
+ SiFivePwmState *s = opaque;
291
+
292
+ sifive_pwm_interrupt(s, 0);
293
+}
294
+
295
+static void sifive_pwm_interrupt_1(void *opaque)
296
+{
297
+ SiFivePwmState *s = opaque;
298
+
299
+ sifive_pwm_interrupt(s, 1);
300
+}
301
+
302
+static void sifive_pwm_interrupt_2(void *opaque)
303
+{
304
+ SiFivePwmState *s = opaque;
305
+
306
+ sifive_pwm_interrupt(s, 2);
307
+}
308
+
309
+static void sifive_pwm_interrupt_3(void *opaque)
310
+{
311
+ SiFivePwmState *s = opaque;
312
+
313
+ sifive_pwm_interrupt(s, 3);
314
+}
315
+
316
+static uint64_t sifive_pwm_read(void *opaque, hwaddr addr,
317
+ unsigned int size)
318
+{
319
+ SiFivePwmState *s = opaque;
320
+ uint64_t cur_time, scale;
321
+ uint64_t now = sifive_pwm_ns_to_ticks(s,
322
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
323
+
324
+ trace_sifive_pwm_read(addr);
325
+
326
+ switch (addr) {
327
+ case A_CONFIG:
328
+ return s->pwmcfg;
329
+ case A_COUNT:
330
+ cur_time = s->tick_offset;
331
+
332
+ if (HAS_PWM_EN_BITS(s->pwmcfg)) {
333
+ cur_time = now - cur_time;
334
+ }
335
+
336
+ /*
337
+ * Return the value in the counter with bit 31 always 0
338
+ * This is allowed to wrap around so we don't need to check that.
339
+ */
340
+ return cur_time & PWMCOUNT_MASK;
341
+ case A_PWMS:
342
+ cur_time = s->tick_offset;
343
+ scale = sifive_pwm_compute_scale(s);
344
+
345
+ if (HAS_PWM_EN_BITS(s->pwmcfg)) {
346
+ cur_time = now - cur_time;
347
+ }
348
+
349
+ return ((cur_time & PWMCOUNT_MASK) >> scale) & PWMCMP_MASK;
350
+ case A_PWMCMP0:
351
+ return s->pwmcmp[0] & PWMCMP_MASK;
352
+ case A_PWMCMP1:
353
+ return s->pwmcmp[1] & PWMCMP_MASK;
354
+ case A_PWMCMP2:
355
+ return s->pwmcmp[2] & PWMCMP_MASK;
356
+ case A_PWMCMP3:
357
+ return s->pwmcmp[3] & PWMCMP_MASK;
358
+ default:
359
+ qemu_log_mask(LOG_GUEST_ERROR,
360
+ "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
361
+ return 0;
124
+ }
362
+ }
125
+
363
+
126
+ return 0;
364
+ return 0;
127
+}
365
+}
128
+
366
+
129
+static RISCVException read_th_sxstatus(CPURISCVState *env, int csrno,
367
+static void sifive_pwm_write(void *opaque, hwaddr addr,
130
+ target_ulong *val)
368
+ uint64_t val64, unsigned int size)
131
+{
369
+{
132
+ /* We don't set MAEE here, because QEMU does not implement MAEE. */
370
+ SiFivePwmState *s = opaque;
133
+ *val = TH_SXSTATUS_UCME | TH_SXSTATUS_THEADISAEE;
371
+ uint32_t value = val64;
134
+ return RISCV_EXCP_NONE;
372
+ uint64_t new_offset, scale;
135
+}
373
+ uint64_t now = sifive_pwm_ns_to_ticks(s,
136
+
374
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
137
+static riscv_csr th_csr_list[] = {
375
+
138
+ {
376
+ trace_sifive_pwm_write(value, addr);
139
+ .csrno = CSR_TH_SXSTATUS,
377
+
140
+ .insertion_test = test_thead_mvendorid,
378
+ switch (addr) {
141
+ .csr_ops = { "th.sxstatus", smode, read_th_sxstatus }
379
+ case A_CONFIG:
142
+ }
380
+ if (value & (R_CONFIG_CMP0CENTER_MASK | R_CONFIG_CMP1CENTER_MASK |
381
+ R_CONFIG_CMP2CENTER_MASK | R_CONFIG_CMP3CENTER_MASK)) {
382
+ qemu_log_mask(LOG_UNIMP, "%s: CMPxCENTER is not supported\n",
383
+ __func__);
384
+ }
385
+
386
+ if (value & (R_CONFIG_CMP0GANG_MASK | R_CONFIG_CMP1GANG_MASK |
387
+ R_CONFIG_CMP2GANG_MASK | R_CONFIG_CMP3GANG_MASK)) {
388
+ qemu_log_mask(LOG_UNIMP, "%s: CMPxGANG is not supported\n",
389
+ __func__);
390
+ }
391
+
392
+ if (value & (R_CONFIG_CMP0IP_MASK | R_CONFIG_CMP1IP_MASK |
393
+ R_CONFIG_CMP2IP_MASK | R_CONFIG_CMP3IP_MASK)) {
394
+ qemu_log_mask(LOG_UNIMP, "%s: CMPxIP is not supported\n",
395
+ __func__);
396
+ }
397
+
398
+ if (!(value & R_CONFIG_CMP0IP_MASK)) {
399
+ qemu_irq_lower(s->irqs[0]);
400
+ }
401
+
402
+ if (!(value & R_CONFIG_CMP1IP_MASK)) {
403
+ qemu_irq_lower(s->irqs[1]);
404
+ }
405
+
406
+ if (!(value & R_CONFIG_CMP2IP_MASK)) {
407
+ qemu_irq_lower(s->irqs[2]);
408
+ }
409
+
410
+ if (!(value & R_CONFIG_CMP3IP_MASK)) {
411
+ qemu_irq_lower(s->irqs[3]);
412
+ }
413
+
414
+ /*
415
+ * If this write enables the timer increment
416
+ * set the time when pwmcount was zero to be cur_time - pwmcount.
417
+ * If this write disables the timer increment
418
+ * convert back from pwmcount to the time in ticks
419
+ * when pwmcount was zero.
420
+ */
421
+ if ((!HAS_PWM_EN_BITS(s->pwmcfg) && HAS_PWM_EN_BITS(value)) ||
422
+ (HAS_PWM_EN_BITS(s->pwmcfg) && !HAS_PWM_EN_BITS(value))) {
423
+ s->tick_offset = (now - s->tick_offset) & PWMCOUNT_MASK;
424
+ }
425
+
426
+ s->pwmcfg = value;
427
+ break;
428
+ case A_COUNT:
429
+ /* The guest changed the counter, updated the offset value. */
430
+ new_offset = value;
431
+
432
+ if (HAS_PWM_EN_BITS(s->pwmcfg)) {
433
+ new_offset = now - new_offset;
434
+ }
435
+
436
+ s->tick_offset = new_offset;
437
+ break;
438
+ case A_PWMS:
439
+ scale = sifive_pwm_compute_scale(s);
440
+ new_offset = (((value & PWMCMP_MASK) << scale) & PWMCOUNT_MASK);
441
+
442
+ if (HAS_PWM_EN_BITS(s->pwmcfg)) {
443
+ new_offset = now - new_offset;
444
+ }
445
+
446
+ s->tick_offset = new_offset;
447
+ break;
448
+ case A_PWMCMP0:
449
+ s->pwmcmp[0] = value & PWMCMP_MASK;
450
+ break;
451
+ case A_PWMCMP1:
452
+ s->pwmcmp[1] = value & PWMCMP_MASK;
453
+ break;
454
+ case A_PWMCMP2:
455
+ s->pwmcmp[2] = value & PWMCMP_MASK;
456
+ break;
457
+ case A_PWMCMP3:
458
+ s->pwmcmp[3] = value & PWMCMP_MASK;
459
+ break;
460
+ default:
461
+ qemu_log_mask(LOG_GUEST_ERROR,
462
+ "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
463
+ }
464
+
465
+ /* Update the alarms to reflect possible updated values */
466
+ sifive_pwm_set_alarms(s);
467
+}
468
+
469
+static void sifive_pwm_reset(DeviceState *dev)
470
+{
471
+ SiFivePwmState *s = SIFIVE_PWM(dev);
472
+ uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
473
+
474
+ s->pwmcfg = 0x00000000;
475
+ s->pwmcmp[0] = 0x00000000;
476
+ s->pwmcmp[1] = 0x00000000;
477
+ s->pwmcmp[2] = 0x00000000;
478
+ s->pwmcmp[3] = 0x00000000;
479
+
480
+ s->tick_offset = sifive_pwm_ns_to_ticks(s, now);
481
+}
482
+
483
+static const MemoryRegionOps sifive_pwm_ops = {
484
+ .read = sifive_pwm_read,
485
+ .write = sifive_pwm_write,
486
+ .endianness = DEVICE_NATIVE_ENDIAN,
143
+};
487
+};
144
+
488
+
145
+void th_register_custom_csrs(RISCVCPU *cpu)
489
+static const VMStateDescription vmstate_sifive_pwm = {
146
+{
490
+ .name = TYPE_SIFIVE_PWM,
147
+ for (size_t i = 0; i < ARRAY_SIZE(th_csr_list); i++) {
491
+ .version_id = 1,
148
+ int csrno = th_csr_list[i].csrno;
492
+ .minimum_version_id = 1,
149
+ riscv_csr_operations *csr_ops = &th_csr_list[i].csr_ops;
493
+ .fields = (VMStateField[]) {
150
+ if (!th_csr_list[i].insertion_test(cpu)) {
494
+ VMSTATE_TIMER_ARRAY(timer, SiFivePwmState, 4),
151
+ riscv_set_csr_ops(csrno, csr_ops);
495
+ VMSTATE_UINT64(tick_offset, SiFivePwmState),
152
+ }
496
+ VMSTATE_UINT32(pwmcfg, SiFivePwmState),
153
+ }
497
+ VMSTATE_UINT32_ARRAY(pwmcmp, SiFivePwmState, 4),
154
+}
498
+ VMSTATE_END_OF_LIST()
155
diff --git a/target/riscv/meson.build b/target/riscv/meson.build
499
+ }
500
+};
501
+
502
+static Property sifive_pwm_properties[] = {
503
+ /* 0.5Ghz per spec after FSBL */
504
+ DEFINE_PROP_UINT64("clock-frequency", struct SiFivePwmState,
505
+ freq_hz, 500000000ULL),
506
+ DEFINE_PROP_END_OF_LIST(),
507
+};
508
+
509
+static void sifive_pwm_init(Object *obj)
510
+{
511
+ SiFivePwmState *s = SIFIVE_PWM(obj);
512
+ int i;
513
+
514
+ for (i = 0; i < SIFIVE_PWM_IRQS; i++) {
515
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irqs[i]);
516
+ }
517
+
518
+ memory_region_init_io(&s->mmio, obj, &sifive_pwm_ops, s,
519
+ TYPE_SIFIVE_PWM, 0x100);
520
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
521
+}
522
+
523
+static void sifive_pwm_realize(DeviceState *dev, Error **errp)
524
+{
525
+ SiFivePwmState *s = SIFIVE_PWM(dev);
526
+
527
+ timer_init_ns(&s->timer[0], QEMU_CLOCK_VIRTUAL,
528
+ sifive_pwm_interrupt_0, s);
529
+
530
+ timer_init_ns(&s->timer[1], QEMU_CLOCK_VIRTUAL,
531
+ sifive_pwm_interrupt_1, s);
532
+
533
+ timer_init_ns(&s->timer[2], QEMU_CLOCK_VIRTUAL,
534
+ sifive_pwm_interrupt_2, s);
535
+
536
+ timer_init_ns(&s->timer[3], QEMU_CLOCK_VIRTUAL,
537
+ sifive_pwm_interrupt_3, s);
538
+}
539
+
540
+static void sifive_pwm_class_init(ObjectClass *klass, void *data)
541
+{
542
+ DeviceClass *dc = DEVICE_CLASS(klass);
543
+
544
+ dc->reset = sifive_pwm_reset;
545
+ device_class_set_props(dc, sifive_pwm_properties);
546
+ dc->vmsd = &vmstate_sifive_pwm;
547
+ dc->realize = sifive_pwm_realize;
548
+}
549
+
550
+static const TypeInfo sifive_pwm_info = {
551
+ .name = TYPE_SIFIVE_PWM,
552
+ .parent = TYPE_SYS_BUS_DEVICE,
553
+ .instance_size = sizeof(SiFivePwmState),
554
+ .instance_init = sifive_pwm_init,
555
+ .class_init = sifive_pwm_class_init,
556
+};
557
+
558
+static void sifive_pwm_register_types(void)
559
+{
560
+ type_register_static(&sifive_pwm_info);
561
+}
562
+
563
+type_init(sifive_pwm_register_types)
564
diff --git a/hw/timer/Kconfig b/hw/timer/Kconfig
156
index XXXXXXX..XXXXXXX 100644
565
index XXXXXXX..XXXXXXX 100644
157
--- a/target/riscv/meson.build
566
--- a/hw/timer/Kconfig
158
+++ b/target/riscv/meson.build
567
+++ b/hw/timer/Kconfig
159
@@ -XXX,XX +XXX,XX @@ riscv_system_ss.add(files(
568
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_A10_PIT
160
'monitor.c',
569
bool
161
'machine.c',
570
select PTIMER
162
'pmu.c',
571
163
+ 'th_csr.c',
572
+config SIFIVE_PWM
164
'time_helper.c',
573
+ bool
165
'riscv-qmp-cmds.c',
574
+
166
))
575
config STM32F2XX_TIMER
576
bool
577
578
diff --git a/hw/timer/meson.build b/hw/timer/meson.build
579
index XXXXXXX..XXXXXXX 100644
580
--- a/hw/timer/meson.build
581
+++ b/hw/timer/meson.build
582
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_STELLARIS_GPTM', if_true: files('stellaris-gptm.c')
583
softmmu_ss.add(when: 'CONFIG_STM32F2XX_TIMER', if_true: files('stm32f2xx_timer.c'))
584
softmmu_ss.add(when: 'CONFIG_XILINX', if_true: files('xilinx_timer.c'))
585
specific_ss.add(when: 'CONFIG_IBEX', if_true: files('ibex_timer.c'))
586
+softmmu_ss.add(when: 'CONFIG_SIFIVE_PWM', if_true: files('sifive_pwm.c'))
587
588
specific_ss.add(when: 'CONFIG_AVR_TIMER16', if_true: files('avr_timer16.c'))
589
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
590
index XXXXXXX..XXXXXXX 100644
591
--- a/hw/timer/trace-events
592
+++ b/hw/timer/trace-events
593
@@ -XXX,XX +XXX,XX @@ sse_counter_reset(void) "SSE system counter: reset"
594
sse_timer_read(uint64_t offset, uint64_t data, unsigned size) "SSE system timer read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
595
sse_timer_write(uint64_t offset, uint64_t data, unsigned size) "SSE system timer write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
596
sse_timer_reset(void) "SSE system timer: reset"
597
+
598
+# sifive_pwm.c
599
+sifive_pwm_set_alarm(uint64_t alarm, uint64_t now) "Setting alarm to: 0x%" PRIx64 ", now: 0x%" PRIx64
600
+sifive_pwm_interrupt(int num) "Interrupt %d"
601
+sifive_pwm_read(uint64_t offset) "Read at address: 0x%" PRIx64
602
+sifive_pwm_write(uint64_t data, uint64_t offset) "Write 0x%" PRIx64 " at address: 0x%" PRIx64
167
--
603
--
168
2.45.1
604
2.31.1
169
605
170
606
diff view generated by jsdifflib
1
From: Alistair Francis <alistair23@gmail.com>
1
From: Alistair Francis <alistair.francis@wdc.com>
2
2
3
When running the instruction
3
Connect the SiFive PWM device and expose it via the device tree.
4
5
```
6
cbo.flush 0(x0)
7
```
8
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
4
27
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
5
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
28
Reported-by: Fabian Thomas <fabian.thomas@cispa.de>
6
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
29
Fixes: e05da09b7cfd ("target/riscv: implement Zicbom extension")
7
Message-id: 22f98648b4e012f78529a56f5ca60b0b27852a4d.1631159656.git.alistair.francis@wdc.com
30
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
31
Cc: qemu-stable <qemu-stable@nongnu.org>
32
Message-ID: <20240514023910.301766-1-alistair.francis@wdc.com>
33
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
34
---
8
---
35
target/riscv/insn_trans/trans_rvzicbo.c.inc | 16 ++++++++++++----
9
docs/system/riscv/sifive_u.rst | 1 +
36
1 file changed, 12 insertions(+), 4 deletions(-)
10
include/hw/riscv/sifive_u.h | 14 ++++++++-
11
hw/riscv/sifive_u.c | 55 +++++++++++++++++++++++++++++++++-
12
hw/riscv/Kconfig | 1 +
13
4 files changed, 69 insertions(+), 2 deletions(-)
37
14
38
diff --git a/target/riscv/insn_trans/trans_rvzicbo.c.inc b/target/riscv/insn_trans/trans_rvzicbo.c.inc
15
diff --git a/docs/system/riscv/sifive_u.rst b/docs/system/riscv/sifive_u.rst
39
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
40
--- a/target/riscv/insn_trans/trans_rvzicbo.c.inc
17
--- a/docs/system/riscv/sifive_u.rst
41
+++ b/target/riscv/insn_trans/trans_rvzicbo.c.inc
18
+++ b/docs/system/riscv/sifive_u.rst
19
@@ -XXX,XX +XXX,XX @@ The ``sifive_u`` machine supports the following devices:
20
* 2 QSPI controllers
21
* 1 ISSI 25WP256 flash
22
* 1 SD card in SPI mode
23
+* PWM0 and PWM1
24
25
Please note the real world HiFive Unleashed board has a fixed configuration of
26
1 E51 core and 4 U54 core combination and the RISC-V core boots in 64-bit mode.
27
diff --git a/include/hw/riscv/sifive_u.h b/include/hw/riscv/sifive_u.h
28
index XXXXXXX..XXXXXXX 100644
29
--- a/include/hw/riscv/sifive_u.h
30
+++ b/include/hw/riscv/sifive_u.h
42
@@ -XXX,XX +XXX,XX @@
31
@@ -XXX,XX +XXX,XX @@
43
static bool trans_cbo_clean(DisasContext *ctx, arg_cbo_clean *a)
32
#include "hw/misc/sifive_u_otp.h"
44
{
33
#include "hw/misc/sifive_u_prci.h"
45
REQUIRE_ZICBOM(ctx);
34
#include "hw/ssi/sifive_spi.h"
46
- gen_helper_cbo_clean_flush(tcg_env, cpu_gpr[a->rs1]);
35
+#include "hw/timer/sifive_pwm.h"
47
+ TCGv src = get_address(ctx, a->rs1, 0);
36
37
#define TYPE_RISCV_U_SOC "riscv.sifive.u.soc"
38
#define RISCV_U_SOC(obj) \
39
@@ -XXX,XX +XXX,XX @@ typedef struct SiFiveUSoCState {
40
SiFiveSPIState spi0;
41
SiFiveSPIState spi2;
42
CadenceGEMState gem;
43
+ SiFivePwmState pwm[2];
44
45
uint32_t serial;
46
char *cpu_type;
47
@@ -XXX,XX +XXX,XX @@ enum {
48
SIFIVE_U_DEV_FLASH0,
49
SIFIVE_U_DEV_DRAM,
50
SIFIVE_U_DEV_GEM,
51
- SIFIVE_U_DEV_GEM_MGMT
52
+ SIFIVE_U_DEV_GEM_MGMT,
53
+ SIFIVE_U_DEV_PWM0,
54
+ SIFIVE_U_DEV_PWM1
55
};
56
57
enum {
58
@@ -XXX,XX +XXX,XX @@ enum {
59
SIFIVE_U_PDMA_IRQ5 = 28,
60
SIFIVE_U_PDMA_IRQ6 = 29,
61
SIFIVE_U_PDMA_IRQ7 = 30,
62
+ SIFIVE_U_PWM0_IRQ0 = 42,
63
+ SIFIVE_U_PWM0_IRQ1 = 43,
64
+ SIFIVE_U_PWM0_IRQ2 = 44,
65
+ SIFIVE_U_PWM0_IRQ3 = 45,
66
+ SIFIVE_U_PWM1_IRQ0 = 46,
67
+ SIFIVE_U_PWM1_IRQ1 = 47,
68
+ SIFIVE_U_PWM1_IRQ2 = 48,
69
+ SIFIVE_U_PWM1_IRQ3 = 49,
70
SIFIVE_U_QSPI0_IRQ = 51,
71
SIFIVE_U_GEM_IRQ = 53
72
};
73
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/hw/riscv/sifive_u.c
76
+++ b/hw/riscv/sifive_u.c
77
@@ -XXX,XX +XXX,XX @@
78
* 7) DMA (Direct Memory Access Controller)
79
* 8) SPI0 connected to an SPI flash
80
* 9) SPI2 connected to an SD card
81
+ * 10) PWM0 and PWM1
82
*
83
* This board currently generates devicetree dynamically that indicates at least
84
* two harts and up to five harts.
85
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry sifive_u_memmap[] = {
86
[SIFIVE_U_DEV_PRCI] = { 0x10000000, 0x1000 },
87
[SIFIVE_U_DEV_UART0] = { 0x10010000, 0x1000 },
88
[SIFIVE_U_DEV_UART1] = { 0x10011000, 0x1000 },
89
+ [SIFIVE_U_DEV_PWM0] = { 0x10020000, 0x1000 },
90
+ [SIFIVE_U_DEV_PWM1] = { 0x10021000, 0x1000 },
91
[SIFIVE_U_DEV_QSPI0] = { 0x10040000, 0x1000 },
92
[SIFIVE_U_DEV_QSPI2] = { 0x10050000, 0x1000 },
93
[SIFIVE_U_DEV_GPIO] = { 0x10060000, 0x1000 },
94
@@ -XXX,XX +XXX,XX @@ static void create_fdt(SiFiveUState *s, const MemMapEntry *memmap,
95
qemu_fdt_setprop_cell(fdt, nodename, "reg", 0x0);
96
g_free(nodename);
97
98
+ nodename = g_strdup_printf("/soc/pwm@%lx",
99
+ (long)memmap[SIFIVE_U_DEV_PWM0].base);
100
+ qemu_fdt_add_subnode(fdt, nodename);
101
+ qemu_fdt_setprop_string(fdt, nodename, "compatible", "sifive,pwm0");
102
+ qemu_fdt_setprop_cells(fdt, nodename, "reg",
103
+ 0x0, memmap[SIFIVE_U_DEV_PWM0].base,
104
+ 0x0, memmap[SIFIVE_U_DEV_PWM0].size);
105
+ qemu_fdt_setprop_cell(fdt, nodename, "interrupt-parent", plic_phandle);
106
+ qemu_fdt_setprop_cells(fdt, nodename, "interrupts",
107
+ SIFIVE_U_PWM0_IRQ0, SIFIVE_U_PWM0_IRQ1,
108
+ SIFIVE_U_PWM0_IRQ2, SIFIVE_U_PWM0_IRQ3);
109
+ qemu_fdt_setprop_cells(fdt, nodename, "clocks",
110
+ prci_phandle, PRCI_CLK_TLCLK);
111
+ qemu_fdt_setprop_cell(fdt, nodename, "#pwm-cells", 0);
112
+ g_free(nodename);
48
+
113
+
49
+ gen_helper_cbo_clean_flush(tcg_env, src);
114
+ nodename = g_strdup_printf("/soc/pwm@%lx",
50
return true;
115
+ (long)memmap[SIFIVE_U_DEV_PWM1].base);
116
+ qemu_fdt_add_subnode(fdt, nodename);
117
+ qemu_fdt_setprop_string(fdt, nodename, "compatible", "sifive,pwm0");
118
+ qemu_fdt_setprop_cells(fdt, nodename, "reg",
119
+ 0x0, memmap[SIFIVE_U_DEV_PWM1].base,
120
+ 0x0, memmap[SIFIVE_U_DEV_PWM1].size);
121
+ qemu_fdt_setprop_cell(fdt, nodename, "interrupt-parent", plic_phandle);
122
+ qemu_fdt_setprop_cells(fdt, nodename, "interrupts",
123
+ SIFIVE_U_PWM1_IRQ0, SIFIVE_U_PWM1_IRQ1,
124
+ SIFIVE_U_PWM1_IRQ2, SIFIVE_U_PWM1_IRQ3);
125
+ qemu_fdt_setprop_cells(fdt, nodename, "clocks",
126
+ prci_phandle, PRCI_CLK_TLCLK);
127
+ qemu_fdt_setprop_cell(fdt, nodename, "#pwm-cells", 0);
128
+ g_free(nodename);
129
+
130
nodename = g_strdup_printf("/soc/serial@%lx",
131
(long)memmap[SIFIVE_U_DEV_UART1].base);
132
qemu_fdt_add_subnode(fdt, nodename);
133
@@ -XXX,XX +XXX,XX @@ static void sifive_u_soc_instance_init(Object *obj)
134
object_initialize_child(obj, "pdma", &s->dma, TYPE_SIFIVE_PDMA);
135
object_initialize_child(obj, "spi0", &s->spi0, TYPE_SIFIVE_SPI);
136
object_initialize_child(obj, "spi2", &s->spi2, TYPE_SIFIVE_SPI);
137
+ object_initialize_child(obj, "pwm0", &s->pwm[0], TYPE_SIFIVE_PWM);
138
+ object_initialize_child(obj, "pwm1", &s->pwm[1], TYPE_SIFIVE_PWM);
51
}
139
}
52
140
53
static bool trans_cbo_flush(DisasContext *ctx, arg_cbo_flush *a)
141
static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
54
{
142
@@ -XXX,XX +XXX,XX @@ static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
55
REQUIRE_ZICBOM(ctx);
143
MemoryRegion *l2lim_mem = g_new(MemoryRegion, 1);
56
- gen_helper_cbo_clean_flush(tcg_env, cpu_gpr[a->rs1]);
144
char *plic_hart_config;
57
+ TCGv src = get_address(ctx, a->rs1, 0);
145
size_t plic_hart_config_len;
146
- int i;
147
+ int i, j;
148
NICInfo *nd = &nd_table[0];
149
150
qdev_prop_set_uint32(DEVICE(&s->u_cpus), "num-harts", ms->smp.cpus - 1);
151
@@ -XXX,XX +XXX,XX @@ static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
152
sysbus_connect_irq(SYS_BUS_DEVICE(&s->gem), 0,
153
qdev_get_gpio_in(DEVICE(s->plic), SIFIVE_U_GEM_IRQ));
154
155
+ /* PWM */
156
+ for (i = 0; i < 2; i++) {
157
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->pwm[i]), errp)) {
158
+ return;
159
+ }
160
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->pwm[i]), 0,
161
+ memmap[SIFIVE_U_DEV_PWM0].base + (0x1000 * i));
58
+
162
+
59
+ gen_helper_cbo_clean_flush(tcg_env, src);
163
+ /* Connect PWM interrupts to the PLIC */
60
return true;
164
+ for (j = 0; j < SIFIVE_PWM_IRQS; j++) {
61
}
165
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->pwm[i]), j,
62
166
+ qdev_get_gpio_in(DEVICE(s->plic),
63
static bool trans_cbo_inval(DisasContext *ctx, arg_cbo_inval *a)
167
+ SIFIVE_U_PWM0_IRQ0 + (i * 4) + j));
64
{
168
+ }
65
REQUIRE_ZICBOM(ctx);
169
+ }
66
- gen_helper_cbo_inval(tcg_env, cpu_gpr[a->rs1]);
67
+ TCGv src = get_address(ctx, a->rs1, 0);
68
+
170
+
69
+ gen_helper_cbo_inval(tcg_env, src);
171
create_unimplemented_device("riscv.sifive.u.gem-mgmt",
70
return true;
172
memmap[SIFIVE_U_DEV_GEM_MGMT].base, memmap[SIFIVE_U_DEV_GEM_MGMT].size);
71
}
173
72
174
diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
73
static bool trans_cbo_zero(DisasContext *ctx, arg_cbo_zero *a)
175
index XXXXXXX..XXXXXXX 100644
74
{
176
--- a/hw/riscv/Kconfig
75
REQUIRE_ZICBOZ(ctx);
177
+++ b/hw/riscv/Kconfig
76
- gen_helper_cbo_zero(tcg_env, cpu_gpr[a->rs1]);
178
@@ -XXX,XX +XXX,XX @@ config SIFIVE_U
77
+ TCGv src = get_address(ctx, a->rs1, 0);
179
select SIFIVE_UART
78
+
180
select SIFIVE_U_OTP
79
+ gen_helper_cbo_zero(tcg_env, src);
181
select SIFIVE_U_PRCI
80
return true;
182
+ select SIFIVE_PWM
81
}
183
select SSI_M25P80
184
select SSI_SD
185
select UNIMP
82
--
186
--
83
2.45.1
187
2.31.1
188
189
diff view generated by jsdifflib
1
From: Alistair Francis <alistair23@gmail.com>
1
From: Anup Patel <anup.patel@wdc.com>
2
2
3
Previously we only listed a single pmpcfg CSR and the first 16 pmpaddr
3
We will be upgrading SiFive CLINT implementation into RISC-V ACLINT
4
CSRs. This patch fixes this to list all 16 pmpcfg and all 64 pmpaddr
4
implementation so let's first rename the sources.
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
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
8
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
9
Fixes: ea10325917 ("RISC-V Disassembler")
9
Message-id: 20210831110603.338681-2-anup.patel@wdc.com
10
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
11
Cc: qemu-stable <qemu-stable@nongnu.org>
12
Message-ID: <20240514051615.330979-1-alistair.francis@wdc.com>
13
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
14
---
11
---
15
disas/riscv.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++-
12
include/hw/intc/{sifive_clint.h => riscv_aclint.h} | 0
16
1 file changed, 64 insertions(+), 1 deletion(-)
13
hw/intc/{sifive_clint.c => riscv_aclint.c} | 2 +-
17
14
hw/riscv/microchip_pfsoc.c | 2 +-
18
diff --git a/disas/riscv.c b/disas/riscv.c
15
hw/riscv/shakti_c.c | 2 +-
19
index XXXXXXX..XXXXXXX 100644
16
hw/riscv/sifive_e.c | 2 +-
20
--- a/disas/riscv.c
17
hw/riscv/sifive_u.c | 2 +-
21
+++ b/disas/riscv.c
18
hw/riscv/spike.c | 2 +-
22
@@ -XXX,XX +XXX,XX @@ static const char *csr_name(int csrno)
19
hw/riscv/virt.c | 2 +-
23
case 0x0383: return "mibound";
20
hw/intc/Kconfig | 2 +-
24
case 0x0384: return "mdbase";
21
hw/intc/meson.build | 2 +-
25
case 0x0385: return "mdbound";
22
hw/riscv/Kconfig | 12 ++++++------
26
- case 0x03a0: return "pmpcfg3";
23
11 files changed, 15 insertions(+), 15 deletions(-)
27
+ case 0x03a0: return "pmpcfg0";
24
rename include/hw/intc/{sifive_clint.h => riscv_aclint.h} (100%)
28
+ case 0x03a1: return "pmpcfg1";
25
rename hw/intc/{sifive_clint.c => riscv_aclint.c} (99%)
29
+ case 0x03a2: return "pmpcfg2";
26
30
+ case 0x03a3: return "pmpcfg3";
27
diff --git a/include/hw/intc/sifive_clint.h b/include/hw/intc/riscv_aclint.h
31
+ case 0x03a4: return "pmpcfg4";
28
similarity index 100%
32
+ case 0x03a5: return "pmpcfg5";
29
rename from include/hw/intc/sifive_clint.h
33
+ case 0x03a6: return "pmpcfg6";
30
rename to include/hw/intc/riscv_aclint.h
34
+ case 0x03a7: return "pmpcfg7";
31
diff --git a/hw/intc/sifive_clint.c b/hw/intc/riscv_aclint.c
35
+ case 0x03a8: return "pmpcfg8";
32
similarity index 99%
36
+ case 0x03a9: return "pmpcfg9";
33
rename from hw/intc/sifive_clint.c
37
+ case 0x03aa: return "pmpcfg10";
34
rename to hw/intc/riscv_aclint.c
38
+ case 0x03ab: return "pmpcfg11";
35
index XXXXXXX..XXXXXXX 100644
39
+ case 0x03ac: return "pmpcfg12";
36
--- a/hw/intc/sifive_clint.c
40
+ case 0x03ad: return "pmpcfg13";
37
+++ b/hw/intc/riscv_aclint.c
41
+ case 0x03ae: return "pmpcfg14";
38
@@ -XXX,XX +XXX,XX @@
42
+ case 0x03af: return "pmpcfg15";
39
#include "hw/sysbus.h"
43
case 0x03b0: return "pmpaddr0";
40
#include "target/riscv/cpu.h"
44
case 0x03b1: return "pmpaddr1";
41
#include "hw/qdev-properties.h"
45
case 0x03b2: return "pmpaddr2";
42
-#include "hw/intc/sifive_clint.h"
46
@@ -XXX,XX +XXX,XX @@ static const char *csr_name(int csrno)
43
+#include "hw/intc/riscv_aclint.h"
47
case 0x03bd: return "pmpaddr13";
44
#include "qemu/timer.h"
48
case 0x03be: return "pmpaddr14";
45
#include "hw/irq.h"
49
case 0x03bf: return "pmpaddr15";
46
50
+ case 0x03c0: return "pmpaddr16";
47
diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
51
+ case 0x03c1: return "pmpaddr17";
48
index XXXXXXX..XXXXXXX 100644
52
+ case 0x03c2: return "pmpaddr18";
49
--- a/hw/riscv/microchip_pfsoc.c
53
+ case 0x03c3: return "pmpaddr19";
50
+++ b/hw/riscv/microchip_pfsoc.c
54
+ case 0x03c4: return "pmpaddr20";
51
@@ -XXX,XX +XXX,XX @@
55
+ case 0x03c5: return "pmpaddr21";
52
#include "hw/riscv/boot.h"
56
+ case 0x03c6: return "pmpaddr22";
53
#include "hw/riscv/riscv_hart.h"
57
+ case 0x03c7: return "pmpaddr23";
54
#include "hw/riscv/microchip_pfsoc.h"
58
+ case 0x03c8: return "pmpaddr24";
55
-#include "hw/intc/sifive_clint.h"
59
+ case 0x03c9: return "pmpaddr25";
56
+#include "hw/intc/riscv_aclint.h"
60
+ case 0x03ca: return "pmpaddr26";
57
#include "hw/intc/sifive_plic.h"
61
+ case 0x03cb: return "pmpaddr27";
58
#include "sysemu/device_tree.h"
62
+ case 0x03cc: return "pmpaddr28";
59
#include "sysemu/sysemu.h"
63
+ case 0x03cd: return "pmpaddr29";
60
diff --git a/hw/riscv/shakti_c.c b/hw/riscv/shakti_c.c
64
+ case 0x03ce: return "pmpaddr30";
61
index XXXXXXX..XXXXXXX 100644
65
+ case 0x03cf: return "pmpaddr31";
62
--- a/hw/riscv/shakti_c.c
66
+ case 0x03d0: return "pmpaddr32";
63
+++ b/hw/riscv/shakti_c.c
67
+ case 0x03d1: return "pmpaddr33";
64
@@ -XXX,XX +XXX,XX @@
68
+ case 0x03d2: return "pmpaddr34";
65
#include "hw/riscv/shakti_c.h"
69
+ case 0x03d3: return "pmpaddr35";
66
#include "qapi/error.h"
70
+ case 0x03d4: return "pmpaddr36";
67
#include "hw/intc/sifive_plic.h"
71
+ case 0x03d5: return "pmpaddr37";
68
-#include "hw/intc/sifive_clint.h"
72
+ case 0x03d6: return "pmpaddr38";
69
+#include "hw/intc/riscv_aclint.h"
73
+ case 0x03d7: return "pmpaddr39";
70
#include "sysemu/sysemu.h"
74
+ case 0x03d8: return "pmpaddr40";
71
#include "hw/qdev-properties.h"
75
+ case 0x03d9: return "pmpaddr41";
72
#include "exec/address-spaces.h"
76
+ case 0x03da: return "pmpaddr42";
73
diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
77
+ case 0x03db: return "pmpaddr43";
74
index XXXXXXX..XXXXXXX 100644
78
+ case 0x03dc: return "pmpaddr44";
75
--- a/hw/riscv/sifive_e.c
79
+ case 0x03dd: return "pmpaddr45";
76
+++ b/hw/riscv/sifive_e.c
80
+ case 0x03de: return "pmpaddr46";
77
@@ -XXX,XX +XXX,XX @@
81
+ case 0x03df: return "pmpaddr47";
78
#include "hw/riscv/sifive_e.h"
82
+ case 0x03e0: return "pmpaddr48";
79
#include "hw/riscv/boot.h"
83
+ case 0x03e1: return "pmpaddr49";
80
#include "hw/char/sifive_uart.h"
84
+ case 0x03e2: return "pmpaddr50";
81
-#include "hw/intc/sifive_clint.h"
85
+ case 0x03e3: return "pmpaddr51";
82
+#include "hw/intc/riscv_aclint.h"
86
+ case 0x03e4: return "pmpaddr52";
83
#include "hw/intc/sifive_plic.h"
87
+ case 0x03e5: return "pmpaddr53";
84
#include "hw/misc/sifive_e_prci.h"
88
+ case 0x03e6: return "pmpaddr54";
85
#include "chardev/char.h"
89
+ case 0x03e7: return "pmpaddr55";
86
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
90
+ case 0x03e8: return "pmpaddr56";
87
index XXXXXXX..XXXXXXX 100644
91
+ case 0x03e9: return "pmpaddr57";
88
--- a/hw/riscv/sifive_u.c
92
+ case 0x03ea: return "pmpaddr58";
89
+++ b/hw/riscv/sifive_u.c
93
+ case 0x03eb: return "pmpaddr59";
90
@@ -XXX,XX +XXX,XX @@
94
+ case 0x03ec: return "pmpaddr60";
91
#include "hw/riscv/sifive_u.h"
95
+ case 0x03ed: return "pmpaddr61";
92
#include "hw/riscv/boot.h"
96
+ case 0x03ee: return "pmpaddr62";
93
#include "hw/char/sifive_uart.h"
97
+ case 0x03ef: return "pmpaddr63";
94
-#include "hw/intc/sifive_clint.h"
98
case 0x0780: return "mtohost";
95
+#include "hw/intc/riscv_aclint.h"
99
case 0x0781: return "mfromhost";
96
#include "hw/intc/sifive_plic.h"
100
case 0x0782: return "mreset";
97
#include "chardev/char.h"
98
#include "net/eth.h"
99
diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
100
index XXXXXXX..XXXXXXX 100644
101
--- a/hw/riscv/spike.c
102
+++ b/hw/riscv/spike.c
103
@@ -XXX,XX +XXX,XX @@
104
#include "hw/riscv/boot.h"
105
#include "hw/riscv/numa.h"
106
#include "hw/char/riscv_htif.h"
107
-#include "hw/intc/sifive_clint.h"
108
+#include "hw/intc/riscv_aclint.h"
109
#include "chardev/char.h"
110
#include "sysemu/device_tree.h"
111
#include "sysemu/sysemu.h"
112
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
113
index XXXXXXX..XXXXXXX 100644
114
--- a/hw/riscv/virt.c
115
+++ b/hw/riscv/virt.c
116
@@ -XXX,XX +XXX,XX @@
117
#include "hw/riscv/virt.h"
118
#include "hw/riscv/boot.h"
119
#include "hw/riscv/numa.h"
120
-#include "hw/intc/sifive_clint.h"
121
+#include "hw/intc/riscv_aclint.h"
122
#include "hw/intc/sifive_plic.h"
123
#include "hw/misc/sifive_test.h"
124
#include "chardev/char.h"
125
diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
126
index XXXXXXX..XXXXXXX 100644
127
--- a/hw/intc/Kconfig
128
+++ b/hw/intc/Kconfig
129
@@ -XXX,XX +XXX,XX @@ config RX_ICU
130
config LOONGSON_LIOINTC
131
bool
132
133
-config SIFIVE_CLINT
134
+config RISCV_ACLINT
135
bool
136
137
config SIFIVE_PLIC
138
diff --git a/hw/intc/meson.build b/hw/intc/meson.build
139
index XXXXXXX..XXXXXXX 100644
140
--- a/hw/intc/meson.build
141
+++ b/hw/intc/meson.build
142
@@ -XXX,XX +XXX,XX @@ specific_ss.add(when: 'CONFIG_RX_ICU', if_true: files('rx_icu.c'))
143
specific_ss.add(when: 'CONFIG_S390_FLIC', if_true: files('s390_flic.c'))
144
specific_ss.add(when: 'CONFIG_S390_FLIC_KVM', if_true: files('s390_flic_kvm.c'))
145
specific_ss.add(when: 'CONFIG_SH_INTC', if_true: files('sh_intc.c'))
146
-specific_ss.add(when: 'CONFIG_SIFIVE_CLINT', if_true: files('sifive_clint.c'))
147
+specific_ss.add(when: 'CONFIG_RISCV_ACLINT', if_true: files('riscv_aclint.c'))
148
specific_ss.add(when: 'CONFIG_SIFIVE_PLIC', if_true: files('sifive_plic.c'))
149
specific_ss.add(when: 'CONFIG_XICS', if_true: files('xics.c'))
150
specific_ss.add(when: ['CONFIG_KVM', 'CONFIG_XICS'],
151
diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
152
index XXXXXXX..XXXXXXX 100644
153
--- a/hw/riscv/Kconfig
154
+++ b/hw/riscv/Kconfig
155
@@ -XXX,XX +XXX,XX @@ config MICROCHIP_PFSOC
156
select MCHP_PFSOC_MMUART
157
select MCHP_PFSOC_SYSREG
158
select MSI_NONBROKEN
159
- select SIFIVE_CLINT
160
+ select RISCV_ACLINT
161
select SIFIVE_PDMA
162
select SIFIVE_PLIC
163
select UNIMP
164
@@ -XXX,XX +XXX,XX @@ config SHAKTI_C
165
bool
166
select UNIMP
167
select SHAKTI_UART
168
- select SIFIVE_CLINT
169
+ select RISCV_ACLINT
170
select SIFIVE_PLIC
171
172
config RISCV_VIRT
173
@@ -XXX,XX +XXX,XX @@ config RISCV_VIRT
174
select PCI_EXPRESS_GENERIC_BRIDGE
175
select PFLASH_CFI01
176
select SERIAL
177
- select SIFIVE_CLINT
178
+ select RISCV_ACLINT
179
select SIFIVE_PLIC
180
select SIFIVE_TEST
181
select VIRTIO_MMIO
182
@@ -XXX,XX +XXX,XX @@ config RISCV_VIRT
183
config SIFIVE_E
184
bool
185
select MSI_NONBROKEN
186
- select SIFIVE_CLINT
187
+ select RISCV_ACLINT
188
select SIFIVE_GPIO
189
select SIFIVE_PLIC
190
select SIFIVE_UART
191
@@ -XXX,XX +XXX,XX @@ config SIFIVE_U
192
bool
193
select CADENCE
194
select MSI_NONBROKEN
195
- select SIFIVE_CLINT
196
+ select RISCV_ACLINT
197
select SIFIVE_GPIO
198
select SIFIVE_PDMA
199
select SIFIVE_PLIC
200
@@ -XXX,XX +XXX,XX @@ config SPIKE
201
select RISCV_NUMA
202
select HTIF
203
select MSI_NONBROKEN
204
- select SIFIVE_CLINT
205
+ select RISCV_ACLINT
206
select SIFIVE_PLIC
101
--
207
--
102
2.45.1
208
2.31.1
209
210
diff view generated by jsdifflib
1
From: Max Chou <max.chou@sifive.com>
1
From: Anup Patel <anup.patel@wdc.com>
2
2
3
According v spec 18.4, only the vfwcvt.f.f.v and vfncvt.f.f.w
3
The RISC-V ACLINT is more modular and backward compatible with
4
instructions will be affected by Zvfhmin extension.
4
original SiFive CLINT so instead of duplicating the original
5
And the vfwcvt.f.f.v and vfncvt.f.f.w instructions only support the
5
SiFive CLINT implementation we upgrade the current SiFive CLINT
6
conversions of
6
implementation to RISC-V ACLINT implementation.
7
7
8
* From 1*SEW(16/32) to 2*SEW(32/64)
8
Signed-off-by: Anup Patel <anup.patel@wdc.com>
9
* From 2*SEW(32/64) to 1*SEW(16/32)
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
10
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
11
Signed-off-by: Max Chou <max.chou@sifive.com>
11
Message-id: 20210831110603.338681-3-anup.patel@wdc.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>
15
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
16
---
13
---
17
target/riscv/insn_trans/trans_rvv.c.inc | 20 ++++++++++++++++++--
14
include/hw/intc/riscv_aclint.h | 54 +++--
18
1 file changed, 18 insertions(+), 2 deletions(-)
15
hw/intc/riscv_aclint.c | 373 +++++++++++++++++++++++----------
16
hw/riscv/microchip_pfsoc.c | 9 +-
17
hw/riscv/shakti_c.c | 11 +-
18
hw/riscv/sifive_e.c | 11 +-
19
hw/riscv/sifive_u.c | 9 +-
20
hw/riscv/spike.c | 14 +-
21
hw/riscv/virt.c | 14 +-
22
8 files changed, 339 insertions(+), 156 deletions(-)
19
23
20
diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc
24
diff --git a/include/hw/intc/riscv_aclint.h b/include/hw/intc/riscv_aclint.h
21
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
22
--- a/target/riscv/insn_trans/trans_rvv.c.inc
26
--- a/include/hw/intc/riscv_aclint.h
23
+++ b/target/riscv/insn_trans/trans_rvv.c.inc
27
+++ b/include/hw/intc/riscv_aclint.h
24
@@ -XXX,XX +XXX,XX @@ static bool require_rvf(DisasContext *s)
28
@@ -XXX,XX +XXX,XX @@
29
/*
30
- * SiFive CLINT (Core Local Interruptor) interface
31
+ * RISC-V ACLINT (Advanced Core Local Interruptor) interface
32
*
33
* Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
34
* Copyright (c) 2017 SiFive, Inc.
35
+ * Copyright (c) 2021 Western Digital Corporation or its affiliates.
36
*
37
* This program is free software; you can redistribute it and/or modify it
38
* under the terms and conditions of the GNU General Public License,
39
@@ -XXX,XX +XXX,XX @@
40
* this program. If not, see <http://www.gnu.org/licenses/>.
41
*/
42
43
-#ifndef HW_SIFIVE_CLINT_H
44
-#define HW_SIFIVE_CLINT_H
45
+#ifndef HW_RISCV_ACLINT_H
46
+#define HW_RISCV_ACLINT_H
47
48
#include "hw/sysbus.h"
49
50
-#define TYPE_SIFIVE_CLINT "riscv.sifive.clint"
51
+#define TYPE_RISCV_ACLINT_MTIMER "riscv.aclint.mtimer"
52
53
-#define SIFIVE_CLINT(obj) \
54
- OBJECT_CHECK(SiFiveCLINTState, (obj), TYPE_SIFIVE_CLINT)
55
+#define RISCV_ACLINT_MTIMER(obj) \
56
+ OBJECT_CHECK(RISCVAclintMTimerState, (obj), TYPE_RISCV_ACLINT_MTIMER)
57
58
-typedef struct SiFiveCLINTState {
59
+typedef struct RISCVAclintMTimerState {
60
/*< private >*/
61
SysBusDevice parent_obj;
62
63
@@ -XXX,XX +XXX,XX @@ typedef struct SiFiveCLINTState {
64
MemoryRegion mmio;
65
uint32_t hartid_base;
66
uint32_t num_harts;
67
- uint32_t sip_base;
68
uint32_t timecmp_base;
69
uint32_t time_base;
70
uint32_t aperture_size;
71
uint32_t timebase_freq;
72
qemu_irq *timer_irqs;
73
- qemu_irq *soft_irqs;
74
-} SiFiveCLINTState;
75
+} RISCVAclintMTimerState;
76
77
-DeviceState *sifive_clint_create(hwaddr addr, hwaddr size,
78
- uint32_t hartid_base, uint32_t num_harts, uint32_t sip_base,
79
+DeviceState *riscv_aclint_mtimer_create(hwaddr addr, hwaddr size,
80
+ uint32_t hartid_base, uint32_t num_harts,
81
uint32_t timecmp_base, uint32_t time_base, uint32_t timebase_freq,
82
bool provide_rdtime);
83
84
-enum {
85
- SIFIVE_SIP_BASE = 0x0,
86
- SIFIVE_TIMECMP_BASE = 0x4000,
87
- SIFIVE_TIME_BASE = 0xBFF8
88
-};
89
+#define TYPE_RISCV_ACLINT_SWI "riscv.aclint.swi"
90
+
91
+#define RISCV_ACLINT_SWI(obj) \
92
+ OBJECT_CHECK(RISCVAclintSwiState, (obj), TYPE_RISCV_ACLINT_SWI)
93
+
94
+typedef struct RISCVAclintSwiState {
95
+ /*< private >*/
96
+ SysBusDevice parent_obj;
97
+
98
+ /*< public >*/
99
+ MemoryRegion mmio;
100
+ uint32_t hartid_base;
101
+ uint32_t num_harts;
102
+ uint32_t sswi;
103
+ qemu_irq *soft_irqs;
104
+} RISCVAclintSwiState;
105
+
106
+DeviceState *riscv_aclint_swi_create(hwaddr addr, uint32_t hartid_base,
107
+ uint32_t num_harts, bool sswi);
108
109
enum {
110
- SIFIVE_CLINT_TIMEBASE_FREQ = 10000000
111
+ RISCV_ACLINT_DEFAULT_MTIMECMP = 0x0,
112
+ RISCV_ACLINT_DEFAULT_MTIME = 0x7ff8,
113
+ RISCV_ACLINT_DEFAULT_MTIMER_SIZE = 0x8000,
114
+ RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ = 10000000,
115
+ RISCV_ACLINT_MAX_HARTS = 4095,
116
+ RISCV_ACLINT_SWI_SIZE = 0x4000
117
};
118
119
#endif
120
diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c
121
index XXXXXXX..XXXXXXX 100644
122
--- a/hw/intc/riscv_aclint.c
123
+++ b/hw/intc/riscv_aclint.c
124
@@ -XXX,XX +XXX,XX @@
125
/*
126
- * SiFive CLINT (Core Local Interruptor)
127
+ * RISC-V ACLINT (Advanced Core Local Interruptor)
128
+ * URL: https://github.com/riscv/riscv-aclint
129
*
130
* Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
131
* Copyright (c) 2017 SiFive, Inc.
132
+ * Copyright (c) 2021 Western Digital Corporation or its affiliates.
133
*
134
* This provides real-time clock, timer and interprocessor interrupts.
135
*
136
@@ -XXX,XX +XXX,XX @@
137
#include "qemu/osdep.h"
138
#include "qapi/error.h"
139
#include "qemu/error-report.h"
140
+#include "qemu/log.h"
141
#include "qemu/module.h"
142
#include "hw/sysbus.h"
143
#include "target/riscv/cpu.h"
144
@@ -XXX,XX +XXX,XX @@
145
#include "qemu/timer.h"
146
#include "hw/irq.h"
147
148
-typedef struct sifive_clint_callback {
149
- SiFiveCLINTState *s;
150
+typedef struct riscv_aclint_mtimer_callback {
151
+ RISCVAclintMTimerState *s;
152
int num;
153
-} sifive_clint_callback;
154
+} riscv_aclint_mtimer_callback;
155
156
static uint64_t cpu_riscv_read_rtc(uint32_t timebase_freq)
157
{
158
@@ -XXX,XX +XXX,XX @@ static uint64_t cpu_riscv_read_rtc(uint32_t timebase_freq)
159
* Called when timecmp is written to update the QEMU timer or immediately
160
* trigger timer interrupt if mtimecmp <= current timer value.
161
*/
162
-static void sifive_clint_write_timecmp(SiFiveCLINTState *s, RISCVCPU *cpu,
163
- int hartid,
164
- uint64_t value,
165
- uint32_t timebase_freq)
166
+static void riscv_aclint_mtimer_write_timecmp(RISCVAclintMTimerState *mtimer,
167
+ RISCVCPU *cpu,
168
+ int hartid,
169
+ uint64_t value,
170
+ uint32_t timebase_freq)
171
{
172
uint64_t next;
173
uint64_t diff;
174
@@ -XXX,XX +XXX,XX @@ static void sifive_clint_write_timecmp(SiFiveCLINTState *s, RISCVCPU *cpu,
175
176
cpu->env.timecmp = value;
177
if (cpu->env.timecmp <= rtc_r) {
178
- /* if we're setting an MTIMECMP value in the "past",
179
- immediately raise the timer interrupt */
180
- qemu_irq_raise(s->timer_irqs[hartid - s->hartid_base]);
181
+ /*
182
+ * If we're setting an MTIMECMP value in the "past",
183
+ * immediately raise the timer interrupt
184
+ */
185
+ qemu_irq_raise(mtimer->timer_irqs[hartid - mtimer->hartid_base]);
186
return;
25
}
187
}
188
189
/* otherwise, set up the future timer interrupt */
190
- qemu_irq_lower(s->timer_irqs[hartid - s->hartid_base]);
191
+ qemu_irq_lower(mtimer->timer_irqs[hartid - mtimer->hartid_base]);
192
diff = cpu->env.timecmp - rtc_r;
193
/* back to ns (note args switched in muldiv64) */
194
uint64_t ns_diff = muldiv64(diff, NANOSECONDS_PER_SECOND, timebase_freq);
195
@@ -XXX,XX +XXX,XX @@ static void sifive_clint_write_timecmp(SiFiveCLINTState *s, RISCVCPU *cpu,
196
* Callback used when the timer set using timer_mod expires.
197
* Should raise the timer interrupt line
198
*/
199
-static void sifive_clint_timer_cb(void *opaque)
200
+static void riscv_aclint_mtimer_cb(void *opaque)
201
{
202
- sifive_clint_callback *state = opaque;
203
+ riscv_aclint_mtimer_callback *state = opaque;
204
205
qemu_irq_raise(state->s->timer_irqs[state->num]);
26
}
206
}
27
207
28
+static bool require_rvfmin(DisasContext *s)
208
-/* CPU wants to read rtc or timecmp register */
209
-static uint64_t sifive_clint_read(void *opaque, hwaddr addr, unsigned size)
210
+/* CPU read MTIMER register */
211
+static uint64_t riscv_aclint_mtimer_read(void *opaque, hwaddr addr,
212
+ unsigned size)
213
{
214
- SiFiveCLINTState *clint = opaque;
215
- if (addr >= clint->sip_base &&
216
- addr < clint->sip_base + (clint->num_harts << 2)) {
217
- size_t hartid = clint->hartid_base + ((addr - clint->sip_base) >> 2);
218
- CPUState *cpu = qemu_get_cpu(hartid);
219
- CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
220
- if (!env) {
221
- error_report("clint: invalid timecmp hartid: %zu", hartid);
222
- } else if ((addr & 0x3) == 0) {
223
- return (env->mip & MIP_MSIP) > 0;
224
- } else {
225
- error_report("clint: invalid read: %08x", (uint32_t)addr);
226
- return 0;
227
- }
228
- } else if (addr >= clint->timecmp_base &&
229
- addr < clint->timecmp_base + (clint->num_harts << 3)) {
230
- size_t hartid = clint->hartid_base +
231
- ((addr - clint->timecmp_base) >> 3);
232
+ RISCVAclintMTimerState *mtimer = opaque;
233
+
234
+ if (addr >= mtimer->timecmp_base &&
235
+ addr < (mtimer->timecmp_base + (mtimer->num_harts << 3))) {
236
+ size_t hartid = mtimer->hartid_base +
237
+ ((addr - mtimer->timecmp_base) >> 3);
238
CPUState *cpu = qemu_get_cpu(hartid);
239
CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
240
if (!env) {
241
- error_report("clint: invalid timecmp hartid: %zu", hartid);
242
+ qemu_log_mask(LOG_GUEST_ERROR,
243
+ "aclint-mtimer: invalid hartid: %zu", hartid);
244
} else if ((addr & 0x7) == 0) {
245
/* timecmp_lo */
246
uint64_t timecmp = env->timecmp;
247
@@ -XXX,XX +XXX,XX @@ static uint64_t sifive_clint_read(void *opaque, hwaddr addr, unsigned size)
248
uint64_t timecmp = env->timecmp;
249
return (timecmp >> 32) & 0xFFFFFFFF;
250
} else {
251
- error_report("clint: invalid read: %08x", (uint32_t)addr);
252
+ qemu_log_mask(LOG_UNIMP,
253
+ "aclint-mtimer: invalid read: %08x", (uint32_t)addr);
254
return 0;
255
}
256
- } else if (addr == clint->time_base) {
257
+ } else if (addr == mtimer->time_base) {
258
/* time_lo */
259
- return cpu_riscv_read_rtc(clint->timebase_freq) & 0xFFFFFFFF;
260
- } else if (addr == clint->time_base + 4) {
261
+ return cpu_riscv_read_rtc(mtimer->timebase_freq) & 0xFFFFFFFF;
262
+ } else if (addr == mtimer->time_base + 4) {
263
/* time_hi */
264
- return (cpu_riscv_read_rtc(clint->timebase_freq) >> 32) & 0xFFFFFFFF;
265
+ return (cpu_riscv_read_rtc(mtimer->timebase_freq) >> 32) & 0xFFFFFFFF;
266
}
267
268
- error_report("clint: invalid read: %08x", (uint32_t)addr);
269
+ qemu_log_mask(LOG_UNIMP,
270
+ "aclint-mtimer: invalid read: %08x", (uint32_t)addr);
271
return 0;
272
}
273
274
-/* CPU wrote to rtc or timecmp register */
275
-static void sifive_clint_write(void *opaque, hwaddr addr, uint64_t value,
276
- unsigned size)
277
+/* CPU write MTIMER register */
278
+static void riscv_aclint_mtimer_write(void *opaque, hwaddr addr,
279
+ uint64_t value, unsigned size)
280
{
281
- SiFiveCLINTState *clint = opaque;
282
+ RISCVAclintMTimerState *mtimer = opaque;
283
284
- if (addr >= clint->sip_base &&
285
- addr < clint->sip_base + (clint->num_harts << 2)) {
286
- size_t hartid = clint->hartid_base + ((addr - clint->sip_base) >> 2);
287
- CPUState *cpu = qemu_get_cpu(hartid);
288
- CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
289
- if (!env) {
290
- error_report("clint: invalid timecmp hartid: %zu", hartid);
291
- } else if ((addr & 0x3) == 0) {
292
- qemu_set_irq(clint->soft_irqs[hartid - clint->hartid_base], value);
293
- } else {
294
- error_report("clint: invalid sip write: %08x", (uint32_t)addr);
295
- }
296
- return;
297
- } else if (addr >= clint->timecmp_base &&
298
- addr < clint->timecmp_base + (clint->num_harts << 3)) {
299
- size_t hartid = clint->hartid_base +
300
- ((addr - clint->timecmp_base) >> 3);
301
+ if (addr >= mtimer->timecmp_base &&
302
+ addr < (mtimer->timecmp_base + (mtimer->num_harts << 3))) {
303
+ size_t hartid = mtimer->hartid_base +
304
+ ((addr - mtimer->timecmp_base) >> 3);
305
CPUState *cpu = qemu_get_cpu(hartid);
306
CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
307
if (!env) {
308
- error_report("clint: invalid timecmp hartid: %zu", hartid);
309
+ qemu_log_mask(LOG_GUEST_ERROR,
310
+ "aclint-mtimer: invalid hartid: %zu", hartid);
311
} else if ((addr & 0x7) == 0) {
312
/* timecmp_lo */
313
uint64_t timecmp_hi = env->timecmp >> 32;
314
- sifive_clint_write_timecmp(clint, RISCV_CPU(cpu), hartid,
315
- timecmp_hi << 32 | (value & 0xFFFFFFFF), clint->timebase_freq);
316
+ riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), hartid,
317
+ timecmp_hi << 32 | (value & 0xFFFFFFFF),
318
+ mtimer->timebase_freq);
319
return;
320
} else if ((addr & 0x7) == 4) {
321
/* timecmp_hi */
322
uint64_t timecmp_lo = env->timecmp;
323
- sifive_clint_write_timecmp(clint, RISCV_CPU(cpu), hartid,
324
- value << 32 | (timecmp_lo & 0xFFFFFFFF), clint->timebase_freq);
325
+ riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), hartid,
326
+ value << 32 | (timecmp_lo & 0xFFFFFFFF),
327
+ mtimer->timebase_freq);
328
} else {
329
- error_report("clint: invalid timecmp write: %08x", (uint32_t)addr);
330
+ qemu_log_mask(LOG_UNIMP,
331
+ "aclint-mtimer: invalid timecmp write: %08x",
332
+ (uint32_t)addr);
333
}
334
return;
335
- } else if (addr == clint->time_base) {
336
+ } else if (addr == mtimer->time_base) {
337
/* time_lo */
338
- error_report("clint: time_lo write not implemented");
339
+ qemu_log_mask(LOG_UNIMP,
340
+ "aclint-mtimer: time_lo write not implemented");
341
return;
342
- } else if (addr == clint->time_base + 4) {
343
+ } else if (addr == mtimer->time_base + 4) {
344
/* time_hi */
345
- error_report("clint: time_hi write not implemented");
346
+ qemu_log_mask(LOG_UNIMP,
347
+ "aclint-mtimer: time_hi write not implemented");
348
return;
349
}
350
351
- error_report("clint: invalid write: %08x", (uint32_t)addr);
352
+ qemu_log_mask(LOG_UNIMP,
353
+ "aclint-mtimer: invalid write: %08x", (uint32_t)addr);
354
}
355
356
-static const MemoryRegionOps sifive_clint_ops = {
357
- .read = sifive_clint_read,
358
- .write = sifive_clint_write,
359
+static const MemoryRegionOps riscv_aclint_mtimer_ops = {
360
+ .read = riscv_aclint_mtimer_read,
361
+ .write = riscv_aclint_mtimer_write,
362
.endianness = DEVICE_LITTLE_ENDIAN,
363
.valid = {
364
.min_access_size = 4,
365
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps sifive_clint_ops = {
366
}
367
};
368
369
-static Property sifive_clint_properties[] = {
370
- DEFINE_PROP_UINT32("hartid-base", SiFiveCLINTState, hartid_base, 0),
371
- DEFINE_PROP_UINT32("num-harts", SiFiveCLINTState, num_harts, 0),
372
- DEFINE_PROP_UINT32("sip-base", SiFiveCLINTState, sip_base, 0),
373
- DEFINE_PROP_UINT32("timecmp-base", SiFiveCLINTState, timecmp_base, 0),
374
- DEFINE_PROP_UINT32("time-base", SiFiveCLINTState, time_base, 0),
375
- DEFINE_PROP_UINT32("aperture-size", SiFiveCLINTState, aperture_size, 0),
376
- DEFINE_PROP_UINT32("timebase-freq", SiFiveCLINTState, timebase_freq, 0),
377
+static Property riscv_aclint_mtimer_properties[] = {
378
+ DEFINE_PROP_UINT32("hartid-base", RISCVAclintMTimerState,
379
+ hartid_base, 0),
380
+ DEFINE_PROP_UINT32("num-harts", RISCVAclintMTimerState, num_harts, 1),
381
+ DEFINE_PROP_UINT32("timecmp-base", RISCVAclintMTimerState,
382
+ timecmp_base, RISCV_ACLINT_DEFAULT_MTIMECMP),
383
+ DEFINE_PROP_UINT32("time-base", RISCVAclintMTimerState,
384
+ time_base, RISCV_ACLINT_DEFAULT_MTIME),
385
+ DEFINE_PROP_UINT32("aperture-size", RISCVAclintMTimerState,
386
+ aperture_size, RISCV_ACLINT_DEFAULT_MTIMER_SIZE),
387
+ DEFINE_PROP_UINT32("timebase-freq", RISCVAclintMTimerState,
388
+ timebase_freq, 0),
389
DEFINE_PROP_END_OF_LIST(),
390
};
391
392
-static void sifive_clint_realize(DeviceState *dev, Error **errp)
393
+static void riscv_aclint_mtimer_realize(DeviceState *dev, Error **errp)
394
{
395
- SiFiveCLINTState *s = SIFIVE_CLINT(dev);
396
- memory_region_init_io(&s->mmio, OBJECT(dev), &sifive_clint_ops, s,
397
- TYPE_SIFIVE_CLINT, s->aperture_size);
398
+ RISCVAclintMTimerState *s = RISCV_ACLINT_MTIMER(dev);
399
+ int i;
400
+
401
+ memory_region_init_io(&s->mmio, OBJECT(dev), &riscv_aclint_mtimer_ops,
402
+ s, TYPE_RISCV_ACLINT_MTIMER, s->aperture_size);
403
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
404
405
s->timer_irqs = g_malloc(sizeof(qemu_irq) * s->num_harts);
406
qdev_init_gpio_out(dev, s->timer_irqs, s->num_harts);
407
408
- s->soft_irqs = g_malloc(sizeof(qemu_irq) * s->num_harts);
409
- qdev_init_gpio_out(dev, s->soft_irqs, s->num_harts);
410
+ /* Claim timer interrupt bits */
411
+ for (i = 0; i < s->num_harts; i++) {
412
+ RISCVCPU *cpu = RISCV_CPU(qemu_get_cpu(s->hartid_base + i));
413
+ if (riscv_cpu_claim_interrupts(cpu, MIP_MTIP) < 0) {
414
+ error_report("MTIP already claimed");
415
+ exit(1);
416
+ }
417
+ }
418
}
419
420
-static void sifive_clint_class_init(ObjectClass *klass, void *data)
421
+static void riscv_aclint_mtimer_class_init(ObjectClass *klass, void *data)
422
{
423
DeviceClass *dc = DEVICE_CLASS(klass);
424
- dc->realize = sifive_clint_realize;
425
- device_class_set_props(dc, sifive_clint_properties);
426
+ dc->realize = riscv_aclint_mtimer_realize;
427
+ device_class_set_props(dc, riscv_aclint_mtimer_properties);
428
}
429
430
-static const TypeInfo sifive_clint_info = {
431
- .name = TYPE_SIFIVE_CLINT,
432
+static const TypeInfo riscv_aclint_mtimer_info = {
433
+ .name = TYPE_RISCV_ACLINT_MTIMER,
434
.parent = TYPE_SYS_BUS_DEVICE,
435
- .instance_size = sizeof(SiFiveCLINTState),
436
- .class_init = sifive_clint_class_init,
437
+ .instance_size = sizeof(RISCVAclintMTimerState),
438
+ .class_init = riscv_aclint_mtimer_class_init,
439
};
440
441
-static void sifive_clint_register_types(void)
442
-{
443
- type_register_static(&sifive_clint_info);
444
-}
445
-
446
-type_init(sifive_clint_register_types)
447
-
448
/*
449
- * Create CLINT device.
450
+ * Create ACLINT MTIMER device.
451
*/
452
-DeviceState *sifive_clint_create(hwaddr addr, hwaddr size,
453
- uint32_t hartid_base, uint32_t num_harts, uint32_t sip_base,
454
+DeviceState *riscv_aclint_mtimer_create(hwaddr addr, hwaddr size,
455
+ uint32_t hartid_base, uint32_t num_harts,
456
uint32_t timecmp_base, uint32_t time_base, uint32_t timebase_freq,
457
bool provide_rdtime)
458
{
459
int i;
460
+ DeviceState *dev = qdev_new(TYPE_RISCV_ACLINT_MTIMER);
461
+
462
+ assert(num_harts <= RISCV_ACLINT_MAX_HARTS);
463
+ assert(!(addr & 0x7));
464
+ assert(!(timecmp_base & 0x7));
465
+ assert(!(time_base & 0x7));
466
467
- DeviceState *dev = qdev_new(TYPE_SIFIVE_CLINT);
468
qdev_prop_set_uint32(dev, "hartid-base", hartid_base);
469
qdev_prop_set_uint32(dev, "num-harts", num_harts);
470
- qdev_prop_set_uint32(dev, "sip-base", sip_base);
471
qdev_prop_set_uint32(dev, "timecmp-base", timecmp_base);
472
qdev_prop_set_uint32(dev, "time-base", time_base);
473
qdev_prop_set_uint32(dev, "aperture-size", size);
474
@@ -XXX,XX +XXX,XX @@ DeviceState *sifive_clint_create(hwaddr addr, hwaddr size,
475
CPUState *cpu = qemu_get_cpu(hartid_base + i);
476
RISCVCPU *rvcpu = RISCV_CPU(cpu);
477
CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
478
- sifive_clint_callback *cb = g_malloc0(sizeof(sifive_clint_callback));
479
+ riscv_aclint_mtimer_callback *cb =
480
+ g_malloc0(sizeof(riscv_aclint_mtimer_callback));
481
482
if (!env) {
483
g_free(cb);
484
@@ -XXX,XX +XXX,XX @@ DeviceState *sifive_clint_create(hwaddr addr, hwaddr size,
485
riscv_cpu_set_rdtime_fn(env, cpu_riscv_read_rtc, timebase_freq);
486
}
487
488
- cb->s = SIFIVE_CLINT(dev);
489
+ cb->s = RISCV_ACLINT_MTIMER(dev);
490
cb->num = i;
491
env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
492
- &sifive_clint_timer_cb, cb);
493
+ &riscv_aclint_mtimer_cb, cb);
494
env->timecmp = 0;
495
496
qdev_connect_gpio_out(dev, i,
497
qdev_get_gpio_in(DEVICE(rvcpu), IRQ_M_TIMER));
498
- qdev_connect_gpio_out(dev, num_harts + i,
499
- qdev_get_gpio_in(DEVICE(rvcpu), IRQ_M_SOFT));
500
}
501
502
return dev;
503
}
504
+
505
+/* CPU read [M|S]SWI register */
506
+static uint64_t riscv_aclint_swi_read(void *opaque, hwaddr addr,
507
+ unsigned size)
29
+{
508
+{
30
+ if (s->mstatus_fs == EXT_STATUS_DISABLED) {
509
+ RISCVAclintSwiState *swi = opaque;
31
+ return false;
510
+
511
+ if (addr < (swi->num_harts << 2)) {
512
+ size_t hartid = swi->hartid_base + (addr >> 2);
513
+ CPUState *cpu = qemu_get_cpu(hartid);
514
+ CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
515
+ if (!env) {
516
+ qemu_log_mask(LOG_GUEST_ERROR,
517
+ "aclint-swi: invalid hartid: %zu", hartid);
518
+ } else if ((addr & 0x3) == 0) {
519
+ return (swi->sswi) ? 0 : ((env->mip & MIP_MSIP) > 0);
520
+ }
32
+ }
521
+ }
33
+
522
+
34
+ switch (s->sew) {
523
+ qemu_log_mask(LOG_UNIMP,
35
+ case MO_16:
524
+ "aclint-swi: invalid read: %08x", (uint32_t)addr);
36
+ return s->cfg_ptr->ext_zvfhmin;
525
+ return 0;
37
+ case MO_32:
526
+}
38
+ return s->cfg_ptr->ext_zve32f;
527
+
39
+ default:
528
+/* CPU write [M|S]SWI register */
40
+ return false;
529
+static void riscv_aclint_swi_write(void *opaque, hwaddr addr, uint64_t value,
530
+ unsigned size)
531
+{
532
+ RISCVAclintSwiState *swi = opaque;
533
+
534
+ if (addr < (swi->num_harts << 2)) {
535
+ size_t hartid = swi->hartid_base + (addr >> 2);
536
+ CPUState *cpu = qemu_get_cpu(hartid);
537
+ CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
538
+ if (!env) {
539
+ qemu_log_mask(LOG_GUEST_ERROR,
540
+ "aclint-swi: invalid hartid: %zu", hartid);
541
+ } else if ((addr & 0x3) == 0) {
542
+ if (value & 0x1) {
543
+ qemu_irq_raise(swi->soft_irqs[hartid - swi->hartid_base]);
544
+ } else {
545
+ if (!swi->sswi) {
546
+ qemu_irq_lower(swi->soft_irqs[hartid - swi->hartid_base]);
547
+ }
548
+ }
549
+ return;
550
+ }
551
+ }
552
+
553
+ qemu_log_mask(LOG_UNIMP,
554
+ "aclint-swi: invalid write: %08x", (uint32_t)addr);
555
+}
556
+
557
+static const MemoryRegionOps riscv_aclint_swi_ops = {
558
+ .read = riscv_aclint_swi_read,
559
+ .write = riscv_aclint_swi_write,
560
+ .endianness = DEVICE_LITTLE_ENDIAN,
561
+ .valid = {
562
+ .min_access_size = 4,
563
+ .max_access_size = 4
564
+ }
565
+};
566
+
567
+static Property riscv_aclint_swi_properties[] = {
568
+ DEFINE_PROP_UINT32("hartid-base", RISCVAclintSwiState, hartid_base, 0),
569
+ DEFINE_PROP_UINT32("num-harts", RISCVAclintSwiState, num_harts, 1),
570
+ DEFINE_PROP_UINT32("sswi", RISCVAclintSwiState, sswi, false),
571
+ DEFINE_PROP_END_OF_LIST(),
572
+};
573
+
574
+static void riscv_aclint_swi_realize(DeviceState *dev, Error **errp)
575
+{
576
+ RISCVAclintSwiState *swi = RISCV_ACLINT_SWI(dev);
577
+ int i;
578
+
579
+ memory_region_init_io(&swi->mmio, OBJECT(dev), &riscv_aclint_swi_ops, swi,
580
+ TYPE_RISCV_ACLINT_SWI, RISCV_ACLINT_SWI_SIZE);
581
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &swi->mmio);
582
+
583
+ swi->soft_irqs = g_malloc(sizeof(qemu_irq) * swi->num_harts);
584
+ qdev_init_gpio_out(dev, swi->soft_irqs, swi->num_harts);
585
+
586
+ /* Claim software interrupt bits */
587
+ for (i = 0; i < swi->num_harts; i++) {
588
+ RISCVCPU *cpu = RISCV_CPU(qemu_get_cpu(swi->hartid_base + i));
589
+ /* We don't claim mip.SSIP because it is writeable by software */
590
+ if (riscv_cpu_claim_interrupts(cpu, swi->sswi ? 0 : MIP_MSIP) < 0) {
591
+ error_report("MSIP already claimed");
592
+ exit(1);
593
+ }
41
+ }
594
+ }
42
+}
595
+}
43
+
596
+
44
static bool require_scale_rvf(DisasContext *s)
597
+static void riscv_aclint_swi_class_init(ObjectClass *klass, void *data)
45
{
598
+{
46
if (s->mstatus_fs == EXT_STATUS_DISABLED) {
599
+ DeviceClass *dc = DEVICE_CLASS(klass);
47
@@ -XXX,XX +XXX,XX @@ static bool require_scale_rvfmin(DisasContext *s)
600
+ dc->realize = riscv_aclint_swi_realize;
601
+ device_class_set_props(dc, riscv_aclint_swi_properties);
602
+}
603
+
604
+static const TypeInfo riscv_aclint_swi_info = {
605
+ .name = TYPE_RISCV_ACLINT_SWI,
606
+ .parent = TYPE_SYS_BUS_DEVICE,
607
+ .instance_size = sizeof(RISCVAclintSwiState),
608
+ .class_init = riscv_aclint_swi_class_init,
609
+};
610
+
611
+/*
612
+ * Create ACLINT [M|S]SWI device.
613
+ */
614
+DeviceState *riscv_aclint_swi_create(hwaddr addr, uint32_t hartid_base,
615
+ uint32_t num_harts, bool sswi)
616
+{
617
+ int i;
618
+ DeviceState *dev = qdev_new(TYPE_RISCV_ACLINT_SWI);
619
+
620
+ assert(num_harts <= RISCV_ACLINT_MAX_HARTS);
621
+ assert(!(addr & 0x3));
622
+
623
+ qdev_prop_set_uint32(dev, "hartid-base", hartid_base);
624
+ qdev_prop_set_uint32(dev, "num-harts", num_harts);
625
+ qdev_prop_set_uint32(dev, "sswi", sswi ? true : false);
626
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
627
+ sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
628
+
629
+ for (i = 0; i < num_harts; i++) {
630
+ CPUState *cpu = qemu_get_cpu(hartid_base + i);
631
+ RISCVCPU *rvcpu = RISCV_CPU(cpu);
632
+
633
+ qdev_connect_gpio_out(dev, i,
634
+ qdev_get_gpio_in(DEVICE(rvcpu),
635
+ (sswi) ? IRQ_S_SOFT : IRQ_M_SOFT));
636
+ }
637
+
638
+ return dev;
639
+}
640
+
641
+static void riscv_aclint_register_types(void)
642
+{
643
+ type_register_static(&riscv_aclint_mtimer_info);
644
+ type_register_static(&riscv_aclint_swi_info);
645
+}
646
+
647
+type_init(riscv_aclint_register_types)
648
diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
649
index XXXXXXX..XXXXXXX 100644
650
--- a/hw/riscv/microchip_pfsoc.c
651
+++ b/hw/riscv/microchip_pfsoc.c
652
@@ -XXX,XX +XXX,XX @@ static void microchip_pfsoc_soc_realize(DeviceState *dev, Error **errp)
653
memmap[MICROCHIP_PFSOC_BUSERR_UNIT4].size);
654
655
/* CLINT */
656
- sifive_clint_create(memmap[MICROCHIP_PFSOC_CLINT].base,
657
- memmap[MICROCHIP_PFSOC_CLINT].size, 0, ms->smp.cpus,
658
- SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE,
659
+ riscv_aclint_swi_create(memmap[MICROCHIP_PFSOC_CLINT].base,
660
+ 0, ms->smp.cpus, false);
661
+ riscv_aclint_mtimer_create(
662
+ memmap[MICROCHIP_PFSOC_CLINT].base + RISCV_ACLINT_SWI_SIZE,
663
+ RISCV_ACLINT_DEFAULT_MTIMER_SIZE, 0, ms->smp.cpus,
664
+ RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME,
665
CLINT_TIMEBASE_FREQ, false);
666
667
/* L2 cache controller */
668
diff --git a/hw/riscv/shakti_c.c b/hw/riscv/shakti_c.c
669
index XXXXXXX..XXXXXXX 100644
670
--- a/hw/riscv/shakti_c.c
671
+++ b/hw/riscv/shakti_c.c
672
@@ -XXX,XX +XXX,XX @@ static void shakti_c_soc_state_realize(DeviceState *dev, Error **errp)
673
SHAKTI_C_PLIC_CONTEXT_STRIDE,
674
shakti_c_memmap[SHAKTI_C_PLIC].size);
675
676
- sifive_clint_create(shakti_c_memmap[SHAKTI_C_CLINT].base,
677
- shakti_c_memmap[SHAKTI_C_CLINT].size, 0, 1,
678
- SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE,
679
- SIFIVE_CLINT_TIMEBASE_FREQ, false);
680
+ riscv_aclint_swi_create(shakti_c_memmap[SHAKTI_C_CLINT].base,
681
+ 0, 1, false);
682
+ riscv_aclint_mtimer_create(shakti_c_memmap[SHAKTI_C_CLINT].base +
683
+ RISCV_ACLINT_SWI_SIZE,
684
+ RISCV_ACLINT_DEFAULT_MTIMER_SIZE, 0, 1,
685
+ RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME,
686
+ RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ, false);
687
688
qdev_prop_set_chr(DEVICE(&(sss->uart)), "chardev", serial_hd(0));
689
if (!sysbus_realize(SYS_BUS_DEVICE(&sss->uart), errp)) {
690
diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
691
index XXXXXXX..XXXXXXX 100644
692
--- a/hw/riscv/sifive_e.c
693
+++ b/hw/riscv/sifive_e.c
694
@@ -XXX,XX +XXX,XX @@ static void sifive_e_soc_realize(DeviceState *dev, Error **errp)
695
SIFIVE_E_PLIC_CONTEXT_BASE,
696
SIFIVE_E_PLIC_CONTEXT_STRIDE,
697
memmap[SIFIVE_E_DEV_PLIC].size);
698
- sifive_clint_create(memmap[SIFIVE_E_DEV_CLINT].base,
699
- memmap[SIFIVE_E_DEV_CLINT].size, 0, ms->smp.cpus,
700
- SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE,
701
- SIFIVE_CLINT_TIMEBASE_FREQ, false);
702
+ riscv_aclint_swi_create(memmap[SIFIVE_E_DEV_CLINT].base,
703
+ 0, ms->smp.cpus, false);
704
+ riscv_aclint_mtimer_create(memmap[SIFIVE_E_DEV_CLINT].base +
705
+ RISCV_ACLINT_SWI_SIZE,
706
+ RISCV_ACLINT_DEFAULT_MTIMER_SIZE, 0, ms->smp.cpus,
707
+ RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME,
708
+ RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ, false);
709
create_unimplemented_device("riscv.sifive.e.aon",
710
memmap[SIFIVE_E_DEV_AON].base, memmap[SIFIVE_E_DEV_AON].size);
711
sifive_e_prci_create(memmap[SIFIVE_E_DEV_PRCI].base);
712
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
713
index XXXXXXX..XXXXXXX 100644
714
--- a/hw/riscv/sifive_u.c
715
+++ b/hw/riscv/sifive_u.c
716
@@ -XXX,XX +XXX,XX @@ static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
717
serial_hd(0), qdev_get_gpio_in(DEVICE(s->plic), SIFIVE_U_UART0_IRQ));
718
sifive_uart_create(system_memory, memmap[SIFIVE_U_DEV_UART1].base,
719
serial_hd(1), qdev_get_gpio_in(DEVICE(s->plic), SIFIVE_U_UART1_IRQ));
720
- sifive_clint_create(memmap[SIFIVE_U_DEV_CLINT].base,
721
- memmap[SIFIVE_U_DEV_CLINT].size, 0, ms->smp.cpus,
722
- SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE,
723
+ riscv_aclint_swi_create(memmap[SIFIVE_U_DEV_CLINT].base, 0,
724
+ ms->smp.cpus, false);
725
+ riscv_aclint_mtimer_create(memmap[SIFIVE_U_DEV_CLINT].base +
726
+ RISCV_ACLINT_SWI_SIZE,
727
+ RISCV_ACLINT_DEFAULT_MTIMER_SIZE, 0, ms->smp.cpus,
728
+ RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME,
729
CLINT_TIMEBASE_FREQ, false);
730
731
if (!sysbus_realize(SYS_BUS_DEVICE(&s->prci), errp)) {
732
diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
733
index XXXXXXX..XXXXXXX 100644
734
--- a/hw/riscv/spike.c
735
+++ b/hw/riscv/spike.c
736
@@ -XXX,XX +XXX,XX @@ static void create_fdt(SpikeState *s, const MemMapEntry *memmap,
737
738
qemu_fdt_add_subnode(fdt, "/cpus");
739
qemu_fdt_setprop_cell(fdt, "/cpus", "timebase-frequency",
740
- SIFIVE_CLINT_TIMEBASE_FREQ);
741
+ RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ);
742
qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0x0);
743
qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 0x1);
744
qemu_fdt_add_subnode(fdt, "/cpus/cpu-map");
745
@@ -XXX,XX +XXX,XX @@ static void spike_board_init(MachineState *machine)
746
sysbus_realize(SYS_BUS_DEVICE(&s->soc[i]), &error_abort);
747
748
/* Core Local Interruptor (timer and IPI) for each socket */
749
- sifive_clint_create(
750
+ riscv_aclint_swi_create(
751
memmap[SPIKE_CLINT].base + i * memmap[SPIKE_CLINT].size,
752
- memmap[SPIKE_CLINT].size, base_hartid, hart_count,
753
- SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE,
754
- SIFIVE_CLINT_TIMEBASE_FREQ, false);
755
+ base_hartid, hart_count, false);
756
+ riscv_aclint_mtimer_create(
757
+ memmap[SPIKE_CLINT].base + i * memmap[SPIKE_CLINT].size +
758
+ RISCV_ACLINT_SWI_SIZE,
759
+ RISCV_ACLINT_DEFAULT_MTIMER_SIZE, base_hartid, hart_count,
760
+ RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME,
761
+ RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ, false);
48
}
762
}
49
763
50
switch (s->sew) {
764
/* register system main memory (actual RAM) */
51
- case MO_8:
765
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
52
- return s->cfg_ptr->ext_zvfhmin;
766
index XXXXXXX..XXXXXXX 100644
53
case MO_16:
767
--- a/hw/riscv/virt.c
54
return s->cfg_ptr->ext_zve32f;
768
+++ b/hw/riscv/virt.c
55
case MO_32:
769
@@ -XXX,XX +XXX,XX @@ static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap,
56
@@ -XXX,XX +XXX,XX @@ static bool opxfv_widen_check(DisasContext *s, arg_rmr *a)
770
57
static bool opffv_widen_check(DisasContext *s, arg_rmr *a)
771
qemu_fdt_add_subnode(fdt, "/cpus");
58
{
772
qemu_fdt_setprop_cell(fdt, "/cpus", "timebase-frequency",
59
return opfv_widen_check(s, a) &&
773
- SIFIVE_CLINT_TIMEBASE_FREQ);
60
+ require_rvfmin(s) &&
774
+ RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ);
61
require_scale_rvfmin(s) &&
775
qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0x0);
62
(s->sew != MO_8);
776
qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 0x1);
63
}
777
qemu_fdt_add_subnode(fdt, "/cpus/cpu-map");
64
@@ -XXX,XX +XXX,XX @@ static bool opfxv_narrow_check(DisasContext *s, arg_rmr *a)
778
@@ -XXX,XX +XXX,XX @@ static void virt_machine_init(MachineState *machine)
65
static bool opffv_narrow_check(DisasContext *s, arg_rmr *a)
779
sysbus_realize(SYS_BUS_DEVICE(&s->soc[i]), &error_abort);
66
{
780
67
return opfv_narrow_check(s, a) &&
781
/* Per-socket CLINT */
68
+ require_rvfmin(s) &&
782
- sifive_clint_create(
69
require_scale_rvfmin(s) &&
783
+ riscv_aclint_swi_create(
70
(s->sew != MO_8);
784
memmap[VIRT_CLINT].base + i * memmap[VIRT_CLINT].size,
71
}
785
- memmap[VIRT_CLINT].size, base_hartid, hart_count,
786
- SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE,
787
- SIFIVE_CLINT_TIMEBASE_FREQ, true);
788
+ base_hartid, hart_count, false);
789
+ riscv_aclint_mtimer_create(
790
+ memmap[VIRT_CLINT].base + i * memmap[VIRT_CLINT].size +
791
+ RISCV_ACLINT_SWI_SIZE,
792
+ RISCV_ACLINT_DEFAULT_MTIMER_SIZE, base_hartid, hart_count,
793
+ RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME,
794
+ RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ, true);
795
796
/* Per-socket PLIC hart topology configuration string */
797
plic_hart_config = plic_hart_config_string(hart_count);
72
--
798
--
73
2.45.1
799
2.31.1
800
801
diff view generated by jsdifflib
1
From: Cheng Yang <yangcheng.work@foxmail.com>
1
From: Anup Patel <anup.patel@wdc.com>
2
2
3
Use qemu_fdt_setprop_u64() instead of qemu_fdt_setprop_cell()
3
We re-factor and break the FDT generation into smaller functions
4
to set the address of initrd in FDT to support 64-bit address.
4
so that it is easier to modify FDT generation for different
5
configurations of virt machine.
5
6
6
Signed-off-by: Cheng Yang <yangcheng.work@foxmail.com>
7
Signed-off-by: Anup Patel <anup.patel@wdc.com>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Message-ID: <tencent_A4482251DD0890F312758FA6B33F60815609@qq.com>
9
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
10
Message-id: 20210831110603.338681-4-anup.patel@wdc.com
9
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
10
---
12
---
11
hw/riscv/boot.c | 4 ++--
13
hw/riscv/virt.c | 527 ++++++++++++++++++++++++++++++------------------
12
1 file changed, 2 insertions(+), 2 deletions(-)
14
1 file changed, 327 insertions(+), 200 deletions(-)
13
15
14
diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
16
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/riscv/boot.c
18
--- a/hw/riscv/virt.c
17
+++ b/hw/riscv/boot.c
19
+++ b/hw/riscv/virt.c
18
@@ -XXX,XX +XXX,XX @@ static void riscv_load_initrd(MachineState *machine, uint64_t kernel_entry)
20
@@ -XXX,XX +XXX,XX @@ static void create_pcie_irq_map(void *fdt, char *nodename,
19
/* Some RISC-V machines (e.g. opentitan) don't have a fdt. */
21
0x1800, 0, 0, 0x7);
20
if (fdt) {
22
}
21
end = start + size;
23
22
- qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start", start);
24
-static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap,
23
- qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end", end);
25
- uint64_t mem_size, const char *cmdline, bool is_32_bit)
24
+ qemu_fdt_setprop_u64(fdt, "/chosen", "linux,initrd-start", start);
26
+static void create_fdt_socket_cpus(RISCVVirtState *s, int socket,
25
+ qemu_fdt_setprop_u64(fdt, "/chosen", "linux,initrd-end", end);
27
+ char *clust_name, uint32_t *phandle,
28
+ bool is_32_bit, uint32_t *intc_phandles)
29
{
30
- void *fdt;
31
- int i, cpu, socket;
32
+ int cpu;
33
+ uint32_t cpu_phandle;
34
MachineState *mc = MACHINE(s);
35
+ char *name, *cpu_name, *core_name, *intc_name;
36
+
37
+ for (cpu = s->soc[socket].num_harts - 1; cpu >= 0; cpu--) {
38
+ cpu_phandle = (*phandle)++;
39
+
40
+ cpu_name = g_strdup_printf("/cpus/cpu@%d",
41
+ s->soc[socket].hartid_base + cpu);
42
+ qemu_fdt_add_subnode(mc->fdt, cpu_name);
43
+ qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
44
+ (is_32_bit) ? "riscv,sv32" : "riscv,sv48");
45
+ name = riscv_isa_string(&s->soc[socket].harts[cpu]);
46
+ qemu_fdt_setprop_string(mc->fdt, cpu_name, "riscv,isa", name);
47
+ g_free(name);
48
+ qemu_fdt_setprop_string(mc->fdt, cpu_name, "compatible", "riscv");
49
+ qemu_fdt_setprop_string(mc->fdt, cpu_name, "status", "okay");
50
+ qemu_fdt_setprop_cell(mc->fdt, cpu_name, "reg",
51
+ s->soc[socket].hartid_base + cpu);
52
+ qemu_fdt_setprop_string(mc->fdt, cpu_name, "device_type", "cpu");
53
+ riscv_socket_fdt_write_id(mc, mc->fdt, cpu_name, socket);
54
+ qemu_fdt_setprop_cell(mc->fdt, cpu_name, "phandle", cpu_phandle);
55
+
56
+ intc_phandles[cpu] = (*phandle)++;
57
+
58
+ intc_name = g_strdup_printf("%s/interrupt-controller", cpu_name);
59
+ qemu_fdt_add_subnode(mc->fdt, intc_name);
60
+ qemu_fdt_setprop_cell(mc->fdt, intc_name, "phandle",
61
+ intc_phandles[cpu]);
62
+ qemu_fdt_setprop_string(mc->fdt, intc_name, "compatible",
63
+ "riscv,cpu-intc");
64
+ qemu_fdt_setprop(mc->fdt, intc_name, "interrupt-controller", NULL, 0);
65
+ qemu_fdt_setprop_cell(mc->fdt, intc_name, "#interrupt-cells", 1);
66
+
67
+ core_name = g_strdup_printf("%s/core%d", clust_name, cpu);
68
+ qemu_fdt_add_subnode(mc->fdt, core_name);
69
+ qemu_fdt_setprop_cell(mc->fdt, core_name, "cpu", cpu_phandle);
70
+
71
+ g_free(core_name);
72
+ g_free(intc_name);
73
+ g_free(cpu_name);
74
+ }
75
+}
76
+
77
+static void create_fdt_socket_memory(RISCVVirtState *s,
78
+ const MemMapEntry *memmap, int socket)
79
+{
80
+ char *mem_name;
81
uint64_t addr, size;
82
- uint32_t *clint_cells, *plic_cells;
83
- unsigned long clint_addr, plic_addr;
84
- uint32_t plic_phandle[MAX_NODES];
85
- uint32_t cpu_phandle, intc_phandle, test_phandle;
86
- uint32_t phandle = 1, plic_mmio_phandle = 1;
87
- uint32_t plic_pcie_phandle = 1, plic_virtio_phandle = 1;
88
- char *mem_name, *cpu_name, *core_name, *intc_name;
89
- char *name, *clint_name, *plic_name, *clust_name;
90
- hwaddr flashsize = virt_memmap[VIRT_FLASH].size / 2;
91
- hwaddr flashbase = virt_memmap[VIRT_FLASH].base;
92
+ MachineState *mc = MACHINE(s);
93
+
94
+ addr = memmap[VIRT_DRAM].base + riscv_socket_mem_offset(mc, socket);
95
+ size = riscv_socket_mem_size(mc, socket);
96
+ mem_name = g_strdup_printf("/memory@%lx", (long)addr);
97
+ qemu_fdt_add_subnode(mc->fdt, mem_name);
98
+ qemu_fdt_setprop_cells(mc->fdt, mem_name, "reg",
99
+ addr >> 32, addr, size >> 32, size);
100
+ qemu_fdt_setprop_string(mc->fdt, mem_name, "device_type", "memory");
101
+ riscv_socket_fdt_write_id(mc, mc->fdt, mem_name, socket);
102
+ g_free(mem_name);
103
+}
104
+
105
+static void create_fdt_socket_clint(RISCVVirtState *s,
106
+ const MemMapEntry *memmap, int socket,
107
+ uint32_t *intc_phandles)
108
+{
109
+ int cpu;
110
+ char *clint_name;
111
+ uint32_t *clint_cells;
112
+ unsigned long clint_addr;
113
+ MachineState *mc = MACHINE(s);
114
static const char * const clint_compat[2] = {
115
"sifive,clint0", "riscv,clint0"
116
};
117
+
118
+ clint_cells = g_new0(uint32_t, s->soc[socket].num_harts * 4);
119
+
120
+ for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) {
121
+ clint_cells[cpu * 4 + 0] = cpu_to_be32(intc_phandles[cpu]);
122
+ clint_cells[cpu * 4 + 1] = cpu_to_be32(IRQ_M_SOFT);
123
+ clint_cells[cpu * 4 + 2] = cpu_to_be32(intc_phandles[cpu]);
124
+ clint_cells[cpu * 4 + 3] = cpu_to_be32(IRQ_M_TIMER);
125
+ }
126
+
127
+ clint_addr = memmap[VIRT_CLINT].base + (memmap[VIRT_CLINT].size * socket);
128
+ clint_name = g_strdup_printf("/soc/clint@%lx", clint_addr);
129
+ qemu_fdt_add_subnode(mc->fdt, clint_name);
130
+ qemu_fdt_setprop_string_array(mc->fdt, clint_name, "compatible",
131
+ (char **)&clint_compat,
132
+ ARRAY_SIZE(clint_compat));
133
+ qemu_fdt_setprop_cells(mc->fdt, clint_name, "reg",
134
+ 0x0, clint_addr, 0x0, memmap[VIRT_CLINT].size);
135
+ qemu_fdt_setprop(mc->fdt, clint_name, "interrupts-extended",
136
+ clint_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 4);
137
+ riscv_socket_fdt_write_id(mc, mc->fdt, clint_name, socket);
138
+ g_free(clint_name);
139
+
140
+ g_free(clint_cells);
141
+}
142
+
143
+static void create_fdt_socket_plic(RISCVVirtState *s,
144
+ const MemMapEntry *memmap, int socket,
145
+ uint32_t *phandle, uint32_t *intc_phandles,
146
+ uint32_t *plic_phandles)
147
+{
148
+ int cpu;
149
+ char *plic_name;
150
+ uint32_t *plic_cells;
151
+ unsigned long plic_addr;
152
+ MachineState *mc = MACHINE(s);
153
static const char * const plic_compat[2] = {
154
"sifive,plic-1.0.0", "riscv,plic0"
155
};
156
157
- if (mc->dtb) {
158
- fdt = mc->fdt = load_device_tree(mc->dtb, &s->fdt_size);
159
- if (!fdt) {
160
- error_report("load_device_tree() failed");
161
- exit(1);
162
- }
163
- goto update_bootargs;
164
- } else {
165
- fdt = mc->fdt = create_device_tree(&s->fdt_size);
166
- if (!fdt) {
167
- error_report("create_device_tree() failed");
168
- exit(1);
169
- }
170
+ plic_cells = g_new0(uint32_t, s->soc[socket].num_harts * 4);
171
+
172
+ for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) {
173
+ plic_cells[cpu * 4 + 0] = cpu_to_be32(intc_phandles[cpu]);
174
+ plic_cells[cpu * 4 + 1] = cpu_to_be32(IRQ_M_EXT);
175
+ plic_cells[cpu * 4 + 2] = cpu_to_be32(intc_phandles[cpu]);
176
+ plic_cells[cpu * 4 + 3] = cpu_to_be32(IRQ_S_EXT);
177
}
178
179
- qemu_fdt_setprop_string(fdt, "/", "model", "riscv-virtio,qemu");
180
- qemu_fdt_setprop_string(fdt, "/", "compatible", "riscv-virtio");
181
- qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 0x2);
182
- qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 0x2);
183
+ plic_phandles[socket] = (*phandle)++;
184
+ plic_addr = memmap[VIRT_PLIC].base + (memmap[VIRT_PLIC].size * socket);
185
+ plic_name = g_strdup_printf("/soc/plic@%lx", plic_addr);
186
+ qemu_fdt_add_subnode(mc->fdt, plic_name);
187
+ qemu_fdt_setprop_cell(mc->fdt, plic_name,
188
+ "#address-cells", FDT_PLIC_ADDR_CELLS);
189
+ qemu_fdt_setprop_cell(mc->fdt, plic_name,
190
+ "#interrupt-cells", FDT_PLIC_INT_CELLS);
191
+ qemu_fdt_setprop_string_array(mc->fdt, plic_name, "compatible",
192
+ (char **)&plic_compat,
193
+ ARRAY_SIZE(plic_compat));
194
+ qemu_fdt_setprop(mc->fdt, plic_name, "interrupt-controller", NULL, 0);
195
+ qemu_fdt_setprop(mc->fdt, plic_name, "interrupts-extended",
196
+ plic_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 4);
197
+ qemu_fdt_setprop_cells(mc->fdt, plic_name, "reg",
198
+ 0x0, plic_addr, 0x0, memmap[VIRT_PLIC].size);
199
+ qemu_fdt_setprop_cell(mc->fdt, plic_name, "riscv,ndev", VIRTIO_NDEV);
200
+ riscv_socket_fdt_write_id(mc, mc->fdt, plic_name, socket);
201
+ qemu_fdt_setprop_cell(mc->fdt, plic_name, "phandle",
202
+ plic_phandles[socket]);
203
+ g_free(plic_name);
204
+
205
+ g_free(plic_cells);
206
+}
207
208
- qemu_fdt_add_subnode(fdt, "/soc");
209
- qemu_fdt_setprop(fdt, "/soc", "ranges", NULL, 0);
210
- qemu_fdt_setprop_string(fdt, "/soc", "compatible", "simple-bus");
211
- qemu_fdt_setprop_cell(fdt, "/soc", "#size-cells", 0x2);
212
- qemu_fdt_setprop_cell(fdt, "/soc", "#address-cells", 0x2);
213
+static void create_fdt_sockets(RISCVVirtState *s, const MemMapEntry *memmap,
214
+ bool is_32_bit, uint32_t *phandle,
215
+ uint32_t *irq_mmio_phandle,
216
+ uint32_t *irq_pcie_phandle,
217
+ uint32_t *irq_virtio_phandle)
218
+{
219
+ int socket;
220
+ char *clust_name;
221
+ uint32_t *intc_phandles;
222
+ MachineState *mc = MACHINE(s);
223
+ uint32_t xplic_phandles[MAX_NODES];
224
225
- qemu_fdt_add_subnode(fdt, "/cpus");
226
- qemu_fdt_setprop_cell(fdt, "/cpus", "timebase-frequency",
227
+ qemu_fdt_add_subnode(mc->fdt, "/cpus");
228
+ qemu_fdt_setprop_cell(mc->fdt, "/cpus", "timebase-frequency",
229
RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ);
230
- qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0x0);
231
- qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 0x1);
232
- qemu_fdt_add_subnode(fdt, "/cpus/cpu-map");
233
+ qemu_fdt_setprop_cell(mc->fdt, "/cpus", "#size-cells", 0x0);
234
+ qemu_fdt_setprop_cell(mc->fdt, "/cpus", "#address-cells", 0x1);
235
+ qemu_fdt_add_subnode(mc->fdt, "/cpus/cpu-map");
236
237
for (socket = (riscv_socket_count(mc) - 1); socket >= 0; socket--) {
238
clust_name = g_strdup_printf("/cpus/cpu-map/cluster%d", socket);
239
- qemu_fdt_add_subnode(fdt, clust_name);
240
-
241
- plic_cells = g_new0(uint32_t, s->soc[socket].num_harts * 4);
242
- clint_cells = g_new0(uint32_t, s->soc[socket].num_harts * 4);
243
-
244
- for (cpu = s->soc[socket].num_harts - 1; cpu >= 0; cpu--) {
245
- cpu_phandle = phandle++;
246
-
247
- cpu_name = g_strdup_printf("/cpus/cpu@%d",
248
- s->soc[socket].hartid_base + cpu);
249
- qemu_fdt_add_subnode(fdt, cpu_name);
250
- if (is_32_bit) {
251
- qemu_fdt_setprop_string(fdt, cpu_name, "mmu-type", "riscv,sv32");
252
- } else {
253
- qemu_fdt_setprop_string(fdt, cpu_name, "mmu-type", "riscv,sv48");
254
- }
255
- name = riscv_isa_string(&s->soc[socket].harts[cpu]);
256
- qemu_fdt_setprop_string(fdt, cpu_name, "riscv,isa", name);
257
- g_free(name);
258
- qemu_fdt_setprop_string(fdt, cpu_name, "compatible", "riscv");
259
- qemu_fdt_setprop_string(fdt, cpu_name, "status", "okay");
260
- qemu_fdt_setprop_cell(fdt, cpu_name, "reg",
261
- s->soc[socket].hartid_base + cpu);
262
- qemu_fdt_setprop_string(fdt, cpu_name, "device_type", "cpu");
263
- riscv_socket_fdt_write_id(mc, fdt, cpu_name, socket);
264
- qemu_fdt_setprop_cell(fdt, cpu_name, "phandle", cpu_phandle);
265
-
266
- intc_name = g_strdup_printf("%s/interrupt-controller", cpu_name);
267
- qemu_fdt_add_subnode(fdt, intc_name);
268
- intc_phandle = phandle++;
269
- qemu_fdt_setprop_cell(fdt, intc_name, "phandle", intc_phandle);
270
- qemu_fdt_setprop_string(fdt, intc_name, "compatible",
271
- "riscv,cpu-intc");
272
- qemu_fdt_setprop(fdt, intc_name, "interrupt-controller", NULL, 0);
273
- qemu_fdt_setprop_cell(fdt, intc_name, "#interrupt-cells", 1);
274
-
275
- clint_cells[cpu * 4 + 0] = cpu_to_be32(intc_phandle);
276
- clint_cells[cpu * 4 + 1] = cpu_to_be32(IRQ_M_SOFT);
277
- clint_cells[cpu * 4 + 2] = cpu_to_be32(intc_phandle);
278
- clint_cells[cpu * 4 + 3] = cpu_to_be32(IRQ_M_TIMER);
279
-
280
- plic_cells[cpu * 4 + 0] = cpu_to_be32(intc_phandle);
281
- plic_cells[cpu * 4 + 1] = cpu_to_be32(IRQ_M_EXT);
282
- plic_cells[cpu * 4 + 2] = cpu_to_be32(intc_phandle);
283
- plic_cells[cpu * 4 + 3] = cpu_to_be32(IRQ_S_EXT);
284
-
285
- core_name = g_strdup_printf("%s/core%d", clust_name, cpu);
286
- qemu_fdt_add_subnode(fdt, core_name);
287
- qemu_fdt_setprop_cell(fdt, core_name, "cpu", cpu_phandle);
288
-
289
- g_free(core_name);
290
- g_free(intc_name);
291
- g_free(cpu_name);
292
- }
293
+ qemu_fdt_add_subnode(mc->fdt, clust_name);
294
+
295
+ intc_phandles = g_new0(uint32_t, s->soc[socket].num_harts);
296
+
297
+ create_fdt_socket_cpus(s, socket, clust_name, phandle,
298
+ is_32_bit, intc_phandles);
299
300
- addr = memmap[VIRT_DRAM].base + riscv_socket_mem_offset(mc, socket);
301
- size = riscv_socket_mem_size(mc, socket);
302
- mem_name = g_strdup_printf("/memory@%lx", (long)addr);
303
- qemu_fdt_add_subnode(fdt, mem_name);
304
- qemu_fdt_setprop_cells(fdt, mem_name, "reg",
305
- addr >> 32, addr, size >> 32, size);
306
- qemu_fdt_setprop_string(fdt, mem_name, "device_type", "memory");
307
- riscv_socket_fdt_write_id(mc, fdt, mem_name, socket);
308
- g_free(mem_name);
309
-
310
- clint_addr = memmap[VIRT_CLINT].base +
311
- (memmap[VIRT_CLINT].size * socket);
312
- clint_name = g_strdup_printf("/soc/clint@%lx", clint_addr);
313
- qemu_fdt_add_subnode(fdt, clint_name);
314
- qemu_fdt_setprop_string_array(fdt, clint_name, "compatible",
315
- (char **)&clint_compat, ARRAY_SIZE(clint_compat));
316
- qemu_fdt_setprop_cells(fdt, clint_name, "reg",
317
- 0x0, clint_addr, 0x0, memmap[VIRT_CLINT].size);
318
- qemu_fdt_setprop(fdt, clint_name, "interrupts-extended",
319
- clint_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 4);
320
- riscv_socket_fdt_write_id(mc, fdt, clint_name, socket);
321
- g_free(clint_name);
322
-
323
- plic_phandle[socket] = phandle++;
324
- plic_addr = memmap[VIRT_PLIC].base + (memmap[VIRT_PLIC].size * socket);
325
- plic_name = g_strdup_printf("/soc/plic@%lx", plic_addr);
326
- qemu_fdt_add_subnode(fdt, plic_name);
327
- qemu_fdt_setprop_cell(fdt, plic_name,
328
- "#address-cells", FDT_PLIC_ADDR_CELLS);
329
- qemu_fdt_setprop_cell(fdt, plic_name,
330
- "#interrupt-cells", FDT_PLIC_INT_CELLS);
331
- qemu_fdt_setprop_string_array(fdt, plic_name, "compatible",
332
- (char **)&plic_compat, ARRAY_SIZE(plic_compat));
333
- qemu_fdt_setprop(fdt, plic_name, "interrupt-controller", NULL, 0);
334
- qemu_fdt_setprop(fdt, plic_name, "interrupts-extended",
335
- plic_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 4);
336
- qemu_fdt_setprop_cells(fdt, plic_name, "reg",
337
- 0x0, plic_addr, 0x0, memmap[VIRT_PLIC].size);
338
- qemu_fdt_setprop_cell(fdt, plic_name, "riscv,ndev", VIRTIO_NDEV);
339
- riscv_socket_fdt_write_id(mc, fdt, plic_name, socket);
340
- qemu_fdt_setprop_cell(fdt, plic_name, "phandle", plic_phandle[socket]);
341
- g_free(plic_name);
342
-
343
- g_free(clint_cells);
344
- g_free(plic_cells);
345
+ create_fdt_socket_memory(s, memmap, socket);
346
+
347
+ create_fdt_socket_clint(s, memmap, socket, intc_phandles);
348
+
349
+ create_fdt_socket_plic(s, memmap, socket, phandle,
350
+ intc_phandles, xplic_phandles);
351
+
352
+ g_free(intc_phandles);
353
g_free(clust_name);
354
}
355
356
for (socket = 0; socket < riscv_socket_count(mc); socket++) {
357
if (socket == 0) {
358
- plic_mmio_phandle = plic_phandle[socket];
359
- plic_virtio_phandle = plic_phandle[socket];
360
- plic_pcie_phandle = plic_phandle[socket];
361
+ *irq_mmio_phandle = xplic_phandles[socket];
362
+ *irq_virtio_phandle = xplic_phandles[socket];
363
+ *irq_pcie_phandle = xplic_phandles[socket];
364
}
365
if (socket == 1) {
366
- plic_virtio_phandle = plic_phandle[socket];
367
- plic_pcie_phandle = plic_phandle[socket];
368
+ *irq_virtio_phandle = xplic_phandles[socket];
369
+ *irq_pcie_phandle = xplic_phandles[socket];
370
}
371
if (socket == 2) {
372
- plic_pcie_phandle = plic_phandle[socket];
373
+ *irq_pcie_phandle = xplic_phandles[socket];
374
}
375
}
376
377
- riscv_socket_fdt_write_distance_matrix(mc, fdt);
378
+ riscv_socket_fdt_write_distance_matrix(mc, mc->fdt);
379
+}
380
+
381
+static void create_fdt_virtio(RISCVVirtState *s, const MemMapEntry *memmap,
382
+ uint32_t irq_virtio_phandle)
383
+{
384
+ int i;
385
+ char *name;
386
+ MachineState *mc = MACHINE(s);
387
388
for (i = 0; i < VIRTIO_COUNT; i++) {
389
name = g_strdup_printf("/soc/virtio_mmio@%lx",
390
(long)(memmap[VIRT_VIRTIO].base + i * memmap[VIRT_VIRTIO].size));
391
- qemu_fdt_add_subnode(fdt, name);
392
- qemu_fdt_setprop_string(fdt, name, "compatible", "virtio,mmio");
393
- qemu_fdt_setprop_cells(fdt, name, "reg",
394
+ qemu_fdt_add_subnode(mc->fdt, name);
395
+ qemu_fdt_setprop_string(mc->fdt, name, "compatible", "virtio,mmio");
396
+ qemu_fdt_setprop_cells(mc->fdt, name, "reg",
397
0x0, memmap[VIRT_VIRTIO].base + i * memmap[VIRT_VIRTIO].size,
398
0x0, memmap[VIRT_VIRTIO].size);
399
- qemu_fdt_setprop_cell(fdt, name, "interrupt-parent",
400
- plic_virtio_phandle);
401
- qemu_fdt_setprop_cell(fdt, name, "interrupts", VIRTIO_IRQ + i);
402
+ qemu_fdt_setprop_cell(mc->fdt, name, "interrupt-parent",
403
+ irq_virtio_phandle);
404
+ qemu_fdt_setprop_cell(mc->fdt, name, "interrupts", VIRTIO_IRQ + i);
405
g_free(name);
406
}
407
+}
408
+
409
+static void create_fdt_pcie(RISCVVirtState *s, const MemMapEntry *memmap,
410
+ uint32_t irq_pcie_phandle)
411
+{
412
+ char *name;
413
+ MachineState *mc = MACHINE(s);
414
415
name = g_strdup_printf("/soc/pci@%lx",
416
(long) memmap[VIRT_PCIE_ECAM].base);
417
- qemu_fdt_add_subnode(fdt, name);
418
- qemu_fdt_setprop_cell(fdt, name, "#address-cells", FDT_PCI_ADDR_CELLS);
419
- qemu_fdt_setprop_cell(fdt, name, "#interrupt-cells", FDT_PCI_INT_CELLS);
420
- qemu_fdt_setprop_cell(fdt, name, "#size-cells", 0x2);
421
- qemu_fdt_setprop_string(fdt, name, "compatible", "pci-host-ecam-generic");
422
- qemu_fdt_setprop_string(fdt, name, "device_type", "pci");
423
- qemu_fdt_setprop_cell(fdt, name, "linux,pci-domain", 0);
424
- qemu_fdt_setprop_cells(fdt, name, "bus-range", 0,
425
+ qemu_fdt_add_subnode(mc->fdt, name);
426
+ qemu_fdt_setprop_cell(mc->fdt, name, "#address-cells",
427
+ FDT_PCI_ADDR_CELLS);
428
+ qemu_fdt_setprop_cell(mc->fdt, name, "#interrupt-cells",
429
+ FDT_PCI_INT_CELLS);
430
+ qemu_fdt_setprop_cell(mc->fdt, name, "#size-cells", 0x2);
431
+ qemu_fdt_setprop_string(mc->fdt, name, "compatible",
432
+ "pci-host-ecam-generic");
433
+ qemu_fdt_setprop_string(mc->fdt, name, "device_type", "pci");
434
+ qemu_fdt_setprop_cell(mc->fdt, name, "linux,pci-domain", 0);
435
+ qemu_fdt_setprop_cells(mc->fdt, name, "bus-range", 0,
436
memmap[VIRT_PCIE_ECAM].size / PCIE_MMCFG_SIZE_MIN - 1);
437
- qemu_fdt_setprop(fdt, name, "dma-coherent", NULL, 0);
438
- qemu_fdt_setprop_cells(fdt, name, "reg", 0,
439
+ qemu_fdt_setprop(mc->fdt, name, "dma-coherent", NULL, 0);
440
+ qemu_fdt_setprop_cells(mc->fdt, name, "reg", 0,
441
memmap[VIRT_PCIE_ECAM].base, 0, memmap[VIRT_PCIE_ECAM].size);
442
- qemu_fdt_setprop_sized_cells(fdt, name, "ranges",
443
+ qemu_fdt_setprop_sized_cells(mc->fdt, name, "ranges",
444
1, FDT_PCI_RANGE_IOPORT, 2, 0,
445
2, memmap[VIRT_PCIE_PIO].base, 2, memmap[VIRT_PCIE_PIO].size,
446
1, FDT_PCI_RANGE_MMIO,
447
@@ -XXX,XX +XXX,XX @@ static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap,
448
2, virt_high_pcie_memmap.base,
449
2, virt_high_pcie_memmap.base, 2, virt_high_pcie_memmap.size);
450
451
- create_pcie_irq_map(fdt, name, plic_pcie_phandle);
452
+ create_pcie_irq_map(mc->fdt, name, irq_pcie_phandle);
453
g_free(name);
454
+}
455
456
- test_phandle = phandle++;
457
+static void create_fdt_reset(RISCVVirtState *s, const MemMapEntry *memmap,
458
+ uint32_t *phandle)
459
+{
460
+ char *name;
461
+ uint32_t test_phandle;
462
+ MachineState *mc = MACHINE(s);
463
+
464
+ test_phandle = (*phandle)++;
465
name = g_strdup_printf("/soc/test@%lx",
466
(long)memmap[VIRT_TEST].base);
467
- qemu_fdt_add_subnode(fdt, name);
468
+ qemu_fdt_add_subnode(mc->fdt, name);
469
{
470
static const char * const compat[3] = {
471
"sifive,test1", "sifive,test0", "syscon"
472
};
473
- qemu_fdt_setprop_string_array(fdt, name, "compatible", (char **)&compat,
474
- ARRAY_SIZE(compat));
475
+ qemu_fdt_setprop_string_array(mc->fdt, name, "compatible",
476
+ (char **)&compat, ARRAY_SIZE(compat));
477
}
478
- qemu_fdt_setprop_cells(fdt, name, "reg",
479
- 0x0, memmap[VIRT_TEST].base,
480
- 0x0, memmap[VIRT_TEST].size);
481
- qemu_fdt_setprop_cell(fdt, name, "phandle", test_phandle);
482
- test_phandle = qemu_fdt_get_phandle(fdt, name);
483
+ qemu_fdt_setprop_cells(mc->fdt, name, "reg",
484
+ 0x0, memmap[VIRT_TEST].base, 0x0, memmap[VIRT_TEST].size);
485
+ qemu_fdt_setprop_cell(mc->fdt, name, "phandle", test_phandle);
486
+ test_phandle = qemu_fdt_get_phandle(mc->fdt, name);
487
g_free(name);
488
489
name = g_strdup_printf("/soc/reboot");
490
- qemu_fdt_add_subnode(fdt, name);
491
- qemu_fdt_setprop_string(fdt, name, "compatible", "syscon-reboot");
492
- qemu_fdt_setprop_cell(fdt, name, "regmap", test_phandle);
493
- qemu_fdt_setprop_cell(fdt, name, "offset", 0x0);
494
- qemu_fdt_setprop_cell(fdt, name, "value", FINISHER_RESET);
495
+ qemu_fdt_add_subnode(mc->fdt, name);
496
+ qemu_fdt_setprop_string(mc->fdt, name, "compatible", "syscon-reboot");
497
+ qemu_fdt_setprop_cell(mc->fdt, name, "regmap", test_phandle);
498
+ qemu_fdt_setprop_cell(mc->fdt, name, "offset", 0x0);
499
+ qemu_fdt_setprop_cell(mc->fdt, name, "value", FINISHER_RESET);
500
g_free(name);
501
502
name = g_strdup_printf("/soc/poweroff");
503
- qemu_fdt_add_subnode(fdt, name);
504
- qemu_fdt_setprop_string(fdt, name, "compatible", "syscon-poweroff");
505
- qemu_fdt_setprop_cell(fdt, name, "regmap", test_phandle);
506
- qemu_fdt_setprop_cell(fdt, name, "offset", 0x0);
507
- qemu_fdt_setprop_cell(fdt, name, "value", FINISHER_PASS);
508
+ qemu_fdt_add_subnode(mc->fdt, name);
509
+ qemu_fdt_setprop_string(mc->fdt, name, "compatible", "syscon-poweroff");
510
+ qemu_fdt_setprop_cell(mc->fdt, name, "regmap", test_phandle);
511
+ qemu_fdt_setprop_cell(mc->fdt, name, "offset", 0x0);
512
+ qemu_fdt_setprop_cell(mc->fdt, name, "value", FINISHER_PASS);
513
g_free(name);
514
+}
515
+
516
+static void create_fdt_uart(RISCVVirtState *s, const MemMapEntry *memmap,
517
+ uint32_t irq_mmio_phandle)
518
+{
519
+ char *name;
520
+ MachineState *mc = MACHINE(s);
521
522
name = g_strdup_printf("/soc/uart@%lx", (long)memmap[VIRT_UART0].base);
523
- qemu_fdt_add_subnode(fdt, name);
524
- qemu_fdt_setprop_string(fdt, name, "compatible", "ns16550a");
525
- qemu_fdt_setprop_cells(fdt, name, "reg",
526
+ qemu_fdt_add_subnode(mc->fdt, name);
527
+ qemu_fdt_setprop_string(mc->fdt, name, "compatible", "ns16550a");
528
+ qemu_fdt_setprop_cells(mc->fdt, name, "reg",
529
0x0, memmap[VIRT_UART0].base,
530
0x0, memmap[VIRT_UART0].size);
531
- qemu_fdt_setprop_cell(fdt, name, "clock-frequency", 3686400);
532
- qemu_fdt_setprop_cell(fdt, name, "interrupt-parent", plic_mmio_phandle);
533
- qemu_fdt_setprop_cell(fdt, name, "interrupts", UART0_IRQ);
534
+ qemu_fdt_setprop_cell(mc->fdt, name, "clock-frequency", 3686400);
535
+ qemu_fdt_setprop_cell(mc->fdt, name, "interrupt-parent", irq_mmio_phandle);
536
+ qemu_fdt_setprop_cell(mc->fdt, name, "interrupts", UART0_IRQ);
537
538
- qemu_fdt_add_subnode(fdt, "/chosen");
539
- qemu_fdt_setprop_string(fdt, "/chosen", "stdout-path", name);
540
+ qemu_fdt_add_subnode(mc->fdt, "/chosen");
541
+ qemu_fdt_setprop_string(mc->fdt, "/chosen", "stdout-path", name);
542
g_free(name);
543
+}
544
+
545
+static void create_fdt_rtc(RISCVVirtState *s, const MemMapEntry *memmap,
546
+ uint32_t irq_mmio_phandle)
547
+{
548
+ char *name;
549
+ MachineState *mc = MACHINE(s);
550
551
name = g_strdup_printf("/soc/rtc@%lx", (long)memmap[VIRT_RTC].base);
552
- qemu_fdt_add_subnode(fdt, name);
553
- qemu_fdt_setprop_string(fdt, name, "compatible", "google,goldfish-rtc");
554
- qemu_fdt_setprop_cells(fdt, name, "reg",
555
- 0x0, memmap[VIRT_RTC].base,
556
- 0x0, memmap[VIRT_RTC].size);
557
- qemu_fdt_setprop_cell(fdt, name, "interrupt-parent", plic_mmio_phandle);
558
- qemu_fdt_setprop_cell(fdt, name, "interrupts", RTC_IRQ);
559
+ qemu_fdt_add_subnode(mc->fdt, name);
560
+ qemu_fdt_setprop_string(mc->fdt, name, "compatible",
561
+ "google,goldfish-rtc");
562
+ qemu_fdt_setprop_cells(mc->fdt, name, "reg",
563
+ 0x0, memmap[VIRT_RTC].base, 0x0, memmap[VIRT_RTC].size);
564
+ qemu_fdt_setprop_cell(mc->fdt, name, "interrupt-parent",
565
+ irq_mmio_phandle);
566
+ qemu_fdt_setprop_cell(mc->fdt, name, "interrupts", RTC_IRQ);
567
g_free(name);
568
+}
569
+
570
+static void create_fdt_flash(RISCVVirtState *s, const MemMapEntry *memmap)
571
+{
572
+ char *name;
573
+ MachineState *mc = MACHINE(s);
574
+ hwaddr flashsize = virt_memmap[VIRT_FLASH].size / 2;
575
+ hwaddr flashbase = virt_memmap[VIRT_FLASH].base;
576
577
name = g_strdup_printf("/flash@%" PRIx64, flashbase);
578
qemu_fdt_add_subnode(mc->fdt, name);
579
@@ -XXX,XX +XXX,XX @@ static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap,
580
2, flashbase + flashsize, 2, flashsize);
581
qemu_fdt_setprop_cell(mc->fdt, name, "bank-width", 4);
582
g_free(name);
583
+}
584
+
585
+static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap,
586
+ uint64_t mem_size, const char *cmdline, bool is_32_bit)
587
+{
588
+ MachineState *mc = MACHINE(s);
589
+ uint32_t phandle = 1, irq_mmio_phandle = 1;
590
+ uint32_t irq_pcie_phandle = 1, irq_virtio_phandle = 1;
591
+
592
+ if (mc->dtb) {
593
+ mc->fdt = load_device_tree(mc->dtb, &s->fdt_size);
594
+ if (!mc->fdt) {
595
+ error_report("load_device_tree() failed");
596
+ exit(1);
597
+ }
598
+ goto update_bootargs;
599
+ } else {
600
+ mc->fdt = create_device_tree(&s->fdt_size);
601
+ if (!mc->fdt) {
602
+ error_report("create_device_tree() failed");
603
+ exit(1);
604
+ }
605
+ }
606
+
607
+ qemu_fdt_setprop_string(mc->fdt, "/", "model", "riscv-virtio,qemu");
608
+ qemu_fdt_setprop_string(mc->fdt, "/", "compatible", "riscv-virtio");
609
+ qemu_fdt_setprop_cell(mc->fdt, "/", "#size-cells", 0x2);
610
+ qemu_fdt_setprop_cell(mc->fdt, "/", "#address-cells", 0x2);
611
+
612
+ qemu_fdt_add_subnode(mc->fdt, "/soc");
613
+ qemu_fdt_setprop(mc->fdt, "/soc", "ranges", NULL, 0);
614
+ qemu_fdt_setprop_string(mc->fdt, "/soc", "compatible", "simple-bus");
615
+ qemu_fdt_setprop_cell(mc->fdt, "/soc", "#size-cells", 0x2);
616
+ qemu_fdt_setprop_cell(mc->fdt, "/soc", "#address-cells", 0x2);
617
+
618
+ create_fdt_sockets(s, memmap, is_32_bit, &phandle,
619
+ &irq_mmio_phandle, &irq_pcie_phandle, &irq_virtio_phandle);
620
+
621
+ create_fdt_virtio(s, memmap, irq_virtio_phandle);
622
+
623
+ create_fdt_pcie(s, memmap, irq_pcie_phandle);
624
+
625
+ create_fdt_reset(s, memmap, &phandle);
626
+
627
+ create_fdt_uart(s, memmap, irq_mmio_phandle);
628
+
629
+ create_fdt_rtc(s, memmap, irq_mmio_phandle);
630
+
631
+ create_fdt_flash(s, memmap);
632
633
update_bootargs:
634
if (cmdline) {
635
- qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline);
636
+ qemu_fdt_setprop_string(mc->fdt, "/chosen", "bootargs", cmdline);
26
}
637
}
27
}
638
}
28
639
29
--
640
--
30
2.45.1
641
2.31.1
642
643
diff view generated by jsdifflib
1
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
1
From: Anup Patel <anup.patel@wdc.com>
2
2
3
SBI defines a Debug Console extension "DBCN" that will, in time, replace
3
We extend virt machine to emulate ACLINT devices only when "aclint=on"
4
the legacy console putchar and getchar SBI extensions.
4
parameter is passed along with machine name in QEMU command-line.
5
5
6
The appeal of the DBCN extension is that it allows multiple bytes to be
6
Signed-off-by: Anup Patel <anup.patel@wdc.com>
7
read/written in the SBI console in a single SBI call.
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
8
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
9
As far as KVM goes, the DBCN calls are forwarded by an in-kernel KVM
9
Message-id: 20210831110603.338681-5-anup.patel@wdc.com
10
module to userspace. But this will only happens if the KVM module
11
actually supports this SBI extension and we activate it.
12
13
We'll check for DBCN support during init time, checking if get-reg-list
14
is advertising KVM_RISCV_SBI_EXT_DBCN. In that case, we'll enable it via
15
kvm_set_one_reg() during kvm_arch_init_vcpu().
16
17
Finally, change kvm_riscv_handle_sbi() to handle the incoming calls for
18
SBI_EXT_DBCN, reading and writing as required.
19
20
A simple KVM guest with 'earlycon=sbi', running in an emulated RISC-V
21
host, takes around 20 seconds to boot without using DBCN. With this
22
patch we're taking around 14 seconds to boot due to the speed-up in the
23
terminal output. There's no change in boot time if the guest isn't
24
using earlycon.
25
26
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
27
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
28
Message-ID: <20240425155012.581366-1-dbarboza@ventanamicro.com>
29
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
30
---
11
---
31
target/riscv/sbi_ecall_interface.h | 17 +++++
12
docs/system/riscv/virt.rst | 10 ++++
32
target/riscv/kvm/kvm-cpu.c | 111 +++++++++++++++++++++++++++++
13
include/hw/riscv/virt.h | 2 +
33
2 files changed, 128 insertions(+)
14
hw/riscv/virt.c | 113 ++++++++++++++++++++++++++++++++++++-
34
15
3 files changed, 124 insertions(+), 1 deletion(-)
35
diff --git a/target/riscv/sbi_ecall_interface.h b/target/riscv/sbi_ecall_interface.h
16
17
diff --git a/docs/system/riscv/virt.rst b/docs/system/riscv/virt.rst
36
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
37
--- a/target/riscv/sbi_ecall_interface.h
19
--- a/docs/system/riscv/virt.rst
38
+++ b/target/riscv/sbi_ecall_interface.h
20
+++ b/docs/system/riscv/virt.rst
39
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@ with the default OpenSBI firmware image as the -bios. It also supports
40
22
the recommended RISC-V bootflow: U-Boot SPL (M-mode) loads OpenSBI fw_dynamic
41
/* clang-format off */
23
firmware and U-Boot proper (S-mode), using the standard -bios functionality.
42
24
43
+#define SBI_SUCCESS 0
25
+Machine-specific options
44
+#define SBI_ERR_FAILED -1
26
+------------------------
45
+#define SBI_ERR_NOT_SUPPORTED -2
27
+
46
+#define SBI_ERR_INVALID_PARAM -3
28
+The following machine-specific options are supported:
47
+#define SBI_ERR_DENIED -4
29
+
48
+#define SBI_ERR_INVALID_ADDRESS -5
30
+- aclint=[on|off]
49
+#define SBI_ERR_ALREADY_AVAILABLE -6
31
+
50
+#define SBI_ERR_ALREADY_STARTED -7
32
+ When this option is "on", ACLINT devices will be emulated instead of
51
+#define SBI_ERR_ALREADY_STOPPED -8
33
+ SiFive CLINT. When not specified, this option is assumed to be "off".
52
+#define SBI_ERR_NO_SHMEM -9
34
+
53
+
35
Running Linux kernel
54
/* SBI Extension IDs */
36
--------------------
55
#define SBI_EXT_0_1_SET_TIMER 0x0
37
56
#define SBI_EXT_0_1_CONSOLE_PUTCHAR 0x1
38
diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
57
@@ -XXX,XX +XXX,XX @@
58
#define SBI_EXT_IPI 0x735049
59
#define SBI_EXT_RFENCE 0x52464E43
60
#define SBI_EXT_HSM 0x48534D
61
+#define SBI_EXT_DBCN 0x4442434E
62
63
/* SBI function IDs for BASE extension */
64
#define SBI_EXT_BASE_GET_SPEC_VERSION 0x0
65
@@ -XXX,XX +XXX,XX @@
66
#define SBI_EXT_HSM_HART_STOP 0x1
67
#define SBI_EXT_HSM_HART_GET_STATUS 0x2
68
69
+/* SBI function IDs for DBCN extension */
70
+#define SBI_EXT_DBCN_CONSOLE_WRITE 0x0
71
+#define SBI_EXT_DBCN_CONSOLE_READ 0x1
72
+#define SBI_EXT_DBCN_CONSOLE_WRITE_BYTE 0x2
73
+
74
#define SBI_HSM_HART_STATUS_STARTED 0x0
75
#define SBI_HSM_HART_STATUS_STOPPED 0x1
76
#define SBI_HSM_HART_STATUS_START_PENDING 0x2
77
diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
78
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
79
--- a/target/riscv/kvm/kvm-cpu.c
40
--- a/include/hw/riscv/virt.h
80
+++ b/target/riscv/kvm/kvm-cpu.c
41
+++ b/include/hw/riscv/virt.h
81
@@ -XXX,XX +XXX,XX @@ static KVMCPUConfig kvm_v_vlenb = {
42
@@ -XXX,XX +XXX,XX @@ struct RISCVVirtState {
82
KVM_REG_RISCV_VECTOR_CSR_REG(vlenb)
43
FWCfgState *fw_cfg;
44
45
int fdt_size;
46
+ bool have_aclint;
83
};
47
};
84
48
85
+static KVMCPUConfig kvm_sbi_dbcn = {
49
enum {
86
+ .name = "sbi_dbcn",
50
@@ -XXX,XX +XXX,XX @@ enum {
87
+ .kvm_reg_id = KVM_REG_RISCV | KVM_REG_SIZE_U64 |
51
VIRT_TEST,
88
+ KVM_REG_RISCV_SBI_EXT | KVM_RISCV_SBI_EXT_DBCN
52
VIRT_RTC,
89
+};
53
VIRT_CLINT,
90
+
54
+ VIRT_ACLINT_SSWI,
91
static void kvm_riscv_update_cpu_cfg_isa_ext(RISCVCPU *cpu, CPUState *cs)
55
VIRT_PLIC,
56
VIRT_UART0,
57
VIRT_VIRTIO,
58
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
59
index XXXXXXX..XXXXXXX 100644
60
--- a/hw/riscv/virt.c
61
+++ b/hw/riscv/virt.c
62
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry virt_memmap[] = {
63
[VIRT_TEST] = { 0x100000, 0x1000 },
64
[VIRT_RTC] = { 0x101000, 0x1000 },
65
[VIRT_CLINT] = { 0x2000000, 0x10000 },
66
+ [VIRT_ACLINT_SSWI] = { 0x2F00000, 0x4000 },
67
[VIRT_PCIE_PIO] = { 0x3000000, 0x10000 },
68
[VIRT_PLIC] = { 0xc000000, VIRT_PLIC_SIZE(VIRT_CPUS_MAX * 2) },
69
[VIRT_UART0] = { 0x10000000, 0x100 },
70
@@ -XXX,XX +XXX,XX @@ static void create_fdt_socket_clint(RISCVVirtState *s,
71
g_free(clint_cells);
72
}
73
74
+static void create_fdt_socket_aclint(RISCVVirtState *s,
75
+ const MemMapEntry *memmap, int socket,
76
+ uint32_t *intc_phandles)
77
+{
78
+ int cpu;
79
+ char *name;
80
+ unsigned long addr;
81
+ uint32_t aclint_cells_size;
82
+ uint32_t *aclint_mswi_cells;
83
+ uint32_t *aclint_sswi_cells;
84
+ uint32_t *aclint_mtimer_cells;
85
+ MachineState *mc = MACHINE(s);
86
+
87
+ aclint_mswi_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2);
88
+ aclint_mtimer_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2);
89
+ aclint_sswi_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2);
90
+
91
+ for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) {
92
+ aclint_mswi_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
93
+ aclint_mswi_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_M_SOFT);
94
+ aclint_mtimer_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
95
+ aclint_mtimer_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_M_TIMER);
96
+ aclint_sswi_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
97
+ aclint_sswi_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_S_SOFT);
98
+ }
99
+ aclint_cells_size = s->soc[socket].num_harts * sizeof(uint32_t) * 2;
100
+
101
+ addr = memmap[VIRT_CLINT].base + (memmap[VIRT_CLINT].size * socket);
102
+ name = g_strdup_printf("/soc/mswi@%lx", addr);
103
+ qemu_fdt_add_subnode(mc->fdt, name);
104
+ qemu_fdt_setprop_string(mc->fdt, name, "compatible", "riscv,aclint-mswi");
105
+ qemu_fdt_setprop_cells(mc->fdt, name, "reg",
106
+ 0x0, addr, 0x0, RISCV_ACLINT_SWI_SIZE);
107
+ qemu_fdt_setprop(mc->fdt, name, "interrupts-extended",
108
+ aclint_mswi_cells, aclint_cells_size);
109
+ qemu_fdt_setprop(mc->fdt, name, "interrupt-controller", NULL, 0);
110
+ qemu_fdt_setprop_cell(mc->fdt, name, "#interrupt-cells", 0);
111
+ riscv_socket_fdt_write_id(mc, mc->fdt, name, socket);
112
+ g_free(name);
113
+
114
+ addr = memmap[VIRT_CLINT].base + RISCV_ACLINT_SWI_SIZE +
115
+ (memmap[VIRT_CLINT].size * socket);
116
+ name = g_strdup_printf("/soc/mtimer@%lx", addr);
117
+ qemu_fdt_add_subnode(mc->fdt, name);
118
+ qemu_fdt_setprop_string(mc->fdt, name, "compatible",
119
+ "riscv,aclint-mtimer");
120
+ qemu_fdt_setprop_cells(mc->fdt, name, "reg",
121
+ 0x0, addr + RISCV_ACLINT_DEFAULT_MTIME,
122
+ 0x0, memmap[VIRT_CLINT].size - RISCV_ACLINT_SWI_SIZE -
123
+ RISCV_ACLINT_DEFAULT_MTIME,
124
+ 0x0, addr + RISCV_ACLINT_DEFAULT_MTIMECMP,
125
+ 0x0, RISCV_ACLINT_DEFAULT_MTIME);
126
+ qemu_fdt_setprop(mc->fdt, name, "interrupts-extended",
127
+ aclint_mtimer_cells, aclint_cells_size);
128
+ riscv_socket_fdt_write_id(mc, mc->fdt, name, socket);
129
+ g_free(name);
130
+
131
+ addr = memmap[VIRT_ACLINT_SSWI].base +
132
+ (memmap[VIRT_ACLINT_SSWI].size * socket);
133
+ name = g_strdup_printf("/soc/sswi@%lx", addr);
134
+ qemu_fdt_add_subnode(mc->fdt, name);
135
+ qemu_fdt_setprop_string(mc->fdt, name, "compatible", "riscv,aclint-sswi");
136
+ qemu_fdt_setprop_cells(mc->fdt, name, "reg",
137
+ 0x0, addr, 0x0, memmap[VIRT_ACLINT_SSWI].size);
138
+ qemu_fdt_setprop(mc->fdt, name, "interrupts-extended",
139
+ aclint_sswi_cells, aclint_cells_size);
140
+ qemu_fdt_setprop(mc->fdt, name, "interrupt-controller", NULL, 0);
141
+ qemu_fdt_setprop_cell(mc->fdt, name, "#interrupt-cells", 0);
142
+ riscv_socket_fdt_write_id(mc, mc->fdt, name, socket);
143
+ g_free(name);
144
+
145
+ g_free(aclint_mswi_cells);
146
+ g_free(aclint_mtimer_cells);
147
+ g_free(aclint_sswi_cells);
148
+}
149
+
150
static void create_fdt_socket_plic(RISCVVirtState *s,
151
const MemMapEntry *memmap, int socket,
152
uint32_t *phandle, uint32_t *intc_phandles,
153
@@ -XXX,XX +XXX,XX @@ static void create_fdt_sockets(RISCVVirtState *s, const MemMapEntry *memmap,
154
155
create_fdt_socket_memory(s, memmap, socket);
156
157
- create_fdt_socket_clint(s, memmap, socket, intc_phandles);
158
+ if (s->have_aclint) {
159
+ create_fdt_socket_aclint(s, memmap, socket, intc_phandles);
160
+ } else {
161
+ create_fdt_socket_clint(s, memmap, socket, intc_phandles);
162
+ }
163
164
create_fdt_socket_plic(s, memmap, socket, phandle,
165
intc_phandles, xplic_phandles);
166
@@ -XXX,XX +XXX,XX @@ static void virt_machine_init(MachineState *machine)
167
RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME,
168
RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ, true);
169
170
+ /* Per-socket ACLINT SSWI */
171
+ if (s->have_aclint) {
172
+ riscv_aclint_swi_create(
173
+ memmap[VIRT_ACLINT_SSWI].base +
174
+ i * memmap[VIRT_ACLINT_SSWI].size,
175
+ base_hartid, hart_count, true);
176
+ }
177
+
178
/* Per-socket PLIC hart topology configuration string */
179
plic_hart_config = plic_hart_config_string(hart_count);
180
181
@@ -XXX,XX +XXX,XX @@ static void virt_machine_instance_init(Object *obj)
92
{
182
{
93
CPURISCVState *env = &cpu->env;
94
@@ -XXX,XX +XXX,XX @@ static int uint64_cmp(const void *a, const void *b)
95
return 0;
96
}
183
}
97
184
98
+static void kvm_riscv_check_sbi_dbcn_support(RISCVCPU *cpu,
185
+static bool virt_get_aclint(Object *obj, Error **errp)
99
+ KVMScratchCPU *kvmcpu,
100
+ struct kvm_reg_list *reglist)
101
+{
186
+{
102
+ struct kvm_reg_list *reg_search;
187
+ MachineState *ms = MACHINE(obj);
103
+
188
+ RISCVVirtState *s = RISCV_VIRT_MACHINE(ms);
104
+ reg_search = bsearch(&kvm_sbi_dbcn.kvm_reg_id, reglist->reg, reglist->n,
189
+
105
+ sizeof(uint64_t), uint64_cmp);
190
+ return s->have_aclint;
106
+
107
+ if (reg_search) {
108
+ kvm_sbi_dbcn.supported = true;
109
+ }
110
+}
191
+}
111
+
192
+
112
static void kvm_riscv_read_vlenb(RISCVCPU *cpu, KVMScratchCPU *kvmcpu,
193
+static void virt_set_aclint(Object *obj, bool value, Error **errp)
113
struct kvm_reg_list *reglist)
194
+{
195
+ MachineState *ms = MACHINE(obj);
196
+ RISCVVirtState *s = RISCV_VIRT_MACHINE(ms);
197
+
198
+ s->have_aclint = value;
199
+}
200
+
201
static void virt_machine_class_init(ObjectClass *oc, void *data)
114
{
202
{
115
@@ -XXX,XX +XXX,XX @@ static void kvm_riscv_init_multiext_cfg(RISCVCPU *cpu, KVMScratchCPU *kvmcpu)
203
MachineClass *mc = MACHINE_CLASS(oc);
116
if (riscv_has_ext(&cpu->env, RVV)) {
204
@@ -XXX,XX +XXX,XX @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
117
kvm_riscv_read_vlenb(cpu, kvmcpu, reglist);
205
mc->numa_mem_supported = true;
118
}
206
119
+
207
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
120
+ kvm_riscv_check_sbi_dbcn_support(cpu, kvmcpu, reglist);
208
+
209
+ object_class_property_add_bool(oc, "aclint", virt_get_aclint,
210
+ virt_set_aclint);
211
+ object_class_property_set_description(oc, "aclint",
212
+ "Set on/off to enable/disable "
213
+ "emulating ACLINT devices");
121
}
214
}
122
215
123
static void riscv_init_kvm_registers(Object *cpu_obj)
216
static const TypeInfo virt_machine_typeinfo = {
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)
129
+{
130
+ target_ulong reg = 1;
131
+
132
+ if (!kvm_sbi_dbcn.supported) {
133
+ return 0;
134
+ }
135
+
136
+ return kvm_set_one_reg(cs, kvm_sbi_dbcn.kvm_reg_id, &reg);
137
+}
138
+
139
int kvm_arch_init_vcpu(CPUState *cs)
140
{
141
int ret = 0;
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)
156
+{
157
+ g_autofree uint8_t *buf = NULL;
158
+ RISCVCPU *cpu = RISCV_CPU(cs);
159
+ target_ulong num_bytes;
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;
225
+ }
226
+}
227
+
228
static int kvm_riscv_handle_sbi(CPUState *cs, struct kvm_run *run)
229
{
230
int ret = 0;
231
@@ -XXX,XX +XXX,XX @@ static int kvm_riscv_handle_sbi(CPUState *cs, struct kvm_run *run)
232
}
233
ret = 0;
234
break;
235
+ case SBI_EXT_DBCN:
236
+ kvm_riscv_handle_sbi_dbcn(cs, run);
237
+ break;
238
default:
239
qemu_log_mask(LOG_UNIMP,
240
"%s: un-handled SBI EXIT, specific reasons is %lu\n",
241
--
217
--
242
2.45.1
218
2.31.1
219
220
diff view generated by jsdifflib
1
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
1
From: Frank Chang <frank.chang@sifive.com>
2
2
3
Commit 33a24910ae changed 'reg_width' to use 'vlenb', i.e. vector length
3
Setting Control.claim clears all of the chanel's Next registers.
4
in bytes, when in this context we want 'reg_width' as the length in
4
This is effective only when Control.claim is set from 0 to 1.
5
bits.
6
5
7
Fix 'reg_width' back to the value in bits like 7cb59921c05a
6
Signed-off-by: Frank Chang <frank.chang@sifive.com>
8
("target/riscv/gdbstub.c: use 'vlenb' instead of shifting 'vlen'") set
7
Tested-by: Max Hsu <max.hsu@sifive.com>
9
beforehand.
8
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
10
9
Tested-by: Bin Meng <bmeng.cn@gmail.com>
11
While we're at it, rename 'reg_width' to 'bitsize' to provide a bit more
10
Message-id: 20210912130553.179501-2-frank.chang@sifive.com
12
clarity about what the variable represents. 'bitsize' is also used in
13
riscv_gen_dynamic_csr_feature() with the same purpose, i.e. as an input to
14
gdb_feature_builder_append_reg().
15
16
Cc: Akihiko Odaki <akihiko.odaki@daynix.com>
17
Cc: Alex Bennée <alex.bennee@linaro.org>
18
Reported-by: Robin Dapp <rdapp.gcc@gmail.com>
19
Fixes: 33a24910ae ("target/riscv: Use GDBFeature for dynamic XML")
20
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
21
Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
22
Acked-by: Alex Bennée <alex.bennee@linaro.org>
23
Reviewed-by: Akihiko Odaki <akihiko.odaki@daynix.com>
24
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
25
Cc: qemu-stable <qemu-stable@nongnu.org>
26
Message-ID: <20240517203054.880861-2-dbarboza@ventanamicro.com>
27
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
28
---
12
---
29
target/riscv/gdbstub.c | 6 +++---
13
hw/dma/sifive_pdma.c | 19 +++++++++++++++++++
30
1 file changed, 3 insertions(+), 3 deletions(-)
14
1 file changed, 19 insertions(+)
31
15
32
diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
16
diff --git a/hw/dma/sifive_pdma.c b/hw/dma/sifive_pdma.c
33
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
34
--- a/target/riscv/gdbstub.c
18
--- a/hw/dma/sifive_pdma.c
35
+++ b/target/riscv/gdbstub.c
19
+++ b/hw/dma/sifive_pdma.c
36
@@ -XXX,XX +XXX,XX @@ static GDBFeature *riscv_gen_dynamic_csr_feature(CPUState *cs, int base_reg)
20
@@ -XXX,XX +XXX,XX @@
37
static GDBFeature *ricsv_gen_dynamic_vector_feature(CPUState *cs, int base_reg)
21
#define DMA_EXEC_DST 0x110
22
#define DMA_EXEC_SRC 0x118
23
24
+/*
25
+ * FU540/FU740 docs are incorrect with NextConfig.wsize/rsize reset values.
26
+ * The reset values tested on Unleashed/Unmatched boards are 6 instead of 0.
27
+ */
28
+#define CONFIG_WRSZ_DEFAULT 6
29
+#define CONFIG_RDSZ_DEFAULT 6
30
+
31
enum dma_chan_state {
32
DMA_CHAN_STATE_IDLE,
33
DMA_CHAN_STATE_STARTED,
34
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_write(void *opaque, hwaddr offset,
38
{
35
{
39
RISCVCPU *cpu = RISCV_CPU(cs);
36
SiFivePDMAState *s = opaque;
40
- int reg_width = cpu->cfg.vlenb;
37
int ch = SIFIVE_PDMA_CHAN_NO(offset);
41
+ int bitsize = cpu->cfg.vlenb << 3;
38
+ bool claimed;
42
GDBFeatureBuilder builder;
39
43
int i;
40
if (ch >= SIFIVE_PDMA_CHANS) {
44
41
qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid channel no %d\n",
45
@@ -XXX,XX +XXX,XX @@ static GDBFeature *ricsv_gen_dynamic_vector_feature(CPUState *cs, int base_reg)
42
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_write(void *opaque, hwaddr offset,
46
43
offset &= 0xfff;
47
/* First define types and totals in a whole VL */
44
switch (offset) {
48
for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
45
case DMA_CONTROL:
49
- int count = reg_width / vec_lanes[i].size;
46
+ claimed = !!s->chan[ch].control & CONTROL_CLAIM;
50
+ int count = bitsize / vec_lanes[i].size;
47
+
51
gdb_feature_builder_append_tag(
48
+ if (!claimed && (value & CONTROL_CLAIM)) {
52
&builder, "<vector id=\"%s\" type=\"%s\" count=\"%d\"/>",
49
+ /* reset Next* registers */
53
vec_lanes[i].id, vec_lanes[i].gdb_type, count);
50
+ s->chan[ch].next_config = (CONFIG_RDSZ_DEFAULT << CONFIG_RDSZ_SHIFT) |
54
@@ -XXX,XX +XXX,XX @@ static GDBFeature *ricsv_gen_dynamic_vector_feature(CPUState *cs, int base_reg)
51
+ (CONFIG_WRSZ_DEFAULT << CONFIG_WRSZ_SHIFT);
55
/* Define vector registers */
52
+ s->chan[ch].next_bytes = 0;
56
for (i = 0; i < 32; i++) {
53
+ s->chan[ch].next_dst = 0;
57
gdb_feature_builder_append_reg(&builder, g_strdup_printf("v%d", i),
54
+ s->chan[ch].next_src = 0;
58
- reg_width, i, "riscv_vector", "vector");
55
+ }
59
+ bitsize, i, "riscv_vector", "vector");
56
+
60
}
57
s->chan[ch].control = value;
61
58
62
gdb_feature_builder_end(&builder);
59
if (value & CONTROL_RUN) {
63
--
60
--
64
2.45.1
61
2.31.1
65
62
66
63
diff view generated by jsdifflib
1
From: Max Chou <max.chou@sifive.com>
1
From: Frank Chang <frank.chang@sifive.com>
2
2
3
The require_scale_rvf function only checks the double width operator for
3
Real PDMA must have Control.claim bit to be set before
4
the vector floating point widen instructions, so most of the widen
4
Control.run bit is set to start any DMA transactions.
5
checking functions need to add require_rvf for single width operator.
5
Otherwise nothing will be transferred.
6
6
7
The vfwcvt.f.x.v and vfwcvt.f.xu.v instructions convert single width
7
The following result is PDMA tested in U-Boot on Unmatched board:
8
integer to double width float, so the opfxv_widen_check function doesn’t
9
need require_rvf for the single width operator(integer).
10
8
11
Signed-off-by: Max Chou <max.chou@sifive.com>
9
=> mw.l 0x3000000 0x0 <= Disclaim channel 0
12
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
10
(Channel 0 is not claimed)
13
Cc: qemu-stable <qemu-stable@nongnu.org>
11
=> mw.l 0x3000004 0x55000000 <= wsize = rsize = 5 (2^5 = 32 bytes)
14
Message-ID: <20240322092600.1198921-3-max.chou@sifive.com>
12
=> mw.q 0x3000008 0x2 <= NextBytes = 2
13
=> mw.q 0x3000010 0x84000000 <= NextDestination = 0x84000000
14
=> mw.q 0x3000018 0x84001000 <= NextSource = 0x84001000
15
=> mw.l 0x84000000 0x87654321 <= Fill test data to dst
16
=> mw.l 0x84001000 0x12345678 <= Fill test data to src
17
=> md.l 0x84000000 1; md.l 0x84001000 1 <= Dump src/dst memory contents
18
84000000: 87654321 !Ce.
19
84001000: 12345678 xV4.
20
=> md.l 0x3000000 8 <= Dump PDMA status
21
03000000: 00000000 55000000 00000002 00000000 .......U........
22
03000010: 84000000 00000000 84001000 00000000 ................
23
=> mw.l 0x3000000 0x3 <= Set channel 0 run and claim bits
24
=> md.l 0x3000000 8 <= Dump PDMA status
25
03000000: 00000001 66000000 00000000 00000000 .......f........
26
03000010: 00000000 00000000 00000000 00000000 ................
27
=> md.l 0x84000000 1; md.l 0x84001000 1 <= Dump src/dst memory contents
28
84000000: 87654321 !Ce.
29
84001000: 12345678 xV4.
30
31
Signed-off-by: Frank Chang <frank.chang@sifive.com>
32
Tested-by: Max Hsu <max.hsu@sifive.com>
33
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
34
Tested-by: Bin Meng <bmeng.cn@gmail.com>
35
Message-id: 20210912130553.179501-3-frank.chang@sifive.com
15
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
36
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
16
---
37
---
17
target/riscv/insn_trans/trans_rvv.c.inc | 5 +++++
38
hw/dma/sifive_pdma.c | 9 +++++++++
18
1 file changed, 5 insertions(+)
39
1 file changed, 9 insertions(+)
19
40
20
diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc
41
diff --git a/hw/dma/sifive_pdma.c b/hw/dma/sifive_pdma.c
21
index XXXXXXX..XXXXXXX 100644
42
index XXXXXXX..XXXXXXX 100644
22
--- a/target/riscv/insn_trans/trans_rvv.c.inc
43
--- a/hw/dma/sifive_pdma.c
23
+++ b/target/riscv/insn_trans/trans_rvv.c.inc
44
+++ b/hw/dma/sifive_pdma.c
24
@@ -XXX,XX +XXX,XX @@ GEN_OPFVF_TRANS(vfrsub_vf, opfvf_check)
45
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_write(void *opaque, hwaddr offset,
25
static bool opfvv_widen_check(DisasContext *s, arg_rmrr *a)
46
26
{
47
s->chan[ch].control = value;
27
return require_rvv(s) &&
48
28
+ require_rvf(s) &&
49
+ /*
29
require_scale_rvf(s) &&
50
+ * If channel was not claimed before run bit is set,
30
(s->sew != MO_8) &&
51
+ * DMA won't run.
31
vext_check_isa_ill(s) &&
52
+ */
32
@@ -XXX,XX +XXX,XX @@ GEN_OPFVV_WIDEN_TRANS(vfwsub_vv, opfvv_widen_check)
53
+ if (!claimed) {
33
static bool opfvf_widen_check(DisasContext *s, arg_rmrr *a)
54
+ s->chan[ch].control &= ~CONTROL_RUN;
34
{
55
+ return;
35
return require_rvv(s) &&
56
+ }
36
+ require_rvf(s) &&
57
+
37
require_scale_rvf(s) &&
58
if (value & CONTROL_RUN) {
38
(s->sew != MO_8) &&
59
sifive_pdma_run(s, ch);
39
vext_check_isa_ill(s) &&
60
}
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
}
64
--
61
--
65
2.45.1
62
2.31.1
66
63
67
64
diff view generated by jsdifflib
1
From: Yu-Ming Chang <yumin686@andestech.com>
1
From: Green Wan <green.wan@sifive.com>
2
2
3
Both CSRRS and CSRRC always read the addressed CSR and cause any read side
3
Real PDMA is able to deal with non-multiple transaction size transactions.
4
effects regardless of rs1 and rd fields. Note that if rs1 specifies a register
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.
7
4
8
So if CSRRS or CSRRC tries to write a read-only CSR with rs1 which specifies
5
The following result is PDMA tested in U-Boot on Unmatched board:
9
a register holding a zero value, an illegal instruction exception should be
10
raised.
11
6
12
Signed-off-by: Yu-Ming Chang <yumin686@andestech.com>
7
=> mw.l 0x3000000 0x0 <= Disclaim channel 0
13
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
=> mw.l 0x3000000 0x1 <= Claim channel 0
14
Message-ID: <20240403070823.80897-1-yumin686@andestech.com>
9
=> mw.l 0x3000004 0x11000000 <= wsize = rsize = 1 (2^1 = 2 bytes)
10
=> mw.q 0x3000008 0x3 <= NextBytes = 3
11
=> mw.q 0x3000010 0x84000000 <= NextDestination = 0x84000000
12
=> mw.q 0x3000018 0x84001000 <= NextSource = 0x84001000
13
=> mw.l 0x84000000 0x87654321 <= Fill test data to dst
14
=> mw.l 0x84001000 0x12345678 <= Fill test data to src
15
=> md.l 0x84000000 1; md.l 0x84001000 1 <= Dump src/dst memory contents
16
84000000: 87654321 !Ce.
17
84001000: 12345678 xV4.
18
=> md.l 0x3000000 8 <= Dump PDMA status
19
03000000: 00000001 11000000 00000003 00000000 ................
20
03000010: 84000000 00000000 84001000 00000000 ................
21
=> mw.l 0x3000000 0x3 <= Set channel 0 run and claim bits
22
=> md.l 0x3000000 8 <= Dump PDMA status
23
03000000: 40000001 11000000 00000003 00000000 ...@............
24
03000010: 84000000 00000000 84001000 00000000 ................
25
=> md.l 0x84000000 1; md.l 0x84001000 1 <= Dump src/dst memory contents
26
84000000: 87345678 xV4.
27
84001000: 12345678 xV4.
28
29
Signed-off-by: Green Wan <green.wan@sifive.com>
30
Reviewed-by: Frank Chang <frank.chang@sifive.com>
31
Tested-by: Max Hsu <max.hsu@sifive.com>
32
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
33
Tested-by: Bin Meng <bmeng.cn@gmail.com>
34
Signed-off-by: Frank Chang <frank.chang@sifive.com>
35
Message-id: 20210912130553.179501-4-frank.chang@sifive.com
15
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
36
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
16
---
37
---
17
target/riscv/cpu.h | 4 ++++
38
hw/dma/sifive_pdma.c | 16 ++++++++++------
18
target/riscv/csr.c | 51 ++++++++++++++++++++++++++++++++++++----
39
1 file changed, 10 insertions(+), 6 deletions(-)
19
target/riscv/op_helper.c | 6 ++---
20
3 files changed, 53 insertions(+), 8 deletions(-)
21
40
22
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
41
diff --git a/hw/dma/sifive_pdma.c b/hw/dma/sifive_pdma.c
23
index XXXXXXX..XXXXXXX 100644
42
index XXXXXXX..XXXXXXX 100644
24
--- a/target/riscv/cpu.h
43
--- a/hw/dma/sifive_pdma.c
25
+++ b/target/riscv/cpu.h
44
+++ b/hw/dma/sifive_pdma.c
26
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
45
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_run(SiFivePDMAState *s, int ch)
27
void riscv_cpu_update_mask(CPURISCVState *env);
46
uint64_t dst = s->chan[ch].next_dst;
28
bool riscv_cpu_is_32bit(RISCVCPU *cpu);
47
uint64_t src = s->chan[ch].next_src;
29
48
uint32_t config = s->chan[ch].next_config;
30
+RISCVException riscv_csrr(CPURISCVState *env, int csrno,
49
- int wsize, rsize, size;
31
+ target_ulong *ret_value);
50
+ int wsize, rsize, size, remainder;
32
RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
51
uint8_t buf[64];
33
target_ulong *ret_value,
52
int n;
34
target_ulong new_value, target_ulong write_mask);
53
35
@@ -XXX,XX +XXX,XX @@ typedef RISCVException (*riscv_csr_op_fn)(CPURISCVState *env, int csrno,
54
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_run(SiFivePDMAState *s, int ch)
36
target_ulong new_value,
55
size = 6;
37
target_ulong write_mask);
38
39
+RISCVException riscv_csrr_i128(CPURISCVState *env, int csrno,
40
+ Int128 *ret_value);
41
RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno,
42
Int128 *ret_value,
43
Int128 new_value, Int128 write_mask);
44
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/target/riscv/csr.c
47
+++ b/target/riscv/csr.c
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
}
56
}
59
57
size = 1 << size;
60
/* read / write check */
58
-
61
- if (write_mask && read_only) {
59
- /* the bytes to transfer should be multiple of transaction size */
62
+ if (write && read_only) {
60
- if (bytes % size) {
63
return RISCV_EXCP_ILLEGAL_INST;
61
- goto error;
62
- }
63
+ remainder = bytes % size;
64
65
/* indicate a DMA transfer is started */
66
s->chan[ch].state = DMA_CHAN_STATE_STARTED;
67
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_run(SiFivePDMAState *s, int ch)
68
s->chan[ch].exec_bytes -= size;
64
}
69
}
65
70
66
@@ -XXX,XX +XXX,XX @@ static RISCVException riscv_csrrw_do64(CPURISCVState *env, int csrno,
71
+ if (remainder) {
67
return RISCV_EXCP_NONE;
72
+ cpu_physical_memory_read(s->chan[ch].exec_src, buf, remainder);
68
}
73
+ cpu_physical_memory_write(s->chan[ch].exec_dst, buf, remainder);
69
74
+ s->chan[ch].exec_src += remainder;
70
+RISCVException riscv_csrr(CPURISCVState *env, int csrno,
75
+ s->chan[ch].exec_dst += remainder;
71
+ target_ulong *ret_value)
76
+ s->chan[ch].exec_bytes -= remainder;
72
+{
73
+ RISCVException ret = riscv_csrrw_check(env, csrno, false);
74
+ if (ret != RISCV_EXCP_NONE) {
75
+ return ret;
76
+ }
77
+ }
77
+
78
+
78
+ return riscv_csrrw_do64(env, csrno, ret_value, 0, 0);
79
/* indicate a DMA transfer is done */
79
+}
80
s->chan[ch].state = DMA_CHAN_STATE_DONE;
80
+
81
s->chan[ch].control &= ~CONTROL_RUN;
81
RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
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)
96
+{
97
+ RISCVException ret;
98
+
99
+ ret = riscv_csrrw_check(env, csrno, false);
100
+ if (ret != RISCV_EXCP_NONE) {
101
+ return ret;
102
+ }
103
+
104
+ if (csr_ops[csrno].read128) {
105
+ return riscv_csrrw_do128(env, csrno, ret_value,
106
+ int128_zero(), int128_zero());
107
+ }
108
+
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;
124
+}
125
+
126
RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno,
127
Int128 *ret_value,
128
Int128 new_value, Int128 write_mask)
129
{
130
RISCVException ret;
131
132
- ret = riscv_csrrw_check(env, csrno, int128_nz(write_mask));
133
+ ret = riscv_csrrw_check(env, csrno, true);
134
if (ret != RISCV_EXCP_NONE) {
135
return ret;
136
}
137
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
138
index XXXXXXX..XXXXXXX 100644
139
--- a/target/riscv/op_helper.c
140
+++ b/target/riscv/op_helper.c
141
@@ -XXX,XX +XXX,XX @@ target_ulong helper_csrr(CPURISCVState *env, int csr)
142
}
143
144
target_ulong val = 0;
145
- RISCVException ret = riscv_csrrw(env, csr, &val, 0, 0);
146
+ RISCVException ret = riscv_csrr(env, csr, &val);
147
148
if (ret != RISCV_EXCP_NONE) {
149
riscv_raise_exception(env, ret, GETPC());
150
@@ -XXX,XX +XXX,XX @@ target_ulong helper_csrrw(CPURISCVState *env, int csr,
151
target_ulong helper_csrr_i128(CPURISCVState *env, int csr)
152
{
153
Int128 rv = int128_zero();
154
- RISCVException ret = riscv_csrrw_i128(env, csr, &rv,
155
- int128_zero(),
156
- int128_zero());
157
+ RISCVException ret = riscv_csrr_i128(env, csr, &rv);
158
159
if (ret != RISCV_EXCP_NONE) {
160
riscv_raise_exception(env, ret, GETPC());
161
--
82
--
162
2.45.1
83
2.31.1
84
85
diff view generated by jsdifflib
1
From: Jason Chien <jason.chien@sifive.com>
1
From: Frank Chang <frank.chang@sifive.com>
2
2
3
Add support for Zve64x extension. Enabling Zve64f enables Zve64x and
3
Real PDMA doesn't set Control.error if there are 0 bytes to be
4
enabling Zve64x enables Zve32x according to their dependency.
4
transferred. The DMA transfer is still success.
5
5
6
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2107
6
The following result is PDMA tested in U-Boot on Unmatched board:
7
Signed-off-by: Jason Chien <jason.chien@sifive.com>
7
8
Reviewed-by: Frank Chang <frank.chang@sifive.com>
8
=> mw.l 0x3000000 0x0 <= Disclaim channel 0
9
Reviewed-by: Max Chou <max.chou@sifive.com>
9
=> mw.l 0x3000000 0x1 <= Claim channel 0
10
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
10
=> mw.l 0x3000004 0x55000000 <= wsize = rsize = 5 (2^5 = 32 bytes)
11
Message-ID: <20240328022343.6871-3-jason.chien@sifive.com>
11
=> mw.q 0x3000008 0x0 <= NextBytes = 0
12
=> mw.q 0x3000010 0x84000000 <= NextDestination = 0x84000000
13
=> mw.q 0x3000018 0x84001000 <= NextSource = 0x84001000
14
=> mw.l 0x84000000 0x87654321 <= Fill test data to dst
15
=> mw.l 0x84001000 0x12345678 <= Fill test data to src
16
=> md.l 0x84000000 1; md.l 0x84001000 1 <= Dump src/dst memory contents
17
84000000: 87654321 !Ce.
18
84001000: 12345678 xV4.
19
=> md.l 0x3000000 8 <= Dump PDMA status
20
03000000: 00000001 55000000 00000000 00000000 .......U........
21
03000010: 84000000 00000000 84001000 00000000 ................
22
=> mw.l 0x3000000 0x3 <= Set channel 0 run and claim bits
23
=> md.l 0x3000000 8 <= Dump PDMA status
24
03000000: 40000001 55000000 00000000 00000000 ...@...U........
25
03000010: 84000000 00000000 84001000 00000000 ................
26
=> md.l 0x84000000 1; md.l 0x84001000 1 <= Dump src/dst memory contents
27
84000000: 87654321 !Ce.
28
84001000: 12345678 xV4.
29
30
Signed-off-by: Frank Chang <frank.chang@sifive.com>
31
Tested-by: Max Hsu <max.hsu@sifive.com>
32
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
33
Tested-by: Bin Meng <bmeng.cn@gmail.com>
34
Message-id: 20210912130553.179501-5-frank.chang@sifive.com
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
35
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
13
---
36
---
14
target/riscv/cpu_cfg.h | 1 +
37
hw/dma/sifive_pdma.c | 12 ++++++------
15
target/riscv/cpu.c | 2 ++
38
1 file changed, 6 insertions(+), 6 deletions(-)
16
target/riscv/tcg/tcg-cpu.c | 17 +++++++++++------
17
3 files changed, 14 insertions(+), 6 deletions(-)
18
39
19
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
40
diff --git a/hw/dma/sifive_pdma.c b/hw/dma/sifive_pdma.c
20
index XXXXXXX..XXXXXXX 100644
41
index XXXXXXX..XXXXXXX 100644
21
--- a/target/riscv/cpu_cfg.h
42
--- a/hw/dma/sifive_pdma.c
22
+++ b/target/riscv/cpu_cfg.h
43
+++ b/hw/dma/sifive_pdma.c
23
@@ -XXX,XX +XXX,XX @@ struct RISCVCPUConfig {
44
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_run(SiFivePDMAState *s, int ch)
24
bool ext_zve32x;
45
25
bool ext_zve64f;
46
/* do nothing if bytes to transfer is zero */
26
bool ext_zve64d;
47
if (!bytes) {
27
+ bool ext_zve64x;
48
- goto error;
28
bool ext_zvbb;
49
+ goto done;
29
bool ext_zvbc;
30
bool ext_zvkb;
31
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/target/riscv/cpu.c
34
+++ b/target/riscv/cpu.c
35
@@ -XXX,XX +XXX,XX @@ const RISCVIsaExtData isa_edata_arr[] = {
36
ISA_EXT_DATA_ENTRY(zve32x, PRIV_VERSION_1_10_0, ext_zve32x),
37
ISA_EXT_DATA_ENTRY(zve64f, PRIV_VERSION_1_10_0, ext_zve64f),
38
ISA_EXT_DATA_ENTRY(zve64d, PRIV_VERSION_1_10_0, ext_zve64d),
39
+ ISA_EXT_DATA_ENTRY(zve64x, PRIV_VERSION_1_10_0, ext_zve64x),
40
ISA_EXT_DATA_ENTRY(zvfbfmin, PRIV_VERSION_1_12_0, ext_zvfbfmin),
41
ISA_EXT_DATA_ENTRY(zvfbfwma, PRIV_VERSION_1_12_0, ext_zvfbfwma),
42
ISA_EXT_DATA_ENTRY(zvfh, PRIV_VERSION_1_12_0, ext_zvfh),
43
@@ -XXX,XX +XXX,XX @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
44
MULTI_EXT_CFG_BOOL("zve32x", ext_zve32x, false),
45
MULTI_EXT_CFG_BOOL("zve64f", ext_zve64f, false),
46
MULTI_EXT_CFG_BOOL("zve64d", ext_zve64d, false),
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);
64
}
50
}
65
51
66
- /* The Zve64f extension depends on the Zve32f extension */
52
/*
67
+ /* The Zve64f extension depends on the Zve64x and Zve32f extensions */
53
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_run(SiFivePDMAState *s, int ch)
68
if (cpu->cfg.ext_zve64f) {
54
s->chan[ch].exec_bytes -= remainder;
69
+ cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve64x), true);
70
cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve32f), true);
71
}
55
}
72
56
73
- if (cpu->cfg.ext_zve64d && !riscv_has_ext(env, RVD)) {
57
- /* indicate a DMA transfer is done */
74
- error_setg(errp, "Zve64d/V extensions require D extension");
58
- s->chan[ch].state = DMA_CHAN_STATE_DONE;
75
- return;
59
- s->chan[ch].control &= ~CONTROL_RUN;
76
+ /* The Zve64x extension depends on the Zve32x extension */
60
- s->chan[ch].control |= CONTROL_DONE;
77
+ if (cpu->cfg.ext_zve64x) {
61
-
78
+ cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve32x), true);
62
/* reload exec_ registers if repeat is required */
63
if (s->chan[ch].next_config & CONFIG_REPEAT) {
64
s->chan[ch].exec_bytes = bytes;
65
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_run(SiFivePDMAState *s, int ch)
66
s->chan[ch].exec_src = src;
79
}
67
}
80
68
81
/* The Zve32f extension depends on the Zve32x extension */
69
+done:
82
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
70
+ /* indicate a DMA transfer is done */
83
return;
71
+ s->chan[ch].state = DMA_CHAN_STATE_DONE;
84
}
72
+ s->chan[ch].control &= ~CONTROL_RUN;
85
73
+ s->chan[ch].control |= CONTROL_DONE;
86
- if ((cpu->cfg.ext_zvbc || cpu->cfg.ext_zvknhb) && !cpu->cfg.ext_zve64f) {
74
return;
87
+ if ((cpu->cfg.ext_zvbc || cpu->cfg.ext_zvknhb) && !cpu->cfg.ext_zve64x) {
75
88
error_setg(
76
error:
89
errp,
90
- "Zvbc and Zvknhb extensions require V or Zve64{f,d} extensions");
91
+ "Zvbc and Zvknhb extensions require V or Zve64x extensions");
92
return;
93
}
94
95
--
77
--
96
2.45.1
78
2.31.1
79
80
diff view generated by jsdifflib
1
From: Huang Tao <eric.huang@linux.alibaba.com>
1
From: Bin Meng <bmeng.cn@gmail.com>
2
2
3
In RVV and vcrypto instructions, the masked and tail elements are set to 1s
3
In U-Boot v2021.07 release, there were 2 major changes for the
4
using vext_set_elems_1s function if the vma/vta bit is set. It is the element
4
SiFive Unleashed board support:
5
agnostic policy.
6
5
7
However, this function can't deal the big endian situation. This patch fixes
6
- Board config name was changed from sifive_fu540_defconfig to
8
the problem by adding handling of such case.
7
sifive_unleashed_defconfig
8
- The generic binman tool was used to generate the FIT image
9
(combination of U-Boot proper, DTB and OpenSBI firmware)
9
10
10
Signed-off-by: Huang Tao <eric.huang@linux.alibaba.com>
11
which make the existing U-Boot instructions out of date.
11
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
12
12
Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
13
Update the doc with latest instructions.
13
Cc: qemu-stable <qemu-stable@nongnu.org>
14
14
Message-ID: <20240325021654.6594-1-eric.huang@linux.alibaba.com>
15
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
16
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
17
Message-id: 20210911153431.10362-1-bmeng.cn@gmail.com
15
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
18
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
16
---
19
---
17
target/riscv/vector_internals.c | 22 ++++++++++++++++++++++
20
docs/system/riscv/sifive_u.rst | 49 ++++++++++++++++++----------------
18
1 file changed, 22 insertions(+)
21
1 file changed, 26 insertions(+), 23 deletions(-)
19
22
20
diff --git a/target/riscv/vector_internals.c b/target/riscv/vector_internals.c
23
diff --git a/docs/system/riscv/sifive_u.rst b/docs/system/riscv/sifive_u.rst
21
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
22
--- a/target/riscv/vector_internals.c
25
--- a/docs/system/riscv/sifive_u.rst
23
+++ b/target/riscv/vector_internals.c
26
+++ b/docs/system/riscv/sifive_u.rst
24
@@ -XXX,XX +XXX,XX @@ void vext_set_elems_1s(void *base, uint32_t is_agnostic, uint32_t cnt,
27
@@ -XXX,XX +XXX,XX @@ command line options with ``qemu-system-riscv32``.
25
if (tot - cnt == 0) {
28
Running U-Boot
26
return ;
29
--------------
27
}
30
31
-U-Boot mainline v2021.01 release is tested at the time of writing. To build a
32
+U-Boot mainline v2021.07 release is tested at the time of writing. To build a
33
U-Boot mainline bootloader that can be booted by the ``sifive_u`` machine, use
34
-the sifive_fu540_defconfig with similar commands as described above for Linux:
35
+the sifive_unleashed_defconfig with similar commands as described above for
36
+Linux:
37
38
.. code-block:: bash
39
40
$ export CROSS_COMPILE=riscv64-linux-
41
$ export OPENSBI=/path/to/opensbi-riscv64-generic-fw_dynamic.bin
42
- $ make sifive_fu540_defconfig
43
+ $ make sifive_unleashed_defconfig
44
45
You will get spl/u-boot-spl.bin and u-boot.itb file in the build tree.
46
47
@@ -XXX,XX +XXX,XX @@ board on QEMU ``sifive_u`` machine out of the box. This allows users to
48
develop and test the recommended RISC-V boot flow with a real world use
49
case: ZSBL (in QEMU) loads U-Boot SPL from SD card or SPI flash to L2LIM,
50
then U-Boot SPL loads the combined payload image of OpenSBI fw_dynamic
51
-firmware and U-Boot proper. However sometimes we want to have a quick test
52
-of booting U-Boot on QEMU without the needs of preparing the SPI flash or
53
-SD card images, an alternate way can be used, which is to create a U-Boot
54
-S-mode image by modifying the configuration of U-Boot:
55
+firmware and U-Boot proper.
28
+
56
+
29
+ if (HOST_BIG_ENDIAN) {
57
+However sometimes we want to have a quick test of booting U-Boot on QEMU
30
+ /*
58
+without the needs of preparing the SPI flash or SD card images, an alternate
31
+ * Deal the situation when the elements are insdie
59
+way can be used, which is to create a U-Boot S-mode image by modifying the
32
+ * only one uint64 block including setting the
60
+configuration of U-Boot:
33
+ * masked-off element.
61
34
+ */
62
.. code-block:: bash
35
+ if (((tot - 1) ^ cnt) < 8) {
63
36
+ memset(base + H1(tot - 1), -1, tot - cnt);
64
+ $ export CROSS_COMPILE=riscv64-linux-
37
+ return;
65
+ $ make sifive_unleashed_defconfig
38
+ }
66
$ make menuconfig
39
+ /*
67
40
+ * Otherwise, at least cross two uint64_t blocks.
68
-then manually select the following configuration in U-Boot:
41
+ * Set first unaligned block.
69
-
42
+ */
70
- Device Tree Control > Provider of DTB for DT Control > Prior Stage bootloader DTB
43
+ if (cnt % 8 != 0) {
71
+then manually select the following configuration:
44
+ uint32_t j = ROUND_UP(cnt, 8);
72
45
+ memset(base + H1(j - 1), -1, j - cnt);
73
-This lets U-Boot to use the QEMU generated device tree blob. During the build,
46
+ cnt = j;
74
-a build error will be seen below:
47
+ }
75
+ * Device Tree Control ---> Provider of DTB for DT Control ---> Prior Stage bootloader DTB
48
+ /* Set other 64bit aligend blocks */
76
49
+ }
77
-.. code-block:: none
50
memset(base + cnt, -1, tot - cnt);
78
+and unselect the following configuration:
51
}
79
80
- MKIMAGE u-boot.img
81
- ./tools/mkimage: Can't open arch/riscv/dts/hifive-unleashed-a00.dtb: No such file or directory
82
- ./tools/mkimage: failed to build FIT
83
- make: *** [Makefile:1440: u-boot.img] Error 1
84
+ * Library routines ---> Allow access to binman information in the device tree
85
86
-The above errors can be safely ignored as we don't run U-Boot SPL under QEMU
87
-in this alternate configuration.
88
+This changes U-Boot to use the QEMU generated device tree blob, and bypass
89
+running the U-Boot SPL stage.
90
91
Boot the 64-bit U-Boot S-mode image directly:
92
93
@@ -XXX,XX +XXX,XX @@ It's possible to create a 32-bit U-Boot S-mode image as well.
94
.. code-block:: bash
95
96
$ export CROSS_COMPILE=riscv64-linux-
97
- $ make sifive_fu540_defconfig
98
+ $ make sifive_unleashed_defconfig
99
$ make menuconfig
100
101
then manually update the following configuration in U-Boot:
102
103
- Device Tree Control > Provider of DTB for DT Control > Prior Stage bootloader DTB
104
- RISC-V architecture > Base ISA > RV32I
105
- Boot images > Text Base > 0x80400000
106
+ * Device Tree Control ---> Provider of DTB for DT Control ---> Prior Stage bootloader DTB
107
+ * RISC-V architecture ---> Base ISA ---> RV32I
108
+ * Boot options ---> Boot images ---> Text Base ---> 0x80400000
109
+
110
+and unselect the following configuration:
111
+
112
+ * Library routines ---> Allow access to binman information in the device tree
113
114
Use the same command line options to boot the 32-bit U-Boot S-mode image:
52
115
53
--
116
--
54
2.45.1
117
2.31.1
118
119
diff view generated by jsdifflib
1
From: Alexei Filippov <alexei.filippov@syntacore.com>
1
From: Frank Chang <frank.chang@sifive.com>
2
2
3
Previous patch fixed the PMP priority in raise_mmu_exception() but we're still
3
When virtual registers are swapped, mstatus.SD bit should also be
4
setting mtval2 incorrectly. In riscv_cpu_tlb_fill(), after pmp check in 2 stage
4
backed up/restored. Otherwise, mstatus.SD bit will be incorrectly kept
5
translation part, mtval2 will be set in case of successes 2 stage translation but
5
across the world switches.
6
failed pmp check.
7
6
8
In this case we gonna set mtval2 via env->guest_phys_fault_addr in context of
7
Signed-off-by: Frank Chang <frank.chang@sifive.com>
9
riscv_cpu_tlb_fill(), as this was a guest-page-fault, but it didn't and mtval2
8
Reviewed-by: Vincent Chen <vincent.chen@sifive.com>
10
should be zero, according to RISCV privileged spec sect. 9.4.4: When a guest
11
page-fault is taken into M-mode, mtval2 is written with either zero or guest
12
physical address that faulted, shifted by 2 bits. *For other traps, mtval2
13
is set to zero...*
14
15
Signed-off-by: Alexei Filippov <alexei.filippov@syntacore.com>
16
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
17
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
18
Message-ID: <20240503103052.6819-1-alexei.filippov@syntacore.com>
10
Message-id: 20210914013717.881430-1-frank.chang@sifive.com
19
Cc: qemu-stable <qemu-stable@nongnu.org>
11
[ Changes by AF:
12
- Convert variable to a uint64_t to fix clang error
13
]
20
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
14
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
21
---
15
---
22
target/riscv/cpu_helper.c | 12 ++++++------
16
target/riscv/cpu_helper.c | 3 ++-
23
1 file changed, 6 insertions(+), 6 deletions(-)
17
1 file changed, 2 insertions(+), 1 deletion(-)
24
18
25
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
19
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
26
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
27
--- a/target/riscv/cpu_helper.c
21
--- a/target/riscv/cpu_helper.c
28
+++ b/target/riscv/cpu_helper.c
22
+++ b/target/riscv/cpu_helper.c
29
@@ -XXX,XX +XXX,XX @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
23
@@ -XXX,XX +XXX,XX @@ bool riscv_cpu_fp_enabled(CPURISCVState *env)
30
__func__, pa, ret, prot_pmp, tlb_size);
24
31
25
void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env)
32
prot &= prot_pmp;
26
{
33
- }
27
+ uint64_t sd = riscv_cpu_is_32bit(env) ? MSTATUS32_SD : MSTATUS64_SD;
34
-
28
uint64_t mstatus_mask = MSTATUS_MXR | MSTATUS_SUM | MSTATUS_FS |
35
- if (ret != TRANSLATE_SUCCESS) {
29
MSTATUS_SPP | MSTATUS_SPIE | MSTATUS_SIE |
36
+ } else {
30
- MSTATUS64_UXL;
37
/*
31
+ MSTATUS64_UXL | sd;
38
* Guest physical address translation failed, this is a HS
32
bool current_virt = riscv_cpu_virt_enabled(env);
39
* level exception
33
40
*/
34
g_assert(riscv_has_ext(env, RVH));
41
first_stage_error = false;
42
- env->guest_phys_fault_addr = (im_address |
43
- (address &
44
- (TARGET_PAGE_SIZE - 1))) >> 2;
45
+ if (ret != TRANSLATE_PMP_FAIL) {
46
+ env->guest_phys_fault_addr = (im_address |
47
+ (address &
48
+ (TARGET_PAGE_SIZE - 1))) >> 2;
49
+ }
50
}
51
}
52
} else {
53
--
35
--
54
2.45.1
36
2.31.1
37
38
diff view generated by jsdifflib
1
From: Clément Léger <cleger@rivosinc.com>
1
From: Bin Meng <bmeng.cn@gmail.com>
2
2
3
The current semihost exception number (16) is a reserved number (range
3
The macro name HCOUNTEREN_CY suggests it is for CSR HCOUNTEREN, but
4
[16-17]). The upcoming double trap specification uses that number for
4
in fact it applies to M-mode and S-mode CSR too. Rename these macros
5
the double trap exception. Since the privileged spec (Table 22) defines
5
to have the COUNTEREN_ prefix.
6
ranges for custom uses change the semihosting exception number to 63
7
which belongs to the range [48-63] in order to avoid any future
8
collisions with reserved exception.
9
6
10
Signed-off-by: Clément Léger <cleger@rivosinc.com>
7
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
11
12
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
13
Message-ID: <20240422135840.1959967-1-cleger@rivosinc.com>
9
Message-id: 20210915084601.24304-1-bmeng.cn@gmail.com
14
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
15
---
11
---
16
target/riscv/cpu_bits.h | 2 +-
12
target/riscv/cpu_bits.h | 8 ++++----
17
1 file changed, 1 insertion(+), 1 deletion(-)
13
target/riscv/csr.c | 24 ++++++++++++------------
14
2 files changed, 16 insertions(+), 16 deletions(-)
18
15
19
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
16
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
20
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
21
--- a/target/riscv/cpu_bits.h
18
--- a/target/riscv/cpu_bits.h
22
+++ b/target/riscv/cpu_bits.h
19
+++ b/target/riscv/cpu_bits.h
23
@@ -XXX,XX +XXX,XX @@ typedef enum RISCVException {
20
@@ -XXX,XX +XXX,XX @@
24
RISCV_EXCP_INST_PAGE_FAULT = 0xc, /* since: priv-1.10.0 */
21
#define HSTATUS32_WPRI 0xFF8FF87E
25
RISCV_EXCP_LOAD_PAGE_FAULT = 0xd, /* since: priv-1.10.0 */
22
#define HSTATUS64_WPRI 0xFFFFFFFFFF8FF87EULL
26
RISCV_EXCP_STORE_PAGE_FAULT = 0xf, /* since: priv-1.10.0 */
23
27
- RISCV_EXCP_SEMIHOST = 0x10,
24
-#define HCOUNTEREN_CY (1 << 0)
28
RISCV_EXCP_INST_GUEST_PAGE_FAULT = 0x14,
25
-#define HCOUNTEREN_TM (1 << 1)
29
RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT = 0x15,
26
-#define HCOUNTEREN_IR (1 << 2)
30
RISCV_EXCP_VIRT_INSTRUCTION_FAULT = 0x16,
27
-#define HCOUNTEREN_HPM3 (1 << 3)
31
RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT = 0x17,
28
+#define COUNTEREN_CY (1 << 0)
32
+ RISCV_EXCP_SEMIHOST = 0x3f,
29
+#define COUNTEREN_TM (1 << 1)
33
} RISCVException;
30
+#define COUNTEREN_IR (1 << 2)
34
31
+#define COUNTEREN_HPM3 (1 << 3)
35
#define RISCV_EXCP_INT_FLAG 0x80000000
32
33
/* Privilege modes */
34
#define PRV_U 0
35
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/riscv/csr.c
38
+++ b/target/riscv/csr.c
39
@@ -XXX,XX +XXX,XX @@ static RISCVException ctr(CPURISCVState *env, int csrno)
40
if (riscv_cpu_virt_enabled(env)) {
41
switch (csrno) {
42
case CSR_CYCLE:
43
- if (!get_field(env->hcounteren, HCOUNTEREN_CY) &&
44
- get_field(env->mcounteren, HCOUNTEREN_CY)) {
45
+ if (!get_field(env->hcounteren, COUNTEREN_CY) &&
46
+ get_field(env->mcounteren, COUNTEREN_CY)) {
47
return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
48
}
49
break;
50
case CSR_TIME:
51
- if (!get_field(env->hcounteren, HCOUNTEREN_TM) &&
52
- get_field(env->mcounteren, HCOUNTEREN_TM)) {
53
+ if (!get_field(env->hcounteren, COUNTEREN_TM) &&
54
+ get_field(env->mcounteren, COUNTEREN_TM)) {
55
return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
56
}
57
break;
58
case CSR_INSTRET:
59
- if (!get_field(env->hcounteren, HCOUNTEREN_IR) &&
60
- get_field(env->mcounteren, HCOUNTEREN_IR)) {
61
+ if (!get_field(env->hcounteren, COUNTEREN_IR) &&
62
+ get_field(env->mcounteren, COUNTEREN_IR)) {
63
return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
64
}
65
break;
66
@@ -XXX,XX +XXX,XX @@ static RISCVException ctr(CPURISCVState *env, int csrno)
67
if (riscv_cpu_is_32bit(env)) {
68
switch (csrno) {
69
case CSR_CYCLEH:
70
- if (!get_field(env->hcounteren, HCOUNTEREN_CY) &&
71
- get_field(env->mcounteren, HCOUNTEREN_CY)) {
72
+ if (!get_field(env->hcounteren, COUNTEREN_CY) &&
73
+ get_field(env->mcounteren, COUNTEREN_CY)) {
74
return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
75
}
76
break;
77
case CSR_TIMEH:
78
- if (!get_field(env->hcounteren, HCOUNTEREN_TM) &&
79
- get_field(env->mcounteren, HCOUNTEREN_TM)) {
80
+ if (!get_field(env->hcounteren, COUNTEREN_TM) &&
81
+ get_field(env->mcounteren, COUNTEREN_TM)) {
82
return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
83
}
84
break;
85
case CSR_INSTRETH:
86
- if (!get_field(env->hcounteren, HCOUNTEREN_IR) &&
87
- get_field(env->mcounteren, HCOUNTEREN_IR)) {
88
+ if (!get_field(env->hcounteren, COUNTEREN_IR) &&
89
+ get_field(env->mcounteren, COUNTEREN_IR)) {
90
return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
91
}
92
break;
36
--
93
--
37
2.45.1
94
2.31.1
38
95
39
96
diff view generated by jsdifflib
Deleted patch
1
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
2
1
3
Running a KVM guest using a 6.9-rc3 kernel, in a 6.8 host that has zkr
4
enabled, will fail with a kernel oops SIGILL right at the start. The
5
reason is that we can't expose zkr without implementing the SEED CSR.
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.
8
9
In hindsight this is too strict. If we keep proceeding, despite not
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.
14
15
Change our current logic to not error out if we fail to disable an
16
extension in kvm_set_one_reg(), but show a warning and keep booting. It
17
is important to throw a warning because we must make the user aware that
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>
34
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
35
---
36
target/riscv/kvm/kvm-cpu.c | 12 ++++++++----
37
1 file changed, 8 insertions(+), 4 deletions(-)
38
39
diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/target/riscv/kvm/kvm-cpu.c
42
+++ b/target/riscv/kvm/kvm-cpu.c
43
@@ -XXX,XX +XXX,XX @@ static void kvm_riscv_update_cpu_cfg_isa_ext(RISCVCPU *cpu, CPUState *cs)
44
reg = kvm_cpu_cfg_get(cpu, multi_ext_cfg);
45
ret = kvm_set_one_reg(cs, id, &reg);
46
if (ret != 0) {
47
- error_report("Unable to %s extension %s in KVM, error %d",
48
- reg ? "enable" : "disable",
49
- multi_ext_cfg->name, ret);
50
- exit(EXIT_FAILURE);
51
+ if (!reg && ret == -EINVAL) {
52
+ warn_report("KVM cannot disable extension %s",
53
+ multi_ext_cfg->name);
54
+ } else {
55
+ error_report("Unable to enable extension %s in KVM, error %d",
56
+ multi_ext_cfg->name, ret);
57
+ exit(EXIT_FAILURE);
58
+ }
59
}
60
}
61
}
62
--
63
2.45.1
diff view generated by jsdifflib
Deleted patch
1
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
2
1
3
We're not setting (s/m)tval when triggering breakpoints of type 2
4
(mcontrol) and 6 (mcontrol6). According to the debug spec section
5
5.7.12, "Match Control Type 6":
6
7
"The Privileged Spec says that breakpoint exceptions that occur on
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>
26
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
27
Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
28
Message-ID: <20240416230437.1869024-2-dbarboza@ventanamicro.com>
29
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
30
---
31
target/riscv/cpu_helper.c | 1 +
32
target/riscv/debug.c | 3 +++
33
2 files changed, 4 insertions(+)
34
35
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/riscv/cpu_helper.c
38
+++ b/target/riscv/cpu_helper.c
39
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_do_interrupt(CPUState *cs)
40
tval = env->bins;
41
break;
42
case RISCV_EXCP_BREAKPOINT:
43
+ tval = env->badaddr;
44
if (cs->watchpoint_hit) {
45
tval = cs->watchpoint_hit->hitaddr;
46
cs->watchpoint_hit = NULL;
47
diff --git a/target/riscv/debug.c b/target/riscv/debug.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/target/riscv/debug.c
50
+++ b/target/riscv/debug.c
51
@@ -XXX,XX +XXX,XX @@ bool riscv_cpu_debug_check_breakpoint(CPUState *cs)
52
if ((ctrl & TYPE2_EXEC) && (bp->pc == pc)) {
53
/* check U/S/M bit against current privilege level */
54
if ((ctrl >> 3) & BIT(env->priv)) {
55
+ env->badaddr = pc;
56
return true;
57
}
58
}
59
@@ -XXX,XX +XXX,XX @@ bool riscv_cpu_debug_check_breakpoint(CPUState *cs)
60
if (env->virt_enabled) {
61
/* check VU/VS bit against current privilege level */
62
if ((ctrl >> 23) & BIT(env->priv)) {
63
+ env->badaddr = pc;
64
return true;
65
}
66
} else {
67
/* check U/S/M bit against current privilege level */
68
if ((ctrl >> 3) & BIT(env->priv)) {
69
+ env->badaddr = pc;
70
return true;
71
}
72
}
73
--
74
2.45.1
diff view generated by jsdifflib
Deleted patch
1
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
2
1
3
Privileged spec section 4.1.9 mentions:
4
5
"When a trap is taken into S-mode, stval is written with
6
exception-specific information to assist software in handling the trap.
7
(...)
8
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>
23
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
24
Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
25
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
26
Message-ID: <20240416230437.1869024-3-dbarboza@ventanamicro.com>
27
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
28
---
29
target/riscv/insn_trans/trans_privileged.c.inc | 2 ++
30
1 file changed, 2 insertions(+)
31
32
diff --git a/target/riscv/insn_trans/trans_privileged.c.inc b/target/riscv/insn_trans/trans_privileged.c.inc
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/riscv/insn_trans/trans_privileged.c.inc
35
+++ b/target/riscv/insn_trans/trans_privileged.c.inc
36
@@ -XXX,XX +XXX,XX @@ static bool trans_ebreak(DisasContext *ctx, arg_ebreak *a)
37
if (pre == 0x01f01013 && ebreak == 0x00100073 && post == 0x40705013) {
38
generate_exception(ctx, RISCV_EXCP_SEMIHOST);
39
} else {
40
+ tcg_gen_st_tl(tcg_constant_tl(ebreak_addr), tcg_env,
41
+ offsetof(CPURISCVState, badaddr));
42
generate_exception(ctx, RISCV_EXCP_BREAKPOINT);
43
}
44
return true;
45
--
46
2.45.1
diff view generated by jsdifflib
1
From: Jason Chien <jason.chien@sifive.com>
1
From: Alistair Francis <alistair.francis@wdc.com>
2
2
3
In current implementation, the gdbstub allows reading vector registers
3
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
4
only if V extension is supported. However, all vector extensions and
4
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
5
vector crypto extensions have the vector registers and they all depend
5
Message-id: d6cb4dfe75a2f536f217d7075b750ece3acb1535.1631767043.git.alistair.francis@wdc.com
6
on Zve32x. The gdbstub should check for Zve32x instead.
7
8
Signed-off-by: Jason Chien <jason.chien@sifive.com>
9
Reviewed-by: Frank Chang <frank.chang@sifive.com>
10
Reviewed-by: Max Chou <max.chou@sifive.com>
11
Message-ID: <20240328022343.6871-4-jason.chien@sifive.com>
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
6
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
13
---
7
---
14
target/riscv/gdbstub.c | 2 +-
8
hw/riscv/opentitan.c | 2 +-
15
1 file changed, 1 insertion(+), 1 deletion(-)
9
1 file changed, 1 insertion(+), 1 deletion(-)
16
10
17
diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
11
diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c
18
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
19
--- a/target/riscv/gdbstub.c
13
--- a/hw/riscv/opentitan.c
20
+++ b/target/riscv/gdbstub.c
14
+++ b/hw/riscv/opentitan.c
21
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
15
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry ibex_memmap[] = {
22
gdb_find_static_feature("riscv-32bit-fpu.xml"),
16
[IBEX_DEV_TIMER] = { 0x40100000, 0x1000 },
23
0);
17
[IBEX_DEV_SENSOR_CTRL] = { 0x40110000, 0x1000 },
24
}
18
[IBEX_DEV_OTP_CTRL] = { 0x40130000, 0x4000 },
25
- if (env->misa_ext & RVV) {
19
+ [IBEX_DEV_USBDEV] = { 0x40150000, 0x1000 },
26
+ if (cpu->cfg.ext_zve32x) {
20
[IBEX_DEV_PWRMGR] = { 0x40400000, 0x1000 },
27
gdb_register_coprocessor(cs, riscv_gdb_get_vector,
21
[IBEX_DEV_RSTMGR] = { 0x40410000, 0x1000 },
28
riscv_gdb_set_vector,
22
[IBEX_DEV_CLKMGR] = { 0x40420000, 0x1000 },
29
ricsv_gen_dynamic_vector_feature(cs, cs->gdb_num_regs),
23
[IBEX_DEV_PINMUX] = { 0x40460000, 0x1000 },
24
[IBEX_DEV_PADCTRL] = { 0x40470000, 0x1000 },
25
- [IBEX_DEV_USBDEV] = { 0x40500000, 0x1000 },
26
[IBEX_DEV_FLASH_CTRL] = { 0x41000000, 0x1000 },
27
[IBEX_DEV_PLIC] = { 0x41010000, 0x1000 },
28
[IBEX_DEV_AES] = { 0x41100000, 0x1000 },
30
--
29
--
31
2.45.1
30
2.31.1
31
32
diff view generated by jsdifflib
Deleted patch
1
From: Max Chou <max.chou@sifive.com>
2
1
3
The opfv_narrow_check needs to check the single width float operator by
4
require_rvf.
5
6
Signed-off-by: Max Chou <max.chou@sifive.com>
7
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
8
Cc: qemu-stable <qemu-stable@nongnu.org>
9
Message-ID: <20240322092600.1198921-4-max.chou@sifive.com>
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
---
12
target/riscv/insn_trans/trans_rvv.c.inc | 1 +
13
1 file changed, 1 insertion(+)
14
15
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
17
--- a/target/riscv/insn_trans/trans_rvv.c.inc
18
+++ b/target/riscv/insn_trans/trans_rvv.c.inc
19
@@ -XXX,XX +XXX,XX @@ static bool opffv_narrow_check(DisasContext *s, arg_rmr *a)
20
static bool opffv_rod_narrow_check(DisasContext *s, arg_rmr *a)
21
{
22
return opfv_narrow_check(s, a) &&
23
+ require_rvf(s) &&
24
require_scale_rvf(s) &&
25
(s->sew != MO_8);
26
}
27
--
28
2.45.1
diff view generated by jsdifflib
Deleted patch
1
From: Max Chou <max.chou@sifive.com>
2
1
3
If the checking functions check both the single and double width
4
operators at the same time, then the single width operator checking
5
functions (require_rvf[min]) will check whether the SEW is 8.
6
7
Signed-off-by: Max Chou <max.chou@sifive.com>
8
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
9
Cc: qemu-stable <qemu-stable@nongnu.org>
10
Message-ID: <20240322092600.1198921-5-max.chou@sifive.com>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
---
13
target/riscv/insn_trans/trans_rvv.c.inc | 16 ++++------------
14
1 file changed, 4 insertions(+), 12 deletions(-)
15
16
diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/riscv/insn_trans/trans_rvv.c.inc
19
+++ b/target/riscv/insn_trans/trans_rvv.c.inc
20
@@ -XXX,XX +XXX,XX @@ static bool opfvv_widen_check(DisasContext *s, arg_rmrr *a)
21
return require_rvv(s) &&
22
require_rvf(s) &&
23
require_scale_rvf(s) &&
24
- (s->sew != MO_8) &&
25
vext_check_isa_ill(s) &&
26
vext_check_dss(s, a->rd, a->rs1, a->rs2, a->vm);
27
}
28
@@ -XXX,XX +XXX,XX @@ static bool opfvf_widen_check(DisasContext *s, arg_rmrr *a)
29
return require_rvv(s) &&
30
require_rvf(s) &&
31
require_scale_rvf(s) &&
32
- (s->sew != MO_8) &&
33
vext_check_isa_ill(s) &&
34
vext_check_ds(s, a->rd, a->rs2, a->vm);
35
}
36
@@ -XXX,XX +XXX,XX @@ static bool opfwv_widen_check(DisasContext *s, arg_rmrr *a)
37
return require_rvv(s) &&
38
require_rvf(s) &&
39
require_scale_rvf(s) &&
40
- (s->sew != MO_8) &&
41
vext_check_isa_ill(s) &&
42
vext_check_dds(s, a->rd, a->rs1, a->rs2, a->vm);
43
}
44
@@ -XXX,XX +XXX,XX @@ static bool opfwf_widen_check(DisasContext *s, arg_rmrr *a)
45
return require_rvv(s) &&
46
require_rvf(s) &&
47
require_scale_rvf(s) &&
48
- (s->sew != MO_8) &&
49
vext_check_isa_ill(s) &&
50
vext_check_dd(s, a->rd, a->rs2, a->vm);
51
}
52
@@ -XXX,XX +XXX,XX @@ static bool opffv_widen_check(DisasContext *s, arg_rmr *a)
53
{
54
return opfv_widen_check(s, a) &&
55
require_rvfmin(s) &&
56
- require_scale_rvfmin(s) &&
57
- (s->sew != MO_8);
58
+ require_scale_rvfmin(s);
59
}
60
61
#define GEN_OPFV_WIDEN_TRANS(NAME, CHECK, HELPER, FRM) \
62
@@ -XXX,XX +XXX,XX @@ static bool opffv_narrow_check(DisasContext *s, arg_rmr *a)
63
{
64
return opfv_narrow_check(s, a) &&
65
require_rvfmin(s) &&
66
- require_scale_rvfmin(s) &&
67
- (s->sew != MO_8);
68
+ require_scale_rvfmin(s);
69
}
70
71
static bool opffv_rod_narrow_check(DisasContext *s, arg_rmr *a)
72
{
73
return opfv_narrow_check(s, a) &&
74
require_rvf(s) &&
75
- require_scale_rvf(s) &&
76
- (s->sew != MO_8);
77
+ require_scale_rvf(s);
78
}
79
80
#define GEN_OPFV_NARROW_TRANS(NAME, CHECK, HELPER, FRM) \
81
@@ -XXX,XX +XXX,XX @@ static bool freduction_widen_check(DisasContext *s, arg_rmrr *a)
82
{
83
return reduction_widen_check(s, a) &&
84
require_rvf(s) &&
85
- require_scale_rvf(s) &&
86
- (s->sew != MO_8);
87
+ require_scale_rvf(s);
88
}
89
90
GEN_OPFVV_WIDEN_TRANS(vfwredusum_vs, freduction_widen_check)
91
--
92
2.45.1
diff view generated by jsdifflib
Deleted patch
1
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
2
1
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.
6
7
There's no mention in the spec about guest page fault being a higher
8
priority that PMP faults. In fact, privileged spec section 3.7.1 says:
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>
30
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
31
Message-ID: <20240413105929.7030-1-alexei.filippov@syntacore.com>
32
Cc: qemu-stable <qemu-stable@nongnu.org>
33
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
34
---
35
target/riscv/cpu_helper.c | 22 ++++++++++++----------
36
1 file changed, 12 insertions(+), 10 deletions(-)
37
38
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/target/riscv/cpu_helper.c
41
+++ b/target/riscv/cpu_helper.c
42
@@ -XXX,XX +XXX,XX @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
43
44
switch (access_type) {
45
case MMU_INST_FETCH:
46
- if (env->virt_enabled && !first_stage) {
47
+ if (pmp_violation) {
48
+ cs->exception_index = RISCV_EXCP_INST_ACCESS_FAULT;
49
+ } else if (env->virt_enabled && !first_stage) {
50
cs->exception_index = RISCV_EXCP_INST_GUEST_PAGE_FAULT;
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:
83
--
84
2.45.1
diff view generated by jsdifflib