1
From: Alistair Francis <alistair.francis@wdc.com>
1
The following changes since commit ad10b4badc1dd5b28305f9b9f1168cf0aa3ae946:
2
2
3
The following changes since commit d1fe59377bbbf91dfded1f08ffe3c636e9db8dc0:
3
Merge tag 'pull-error-2024-05-27' of https://repo.or.cz/qemu/armbru into staging (2024-05-27 06:40:42 -0700)
4
5
Merge remote-tracking branch 'remotes/vivier2/tags/trivial-branch-for-6.2-pull-request' into staging (2021-09-16 16:02:31 +0100)
6
4
7
are available in the Git repository at:
5
are available in the Git repository at:
8
6
9
git@github.com:alistair23/qemu.git tags/pull-riscv-to-apply-20210917
7
https://github.com/alistair23/qemu.git tags/pull-riscv-to-apply-20240528
10
8
11
for you to fetch changes up to c14620db9b66de88bb4fef1d0cfc283bb3d53f85:
9
for you to fetch changes up to 1806da76cb81088ea026ca3441551782b850e393:
12
10
13
hw/riscv: opentitan: Correct the USB Dev address (2021-09-17 07:43:55 +1000)
11
target/riscv: raise an exception when CSRRS/CSRRC writes a read-only CSR (2024-05-28 12:20:27 +1000)
14
12
15
----------------------------------------------------------------
13
----------------------------------------------------------------
16
Second RISC-V PR for QEMU 6.2
14
RISC-V PR for 9.1
17
15
18
- ePMP CSR address updates
16
* APLICs add child earlier than realize
19
- Convert internal interrupts to use QEMU GPIO lines
17
* Fix exposure of Zkr
20
- SiFive PWM support
18
* Raise exceptions on wrs.nto
21
- Support for RISC-V ACLINT
19
* Implement SBI debug console (DBCN) calls for KVM
22
- SiFive PDMA fixes
20
* Support 64-bit addresses for initrd
23
- Update to u-boot instructions for sifive_u
21
* Change RISCV_EXCP_SEMIHOST exception number to 63
24
- mstatus.SD bug fix for hypervisor extensions
22
* Tolerate KVM disable ext errors
25
- OpenTitan fix for USB dev address
23
* Set tval in breakpoints
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
26
43
27
----------------------------------------------------------------
44
----------------------------------------------------------------
28
Alistair Francis (9):
45
Alexei Filippov (1):
29
target/riscv: Update the ePMP CSR address
46
target/riscv: do not set mtval2 for non guest-page faults
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
38
47
39
Anup Patel (4):
48
Alistair Francis (2):
40
hw/intc: Rename sifive_clint sources to riscv_aclint sources
49
target/riscv: rvzicbo: Fixup CBO extension register calculation
41
hw/intc: Upgrade the SiFive CLINT implementation to RISC-V ACLINT
50
disas/riscv: Decode all of the pmpcfg and pmpaddr CSRs
42
hw/riscv: virt: Re-factor FDT generation
43
hw/riscv: virt: Add optional ACLINT support to virt machine
44
51
45
Bin Meng (2):
52
Andrew Jones (2):
46
docs/system/riscv: sifive_u: Update U-Boot instructions
53
target/riscv/kvm: Fix exposure of Zkr
47
target/riscv: csr: Rename HCOUNTEREN_CY and friends
54
target/riscv: Raise exceptions on wrs.nto
48
55
49
Frank Chang (4):
56
Cheng Yang (1):
50
hw/dma: sifive_pdma: reset Next* registers when Control.claim is set
57
hw/riscv/boot.c: Support 64-bit address for initrd
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
54
58
55
Green Wan (1):
59
Christoph Müllner (1):
56
hw/dma: sifive_pdma: allow non-multiple transaction size transactions
60
riscv: thead: Add th.sxstatus CSR emulation
57
61
58
LIU Zhiwei (1):
62
Clément Léger (1):
59
target/riscv: Fix satp write
63
target/riscv: change RISCV_EXCP_SEMIHOST exception number to 63
60
64
61
docs/system/riscv/sifive_u.rst | 50 ++--
65
Daniel Henrique Barboza (6):
62
docs/system/riscv/virt.rst | 10 +
66
target/riscv/kvm: implement SBI debug console (DBCN) calls
63
include/hw/intc/ibex_plic.h | 2 +
67
target/riscv/kvm: tolerate KVM disable ext errors
64
include/hw/intc/riscv_aclint.h | 80 +++++
68
target/riscv/debug: set tval=pc in breakpoint exceptions
65
include/hw/intc/sifive_clint.h | 60 ----
69
trans_privileged.c.inc: set (m|s)tval on ebreak breakpoint
66
include/hw/intc/sifive_plic.h | 4 +
70
target/riscv: prioritize pmp errors in raise_mmu_exception()
67
include/hw/riscv/sifive_u.h | 14 +-
71
riscv, gdbstub.c: fix reg_width in ricsv_gen_dynamic_vector_feature()
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
102
72
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
New patch
1
From: "yang.zhang" <yang.zhang@hexintek.com>
1
2
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: LIU Zhiwei <zhiwei_liu@c-sky.com>
1
From: Andrew Jones <ajones@ventanamicro.com>
2
2
3
These variables should be target_ulong. If truncated to int,
3
The Zkr extension may only be exposed to KVM guests if the VMM
4
the bool conditions they indicate will be wrong.
4
implements the SEED CSR. Use the same implementation as TCG.
5
5
6
As satp is very important for Linux, this bug almost fails every boot.
6
Without this patch, running with a KVM which does not forward the
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.
7
11
8
Signed-off-by: LIU Zhiwei <zhiwei_liu@c-sky.com>
12
Fixes: 3108e2f1c69d ("target/riscv/kvm: update KVM exts to Linux 6.8")
9
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
13
Signed-off-by: Andrew Jones <ajones@ventanamicro.com>
10
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
14
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
11
Message-id: 20210901124539.222868-1-zhiwei_liu@c-sky.com
15
Cc: qemu-stable <qemu-stable@nongnu.org>
16
Message-ID: <20240422134605.534207-2-ajones@ventanamicro.com>
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
17
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
13
---
18
---
14
target/riscv/csr.c | 2 +-
19
target/riscv/cpu.h | 3 +++
15
1 file changed, 1 insertion(+), 1 deletion(-)
20
target/riscv/csr.c | 18 ++++++++++++++----
21
target/riscv/kvm/kvm-cpu.c | 25 +++++++++++++++++++++++++
22
3 files changed, 42 insertions(+), 4 deletions(-)
16
23
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
17
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
38
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
18
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
19
--- a/target/riscv/csr.c
40
--- a/target/riscv/csr.c
20
+++ b/target/riscv/csr.c
41
+++ b/target/riscv/csr.c
21
@@ -XXX,XX +XXX,XX @@ static RISCVException read_satp(CPURISCVState *env, int csrno,
42
@@ -XXX,XX +XXX,XX @@ static RISCVException write_upmbase(CPURISCVState *env, int csrno,
22
static RISCVException write_satp(CPURISCVState *env, int csrno,
43
#endif
23
target_ulong val)
44
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)
24
{
52
{
25
- int vm, mask, asid;
53
uint16_t random_v;
26
+ target_ulong vm, mask, asid;
54
Error *random_e = NULL;
27
55
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_seed(CPURISCVState *env, int csrno,
28
if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
56
rval = random_v | SEED_OPST_ES16;
29
return RISCV_EXCP_NONE;
57
}
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);
30
--
117
--
31
2.31.1
118
2.45.1
32
33
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@wdc.com>
1
From: Andrew Jones <ajones@ventanamicro.com>
2
2
3
Instead of using riscv_cpu_update_mip() let's instead use the new RISC-V
3
Implementing wrs.nto to always just return is consistent with the
4
CPU GPIO lines to set the timer MIP bits.
4
specification, as the instruction is permitted to terminate the
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.
5
13
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>
6
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
19
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
10
---
20
---
11
include/hw/timer/ibex_timer.h | 2 ++
21
target/riscv/helper.h | 1 +
12
hw/riscv/opentitan.c | 3 +++
22
target/riscv/op_helper.c | 11 ++++++++
13
hw/timer/ibex_timer.c | 17 ++++++++++++-----
23
target/riscv/insn_trans/trans_rvzawrs.c.inc | 29 ++++++++++++++-------
14
3 files changed, 17 insertions(+), 5 deletions(-)
24
3 files changed, 32 insertions(+), 9 deletions(-)
15
25
16
diff --git a/include/hw/timer/ibex_timer.h b/include/hw/timer/ibex_timer.h
26
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
17
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/timer/ibex_timer.h
28
--- a/target/riscv/helper.h
19
+++ b/include/hw/timer/ibex_timer.h
29
+++ b/target/riscv/helper.h
20
@@ -XXX,XX +XXX,XX @@ struct IbexTimerState {
30
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_6(csrrw_i128, tl, env, int, tl, tl, tl, tl)
21
uint32_t timebase_freq;
31
DEF_HELPER_1(sret, tl, env)
22
32
DEF_HELPER_1(mret, tl, env)
23
qemu_irq irq;
33
DEF_HELPER_1(wfi, void, env)
24
+
34
+DEF_HELPER_1(wrs_nto, void, env)
25
+ qemu_irq m_timer_irq;
35
DEF_HELPER_1(tlb_flush, void, env)
26
};
36
DEF_HELPER_1(tlb_flush_all, void, env)
27
#endif /* HW_IBEX_TIMER_H */
37
/* Native Debug */
28
diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c
38
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
29
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
30
--- a/hw/riscv/opentitan.c
40
--- a/target/riscv/op_helper.c
31
+++ b/hw/riscv/opentitan.c
41
+++ b/target/riscv/op_helper.c
32
@@ -XXX,XX +XXX,XX @@ static void lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp)
42
@@ -XXX,XX +XXX,XX @@ void helper_wfi(CPURISCVState *env)
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)
56
}
43
}
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);
78
}
44
}
79
45
80
+static void ibex_timer_realize(DeviceState *dev, Error **errp)
46
+void helper_wrs_nto(CPURISCVState *env)
81
+{
47
+{
82
+ IbexTimerState *s = IBEX_TIMER(dev);
48
+ if (env->virt_enabled && (env->priv == PRV_S || env->priv == PRV_U) &&
83
+
49
+ get_field(env->hstatus, HSTATUS_VTW) &&
84
+ qdev_init_gpio_out(dev, &s->m_timer_irq, 1);
50
+ !get_field(env->mstatus, MSTATUS_TW)) {
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
+ }
85
+}
55
+}
86
+
56
+
57
void helper_tlb_flush(CPURISCVState *env)
58
{
59
CPUState *cs = env_cpu(env);
60
diff --git a/target/riscv/insn_trans/trans_rvzawrs.c.inc b/target/riscv/insn_trans/trans_rvzawrs.c.inc
61
index XXXXXXX..XXXXXXX 100644
62
--- a/target/riscv/insn_trans/trans_rvzawrs.c.inc
63
+++ b/target/riscv/insn_trans/trans_rvzawrs.c.inc
64
@@ -XXX,XX +XXX,XX @@
65
* this program. If not, see <http://www.gnu.org/licenses/>.
66
*/
67
68
-static bool trans_wrs(DisasContext *ctx)
69
+static bool trans_wrs_sto(DisasContext *ctx, arg_wrs_sto *a)
70
{
71
if (!ctx->cfg_ptr->ext_zawrs) {
72
return false;
73
@@ -XXX,XX +XXX,XX @@ static bool trans_wrs(DisasContext *ctx)
74
return true;
75
}
76
77
-#define GEN_TRANS_WRS(insn) \
78
-static bool trans_ ## insn(DisasContext *ctx, arg_ ## insn *a) \
79
-{ \
80
- (void)a; \
81
- return trans_wrs(ctx); \
82
-}
83
+static bool trans_wrs_nto(DisasContext *ctx, arg_wrs_nto *a)
84
+{
85
+ if (!ctx->cfg_ptr->ext_zawrs) {
86
+ return false;
87
+ }
88
89
-GEN_TRANS_WRS(wrs_nto)
90
-GEN_TRANS_WRS(wrs_sto)
91
+ /*
92
+ * Depending on the mode of execution, mstatus.TW and hstatus.VTW, wrs.nto
93
+ * should raise an exception when the implementation-specific bounded time
94
+ * limit has expired. Our time limit is zero, so we either return
95
+ * immediately, as does our implementation of wrs.sto, or raise an
96
+ * exception, as handled by the wrs.nto helper.
97
+ */
98
+#ifndef CONFIG_USER_ONLY
99
+ gen_helper_wrs_nto(tcg_env);
100
+#endif
87
+
101
+
88
static void ibex_timer_class_init(ObjectClass *klass, void *data)
102
+ /* We only get here when helper_wrs_nto() doesn't raise an exception. */
89
{
103
+ return trans_wrs_sto(ctx, NULL);
90
DeviceClass *dc = DEVICE_CLASS(klass);
104
+}
91
92
dc->reset = ibex_timer_reset;
93
dc->vmsd = &vmstate_ibex_timer;
94
+ dc->realize = ibex_timer_realize;
95
device_class_set_props(dc, ibex_timer_properties);
96
}
97
98
--
105
--
99
2.31.1
106
2.45.1
100
107
101
108
diff view generated by jsdifflib
1
From: Anup Patel <anup.patel@wdc.com>
1
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
2
2
3
We re-factor and break the FDT generation into smaller functions
3
SBI defines a Debug Console extension "DBCN" that will, in time, replace
4
so that it is easier to modify FDT generation for different
4
the legacy console putchar and getchar SBI extensions.
5
configurations of virt machine.
5
6
6
The appeal of the DBCN extension is that it allows multiple bytes to be
7
Signed-off-by: Anup Patel <anup.patel@wdc.com>
7
read/written in the SBI console in a single SBI call.
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
9
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
9
As far as KVM goes, the DBCN calls are forwarded by an in-kernel KVM
10
Message-id: 20210831110603.338681-4-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>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
29
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
---
30
---
13
hw/riscv/virt.c | 527 ++++++++++++++++++++++++++++++------------------
31
target/riscv/sbi_ecall_interface.h | 17 +++++
14
1 file changed, 327 insertions(+), 200 deletions(-)
32
target/riscv/kvm/kvm-cpu.c | 111 +++++++++++++++++++++++++++++
15
33
2 files changed, 128 insertions(+)
16
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
34
35
diff --git a/target/riscv/sbi_ecall_interface.h b/target/riscv/sbi_ecall_interface.h
17
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/riscv/virt.c
37
--- a/target/riscv/sbi_ecall_interface.h
19
+++ b/hw/riscv/virt.c
38
+++ b/target/riscv/sbi_ecall_interface.h
20
@@ -XXX,XX +XXX,XX @@ static void create_pcie_irq_map(void *fdt, char *nodename,
39
@@ -XXX,XX +XXX,XX @@
21
0x1800, 0, 0, 0x7);
40
22
}
41
/* clang-format off */
23
42
24
-static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap,
43
+#define SBI_SUCCESS 0
25
- uint64_t mem_size, const char *cmdline, bool is_32_bit)
44
+#define SBI_ERR_FAILED -1
26
+static void create_fdt_socket_cpus(RISCVVirtState *s, int socket,
45
+#define SBI_ERR_NOT_SUPPORTED -2
27
+ char *clust_name, uint32_t *phandle,
46
+#define SBI_ERR_INVALID_PARAM -3
28
+ bool is_32_bit, uint32_t *intc_phandles)
47
+#define SBI_ERR_DENIED -4
29
{
48
+#define SBI_ERR_INVALID_ADDRESS -5
30
- void *fdt;
49
+#define SBI_ERR_ALREADY_AVAILABLE -6
31
- int i, cpu, socket;
50
+#define SBI_ERR_ALREADY_STARTED -7
32
+ int cpu;
51
+#define SBI_ERR_ALREADY_STOPPED -8
33
+ uint32_t cpu_phandle;
52
+#define SBI_ERR_NO_SHMEM -9
34
MachineState *mc = MACHINE(s);
53
+
35
+ char *name, *cpu_name, *core_name, *intc_name;
54
/* SBI Extension IDs */
36
+
55
#define SBI_EXT_0_1_SET_TIMER 0x0
37
+ for (cpu = s->soc[socket].num_harts - 1; cpu >= 0; cpu--) {
56
#define SBI_EXT_0_1_CONSOLE_PUTCHAR 0x1
38
+ cpu_phandle = (*phandle)++;
57
@@ -XXX,XX +XXX,XX @@
39
+
58
#define SBI_EXT_IPI 0x735049
40
+ cpu_name = g_strdup_printf("/cpus/cpu@%d",
59
#define SBI_EXT_RFENCE 0x52464E43
41
+ s->soc[socket].hartid_base + cpu);
60
#define SBI_EXT_HSM 0x48534D
42
+ qemu_fdt_add_subnode(mc->fdt, cpu_name);
61
+#define SBI_EXT_DBCN 0x4442434E
43
+ qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
62
44
+ (is_32_bit) ? "riscv,sv32" : "riscv,sv48");
63
/* SBI function IDs for BASE extension */
45
+ name = riscv_isa_string(&s->soc[socket].harts[cpu]);
64
#define SBI_EXT_BASE_GET_SPEC_VERSION 0x0
46
+ qemu_fdt_setprop_string(mc->fdt, cpu_name, "riscv,isa", name);
65
@@ -XXX,XX +XXX,XX @@
47
+ g_free(name);
66
#define SBI_EXT_HSM_HART_STOP 0x1
48
+ qemu_fdt_setprop_string(mc->fdt, cpu_name, "compatible", "riscv");
67
#define SBI_EXT_HSM_HART_GET_STATUS 0x2
49
+ qemu_fdt_setprop_string(mc->fdt, cpu_name, "status", "okay");
68
50
+ qemu_fdt_setprop_cell(mc->fdt, cpu_name, "reg",
69
+/* SBI function IDs for DBCN extension */
51
+ s->soc[socket].hartid_base + cpu);
70
+#define SBI_EXT_DBCN_CONSOLE_WRITE 0x0
52
+ qemu_fdt_setprop_string(mc->fdt, cpu_name, "device_type", "cpu");
71
+#define SBI_EXT_DBCN_CONSOLE_READ 0x1
53
+ riscv_socket_fdt_write_id(mc, mc->fdt, cpu_name, socket);
72
+#define SBI_EXT_DBCN_CONSOLE_WRITE_BYTE 0x2
54
+ qemu_fdt_setprop_cell(mc->fdt, cpu_name, "phandle", cpu_phandle);
73
+
55
+
74
#define SBI_HSM_HART_STATUS_STARTED 0x0
56
+ intc_phandles[cpu] = (*phandle)++;
75
#define SBI_HSM_HART_STATUS_STOPPED 0x1
57
+
76
#define SBI_HSM_HART_STATUS_START_PENDING 0x2
58
+ intc_name = g_strdup_printf("%s/interrupt-controller", cpu_name);
77
diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
59
+ qemu_fdt_add_subnode(mc->fdt, intc_name);
78
index XXXXXXX..XXXXXXX 100644
60
+ qemu_fdt_setprop_cell(mc->fdt, intc_name, "phandle",
79
--- a/target/riscv/kvm/kvm-cpu.c
61
+ intc_phandles[cpu]);
80
+++ b/target/riscv/kvm/kvm-cpu.c
62
+ qemu_fdt_setprop_string(mc->fdt, intc_name, "compatible",
81
@@ -XXX,XX +XXX,XX @@ static KVMCPUConfig kvm_v_vlenb = {
63
+ "riscv,cpu-intc");
82
KVM_REG_RISCV_VECTOR_CSR_REG(vlenb)
64
+ qemu_fdt_setprop(mc->fdt, intc_name, "interrupt-controller", NULL, 0);
83
};
65
+ qemu_fdt_setprop_cell(mc->fdt, intc_name, "#interrupt-cells", 1);
84
66
+
85
+static KVMCPUConfig kvm_sbi_dbcn = {
67
+ core_name = g_strdup_printf("%s/core%d", clust_name, cpu);
86
+ .name = "sbi_dbcn",
68
+ qemu_fdt_add_subnode(mc->fdt, core_name);
87
+ .kvm_reg_id = KVM_REG_RISCV | KVM_REG_SIZE_U64 |
69
+ qemu_fdt_setprop_cell(mc->fdt, core_name, "cpu", cpu_phandle);
88
+ KVM_REG_RISCV_SBI_EXT | KVM_RISCV_SBI_EXT_DBCN
70
+
89
+};
71
+ g_free(core_name);
90
+
72
+ g_free(intc_name);
91
static void kvm_riscv_update_cpu_cfg_isa_ext(RISCVCPU *cpu, CPUState *cs)
73
+ g_free(cpu_name);
92
{
93
CPURISCVState *env = &cpu->env;
94
@@ -XXX,XX +XXX,XX @@ static int uint64_cmp(const void *a, const void *b)
95
return 0;
96
}
97
98
+static void kvm_riscv_check_sbi_dbcn_support(RISCVCPU *cpu,
99
+ KVMScratchCPU *kvmcpu,
100
+ struct kvm_reg_list *reglist)
101
+{
102
+ struct kvm_reg_list *reg_search;
103
+
104
+ reg_search = bsearch(&kvm_sbi_dbcn.kvm_reg_id, reglist->reg, reglist->n,
105
+ sizeof(uint64_t), uint64_cmp);
106
+
107
+ if (reg_search) {
108
+ kvm_sbi_dbcn.supported = true;
74
+ }
109
+ }
75
+}
110
+}
76
+
111
+
77
+static void create_fdt_socket_memory(RISCVVirtState *s,
112
static void kvm_riscv_read_vlenb(RISCVCPU *cpu, KVMScratchCPU *kvmcpu,
78
+ const MemMapEntry *memmap, int socket)
113
struct kvm_reg_list *reglist)
114
{
115
@@ -XXX,XX +XXX,XX @@ static void kvm_riscv_init_multiext_cfg(RISCVCPU *cpu, KVMScratchCPU *kvmcpu)
116
if (riscv_has_ext(&cpu->env, RVV)) {
117
kvm_riscv_read_vlenb(cpu, kvmcpu, reglist);
118
}
119
+
120
+ kvm_riscv_check_sbi_dbcn_support(cpu, kvmcpu, reglist);
121
}
122
123
static void riscv_init_kvm_registers(Object *cpu_obj)
124
@@ -XXX,XX +XXX,XX @@ static int kvm_vcpu_set_machine_ids(RISCVCPU *cpu, CPUState *cs)
125
return ret;
126
}
127
128
+static int kvm_vcpu_enable_sbi_dbcn(RISCVCPU *cpu, CPUState *cs)
79
+{
129
+{
80
+ char *mem_name;
130
+ target_ulong reg = 1;
81
uint64_t addr, size;
131
+
82
- uint32_t *clint_cells, *plic_cells;
132
+ if (!kvm_sbi_dbcn.supported) {
83
- unsigned long clint_addr, plic_addr;
133
+ return 0;
84
- uint32_t plic_phandle[MAX_NODES];
134
+ }
85
- uint32_t cpu_phandle, intc_phandle, test_phandle;
135
+
86
- uint32_t phandle = 1, plic_mmio_phandle = 1;
136
+ return kvm_set_one_reg(cs, kvm_sbi_dbcn.kvm_reg_id, &reg);
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
+}
137
+}
104
+
138
+
105
+static void create_fdt_socket_clint(RISCVVirtState *s,
139
int kvm_arch_init_vcpu(CPUState *cs)
106
+ const MemMapEntry *memmap, int socket,
140
{
107
+ uint32_t *intc_phandles)
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)
108
+{
156
+{
109
+ int cpu;
157
+ g_autofree uint8_t *buf = NULL;
110
+ char *clint_name;
158
+ RISCVCPU *cpu = RISCV_CPU(cs);
111
+ uint32_t *clint_cells;
159
+ target_ulong num_bytes;
112
+ unsigned long clint_addr;
160
+ uint64_t addr;
113
+ MachineState *mc = MACHINE(s);
161
+ unsigned char ch;
114
static const char * const clint_compat[2] = {
162
+ int ret;
115
"sifive,clint0", "riscv,clint0"
163
+
116
};
164
+ switch (run->riscv_sbi.function_id) {
117
+
165
+ case SBI_EXT_DBCN_CONSOLE_READ:
118
+ clint_cells = g_new0(uint32_t, s->soc[socket].num_harts * 4);
166
+ case SBI_EXT_DBCN_CONSOLE_WRITE:
119
+
167
+ num_bytes = run->riscv_sbi.args[0];
120
+ for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) {
168
+
121
+ clint_cells[cpu * 4 + 0] = cpu_to_be32(intc_phandles[cpu]);
169
+ if (num_bytes == 0) {
122
+ clint_cells[cpu * 4 + 1] = cpu_to_be32(IRQ_M_SOFT);
170
+ run->riscv_sbi.ret[0] = SBI_SUCCESS;
123
+ clint_cells[cpu * 4 + 2] = cpu_to_be32(intc_phandles[cpu]);
171
+ run->riscv_sbi.ret[1] = 0;
124
+ clint_cells[cpu * 4 + 3] = cpu_to_be32(IRQ_M_TIMER);
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;
125
+ }
225
+ }
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
+}
226
+}
142
+
227
+
143
+static void create_fdt_socket_plic(RISCVVirtState *s,
228
static int kvm_riscv_handle_sbi(CPUState *cs, struct kvm_run *run)
144
+ const MemMapEntry *memmap, int socket,
229
{
145
+ uint32_t *phandle, uint32_t *intc_phandles,
230
int ret = 0;
146
+ uint32_t *plic_phandles)
231
@@ -XXX,XX +XXX,XX @@ static int kvm_riscv_handle_sbi(CPUState *cs, struct kvm_run *run)
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
}
232
}
365
if (socket == 1) {
233
ret = 0;
366
- plic_virtio_phandle = plic_phandle[socket];
234
break;
367
- plic_pcie_phandle = plic_phandle[socket];
235
+ case SBI_EXT_DBCN:
368
+ *irq_virtio_phandle = xplic_phandles[socket];
236
+ kvm_riscv_handle_sbi_dbcn(cs, run);
369
+ *irq_pcie_phandle = xplic_phandles[socket];
237
+ break;
370
}
238
default:
371
if (socket == 2) {
239
qemu_log_mask(LOG_UNIMP,
372
- plic_pcie_phandle = plic_phandle[socket];
240
"%s: un-handled SBI EXIT, specific reasons is %lu\n",
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);
637
}
638
}
639
640
--
241
--
641
2.31.1
242
2.45.1
642
643
diff view generated by jsdifflib
1
From: Bin Meng <bmeng.cn@gmail.com>
1
From: Cheng Yang <yangcheng.work@foxmail.com>
2
2
3
In U-Boot v2021.07 release, there were 2 major changes for the
3
Use qemu_fdt_setprop_u64() instead of qemu_fdt_setprop_cell()
4
SiFive Unleashed board support:
4
to set the address of initrd in FDT to support 64-bit address.
5
5
6
- Board config name was changed from sifive_fu540_defconfig to
6
Signed-off-by: Cheng Yang <yangcheng.work@foxmail.com>
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)
10
11
which make the existing U-Boot instructions out of date.
12
13
Update the doc with latest instructions.
14
15
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
16
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
17
Message-id: 20210911153431.10362-1-bmeng.cn@gmail.com
8
Message-ID: <tencent_A4482251DD0890F312758FA6B33F60815609@qq.com>
18
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
9
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
19
---
10
---
20
docs/system/riscv/sifive_u.rst | 49 ++++++++++++++++++----------------
11
hw/riscv/boot.c | 4 ++--
21
1 file changed, 26 insertions(+), 23 deletions(-)
12
1 file changed, 2 insertions(+), 2 deletions(-)
22
13
23
diff --git a/docs/system/riscv/sifive_u.rst b/docs/system/riscv/sifive_u.rst
14
diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
24
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
25
--- a/docs/system/riscv/sifive_u.rst
16
--- a/hw/riscv/boot.c
26
+++ b/docs/system/riscv/sifive_u.rst
17
+++ b/hw/riscv/boot.c
27
@@ -XXX,XX +XXX,XX @@ command line options with ``qemu-system-riscv32``.
18
@@ -XXX,XX +XXX,XX @@ static void riscv_load_initrd(MachineState *machine, uint64_t kernel_entry)
28
Running U-Boot
19
/* Some RISC-V machines (e.g. opentitan) don't have a fdt. */
29
--------------
20
if (fdt) {
30
21
end = start + size;
31
-U-Boot mainline v2021.01 release is tested at the time of writing. To build a
22
- qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start", start);
32
+U-Boot mainline v2021.07 release is tested at the time of writing. To build a
23
- qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end", end);
33
U-Boot mainline bootloader that can be booted by the ``sifive_u`` machine, use
24
+ qemu_fdt_setprop_u64(fdt, "/chosen", "linux,initrd-start", start);
34
-the sifive_fu540_defconfig with similar commands as described above for Linux:
25
+ qemu_fdt_setprop_u64(fdt, "/chosen", "linux,initrd-end", end);
35
+the sifive_unleashed_defconfig with similar commands as described above for
26
}
36
+Linux:
27
}
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.
56
+
57
+However sometimes we want to have a quick test of booting U-Boot on QEMU
58
+without the needs of preparing the SPI flash or SD card images, an alternate
59
+way can be used, which is to create a U-Boot S-mode image by modifying the
60
+configuration of U-Boot:
61
62
.. code-block:: bash
63
64
+ $ export CROSS_COMPILE=riscv64-linux-
65
+ $ make sifive_unleashed_defconfig
66
$ make menuconfig
67
68
-then manually select the following configuration in U-Boot:
69
-
70
- Device Tree Control > Provider of DTB for DT Control > Prior Stage bootloader DTB
71
+then manually select the following configuration:
72
73
-This lets U-Boot to use the QEMU generated device tree blob. During the build,
74
-a build error will be seen below:
75
+ * Device Tree Control ---> Provider of DTB for DT Control ---> Prior Stage bootloader DTB
76
77
-.. code-block:: none
78
+and unselect the following configuration:
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:
115
28
116
--
29
--
117
2.31.1
30
2.45.1
118
119
diff view generated by jsdifflib
1
From: Bin Meng <bmeng.cn@gmail.com>
1
From: Clément Léger <cleger@rivosinc.com>
2
2
3
The macro name HCOUNTEREN_CY suggests it is for CSR HCOUNTEREN, but
3
The current semihost exception number (16) is a reserved number (range
4
in fact it applies to M-mode and S-mode CSR too. Rename these macros
4
[16-17]). The upcoming double trap specification uses that number for
5
to have the COUNTEREN_ prefix.
5
the double trap exception. Since the privileged spec (Table 22) defines
6
ranges for custom uses change the semihosting exception number to 63
7
which belongs to the range [48-63] in order to avoid any future
8
collisions with reserved exception.
6
9
7
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
10
Signed-off-by: Clément Léger <cleger@rivosinc.com>
11
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
12
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Message-id: 20210915084601.24304-1-bmeng.cn@gmail.com
13
Message-ID: <20240422135840.1959967-1-cleger@rivosinc.com>
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
14
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
---
15
---
12
target/riscv/cpu_bits.h | 8 ++++----
16
target/riscv/cpu_bits.h | 2 +-
13
target/riscv/csr.c | 24 ++++++++++++------------
17
1 file changed, 1 insertion(+), 1 deletion(-)
14
2 files changed, 16 insertions(+), 16 deletions(-)
15
18
16
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
19
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
17
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
18
--- a/target/riscv/cpu_bits.h
21
--- a/target/riscv/cpu_bits.h
19
+++ b/target/riscv/cpu_bits.h
22
+++ b/target/riscv/cpu_bits.h
20
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@ typedef enum RISCVException {
21
#define HSTATUS32_WPRI 0xFF8FF87E
24
RISCV_EXCP_INST_PAGE_FAULT = 0xc, /* since: priv-1.10.0 */
22
#define HSTATUS64_WPRI 0xFFFFFFFFFF8FF87EULL
25
RISCV_EXCP_LOAD_PAGE_FAULT = 0xd, /* since: priv-1.10.0 */
23
26
RISCV_EXCP_STORE_PAGE_FAULT = 0xf, /* since: priv-1.10.0 */
24
-#define HCOUNTEREN_CY (1 << 0)
27
- RISCV_EXCP_SEMIHOST = 0x10,
25
-#define HCOUNTEREN_TM (1 << 1)
28
RISCV_EXCP_INST_GUEST_PAGE_FAULT = 0x14,
26
-#define HCOUNTEREN_IR (1 << 2)
29
RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT = 0x15,
27
-#define HCOUNTEREN_HPM3 (1 << 3)
30
RISCV_EXCP_VIRT_INSTRUCTION_FAULT = 0x16,
28
+#define COUNTEREN_CY (1 << 0)
31
RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT = 0x17,
29
+#define COUNTEREN_TM (1 << 1)
32
+ RISCV_EXCP_SEMIHOST = 0x3f,
30
+#define COUNTEREN_IR (1 << 2)
33
} RISCVException;
31
+#define COUNTEREN_HPM3 (1 << 3)
34
32
35
#define RISCV_EXCP_INT_FLAG 0x80000000
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;
93
--
36
--
94
2.31.1
37
2.45.1
95
38
96
39
diff view generated by jsdifflib
New patch
1
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
1
2
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
New patch
1
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
1
2
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
New patch
1
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
1
2
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: Frank Chang <frank.chang@sifive.com>
1
From: Jason Chien <jason.chien@sifive.com>
2
2
3
Real PDMA doesn't set Control.error if there are 0 bytes to be
3
Add support for Zve32x extension and replace some checks for Zve32f with
4
transferred. The DMA transfer is still success.
4
Zve32x, since Zve32f depends on Zve32x.
5
5
6
The following result is PDMA tested in U-Boot on Unmatched board:
6
Signed-off-by: Jason Chien <jason.chien@sifive.com>
7
7
Reviewed-by: Frank Chang <frank.chang@sifive.com>
8
=> mw.l 0x3000000 0x0 <= Disclaim channel 0
8
Reviewed-by: Max Chou <max.chou@sifive.com>
9
=> mw.l 0x3000000 0x1 <= Claim channel 0
9
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
10
=> mw.l 0x3000004 0x55000000 <= wsize = rsize = 5 (2^5 = 32 bytes)
10
Message-ID: <20240328022343.6871-2-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
35
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
36
---
12
---
37
hw/dma/sifive_pdma.c | 12 ++++++------
13
target/riscv/cpu_cfg.h | 1 +
38
1 file changed, 6 insertions(+), 6 deletions(-)
14
target/riscv/cpu.c | 2 ++
15
target/riscv/cpu_helper.c | 2 +-
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(-)
39
20
40
diff --git a/hw/dma/sifive_pdma.c b/hw/dma/sifive_pdma.c
21
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
41
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/dma/sifive_pdma.c
23
--- a/target/riscv/cpu_cfg.h
43
+++ b/hw/dma/sifive_pdma.c
24
+++ b/target/riscv/cpu_cfg.h
44
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_run(SiFivePDMAState *s, int ch)
25
@@ -XXX,XX +XXX,XX @@ struct RISCVCPUConfig {
45
26
bool ext_zhinx;
46
/* do nothing if bytes to transfer is zero */
27
bool ext_zhinxmin;
47
if (!bytes) {
28
bool ext_zve32f;
48
- goto error;
29
+ bool ext_zve32x;
49
+ goto done;
30
bool ext_zve64f;
31
bool ext_zve64d;
32
bool ext_zvbb;
33
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/riscv/cpu.c
36
+++ b/target/riscv/cpu.c
37
@@ -XXX,XX +XXX,XX @@ const RISCVIsaExtData isa_edata_arr[] = {
38
ISA_EXT_DATA_ENTRY(zvbb, PRIV_VERSION_1_12_0, ext_zvbb),
39
ISA_EXT_DATA_ENTRY(zvbc, PRIV_VERSION_1_12_0, ext_zvbc),
40
ISA_EXT_DATA_ENTRY(zve32f, PRIV_VERSION_1_10_0, ext_zve32f),
41
+ ISA_EXT_DATA_ENTRY(zve32x, PRIV_VERSION_1_10_0, ext_zve32x),
42
ISA_EXT_DATA_ENTRY(zve64f, PRIV_VERSION_1_10_0, ext_zve64f),
43
ISA_EXT_DATA_ENTRY(zve64d, PRIV_VERSION_1_10_0, ext_zve64d),
44
ISA_EXT_DATA_ENTRY(zvfbfmin, PRIV_VERSION_1_12_0, ext_zvfbfmin),
45
@@ -XXX,XX +XXX,XX @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
46
MULTI_EXT_CFG_BOOL("zfh", ext_zfh, false),
47
MULTI_EXT_CFG_BOOL("zfhmin", ext_zfhmin, false),
48
MULTI_EXT_CFG_BOOL("zve32f", ext_zve32f, false),
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
{
74
- if (riscv_cpu_cfg(env)->ext_zve32f) {
75
+ if (riscv_cpu_cfg(env)->ext_zve32x) {
76
#if !defined(CONFIG_USER_ONLY)
77
if (!env->debugger && !riscv_cpu_vector_enabled(env)) {
78
return RISCV_EXCP_ILLEGAL_INST;
79
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
80
index XXXXXXX..XXXXXXX 100644
81
--- a/target/riscv/tcg/tcg-cpu.c
82
+++ b/target/riscv/tcg/tcg-cpu.c
83
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
84
return;
50
}
85
}
51
86
52
/*
87
- if (cpu->cfg.ext_zve32f && !riscv_has_ext(env, RVF)) {
53
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_run(SiFivePDMAState *s, int ch)
88
- error_setg(errp, "Zve32f/Zve64f extensions require F extension");
54
s->chan[ch].exec_bytes -= remainder;
89
- return;
90
+ /* The Zve32f extension depends on the Zve32x extension */
91
+ if (cpu->cfg.ext_zve32f) {
92
+ if (!riscv_has_ext(env, RVF)) {
93
+ error_setg(errp, "Zve32f/Zve64f extensions require F extension");
94
+ return;
95
+ }
96
+ cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve32x), true);
55
}
97
}
56
98
57
- /* indicate a DMA transfer is done */
99
if (cpu->cfg.ext_zvfh) {
58
- s->chan[ch].state = DMA_CHAN_STATE_DONE;
100
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
59
- s->chan[ch].control &= ~CONTROL_RUN;
101
cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvbc), true);
60
- s->chan[ch].control |= CONTROL_DONE;
61
-
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;
67
}
102
}
68
103
69
+done:
104
- /*
70
+ /* indicate a DMA transfer is done */
105
- * In principle Zve*x would also suffice here, were they supported
71
+ s->chan[ch].state = DMA_CHAN_STATE_DONE;
106
- * in qemu
72
+ s->chan[ch].control &= ~CONTROL_RUN;
107
- */
73
+ s->chan[ch].control |= CONTROL_DONE;
108
if ((cpu->cfg.ext_zvbb || cpu->cfg.ext_zvkb || cpu->cfg.ext_zvkg ||
74
return;
109
cpu->cfg.ext_zvkned || cpu->cfg.ext_zvknha || cpu->cfg.ext_zvksed ||
75
110
- cpu->cfg.ext_zvksh) && !cpu->cfg.ext_zve32f) {
76
error:
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
77
--
137
--
78
2.31.1
138
2.45.1
79
80
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@wdc.com>
1
From: Jason Chien <jason.chien@sifive.com>
2
2
3
Instead of using riscv_cpu_update_mip() let's instead use the new RISC-V
3
Add support for Zve64x extension. Enabling Zve64f enables Zve64x and
4
CPU GPIO lines to set the timer and soft MIP bits.
4
enabling Zve64x enables Zve32x according to their dependency.
5
5
6
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2107
7
Signed-off-by: Jason Chien <jason.chien@sifive.com>
8
Reviewed-by: Frank Chang <frank.chang@sifive.com>
9
Reviewed-by: Max Chou <max.chou@sifive.com>
10
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
11
Message-ID: <20240328022343.6871-3-jason.chien@sifive.com>
6
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
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
11
---
13
---
12
include/hw/intc/sifive_clint.h | 2 +
14
target/riscv/cpu_cfg.h | 1 +
13
hw/intc/sifive_clint.c | 68 ++++++++++++++++++++++++----------
15
target/riscv/cpu.c | 2 ++
14
2 files changed, 50 insertions(+), 20 deletions(-)
16
target/riscv/tcg/tcg-cpu.c | 17 +++++++++++------
17
3 files changed, 14 insertions(+), 6 deletions(-)
15
18
16
diff --git a/include/hw/intc/sifive_clint.h b/include/hw/intc/sifive_clint.h
19
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
17
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/intc/sifive_clint.h
21
--- a/target/riscv/cpu_cfg.h
19
+++ b/include/hw/intc/sifive_clint.h
22
+++ b/target/riscv/cpu_cfg.h
20
@@ -XXX,XX +XXX,XX @@ typedef struct SiFiveCLINTState {
23
@@ -XXX,XX +XXX,XX @@ struct RISCVCPUConfig {
21
uint32_t time_base;
24
bool ext_zve32x;
22
uint32_t aperture_size;
25
bool ext_zve64f;
23
uint32_t timebase_freq;
26
bool ext_zve64d;
24
+ qemu_irq *timer_irqs;
27
+ bool ext_zve64x;
25
+ qemu_irq *soft_irqs;
28
bool ext_zvbb;
26
} SiFiveCLINTState;
29
bool ext_zvbc;
27
30
bool ext_zvkb;
28
DeviceState *sifive_clint_create(hwaddr addr, hwaddr size,
31
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
29
diff --git a/hw/intc/sifive_clint.c b/hw/intc/sifive_clint.c
30
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/intc/sifive_clint.c
33
--- a/target/riscv/cpu.c
32
+++ b/hw/intc/sifive_clint.c
34
+++ b/target/riscv/cpu.c
33
@@ -XXX,XX +XXX,XX @@
35
@@ -XXX,XX +XXX,XX @@ const RISCVIsaExtData isa_edata_arr[] = {
34
#include "hw/qdev-properties.h"
36
ISA_EXT_DATA_ENTRY(zve32x, PRIV_VERSION_1_10_0, ext_zve32x),
35
#include "hw/intc/sifive_clint.h"
37
ISA_EXT_DATA_ENTRY(zve64f, PRIV_VERSION_1_10_0, ext_zve64f),
36
#include "qemu/timer.h"
38
ISA_EXT_DATA_ENTRY(zve64d, PRIV_VERSION_1_10_0, ext_zve64d),
37
+#include "hw/irq.h"
39
+ ISA_EXT_DATA_ENTRY(zve64x, PRIV_VERSION_1_10_0, ext_zve64x),
38
+
40
ISA_EXT_DATA_ENTRY(zvfbfmin, PRIV_VERSION_1_12_0, ext_zvfbfmin),
39
+typedef struct sifive_clint_callback {
41
ISA_EXT_DATA_ENTRY(zvfbfwma, PRIV_VERSION_1_12_0, ext_zvfbfwma),
40
+ SiFiveCLINTState *s;
42
ISA_EXT_DATA_ENTRY(zvfh, PRIV_VERSION_1_12_0, ext_zvfh),
41
+ int num;
43
@@ -XXX,XX +XXX,XX @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
42
+} sifive_clint_callback;
44
MULTI_EXT_CFG_BOOL("zve32x", ext_zve32x, false),
43
45
MULTI_EXT_CFG_BOOL("zve64f", ext_zve64f, false),
44
static uint64_t cpu_riscv_read_rtc(uint32_t timebase_freq)
46
MULTI_EXT_CFG_BOOL("zve64d", ext_zve64d, false),
45
{
47
+ MULTI_EXT_CFG_BOOL("zve64x", ext_zve64x, false),
46
@@ -XXX,XX +XXX,XX @@ static uint64_t cpu_riscv_read_rtc(uint32_t timebase_freq)
48
MULTI_EXT_CFG_BOOL("zvfbfmin", ext_zvfbfmin, false),
47
* Called when timecmp is written to update the QEMU timer or immediately
49
MULTI_EXT_CFG_BOOL("zvfbfwma", ext_zvfbfwma, false),
48
* trigger timer interrupt if mtimecmp <= current timer value.
50
MULTI_EXT_CFG_BOOL("zvfh", ext_zvfh, false),
49
*/
51
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
50
-static void sifive_clint_write_timecmp(RISCVCPU *cpu, uint64_t value,
52
index XXXXXXX..XXXXXXX 100644
51
+static void sifive_clint_write_timecmp(SiFiveCLINTState *s, RISCVCPU *cpu,
53
--- a/target/riscv/tcg/tcg-cpu.c
52
+ int hartid,
54
+++ b/target/riscv/tcg/tcg-cpu.c
53
+ uint64_t value,
55
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
54
uint32_t timebase_freq)
56
55
{
57
/* The Zve64d extension depends on the Zve64f extension */
56
uint64_t next;
58
if (cpu->cfg.ext_zve64d) {
57
@@ -XXX,XX +XXX,XX @@ static void sifive_clint_write_timecmp(RISCVCPU *cpu, uint64_t value,
59
+ if (!riscv_has_ext(env, RVD)) {
58
if (cpu->env.timecmp <= rtc_r) {
60
+ error_setg(errp, "Zve64d/V extensions require D extension");
59
/* if we're setting an MTIMECMP value in the "past",
61
+ return;
60
immediately raise the timer interrupt */
62
+ }
61
- riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(1));
63
cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve64f), true);
62
+ qemu_irq_raise(s->timer_irqs[hartid - s->hartid_base]);
64
}
65
66
- /* The Zve64f extension depends on the Zve32f extension */
67
+ /* The Zve64f extension depends on the Zve64x and Zve32f extensions */
68
if (cpu->cfg.ext_zve64f) {
69
+ cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve64x), true);
70
cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve32f), true);
71
}
72
73
- if (cpu->cfg.ext_zve64d && !riscv_has_ext(env, RVD)) {
74
- error_setg(errp, "Zve64d/V extensions require D extension");
75
- return;
76
+ /* The Zve64x extension depends on the Zve32x extension */
77
+ if (cpu->cfg.ext_zve64x) {
78
+ cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve32x), true);
79
}
80
81
/* The Zve32f extension depends on the Zve32x extension */
82
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
63
return;
83
return;
64
}
84
}
65
85
66
/* otherwise, set up the future timer interrupt */
86
- if ((cpu->cfg.ext_zvbc || cpu->cfg.ext_zvknhb) && !cpu->cfg.ext_zve64f) {
67
- riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(0));
87
+ if ((cpu->cfg.ext_zvbc || cpu->cfg.ext_zvknhb) && !cpu->cfg.ext_zve64x) {
68
+ qemu_irq_lower(s->timer_irqs[hartid - s->hartid_base]);
88
error_setg(
69
diff = cpu->env.timecmp - rtc_r;
89
errp,
70
/* back to ns (note args switched in muldiv64) */
90
- "Zvbc and Zvknhb extensions require V or Zve64{f,d} extensions");
71
uint64_t ns_diff = muldiv64(diff, NANOSECONDS_PER_SECOND, timebase_freq);
91
+ "Zvbc and Zvknhb extensions require V or Zve64x extensions");
72
@@ -XXX,XX +XXX,XX @@ static void sifive_clint_write_timecmp(RISCVCPU *cpu, uint64_t value,
92
return;
73
*/
74
static void sifive_clint_timer_cb(void *opaque)
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));
171
}
93
}
172
94
173
- DeviceState *dev = qdev_new(TYPE_SIFIVE_CLINT);
174
- qdev_prop_set_uint32(dev, "hartid-base", hartid_base);
175
- qdev_prop_set_uint32(dev, "num-harts", num_harts);
176
- qdev_prop_set_uint32(dev, "sip-base", sip_base);
177
- qdev_prop_set_uint32(dev, "timecmp-base", timecmp_base);
178
- qdev_prop_set_uint32(dev, "time-base", time_base);
179
- qdev_prop_set_uint32(dev, "aperture-size", size);
180
- qdev_prop_set_uint32(dev, "timebase-freq", timebase_freq);
181
- sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
182
- sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
183
return dev;
184
}
185
--
95
--
186
2.31.1
96
2.45.1
187
188
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@wdc.com>
1
From: Jason Chien <jason.chien@sifive.com>
2
2
3
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
3
In current implementation, the gdbstub allows reading vector registers
4
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
4
only if V extension is supported. However, all vector extensions and
5
Message-id: d6cb4dfe75a2f536f217d7075b750ece3acb1535.1631767043.git.alistair.francis@wdc.com
5
vector crypto extensions have the vector registers and they all depend
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>
6
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
7
---
13
---
8
hw/riscv/opentitan.c | 2 +-
14
target/riscv/gdbstub.c | 2 +-
9
1 file changed, 1 insertion(+), 1 deletion(-)
15
1 file changed, 1 insertion(+), 1 deletion(-)
10
16
11
diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c
17
diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
12
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/riscv/opentitan.c
19
--- a/target/riscv/gdbstub.c
14
+++ b/hw/riscv/opentitan.c
20
+++ b/target/riscv/gdbstub.c
15
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry ibex_memmap[] = {
21
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
16
[IBEX_DEV_TIMER] = { 0x40100000, 0x1000 },
22
gdb_find_static_feature("riscv-32bit-fpu.xml"),
17
[IBEX_DEV_SENSOR_CTRL] = { 0x40110000, 0x1000 },
23
0);
18
[IBEX_DEV_OTP_CTRL] = { 0x40130000, 0x4000 },
24
}
19
+ [IBEX_DEV_USBDEV] = { 0x40150000, 0x1000 },
25
- if (env->misa_ext & RVV) {
20
[IBEX_DEV_PWRMGR] = { 0x40400000, 0x1000 },
26
+ if (cpu->cfg.ext_zve32x) {
21
[IBEX_DEV_RSTMGR] = { 0x40410000, 0x1000 },
27
gdb_register_coprocessor(cs, riscv_gdb_get_vector,
22
[IBEX_DEV_CLKMGR] = { 0x40420000, 0x1000 },
28
riscv_gdb_set_vector,
23
[IBEX_DEV_PINMUX] = { 0x40460000, 0x1000 },
29
ricsv_gen_dynamic_vector_feature(cs, cs->gdb_num_regs),
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 },
29
--
30
--
30
2.31.1
31
2.45.1
31
32
diff view generated by jsdifflib
1
From: Frank Chang <frank.chang@sifive.com>
1
From: Huang Tao <eric.huang@linux.alibaba.com>
2
2
3
Real PDMA must have Control.claim bit to be set before
3
In RVV and vcrypto instructions, the masked and tail elements are set to 1s
4
Control.run bit is set to start any DMA transactions.
4
using vext_set_elems_1s function if the vma/vta bit is set. It is the element
5
Otherwise nothing will be transferred.
5
agnostic policy.
6
6
7
The following result is PDMA tested in U-Boot on Unmatched board:
7
However, this function can't deal the big endian situation. This patch fixes
8
the problem by adding handling of such case.
8
9
9
=> mw.l 0x3000000 0x0 <= Disclaim channel 0
10
Signed-off-by: Huang Tao <eric.huang@linux.alibaba.com>
10
(Channel 0 is not claimed)
11
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
11
=> mw.l 0x3000004 0x55000000 <= wsize = rsize = 5 (2^5 = 32 bytes)
12
Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
12
=> mw.q 0x3000008 0x2 <= NextBytes = 2
13
Cc: qemu-stable <qemu-stable@nongnu.org>
13
=> mw.q 0x3000010 0x84000000 <= NextDestination = 0x84000000
14
Message-ID: <20240325021654.6594-1-eric.huang@linux.alibaba.com>
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
36
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
15
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
37
---
16
---
38
hw/dma/sifive_pdma.c | 9 +++++++++
17
target/riscv/vector_internals.c | 22 ++++++++++++++++++++++
39
1 file changed, 9 insertions(+)
18
1 file changed, 22 insertions(+)
40
19
41
diff --git a/hw/dma/sifive_pdma.c b/hw/dma/sifive_pdma.c
20
diff --git a/target/riscv/vector_internals.c b/target/riscv/vector_internals.c
42
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
43
--- a/hw/dma/sifive_pdma.c
22
--- a/target/riscv/vector_internals.c
44
+++ b/hw/dma/sifive_pdma.c
23
+++ b/target/riscv/vector_internals.c
45
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_write(void *opaque, hwaddr offset,
24
@@ -XXX,XX +XXX,XX @@ void vext_set_elems_1s(void *base, uint32_t is_agnostic, uint32_t cnt,
46
25
if (tot - cnt == 0) {
47
s->chan[ch].control = value;
26
return ;
48
27
}
28
+
29
+ if (HOST_BIG_ENDIAN) {
49
+ /*
30
+ /*
50
+ * If channel was not claimed before run bit is set,
31
+ * Deal the situation when the elements are insdie
51
+ * DMA won't run.
32
+ * only one uint64 block including setting the
33
+ * masked-off element.
52
+ */
34
+ */
53
+ if (!claimed) {
35
+ if (((tot - 1) ^ cnt) < 8) {
54
+ s->chan[ch].control &= ~CONTROL_RUN;
36
+ memset(base + H1(tot - 1), -1, tot - cnt);
55
+ return;
37
+ return;
56
+ }
38
+ }
57
+
39
+ /*
58
if (value & CONTROL_RUN) {
40
+ * Otherwise, at least cross two uint64_t blocks.
59
sifive_pdma_run(s, ch);
41
+ * Set first unaligned block.
60
}
42
+ */
43
+ if (cnt % 8 != 0) {
44
+ uint32_t j = ROUND_UP(cnt, 8);
45
+ memset(base + H1(j - 1), -1, j - cnt);
46
+ cnt = j;
47
+ }
48
+ /* Set other 64bit aligend blocks */
49
+ }
50
memset(base + cnt, -1, tot - cnt);
51
}
52
61
--
53
--
62
2.31.1
54
2.45.1
63
64
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@wdc.com>
1
From: Yangyu Chen <cyy@cyyself.name>
2
2
3
Update the ePMP CSRs to match the 0.9.3 ePMP spec
3
This code has a typo that writes zvkb to zvkg, causing users can't
4
https://github.com/riscv/riscv-tee/blob/61455747230a26002d741f64879dd78cc9689323/Smepmp/Smepmp.pdf
4
enable zvkb through the config. This patch gets this fixed.
5
5
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>
6
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
14
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
7
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
8
Message-id: 28c908de60b9b04fa20e63d113885c98586053f3.1630543194.git.alistair.francis@wdc.com
9
---
15
---
10
target/riscv/cpu_bits.h | 4 ++--
16
target/riscv/cpu.c | 2 +-
11
target/riscv/cpu.c | 1 +
17
1 file changed, 1 insertion(+), 1 deletion(-)
12
2 files changed, 3 insertions(+), 2 deletions(-)
13
18
14
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/riscv/cpu_bits.h
17
+++ b/target/riscv/cpu_bits.h
18
@@ -XXX,XX +XXX,XX @@
19
#define CSR_MTVAL2 0x34b
20
21
/* Enhanced Physical Memory Protection (ePMP) */
22
-#define CSR_MSECCFG 0x390
23
-#define CSR_MSECCFGH 0x391
24
+#define CSR_MSECCFG 0x747
25
+#define CSR_MSECCFGH 0x757
26
/* Physical Memory Protection */
27
#define CSR_PMPCFG0 0x3a0
28
#define CSR_PMPCFG1 0x3a1
29
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
19
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
30
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
31
--- a/target/riscv/cpu.c
21
--- a/target/riscv/cpu.c
32
+++ b/target/riscv/cpu.c
22
+++ b/target/riscv/cpu.c
33
@@ -XXX,XX +XXX,XX @@ static Property riscv_cpu_properties[] = {
23
@@ -XXX,XX +XXX,XX @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
34
DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
24
/* Vector cryptography extensions */
35
DEFINE_PROP_BOOL("mmu", RISCVCPU, cfg.mmu, true),
25
MULTI_EXT_CFG_BOOL("zvbb", ext_zvbb, false),
36
DEFINE_PROP_BOOL("pmp", RISCVCPU, cfg.pmp, true),
26
MULTI_EXT_CFG_BOOL("zvbc", ext_zvbc, false),
37
+ /* ePMP 0.9.3 */
27
- MULTI_EXT_CFG_BOOL("zvkb", ext_zvkg, false),
38
DEFINE_PROP_BOOL("x-epmp", RISCVCPU, cfg.epmp, false),
28
+ MULTI_EXT_CFG_BOOL("zvkb", ext_zvkb, false),
39
29
MULTI_EXT_CFG_BOOL("zvkg", ext_zvkg, false),
40
DEFINE_PROP_UINT64("resetvec", RISCVCPU, cfg.resetvec, DEFAULT_RSTVEC),
30
MULTI_EXT_CFG_BOOL("zvkned", ext_zvkned, false),
31
MULTI_EXT_CFG_BOOL("zvknha", ext_zvknha, false),
41
--
32
--
42
2.31.1
33
2.45.1
43
34
44
35
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@wdc.com>
1
From: Huang Tao <eric.huang@linux.alibaba.com>
2
2
3
Expose the 12 interrupt pending bits in MIP as GPIO lines.
3
In this patch, we modify the decoder to be a freely composable data
4
structure instead of a hardcoded one. It can be dynamically builded up
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.
4
20
21
Signed-off-by: Huang Tao <eric.huang@linux.alibaba.com>
22
Suggested-by: Christoph Muellner <christoph.muellner@vrull.eu>
23
Co-authored-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
24
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
25
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
26
Message-ID: <20240506023607.29544-1-eric.huang@linux.alibaba.com>
5
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
27
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
11
---
28
---
12
target/riscv/cpu.c | 30 ++++++++++++++++++++++++++++++
29
target/riscv/cpu.h | 1 +
13
1 file changed, 30 insertions(+)
30
target/riscv/tcg/tcg-cpu.h | 15 +++++++++++++++
31
target/riscv/cpu.c | 1 +
32
target/riscv/tcg/tcg-cpu.c | 15 +++++++++++++++
33
target/riscv/translate.c | 31 +++++++++++++++----------------
34
5 files changed, 47 insertions(+), 16 deletions(-)
14
35
36
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
37
index XXXXXXX..XXXXXXX 100644
38
--- a/target/riscv/cpu.h
39
+++ b/target/riscv/cpu.h
40
@@ -XXX,XX +XXX,XX @@ struct ArchCPU {
41
uint32_t pmu_avail_ctrs;
42
/* Mapping of events to counters */
43
GHashTable *pmu_event_ctr_map;
44
+ const GPtrArray *decoders;
45
};
46
47
/**
48
diff --git a/target/riscv/tcg/tcg-cpu.h b/target/riscv/tcg/tcg-cpu.h
49
index XXXXXXX..XXXXXXX 100644
50
--- a/target/riscv/tcg/tcg-cpu.h
51
+++ b/target/riscv/tcg/tcg-cpu.h
52
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp);
53
void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp);
54
bool riscv_cpu_tcg_compatible(RISCVCPU *cpu);
55
56
+struct DisasContext;
57
+struct RISCVCPUConfig;
58
+typedef struct RISCVDecoder {
59
+ bool (*guard_func)(const struct RISCVCPUConfig *);
60
+ bool (*riscv_cpu_decode_fn)(struct DisasContext *, uint32_t);
61
+} RISCVDecoder;
62
+
63
+typedef bool (*riscv_cpu_decode_fn)(struct DisasContext *, uint32_t);
64
+
65
+extern const size_t decoder_table_size;
66
+
67
+extern const RISCVDecoder decoder_table[];
68
+
69
+void riscv_tcg_cpu_finalize_dynamic_decoder(RISCVCPU *cpu);
70
+
71
#endif
15
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
72
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
16
index XXXXXXX..XXXXXXX 100644
73
index XXXXXXX..XXXXXXX 100644
17
--- a/target/riscv/cpu.c
74
--- a/target/riscv/cpu.c
18
+++ b/target/riscv/cpu.c
75
+++ b/target/riscv/cpu.c
19
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
76
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_finalize_features(RISCVCPU *cpu, Error **errp)
20
mcc->parent_realize(dev, errp);
77
error_propagate(errp, local_err);
78
return;
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
}
21
}
90
}
22
91
23
+#ifndef CONFIG_USER_ONLY
92
+void riscv_tcg_cpu_finalize_dynamic_decoder(RISCVCPU *cpu)
24
+static void riscv_cpu_set_irq(void *opaque, int irq, int level)
25
+{
93
+{
26
+ RISCVCPU *cpu = RISCV_CPU(opaque);
94
+ GPtrArray *dynamic_decoders;
95
+ dynamic_decoders = g_ptr_array_sized_new(decoder_table_size);
96
+ for (size_t i = 0; i < decoder_table_size; ++i) {
97
+ if (decoder_table[i].guard_func &&
98
+ decoder_table[i].guard_func(&cpu->cfg)) {
99
+ g_ptr_array_add(dynamic_decoders,
100
+ (gpointer)decoder_table[i].riscv_cpu_decode_fn);
101
+ }
102
+ }
27
+
103
+
28
+ switch (irq) {
104
+ cpu->decoders = dynamic_decoders;
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
+}
105
+}
47
+#endif /* CONFIG_USER_ONLY */
48
+
106
+
49
static void riscv_cpu_init(Object *obj)
107
bool riscv_cpu_tcg_compatible(RISCVCPU *cpu)
50
{
108
{
51
RISCVCPU *cpu = RISCV_CPU(obj);
109
return object_dynamic_cast(OBJECT(cpu), TYPE_RISCV_CPU_HOST) == NULL;
52
110
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
53
cpu_set_cpustate_pointers(cpu);
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"
54
+
119
+
55
+#ifndef CONFIG_USER_ONLY
120
/* global register indices */
56
+ qdev_init_gpio_in(DEVICE(cpu), riscv_cpu_set_irq, 12);
121
static TCGv cpu_gpr[32], cpu_gprh[32], cpu_pc, cpu_vl, cpu_vstart;
57
+#endif /* CONFIG_USER_ONLY */
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;
58
}
133
}
59
134
60
static Property riscv_cpu_properties[] = {
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)
61
--
182
--
62
2.31.1
183
2.45.1
63
64
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@wdc.com>
1
From: Christoph Müllner <christoph.muellner@vrull.eu>
2
2
3
This is the initial commit of the SiFive PWM timer. This is used by
3
The th.sxstatus CSR can be used to identify available custom extension
4
guest software as a timer and is included in the SiFive FU540 SoC.
4
on T-Head CPUs. The CSR is documented here:
5
https://github.com/T-head-Semi/thead-extension-spec/blob/master/xtheadsxstatus.adoc
5
6
6
Signed-off-by: Justin Restivo <jrestivo@draper.com>
7
An important property of this patch is, that the th.sxstatus MAEE field
7
Signed-off-by: Alexandra Clifford <aclifford@draper.com>
8
is not set (indicating that XTheadMae is not available).
8
Signed-off-by: Amanda Strnad <astrnad@draper.com>
9
XTheadMae is a memory attribute extension (similar to Svpbmt) which is
10
implemented in many T-Head CPUs (C906, C910, etc.) and utilizes bits
11
in PTEs that are marked as reserved. QEMU maintainers prefer to not
12
implement XTheadMae, so we need give kernels a mechanism to identify
13
if XTheadMae is available in a system or not. And this patch introduces
14
this mechanism in QEMU in a way that's compatible with real HW
15
(i.e., probing the th.sxstatus.MAEE bit).
16
17
Further context can be found on the list:
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>
9
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
24
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
10
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
11
Message-id: 9f70a210acbfaf0e1ea6ad311ab892ac69134d8b.1631159656.git.alistair.francis@wdc.com
12
---
25
---
13
include/hw/timer/sifive_pwm.h | 62 +++++
26
MAINTAINERS | 1 +
14
hw/timer/sifive_pwm.c | 468 ++++++++++++++++++++++++++++++++++
27
target/riscv/cpu.h | 3 ++
15
hw/timer/Kconfig | 3 +
28
target/riscv/cpu.c | 1 +
16
hw/timer/meson.build | 1 +
29
target/riscv/th_csr.c | 79 ++++++++++++++++++++++++++++++++++++++++
17
hw/timer/trace-events | 6 +
30
target/riscv/meson.build | 1 +
18
5 files changed, 540 insertions(+)
31
5 files changed, 85 insertions(+)
19
create mode 100644 include/hw/timer/sifive_pwm.h
32
create mode 100644 target/riscv/th_csr.c
20
create mode 100644 hw/timer/sifive_pwm.c
21
33
22
diff --git a/include/hw/timer/sifive_pwm.h b/include/hw/timer/sifive_pwm.h
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
23
new file mode 100644
71
new file mode 100644
24
index XXXXXXX..XXXXXXX
72
index XXXXXXX..XXXXXXX
25
--- /dev/null
73
--- /dev/null
26
+++ b/include/hw/timer/sifive_pwm.h
74
+++ b/target/riscv/th_csr.c
27
@@ -XXX,XX +XXX,XX @@
75
@@ -XXX,XX +XXX,XX @@
28
+/*
76
+/*
29
+ * SiFive PWM
77
+ * T-Head-specific CSRs.
30
+ *
78
+ *
31
+ * Copyright (c) 2020 Western Digital
79
+ * Copyright (c) 2024 VRULL GmbH
32
+ *
80
+ *
33
+ * Author: Alistair Francis <alistair.francis@wdc.com>
81
+ * This program is free software; you can redistribute it and/or modify it
82
+ * under the terms and conditions of the GNU General Public License,
83
+ * version 2 or later, as published by the Free Software Foundation.
34
+ *
84
+ *
35
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
85
+ * This program is distributed in the hope it will be useful, but WITHOUT
36
+ * of this software and associated documentation files (the "Software"), to deal
86
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
37
+ * in the Software without restriction, including without limitation the rights
87
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
38
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
88
+ * more details.
39
+ * copies of the Software, and to permit persons to whom the Software is
40
+ * furnished to do so, subject to the following conditions:
41
+ *
89
+ *
42
+ * The above copyright notice and this permission notice shall be included in
90
+ * You should have received a copy of the GNU General Public License along with
43
+ * all copies or substantial portions of the Software.
91
+ * this program. If not, see <http://www.gnu.org/licenses/>.
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.
52
+ */
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
+ */
92
+ */
121
+
93
+
122
+#include "qemu/osdep.h"
94
+#include "qemu/osdep.h"
123
+#include "trace.h"
95
+#include "cpu.h"
124
+#include "hw/irq.h"
96
+#include "cpu_vendorid.h"
125
+#include "hw/timer/sifive_pwm.h"
126
+#include "hw/qdev-properties.h"
127
+#include "hw/registerfields.h"
128
+#include "migration/vmstate.h"
129
+#include "qemu/log.h"
130
+#include "qemu/module.h"
131
+
97
+
132
+#define HAS_PWM_EN_BITS(cfg) ((cfg & R_CONFIG_ENONESHOT_MASK) || \
98
+#define CSR_TH_SXSTATUS 0x5c0
133
+ (cfg & R_CONFIG_ENALWAYS_MASK))
134
+
99
+
135
+#define PWMCMP_MASK 0xFFFF
100
+/* TH_SXSTATUS bits */
136
+#define PWMCOUNT_MASK 0x7FFFFFFF
101
+#define TH_SXSTATUS_UCME BIT(16)
102
+#define TH_SXSTATUS_MAEE BIT(21)
103
+#define TH_SXSTATUS_THEADISAEE BIT(22)
137
+
104
+
138
+REG32(CONFIG, 0x00)
105
+typedef struct {
139
+ FIELD(CONFIG, SCALE, 0, 4)
106
+ int csrno;
140
+ FIELD(CONFIG, STICKY, 8, 1)
107
+ int (*insertion_test)(RISCVCPU *cpu);
141
+ FIELD(CONFIG, ZEROCMP, 9, 1)
108
+ riscv_csr_operations csr_ops;
142
+ FIELD(CONFIG, DEGLITCH, 10, 1)
109
+} riscv_csr;
143
+ FIELD(CONFIG, ENALWAYS, 12, 1)
144
+ FIELD(CONFIG, ENONESHOT, 13, 1)
145
+ FIELD(CONFIG, CMP0CENTER, 16, 1)
146
+ FIELD(CONFIG, CMP1CENTER, 17, 1)
147
+ FIELD(CONFIG, CMP2CENTER, 18, 1)
148
+ FIELD(CONFIG, CMP3CENTER, 19, 1)
149
+ FIELD(CONFIG, CMP0GANG, 24, 1)
150
+ FIELD(CONFIG, CMP1GANG, 25, 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
+
110
+
164
+static inline uint64_t sifive_pwm_ns_to_ticks(SiFivePwmState *s,
111
+static RISCVException smode(CPURISCVState *env, int csrno)
165
+ uint64_t time)
166
+{
112
+{
167
+ return muldiv64(time, s->freq_hz, NANOSECONDS_PER_SECOND);
113
+ if (riscv_has_ext(env, RVS)) {
114
+ return RISCV_EXCP_NONE;
115
+ }
116
+
117
+ return RISCV_EXCP_ILLEGAL_INST;
168
+}
118
+}
169
+
119
+
170
+static inline uint64_t sifive_pwm_ticks_to_ns(SiFivePwmState *s,
120
+static int test_thead_mvendorid(RISCVCPU *cpu)
171
+ uint64_t ticks)
172
+{
121
+{
173
+ return muldiv64(ticks, NANOSECONDS_PER_SECOND, s->freq_hz);
122
+ if (cpu->cfg.mvendorid != THEAD_VENDOR_ID) {
174
+}
123
+ return -1;
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;
362
+ }
124
+ }
363
+
125
+
364
+ return 0;
126
+ return 0;
365
+}
127
+}
366
+
128
+
367
+static void sifive_pwm_write(void *opaque, hwaddr addr,
129
+static RISCVException read_th_sxstatus(CPURISCVState *env, int csrno,
368
+ uint64_t val64, unsigned int size)
130
+ target_ulong *val)
369
+{
131
+{
370
+ SiFivePwmState *s = opaque;
132
+ /* We don't set MAEE here, because QEMU does not implement MAEE. */
371
+ uint32_t value = val64;
133
+ *val = TH_SXSTATUS_UCME | TH_SXSTATUS_THEADISAEE;
372
+ uint64_t new_offset, scale;
134
+ return RISCV_EXCP_NONE;
373
+ uint64_t now = sifive_pwm_ns_to_ticks(s,
374
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
375
+
376
+ trace_sifive_pwm_write(value, addr);
377
+
378
+ switch (addr) {
379
+ case A_CONFIG:
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
+}
135
+}
468
+
136
+
469
+static void sifive_pwm_reset(DeviceState *dev)
137
+static riscv_csr th_csr_list[] = {
470
+{
138
+ {
471
+ SiFivePwmState *s = SIFIVE_PWM(dev);
139
+ .csrno = CSR_TH_SXSTATUS,
472
+ uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
140
+ .insertion_test = test_thead_mvendorid,
473
+
141
+ .csr_ops = { "th.sxstatus", smode, read_th_sxstatus }
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,
487
+};
488
+
489
+static const VMStateDescription vmstate_sifive_pwm = {
490
+ .name = TYPE_SIFIVE_PWM,
491
+ .version_id = 1,
492
+ .minimum_version_id = 1,
493
+ .fields = (VMStateField[]) {
494
+ VMSTATE_TIMER_ARRAY(timer, SiFivePwmState, 4),
495
+ VMSTATE_UINT64(tick_offset, SiFivePwmState),
496
+ VMSTATE_UINT32(pwmcfg, SiFivePwmState),
497
+ VMSTATE_UINT32_ARRAY(pwmcmp, SiFivePwmState, 4),
498
+ VMSTATE_END_OF_LIST()
499
+ }
142
+ }
500
+};
143
+};
501
+
144
+
502
+static Property sifive_pwm_properties[] = {
145
+void th_register_custom_csrs(RISCVCPU *cpu)
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
+{
146
+{
511
+ SiFivePwmState *s = SIFIVE_PWM(obj);
147
+ for (size_t i = 0; i < ARRAY_SIZE(th_csr_list); i++) {
512
+ int i;
148
+ int csrno = th_csr_list[i].csrno;
513
+
149
+ riscv_csr_operations *csr_ops = &th_csr_list[i].csr_ops;
514
+ for (i = 0; i < SIFIVE_PWM_IRQS; i++) {
150
+ if (!th_csr_list[i].insertion_test(cpu)) {
515
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irqs[i]);
151
+ riscv_set_csr_ops(csrno, csr_ops);
152
+ }
516
+ }
153
+ }
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
+}
154
+}
522
+
155
diff --git a/target/riscv/meson.build b/target/riscv/meson.build
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
565
index XXXXXXX..XXXXXXX 100644
156
index XXXXXXX..XXXXXXX 100644
566
--- a/hw/timer/Kconfig
157
--- a/target/riscv/meson.build
567
+++ b/hw/timer/Kconfig
158
+++ b/target/riscv/meson.build
568
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_A10_PIT
159
@@ -XXX,XX +XXX,XX @@ riscv_system_ss.add(files(
569
bool
160
'monitor.c',
570
select PTIMER
161
'machine.c',
571
162
'pmu.c',
572
+config SIFIVE_PWM
163
+ 'th_csr.c',
573
+ bool
164
'time_helper.c',
574
+
165
'riscv-qmp-cmds.c',
575
config STM32F2XX_TIMER
166
))
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
603
--
167
--
604
2.31.1
168
2.45.1
605
169
606
170
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@wdc.com>
1
From: Max Chou <max.chou@sifive.com>
2
2
3
Instead of using riscv_cpu_update_mip() let's instead use the new RISC-V
3
According v spec 18.4, only the vfwcvt.f.f.v and vfncvt.f.f.w
4
CPU GPIO lines to set the external MIP bits.
4
instructions will be affected by Zvfhmin extension.
5
And the vfwcvt.f.f.v and vfncvt.f.f.w instructions only support the
6
conversions of
5
7
8
* From 1*SEW(16/32) to 2*SEW(32/64)
9
* From 2*SEW(32/64) to 1*SEW(16/32)
10
11
Signed-off-by: Max Chou <max.chou@sifive.com>
12
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
13
Cc: qemu-stable <qemu-stable@nongnu.org>
14
Message-ID: <20240322092600.1198921-2-max.chou@sifive.com>
6
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
15
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: 0a76946981852f5bd15f0c37ab35b253371027a8.1630301632.git.alistair.francis@wdc.com
10
---
16
---
11
include/hw/intc/ibex_plic.h | 2 ++
17
target/riscv/insn_trans/trans_rvv.c.inc | 20 ++++++++++++++++++--
12
hw/intc/ibex_plic.c | 17 ++++++-----------
18
1 file changed, 18 insertions(+), 2 deletions(-)
13
hw/riscv/opentitan.c | 8 ++++++++
14
3 files changed, 16 insertions(+), 11 deletions(-)
15
19
16
diff --git a/include/hw/intc/ibex_plic.h b/include/hw/intc/ibex_plic.h
20
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
21
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/intc/ibex_plic.h
22
--- a/target/riscv/insn_trans/trans_rvv.c.inc
19
+++ b/include/hw/intc/ibex_plic.h
23
+++ b/target/riscv/insn_trans/trans_rvv.c.inc
20
@@ -XXX,XX +XXX,XX @@ struct IbexPlicState {
24
@@ -XXX,XX +XXX,XX @@ static bool require_rvf(DisasContext *s)
21
uint32_t threshold_base;
22
23
uint32_t claim_base;
24
+
25
+ qemu_irq *external_irqs;
26
};
27
28
#endif /* HW_IBEX_PLIC_H */
29
diff --git a/hw/intc/ibex_plic.c b/hw/intc/ibex_plic.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/intc/ibex_plic.c
32
+++ b/hw/intc/ibex_plic.c
33
@@ -XXX,XX +XXX,XX @@
34
#include "target/riscv/cpu_bits.h"
35
#include "target/riscv/cpu.h"
36
#include "hw/intc/ibex_plic.h"
37
+#include "hw/irq.h"
38
39
static bool addr_between(uint32_t addr, uint32_t base, uint32_t num)
40
{
41
@@ -XXX,XX +XXX,XX @@ static bool ibex_plic_irqs_pending(IbexPlicState *s, uint32_t context)
42
43
static void ibex_plic_update(IbexPlicState *s)
44
{
45
- CPUState *cpu;
46
- int level, i;
47
+ int i;
48
49
for (i = 0; i < s->num_cpus; i++) {
50
- cpu = qemu_get_cpu(i);
51
-
52
- if (!cpu) {
53
- continue;
54
- }
55
-
56
- level = ibex_plic_irqs_pending(s, 0);
57
-
58
- riscv_cpu_update_mip(RISCV_CPU(cpu), MIP_MEIP, BOOL_TO_MASK(level));
59
+ qemu_set_irq(s->external_irqs[i], ibex_plic_irqs_pending(s, 0));
60
}
25
}
61
}
26
}
62
27
63
@@ -XXX,XX +XXX,XX @@ static void ibex_plic_realize(DeviceState *dev, Error **errp)
28
+static bool require_rvfmin(DisasContext *s)
64
29
+{
65
qdev_init_gpio_in(dev, ibex_plic_irq_request, s->num_sources);
30
+ if (s->mstatus_fs == EXT_STATUS_DISABLED) {
66
31
+ return false;
67
+ s->external_irqs = g_malloc(sizeof(qemu_irq) * s->num_cpus);
68
+ qdev_init_gpio_out(dev, s->external_irqs, s->num_cpus);
69
+
70
/*
71
* We can't allow the supervisor to control SEIP as this would allow the
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));
94
+ }
32
+ }
95
+
33
+
96
/* UART */
34
+ switch (s->sew) {
97
qdev_prop_set_chr(DEVICE(&(s->uart)), "chardev", serial_hd(0));
35
+ case MO_16:
98
if (!sysbus_realize(SYS_BUS_DEVICE(&s->uart), errp)) {
36
+ return s->cfg_ptr->ext_zvfhmin;
37
+ case MO_32:
38
+ return s->cfg_ptr->ext_zve32f;
39
+ default:
40
+ return false;
41
+ }
42
+}
43
+
44
static bool require_scale_rvf(DisasContext *s)
45
{
46
if (s->mstatus_fs == EXT_STATUS_DISABLED) {
47
@@ -XXX,XX +XXX,XX @@ static bool require_scale_rvfmin(DisasContext *s)
48
}
49
50
switch (s->sew) {
51
- case MO_8:
52
- return s->cfg_ptr->ext_zvfhmin;
53
case MO_16:
54
return s->cfg_ptr->ext_zve32f;
55
case MO_32:
56
@@ -XXX,XX +XXX,XX @@ static bool opxfv_widen_check(DisasContext *s, arg_rmr *a)
57
static bool opffv_widen_check(DisasContext *s, arg_rmr *a)
58
{
59
return opfv_widen_check(s, a) &&
60
+ require_rvfmin(s) &&
61
require_scale_rvfmin(s) &&
62
(s->sew != MO_8);
63
}
64
@@ -XXX,XX +XXX,XX @@ static bool opfxv_narrow_check(DisasContext *s, arg_rmr *a)
65
static bool opffv_narrow_check(DisasContext *s, arg_rmr *a)
66
{
67
return opfv_narrow_check(s, a) &&
68
+ require_rvfmin(s) &&
69
require_scale_rvfmin(s) &&
70
(s->sew != MO_8);
71
}
99
--
72
--
100
2.31.1
73
2.45.1
101
102
diff view generated by jsdifflib
1
From: Anup Patel <anup.patel@wdc.com>
1
From: Max Chou <max.chou@sifive.com>
2
2
3
We will be upgrading SiFive CLINT implementation into RISC-V ACLINT
3
The require_scale_rvf function only checks the double width operator for
4
implementation so let's first rename the sources.
4
the vector floating point widen instructions, so most of the widen
5
checking functions need to add require_rvf for single width operator.
5
6
6
Signed-off-by: Anup Patel <anup.patel@wdc.com>
7
The vfwcvt.f.x.v and vfwcvt.f.xu.v instructions convert single width
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
integer to double width float, so the opfxv_widen_check function doesn’t
8
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
9
need require_rvf for the single width operator(integer).
9
Message-id: 20210831110603.338681-2-anup.patel@wdc.com
10
11
Signed-off-by: Max Chou <max.chou@sifive.com>
12
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
13
Cc: qemu-stable <qemu-stable@nongnu.org>
14
Message-ID: <20240322092600.1198921-3-max.chou@sifive.com>
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
15
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
---
16
---
12
include/hw/intc/{sifive_clint.h => riscv_aclint.h} | 0
17
target/riscv/insn_trans/trans_rvv.c.inc | 5 +++++
13
hw/intc/{sifive_clint.c => riscv_aclint.c} | 2 +-
18
1 file changed, 5 insertions(+)
14
hw/riscv/microchip_pfsoc.c | 2 +-
15
hw/riscv/shakti_c.c | 2 +-
16
hw/riscv/sifive_e.c | 2 +-
17
hw/riscv/sifive_u.c | 2 +-
18
hw/riscv/spike.c | 2 +-
19
hw/riscv/virt.c | 2 +-
20
hw/intc/Kconfig | 2 +-
21
hw/intc/meson.build | 2 +-
22
hw/riscv/Kconfig | 12 ++++++------
23
11 files changed, 15 insertions(+), 15 deletions(-)
24
rename include/hw/intc/{sifive_clint.h => riscv_aclint.h} (100%)
25
rename hw/intc/{sifive_clint.c => riscv_aclint.c} (99%)
26
19
27
diff --git a/include/hw/intc/sifive_clint.h b/include/hw/intc/riscv_aclint.h
20
diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc
28
similarity index 100%
29
rename from include/hw/intc/sifive_clint.h
30
rename to include/hw/intc/riscv_aclint.h
31
diff --git a/hw/intc/sifive_clint.c b/hw/intc/riscv_aclint.c
32
similarity index 99%
33
rename from hw/intc/sifive_clint.c
34
rename to hw/intc/riscv_aclint.c
35
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
36
--- a/hw/intc/sifive_clint.c
22
--- a/target/riscv/insn_trans/trans_rvv.c.inc
37
+++ b/hw/intc/riscv_aclint.c
23
+++ b/target/riscv/insn_trans/trans_rvv.c.inc
38
@@ -XXX,XX +XXX,XX @@
24
@@ -XXX,XX +XXX,XX @@ GEN_OPFVF_TRANS(vfrsub_vf, opfvf_check)
39
#include "hw/sysbus.h"
25
static bool opfvv_widen_check(DisasContext *s, arg_rmrr *a)
40
#include "target/riscv/cpu.h"
26
{
41
#include "hw/qdev-properties.h"
27
return require_rvv(s) &&
42
-#include "hw/intc/sifive_clint.h"
28
+ require_rvf(s) &&
43
+#include "hw/intc/riscv_aclint.h"
29
require_scale_rvf(s) &&
44
#include "qemu/timer.h"
30
(s->sew != MO_8) &&
45
#include "hw/irq.h"
31
vext_check_isa_ill(s) &&
46
32
@@ -XXX,XX +XXX,XX @@ GEN_OPFVV_WIDEN_TRANS(vfwsub_vv, opfvv_widen_check)
47
diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
33
static bool opfvf_widen_check(DisasContext *s, arg_rmrr *a)
48
index XXXXXXX..XXXXXXX 100644
34
{
49
--- a/hw/riscv/microchip_pfsoc.c
35
return require_rvv(s) &&
50
+++ b/hw/riscv/microchip_pfsoc.c
36
+ require_rvf(s) &&
51
@@ -XXX,XX +XXX,XX @@
37
require_scale_rvf(s) &&
52
#include "hw/riscv/boot.h"
38
(s->sew != MO_8) &&
53
#include "hw/riscv/riscv_hart.h"
39
vext_check_isa_ill(s) &&
54
#include "hw/riscv/microchip_pfsoc.h"
40
@@ -XXX,XX +XXX,XX @@ GEN_OPFVF_WIDEN_TRANS(vfwsub_vf)
55
-#include "hw/intc/sifive_clint.h"
41
static bool opfwv_widen_check(DisasContext *s, arg_rmrr *a)
56
+#include "hw/intc/riscv_aclint.h"
42
{
57
#include "hw/intc/sifive_plic.h"
43
return require_rvv(s) &&
58
#include "sysemu/device_tree.h"
44
+ require_rvf(s) &&
59
#include "sysemu/sysemu.h"
45
require_scale_rvf(s) &&
60
diff --git a/hw/riscv/shakti_c.c b/hw/riscv/shakti_c.c
46
(s->sew != MO_8) &&
61
index XXXXXXX..XXXXXXX 100644
47
vext_check_isa_ill(s) &&
62
--- a/hw/riscv/shakti_c.c
48
@@ -XXX,XX +XXX,XX @@ GEN_OPFWV_WIDEN_TRANS(vfwsub_wv)
63
+++ b/hw/riscv/shakti_c.c
49
static bool opfwf_widen_check(DisasContext *s, arg_rmrr *a)
64
@@ -XXX,XX +XXX,XX @@
50
{
65
#include "hw/riscv/shakti_c.h"
51
return require_rvv(s) &&
66
#include "qapi/error.h"
52
+ require_rvf(s) &&
67
#include "hw/intc/sifive_plic.h"
53
require_scale_rvf(s) &&
68
-#include "hw/intc/sifive_clint.h"
54
(s->sew != MO_8) &&
69
+#include "hw/intc/riscv_aclint.h"
55
vext_check_isa_ill(s) &&
70
#include "sysemu/sysemu.h"
56
@@ -XXX,XX +XXX,XX @@ GEN_OPFVV_TRANS(vfredmin_vs, freduction_check)
71
#include "hw/qdev-properties.h"
57
static bool freduction_widen_check(DisasContext *s, arg_rmrr *a)
72
#include "exec/address-spaces.h"
58
{
73
diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
59
return reduction_widen_check(s, a) &&
74
index XXXXXXX..XXXXXXX 100644
60
+ require_rvf(s) &&
75
--- a/hw/riscv/sifive_e.c
61
require_scale_rvf(s) &&
76
+++ b/hw/riscv/sifive_e.c
62
(s->sew != MO_8);
77
@@ -XXX,XX +XXX,XX @@
63
}
78
#include "hw/riscv/sifive_e.h"
79
#include "hw/riscv/boot.h"
80
#include "hw/char/sifive_uart.h"
81
-#include "hw/intc/sifive_clint.h"
82
+#include "hw/intc/riscv_aclint.h"
83
#include "hw/intc/sifive_plic.h"
84
#include "hw/misc/sifive_e_prci.h"
85
#include "chardev/char.h"
86
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/hw/riscv/sifive_u.c
89
+++ b/hw/riscv/sifive_u.c
90
@@ -XXX,XX +XXX,XX @@
91
#include "hw/riscv/sifive_u.h"
92
#include "hw/riscv/boot.h"
93
#include "hw/char/sifive_uart.h"
94
-#include "hw/intc/sifive_clint.h"
95
+#include "hw/intc/riscv_aclint.h"
96
#include "hw/intc/sifive_plic.h"
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
207
--
64
--
208
2.31.1
65
2.45.1
209
66
210
67
diff view generated by jsdifflib
New patch
1
From: Max Chou <max.chou@sifive.com>
1
2
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
1
From: Anup Patel <anup.patel@wdc.com>
1
From: Max Chou <max.chou@sifive.com>
2
2
3
We extend virt machine to emulate ACLINT devices only when "aclint=on"
3
If the checking functions check both the single and double width
4
parameter is passed along with machine name in QEMU command-line.
4
operators at the same time, then the single width operator checking
5
functions (require_rvf[min]) will check whether the SEW is 8.
5
6
6
Signed-off-by: Anup Patel <anup.patel@wdc.com>
7
Signed-off-by: Max Chou <max.chou@sifive.com>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
8
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
9
Cc: qemu-stable <qemu-stable@nongnu.org>
9
Message-id: 20210831110603.338681-5-anup.patel@wdc.com
10
Message-ID: <20240322092600.1198921-5-max.chou@sifive.com>
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
---
12
---
12
docs/system/riscv/virt.rst | 10 ++++
13
target/riscv/insn_trans/trans_rvv.c.inc | 16 ++++------------
13
include/hw/riscv/virt.h | 2 +
14
1 file changed, 4 insertions(+), 12 deletions(-)
14
hw/riscv/virt.c | 113 ++++++++++++++++++++++++++++++++++++-
15
3 files changed, 124 insertions(+), 1 deletion(-)
16
15
17
diff --git a/docs/system/riscv/virt.rst b/docs/system/riscv/virt.rst
16
diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
19
--- a/docs/system/riscv/virt.rst
18
--- a/target/riscv/insn_trans/trans_rvv.c.inc
20
+++ b/docs/system/riscv/virt.rst
19
+++ b/target/riscv/insn_trans/trans_rvv.c.inc
21
@@ -XXX,XX +XXX,XX @@ with the default OpenSBI firmware image as the -bios. It also supports
20
@@ -XXX,XX +XXX,XX @@ static bool opfvv_widen_check(DisasContext *s, arg_rmrr *a)
22
the recommended RISC-V bootflow: U-Boot SPL (M-mode) loads OpenSBI fw_dynamic
21
return require_rvv(s) &&
23
firmware and U-Boot proper (S-mode), using the standard -bios functionality.
22
require_rvf(s) &&
24
23
require_scale_rvf(s) &&
25
+Machine-specific options
24
- (s->sew != MO_8) &&
26
+------------------------
25
vext_check_isa_ill(s) &&
27
+
26
vext_check_dss(s, a->rd, a->rs1, a->rs2, a->vm);
28
+The following machine-specific options are supported:
29
+
30
+- aclint=[on|off]
31
+
32
+ When this option is "on", ACLINT devices will be emulated instead of
33
+ SiFive CLINT. When not specified, this option is assumed to be "off".
34
+
35
Running Linux kernel
36
--------------------
37
38
diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
39
index XXXXXXX..XXXXXXX 100644
40
--- a/include/hw/riscv/virt.h
41
+++ b/include/hw/riscv/virt.h
42
@@ -XXX,XX +XXX,XX @@ struct RISCVVirtState {
43
FWCfgState *fw_cfg;
44
45
int fdt_size;
46
+ bool have_aclint;
47
};
48
49
enum {
50
@@ -XXX,XX +XXX,XX @@ enum {
51
VIRT_TEST,
52
VIRT_RTC,
53
VIRT_CLINT,
54
+ VIRT_ACLINT_SSWI,
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
}
27
}
73
28
@@ -XXX,XX +XXX,XX @@ static bool opfvf_widen_check(DisasContext *s, arg_rmrr *a)
74
+static void create_fdt_socket_aclint(RISCVVirtState *s,
29
return require_rvv(s) &&
75
+ const MemMapEntry *memmap, int socket,
30
require_rvf(s) &&
76
+ uint32_t *intc_phandles)
31
require_scale_rvf(s) &&
77
+{
32
- (s->sew != MO_8) &&
78
+ int cpu;
33
vext_check_isa_ill(s) &&
79
+ char *name;
34
vext_check_ds(s, a->rd, a->rs2, a->vm);
80
+ unsigned long addr;
35
}
81
+ uint32_t aclint_cells_size;
36
@@ -XXX,XX +XXX,XX @@ static bool opfwv_widen_check(DisasContext *s, arg_rmrr *a)
82
+ uint32_t *aclint_mswi_cells;
37
return require_rvv(s) &&
83
+ uint32_t *aclint_sswi_cells;
38
require_rvf(s) &&
84
+ uint32_t *aclint_mtimer_cells;
39
require_scale_rvf(s) &&
85
+ MachineState *mc = MACHINE(s);
40
- (s->sew != MO_8) &&
86
+
41
vext_check_isa_ill(s) &&
87
+ aclint_mswi_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2);
42
vext_check_dds(s, a->rd, a->rs1, a->rs2, a->vm);
88
+ aclint_mtimer_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2);
43
}
89
+ aclint_sswi_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2);
44
@@ -XXX,XX +XXX,XX @@ static bool opfwf_widen_check(DisasContext *s, arg_rmrr *a)
90
+
45
return require_rvv(s) &&
91
+ for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) {
46
require_rvf(s) &&
92
+ aclint_mswi_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
47
require_scale_rvf(s) &&
93
+ aclint_mswi_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_M_SOFT);
48
- (s->sew != MO_8) &&
94
+ aclint_mtimer_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
49
vext_check_isa_ill(s) &&
95
+ aclint_mtimer_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_M_TIMER);
50
vext_check_dd(s, a->rd, a->rs2, a->vm);
96
+ aclint_sswi_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
51
}
97
+ aclint_sswi_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_S_SOFT);
52
@@ -XXX,XX +XXX,XX @@ static bool opffv_widen_check(DisasContext *s, arg_rmr *a)
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)
182
{
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);
183
}
59
}
184
60
185
+static bool virt_get_aclint(Object *obj, Error **errp)
61
#define GEN_OPFV_WIDEN_TRANS(NAME, CHECK, HELPER, FRM) \
186
+{
62
@@ -XXX,XX +XXX,XX @@ static bool opffv_narrow_check(DisasContext *s, arg_rmr *a)
187
+ MachineState *ms = MACHINE(obj);
188
+ RISCVVirtState *s = RISCV_VIRT_MACHINE(ms);
189
+
190
+ return s->have_aclint;
191
+}
192
+
193
+static void virt_set_aclint(Object *obj, bool value, Error **errp)
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)
202
{
63
{
203
MachineClass *mc = MACHINE_CLASS(oc);
64
return opfv_narrow_check(s, a) &&
204
@@ -XXX,XX +XXX,XX @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
65
require_rvfmin(s) &&
205
mc->numa_mem_supported = true;
66
- require_scale_rvfmin(s) &&
206
67
- (s->sew != MO_8);
207
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
68
+ require_scale_rvfmin(s);
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");
214
}
69
}
215
70
216
static const TypeInfo virt_machine_typeinfo = {
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)
217
--
91
--
218
2.31.1
92
2.45.1
219
220
diff view generated by jsdifflib
New patch
1
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
1
2
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
1
From: Frank Chang <frank.chang@sifive.com>
1
From: Alexei Filippov <alexei.filippov@syntacore.com>
2
2
3
When virtual registers are swapped, mstatus.SD bit should also be
3
Previous patch fixed the PMP priority in raise_mmu_exception() but we're still
4
backed up/restored. Otherwise, mstatus.SD bit will be incorrectly kept
4
setting mtval2 incorrectly. In riscv_cpu_tlb_fill(), after pmp check in 2 stage
5
across the world switches.
5
translation part, mtval2 will be set in case of successes 2 stage translation but
6
failed pmp check.
6
7
7
Signed-off-by: Frank Chang <frank.chang@sifive.com>
8
In this case we gonna set mtval2 via env->guest_phys_fault_addr in context of
8
Reviewed-by: Vincent Chen <vincent.chen@sifive.com>
9
riscv_cpu_tlb_fill(), as this was a guest-page-fault, but it didn't and mtval2
10
should be zero, according to RISCV privileged spec sect. 9.4.4: When a guest
11
page-fault is taken into M-mode, mtval2 is written with either zero or guest
12
physical address that faulted, shifted by 2 bits. *For other traps, mtval2
13
is set to zero...*
14
15
Signed-off-by: Alexei Filippov <alexei.filippov@syntacore.com>
16
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
17
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Message-id: 20210914013717.881430-1-frank.chang@sifive.com
18
Message-ID: <20240503103052.6819-1-alexei.filippov@syntacore.com>
19
Cc: qemu-stable <qemu-stable@nongnu.org>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
20
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
---
21
---
13
target/riscv/cpu_helper.c | 3 ++-
22
target/riscv/cpu_helper.c | 12 ++++++------
14
1 file changed, 2 insertions(+), 1 deletion(-)
23
1 file changed, 6 insertions(+), 6 deletions(-)
15
24
16
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
25
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
17
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
18
--- a/target/riscv/cpu_helper.c
27
--- a/target/riscv/cpu_helper.c
19
+++ b/target/riscv/cpu_helper.c
28
+++ b/target/riscv/cpu_helper.c
20
@@ -XXX,XX +XXX,XX @@ bool riscv_cpu_fp_enabled(CPURISCVState *env)
29
@@ -XXX,XX +XXX,XX @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
21
30
__func__, pa, ret, prot_pmp, tlb_size);
22
void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env)
31
23
{
32
prot &= prot_pmp;
24
+ target_ulong sd = riscv_cpu_is_32bit(env) ? MSTATUS32_SD : MSTATUS64_SD;
33
- }
25
uint64_t mstatus_mask = MSTATUS_MXR | MSTATUS_SUM | MSTATUS_FS |
34
-
26
MSTATUS_SPP | MSTATUS_SPIE | MSTATUS_SIE |
35
- if (ret != TRANSLATE_SUCCESS) {
27
- MSTATUS64_UXL;
36
+ } else {
28
+ MSTATUS64_UXL | sd;
37
/*
29
bool current_virt = riscv_cpu_virt_enabled(env);
38
* Guest physical address translation failed, this is a HS
30
39
* level exception
31
g_assert(riscv_has_ext(env, RVH));
40
*/
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 {
32
--
53
--
33
2.31.1
54
2.45.1
34
35
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@wdc.com>
1
From: Rob Bradford <rbradford@rivosinc.com>
2
2
3
Instead of using riscv_cpu_update_mip() let's instead use the new RISC-V
3
This extension has now been ratified:
4
CPU GPIO lines to set the external MIP bits.
4
https://jira.riscv.org/browse/RVS-2006 so the "x-" prefix can be
5
removed.
5
6
7
Since this is now a ratified extension add it to the list of extensions
8
included in the "max" CPU variant.
9
10
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
11
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
12
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
13
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
14
Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
15
Message-ID: <20240514110217.22516-1-rbradford@rivosinc.com>
6
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
16
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
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
10
Tested-by: Bin Meng <bmeng.cn@gmail.com>
11
Message-id: 0364190bfa935058a845c0fa1ecf650328840ad5.1630301632.git.alistair.francis@wdc.com
12
---
17
---
13
include/hw/intc/sifive_plic.h | 4 ++++
18
target/riscv/cpu.c | 2 +-
14
hw/intc/sifive_plic.c | 30 +++++++++++++++++++++++-------
19
target/riscv/tcg/tcg-cpu.c | 2 +-
15
hw/riscv/microchip_pfsoc.c | 2 +-
20
2 files changed, 2 insertions(+), 2 deletions(-)
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(-)
21
21
22
diff --git a/include/hw/intc/sifive_plic.h b/include/hw/intc/sifive_plic.h
22
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
23
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
24
--- a/include/hw/intc/sifive_plic.h
24
--- a/target/riscv/cpu.c
25
+++ b/include/hw/intc/sifive_plic.h
25
+++ b/target/riscv/cpu.c
26
@@ -XXX,XX +XXX,XX @@ struct SiFivePLICState {
26
@@ -XXX,XX +XXX,XX @@ static const MISAExtInfo misa_ext_info_arr[] = {
27
uint32_t context_base;
27
MISA_EXT_INFO(RVJ, "x-j", "Dynamic translated languages"),
28
uint32_t context_stride;
28
MISA_EXT_INFO(RVV, "v", "Vector operations"),
29
uint32_t aperture_size;
29
MISA_EXT_INFO(RVG, "g", "General purpose (IMAFD_Zicsr_Zifencei)"),
30
+
30
- MISA_EXT_INFO(RVB, "x-b", "Bit manipulation (Zba_Zbb_Zbs)")
31
+ qemu_irq *m_external_irqs;
31
+ MISA_EXT_INFO(RVB, "b", "Bit manipulation (Zba_Zbb_Zbs)")
32
+ qemu_irq *s_external_irqs;
33
};
32
};
34
33
35
DeviceState *sifive_plic_create(hwaddr addr, char *hart_config,
34
static void riscv_cpu_validate_misa_mxl(RISCVCPUClass *mcc)
36
+ uint32_t num_harts,
35
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
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
36
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/intc/sifive_plic.c
37
--- a/target/riscv/tcg/tcg-cpu.c
43
+++ b/hw/intc/sifive_plic.c
38
+++ b/target/riscv/tcg/tcg-cpu.c
44
@@ -XXX,XX +XXX,XX @@
39
@@ -XXX,XX +XXX,XX @@ static void riscv_init_max_cpu_extensions(Object *obj)
45
#include "hw/intc/sifive_plic.h"
40
const RISCVCPUMultiExtConfig *prop;
46
#include "target/riscv/cpu.h"
41
47
#include "migration/vmstate.h"
42
/* Enable RVG, RVJ and RVV that are disabled by default */
48
+#include "hw/irq.h"
43
- riscv_cpu_set_misa_ext(env, env->misa_ext | RVG | RVJ | RVV);
49
44
+ riscv_cpu_set_misa_ext(env, env->misa_ext | RVB | RVG | RVJ | RVV);
50
#define RISCV_DEBUG_PLIC 0
45
51
46
for (prop = riscv_cpu_extensions; prop && prop->name; prop++) {
52
@@ -XXX,XX +XXX,XX @@ static void sifive_plic_update(SiFivePLICState *plic)
47
isa_ext_update_enabled(cpu, prop->offset, true);
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));
116
+ }
117
+
118
return dev;
119
}
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,
192
--
48
--
193
2.31.1
49
2.45.1
194
195
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@wdc.com>
1
From: Alistair Francis <alistair23@gmail.com>
2
2
3
Connect the SiFive PWM device and expose it via the device tree.
3
When running the instruction
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.
4
26
5
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
27
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
6
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
28
Reported-by: Fabian Thomas <fabian.thomas@cispa.de>
7
Message-id: 22f98648b4e012f78529a56f5ca60b0b27852a4d.1631159656.git.alistair.francis@wdc.com
29
Fixes: e05da09b7cfd ("target/riscv: implement Zicbom extension")
30
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
31
Cc: qemu-stable <qemu-stable@nongnu.org>
32
Message-ID: <20240514023910.301766-1-alistair.francis@wdc.com>
33
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
8
---
34
---
9
docs/system/riscv/sifive_u.rst | 1 +
35
target/riscv/insn_trans/trans_rvzicbo.c.inc | 16 ++++++++++++----
10
include/hw/riscv/sifive_u.h | 14 ++++++++-
36
1 file changed, 12 insertions(+), 4 deletions(-)
11
hw/riscv/sifive_u.c | 55 +++++++++++++++++++++++++++++++++-
12
hw/riscv/Kconfig | 1 +
13
4 files changed, 69 insertions(+), 2 deletions(-)
14
37
15
diff --git a/docs/system/riscv/sifive_u.rst b/docs/system/riscv/sifive_u.rst
38
diff --git a/target/riscv/insn_trans/trans_rvzicbo.c.inc b/target/riscv/insn_trans/trans_rvzicbo.c.inc
16
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
17
--- a/docs/system/riscv/sifive_u.rst
40
--- a/target/riscv/insn_trans/trans_rvzicbo.c.inc
18
+++ b/docs/system/riscv/sifive_u.rst
41
+++ b/target/riscv/insn_trans/trans_rvzicbo.c.inc
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
31
@@ -XXX,XX +XXX,XX @@
42
@@ -XXX,XX +XXX,XX @@
32
#include "hw/misc/sifive_u_otp.h"
43
static bool trans_cbo_clean(DisasContext *ctx, arg_cbo_clean *a)
33
#include "hw/misc/sifive_u_prci.h"
44
{
34
#include "hw/ssi/sifive_spi.h"
45
REQUIRE_ZICBOM(ctx);
35
+#include "hw/timer/sifive_pwm.h"
46
- gen_helper_cbo_clean_flush(tcg_env, cpu_gpr[a->rs1]);
36
47
+ TCGv src = get_address(ctx, a->rs1, 0);
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);
113
+
48
+
114
+ nodename = g_strdup_printf("/soc/pwm@%lx",
49
+ gen_helper_cbo_clean_flush(tcg_env, src);
115
+ (long)memmap[SIFIVE_U_DEV_PWM1].base);
50
return true;
116
+ qemu_fdt_add_subnode(fdt, nodename);
51
}
117
+ qemu_fdt_setprop_string(fdt, nodename, "compatible", "sifive,pwm0");
52
118
+ qemu_fdt_setprop_cells(fdt, nodename, "reg",
53
static bool trans_cbo_flush(DisasContext *ctx, arg_cbo_flush *a)
119
+ 0x0, memmap[SIFIVE_U_DEV_PWM1].base,
54
{
120
+ 0x0, memmap[SIFIVE_U_DEV_PWM1].size);
55
REQUIRE_ZICBOM(ctx);
121
+ qemu_fdt_setprop_cell(fdt, nodename, "interrupt-parent", plic_phandle);
56
- gen_helper_cbo_clean_flush(tcg_env, cpu_gpr[a->rs1]);
122
+ qemu_fdt_setprop_cells(fdt, nodename, "interrupts",
57
+ TCGv src = get_address(ctx, a->rs1, 0);
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
+
58
+
130
nodename = g_strdup_printf("/soc/serial@%lx",
59
+ gen_helper_cbo_clean_flush(tcg_env, src);
131
(long)memmap[SIFIVE_U_DEV_UART1].base);
60
return true;
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);
139
}
61
}
140
62
141
static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
63
static bool trans_cbo_inval(DisasContext *ctx, arg_cbo_inval *a)
142
@@ -XXX,XX +XXX,XX @@ static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
64
{
143
MemoryRegion *l2lim_mem = g_new(MemoryRegion, 1);
65
REQUIRE_ZICBOM(ctx);
144
char *plic_hart_config;
66
- gen_helper_cbo_inval(tcg_env, cpu_gpr[a->rs1]);
145
size_t plic_hart_config_len;
67
+ TCGv src = get_address(ctx, a->rs1, 0);
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));
162
+
68
+
163
+ /* Connect PWM interrupts to the PLIC */
69
+ gen_helper_cbo_inval(tcg_env, src);
164
+ for (j = 0; j < SIFIVE_PWM_IRQS; j++) {
70
return true;
165
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->pwm[i]), j,
71
}
166
+ qdev_get_gpio_in(DEVICE(s->plic),
72
167
+ SIFIVE_U_PWM0_IRQ0 + (i * 4) + j));
73
static bool trans_cbo_zero(DisasContext *ctx, arg_cbo_zero *a)
168
+ }
74
{
169
+ }
75
REQUIRE_ZICBOZ(ctx);
76
- gen_helper_cbo_zero(tcg_env, cpu_gpr[a->rs1]);
77
+ TCGv src = get_address(ctx, a->rs1, 0);
170
+
78
+
171
create_unimplemented_device("riscv.sifive.u.gem-mgmt",
79
+ gen_helper_cbo_zero(tcg_env, src);
172
memmap[SIFIVE_U_DEV_GEM_MGMT].base, memmap[SIFIVE_U_DEV_GEM_MGMT].size);
80
return true;
173
81
}
174
diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
175
index XXXXXXX..XXXXXXX 100644
176
--- a/hw/riscv/Kconfig
177
+++ b/hw/riscv/Kconfig
178
@@ -XXX,XX +XXX,XX @@ config SIFIVE_U
179
select SIFIVE_UART
180
select SIFIVE_U_OTP
181
select SIFIVE_U_PRCI
182
+ select SIFIVE_PWM
183
select SSI_M25P80
184
select SSI_SD
185
select UNIMP
186
--
82
--
187
2.31.1
83
2.45.1
188
189
diff view generated by jsdifflib
1
From: Green Wan <green.wan@sifive.com>
1
From: Yong-Xuan Wang <yongxuan.wang@sifive.com>
2
2
3
Real PDMA is able to deal with non-multiple transaction size transactions.
3
In AIA spec, each hart (or each hart within a group) has a unique hart
4
number to locate the memory pages of interrupt files in the address
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.
4
8
5
The following result is PDMA tested in U-Boot on Unmatched board:
9
However, if the largest hart number among groups is a power of 2, QEMU
10
will pass an inaccurate hart-index-bit setting to Linux. For example, when
11
the guest OS has 4 harts, only ceil(log2(3 + 1)) = 2 bits are sufficient
12
to represent 4 harts, but we passes 3 to Linux. The code needs to be
13
updated to ensure accurate hart-index-bit settings.
6
14
7
=> mw.l 0x3000000 0x0 <= Disclaim channel 0
15
Additionally, a Linux patch[1] is necessary to correctly recover the hart
8
=> mw.l 0x3000000 0x1 <= Claim channel 0
16
index when the guest OS has only 1 hart, where the hart-index-bit is 0.
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
17
29
Signed-off-by: Green Wan <green.wan@sifive.com>
18
[1] https://lore.kernel.org/lkml/20240415064905.25184-1-yongxuan.wang@sifive.com/t/
30
Reviewed-by: Frank Chang <frank.chang@sifive.com>
19
31
Tested-by: Max Hsu <max.hsu@sifive.com>
20
Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com>
32
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
21
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
33
Tested-by: Bin Meng <bmeng.cn@gmail.com>
22
Cc: qemu-stable <qemu-stable@nongnu.org>
34
Signed-off-by: Frank Chang <frank.chang@sifive.com>
23
Message-ID: <20240515091129.28116-1-yongxuan.wang@sifive.com>
35
Message-id: 20210912130553.179501-4-frank.chang@sifive.com
36
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
24
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
37
---
25
---
38
hw/dma/sifive_pdma.c | 16 ++++++++++------
26
target/riscv/kvm/kvm-cpu.c | 9 ++++++++-
39
1 file changed, 10 insertions(+), 6 deletions(-)
27
1 file changed, 8 insertions(+), 1 deletion(-)
40
28
41
diff --git a/hw/dma/sifive_pdma.c b/hw/dma/sifive_pdma.c
29
diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
42
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
43
--- a/hw/dma/sifive_pdma.c
31
--- a/target/riscv/kvm/kvm-cpu.c
44
+++ b/hw/dma/sifive_pdma.c
32
+++ b/target/riscv/kvm/kvm-cpu.c
45
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_run(SiFivePDMAState *s, int ch)
33
@@ -XXX,XX +XXX,XX @@ void kvm_riscv_aia_create(MachineState *machine, uint64_t group_shift,
46
uint64_t dst = s->chan[ch].next_dst;
34
}
47
uint64_t src = s->chan[ch].next_src;
48
uint32_t config = s->chan[ch].next_config;
49
- int wsize, rsize, size;
50
+ int wsize, rsize, size, remainder;
51
uint8_t buf[64];
52
int n;
53
54
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_run(SiFivePDMAState *s, int ch)
55
size = 6;
56
}
35
}
57
size = 1 << size;
36
58
-
37
- hart_bits = find_last_bit(&max_hart_per_socket, BITS_PER_LONG) + 1;
59
- /* the bytes to transfer should be multiple of transaction size */
38
+
60
- if (bytes % size) {
39
+ if (max_hart_per_socket > 1) {
61
- goto error;
40
+ max_hart_per_socket--;
62
- }
41
+ hart_bits = find_last_bit(&max_hart_per_socket, BITS_PER_LONG) + 1;
63
+ remainder = bytes % size;
42
+ } else {
64
43
+ hart_bits = 0;
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;
69
}
70
71
+ if (remainder) {
72
+ cpu_physical_memory_read(s->chan[ch].exec_src, buf, remainder);
73
+ cpu_physical_memory_write(s->chan[ch].exec_dst, buf, remainder);
74
+ s->chan[ch].exec_src += remainder;
75
+ s->chan[ch].exec_dst += remainder;
76
+ s->chan[ch].exec_bytes -= remainder;
77
+ }
44
+ }
78
+
45
+
79
/* indicate a DMA transfer is done */
46
ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
80
s->chan[ch].state = DMA_CHAN_STATE_DONE;
47
KVM_DEV_RISCV_AIA_CONFIG_HART_BITS,
81
s->chan[ch].control &= ~CONTROL_RUN;
48
&hart_bits, true, NULL);
82
--
49
--
83
2.31.1
50
2.45.1
84
85
diff view generated by jsdifflib
1
From: Frank Chang <frank.chang@sifive.com>
1
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
2
2
3
Setting Control.claim clears all of the chanel's Next registers.
3
Commit 33a24910ae changed 'reg_width' to use 'vlenb', i.e. vector length
4
This is effective only when Control.claim is set from 0 to 1.
4
in bytes, when in this context we want 'reg_width' as the length in
5
bits.
5
6
6
Signed-off-by: Frank Chang <frank.chang@sifive.com>
7
Fix 'reg_width' back to the value in bits like 7cb59921c05a
7
Tested-by: Max Hsu <max.hsu@sifive.com>
8
("target/riscv/gdbstub.c: use 'vlenb' instead of shifting 'vlen'") set
8
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
9
beforehand.
9
Tested-by: Bin Meng <bmeng.cn@gmail.com>
10
10
Message-id: 20210912130553.179501-2-frank.chang@sifive.com
11
While we're at it, rename 'reg_width' to 'bitsize' to provide a bit more
12
clarity about what the variable represents. 'bitsize' is also used in
13
riscv_gen_dynamic_csr_feature() with the same purpose, i.e. as an input to
14
gdb_feature_builder_append_reg().
15
16
Cc: Akihiko Odaki <akihiko.odaki@daynix.com>
17
Cc: Alex Bennée <alex.bennee@linaro.org>
18
Reported-by: Robin Dapp <rdapp.gcc@gmail.com>
19
Fixes: 33a24910ae ("target/riscv: Use GDBFeature for dynamic XML")
20
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
21
Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
22
Acked-by: Alex Bennée <alex.bennee@linaro.org>
23
Reviewed-by: Akihiko Odaki <akihiko.odaki@daynix.com>
24
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
25
Cc: qemu-stable <qemu-stable@nongnu.org>
26
Message-ID: <20240517203054.880861-2-dbarboza@ventanamicro.com>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
27
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
---
28
---
13
hw/dma/sifive_pdma.c | 19 +++++++++++++++++++
29
target/riscv/gdbstub.c | 6 +++---
14
1 file changed, 19 insertions(+)
30
1 file changed, 3 insertions(+), 3 deletions(-)
15
31
16
diff --git a/hw/dma/sifive_pdma.c b/hw/dma/sifive_pdma.c
32
diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
17
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/dma/sifive_pdma.c
34
--- a/target/riscv/gdbstub.c
19
+++ b/hw/dma/sifive_pdma.c
35
+++ b/target/riscv/gdbstub.c
20
@@ -XXX,XX +XXX,XX @@
36
@@ -XXX,XX +XXX,XX @@ static GDBFeature *riscv_gen_dynamic_csr_feature(CPUState *cs, int base_reg)
21
#define DMA_EXEC_DST 0x110
37
static GDBFeature *ricsv_gen_dynamic_vector_feature(CPUState *cs, int base_reg)
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,
35
{
38
{
36
SiFivePDMAState *s = opaque;
39
RISCVCPU *cpu = RISCV_CPU(cs);
37
int ch = SIFIVE_PDMA_CHAN_NO(offset);
40
- int reg_width = cpu->cfg.vlenb;
38
+ bool claimed;
41
+ int bitsize = cpu->cfg.vlenb << 3;
39
42
GDBFeatureBuilder builder;
40
if (ch >= SIFIVE_PDMA_CHANS) {
43
int i;
41
qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid channel no %d\n",
44
42
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_write(void *opaque, hwaddr offset,
45
@@ -XXX,XX +XXX,XX @@ static GDBFeature *ricsv_gen_dynamic_vector_feature(CPUState *cs, int base_reg)
43
offset &= 0xfff;
46
44
switch (offset) {
47
/* First define types and totals in a whole VL */
45
case DMA_CONTROL:
48
for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
46
+ claimed = !!s->chan[ch].control & CONTROL_CLAIM;
49
- int count = reg_width / vec_lanes[i].size;
47
+
50
+ int count = bitsize / vec_lanes[i].size;
48
+ if (!claimed && (value & CONTROL_CLAIM)) {
51
gdb_feature_builder_append_tag(
49
+ /* reset Next* registers */
52
&builder, "<vector id=\"%s\" type=\"%s\" count=\"%d\"/>",
50
+ s->chan[ch].next_config = (CONFIG_RDSZ_DEFAULT << CONFIG_RDSZ_SHIFT) |
53
vec_lanes[i].id, vec_lanes[i].gdb_type, count);
51
+ (CONFIG_WRSZ_DEFAULT << CONFIG_WRSZ_SHIFT);
54
@@ -XXX,XX +XXX,XX @@ static GDBFeature *ricsv_gen_dynamic_vector_feature(CPUState *cs, int base_reg)
52
+ s->chan[ch].next_bytes = 0;
55
/* Define vector registers */
53
+ s->chan[ch].next_dst = 0;
56
for (i = 0; i < 32; i++) {
54
+ s->chan[ch].next_src = 0;
57
gdb_feature_builder_append_reg(&builder, g_strdup_printf("v%d", i),
55
+ }
58
- reg_width, i, "riscv_vector", "vector");
56
+
59
+ bitsize, i, "riscv_vector", "vector");
57
s->chan[ch].control = value;
60
}
58
61
59
if (value & CONTROL_RUN) {
62
gdb_feature_builder_end(&builder);
60
--
63
--
61
2.31.1
64
2.45.1
62
65
63
66
diff view generated by jsdifflib
New patch
1
From: Alistair Francis <alistair23@gmail.com>
1
2
3
Previously we only listed a single pmpcfg CSR and the first 16 pmpaddr
4
CSRs. This patch fixes this to list all 16 pmpcfg and all 64 pmpaddr
5
CSRs are part of the disassembly.
6
7
Reported-by: Eric DeVolder <eric_devolder@yahoo.com>
8
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
9
Fixes: ea10325917 ("RISC-V Disassembler")
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>
14
---
15
disas/riscv.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++-
16
1 file changed, 64 insertions(+), 1 deletion(-)
17
18
diff --git a/disas/riscv.c b/disas/riscv.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/disas/riscv.c
21
+++ b/disas/riscv.c
22
@@ -XXX,XX +XXX,XX @@ static const char *csr_name(int csrno)
23
case 0x0383: return "mibound";
24
case 0x0384: return "mdbase";
25
case 0x0385: return "mdbound";
26
- case 0x03a0: return "pmpcfg3";
27
+ case 0x03a0: return "pmpcfg0";
28
+ case 0x03a1: return "pmpcfg1";
29
+ case 0x03a2: return "pmpcfg2";
30
+ case 0x03a3: return "pmpcfg3";
31
+ case 0x03a4: return "pmpcfg4";
32
+ case 0x03a5: return "pmpcfg5";
33
+ case 0x03a6: return "pmpcfg6";
34
+ case 0x03a7: return "pmpcfg7";
35
+ case 0x03a8: return "pmpcfg8";
36
+ case 0x03a9: return "pmpcfg9";
37
+ case 0x03aa: return "pmpcfg10";
38
+ case 0x03ab: return "pmpcfg11";
39
+ case 0x03ac: return "pmpcfg12";
40
+ case 0x03ad: return "pmpcfg13";
41
+ case 0x03ae: return "pmpcfg14";
42
+ case 0x03af: return "pmpcfg15";
43
case 0x03b0: return "pmpaddr0";
44
case 0x03b1: return "pmpaddr1";
45
case 0x03b2: return "pmpaddr2";
46
@@ -XXX,XX +XXX,XX @@ static const char *csr_name(int csrno)
47
case 0x03bd: return "pmpaddr13";
48
case 0x03be: return "pmpaddr14";
49
case 0x03bf: return "pmpaddr15";
50
+ case 0x03c0: return "pmpaddr16";
51
+ case 0x03c1: return "pmpaddr17";
52
+ case 0x03c2: return "pmpaddr18";
53
+ case 0x03c3: return "pmpaddr19";
54
+ case 0x03c4: return "pmpaddr20";
55
+ case 0x03c5: return "pmpaddr21";
56
+ case 0x03c6: return "pmpaddr22";
57
+ case 0x03c7: return "pmpaddr23";
58
+ case 0x03c8: return "pmpaddr24";
59
+ case 0x03c9: return "pmpaddr25";
60
+ case 0x03ca: return "pmpaddr26";
61
+ case 0x03cb: return "pmpaddr27";
62
+ case 0x03cc: return "pmpaddr28";
63
+ case 0x03cd: return "pmpaddr29";
64
+ case 0x03ce: return "pmpaddr30";
65
+ case 0x03cf: return "pmpaddr31";
66
+ case 0x03d0: return "pmpaddr32";
67
+ case 0x03d1: return "pmpaddr33";
68
+ case 0x03d2: return "pmpaddr34";
69
+ case 0x03d3: return "pmpaddr35";
70
+ case 0x03d4: return "pmpaddr36";
71
+ case 0x03d5: return "pmpaddr37";
72
+ case 0x03d6: return "pmpaddr38";
73
+ case 0x03d7: return "pmpaddr39";
74
+ case 0x03d8: return "pmpaddr40";
75
+ case 0x03d9: return "pmpaddr41";
76
+ case 0x03da: return "pmpaddr42";
77
+ case 0x03db: return "pmpaddr43";
78
+ case 0x03dc: return "pmpaddr44";
79
+ case 0x03dd: return "pmpaddr45";
80
+ case 0x03de: return "pmpaddr46";
81
+ case 0x03df: return "pmpaddr47";
82
+ case 0x03e0: return "pmpaddr48";
83
+ case 0x03e1: return "pmpaddr49";
84
+ case 0x03e2: return "pmpaddr50";
85
+ case 0x03e3: return "pmpaddr51";
86
+ case 0x03e4: return "pmpaddr52";
87
+ case 0x03e5: return "pmpaddr53";
88
+ case 0x03e6: return "pmpaddr54";
89
+ case 0x03e7: return "pmpaddr55";
90
+ case 0x03e8: return "pmpaddr56";
91
+ case 0x03e9: return "pmpaddr57";
92
+ case 0x03ea: return "pmpaddr58";
93
+ case 0x03eb: return "pmpaddr59";
94
+ case 0x03ec: return "pmpaddr60";
95
+ case 0x03ed: return "pmpaddr61";
96
+ case 0x03ee: return "pmpaddr62";
97
+ case 0x03ef: return "pmpaddr63";
98
case 0x0780: return "mtohost";
99
case 0x0781: return "mfromhost";
100
case 0x0782: return "mreset";
101
--
102
2.45.1
diff view generated by jsdifflib
1
From: Anup Patel <anup.patel@wdc.com>
1
From: Yu-Ming Chang <yumin686@andestech.com>
2
2
3
The RISC-V ACLINT is more modular and backward compatible with
3
Both CSRRS and CSRRC always read the addressed CSR and cause any read side
4
original SiFive CLINT so instead of duplicating the original
4
effects regardless of rs1 and rd fields. Note that if rs1 specifies a register
5
SiFive CLINT implementation we upgrade the current SiFive CLINT
5
holding a zero value other than x0, the instruction will still attempt to write
6
implementation to RISC-V ACLINT implementation.
6
the unmodified value back to the CSR and will cause any attendant side effects.
7
7
8
Signed-off-by: Anup Patel <anup.patel@wdc.com>
8
So if CSRRS or CSRRC tries to write a read-only CSR with rs1 which specifies
9
a register holding a zero value, an illegal instruction exception should be
10
raised.
11
12
Signed-off-by: Yu-Ming Chang <yumin686@andestech.com>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
13
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
14
Message-ID: <20240403070823.80897-1-yumin686@andestech.com>
11
Message-id: 20210831110603.338681-3-anup.patel@wdc.com
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
15
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
13
---
16
---
14
include/hw/intc/riscv_aclint.h | 54 +++--
17
target/riscv/cpu.h | 4 ++++
15
hw/intc/riscv_aclint.c | 373 +++++++++++++++++++++++----------
18
target/riscv/csr.c | 51 ++++++++++++++++++++++++++++++++++++----
16
hw/riscv/microchip_pfsoc.c | 9 +-
19
target/riscv/op_helper.c | 6 ++---
17
hw/riscv/shakti_c.c | 11 +-
20
3 files changed, 53 insertions(+), 8 deletions(-)
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(-)
23
21
24
diff --git a/include/hw/intc/riscv_aclint.h b/include/hw/intc/riscv_aclint.h
22
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
25
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
26
--- a/include/hw/intc/riscv_aclint.h
24
--- a/target/riscv/cpu.h
27
+++ b/include/hw/intc/riscv_aclint.h
25
+++ b/target/riscv/cpu.h
28
@@ -XXX,XX +XXX,XX @@
26
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
29
/*
27
void riscv_cpu_update_mask(CPURISCVState *env);
30
- * SiFive CLINT (Core Local Interruptor) interface
28
bool riscv_cpu_is_32bit(RISCVCPU *cpu);
31
+ * RISC-V ACLINT (Advanced Core Local Interruptor) interface
29
32
*
30
+RISCVException riscv_csrr(CPURISCVState *env, int csrno,
33
* Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
31
+ target_ulong *ret_value);
34
* Copyright (c) 2017 SiFive, Inc.
32
RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
35
+ * Copyright (c) 2021 Western Digital Corporation or its affiliates.
33
target_ulong *ret_value,
36
*
34
target_ulong new_value, target_ulong write_mask);
37
* This program is free software; you can redistribute it and/or modify it
35
@@ -XXX,XX +XXX,XX @@ typedef RISCVException (*riscv_csr_op_fn)(CPURISCVState *env, int csrno,
38
* under the terms and conditions of the GNU General Public License,
36
target_ulong new_value,
39
@@ -XXX,XX +XXX,XX @@
37
target_ulong write_mask);
40
* this program. If not, see <http://www.gnu.org/licenses/>.
38
41
*/
39
+RISCVException riscv_csrr_i128(CPURISCVState *env, int csrno,
42
40
+ Int128 *ret_value);
43
-#ifndef HW_SIFIVE_CLINT_H
41
RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno,
44
-#define HW_SIFIVE_CLINT_H
42
Int128 *ret_value,
45
+#ifndef HW_RISCV_ACLINT_H
43
Int128 new_value, Int128 write_mask);
46
+#define HW_RISCV_ACLINT_H
44
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
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
45
index XXXXXXX..XXXXXXX 100644
122
--- a/hw/intc/riscv_aclint.c
46
--- a/target/riscv/csr.c
123
+++ b/hw/intc/riscv_aclint.c
47
+++ b/target/riscv/csr.c
124
@@ -XXX,XX +XXX,XX @@
48
@@ -XXX,XX +XXX,XX @@ static RISCVException rmw_seed(CPURISCVState *env, int csrno,
125
/*
49
126
- * SiFive CLINT (Core Local Interruptor)
50
static inline RISCVException riscv_csrrw_check(CPURISCVState *env,
127
+ * RISC-V ACLINT (Advanced Core Local Interruptor)
51
int csrno,
128
+ * URL: https://github.com/riscv/riscv-aclint
52
- bool write_mask)
129
*
53
+ bool write)
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
{
54
{
158
@@ -XXX,XX +XXX,XX @@ static uint64_t cpu_riscv_read_rtc(uint32_t timebase_freq)
55
/* check privileges and return RISCV_EXCP_ILLEGAL_INST if check fails */
159
* Called when timecmp is written to update the QEMU timer or immediately
56
bool read_only = get_field(csrno, 0xC00) == 3;
160
* trigger timer interrupt if mtimecmp <= current timer value.
57
@@ -XXX,XX +XXX,XX @@ static inline RISCVException riscv_csrrw_check(CPURISCVState *env,
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;
187
}
58
}
188
59
189
/* otherwise, set up the future timer interrupt */
60
/* read / write check */
190
- qemu_irq_lower(s->timer_irqs[hartid - s->hartid_base]);
61
- if (write_mask && read_only) {
191
+ qemu_irq_lower(mtimer->timer_irqs[hartid - mtimer->hartid_base]);
62
+ if (write && read_only) {
192
diff = cpu->env.timecmp - rtc_r;
63
return RISCV_EXCP_ILLEGAL_INST;
193
/* back to ns (note args switched in muldiv64) */
64
}
194
uint64_t ns_diff = muldiv64(diff, NANOSECONDS_PER_SECOND, timebase_freq);
65
195
@@ -XXX,XX +XXX,XX @@ static void sifive_clint_write_timecmp(SiFiveCLINTState *s, RISCVCPU *cpu,
66
@@ -XXX,XX +XXX,XX @@ static RISCVException riscv_csrrw_do64(CPURISCVState *env, int csrno,
196
* Callback used when the timer set using timer_mod expires.
67
return RISCV_EXCP_NONE;
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]);
206
}
68
}
207
69
208
-/* CPU wants to read rtc or timecmp register */
70
+RISCVException riscv_csrr(CPURISCVState *env, int csrno,
209
-static uint64_t sifive_clint_read(void *opaque, hwaddr addr, unsigned size)
71
+ target_ulong *ret_value)
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)
508
+{
72
+{
509
+ RISCVAclintSwiState *swi = opaque;
73
+ RISCVException ret = riscv_csrrw_check(env, csrno, false);
510
+
74
+ if (ret != RISCV_EXCP_NONE) {
511
+ if (addr < (swi->num_harts << 2)) {
75
+ return ret;
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
+ }
521
+ }
76
+ }
522
+
77
+
523
+ qemu_log_mask(LOG_UNIMP,
78
+ return riscv_csrrw_do64(env, csrno, ret_value, 0, 0);
524
+ "aclint-swi: invalid read: %08x", (uint32_t)addr);
525
+ return 0;
526
+}
79
+}
527
+
80
+
528
+/* CPU write [M|S]SWI register */
81
RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
529
+static void riscv_aclint_swi_write(void *opaque, hwaddr addr, uint64_t value,
82
target_ulong *ret_value,
530
+ unsigned size)
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)
531
+{
96
+{
532
+ RISCVAclintSwiState *swi = opaque;
97
+ RISCVException ret;
533
+
98
+
534
+ if (addr < (swi->num_harts << 2)) {
99
+ ret = riscv_csrrw_check(env, csrno, false);
535
+ size_t hartid = swi->hartid_base + (addr >> 2);
100
+ if (ret != RISCV_EXCP_NONE) {
536
+ CPUState *cpu = qemu_get_cpu(hartid);
101
+ return ret;
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
+ }
102
+ }
552
+
103
+
553
+ qemu_log_mask(LOG_UNIMP,
104
+ if (csr_ops[csrno].read128) {
554
+ "aclint-swi: invalid write: %08x", (uint32_t)addr);
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;
555
+}
124
+}
556
+
125
+
557
+static const MemoryRegionOps riscv_aclint_swi_ops = {
126
RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno,
558
+ .read = riscv_aclint_swi_read,
127
Int128 *ret_value,
559
+ .write = riscv_aclint_swi_write,
128
Int128 new_value, Int128 write_mask)
560
+ .endianness = DEVICE_LITTLE_ENDIAN,
129
{
561
+ .valid = {
130
RISCVException ret;
562
+ .min_access_size = 4,
131
563
+ .max_access_size = 4
132
- ret = riscv_csrrw_check(env, csrno, int128_nz(write_mask));
564
+ }
133
+ ret = riscv_csrrw_check(env, csrno, true);
565
+};
134
if (ret != RISCV_EXCP_NONE) {
566
+
135
return ret;
567
+static Property riscv_aclint_swi_properties[] = {
136
}
568
+ DEFINE_PROP_UINT32("hartid-base", RISCVAclintSwiState, hartid_base, 0),
137
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
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
+ }
594
+ }
595
+}
596
+
597
+static void riscv_aclint_swi_class_init(ObjectClass *klass, void *data)
598
+{
599
+ DeviceClass *dc = DEVICE_CLASS(klass);
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
138
index XXXXXXX..XXXXXXX 100644
650
--- a/hw/riscv/microchip_pfsoc.c
139
--- a/target/riscv/op_helper.c
651
+++ b/hw/riscv/microchip_pfsoc.c
140
+++ b/target/riscv/op_helper.c
652
@@ -XXX,XX +XXX,XX @@ static void microchip_pfsoc_soc_realize(DeviceState *dev, Error **errp)
141
@@ -XXX,XX +XXX,XX @@ target_ulong helper_csrr(CPURISCVState *env, int csr)
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);
762
}
142
}
763
143
764
/* register system main memory (actual RAM) */
144
target_ulong val = 0;
765
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
145
- RISCVException ret = riscv_csrrw(env, csr, &val, 0, 0);
766
index XXXXXXX..XXXXXXX 100644
146
+ RISCVException ret = riscv_csrr(env, csr, &val);
767
--- a/hw/riscv/virt.c
147
768
+++ b/hw/riscv/virt.c
148
if (ret != RISCV_EXCP_NONE) {
769
@@ -XXX,XX +XXX,XX @@ static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap,
149
riscv_raise_exception(env, ret, GETPC());
770
150
@@ -XXX,XX +XXX,XX @@ target_ulong helper_csrrw(CPURISCVState *env, int csr,
771
qemu_fdt_add_subnode(fdt, "/cpus");
151
target_ulong helper_csrr_i128(CPURISCVState *env, int csr)
772
qemu_fdt_setprop_cell(fdt, "/cpus", "timebase-frequency",
152
{
773
- SIFIVE_CLINT_TIMEBASE_FREQ);
153
Int128 rv = int128_zero();
774
+ RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ);
154
- RISCVException ret = riscv_csrrw_i128(env, csr, &rv,
775
qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0x0);
155
- int128_zero(),
776
qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 0x1);
156
- int128_zero());
777
qemu_fdt_add_subnode(fdt, "/cpus/cpu-map");
157
+ RISCVException ret = riscv_csrr_i128(env, csr, &rv);
778
@@ -XXX,XX +XXX,XX @@ static void virt_machine_init(MachineState *machine)
158
779
sysbus_realize(SYS_BUS_DEVICE(&s->soc[i]), &error_abort);
159
if (ret != RISCV_EXCP_NONE) {
780
160
riscv_raise_exception(env, ret, GETPC());
781
/* Per-socket CLINT */
782
- sifive_clint_create(
783
+ riscv_aclint_swi_create(
784
memmap[VIRT_CLINT].base + i * memmap[VIRT_CLINT].size,
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);
798
--
161
--
799
2.31.1
162
2.45.1
800
801
diff view generated by jsdifflib