1
From: Alistair Francis <alistair.francis@wdc.com>
1
The following changes since commit c5ea91da443b458352c1b629b490ee6631775cb4:
2
2
3
The following changes since commit d1fe59377bbbf91dfded1f08ffe3c636e9db8dc0:
3
Merge tag 'pull-trivial-patches' of https://gitlab.com/mjt0k/qemu into staging (2023-09-08 10:06:25 -0400)
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-20230911
10
8
11
for you to fetch changes up to c14620db9b66de88bb4fef1d0cfc283bb3d53f85:
9
for you to fetch changes up to e7a03409f29e2da59297d55afbaec98c96e43e3a:
12
10
13
hw/riscv: opentitan: Correct the USB Dev address (2021-09-17 07:43:55 +1000)
11
target/riscv: don't read CSR in riscv_csrrw_do64 (2023-09-11 11:45:55 +1000)
14
12
15
----------------------------------------------------------------
13
----------------------------------------------------------------
16
Second RISC-V PR for QEMU 6.2
14
First RISC-V PR for 8.2
17
15
18
- ePMP CSR address updates
16
* Remove 'host' CPU from TCG
19
- Convert internal interrupts to use QEMU GPIO lines
17
* riscv_htif Fixup printing on big endian hosts
20
- SiFive PWM support
18
* Add zmmul isa string
21
- Support for RISC-V ACLINT
19
* Add smepmp isa string
22
- SiFive PDMA fixes
20
* Fix page_check_range use in fault-only-first
23
- Update to u-boot instructions for sifive_u
21
* Use existing lookup tables for MixColumns
24
- mstatus.SD bug fix for hypervisor extensions
22
* Add RISC-V vector cryptographic instruction set support
25
- OpenTitan fix for USB dev address
23
* Implement WARL behaviour for mcountinhibit/mcounteren
24
* Add Zihintntl extension ISA string to DTS
25
* Fix zfa fleq.d and fltq.d
26
* Fix upper/lower mtime write calculation
27
* Make rtc variable names consistent
28
* Use abi type for linux-user target_ucontext
29
* Add RISC-V KVM AIA Support
30
* Fix riscv,pmu DT node path in the virt machine
31
* Update CSR bits name for svadu extension
32
* Mark zicond non-experimental
33
* Fix satp_mode_finalize() when satp_mode.supported = 0
34
* Fix non-KVM --enable-debug build
35
* Add new extensions to hwprobe
36
* Use accelerated helper for AES64KS1I
37
* Allocate itrigger timers only once
38
* Respect mseccfg.RLB for pmpaddrX changes
39
* Align the AIA model to v1.0 ratified spec
40
* Don't read the CSR in riscv_csrrw_do64
26
41
27
----------------------------------------------------------------
42
----------------------------------------------------------------
28
Alistair Francis (9):
43
Akihiko Odaki (1):
29
target/riscv: Update the ePMP CSR address
44
target/riscv: Allocate itrigger timers only once
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
45
39
Anup Patel (4):
46
Ard Biesheuvel (2):
40
hw/intc: Rename sifive_clint sources to riscv_aclint sources
47
target/riscv: Use existing lookup tables for MixColumns
41
hw/intc: Upgrade the SiFive CLINT implementation to RISC-V ACLINT
48
target/riscv: Use accelerated helper for AES64KS1I
42
hw/riscv: virt: Re-factor FDT generation
43
hw/riscv: virt: Add optional ACLINT support to virt machine
44
49
45
Bin Meng (2):
50
Conor Dooley (1):
46
docs/system/riscv: sifive_u: Update U-Boot instructions
51
hw/riscv: virt: Fix riscv,pmu DT node path
47
target/riscv: csr: Rename HCOUNTEREN_CY and friends
48
52
49
Frank Chang (4):
53
Daniel Henrique Barboza (6):
50
hw/dma: sifive_pdma: reset Next* registers when Control.claim is set
54
target/riscv/cpu.c: do not run 'host' CPU with TCG
51
hw/dma: sifive_pdma: claim bit must be set before DMA transactions
55
target/riscv/cpu.c: add zmmul isa string
52
hw/dma: sifive_pdma: don't set Control.error if 0 bytes to transfer
56
target/riscv/cpu.c: add smepmp isa string
53
target/riscv: Backup/restore mstatus.SD bit when virtual register swapped
57
target/riscv: fix satp_mode_finalize() when satp_mode.supported = 0
58
hw/riscv/virt.c: fix non-KVM --enable-debug build
59
hw/intc/riscv_aplic.c fix non-KVM --enable-debug build
54
60
55
Green Wan (1):
61
Dickon Hood (2):
56
hw/dma: sifive_pdma: allow non-multiple transaction size transactions
62
target/riscv: Refactor translation of vector-widening instruction
63
target/riscv: Add Zvbb ISA extension support
57
64
58
LIU Zhiwei (1):
65
Jason Chien (3):
59
target/riscv: Fix satp write
66
target/riscv: Add Zihintntl extension ISA string to DTS
67
hw/intc: Fix upper/lower mtime write calculation
68
hw/intc: Make rtc variable names consistent
60
69
61
docs/system/riscv/sifive_u.rst | 50 ++--
70
Kiran Ostrolenk (4):
62
docs/system/riscv/virt.rst | 10 +
71
target/riscv: Refactor some of the generic vector functionality
63
include/hw/intc/ibex_plic.h | 2 +
72
target/riscv: Refactor vector-vector translation macro
64
include/hw/intc/riscv_aclint.h | 80 +++++
73
target/riscv: Refactor some of the generic vector functionality
65
include/hw/intc/sifive_clint.h | 60 ----
74
target/riscv: Add Zvknh ISA extension support
66
include/hw/intc/sifive_plic.h | 4 +
67
include/hw/riscv/sifive_u.h | 14 +-
68
include/hw/riscv/virt.h | 2 +
69
include/hw/timer/ibex_timer.h | 2 +
70
include/hw/timer/sifive_pwm.h | 62 ++++
71
target/riscv/cpu_bits.h | 12 +-
72
hw/dma/sifive_pdma.c | 54 +++-
73
hw/intc/ibex_plic.c | 17 +-
74
hw/intc/riscv_aclint.c | 460 +++++++++++++++++++++++++++++
75
hw/intc/sifive_clint.c | 287 ------------------
76
hw/intc/sifive_plic.c | 30 +-
77
hw/riscv/microchip_pfsoc.c | 13 +-
78
hw/riscv/opentitan.c | 13 +-
79
hw/riscv/shakti_c.c | 16 +-
80
hw/riscv/sifive_e.c | 15 +-
81
hw/riscv/sifive_u.c | 68 ++++-
82
hw/riscv/spike.c | 16 +-
83
hw/riscv/virt.c | 654 ++++++++++++++++++++++++++++-------------
84
hw/timer/ibex_timer.c | 17 +-
85
hw/timer/sifive_pwm.c | 468 +++++++++++++++++++++++++++++
86
target/riscv/cpu.c | 31 ++
87
target/riscv/cpu_helper.c | 3 +-
88
target/riscv/csr.c | 26 +-
89
hw/intc/Kconfig | 2 +-
90
hw/intc/meson.build | 2 +-
91
hw/riscv/Kconfig | 13 +-
92
hw/timer/Kconfig | 3 +
93
hw/timer/meson.build | 1 +
94
hw/timer/trace-events | 6 +
95
34 files changed, 1844 insertions(+), 669 deletions(-)
96
create mode 100644 include/hw/intc/riscv_aclint.h
97
delete mode 100644 include/hw/intc/sifive_clint.h
98
create mode 100644 include/hw/timer/sifive_pwm.h
99
create mode 100644 hw/intc/riscv_aclint.c
100
delete mode 100644 hw/intc/sifive_clint.c
101
create mode 100644 hw/timer/sifive_pwm.c
102
75
76
LIU Zhiwei (3):
77
target/riscv: Fix page_check_range use in fault-only-first
78
target/riscv: Fix zfa fleq.d and fltq.d
79
linux-user/riscv: Use abi type for target_ucontext
80
81
Lawrence Hunter (2):
82
target/riscv: Add Zvbc ISA extension support
83
target/riscv: Add Zvksh ISA extension support
84
85
Leon Schuermann (1):
86
target/riscv/pmp.c: respect mseccfg.RLB for pmpaddrX changes
87
88
Max Chou (3):
89
crypto: Create sm4_subword
90
crypto: Add SM4 constant parameter CK
91
target/riscv: Add Zvksed ISA extension support
92
93
Nazar Kazakov (4):
94
target/riscv: Remove redundant "cpu_vl == 0" checks
95
target/riscv: Move vector translation checks
96
target/riscv: Add Zvkned ISA extension support
97
target/riscv: Add Zvkg ISA extension support
98
99
Nikita Shubin (1):
100
target/riscv: don't read CSR in riscv_csrrw_do64
101
102
Rob Bradford (1):
103
target/riscv: Implement WARL behaviour for mcountinhibit/mcounteren
104
105
Robbin Ehn (1):
106
linux-user/riscv: Add new extensions to hwprobe
107
108
Thomas Huth (2):
109
hw/char/riscv_htif: Fix printing of console characters on big endian hosts
110
hw/char/riscv_htif: Fix the console syscall on big endian hosts
111
112
Tommy Wu (1):
113
target/riscv: Align the AIA model to v1.0 ratified spec
114
115
Vineet Gupta (1):
116
riscv: zicond: make non-experimental
117
118
Weiwei Li (1):
119
target/riscv: Update CSR bits name for svadu extension
120
121
Yong-Xuan Wang (5):
122
target/riscv: support the AIA device emulation with KVM enabled
123
target/riscv: check the in-kernel irqchip support
124
target/riscv: Create an KVM AIA irqchip
125
target/riscv: update APLIC and IMSIC to support KVM AIA
126
target/riscv: select KVM AIA in riscv virt machine
127
128
include/crypto/aes.h | 7 +
129
include/crypto/sm4.h | 9 +
130
target/riscv/cpu_bits.h | 8 +-
131
target/riscv/cpu_cfg.h | 9 +
132
target/riscv/debug.h | 3 +-
133
target/riscv/helper.h | 98 +++
134
target/riscv/kvm_riscv.h | 5 +
135
target/riscv/vector_internals.h | 228 +++++++
136
target/riscv/insn32.decode | 58 ++
137
crypto/aes.c | 4 +-
138
crypto/sm4.c | 10 +
139
hw/char/riscv_htif.c | 12 +-
140
hw/intc/riscv_aclint.c | 11 +-
141
hw/intc/riscv_aplic.c | 52 +-
142
hw/intc/riscv_imsic.c | 25 +-
143
hw/riscv/virt.c | 374 ++++++------
144
linux-user/riscv/signal.c | 4 +-
145
linux-user/syscall.c | 14 +-
146
target/arm/tcg/crypto_helper.c | 10 +-
147
target/riscv/cpu.c | 83 ++-
148
target/riscv/cpu_helper.c | 6 +-
149
target/riscv/crypto_helper.c | 51 +-
150
target/riscv/csr.c | 54 +-
151
target/riscv/debug.c | 15 +-
152
target/riscv/kvm.c | 201 ++++++-
153
target/riscv/pmp.c | 4 +
154
target/riscv/translate.c | 1 +
155
target/riscv/vcrypto_helper.c | 970 ++++++++++++++++++++++++++++++
156
target/riscv/vector_helper.c | 245 +-------
157
target/riscv/vector_internals.c | 81 +++
158
target/riscv/insn_trans/trans_rvv.c.inc | 171 +++---
159
target/riscv/insn_trans/trans_rvvk.c.inc | 606 +++++++++++++++++++
160
target/riscv/insn_trans/trans_rvzfa.c.inc | 4 +-
161
target/riscv/meson.build | 4 +-
162
34 files changed, 2785 insertions(+), 652 deletions(-)
163
create mode 100644 target/riscv/vector_internals.h
164
create mode 100644 target/riscv/vcrypto_helper.c
165
create mode 100644 target/riscv/vector_internals.c
166
create mode 100644 target/riscv/insn_trans/trans_rvvk.c.inc
diff view generated by jsdifflib
1
From: Green Wan <green.wan@sifive.com>
1
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
2
2
3
Real PDMA is able to deal with non-multiple transaction size transactions.
3
The 'host' CPU is available in a CONFIG_KVM build and it's currently
4
available for all accels, but is a KVM only CPU. This means that in a
5
RISC-V KVM capable host we can do things like this:
4
6
5
The following result is PDMA tested in U-Boot on Unmatched board:
7
$ ./build/qemu-system-riscv64 -M virt,accel=tcg -cpu host --nographic
8
qemu-system-riscv64: H extension requires priv spec 1.12.0
6
9
7
=> mw.l 0x3000000 0x0 <= Disclaim channel 0
10
This CPU does not have a priv spec because we don't filter its extensions
8
=> mw.l 0x3000000 0x1 <= Claim channel 0
11
via priv spec. We shouldn't be reaching riscv_cpu_realize_tcg() at all
9
=> mw.l 0x3000004 0x11000000 <= wsize = rsize = 1 (2^1 = 2 bytes)
12
with the 'host' CPU.
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
13
29
Signed-off-by: Green Wan <green.wan@sifive.com>
14
We don't have a way to filter the 'host' CPU out of the available CPU
30
Reviewed-by: Frank Chang <frank.chang@sifive.com>
15
options (-cpu help) if the build includes both KVM and TCG. What we can
31
Tested-by: Max Hsu <max.hsu@sifive.com>
16
do is to error out during riscv_cpu_realize_tcg() if the user chooses
32
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
17
the 'host' CPU with accel=tcg:
33
Tested-by: Bin Meng <bmeng.cn@gmail.com>
18
34
Signed-off-by: Frank Chang <frank.chang@sifive.com>
19
$ ./build/qemu-system-riscv64 -M virt,accel=tcg -cpu host --nographic
35
Message-id: 20210912130553.179501-4-frank.chang@sifive.com
20
qemu-system-riscv64: 'host' CPU is not compatible with TCG acceleration
21
22
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
23
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
24
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
25
Message-Id: <20230721133411.474105-1-dbarboza@ventanamicro.com>
36
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
26
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
37
---
27
---
38
hw/dma/sifive_pdma.c | 16 ++++++++++------
28
target/riscv/cpu.c | 5 +++++
39
1 file changed, 10 insertions(+), 6 deletions(-)
29
1 file changed, 5 insertions(+)
40
30
41
diff --git a/hw/dma/sifive_pdma.c b/hw/dma/sifive_pdma.c
31
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
42
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
43
--- a/hw/dma/sifive_pdma.c
33
--- a/target/riscv/cpu.c
44
+++ b/hw/dma/sifive_pdma.c
34
+++ b/target/riscv/cpu.c
45
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_run(SiFivePDMAState *s, int ch)
35
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_realize_tcg(DeviceState *dev, Error **errp)
46
uint64_t dst = s->chan[ch].next_dst;
36
CPURISCVState *env = &cpu->env;
47
uint64_t src = s->chan[ch].next_src;
37
Error *local_err = NULL;
48
uint32_t config = s->chan[ch].next_config;
38
49
- int wsize, rsize, size;
39
+ if (object_dynamic_cast(OBJECT(dev), TYPE_RISCV_CPU_HOST)) {
50
+ int wsize, rsize, size, remainder;
40
+ error_setg(errp, "'host' CPU is not compatible with TCG acceleration");
51
uint8_t buf[64];
41
+ return;
52
int n;
53
54
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_run(SiFivePDMAState *s, int ch)
55
size = 6;
56
}
57
size = 1 << size;
58
-
59
- /* the bytes to transfer should be multiple of transaction size */
60
- if (bytes % size) {
61
- goto error;
62
- }
63
+ remainder = bytes % size;
64
65
/* indicate a DMA transfer is started */
66
s->chan[ch].state = DMA_CHAN_STATE_STARTED;
67
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_run(SiFivePDMAState *s, int ch)
68
s->chan[ch].exec_bytes -= size;
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
+ }
42
+ }
78
+
43
+
79
/* indicate a DMA transfer is done */
44
riscv_cpu_validate_misa_mxl(cpu, &local_err);
80
s->chan[ch].state = DMA_CHAN_STATE_DONE;
45
if (local_err != NULL) {
81
s->chan[ch].control &= ~CONTROL_RUN;
46
error_propagate(errp, local_err);
82
--
47
--
83
2.31.1
48
2.41.0
84
49
85
50
diff view generated by jsdifflib
1
From: Frank Chang <frank.chang@sifive.com>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
When virtual registers are swapped, mstatus.SD bit should also be
3
The character that should be printed is stored in the 64 bit "payload"
4
backed up/restored. Otherwise, mstatus.SD bit will be incorrectly kept
4
variable. The code currently tries to print it by taking the address
5
across the world switches.
5
of the variable and passing this pointer to qemu_chr_fe_write(). However,
6
this only works on little endian hosts where the least significant bits
7
are stored on the lowest address. To do this in a portable way, we have
8
to store the value in an uint8_t variable instead.
6
9
7
Signed-off-by: Frank Chang <frank.chang@sifive.com>
10
Fixes: 5033606780 ("RISC-V HTIF Console")
8
Reviewed-by: Vincent Chen <vincent.chen@sifive.com>
11
Signed-off-by: Thomas Huth <thuth@redhat.com>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
12
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Message-id: 20210914013717.881430-1-frank.chang@sifive.com
13
Reviewed-by: Bin Meng <bmeng@tinylab.org>
14
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
15
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
16
Message-Id: <20230721094720.902454-2-thuth@redhat.com>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
17
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
---
18
---
13
target/riscv/cpu_helper.c | 3 ++-
19
hw/char/riscv_htif.c | 3 ++-
14
1 file changed, 2 insertions(+), 1 deletion(-)
20
1 file changed, 2 insertions(+), 1 deletion(-)
15
21
16
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
22
diff --git a/hw/char/riscv_htif.c b/hw/char/riscv_htif.c
17
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
18
--- a/target/riscv/cpu_helper.c
24
--- a/hw/char/riscv_htif.c
19
+++ b/target/riscv/cpu_helper.c
25
+++ b/hw/char/riscv_htif.c
20
@@ -XXX,XX +XXX,XX @@ bool riscv_cpu_fp_enabled(CPURISCVState *env)
26
@@ -XXX,XX +XXX,XX @@ static void htif_handle_tohost_write(HTIFState *s, uint64_t val_written)
21
27
s->tohost = 0; /* clear to indicate we read */
22
void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env)
28
return;
23
{
29
} else if (cmd == HTIF_CONSOLE_CMD_PUTC) {
24
+ target_ulong sd = riscv_cpu_is_32bit(env) ? MSTATUS32_SD : MSTATUS64_SD;
30
- qemu_chr_fe_write(&s->chr, (uint8_t *)&payload, 1);
25
uint64_t mstatus_mask = MSTATUS_MXR | MSTATUS_SUM | MSTATUS_FS |
31
+ uint8_t ch = (uint8_t)payload;
26
MSTATUS_SPP | MSTATUS_SPIE | MSTATUS_SIE |
32
+ qemu_chr_fe_write(&s->chr, &ch, 1);
27
- MSTATUS64_UXL;
33
resp = 0x100 | (uint8_t)payload;
28
+ MSTATUS64_UXL | sd;
34
} else {
29
bool current_virt = riscv_cpu_virt_enabled(env);
35
qemu_log("HTIF device %d: unknown command\n", device);
30
31
g_assert(riscv_has_ext(env, RVH));
32
--
36
--
33
2.31.1
37
2.41.0
34
38
35
39
diff view generated by jsdifflib
New patch
1
From: Thomas Huth <thuth@redhat.com>
1
2
3
Values that have been read via cpu_physical_memory_read() from the
4
guest's memory have to be swapped in case the host endianess differs
5
from the guest.
6
7
Fixes: a6e13e31d5 ("riscv_htif: Support console output via proxy syscall")
8
Signed-off-by: Thomas Huth <thuth@redhat.com>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Reviewed-by: Bin Meng <bmeng@tinylab.org>
11
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
12
Message-Id: <20230721094720.902454-3-thuth@redhat.com>
13
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
14
---
15
hw/char/riscv_htif.c | 9 +++++----
16
1 file changed, 5 insertions(+), 4 deletions(-)
17
18
diff --git a/hw/char/riscv_htif.c b/hw/char/riscv_htif.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/char/riscv_htif.c
21
+++ b/hw/char/riscv_htif.c
22
@@ -XXX,XX +XXX,XX @@
23
#include "qemu/timer.h"
24
#include "qemu/error-report.h"
25
#include "exec/address-spaces.h"
26
+#include "exec/tswap.h"
27
#include "sysemu/dma.h"
28
29
#define RISCV_DEBUG_HTIF 0
30
@@ -XXX,XX +XXX,XX @@ static void htif_handle_tohost_write(HTIFState *s, uint64_t val_written)
31
} else {
32
uint64_t syscall[8];
33
cpu_physical_memory_read(payload, syscall, sizeof(syscall));
34
- if (syscall[0] == PK_SYS_WRITE &&
35
- syscall[1] == HTIF_DEV_CONSOLE &&
36
- syscall[3] == HTIF_CONSOLE_CMD_PUTC) {
37
+ if (tswap64(syscall[0]) == PK_SYS_WRITE &&
38
+ tswap64(syscall[1]) == HTIF_DEV_CONSOLE &&
39
+ tswap64(syscall[3]) == HTIF_CONSOLE_CMD_PUTC) {
40
uint8_t ch;
41
- cpu_physical_memory_read(syscall[2], &ch, 1);
42
+ cpu_physical_memory_read(tswap64(syscall[2]), &ch, 1);
43
qemu_chr_fe_write(&s->chr, &ch, 1);
44
resp = 0x100 | (uint8_t)payload;
45
} else {
46
--
47
2.41.0
diff view generated by jsdifflib
New patch
1
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
1
2
3
zmmul was promoted from experimental to ratified in commit 6d00ffad4e95.
4
Add a riscv,isa string for it.
5
6
Fixes: 6d00ffad4e95 ("target/riscv: move zmmul out of the experimental properties")
7
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
8
Reviewed-by: Weiwei Li <liweiwei@iscas.ac.cn>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Message-Id: <20230720132424.371132-2-dbarboza@ventanamicro.com>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
---
13
target/riscv/cpu.c | 1 +
14
1 file changed, 1 insertion(+)
15
16
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/riscv/cpu.c
19
+++ b/target/riscv/cpu.c
20
@@ -XXX,XX +XXX,XX @@ static const struct isa_ext_data isa_edata_arr[] = {
21
ISA_EXT_DATA_ENTRY(zicsr, PRIV_VERSION_1_10_0, ext_icsr),
22
ISA_EXT_DATA_ENTRY(zifencei, PRIV_VERSION_1_10_0, ext_ifencei),
23
ISA_EXT_DATA_ENTRY(zihintpause, PRIV_VERSION_1_10_0, ext_zihintpause),
24
+ ISA_EXT_DATA_ENTRY(zmmul, PRIV_VERSION_1_12_0, ext_zmmul),
25
ISA_EXT_DATA_ENTRY(zawrs, PRIV_VERSION_1_12_0, ext_zawrs),
26
ISA_EXT_DATA_ENTRY(zfa, PRIV_VERSION_1_12_0, ext_zfa),
27
ISA_EXT_DATA_ENTRY(zfbfmin, PRIV_VERSION_1_12_0, ext_zfbfmin),
28
--
29
2.41.0
diff view generated by jsdifflib
New patch
1
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
1
2
3
The cpu->cfg.epmp extension is still experimental, but it already has a
4
'smepmp' riscv,isa string. Add it.
5
6
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
7
Reviewed-by: Weiwei Li <liweiwei@iscas.ac.cn>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Message-Id: <20230720132424.371132-3-dbarboza@ventanamicro.com>
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
---
12
target/riscv/cpu.c | 1 +
13
1 file changed, 1 insertion(+)
14
15
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/riscv/cpu.c
18
+++ b/target/riscv/cpu.c
19
@@ -XXX,XX +XXX,XX @@ static const struct isa_ext_data isa_edata_arr[] = {
20
ISA_EXT_DATA_ENTRY(zhinx, PRIV_VERSION_1_12_0, ext_zhinx),
21
ISA_EXT_DATA_ENTRY(zhinxmin, PRIV_VERSION_1_12_0, ext_zhinxmin),
22
ISA_EXT_DATA_ENTRY(smaia, PRIV_VERSION_1_12_0, ext_smaia),
23
+ ISA_EXT_DATA_ENTRY(smepmp, PRIV_VERSION_1_12_0, epmp),
24
ISA_EXT_DATA_ENTRY(smstateen, PRIV_VERSION_1_12_0, ext_smstateen),
25
ISA_EXT_DATA_ENTRY(ssaia, PRIV_VERSION_1_12_0, ext_ssaia),
26
ISA_EXT_DATA_ENTRY(sscofpmf, PRIV_VERSION_1_12_0, ext_sscofpmf),
27
--
28
2.41.0
diff view generated by jsdifflib
New patch
1
From: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
1
2
3
Commit bef6f008b98(accel/tcg: Return bool from page_check_range) converts
4
integer return value to bool type. However, it wrongly converted the use
5
of the API in riscv fault-only-first, where page_check_range < = 0, should
6
be converted to !page_check_range.
7
8
Signed-off-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-ID: <20230729031618.821-1-zhiwei_liu@linux.alibaba.com>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
---
13
target/riscv/vector_helper.c | 2 +-
14
1 file changed, 1 insertion(+), 1 deletion(-)
15
16
diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/riscv/vector_helper.c
19
+++ b/target/riscv/vector_helper.c
20
@@ -XXX,XX +XXX,XX @@ vext_ldff(void *vd, void *v0, target_ulong base,
21
cpu_mmu_index(env, false));
22
if (host) {
23
#ifdef CONFIG_USER_ONLY
24
- if (page_check_range(addr, offset, PAGE_READ)) {
25
+ if (!page_check_range(addr, offset, PAGE_READ)) {
26
vl = i;
27
goto ProbeSuccess;
28
}
29
--
30
2.41.0
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@wdc.com>
1
From: Ard Biesheuvel <ardb@kernel.org>
2
2
3
Instead of using riscv_cpu_update_mip() let's instead use the new RISC-V
3
The AES MixColumns and InvMixColumns operations are relatively
4
CPU GPIO lines to set the external MIP bits.
4
expensive 4x4 matrix multiplications in GF(2^8), which is why C
5
implementations usually rely on precomputed lookup tables rather than
6
performing the calculations on demand.
5
7
8
Given that we already carry those tables in QEMU, we can just grab the
9
right value in the implementation of the RISC-V AES32 instructions. Note
10
that the tables in question are permuted according to the respective
11
Sbox, so we can omit the Sbox lookup as well in this case.
12
13
Cc: Richard Henderson <richard.henderson@linaro.org>
14
Cc: Philippe Mathieu-Daudé <philmd@linaro.org>
15
Cc: Zewen Ye <lustrew@foxmail.com>
16
Cc: Weiwei Li <liweiwei@iscas.ac.cn>
17
Cc: Junqiang Wang <wangjunqiang@iscas.ac.cn>
18
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Message-ID: <20230731084043.1791984-1-ardb@kernel.org>
6
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
21
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
---
22
---
11
include/hw/intc/ibex_plic.h | 2 ++
23
include/crypto/aes.h | 7 +++++++
12
hw/intc/ibex_plic.c | 17 ++++++-----------
24
crypto/aes.c | 4 ++--
13
hw/riscv/opentitan.c | 8 ++++++++
25
target/riscv/crypto_helper.c | 34 ++++------------------------------
14
3 files changed, 16 insertions(+), 11 deletions(-)
26
3 files changed, 13 insertions(+), 32 deletions(-)
15
27
16
diff --git a/include/hw/intc/ibex_plic.h b/include/hw/intc/ibex_plic.h
28
diff --git a/include/crypto/aes.h b/include/crypto/aes.h
17
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/intc/ibex_plic.h
30
--- a/include/crypto/aes.h
19
+++ b/include/hw/intc/ibex_plic.h
31
+++ b/include/crypto/aes.h
20
@@ -XXX,XX +XXX,XX @@ struct IbexPlicState {
32
@@ -XXX,XX +XXX,XX @@ void AES_decrypt(const unsigned char *in, unsigned char *out,
21
uint32_t threshold_base;
33
extern const uint8_t AES_sbox[256];
22
34
extern const uint8_t AES_isbox[256];
23
uint32_t claim_base;
35
36
+/*
37
+AES_Te0[x] = S [x].[02, 01, 01, 03];
38
+AES_Td0[x] = Si[x].[0e, 09, 0d, 0b];
39
+*/
24
+
40
+
25
+ qemu_irq *external_irqs;
41
+extern const uint32_t AES_Te0[256], AES_Td0[256];
42
+
43
#endif
44
diff --git a/crypto/aes.c b/crypto/aes.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/crypto/aes.c
47
+++ b/crypto/aes.c
48
@@ -XXX,XX +XXX,XX @@ AES_Td3[x] = Si[x].[09, 0d, 0b, 0e];
49
AES_Td4[x] = Si[x].[01, 01, 01, 01];
50
*/
51
52
-static const uint32_t AES_Te0[256] = {
53
+const uint32_t AES_Te0[256] = {
54
0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
55
0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
56
0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
57
@@ -XXX,XX +XXX,XX @@ static const uint32_t AES_Te4[256] = {
58
0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U,
26
};
59
};
27
60
28
#endif /* HW_IBEX_PLIC_H */
61
-static const uint32_t AES_Td0[256] = {
29
diff --git a/hw/intc/ibex_plic.c b/hw/intc/ibex_plic.c
62
+const uint32_t AES_Td0[256] = {
63
0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
64
0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
65
0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,
66
diff --git a/target/riscv/crypto_helper.c b/target/riscv/crypto_helper.c
30
index XXXXXXX..XXXXXXX 100644
67
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/intc/ibex_plic.c
68
--- a/target/riscv/crypto_helper.c
32
+++ b/hw/intc/ibex_plic.c
69
+++ b/target/riscv/crypto_helper.c
33
@@ -XXX,XX +XXX,XX @@
70
@@ -XXX,XX +XXX,XX @@
34
#include "target/riscv/cpu_bits.h"
71
#include "crypto/aes-round.h"
35
#include "target/riscv/cpu.h"
72
#include "crypto/sm4.h"
36
#include "hw/intc/ibex_plic.h"
73
37
+#include "hw/irq.h"
74
-#define AES_XTIME(a) \
38
75
- ((a << 1) ^ ((a & 0x80) ? 0x1b : 0))
39
static bool addr_between(uint32_t addr, uint32_t base, uint32_t num)
76
-
77
-#define AES_GFMUL(a, b) (( \
78
- (((b) & 0x1) ? (a) : 0) ^ \
79
- (((b) & 0x2) ? AES_XTIME(a) : 0) ^ \
80
- (((b) & 0x4) ? AES_XTIME(AES_XTIME(a)) : 0) ^ \
81
- (((b) & 0x8) ? AES_XTIME(AES_XTIME(AES_XTIME(a))) : 0)) & 0xFF)
82
-
83
-static inline uint32_t aes_mixcolumn_byte(uint8_t x, bool fwd)
84
-{
85
- uint32_t u;
86
-
87
- if (fwd) {
88
- u = (AES_GFMUL(x, 3) << 24) | (x << 16) | (x << 8) |
89
- (AES_GFMUL(x, 2) << 0);
90
- } else {
91
- u = (AES_GFMUL(x, 0xb) << 24) | (AES_GFMUL(x, 0xd) << 16) |
92
- (AES_GFMUL(x, 0x9) << 8) | (AES_GFMUL(x, 0xe) << 0);
93
- }
94
- return u;
95
-}
96
-
97
#define sext32_xlen(x) (target_ulong)(int32_t)(x)
98
99
static inline target_ulong aes32_operation(target_ulong shamt,
100
@@ -XXX,XX +XXX,XX @@ static inline target_ulong aes32_operation(target_ulong shamt,
101
bool enc, bool mix)
40
{
102
{
41
@@ -XXX,XX +XXX,XX @@ static bool ibex_plic_irqs_pending(IbexPlicState *s, uint32_t context)
103
uint8_t si = rs2 >> shamt;
42
104
- uint8_t so;
43
static void ibex_plic_update(IbexPlicState *s)
105
uint32_t mixed;
44
{
106
target_ulong res;
45
- CPUState *cpu;
107
46
- int level, i;
108
if (enc) {
47
+ int i;
109
- so = AES_sbox[si];
48
110
if (mix) {
49
for (i = 0; i < s->num_cpus; i++) {
111
- mixed = aes_mixcolumn_byte(so, true);
50
- cpu = qemu_get_cpu(i);
112
+ mixed = be32_to_cpu(AES_Te0[si]);
51
-
113
} else {
52
- if (!cpu) {
114
- mixed = so;
53
- continue;
115
+ mixed = AES_sbox[si];
54
- }
116
}
55
-
117
} else {
56
- level = ibex_plic_irqs_pending(s, 0);
118
- so = AES_isbox[si];
57
-
119
if (mix) {
58
- riscv_cpu_update_mip(RISCV_CPU(cpu), MIP_MEIP, BOOL_TO_MASK(level));
120
- mixed = aes_mixcolumn_byte(so, false);
59
+ qemu_set_irq(s->external_irqs[i], ibex_plic_irqs_pending(s, 0));
121
+ mixed = be32_to_cpu(AES_Td0[si]);
122
} else {
123
- mixed = so;
124
+ mixed = AES_isbox[si];
125
}
60
}
126
}
61
}
127
mixed = rol32(mixed, shamt);
62
63
@@ -XXX,XX +XXX,XX @@ static void ibex_plic_realize(DeviceState *dev, Error **errp)
64
65
qdev_init_gpio_in(dev, ibex_plic_irq_request, s->num_sources);
66
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
+ }
95
+
96
/* UART */
97
qdev_prop_set_chr(DEVICE(&(s->uart)), "chardev", serial_hd(0));
98
if (!sysbus_realize(SYS_BUS_DEVICE(&s->uart), errp)) {
99
--
128
--
100
2.31.1
129
2.41.0
101
130
102
131
diff view generated by jsdifflib
New patch
1
From: Kiran Ostrolenk <kiran.ostrolenk@codethink.co.uk>
1
2
3
Take some functions/macros out of `vector_helper` and put them in a new
4
module called `vector_internals`. This ensures they can be used by both
5
vector and vector-crypto helpers (latter implemented in proceeding
6
commits).
7
8
Signed-off-by: Kiran Ostrolenk <kiran.ostrolenk@codethink.co.uk>
9
Reviewed-by: Weiwei Li <liweiwei@iscas.ac.cn>
10
Signed-off-by: Max Chou <max.chou@sifive.com>
11
Acked-by: Alistair Francis <alistair.francis@wdc.com>
12
Message-ID: <20230711165917.2629866-2-max.chou@sifive.com>
13
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
14
---
15
target/riscv/vector_internals.h | 182 +++++++++++++++++++++++++++++
16
target/riscv/vector_helper.c | 201 +-------------------------------
17
target/riscv/vector_internals.c | 81 +++++++++++++
18
target/riscv/meson.build | 1 +
19
4 files changed, 265 insertions(+), 200 deletions(-)
20
create mode 100644 target/riscv/vector_internals.h
21
create mode 100644 target/riscv/vector_internals.c
22
23
diff --git a/target/riscv/vector_internals.h b/target/riscv/vector_internals.h
24
new file mode 100644
25
index XXXXXXX..XXXXXXX
26
--- /dev/null
27
+++ b/target/riscv/vector_internals.h
28
@@ -XXX,XX +XXX,XX @@
29
+/*
30
+ * RISC-V Vector Extension Internals
31
+ *
32
+ * Copyright (c) 2020 T-Head Semiconductor Co., Ltd. All rights reserved.
33
+ *
34
+ * This program is free software; you can redistribute it and/or modify it
35
+ * under the terms and conditions of the GNU General Public License,
36
+ * version 2 or later, as published by the Free Software Foundation.
37
+ *
38
+ * This program is distributed in the hope it will be useful, but WITHOUT
39
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
40
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
41
+ * more details.
42
+ *
43
+ * You should have received a copy of the GNU General Public License along with
44
+ * this program. If not, see <http://www.gnu.org/licenses/>.
45
+ */
46
+
47
+#ifndef TARGET_RISCV_VECTOR_INTERNALS_H
48
+#define TARGET_RISCV_VECTOR_INTERNALS_H
49
+
50
+#include "qemu/osdep.h"
51
+#include "qemu/bitops.h"
52
+#include "cpu.h"
53
+#include "tcg/tcg-gvec-desc.h"
54
+#include "internals.h"
55
+
56
+static inline uint32_t vext_nf(uint32_t desc)
57
+{
58
+ return FIELD_EX32(simd_data(desc), VDATA, NF);
59
+}
60
+
61
+/*
62
+ * Note that vector data is stored in host-endian 64-bit chunks,
63
+ * so addressing units smaller than that needs a host-endian fixup.
64
+ */
65
+#if HOST_BIG_ENDIAN
66
+#define H1(x) ((x) ^ 7)
67
+#define H1_2(x) ((x) ^ 6)
68
+#define H1_4(x) ((x) ^ 4)
69
+#define H2(x) ((x) ^ 3)
70
+#define H4(x) ((x) ^ 1)
71
+#define H8(x) ((x))
72
+#else
73
+#define H1(x) (x)
74
+#define H1_2(x) (x)
75
+#define H1_4(x) (x)
76
+#define H2(x) (x)
77
+#define H4(x) (x)
78
+#define H8(x) (x)
79
+#endif
80
+
81
+/*
82
+ * Encode LMUL to lmul as following:
83
+ * LMUL vlmul lmul
84
+ * 1 000 0
85
+ * 2 001 1
86
+ * 4 010 2
87
+ * 8 011 3
88
+ * - 100 -
89
+ * 1/8 101 -3
90
+ * 1/4 110 -2
91
+ * 1/2 111 -1
92
+ */
93
+static inline int32_t vext_lmul(uint32_t desc)
94
+{
95
+ return sextract32(FIELD_EX32(simd_data(desc), VDATA, LMUL), 0, 3);
96
+}
97
+
98
+static inline uint32_t vext_vm(uint32_t desc)
99
+{
100
+ return FIELD_EX32(simd_data(desc), VDATA, VM);
101
+}
102
+
103
+static inline uint32_t vext_vma(uint32_t desc)
104
+{
105
+ return FIELD_EX32(simd_data(desc), VDATA, VMA);
106
+}
107
+
108
+static inline uint32_t vext_vta(uint32_t desc)
109
+{
110
+ return FIELD_EX32(simd_data(desc), VDATA, VTA);
111
+}
112
+
113
+static inline uint32_t vext_vta_all_1s(uint32_t desc)
114
+{
115
+ return FIELD_EX32(simd_data(desc), VDATA, VTA_ALL_1S);
116
+}
117
+
118
+/*
119
+ * Earlier designs (pre-0.9) had a varying number of bits
120
+ * per mask value (MLEN). In the 0.9 design, MLEN=1.
121
+ * (Section 4.5)
122
+ */
123
+static inline int vext_elem_mask(void *v0, int index)
124
+{
125
+ int idx = index / 64;
126
+ int pos = index % 64;
127
+ return (((uint64_t *)v0)[idx] >> pos) & 1;
128
+}
129
+
130
+/*
131
+ * Get number of total elements, including prestart, body and tail elements.
132
+ * Note that when LMUL < 1, the tail includes the elements past VLMAX that
133
+ * are held in the same vector register.
134
+ */
135
+static inline uint32_t vext_get_total_elems(CPURISCVState *env, uint32_t desc,
136
+ uint32_t esz)
137
+{
138
+ uint32_t vlenb = simd_maxsz(desc);
139
+ uint32_t sew = 1 << FIELD_EX64(env->vtype, VTYPE, VSEW);
140
+ int8_t emul = ctzl(esz) - ctzl(sew) + vext_lmul(desc) < 0 ? 0 :
141
+ ctzl(esz) - ctzl(sew) + vext_lmul(desc);
142
+ return (vlenb << emul) / esz;
143
+}
144
+
145
+/* set agnostic elements to 1s */
146
+void vext_set_elems_1s(void *base, uint32_t is_agnostic, uint32_t cnt,
147
+ uint32_t tot);
148
+
149
+/* expand macro args before macro */
150
+#define RVVCALL(macro, ...) macro(__VA_ARGS__)
151
+
152
+/* (TD, T1, T2, TX1, TX2) */
153
+#define OP_UUU_B uint8_t, uint8_t, uint8_t, uint8_t, uint8_t
154
+#define OP_UUU_H uint16_t, uint16_t, uint16_t, uint16_t, uint16_t
155
+#define OP_UUU_W uint32_t, uint32_t, uint32_t, uint32_t, uint32_t
156
+#define OP_UUU_D uint64_t, uint64_t, uint64_t, uint64_t, uint64_t
157
+
158
+/* operation of two vector elements */
159
+typedef void opivv2_fn(void *vd, void *vs1, void *vs2, int i);
160
+
161
+#define OPIVV2(NAME, TD, T1, T2, TX1, TX2, HD, HS1, HS2, OP) \
162
+static void do_##NAME(void *vd, void *vs1, void *vs2, int i) \
163
+{ \
164
+ TX1 s1 = *((T1 *)vs1 + HS1(i)); \
165
+ TX2 s2 = *((T2 *)vs2 + HS2(i)); \
166
+ *((TD *)vd + HD(i)) = OP(s2, s1); \
167
+}
168
+
169
+void do_vext_vv(void *vd, void *v0, void *vs1, void *vs2,
170
+ CPURISCVState *env, uint32_t desc,
171
+ opivv2_fn *fn, uint32_t esz);
172
+
173
+/* generate the helpers for OPIVV */
174
+#define GEN_VEXT_VV(NAME, ESZ) \
175
+void HELPER(NAME)(void *vd, void *v0, void *vs1, \
176
+ void *vs2, CPURISCVState *env, \
177
+ uint32_t desc) \
178
+{ \
179
+ do_vext_vv(vd, v0, vs1, vs2, env, desc, \
180
+ do_##NAME, ESZ); \
181
+}
182
+
183
+typedef void opivx2_fn(void *vd, target_long s1, void *vs2, int i);
184
+
185
+/*
186
+ * (T1)s1 gives the real operator type.
187
+ * (TX1)(T1)s1 expands the operator type of widen or narrow operations.
188
+ */
189
+#define OPIVX2(NAME, TD, T1, T2, TX1, TX2, HD, HS2, OP) \
190
+static void do_##NAME(void *vd, target_long s1, void *vs2, int i) \
191
+{ \
192
+ TX2 s2 = *((T2 *)vs2 + HS2(i)); \
193
+ *((TD *)vd + HD(i)) = OP(s2, (TX1)(T1)s1); \
194
+}
195
+
196
+void do_vext_vx(void *vd, void *v0, target_long s1, void *vs2,
197
+ CPURISCVState *env, uint32_t desc,
198
+ opivx2_fn fn, uint32_t esz);
199
+
200
+/* generate the helpers for OPIVX */
201
+#define GEN_VEXT_VX(NAME, ESZ) \
202
+void HELPER(NAME)(void *vd, void *v0, target_ulong s1, \
203
+ void *vs2, CPURISCVState *env, \
204
+ uint32_t desc) \
205
+{ \
206
+ do_vext_vx(vd, v0, s1, vs2, env, desc, \
207
+ do_##NAME, ESZ); \
208
+}
209
+
210
+#endif /* TARGET_RISCV_VECTOR_INTERNALS_H */
211
diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
212
index XXXXXXX..XXXXXXX 100644
213
--- a/target/riscv/vector_helper.c
214
+++ b/target/riscv/vector_helper.c
215
@@ -XXX,XX +XXX,XX @@
216
#include "fpu/softfloat.h"
217
#include "tcg/tcg-gvec-desc.h"
218
#include "internals.h"
219
+#include "vector_internals.h"
220
#include <math.h>
221
222
target_ulong HELPER(vsetvl)(CPURISCVState *env, target_ulong s1,
223
@@ -XXX,XX +XXX,XX @@ target_ulong HELPER(vsetvl)(CPURISCVState *env, target_ulong s1,
224
return vl;
225
}
226
227
-/*
228
- * Note that vector data is stored in host-endian 64-bit chunks,
229
- * so addressing units smaller than that needs a host-endian fixup.
230
- */
231
-#if HOST_BIG_ENDIAN
232
-#define H1(x) ((x) ^ 7)
233
-#define H1_2(x) ((x) ^ 6)
234
-#define H1_4(x) ((x) ^ 4)
235
-#define H2(x) ((x) ^ 3)
236
-#define H4(x) ((x) ^ 1)
237
-#define H8(x) ((x))
238
-#else
239
-#define H1(x) (x)
240
-#define H1_2(x) (x)
241
-#define H1_4(x) (x)
242
-#define H2(x) (x)
243
-#define H4(x) (x)
244
-#define H8(x) (x)
245
-#endif
246
-
247
-static inline uint32_t vext_nf(uint32_t desc)
248
-{
249
- return FIELD_EX32(simd_data(desc), VDATA, NF);
250
-}
251
-
252
-static inline uint32_t vext_vm(uint32_t desc)
253
-{
254
- return FIELD_EX32(simd_data(desc), VDATA, VM);
255
-}
256
-
257
-/*
258
- * Encode LMUL to lmul as following:
259
- * LMUL vlmul lmul
260
- * 1 000 0
261
- * 2 001 1
262
- * 4 010 2
263
- * 8 011 3
264
- * - 100 -
265
- * 1/8 101 -3
266
- * 1/4 110 -2
267
- * 1/2 111 -1
268
- */
269
-static inline int32_t vext_lmul(uint32_t desc)
270
-{
271
- return sextract32(FIELD_EX32(simd_data(desc), VDATA, LMUL), 0, 3);
272
-}
273
-
274
-static inline uint32_t vext_vta(uint32_t desc)
275
-{
276
- return FIELD_EX32(simd_data(desc), VDATA, VTA);
277
-}
278
-
279
-static inline uint32_t vext_vma(uint32_t desc)
280
-{
281
- return FIELD_EX32(simd_data(desc), VDATA, VMA);
282
-}
283
-
284
-static inline uint32_t vext_vta_all_1s(uint32_t desc)
285
-{
286
- return FIELD_EX32(simd_data(desc), VDATA, VTA_ALL_1S);
287
-}
288
-
289
/*
290
* Get the maximum number of elements can be operated.
291
*
292
@@ -XXX,XX +XXX,XX @@ static inline uint32_t vext_max_elems(uint32_t desc, uint32_t log2_esz)
293
return scale < 0 ? vlenb >> -scale : vlenb << scale;
294
}
295
296
-/*
297
- * Get number of total elements, including prestart, body and tail elements.
298
- * Note that when LMUL < 1, the tail includes the elements past VLMAX that
299
- * are held in the same vector register.
300
- */
301
-static inline uint32_t vext_get_total_elems(CPURISCVState *env, uint32_t desc,
302
- uint32_t esz)
303
-{
304
- uint32_t vlenb = simd_maxsz(desc);
305
- uint32_t sew = 1 << FIELD_EX64(env->vtype, VTYPE, VSEW);
306
- int8_t emul = ctzl(esz) - ctzl(sew) + vext_lmul(desc) < 0 ? 0 :
307
- ctzl(esz) - ctzl(sew) + vext_lmul(desc);
308
- return (vlenb << emul) / esz;
309
-}
310
-
311
static inline target_ulong adjust_addr(CPURISCVState *env, target_ulong addr)
312
{
313
return (addr & ~env->cur_pmmask) | env->cur_pmbase;
314
@@ -XXX,XX +XXX,XX @@ static void probe_pages(CPURISCVState *env, target_ulong addr,
315
}
316
}
317
318
-/* set agnostic elements to 1s */
319
-static void vext_set_elems_1s(void *base, uint32_t is_agnostic, uint32_t cnt,
320
- uint32_t tot)
321
-{
322
- if (is_agnostic == 0) {
323
- /* policy undisturbed */
324
- return;
325
- }
326
- if (tot - cnt == 0) {
327
- return;
328
- }
329
- memset(base + cnt, -1, tot - cnt);
330
-}
331
-
332
static inline void vext_set_elem_mask(void *v0, int index,
333
uint8_t value)
334
{
335
@@ -XXX,XX +XXX,XX @@ static inline void vext_set_elem_mask(void *v0, int index,
336
((uint64_t *)v0)[idx] = deposit64(old, pos, 1, value);
337
}
338
339
-/*
340
- * Earlier designs (pre-0.9) had a varying number of bits
341
- * per mask value (MLEN). In the 0.9 design, MLEN=1.
342
- * (Section 4.5)
343
- */
344
-static inline int vext_elem_mask(void *v0, int index)
345
-{
346
- int idx = index / 64;
347
- int pos = index % 64;
348
- return (((uint64_t *)v0)[idx] >> pos) & 1;
349
-}
350
-
351
/* elements operations for load and store */
352
typedef void vext_ldst_elem_fn(CPURISCVState *env, abi_ptr addr,
353
uint32_t idx, void *vd, uintptr_t retaddr);
354
@@ -XXX,XX +XXX,XX @@ GEN_VEXT_ST_WHOLE(vs8r_v, int8_t, ste_b)
355
* Vector Integer Arithmetic Instructions
356
*/
357
358
-/* expand macro args before macro */
359
-#define RVVCALL(macro, ...) macro(__VA_ARGS__)
360
-
361
/* (TD, T1, T2, TX1, TX2) */
362
#define OP_SSS_B int8_t, int8_t, int8_t, int8_t, int8_t
363
#define OP_SSS_H int16_t, int16_t, int16_t, int16_t, int16_t
364
#define OP_SSS_W int32_t, int32_t, int32_t, int32_t, int32_t
365
#define OP_SSS_D int64_t, int64_t, int64_t, int64_t, int64_t
366
-#define OP_UUU_B uint8_t, uint8_t, uint8_t, uint8_t, uint8_t
367
-#define OP_UUU_H uint16_t, uint16_t, uint16_t, uint16_t, uint16_t
368
-#define OP_UUU_W uint32_t, uint32_t, uint32_t, uint32_t, uint32_t
369
-#define OP_UUU_D uint64_t, uint64_t, uint64_t, uint64_t, uint64_t
370
#define OP_SUS_B int8_t, uint8_t, int8_t, uint8_t, int8_t
371
#define OP_SUS_H int16_t, uint16_t, int16_t, uint16_t, int16_t
372
#define OP_SUS_W int32_t, uint32_t, int32_t, uint32_t, int32_t
373
@@ -XXX,XX +XXX,XX @@ GEN_VEXT_ST_WHOLE(vs8r_v, int8_t, ste_b)
374
#define NOP_UUU_H uint16_t, uint16_t, uint32_t, uint16_t, uint32_t
375
#define NOP_UUU_W uint32_t, uint32_t, uint64_t, uint32_t, uint64_t
376
377
-/* operation of two vector elements */
378
-typedef void opivv2_fn(void *vd, void *vs1, void *vs2, int i);
379
-
380
-#define OPIVV2(NAME, TD, T1, T2, TX1, TX2, HD, HS1, HS2, OP) \
381
-static void do_##NAME(void *vd, void *vs1, void *vs2, int i) \
382
-{ \
383
- TX1 s1 = *((T1 *)vs1 + HS1(i)); \
384
- TX2 s2 = *((T2 *)vs2 + HS2(i)); \
385
- *((TD *)vd + HD(i)) = OP(s2, s1); \
386
-}
387
#define DO_SUB(N, M) (N - M)
388
#define DO_RSUB(N, M) (M - N)
389
390
@@ -XXX,XX +XXX,XX @@ RVVCALL(OPIVV2, vsub_vv_h, OP_SSS_H, H2, H2, H2, DO_SUB)
391
RVVCALL(OPIVV2, vsub_vv_w, OP_SSS_W, H4, H4, H4, DO_SUB)
392
RVVCALL(OPIVV2, vsub_vv_d, OP_SSS_D, H8, H8, H8, DO_SUB)
393
394
-static void do_vext_vv(void *vd, void *v0, void *vs1, void *vs2,
395
- CPURISCVState *env, uint32_t desc,
396
- opivv2_fn *fn, uint32_t esz)
397
-{
398
- uint32_t vm = vext_vm(desc);
399
- uint32_t vl = env->vl;
400
- uint32_t total_elems = vext_get_total_elems(env, desc, esz);
401
- uint32_t vta = vext_vta(desc);
402
- uint32_t vma = vext_vma(desc);
403
- uint32_t i;
404
-
405
- for (i = env->vstart; i < vl; i++) {
406
- if (!vm && !vext_elem_mask(v0, i)) {
407
- /* set masked-off elements to 1s */
408
- vext_set_elems_1s(vd, vma, i * esz, (i + 1) * esz);
409
- continue;
410
- }
411
- fn(vd, vs1, vs2, i);
412
- }
413
- env->vstart = 0;
414
- /* set tail elements to 1s */
415
- vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz);
416
-}
417
-
418
-/* generate the helpers for OPIVV */
419
-#define GEN_VEXT_VV(NAME, ESZ) \
420
-void HELPER(NAME)(void *vd, void *v0, void *vs1, \
421
- void *vs2, CPURISCVState *env, \
422
- uint32_t desc) \
423
-{ \
424
- do_vext_vv(vd, v0, vs1, vs2, env, desc, \
425
- do_##NAME, ESZ); \
426
-}
427
-
428
GEN_VEXT_VV(vadd_vv_b, 1)
429
GEN_VEXT_VV(vadd_vv_h, 2)
430
GEN_VEXT_VV(vadd_vv_w, 4)
431
@@ -XXX,XX +XXX,XX @@ GEN_VEXT_VV(vsub_vv_h, 2)
432
GEN_VEXT_VV(vsub_vv_w, 4)
433
GEN_VEXT_VV(vsub_vv_d, 8)
434
435
-typedef void opivx2_fn(void *vd, target_long s1, void *vs2, int i);
436
-
437
-/*
438
- * (T1)s1 gives the real operator type.
439
- * (TX1)(T1)s1 expands the operator type of widen or narrow operations.
440
- */
441
-#define OPIVX2(NAME, TD, T1, T2, TX1, TX2, HD, HS2, OP) \
442
-static void do_##NAME(void *vd, target_long s1, void *vs2, int i) \
443
-{ \
444
- TX2 s2 = *((T2 *)vs2 + HS2(i)); \
445
- *((TD *)vd + HD(i)) = OP(s2, (TX1)(T1)s1); \
446
-}
447
448
RVVCALL(OPIVX2, vadd_vx_b, OP_SSS_B, H1, H1, DO_ADD)
449
RVVCALL(OPIVX2, vadd_vx_h, OP_SSS_H, H2, H2, DO_ADD)
450
@@ -XXX,XX +XXX,XX @@ RVVCALL(OPIVX2, vrsub_vx_h, OP_SSS_H, H2, H2, DO_RSUB)
451
RVVCALL(OPIVX2, vrsub_vx_w, OP_SSS_W, H4, H4, DO_RSUB)
452
RVVCALL(OPIVX2, vrsub_vx_d, OP_SSS_D, H8, H8, DO_RSUB)
453
454
-static void do_vext_vx(void *vd, void *v0, target_long s1, void *vs2,
455
- CPURISCVState *env, uint32_t desc,
456
- opivx2_fn fn, uint32_t esz)
457
-{
458
- uint32_t vm = vext_vm(desc);
459
- uint32_t vl = env->vl;
460
- uint32_t total_elems = vext_get_total_elems(env, desc, esz);
461
- uint32_t vta = vext_vta(desc);
462
- uint32_t vma = vext_vma(desc);
463
- uint32_t i;
464
-
465
- for (i = env->vstart; i < vl; i++) {
466
- if (!vm && !vext_elem_mask(v0, i)) {
467
- /* set masked-off elements to 1s */
468
- vext_set_elems_1s(vd, vma, i * esz, (i + 1) * esz);
469
- continue;
470
- }
471
- fn(vd, s1, vs2, i);
472
- }
473
- env->vstart = 0;
474
- /* set tail elements to 1s */
475
- vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz);
476
-}
477
-
478
-/* generate the helpers for OPIVX */
479
-#define GEN_VEXT_VX(NAME, ESZ) \
480
-void HELPER(NAME)(void *vd, void *v0, target_ulong s1, \
481
- void *vs2, CPURISCVState *env, \
482
- uint32_t desc) \
483
-{ \
484
- do_vext_vx(vd, v0, s1, vs2, env, desc, \
485
- do_##NAME, ESZ); \
486
-}
487
-
488
GEN_VEXT_VX(vadd_vx_b, 1)
489
GEN_VEXT_VX(vadd_vx_h, 2)
490
GEN_VEXT_VX(vadd_vx_w, 4)
491
diff --git a/target/riscv/vector_internals.c b/target/riscv/vector_internals.c
492
new file mode 100644
493
index XXXXXXX..XXXXXXX
494
--- /dev/null
495
+++ b/target/riscv/vector_internals.c
496
@@ -XXX,XX +XXX,XX @@
497
+/*
498
+ * RISC-V Vector Extension Internals
499
+ *
500
+ * Copyright (c) 2020 T-Head Semiconductor Co., Ltd. All rights reserved.
501
+ *
502
+ * This program is free software; you can redistribute it and/or modify it
503
+ * under the terms and conditions of the GNU General Public License,
504
+ * version 2 or later, as published by the Free Software Foundation.
505
+ *
506
+ * This program is distributed in the hope it will be useful, but WITHOUT
507
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
508
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
509
+ * more details.
510
+ *
511
+ * You should have received a copy of the GNU General Public License along with
512
+ * this program. If not, see <http://www.gnu.org/licenses/>.
513
+ */
514
+
515
+#include "vector_internals.h"
516
+
517
+/* set agnostic elements to 1s */
518
+void vext_set_elems_1s(void *base, uint32_t is_agnostic, uint32_t cnt,
519
+ uint32_t tot)
520
+{
521
+ if (is_agnostic == 0) {
522
+ /* policy undisturbed */
523
+ return;
524
+ }
525
+ if (tot - cnt == 0) {
526
+ return ;
527
+ }
528
+ memset(base + cnt, -1, tot - cnt);
529
+}
530
+
531
+void do_vext_vv(void *vd, void *v0, void *vs1, void *vs2,
532
+ CPURISCVState *env, uint32_t desc,
533
+ opivv2_fn *fn, uint32_t esz)
534
+{
535
+ uint32_t vm = vext_vm(desc);
536
+ uint32_t vl = env->vl;
537
+ uint32_t total_elems = vext_get_total_elems(env, desc, esz);
538
+ uint32_t vta = vext_vta(desc);
539
+ uint32_t vma = vext_vma(desc);
540
+ uint32_t i;
541
+
542
+ for (i = env->vstart; i < vl; i++) {
543
+ if (!vm && !vext_elem_mask(v0, i)) {
544
+ /* set masked-off elements to 1s */
545
+ vext_set_elems_1s(vd, vma, i * esz, (i + 1) * esz);
546
+ continue;
547
+ }
548
+ fn(vd, vs1, vs2, i);
549
+ }
550
+ env->vstart = 0;
551
+ /* set tail elements to 1s */
552
+ vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz);
553
+}
554
+
555
+void do_vext_vx(void *vd, void *v0, target_long s1, void *vs2,
556
+ CPURISCVState *env, uint32_t desc,
557
+ opivx2_fn fn, uint32_t esz)
558
+{
559
+ uint32_t vm = vext_vm(desc);
560
+ uint32_t vl = env->vl;
561
+ uint32_t total_elems = vext_get_total_elems(env, desc, esz);
562
+ uint32_t vta = vext_vta(desc);
563
+ uint32_t vma = vext_vma(desc);
564
+ uint32_t i;
565
+
566
+ for (i = env->vstart; i < vl; i++) {
567
+ if (!vm && !vext_elem_mask(v0, i)) {
568
+ /* set masked-off elements to 1s */
569
+ vext_set_elems_1s(vd, vma, i * esz, (i + 1) * esz);
570
+ continue;
571
+ }
572
+ fn(vd, s1, vs2, i);
573
+ }
574
+ env->vstart = 0;
575
+ /* set tail elements to 1s */
576
+ vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz);
577
+}
578
diff --git a/target/riscv/meson.build b/target/riscv/meson.build
579
index XXXXXXX..XXXXXXX 100644
580
--- a/target/riscv/meson.build
581
+++ b/target/riscv/meson.build
582
@@ -XXX,XX +XXX,XX @@ riscv_ss.add(files(
583
'gdbstub.c',
584
'op_helper.c',
585
'vector_helper.c',
586
+ 'vector_internals.c',
587
'bitmanip_helper.c',
588
'translate.c',
589
'm128_helper.c',
590
--
591
2.41.0
diff view generated by jsdifflib
New patch
1
From: Kiran Ostrolenk <kiran.ostrolenk@codethink.co.uk>
1
2
3
Refactor the non SEW-specific stuff out of `GEN_OPIVV_TRANS` into
4
function `opivv_trans` (similar to `opivi_trans`). `opivv_trans` will be
5
used in proceeding vector-crypto commits.
6
7
Signed-off-by: Kiran Ostrolenk <kiran.ostrolenk@codethink.co.uk>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Reviewed-by: Weiwei Li <liweiwei@iscas.ac.cn>
11
Signed-off-by: Max Chou <max.chou@sifive.com>
12
Message-ID: <20230711165917.2629866-3-max.chou@sifive.com>
13
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
14
---
15
target/riscv/insn_trans/trans_rvv.c.inc | 62 +++++++++++++------------
16
1 file changed, 32 insertions(+), 30 deletions(-)
17
18
diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/riscv/insn_trans/trans_rvv.c.inc
21
+++ b/target/riscv/insn_trans/trans_rvv.c.inc
22
@@ -XXX,XX +XXX,XX @@ GEN_OPIWX_WIDEN_TRANS(vwadd_wx)
23
GEN_OPIWX_WIDEN_TRANS(vwsubu_wx)
24
GEN_OPIWX_WIDEN_TRANS(vwsub_wx)
25
26
+static bool opivv_trans(uint32_t vd, uint32_t vs1, uint32_t vs2, uint32_t vm,
27
+ gen_helper_gvec_4_ptr *fn, DisasContext *s)
28
+{
29
+ uint32_t data = 0;
30
+ TCGLabel *over = gen_new_label();
31
+ tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
32
+ tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
33
+
34
+ data = FIELD_DP32(data, VDATA, VM, vm);
35
+ data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
36
+ data = FIELD_DP32(data, VDATA, VTA, s->vta);
37
+ data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);
38
+ data = FIELD_DP32(data, VDATA, VMA, s->vma);
39
+ tcg_gen_gvec_4_ptr(vreg_ofs(s, vd), vreg_ofs(s, 0), vreg_ofs(s, vs1),
40
+ vreg_ofs(s, vs2), cpu_env, s->cfg_ptr->vlen / 8,
41
+ s->cfg_ptr->vlen / 8, data, fn);
42
+ mark_vs_dirty(s);
43
+ gen_set_label(over);
44
+ return true;
45
+}
46
+
47
/* Vector Integer Add-with-Carry / Subtract-with-Borrow Instructions */
48
/* OPIVV without GVEC IR */
49
-#define GEN_OPIVV_TRANS(NAME, CHECK) \
50
-static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
51
-{ \
52
- if (CHECK(s, a)) { \
53
- uint32_t data = 0; \
54
- static gen_helper_gvec_4_ptr * const fns[4] = { \
55
- gen_helper_##NAME##_b, gen_helper_##NAME##_h, \
56
- gen_helper_##NAME##_w, gen_helper_##NAME##_d, \
57
- }; \
58
- TCGLabel *over = gen_new_label(); \
59
- tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); \
60
- tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); \
61
- \
62
- data = FIELD_DP32(data, VDATA, VM, a->vm); \
63
- data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \
64
- data = FIELD_DP32(data, VDATA, VTA, s->vta); \
65
- data = \
66
- FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);\
67
- data = FIELD_DP32(data, VDATA, VMA, s->vma); \
68
- tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \
69
- vreg_ofs(s, a->rs1), \
70
- vreg_ofs(s, a->rs2), cpu_env, \
71
- s->cfg_ptr->vlen / 8, \
72
- s->cfg_ptr->vlen / 8, data, \
73
- fns[s->sew]); \
74
- mark_vs_dirty(s); \
75
- gen_set_label(over); \
76
- return true; \
77
- } \
78
- return false; \
79
+#define GEN_OPIVV_TRANS(NAME, CHECK) \
80
+static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
81
+{ \
82
+ if (CHECK(s, a)) { \
83
+ static gen_helper_gvec_4_ptr * const fns[4] = { \
84
+ gen_helper_##NAME##_b, gen_helper_##NAME##_h, \
85
+ gen_helper_##NAME##_w, gen_helper_##NAME##_d, \
86
+ }; \
87
+ return opivv_trans(a->rd, a->rs1, a->rs2, a->vm, fns[s->sew], s);\
88
+ } \
89
+ return false; \
90
}
91
92
/*
93
--
94
2.41.0
diff view generated by jsdifflib
New patch
1
From: Nazar Kazakov <nazar.kazakov@codethink.co.uk>
1
2
3
Remove the redundant "vl == 0" check which is already included within the vstart >= vl check, when vl == 0.
4
5
Signed-off-by: Nazar Kazakov <nazar.kazakov@codethink.co.uk>
6
Reviewed-by: Weiwei Li <liweiwei@iscas.ac.cn>
7
Signed-off-by: Max Chou <max.chou@sifive.com>
8
Acked-by: Alistair Francis <alistair.francis@wdc.com>
9
Message-ID: <20230711165917.2629866-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 | 31 +------------------------
13
1 file changed, 1 insertion(+), 30 deletions(-)
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 ldst_us_trans(uint32_t vd, uint32_t rs1, uint32_t data,
20
TCGv_i32 desc;
21
22
TCGLabel *over = gen_new_label();
23
- tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
24
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
25
26
dest = tcg_temp_new_ptr();
27
@@ -XXX,XX +XXX,XX @@ static bool ldst_stride_trans(uint32_t vd, uint32_t rs1, uint32_t rs2,
28
TCGv_i32 desc;
29
30
TCGLabel *over = gen_new_label();
31
- tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
32
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
33
34
dest = tcg_temp_new_ptr();
35
@@ -XXX,XX +XXX,XX @@ static bool ldst_index_trans(uint32_t vd, uint32_t rs1, uint32_t vs2,
36
TCGv_i32 desc;
37
38
TCGLabel *over = gen_new_label();
39
- tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
40
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
41
42
dest = tcg_temp_new_ptr();
43
@@ -XXX,XX +XXX,XX @@ static bool ldff_trans(uint32_t vd, uint32_t rs1, uint32_t data,
44
TCGv_i32 desc;
45
46
TCGLabel *over = gen_new_label();
47
- tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
48
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
49
50
dest = tcg_temp_new_ptr();
51
@@ -XXX,XX +XXX,XX @@ do_opivv_gvec(DisasContext *s, arg_rmrr *a, GVecGen3Fn *gvec_fn,
52
return false;
53
}
54
55
- tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
56
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
57
58
if (a->vm && s->vl_eq_vlmax && !(s->vta && s->lmul < 0)) {
59
@@ -XXX,XX +XXX,XX @@ static bool opivx_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, uint32_t vm,
60
uint32_t data = 0;
61
62
TCGLabel *over = gen_new_label();
63
- tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
64
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
65
66
dest = tcg_temp_new_ptr();
67
@@ -XXX,XX +XXX,XX @@ static bool opivi_trans(uint32_t vd, uint32_t imm, uint32_t vs2, uint32_t vm,
68
uint32_t data = 0;
69
70
TCGLabel *over = gen_new_label();
71
- tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
72
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
73
74
dest = tcg_temp_new_ptr();
75
@@ -XXX,XX +XXX,XX @@ static bool do_opivv_widen(DisasContext *s, arg_rmrr *a,
76
if (checkfn(s, a)) {
77
uint32_t data = 0;
78
TCGLabel *over = gen_new_label();
79
- tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
80
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
81
82
data = FIELD_DP32(data, VDATA, VM, a->vm);
83
@@ -XXX,XX +XXX,XX @@ static bool do_opiwv_widen(DisasContext *s, arg_rmrr *a,
84
if (opiwv_widen_check(s, a)) {
85
uint32_t data = 0;
86
TCGLabel *over = gen_new_label();
87
- tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
88
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
89
90
data = FIELD_DP32(data, VDATA, VM, a->vm);
91
@@ -XXX,XX +XXX,XX @@ static bool opivv_trans(uint32_t vd, uint32_t vs1, uint32_t vs2, uint32_t vm,
92
{
93
uint32_t data = 0;
94
TCGLabel *over = gen_new_label();
95
- tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
96
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
97
98
data = FIELD_DP32(data, VDATA, VM, vm);
99
@@ -XXX,XX +XXX,XX @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
100
gen_helper_##NAME##_w, \
101
}; \
102
TCGLabel *over = gen_new_label(); \
103
- tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); \
104
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); \
105
\
106
data = FIELD_DP32(data, VDATA, VM, a->vm); \
107
@@ -XXX,XX +XXX,XX @@ static bool trans_vmv_v_v(DisasContext *s, arg_vmv_v_v *a)
108
gen_helper_vmv_v_v_w, gen_helper_vmv_v_v_d,
109
};
110
TCGLabel *over = gen_new_label();
111
- tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
112
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
113
114
tcg_gen_gvec_2_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, a->rs1),
115
@@ -XXX,XX +XXX,XX @@ static bool trans_vmv_v_x(DisasContext *s, arg_vmv_v_x *a)
116
vext_check_ss(s, a->rd, 0, 1)) {
117
TCGv s1;
118
TCGLabel *over = gen_new_label();
119
- tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
120
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
121
122
s1 = get_gpr(s, a->rs1, EXT_SIGN);
123
@@ -XXX,XX +XXX,XX @@ static bool trans_vmv_v_i(DisasContext *s, arg_vmv_v_i *a)
124
gen_helper_vmv_v_x_w, gen_helper_vmv_v_x_d,
125
};
126
TCGLabel *over = gen_new_label();
127
- tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
128
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
129
130
s1 = tcg_constant_i64(simm);
131
@@ -XXX,XX +XXX,XX @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
132
}; \
133
TCGLabel *over = gen_new_label(); \
134
gen_set_rm(s, RISCV_FRM_DYN); \
135
- tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); \
136
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); \
137
\
138
data = FIELD_DP32(data, VDATA, VM, a->vm); \
139
@@ -XXX,XX +XXX,XX @@ static bool opfvf_trans(uint32_t vd, uint32_t rs1, uint32_t vs2,
140
TCGv_i64 t1;
141
142
TCGLabel *over = gen_new_label();
143
- tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
144
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
145
146
dest = tcg_temp_new_ptr();
147
@@ -XXX,XX +XXX,XX @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
148
}; \
149
TCGLabel *over = gen_new_label(); \
150
gen_set_rm(s, RISCV_FRM_DYN); \
151
- tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); \
152
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);\
153
\
154
data = FIELD_DP32(data, VDATA, VM, a->vm); \
155
@@ -XXX,XX +XXX,XX @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
156
}; \
157
TCGLabel *over = gen_new_label(); \
158
gen_set_rm(s, RISCV_FRM_DYN); \
159
- tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); \
160
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); \
161
\
162
data = FIELD_DP32(data, VDATA, VM, a->vm); \
163
@@ -XXX,XX +XXX,XX @@ static bool do_opfv(DisasContext *s, arg_rmr *a,
164
uint32_t data = 0;
165
TCGLabel *over = gen_new_label();
166
gen_set_rm_chkfrm(s, rm);
167
- tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
168
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
169
170
data = FIELD_DP32(data, VDATA, VM, a->vm);
171
@@ -XXX,XX +XXX,XX @@ static bool trans_vfmv_v_f(DisasContext *s, arg_vfmv_v_f *a)
172
gen_helper_vmv_v_x_d,
173
};
174
TCGLabel *over = gen_new_label();
175
- tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
176
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
177
178
t1 = tcg_temp_new_i64();
179
@@ -XXX,XX +XXX,XX @@ static bool trans_##NAME(DisasContext *s, arg_rmr *a) \
180
}; \
181
TCGLabel *over = gen_new_label(); \
182
gen_set_rm_chkfrm(s, FRM); \
183
- tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); \
184
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); \
185
\
186
data = FIELD_DP32(data, VDATA, VM, a->vm); \
187
@@ -XXX,XX +XXX,XX @@ static bool trans_##NAME(DisasContext *s, arg_rmr *a) \
188
}; \
189
TCGLabel *over = gen_new_label(); \
190
gen_set_rm(s, RISCV_FRM_DYN); \
191
- tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); \
192
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); \
193
\
194
data = FIELD_DP32(data, VDATA, VM, a->vm); \
195
@@ -XXX,XX +XXX,XX @@ static bool trans_##NAME(DisasContext *s, arg_rmr *a) \
196
}; \
197
TCGLabel *over = gen_new_label(); \
198
gen_set_rm_chkfrm(s, FRM); \
199
- tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); \
200
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); \
201
\
202
data = FIELD_DP32(data, VDATA, VM, a->vm); \
203
@@ -XXX,XX +XXX,XX @@ static bool trans_##NAME(DisasContext *s, arg_rmr *a) \
204
}; \
205
TCGLabel *over = gen_new_label(); \
206
gen_set_rm_chkfrm(s, FRM); \
207
- tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); \
208
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); \
209
\
210
data = FIELD_DP32(data, VDATA, VM, a->vm); \
211
@@ -XXX,XX +XXX,XX @@ static bool trans_##NAME(DisasContext *s, arg_r *a) \
212
uint32_t data = 0; \
213
gen_helper_gvec_4_ptr *fn = gen_helper_##NAME; \
214
TCGLabel *over = gen_new_label(); \
215
- tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); \
216
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); \
217
\
218
data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \
219
@@ -XXX,XX +XXX,XX @@ static bool trans_vid_v(DisasContext *s, arg_vid_v *a)
220
require_vm(a->vm, a->rd)) {
221
uint32_t data = 0;
222
TCGLabel *over = gen_new_label();
223
- tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
224
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
225
226
data = FIELD_DP32(data, VDATA, VM, a->vm);
227
@@ -XXX,XX +XXX,XX @@ static bool trans_vmv_s_x(DisasContext *s, arg_vmv_s_x *a)
228
TCGv s1;
229
TCGLabel *over = gen_new_label();
230
231
- tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
232
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
233
234
t1 = tcg_temp_new_i64();
235
@@ -XXX,XX +XXX,XX @@ static bool trans_vfmv_s_f(DisasContext *s, arg_vfmv_s_f *a)
236
TCGv_i64 t1;
237
TCGLabel *over = gen_new_label();
238
239
- /* if vl == 0 or vstart >= vl, skip vector register write back */
240
- tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
241
+ /* if vstart >= vl, skip vector register write back */
242
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
243
244
/* NaN-box f[rs1] */
245
@@ -XXX,XX +XXX,XX @@ static bool int_ext_op(DisasContext *s, arg_rmr *a, uint8_t seq)
246
uint32_t data = 0;
247
gen_helper_gvec_3_ptr *fn;
248
TCGLabel *over = gen_new_label();
249
- tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
250
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
251
252
static gen_helper_gvec_3_ptr * const fns[6][4] = {
253
--
254
2.41.0
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@wdc.com>
1
From: Lawrence Hunter <lawrence.hunter@codethink.co.uk>
2
2
3
This is the initial commit of the SiFive PWM timer. This is used by
3
This commit adds support for the Zvbc vector-crypto extension, which
4
guest software as a timer and is included in the SiFive FU540 SoC.
4
consists of the following instructions:
5
5
6
Signed-off-by: Justin Restivo <jrestivo@draper.com>
6
* vclmulh.[vx,vv]
7
Signed-off-by: Alexandra Clifford <aclifford@draper.com>
7
* vclmul.[vx,vv]
8
Signed-off-by: Amanda Strnad <astrnad@draper.com>
8
9
Translation functions are defined in
10
`target/riscv/insn_trans/trans_rvvk.c.inc` and helpers are defined in
11
`target/riscv/vcrypto_helper.c`.
12
13
Co-authored-by: Nazar Kazakov <nazar.kazakov@codethink.co.uk>
14
Co-authored-by: Max Chou <max.chou@sifive.com>
15
Signed-off-by: Nazar Kazakov <nazar.kazakov@codethink.co.uk>
16
Signed-off-by: Lawrence Hunter <lawrence.hunter@codethink.co.uk>
17
Signed-off-by: Max Chou <max.chou@sifive.com>
18
[max.chou@sifive.com: Exposed x-zvbc property]
19
Message-ID: <20230711165917.2629866-5-max.chou@sifive.com>
9
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
20
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
---
21
---
13
include/hw/timer/sifive_pwm.h | 62 +++++
22
target/riscv/cpu_cfg.h | 1 +
14
hw/timer/sifive_pwm.c | 468 ++++++++++++++++++++++++++++++++++
23
target/riscv/helper.h | 6 +++
15
hw/timer/Kconfig | 3 +
24
target/riscv/insn32.decode | 6 +++
16
hw/timer/meson.build | 1 +
25
target/riscv/cpu.c | 9 ++++
17
hw/timer/trace-events | 6 +
26
target/riscv/translate.c | 1 +
18
5 files changed, 540 insertions(+)
27
target/riscv/vcrypto_helper.c | 59 ++++++++++++++++++++++
19
create mode 100644 include/hw/timer/sifive_pwm.h
28
target/riscv/insn_trans/trans_rvvk.c.inc | 62 ++++++++++++++++++++++++
20
create mode 100644 hw/timer/sifive_pwm.c
29
target/riscv/meson.build | 3 +-
21
30
8 files changed, 146 insertions(+), 1 deletion(-)
22
diff --git a/include/hw/timer/sifive_pwm.h b/include/hw/timer/sifive_pwm.h
31
create mode 100644 target/riscv/vcrypto_helper.c
32
create mode 100644 target/riscv/insn_trans/trans_rvvk.c.inc
33
34
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
35
index XXXXXXX..XXXXXXX 100644
36
--- a/target/riscv/cpu_cfg.h
37
+++ b/target/riscv/cpu_cfg.h
38
@@ -XXX,XX +XXX,XX @@ struct RISCVCPUConfig {
39
bool ext_zve32f;
40
bool ext_zve64f;
41
bool ext_zve64d;
42
+ bool ext_zvbc;
43
bool ext_zmmul;
44
bool ext_zvfbfmin;
45
bool ext_zvfbfwma;
46
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/riscv/helper.h
49
+++ b/target/riscv/helper.h
50
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_5(vfwcvtbf16_f_f_v, void, ptr, ptr, ptr, env, i32)
51
52
DEF_HELPER_6(vfwmaccbf16_vv, void, ptr, ptr, ptr, ptr, env, i32)
53
DEF_HELPER_6(vfwmaccbf16_vf, void, ptr, ptr, i64, ptr, env, i32)
54
+
55
+/* Vector crypto functions */
56
+DEF_HELPER_6(vclmul_vv, void, ptr, ptr, ptr, ptr, env, i32)
57
+DEF_HELPER_6(vclmul_vx, void, ptr, ptr, tl, ptr, env, i32)
58
+DEF_HELPER_6(vclmulh_vv, void, ptr, ptr, ptr, ptr, env, i32)
59
+DEF_HELPER_6(vclmulh_vx, void, ptr, ptr, tl, ptr, env, i32)
60
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
61
index XXXXXXX..XXXXXXX 100644
62
--- a/target/riscv/insn32.decode
63
+++ b/target/riscv/insn32.decode
64
@@ -XXX,XX +XXX,XX @@ vfwcvtbf16_f_f_v 010010 . ..... 01101 001 ..... 1010111 @r2_vm
65
# *** Zvfbfwma Standard Extension ***
66
vfwmaccbf16_vv 111011 . ..... ..... 001 ..... 1010111 @r_vm
67
vfwmaccbf16_vf 111011 . ..... ..... 101 ..... 1010111 @r_vm
68
+
69
+# *** Zvbc vector crypto extension ***
70
+vclmul_vv 001100 . ..... ..... 010 ..... 1010111 @r_vm
71
+vclmul_vx 001100 . ..... ..... 110 ..... 1010111 @r_vm
72
+vclmulh_vv 001101 . ..... ..... 010 ..... 1010111 @r_vm
73
+vclmulh_vx 001101 . ..... ..... 110 ..... 1010111 @r_vm
74
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
75
index XXXXXXX..XXXXXXX 100644
76
--- a/target/riscv/cpu.c
77
+++ b/target/riscv/cpu.c
78
@@ -XXX,XX +XXX,XX @@ static const struct isa_ext_data isa_edata_arr[] = {
79
ISA_EXT_DATA_ENTRY(zksed, PRIV_VERSION_1_12_0, ext_zksed),
80
ISA_EXT_DATA_ENTRY(zksh, PRIV_VERSION_1_12_0, ext_zksh),
81
ISA_EXT_DATA_ENTRY(zkt, PRIV_VERSION_1_12_0, ext_zkt),
82
+ ISA_EXT_DATA_ENTRY(zvbc, PRIV_VERSION_1_12_0, ext_zvbc),
83
ISA_EXT_DATA_ENTRY(zve32f, PRIV_VERSION_1_10_0, ext_zve32f),
84
ISA_EXT_DATA_ENTRY(zve64f, PRIV_VERSION_1_10_0, ext_zve64f),
85
ISA_EXT_DATA_ENTRY(zve64d, PRIV_VERSION_1_10_0, ext_zve64d),
86
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
87
return;
88
}
89
90
+ if (cpu->cfg.ext_zvbc && !cpu->cfg.ext_zve64f) {
91
+ error_setg(errp, "Zvbc extension requires V or Zve64{f,d} extensions");
92
+ return;
93
+ }
94
+
95
if (cpu->cfg.ext_zk) {
96
cpu->cfg.ext_zkn = true;
97
cpu->cfg.ext_zkr = true;
98
@@ -XXX,XX +XXX,XX @@ static Property riscv_cpu_extensions[] = {
99
DEFINE_PROP_BOOL("x-zvfbfmin", RISCVCPU, cfg.ext_zvfbfmin, false),
100
DEFINE_PROP_BOOL("x-zvfbfwma", RISCVCPU, cfg.ext_zvfbfwma, false),
101
102
+ /* Vector cryptography extensions */
103
+ DEFINE_PROP_BOOL("x-zvbc", RISCVCPU, cfg.ext_zvbc, false),
104
+
105
DEFINE_PROP_END_OF_LIST(),
106
};
107
108
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
109
index XXXXXXX..XXXXXXX 100644
110
--- a/target/riscv/translate.c
111
+++ b/target/riscv/translate.c
112
@@ -XXX,XX +XXX,XX @@ static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
113
#include "insn_trans/trans_rvzfa.c.inc"
114
#include "insn_trans/trans_rvzfh.c.inc"
115
#include "insn_trans/trans_rvk.c.inc"
116
+#include "insn_trans/trans_rvvk.c.inc"
117
#include "insn_trans/trans_privileged.c.inc"
118
#include "insn_trans/trans_svinval.c.inc"
119
#include "insn_trans/trans_rvbf16.c.inc"
120
diff --git a/target/riscv/vcrypto_helper.c b/target/riscv/vcrypto_helper.c
23
new file mode 100644
121
new file mode 100644
24
index XXXXXXX..XXXXXXX
122
index XXXXXXX..XXXXXXX
25
--- /dev/null
123
--- /dev/null
26
+++ b/include/hw/timer/sifive_pwm.h
124
+++ b/target/riscv/vcrypto_helper.c
27
@@ -XXX,XX +XXX,XX @@
125
@@ -XXX,XX +XXX,XX @@
28
+/*
126
+/*
29
+ * SiFive PWM
127
+ * RISC-V Vector Crypto Extension Helpers for QEMU.
30
+ *
128
+ *
31
+ * Copyright (c) 2020 Western Digital
129
+ * Copyright (C) 2023 SiFive, Inc.
32
+ *
130
+ * Written by Codethink Ltd and SiFive.
33
+ * Author: Alistair Francis <alistair.francis@wdc.com>
131
+ *
34
+ *
132
+ * This program is free software; you can redistribute it and/or modify it
35
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
133
+ * under the terms and conditions of the GNU General Public License,
36
+ * of this software and associated documentation files (the "Software"), to deal
134
+ * version 2 or later, as published by the Free Software Foundation.
37
+ * in the Software without restriction, including without limitation the rights
135
+ *
38
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
136
+ * This program is distributed in the hope it will be useful, but WITHOUT
39
+ * copies of the Software, and to permit persons to whom the Software is
137
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
40
+ * furnished to do so, subject to the following conditions:
138
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
41
+ *
139
+ * more details.
42
+ * The above copyright notice and this permission notice shall be included in
140
+ *
43
+ * all copies or substantial portions of the Software.
141
+ * You should have received a copy of the GNU General Public License along with
44
+ *
142
+ * this program. If not, see <http://www.gnu.org/licenses/>.
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
+ */
143
+ */
53
+
144
+
54
+#ifndef HW_SIFIVE_PWM_H
145
+#include "qemu/osdep.h"
55
+#define HW_SIFIVE_PWM_H
146
+#include "qemu/host-utils.h"
56
+
147
+#include "qemu/bitops.h"
57
+#include "hw/sysbus.h"
148
+#include "cpu.h"
58
+#include "qemu/timer.h"
149
+#include "exec/memop.h"
59
+#include "qom/object.h"
150
+#include "exec/exec-all.h"
60
+
151
+#include "exec/helper-proto.h"
61
+#define TYPE_SIFIVE_PWM "sifive-pwm"
152
+#include "internals.h"
62
+
153
+#include "vector_internals.h"
63
+#define SIFIVE_PWM(obj) \
154
+
64
+ OBJECT_CHECK(SiFivePwmState, (obj), TYPE_SIFIVE_PWM)
155
+static uint64_t clmul64(uint64_t y, uint64_t x)
65
+
156
+{
66
+#define SIFIVE_PWM_CHANS 4
157
+ uint64_t result = 0;
67
+#define SIFIVE_PWM_IRQS SIFIVE_PWM_CHANS
158
+ for (int j = 63; j >= 0; j--) {
68
+
159
+ if ((y >> j) & 1) {
69
+typedef struct SiFivePwmState {
160
+ result ^= (x << j);
70
+ /* <private> */
161
+ }
71
+ SysBusDevice parent_obj;
162
+ }
72
+
163
+ return result;
73
+ /* <public> */
164
+}
74
+ MemoryRegion mmio;
165
+
75
+ QEMUTimer timer[SIFIVE_PWM_CHANS];
166
+static uint64_t clmulh64(uint64_t y, uint64_t x)
76
+ /*
167
+{
77
+ * if en bit(s) set, is the number of ticks when pwmcount was 0
168
+ uint64_t result = 0;
78
+ * if en bit(s) not set, is the number of ticks in pwmcount
169
+ for (int j = 63; j >= 1; j--) {
79
+ */
170
+ if ((y >> j) & 1) {
80
+ uint64_t tick_offset;
171
+ result ^= (x >> (64 - j));
81
+ uint64_t freq_hz;
172
+ }
82
+
173
+ }
83
+ uint32_t pwmcfg;
174
+ return result;
84
+ uint32_t pwmcmp[SIFIVE_PWM_CHANS];
175
+}
85
+
176
+
86
+ qemu_irq irqs[SIFIVE_PWM_IRQS];
177
+RVVCALL(OPIVV2, vclmul_vv, OP_UUU_D, H8, H8, H8, clmul64)
87
+} SiFivePwmState;
178
+GEN_VEXT_VV(vclmul_vv, 8)
88
+
179
+RVVCALL(OPIVX2, vclmul_vx, OP_UUU_D, H8, H8, clmul64)
89
+#endif /* HW_SIFIVE_PWM_H */
180
+GEN_VEXT_VX(vclmul_vx, 8)
90
diff --git a/hw/timer/sifive_pwm.c b/hw/timer/sifive_pwm.c
181
+RVVCALL(OPIVV2, vclmulh_vv, OP_UUU_D, H8, H8, H8, clmulh64)
182
+GEN_VEXT_VV(vclmulh_vv, 8)
183
+RVVCALL(OPIVX2, vclmulh_vx, OP_UUU_D, H8, H8, clmulh64)
184
+GEN_VEXT_VX(vclmulh_vx, 8)
185
diff --git a/target/riscv/insn_trans/trans_rvvk.c.inc b/target/riscv/insn_trans/trans_rvvk.c.inc
91
new file mode 100644
186
new file mode 100644
92
index XXXXXXX..XXXXXXX
187
index XXXXXXX..XXXXXXX
93
--- /dev/null
188
--- /dev/null
94
+++ b/hw/timer/sifive_pwm.c
189
+++ b/target/riscv/insn_trans/trans_rvvk.c.inc
95
@@ -XXX,XX +XXX,XX @@
190
@@ -XXX,XX +XXX,XX @@
96
+/*
191
+/*
97
+ * SiFive PWM
192
+ * RISC-V translation routines for the vector crypto extension.
98
+ *
193
+ *
99
+ * Copyright (c) 2020 Western Digital
194
+ * Copyright (C) 2023 SiFive, Inc.
100
+ *
195
+ * Written by Codethink Ltd and SiFive.
101
+ * Author: Alistair Francis <alistair.francis@wdc.com>
196
+ *
102
+ *
197
+ * This program is free software; you can redistribute it and/or modify it
103
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
198
+ * under the terms and conditions of the GNU General Public License,
104
+ * of this software and associated documentation files (the "Software"), to deal
199
+ * version 2 or later, as published by the Free Software Foundation.
105
+ * in the Software without restriction, including without limitation the rights
200
+ *
106
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
201
+ * This program is distributed in the hope it will be useful, but WITHOUT
107
+ * copies of the Software, and to permit persons to whom the Software is
202
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
108
+ * furnished to do so, subject to the following conditions:
203
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
109
+ *
204
+ * more details.
110
+ * The above copyright notice and this permission notice shall be included in
205
+ *
111
+ * all copies or substantial portions of the Software.
206
+ * You should have received a copy of the GNU General Public License along with
112
+ *
207
+ * this program. If not, see <http://www.gnu.org/licenses/>.
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
+ */
208
+ */
121
+
209
+
122
+#include "qemu/osdep.h"
210
+/*
123
+#include "trace.h"
211
+ * Zvbc
124
+#include "hw/irq.h"
212
+ */
125
+#include "hw/timer/sifive_pwm.h"
213
+
126
+#include "hw/qdev-properties.h"
214
+#define GEN_VV_MASKED_TRANS(NAME, CHECK) \
127
+#include "hw/registerfields.h"
215
+ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
128
+#include "migration/vmstate.h"
216
+ { \
129
+#include "qemu/log.h"
217
+ if (CHECK(s, a)) { \
130
+#include "qemu/module.h"
218
+ return opivv_trans(a->rd, a->rs1, a->rs2, a->vm, \
131
+
219
+ gen_helper_##NAME, s); \
132
+#define HAS_PWM_EN_BITS(cfg) ((cfg & R_CONFIG_ENONESHOT_MASK) || \
220
+ } \
133
+ (cfg & R_CONFIG_ENALWAYS_MASK))
221
+ return false; \
134
+
222
+ }
135
+#define PWMCMP_MASK 0xFFFF
223
+
136
+#define PWMCOUNT_MASK 0x7FFFFFFF
224
+static bool vclmul_vv_check(DisasContext *s, arg_rmrr *a)
137
+
225
+{
138
+REG32(CONFIG, 0x00)
226
+ return opivv_check(s, a) &&
139
+ FIELD(CONFIG, SCALE, 0, 4)
227
+ s->cfg_ptr->ext_zvbc == true &&
140
+ FIELD(CONFIG, STICKY, 8, 1)
228
+ s->sew == MO_64;
141
+ FIELD(CONFIG, ZEROCMP, 9, 1)
229
+}
142
+ FIELD(CONFIG, DEGLITCH, 10, 1)
230
+
143
+ FIELD(CONFIG, ENALWAYS, 12, 1)
231
+GEN_VV_MASKED_TRANS(vclmul_vv, vclmul_vv_check)
144
+ FIELD(CONFIG, ENONESHOT, 13, 1)
232
+GEN_VV_MASKED_TRANS(vclmulh_vv, vclmul_vv_check)
145
+ FIELD(CONFIG, CMP0CENTER, 16, 1)
233
+
146
+ FIELD(CONFIG, CMP1CENTER, 17, 1)
234
+#define GEN_VX_MASKED_TRANS(NAME, CHECK) \
147
+ FIELD(CONFIG, CMP2CENTER, 18, 1)
235
+ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
148
+ FIELD(CONFIG, CMP3CENTER, 19, 1)
236
+ { \
149
+ FIELD(CONFIG, CMP0GANG, 24, 1)
237
+ if (CHECK(s, a)) { \
150
+ FIELD(CONFIG, CMP1GANG, 25, 1)
238
+ return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, \
151
+ FIELD(CONFIG, CMP2GANG, 26, 1)
239
+ gen_helper_##NAME, s); \
152
+ FIELD(CONFIG, CMP3GANG, 27, 1)
240
+ } \
153
+ FIELD(CONFIG, CMP0IP, 28, 1)
241
+ return false; \
154
+ FIELD(CONFIG, CMP1IP, 29, 1)
242
+ }
155
+ FIELD(CONFIG, CMP2IP, 30, 1)
243
+
156
+ FIELD(CONFIG, CMP3IP, 31, 1)
244
+static bool vclmul_vx_check(DisasContext *s, arg_rmrr *a)
157
+REG32(COUNT, 0x08)
245
+{
158
+REG32(PWMS, 0x10)
246
+ return opivx_check(s, a) &&
159
+REG32(PWMCMP0, 0x20)
247
+ s->cfg_ptr->ext_zvbc == true &&
160
+REG32(PWMCMP1, 0x24)
248
+ s->sew == MO_64;
161
+REG32(PWMCMP2, 0x28)
249
+}
162
+REG32(PWMCMP3, 0x2C)
250
+
163
+
251
+GEN_VX_MASKED_TRANS(vclmul_vx, vclmul_vx_check)
164
+static inline uint64_t sifive_pwm_ns_to_ticks(SiFivePwmState *s,
252
+GEN_VX_MASKED_TRANS(vclmulh_vx, vclmul_vx_check)
165
+ uint64_t time)
253
diff --git a/target/riscv/meson.build b/target/riscv/meson.build
166
+{
254
index XXXXXXX..XXXXXXX 100644
167
+ return muldiv64(time, s->freq_hz, NANOSECONDS_PER_SECOND);
255
--- a/target/riscv/meson.build
168
+}
256
+++ b/target/riscv/meson.build
169
+
257
@@ -XXX,XX +XXX,XX @@ riscv_ss.add(files(
170
+static inline uint64_t sifive_pwm_ticks_to_ns(SiFivePwmState *s,
258
'translate.c',
171
+ uint64_t ticks)
259
'm128_helper.c',
172
+{
260
'crypto_helper.c',
173
+ return muldiv64(ticks, NANOSECONDS_PER_SECOND, s->freq_hz);
261
- 'zce_helper.c'
174
+}
262
+ 'zce_helper.c',
175
+
263
+ 'vcrypto_helper.c'
176
+static inline uint64_t sifive_pwm_compute_scale(SiFivePwmState *s)
264
))
177
+{
265
riscv_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'), if_false: files('kvm-stub.c'))
178
+ return s->pwmcfg & R_CONFIG_SCALE_MASK;
266
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
+ }
363
+
364
+ return 0;
365
+}
366
+
367
+static void sifive_pwm_write(void *opaque, hwaddr addr,
368
+ uint64_t val64, unsigned int size)
369
+{
370
+ SiFivePwmState *s = opaque;
371
+ uint32_t value = val64;
372
+ uint64_t new_offset, scale;
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
+}
468
+
469
+static void sifive_pwm_reset(DeviceState *dev)
470
+{
471
+ SiFivePwmState *s = SIFIVE_PWM(dev);
472
+ uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
473
+
474
+ s->pwmcfg = 0x00000000;
475
+ s->pwmcmp[0] = 0x00000000;
476
+ s->pwmcmp[1] = 0x00000000;
477
+ s->pwmcmp[2] = 0x00000000;
478
+ s->pwmcmp[3] = 0x00000000;
479
+
480
+ s->tick_offset = sifive_pwm_ns_to_ticks(s, now);
481
+}
482
+
483
+static const MemoryRegionOps sifive_pwm_ops = {
484
+ .read = sifive_pwm_read,
485
+ .write = sifive_pwm_write,
486
+ .endianness = DEVICE_NATIVE_ENDIAN,
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
+ }
500
+};
501
+
502
+static Property sifive_pwm_properties[] = {
503
+ /* 0.5Ghz per spec after FSBL */
504
+ DEFINE_PROP_UINT64("clock-frequency", struct SiFivePwmState,
505
+ freq_hz, 500000000ULL),
506
+ DEFINE_PROP_END_OF_LIST(),
507
+};
508
+
509
+static void sifive_pwm_init(Object *obj)
510
+{
511
+ SiFivePwmState *s = SIFIVE_PWM(obj);
512
+ int i;
513
+
514
+ for (i = 0; i < SIFIVE_PWM_IRQS; i++) {
515
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irqs[i]);
516
+ }
517
+
518
+ memory_region_init_io(&s->mmio, obj, &sifive_pwm_ops, s,
519
+ TYPE_SIFIVE_PWM, 0x100);
520
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
521
+}
522
+
523
+static void sifive_pwm_realize(DeviceState *dev, Error **errp)
524
+{
525
+ SiFivePwmState *s = SIFIVE_PWM(dev);
526
+
527
+ timer_init_ns(&s->timer[0], QEMU_CLOCK_VIRTUAL,
528
+ sifive_pwm_interrupt_0, s);
529
+
530
+ timer_init_ns(&s->timer[1], QEMU_CLOCK_VIRTUAL,
531
+ sifive_pwm_interrupt_1, s);
532
+
533
+ timer_init_ns(&s->timer[2], QEMU_CLOCK_VIRTUAL,
534
+ sifive_pwm_interrupt_2, s);
535
+
536
+ timer_init_ns(&s->timer[3], QEMU_CLOCK_VIRTUAL,
537
+ sifive_pwm_interrupt_3, s);
538
+}
539
+
540
+static void sifive_pwm_class_init(ObjectClass *klass, void *data)
541
+{
542
+ DeviceClass *dc = DEVICE_CLASS(klass);
543
+
544
+ dc->reset = sifive_pwm_reset;
545
+ device_class_set_props(dc, sifive_pwm_properties);
546
+ dc->vmsd = &vmstate_sifive_pwm;
547
+ dc->realize = sifive_pwm_realize;
548
+}
549
+
550
+static const TypeInfo sifive_pwm_info = {
551
+ .name = TYPE_SIFIVE_PWM,
552
+ .parent = TYPE_SYS_BUS_DEVICE,
553
+ .instance_size = sizeof(SiFivePwmState),
554
+ .instance_init = sifive_pwm_init,
555
+ .class_init = sifive_pwm_class_init,
556
+};
557
+
558
+static void sifive_pwm_register_types(void)
559
+{
560
+ type_register_static(&sifive_pwm_info);
561
+}
562
+
563
+type_init(sifive_pwm_register_types)
564
diff --git a/hw/timer/Kconfig b/hw/timer/Kconfig
565
index XXXXXXX..XXXXXXX 100644
566
--- a/hw/timer/Kconfig
567
+++ b/hw/timer/Kconfig
568
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_A10_PIT
569
bool
570
select PTIMER
571
572
+config SIFIVE_PWM
573
+ bool
574
+
575
config STM32F2XX_TIMER
576
bool
577
578
diff --git a/hw/timer/meson.build b/hw/timer/meson.build
579
index XXXXXXX..XXXXXXX 100644
580
--- a/hw/timer/meson.build
581
+++ b/hw/timer/meson.build
582
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_STELLARIS_GPTM', if_true: files('stellaris-gptm.c')
583
softmmu_ss.add(when: 'CONFIG_STM32F2XX_TIMER', if_true: files('stm32f2xx_timer.c'))
584
softmmu_ss.add(when: 'CONFIG_XILINX', if_true: files('xilinx_timer.c'))
585
specific_ss.add(when: 'CONFIG_IBEX', if_true: files('ibex_timer.c'))
586
+softmmu_ss.add(when: 'CONFIG_SIFIVE_PWM', if_true: files('sifive_pwm.c'))
587
588
specific_ss.add(when: 'CONFIG_AVR_TIMER16', if_true: files('avr_timer16.c'))
589
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
590
index XXXXXXX..XXXXXXX 100644
591
--- a/hw/timer/trace-events
592
+++ b/hw/timer/trace-events
593
@@ -XXX,XX +XXX,XX @@ sse_counter_reset(void) "SSE system counter: reset"
594
sse_timer_read(uint64_t offset, uint64_t data, unsigned size) "SSE system timer read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
595
sse_timer_write(uint64_t offset, uint64_t data, unsigned size) "SSE system timer write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
596
sse_timer_reset(void) "SSE system timer: reset"
597
+
598
+# sifive_pwm.c
599
+sifive_pwm_set_alarm(uint64_t alarm, uint64_t now) "Setting alarm to: 0x%" PRIx64 ", now: 0x%" PRIx64
600
+sifive_pwm_interrupt(int num) "Interrupt %d"
601
+sifive_pwm_read(uint64_t offset) "Read at address: 0x%" PRIx64
602
+sifive_pwm_write(uint64_t data, uint64_t offset) "Write 0x%" PRIx64 " at address: 0x%" PRIx64
603
--
267
--
604
2.31.1
268
2.41.0
605
606
diff view generated by jsdifflib
New patch
1
From: Nazar Kazakov <nazar.kazakov@codethink.co.uk>
1
2
3
Move the checks out of `do_opiv{v,x,i}_gvec{,_shift}` functions
4
and into the corresponding macros. This enables the functions to be
5
reused in proceeding commits without check duplication.
6
7
Signed-off-by: Nazar Kazakov <nazar.kazakov@codethink.co.uk>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Weiwei Li <liweiwei@iscas.ac.cn>
10
Signed-off-by: Max Chou <max.chou@sifive.com>
11
Message-ID: <20230711165917.2629866-6-max.chou@sifive.com>
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
13
---
14
target/riscv/insn_trans/trans_rvv.c.inc | 28 +++++++++++--------------
15
1 file changed, 12 insertions(+), 16 deletions(-)
16
17
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
19
--- a/target/riscv/insn_trans/trans_rvv.c.inc
20
+++ b/target/riscv/insn_trans/trans_rvv.c.inc
21
@@ -XXX,XX +XXX,XX @@ do_opivv_gvec(DisasContext *s, arg_rmrr *a, GVecGen3Fn *gvec_fn,
22
gen_helper_gvec_4_ptr *fn)
23
{
24
TCGLabel *over = gen_new_label();
25
- if (!opivv_check(s, a)) {
26
- return false;
27
- }
28
29
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
30
31
@@ -XXX,XX +XXX,XX @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
32
gen_helper_##NAME##_b, gen_helper_##NAME##_h, \
33
gen_helper_##NAME##_w, gen_helper_##NAME##_d, \
34
}; \
35
+ if (!opivv_check(s, a)) { \
36
+ return false; \
37
+ } \
38
return do_opivv_gvec(s, a, tcg_gen_gvec_##SUF, fns[s->sew]); \
39
}
40
41
@@ -XXX,XX +XXX,XX @@ static inline bool
42
do_opivx_gvec(DisasContext *s, arg_rmrr *a, GVecGen2sFn *gvec_fn,
43
gen_helper_opivx *fn)
44
{
45
- if (!opivx_check(s, a)) {
46
- return false;
47
- }
48
-
49
if (a->vm && s->vl_eq_vlmax && !(s->vta && s->lmul < 0)) {
50
TCGv_i64 src1 = tcg_temp_new_i64();
51
52
@@ -XXX,XX +XXX,XX @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
53
gen_helper_##NAME##_b, gen_helper_##NAME##_h, \
54
gen_helper_##NAME##_w, gen_helper_##NAME##_d, \
55
}; \
56
+ if (!opivx_check(s, a)) { \
57
+ return false; \
58
+ } \
59
return do_opivx_gvec(s, a, tcg_gen_gvec_##SUF, fns[s->sew]); \
60
}
61
62
@@ -XXX,XX +XXX,XX @@ static inline bool
63
do_opivi_gvec(DisasContext *s, arg_rmrr *a, GVecGen2iFn *gvec_fn,
64
gen_helper_opivx *fn, imm_mode_t imm_mode)
65
{
66
- if (!opivx_check(s, a)) {
67
- return false;
68
- }
69
-
70
if (a->vm && s->vl_eq_vlmax && !(s->vta && s->lmul < 0)) {
71
gvec_fn(s->sew, vreg_ofs(s, a->rd), vreg_ofs(s, a->rs2),
72
extract_imm(s, a->rs1, imm_mode), MAXSZ(s), MAXSZ(s));
73
@@ -XXX,XX +XXX,XX @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
74
gen_helper_##OPIVX##_b, gen_helper_##OPIVX##_h, \
75
gen_helper_##OPIVX##_w, gen_helper_##OPIVX##_d, \
76
}; \
77
+ if (!opivx_check(s, a)) { \
78
+ return false; \
79
+ } \
80
return do_opivi_gvec(s, a, tcg_gen_gvec_##SUF, \
81
fns[s->sew], IMM_MODE); \
82
}
83
@@ -XXX,XX +XXX,XX @@ static inline bool
84
do_opivx_gvec_shift(DisasContext *s, arg_rmrr *a, GVecGen2sFn32 *gvec_fn,
85
gen_helper_opivx *fn)
86
{
87
- if (!opivx_check(s, a)) {
88
- return false;
89
- }
90
-
91
if (a->vm && s->vl_eq_vlmax && !(s->vta && s->lmul < 0)) {
92
TCGv_i32 src1 = tcg_temp_new_i32();
93
94
@@ -XXX,XX +XXX,XX @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
95
gen_helper_##NAME##_b, gen_helper_##NAME##_h, \
96
gen_helper_##NAME##_w, gen_helper_##NAME##_d, \
97
}; \
98
- \
99
+ if (!opivx_check(s, a)) { \
100
+ return false; \
101
+ } \
102
return do_opivx_gvec_shift(s, a, tcg_gen_gvec_##SUF, fns[s->sew]); \
103
}
104
105
--
106
2.41.0
diff view generated by jsdifflib
New patch
1
From: Dickon Hood <dickon.hood@codethink.co.uk>
1
2
3
Zvbb (implemented in later commit) has a widening instruction, which
4
requires an extra check on the enabled extensions. Refactor
5
GEN_OPIVX_WIDEN_TRANS() to take a check function to avoid reimplementing
6
it.
7
8
Signed-off-by: Dickon Hood <dickon.hood@codethink.co.uk>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Weiwei Li <liweiwei@iscas.ac.cn>
11
Signed-off-by: Max Chou <max.chou@sifive.com>
12
Message-ID: <20230711165917.2629866-7-max.chou@sifive.com>
13
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
14
---
15
target/riscv/insn_trans/trans_rvv.c.inc | 52 +++++++++++--------------
16
1 file changed, 23 insertions(+), 29 deletions(-)
17
18
diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/riscv/insn_trans/trans_rvv.c.inc
21
+++ b/target/riscv/insn_trans/trans_rvv.c.inc
22
@@ -XXX,XX +XXX,XX @@ static bool opivx_widen_check(DisasContext *s, arg_rmrr *a)
23
vext_check_ds(s, a->rd, a->rs2, a->vm);
24
}
25
26
-static bool do_opivx_widen(DisasContext *s, arg_rmrr *a,
27
- gen_helper_opivx *fn)
28
-{
29
- if (opivx_widen_check(s, a)) {
30
- return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, fn, s);
31
- }
32
- return false;
33
-}
34
-
35
-#define GEN_OPIVX_WIDEN_TRANS(NAME) \
36
-static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
37
-{ \
38
- static gen_helper_opivx * const fns[3] = { \
39
- gen_helper_##NAME##_b, \
40
- gen_helper_##NAME##_h, \
41
- gen_helper_##NAME##_w \
42
- }; \
43
- return do_opivx_widen(s, a, fns[s->sew]); \
44
+#define GEN_OPIVX_WIDEN_TRANS(NAME, CHECK) \
45
+static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
46
+{ \
47
+ if (CHECK(s, a)) { \
48
+ static gen_helper_opivx * const fns[3] = { \
49
+ gen_helper_##NAME##_b, \
50
+ gen_helper_##NAME##_h, \
51
+ gen_helper_##NAME##_w \
52
+ }; \
53
+ return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, fns[s->sew], s); \
54
+ } \
55
+ return false; \
56
}
57
58
-GEN_OPIVX_WIDEN_TRANS(vwaddu_vx)
59
-GEN_OPIVX_WIDEN_TRANS(vwadd_vx)
60
-GEN_OPIVX_WIDEN_TRANS(vwsubu_vx)
61
-GEN_OPIVX_WIDEN_TRANS(vwsub_vx)
62
+GEN_OPIVX_WIDEN_TRANS(vwaddu_vx, opivx_widen_check)
63
+GEN_OPIVX_WIDEN_TRANS(vwadd_vx, opivx_widen_check)
64
+GEN_OPIVX_WIDEN_TRANS(vwsubu_vx, opivx_widen_check)
65
+GEN_OPIVX_WIDEN_TRANS(vwsub_vx, opivx_widen_check)
66
67
/* WIDEN OPIVV with WIDEN */
68
static bool opiwv_widen_check(DisasContext *s, arg_rmrr *a)
69
@@ -XXX,XX +XXX,XX @@ GEN_OPIVX_TRANS(vrem_vx, opivx_check)
70
GEN_OPIVV_WIDEN_TRANS(vwmul_vv, opivv_widen_check)
71
GEN_OPIVV_WIDEN_TRANS(vwmulu_vv, opivv_widen_check)
72
GEN_OPIVV_WIDEN_TRANS(vwmulsu_vv, opivv_widen_check)
73
-GEN_OPIVX_WIDEN_TRANS(vwmul_vx)
74
-GEN_OPIVX_WIDEN_TRANS(vwmulu_vx)
75
-GEN_OPIVX_WIDEN_TRANS(vwmulsu_vx)
76
+GEN_OPIVX_WIDEN_TRANS(vwmul_vx, opivx_widen_check)
77
+GEN_OPIVX_WIDEN_TRANS(vwmulu_vx, opivx_widen_check)
78
+GEN_OPIVX_WIDEN_TRANS(vwmulsu_vx, opivx_widen_check)
79
80
/* Vector Single-Width Integer Multiply-Add Instructions */
81
GEN_OPIVV_TRANS(vmacc_vv, opivv_check)
82
@@ -XXX,XX +XXX,XX @@ GEN_OPIVX_TRANS(vnmsub_vx, opivx_check)
83
GEN_OPIVV_WIDEN_TRANS(vwmaccu_vv, opivv_widen_check)
84
GEN_OPIVV_WIDEN_TRANS(vwmacc_vv, opivv_widen_check)
85
GEN_OPIVV_WIDEN_TRANS(vwmaccsu_vv, opivv_widen_check)
86
-GEN_OPIVX_WIDEN_TRANS(vwmaccu_vx)
87
-GEN_OPIVX_WIDEN_TRANS(vwmacc_vx)
88
-GEN_OPIVX_WIDEN_TRANS(vwmaccsu_vx)
89
-GEN_OPIVX_WIDEN_TRANS(vwmaccus_vx)
90
+GEN_OPIVX_WIDEN_TRANS(vwmaccu_vx, opivx_widen_check)
91
+GEN_OPIVX_WIDEN_TRANS(vwmacc_vx, opivx_widen_check)
92
+GEN_OPIVX_WIDEN_TRANS(vwmaccsu_vx, opivx_widen_check)
93
+GEN_OPIVX_WIDEN_TRANS(vwmaccus_vx, opivx_widen_check)
94
95
/* Vector Integer Merge and Move Instructions */
96
static bool trans_vmv_v_v(DisasContext *s, arg_vmv_v_v *a)
97
--
98
2.41.0
diff view generated by jsdifflib
New patch
1
From: Kiran Ostrolenk <kiran.ostrolenk@codethink.co.uk>
1
2
3
Move some macros out of `vector_helper` and into `vector_internals`.
4
This ensures they can be used by both vector and vector-crypto helpers
5
(latter implemented in proceeding commits).
6
7
Signed-off-by: Kiran Ostrolenk <kiran.ostrolenk@codethink.co.uk>
8
Reviewed-by: Weiwei Li <liweiwei@iscas.ac.cn>
9
Signed-off-by: Max Chou <max.chou@sifive.com>
10
Message-ID: <20230711165917.2629866-8-max.chou@sifive.com>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
---
13
target/riscv/vector_internals.h | 46 +++++++++++++++++++++++++++++++++
14
target/riscv/vector_helper.c | 42 ------------------------------
15
2 files changed, 46 insertions(+), 42 deletions(-)
16
17
diff --git a/target/riscv/vector_internals.h b/target/riscv/vector_internals.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/riscv/vector_internals.h
20
+++ b/target/riscv/vector_internals.h
21
@@ -XXX,XX +XXX,XX @@ void vext_set_elems_1s(void *base, uint32_t is_agnostic, uint32_t cnt,
22
/* expand macro args before macro */
23
#define RVVCALL(macro, ...) macro(__VA_ARGS__)
24
25
+/* (TD, T2, TX2) */
26
+#define OP_UU_B uint8_t, uint8_t, uint8_t
27
+#define OP_UU_H uint16_t, uint16_t, uint16_t
28
+#define OP_UU_W uint32_t, uint32_t, uint32_t
29
+#define OP_UU_D uint64_t, uint64_t, uint64_t
30
+
31
/* (TD, T1, T2, TX1, TX2) */
32
#define OP_UUU_B uint8_t, uint8_t, uint8_t, uint8_t, uint8_t
33
#define OP_UUU_H uint16_t, uint16_t, uint16_t, uint16_t, uint16_t
34
#define OP_UUU_W uint32_t, uint32_t, uint32_t, uint32_t, uint32_t
35
#define OP_UUU_D uint64_t, uint64_t, uint64_t, uint64_t, uint64_t
36
37
+#define OPIVV1(NAME, TD, T2, TX2, HD, HS2, OP) \
38
+static void do_##NAME(void *vd, void *vs2, int i) \
39
+{ \
40
+ TX2 s2 = *((T2 *)vs2 + HS2(i)); \
41
+ *((TD *)vd + HD(i)) = OP(s2); \
42
+}
43
+
44
+#define GEN_VEXT_V(NAME, ESZ) \
45
+void HELPER(NAME)(void *vd, void *v0, void *vs2, \
46
+ CPURISCVState *env, uint32_t desc) \
47
+{ \
48
+ uint32_t vm = vext_vm(desc); \
49
+ uint32_t vl = env->vl; \
50
+ uint32_t total_elems = \
51
+ vext_get_total_elems(env, desc, ESZ); \
52
+ uint32_t vta = vext_vta(desc); \
53
+ uint32_t vma = vext_vma(desc); \
54
+ uint32_t i; \
55
+ \
56
+ for (i = env->vstart; i < vl; i++) { \
57
+ if (!vm && !vext_elem_mask(v0, i)) { \
58
+ /* set masked-off elements to 1s */ \
59
+ vext_set_elems_1s(vd, vma, i * ESZ, \
60
+ (i + 1) * ESZ); \
61
+ continue; \
62
+ } \
63
+ do_##NAME(vd, vs2, i); \
64
+ } \
65
+ env->vstart = 0; \
66
+ /* set tail elements to 1s */ \
67
+ vext_set_elems_1s(vd, vta, vl * ESZ, \
68
+ total_elems * ESZ); \
69
+}
70
+
71
/* operation of two vector elements */
72
typedef void opivv2_fn(void *vd, void *vs1, void *vs2, int i);
73
74
@@ -XXX,XX +XXX,XX @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, \
75
do_##NAME, ESZ); \
76
}
77
78
+/* Three of the widening shortening macros: */
79
+/* (TD, T1, T2, TX1, TX2) */
80
+#define WOP_UUU_B uint16_t, uint8_t, uint8_t, uint16_t, uint16_t
81
+#define WOP_UUU_H uint32_t, uint16_t, uint16_t, uint32_t, uint32_t
82
+#define WOP_UUU_W uint64_t, uint32_t, uint32_t, uint64_t, uint64_t
83
+
84
#endif /* TARGET_RISCV_VECTOR_INTERNALS_H */
85
diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
86
index XXXXXXX..XXXXXXX 100644
87
--- a/target/riscv/vector_helper.c
88
+++ b/target/riscv/vector_helper.c
89
@@ -XXX,XX +XXX,XX @@ GEN_VEXT_ST_WHOLE(vs8r_v, int8_t, ste_b)
90
#define OP_SUS_H int16_t, uint16_t, int16_t, uint16_t, int16_t
91
#define OP_SUS_W int32_t, uint32_t, int32_t, uint32_t, int32_t
92
#define OP_SUS_D int64_t, uint64_t, int64_t, uint64_t, int64_t
93
-#define WOP_UUU_B uint16_t, uint8_t, uint8_t, uint16_t, uint16_t
94
-#define WOP_UUU_H uint32_t, uint16_t, uint16_t, uint32_t, uint32_t
95
-#define WOP_UUU_W uint64_t, uint32_t, uint32_t, uint64_t, uint64_t
96
#define WOP_SSS_B int16_t, int8_t, int8_t, int16_t, int16_t
97
#define WOP_SSS_H int32_t, int16_t, int16_t, int32_t, int32_t
98
#define WOP_SSS_W int64_t, int32_t, int32_t, int64_t, int64_t
99
@@ -XXX,XX +XXX,XX @@ GEN_VEXT_VF(vfwnmsac_vf_h, 4)
100
GEN_VEXT_VF(vfwnmsac_vf_w, 8)
101
102
/* Vector Floating-Point Square-Root Instruction */
103
-/* (TD, T2, TX2) */
104
-#define OP_UU_H uint16_t, uint16_t, uint16_t
105
-#define OP_UU_W uint32_t, uint32_t, uint32_t
106
-#define OP_UU_D uint64_t, uint64_t, uint64_t
107
-
108
#define OPFVV1(NAME, TD, T2, TX2, HD, HS2, OP) \
109
static void do_##NAME(void *vd, void *vs2, int i, \
110
CPURISCVState *env) \
111
@@ -XXX,XX +XXX,XX @@ GEN_VEXT_CMP_VF(vmfge_vf_w, uint32_t, H4, vmfge32)
112
GEN_VEXT_CMP_VF(vmfge_vf_d, uint64_t, H8, vmfge64)
113
114
/* Vector Floating-Point Classify Instruction */
115
-#define OPIVV1(NAME, TD, T2, TX2, HD, HS2, OP) \
116
-static void do_##NAME(void *vd, void *vs2, int i) \
117
-{ \
118
- TX2 s2 = *((T2 *)vs2 + HS2(i)); \
119
- *((TD *)vd + HD(i)) = OP(s2); \
120
-}
121
-
122
-#define GEN_VEXT_V(NAME, ESZ) \
123
-void HELPER(NAME)(void *vd, void *v0, void *vs2, \
124
- CPURISCVState *env, uint32_t desc) \
125
-{ \
126
- uint32_t vm = vext_vm(desc); \
127
- uint32_t vl = env->vl; \
128
- uint32_t total_elems = \
129
- vext_get_total_elems(env, desc, ESZ); \
130
- uint32_t vta = vext_vta(desc); \
131
- uint32_t vma = vext_vma(desc); \
132
- uint32_t i; \
133
- \
134
- for (i = env->vstart; i < vl; i++) { \
135
- if (!vm && !vext_elem_mask(v0, i)) { \
136
- /* set masked-off elements to 1s */ \
137
- vext_set_elems_1s(vd, vma, i * ESZ, \
138
- (i + 1) * ESZ); \
139
- continue; \
140
- } \
141
- do_##NAME(vd, vs2, i); \
142
- } \
143
- env->vstart = 0; \
144
- /* set tail elements to 1s */ \
145
- vext_set_elems_1s(vd, vta, vl * ESZ, \
146
- total_elems * ESZ); \
147
-}
148
-
149
target_ulong fclass_h(uint64_t frs1)
150
{
151
float16 f = frs1;
152
--
153
2.41.0
diff view generated by jsdifflib
1
From: Anup Patel <anup.patel@wdc.com>
1
From: Dickon Hood <dickon.hood@codethink.co.uk>
2
2
3
The RISC-V ACLINT is more modular and backward compatible with
3
This commit adds support for the Zvbb vector-crypto extension, which
4
original SiFive CLINT so instead of duplicating the original
4
consists of the following instructions:
5
SiFive CLINT implementation we upgrade the current SiFive CLINT
6
implementation to RISC-V ACLINT implementation.
7
5
8
Signed-off-by: Anup Patel <anup.patel@wdc.com>
6
* vrol.[vv,vx]
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
7
* vror.[vv,vx,vi]
10
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
8
* vbrev8.v
11
Message-id: 20210831110603.338681-3-anup.patel@wdc.com
9
* vrev8.v
10
* vandn.[vv,vx]
11
* vbrev.v
12
* vclz.v
13
* vctz.v
14
* vcpop.v
15
* vwsll.[vv,vx,vi]
16
17
Translation functions are defined in
18
`target/riscv/insn_trans/trans_rvvk.c.inc` and helpers are defined in
19
`target/riscv/vcrypto_helper.c`.
20
21
Co-authored-by: Nazar Kazakov <nazar.kazakov@codethink.co.uk>
22
Co-authored-by: William Salmon <will.salmon@codethink.co.uk>
23
Co-authored-by: Kiran Ostrolenk <kiran.ostrolenk@codethink.co.uk>
24
[max.chou@sifive.com: Fix imm mode of vror.vi]
25
Signed-off-by: Nazar Kazakov <nazar.kazakov@codethink.co.uk>
26
Signed-off-by: William Salmon <will.salmon@codethink.co.uk>
27
Signed-off-by: Kiran Ostrolenk <kiran.ostrolenk@codethink.co.uk>
28
Signed-off-by: Dickon Hood <dickon.hood@codethink.co.uk>
29
Signed-off-by: Max Chou <max.chou@sifive.com>
30
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
31
[max.chou@sifive.com: Exposed x-zvbb property]
32
Message-ID: <20230711165917.2629866-9-max.chou@sifive.com>
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
33
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
13
---
34
---
14
include/hw/intc/riscv_aclint.h | 54 +++--
35
target/riscv/cpu_cfg.h | 1 +
15
hw/intc/riscv_aclint.c | 373 +++++++++++++++++++++++----------
36
target/riscv/helper.h | 62 +++++++++
16
hw/riscv/microchip_pfsoc.c | 9 +-
37
target/riscv/insn32.decode | 20 +++
17
hw/riscv/shakti_c.c | 11 +-
38
target/riscv/cpu.c | 12 ++
18
hw/riscv/sifive_e.c | 11 +-
39
target/riscv/vcrypto_helper.c | 138 +++++++++++++++++++
19
hw/riscv/sifive_u.c | 9 +-
40
target/riscv/insn_trans/trans_rvvk.c.inc | 164 +++++++++++++++++++++++
20
hw/riscv/spike.c | 14 +-
41
6 files changed, 397 insertions(+)
21
hw/riscv/virt.c | 14 +-
22
8 files changed, 339 insertions(+), 156 deletions(-)
23
42
24
diff --git a/include/hw/intc/riscv_aclint.h b/include/hw/intc/riscv_aclint.h
43
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
25
index XXXXXXX..XXXXXXX 100644
44
index XXXXXXX..XXXXXXX 100644
26
--- a/include/hw/intc/riscv_aclint.h
45
--- a/target/riscv/cpu_cfg.h
27
+++ b/include/hw/intc/riscv_aclint.h
46
+++ b/target/riscv/cpu_cfg.h
47
@@ -XXX,XX +XXX,XX @@ struct RISCVCPUConfig {
48
bool ext_zve32f;
49
bool ext_zve64f;
50
bool ext_zve64d;
51
+ bool ext_zvbb;
52
bool ext_zvbc;
53
bool ext_zmmul;
54
bool ext_zvfbfmin;
55
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
56
index XXXXXXX..XXXXXXX 100644
57
--- a/target/riscv/helper.h
58
+++ b/target/riscv/helper.h
59
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_6(vclmul_vv, void, ptr, ptr, ptr, ptr, env, i32)
60
DEF_HELPER_6(vclmul_vx, void, ptr, ptr, tl, ptr, env, i32)
61
DEF_HELPER_6(vclmulh_vv, void, ptr, ptr, ptr, ptr, env, i32)
62
DEF_HELPER_6(vclmulh_vx, void, ptr, ptr, tl, ptr, env, i32)
63
+
64
+DEF_HELPER_6(vror_vv_b, void, ptr, ptr, ptr, ptr, env, i32)
65
+DEF_HELPER_6(vror_vv_h, void, ptr, ptr, ptr, ptr, env, i32)
66
+DEF_HELPER_6(vror_vv_w, void, ptr, ptr, ptr, ptr, env, i32)
67
+DEF_HELPER_6(vror_vv_d, void, ptr, ptr, ptr, ptr, env, i32)
68
+
69
+DEF_HELPER_6(vror_vx_b, void, ptr, ptr, tl, ptr, env, i32)
70
+DEF_HELPER_6(vror_vx_h, void, ptr, ptr, tl, ptr, env, i32)
71
+DEF_HELPER_6(vror_vx_w, void, ptr, ptr, tl, ptr, env, i32)
72
+DEF_HELPER_6(vror_vx_d, void, ptr, ptr, tl, ptr, env, i32)
73
+
74
+DEF_HELPER_6(vrol_vv_b, void, ptr, ptr, ptr, ptr, env, i32)
75
+DEF_HELPER_6(vrol_vv_h, void, ptr, ptr, ptr, ptr, env, i32)
76
+DEF_HELPER_6(vrol_vv_w, void, ptr, ptr, ptr, ptr, env, i32)
77
+DEF_HELPER_6(vrol_vv_d, void, ptr, ptr, ptr, ptr, env, i32)
78
+
79
+DEF_HELPER_6(vrol_vx_b, void, ptr, ptr, tl, ptr, env, i32)
80
+DEF_HELPER_6(vrol_vx_h, void, ptr, ptr, tl, ptr, env, i32)
81
+DEF_HELPER_6(vrol_vx_w, void, ptr, ptr, tl, ptr, env, i32)
82
+DEF_HELPER_6(vrol_vx_d, void, ptr, ptr, tl, ptr, env, i32)
83
+
84
+DEF_HELPER_5(vrev8_v_b, void, ptr, ptr, ptr, env, i32)
85
+DEF_HELPER_5(vrev8_v_h, void, ptr, ptr, ptr, env, i32)
86
+DEF_HELPER_5(vrev8_v_w, void, ptr, ptr, ptr, env, i32)
87
+DEF_HELPER_5(vrev8_v_d, void, ptr, ptr, ptr, env, i32)
88
+DEF_HELPER_5(vbrev8_v_b, void, ptr, ptr, ptr, env, i32)
89
+DEF_HELPER_5(vbrev8_v_h, void, ptr, ptr, ptr, env, i32)
90
+DEF_HELPER_5(vbrev8_v_w, void, ptr, ptr, ptr, env, i32)
91
+DEF_HELPER_5(vbrev8_v_d, void, ptr, ptr, ptr, env, i32)
92
+DEF_HELPER_5(vbrev_v_b, void, ptr, ptr, ptr, env, i32)
93
+DEF_HELPER_5(vbrev_v_h, void, ptr, ptr, ptr, env, i32)
94
+DEF_HELPER_5(vbrev_v_w, void, ptr, ptr, ptr, env, i32)
95
+DEF_HELPER_5(vbrev_v_d, void, ptr, ptr, ptr, env, i32)
96
+
97
+DEF_HELPER_5(vclz_v_b, void, ptr, ptr, ptr, env, i32)
98
+DEF_HELPER_5(vclz_v_h, void, ptr, ptr, ptr, env, i32)
99
+DEF_HELPER_5(vclz_v_w, void, ptr, ptr, ptr, env, i32)
100
+DEF_HELPER_5(vclz_v_d, void, ptr, ptr, ptr, env, i32)
101
+DEF_HELPER_5(vctz_v_b, void, ptr, ptr, ptr, env, i32)
102
+DEF_HELPER_5(vctz_v_h, void, ptr, ptr, ptr, env, i32)
103
+DEF_HELPER_5(vctz_v_w, void, ptr, ptr, ptr, env, i32)
104
+DEF_HELPER_5(vctz_v_d, void, ptr, ptr, ptr, env, i32)
105
+DEF_HELPER_5(vcpop_v_b, void, ptr, ptr, ptr, env, i32)
106
+DEF_HELPER_5(vcpop_v_h, void, ptr, ptr, ptr, env, i32)
107
+DEF_HELPER_5(vcpop_v_w, void, ptr, ptr, ptr, env, i32)
108
+DEF_HELPER_5(vcpop_v_d, void, ptr, ptr, ptr, env, i32)
109
+
110
+DEF_HELPER_6(vwsll_vv_b, void, ptr, ptr, ptr, ptr, env, i32)
111
+DEF_HELPER_6(vwsll_vv_h, void, ptr, ptr, ptr, ptr, env, i32)
112
+DEF_HELPER_6(vwsll_vv_w, void, ptr, ptr, ptr, ptr, env, i32)
113
+DEF_HELPER_6(vwsll_vx_b, void, ptr, ptr, tl, ptr, env, i32)
114
+DEF_HELPER_6(vwsll_vx_h, void, ptr, ptr, tl, ptr, env, i32)
115
+DEF_HELPER_6(vwsll_vx_w, void, ptr, ptr, tl, ptr, env, i32)
116
+
117
+DEF_HELPER_6(vandn_vv_b, void, ptr, ptr, ptr, ptr, env, i32)
118
+DEF_HELPER_6(vandn_vv_h, void, ptr, ptr, ptr, ptr, env, i32)
119
+DEF_HELPER_6(vandn_vv_w, void, ptr, ptr, ptr, ptr, env, i32)
120
+DEF_HELPER_6(vandn_vv_d, void, ptr, ptr, ptr, ptr, env, i32)
121
+DEF_HELPER_6(vandn_vx_b, void, ptr, ptr, tl, ptr, env, i32)
122
+DEF_HELPER_6(vandn_vx_h, void, ptr, ptr, tl, ptr, env, i32)
123
+DEF_HELPER_6(vandn_vx_w, void, ptr, ptr, tl, ptr, env, i32)
124
+DEF_HELPER_6(vandn_vx_d, void, ptr, ptr, tl, ptr, env, i32)
125
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
126
index XXXXXXX..XXXXXXX 100644
127
--- a/target/riscv/insn32.decode
128
+++ b/target/riscv/insn32.decode
28
@@ -XXX,XX +XXX,XX @@
129
@@ -XXX,XX +XXX,XX @@
29
/*
130
%imm_u 12:s20 !function=ex_shift_12
30
- * SiFive CLINT (Core Local Interruptor) interface
131
%imm_bs 30:2 !function=ex_shift_3
31
+ * RISC-V ACLINT (Advanced Core Local Interruptor) interface
132
%imm_rnum 20:4
32
*
133
+%imm_z6 26:1 15:5
33
* Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
134
34
* Copyright (c) 2017 SiFive, Inc.
135
# Argument sets:
35
+ * Copyright (c) 2021 Western Digital Corporation or its affiliates.
136
&empty
36
*
37
* This program is free software; you can redistribute it and/or modify it
38
* under the terms and conditions of the GNU General Public License,
39
@@ -XXX,XX +XXX,XX @@
137
@@ -XXX,XX +XXX,XX @@
40
* this program. If not, see <http://www.gnu.org/licenses/>.
138
@r_vm ...... vm:1 ..... ..... ... ..... ....... &rmrr %rs2 %rs1 %rd
41
*/
139
@r_vm_1 ...... . ..... ..... ... ..... ....... &rmrr vm=1 %rs2 %rs1 %rd
42
140
@r_vm_0 ...... . ..... ..... ... ..... ....... &rmrr vm=0 %rs2 %rs1 %rd
43
-#ifndef HW_SIFIVE_CLINT_H
141
+@r2_zimm6 ..... . vm:1 ..... ..... ... ..... ....... &rmrr %rs2 rs1=%imm_z6 %rd
44
-#define HW_SIFIVE_CLINT_H
142
@r2_zimm11 . zimm:11 ..... ... ..... ....... %rs1 %rd
45
+#ifndef HW_RISCV_ACLINT_H
143
@r2_zimm10 .. zimm:10 ..... ... ..... ....... %rs1 %rd
46
+#define HW_RISCV_ACLINT_H
144
@r2_s ....... ..... ..... ... ..... ....... %rs2 %rs1
47
145
@@ -XXX,XX +XXX,XX @@ vclmul_vv 001100 . ..... ..... 010 ..... 1010111 @r_vm
48
#include "hw/sysbus.h"
146
vclmul_vx 001100 . ..... ..... 110 ..... 1010111 @r_vm
49
147
vclmulh_vv 001101 . ..... ..... 010 ..... 1010111 @r_vm
50
-#define TYPE_SIFIVE_CLINT "riscv.sifive.clint"
148
vclmulh_vx 001101 . ..... ..... 110 ..... 1010111 @r_vm
51
+#define TYPE_RISCV_ACLINT_MTIMER "riscv.aclint.mtimer"
149
+
52
150
+# *** Zvbb vector crypto extension ***
53
-#define SIFIVE_CLINT(obj) \
151
+vrol_vv 010101 . ..... ..... 000 ..... 1010111 @r_vm
54
- OBJECT_CHECK(SiFiveCLINTState, (obj), TYPE_SIFIVE_CLINT)
152
+vrol_vx 010101 . ..... ..... 100 ..... 1010111 @r_vm
55
+#define RISCV_ACLINT_MTIMER(obj) \
153
+vror_vv 010100 . ..... ..... 000 ..... 1010111 @r_vm
56
+ OBJECT_CHECK(RISCVAclintMTimerState, (obj), TYPE_RISCV_ACLINT_MTIMER)
154
+vror_vx 010100 . ..... ..... 100 ..... 1010111 @r_vm
57
155
+vror_vi 01010. . ..... ..... 011 ..... 1010111 @r2_zimm6
58
-typedef struct SiFiveCLINTState {
156
+vbrev8_v 010010 . ..... 01000 010 ..... 1010111 @r2_vm
59
+typedef struct RISCVAclintMTimerState {
157
+vrev8_v 010010 . ..... 01001 010 ..... 1010111 @r2_vm
60
/*< private >*/
158
+vandn_vv 000001 . ..... ..... 000 ..... 1010111 @r_vm
61
SysBusDevice parent_obj;
159
+vandn_vx 000001 . ..... ..... 100 ..... 1010111 @r_vm
62
160
+vbrev_v 010010 . ..... 01010 010 ..... 1010111 @r2_vm
63
@@ -XXX,XX +XXX,XX @@ typedef struct SiFiveCLINTState {
161
+vclz_v 010010 . ..... 01100 010 ..... 1010111 @r2_vm
64
MemoryRegion mmio;
162
+vctz_v 010010 . ..... 01101 010 ..... 1010111 @r2_vm
65
uint32_t hartid_base;
163
+vcpop_v 010010 . ..... 01110 010 ..... 1010111 @r2_vm
66
uint32_t num_harts;
164
+vwsll_vv 110101 . ..... ..... 000 ..... 1010111 @r_vm
67
- uint32_t sip_base;
165
+vwsll_vx 110101 . ..... ..... 100 ..... 1010111 @r_vm
68
uint32_t timecmp_base;
166
+vwsll_vi 110101 . ..... ..... 011 ..... 1010111 @r_vm
69
uint32_t time_base;
167
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
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
168
index XXXXXXX..XXXXXXX 100644
122
--- a/hw/intc/riscv_aclint.c
169
--- a/target/riscv/cpu.c
123
+++ b/hw/intc/riscv_aclint.c
170
+++ b/target/riscv/cpu.c
124
@@ -XXX,XX +XXX,XX @@
171
@@ -XXX,XX +XXX,XX @@ static const struct isa_ext_data isa_edata_arr[] = {
125
/*
172
ISA_EXT_DATA_ENTRY(zksed, PRIV_VERSION_1_12_0, ext_zksed),
126
- * SiFive CLINT (Core Local Interruptor)
173
ISA_EXT_DATA_ENTRY(zksh, PRIV_VERSION_1_12_0, ext_zksh),
127
+ * RISC-V ACLINT (Advanced Core Local Interruptor)
174
ISA_EXT_DATA_ENTRY(zkt, PRIV_VERSION_1_12_0, ext_zkt),
128
+ * URL: https://github.com/riscv/riscv-aclint
175
+ ISA_EXT_DATA_ENTRY(zvbb, PRIV_VERSION_1_12_0, ext_zvbb),
129
*
176
ISA_EXT_DATA_ENTRY(zvbc, PRIV_VERSION_1_12_0, ext_zvbc),
130
* Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
177
ISA_EXT_DATA_ENTRY(zve32f, PRIV_VERSION_1_10_0, ext_zve32f),
131
* Copyright (c) 2017 SiFive, Inc.
178
ISA_EXT_DATA_ENTRY(zve64f, PRIV_VERSION_1_10_0, ext_zve64f),
132
+ * Copyright (c) 2021 Western Digital Corporation or its affiliates.
179
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
133
*
180
return;
134
* This provides real-time clock, timer and interprocessor interrupts.
181
}
135
*
182
183
+ /*
184
+ * In principle Zve*x would also suffice here, were they supported
185
+ * in qemu
186
+ */
187
+ if (cpu->cfg.ext_zvbb && !cpu->cfg.ext_zve32f) {
188
+ error_setg(errp,
189
+ "Vector crypto extensions require V or Zve* extensions");
190
+ return;
191
+ }
192
+
193
if (cpu->cfg.ext_zvbc && !cpu->cfg.ext_zve64f) {
194
error_setg(errp, "Zvbc extension requires V or Zve64{f,d} extensions");
195
return;
196
@@ -XXX,XX +XXX,XX @@ static Property riscv_cpu_extensions[] = {
197
DEFINE_PROP_BOOL("x-zvfbfwma", RISCVCPU, cfg.ext_zvfbfwma, false),
198
199
/* Vector cryptography extensions */
200
+ DEFINE_PROP_BOOL("x-zvbb", RISCVCPU, cfg.ext_zvbb, false),
201
DEFINE_PROP_BOOL("x-zvbc", RISCVCPU, cfg.ext_zvbc, false),
202
203
DEFINE_PROP_END_OF_LIST(),
204
diff --git a/target/riscv/vcrypto_helper.c b/target/riscv/vcrypto_helper.c
205
index XXXXXXX..XXXXXXX 100644
206
--- a/target/riscv/vcrypto_helper.c
207
+++ b/target/riscv/vcrypto_helper.c
136
@@ -XXX,XX +XXX,XX @@
208
@@ -XXX,XX +XXX,XX @@
137
#include "qemu/osdep.h"
209
#include "qemu/osdep.h"
138
#include "qapi/error.h"
210
#include "qemu/host-utils.h"
139
#include "qemu/error-report.h"
211
#include "qemu/bitops.h"
140
+#include "qemu/log.h"
212
+#include "qemu/bswap.h"
141
#include "qemu/module.h"
213
#include "cpu.h"
142
#include "hw/sysbus.h"
214
#include "exec/memop.h"
143
#include "target/riscv/cpu.h"
215
#include "exec/exec-all.h"
144
@@ -XXX,XX +XXX,XX @@
216
@@ -XXX,XX +XXX,XX @@ RVVCALL(OPIVV2, vclmulh_vv, OP_UUU_D, H8, H8, H8, clmulh64)
145
#include "qemu/timer.h"
217
GEN_VEXT_VV(vclmulh_vv, 8)
146
#include "hw/irq.h"
218
RVVCALL(OPIVX2, vclmulh_vx, OP_UUU_D, H8, H8, clmulh64)
147
219
GEN_VEXT_VX(vclmulh_vx, 8)
148
-typedef struct sifive_clint_callback {
220
+
149
- SiFiveCLINTState *s;
221
+RVVCALL(OPIVV2, vror_vv_b, OP_UUU_B, H1, H1, H1, ror8)
150
+typedef struct riscv_aclint_mtimer_callback {
222
+RVVCALL(OPIVV2, vror_vv_h, OP_UUU_H, H2, H2, H2, ror16)
151
+ RISCVAclintMTimerState *s;
223
+RVVCALL(OPIVV2, vror_vv_w, OP_UUU_W, H4, H4, H4, ror32)
152
int num;
224
+RVVCALL(OPIVV2, vror_vv_d, OP_UUU_D, H8, H8, H8, ror64)
153
-} sifive_clint_callback;
225
+GEN_VEXT_VV(vror_vv_b, 1)
154
+} riscv_aclint_mtimer_callback;
226
+GEN_VEXT_VV(vror_vv_h, 2)
155
227
+GEN_VEXT_VV(vror_vv_w, 4)
156
static uint64_t cpu_riscv_read_rtc(uint32_t timebase_freq)
228
+GEN_VEXT_VV(vror_vv_d, 8)
157
{
229
+
158
@@ -XXX,XX +XXX,XX @@ static uint64_t cpu_riscv_read_rtc(uint32_t timebase_freq)
230
+RVVCALL(OPIVX2, vror_vx_b, OP_UUU_B, H1, H1, ror8)
159
* Called when timecmp is written to update the QEMU timer or immediately
231
+RVVCALL(OPIVX2, vror_vx_h, OP_UUU_H, H2, H2, ror16)
160
* trigger timer interrupt if mtimecmp <= current timer value.
232
+RVVCALL(OPIVX2, vror_vx_w, OP_UUU_W, H4, H4, ror32)
161
*/
233
+RVVCALL(OPIVX2, vror_vx_d, OP_UUU_D, H8, H8, ror64)
162
-static void sifive_clint_write_timecmp(SiFiveCLINTState *s, RISCVCPU *cpu,
234
+GEN_VEXT_VX(vror_vx_b, 1)
163
- int hartid,
235
+GEN_VEXT_VX(vror_vx_h, 2)
164
- uint64_t value,
236
+GEN_VEXT_VX(vror_vx_w, 4)
165
- uint32_t timebase_freq)
237
+GEN_VEXT_VX(vror_vx_d, 8)
166
+static void riscv_aclint_mtimer_write_timecmp(RISCVAclintMTimerState *mtimer,
238
+
167
+ RISCVCPU *cpu,
239
+RVVCALL(OPIVV2, vrol_vv_b, OP_UUU_B, H1, H1, H1, rol8)
168
+ int hartid,
240
+RVVCALL(OPIVV2, vrol_vv_h, OP_UUU_H, H2, H2, H2, rol16)
169
+ uint64_t value,
241
+RVVCALL(OPIVV2, vrol_vv_w, OP_UUU_W, H4, H4, H4, rol32)
170
+ uint32_t timebase_freq)
242
+RVVCALL(OPIVV2, vrol_vv_d, OP_UUU_D, H8, H8, H8, rol64)
171
{
243
+GEN_VEXT_VV(vrol_vv_b, 1)
172
uint64_t next;
244
+GEN_VEXT_VV(vrol_vv_h, 2)
173
uint64_t diff;
245
+GEN_VEXT_VV(vrol_vv_w, 4)
174
@@ -XXX,XX +XXX,XX @@ static void sifive_clint_write_timecmp(SiFiveCLINTState *s, RISCVCPU *cpu,
246
+GEN_VEXT_VV(vrol_vv_d, 8)
175
247
+
176
cpu->env.timecmp = value;
248
+RVVCALL(OPIVX2, vrol_vx_b, OP_UUU_B, H1, H1, rol8)
177
if (cpu->env.timecmp <= rtc_r) {
249
+RVVCALL(OPIVX2, vrol_vx_h, OP_UUU_H, H2, H2, rol16)
178
- /* if we're setting an MTIMECMP value in the "past",
250
+RVVCALL(OPIVX2, vrol_vx_w, OP_UUU_W, H4, H4, rol32)
179
- immediately raise the timer interrupt */
251
+RVVCALL(OPIVX2, vrol_vx_d, OP_UUU_D, H8, H8, rol64)
180
- qemu_irq_raise(s->timer_irqs[hartid - s->hartid_base]);
252
+GEN_VEXT_VX(vrol_vx_b, 1)
181
+ /*
253
+GEN_VEXT_VX(vrol_vx_h, 2)
182
+ * If we're setting an MTIMECMP value in the "past",
254
+GEN_VEXT_VX(vrol_vx_w, 4)
183
+ * immediately raise the timer interrupt
255
+GEN_VEXT_VX(vrol_vx_d, 8)
184
+ */
256
+
185
+ qemu_irq_raise(mtimer->timer_irqs[hartid - mtimer->hartid_base]);
257
+static uint64_t brev8(uint64_t val)
186
return;
187
}
188
189
/* otherwise, set up the future timer interrupt */
190
- qemu_irq_lower(s->timer_irqs[hartid - s->hartid_base]);
191
+ qemu_irq_lower(mtimer->timer_irqs[hartid - mtimer->hartid_base]);
192
diff = cpu->env.timecmp - rtc_r;
193
/* back to ns (note args switched in muldiv64) */
194
uint64_t ns_diff = muldiv64(diff, NANOSECONDS_PER_SECOND, timebase_freq);
195
@@ -XXX,XX +XXX,XX @@ static void sifive_clint_write_timecmp(SiFiveCLINTState *s, RISCVCPU *cpu,
196
* Callback used when the timer set using timer_mod expires.
197
* Should raise the timer interrupt line
198
*/
199
-static void sifive_clint_timer_cb(void *opaque)
200
+static void riscv_aclint_mtimer_cb(void *opaque)
201
{
202
- sifive_clint_callback *state = opaque;
203
+ riscv_aclint_mtimer_callback *state = opaque;
204
205
qemu_irq_raise(state->s->timer_irqs[state->num]);
206
}
207
208
-/* CPU wants to read rtc or timecmp register */
209
-static uint64_t sifive_clint_read(void *opaque, hwaddr addr, unsigned size)
210
+/* CPU read MTIMER register */
211
+static uint64_t riscv_aclint_mtimer_read(void *opaque, hwaddr addr,
212
+ unsigned size)
213
{
214
- SiFiveCLINTState *clint = opaque;
215
- if (addr >= clint->sip_base &&
216
- addr < clint->sip_base + (clint->num_harts << 2)) {
217
- size_t hartid = clint->hartid_base + ((addr - clint->sip_base) >> 2);
218
- CPUState *cpu = qemu_get_cpu(hartid);
219
- CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
220
- if (!env) {
221
- error_report("clint: invalid timecmp hartid: %zu", hartid);
222
- } else if ((addr & 0x3) == 0) {
223
- return (env->mip & MIP_MSIP) > 0;
224
- } else {
225
- error_report("clint: invalid read: %08x", (uint32_t)addr);
226
- return 0;
227
- }
228
- } else if (addr >= clint->timecmp_base &&
229
- addr < clint->timecmp_base + (clint->num_harts << 3)) {
230
- size_t hartid = clint->hartid_base +
231
- ((addr - clint->timecmp_base) >> 3);
232
+ RISCVAclintMTimerState *mtimer = opaque;
233
+
234
+ if (addr >= mtimer->timecmp_base &&
235
+ addr < (mtimer->timecmp_base + (mtimer->num_harts << 3))) {
236
+ size_t hartid = mtimer->hartid_base +
237
+ ((addr - mtimer->timecmp_base) >> 3);
238
CPUState *cpu = qemu_get_cpu(hartid);
239
CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
240
if (!env) {
241
- error_report("clint: invalid timecmp hartid: %zu", hartid);
242
+ qemu_log_mask(LOG_GUEST_ERROR,
243
+ "aclint-mtimer: invalid hartid: %zu", hartid);
244
} else if ((addr & 0x7) == 0) {
245
/* timecmp_lo */
246
uint64_t timecmp = env->timecmp;
247
@@ -XXX,XX +XXX,XX @@ static uint64_t sifive_clint_read(void *opaque, hwaddr addr, unsigned size)
248
uint64_t timecmp = env->timecmp;
249
return (timecmp >> 32) & 0xFFFFFFFF;
250
} else {
251
- error_report("clint: invalid read: %08x", (uint32_t)addr);
252
+ qemu_log_mask(LOG_UNIMP,
253
+ "aclint-mtimer: invalid read: %08x", (uint32_t)addr);
254
return 0;
255
}
256
- } else if (addr == clint->time_base) {
257
+ } else if (addr == mtimer->time_base) {
258
/* time_lo */
259
- return cpu_riscv_read_rtc(clint->timebase_freq) & 0xFFFFFFFF;
260
- } else if (addr == clint->time_base + 4) {
261
+ return cpu_riscv_read_rtc(mtimer->timebase_freq) & 0xFFFFFFFF;
262
+ } else if (addr == mtimer->time_base + 4) {
263
/* time_hi */
264
- return (cpu_riscv_read_rtc(clint->timebase_freq) >> 32) & 0xFFFFFFFF;
265
+ return (cpu_riscv_read_rtc(mtimer->timebase_freq) >> 32) & 0xFFFFFFFF;
266
}
267
268
- error_report("clint: invalid read: %08x", (uint32_t)addr);
269
+ qemu_log_mask(LOG_UNIMP,
270
+ "aclint-mtimer: invalid read: %08x", (uint32_t)addr);
271
return 0;
272
}
273
274
-/* CPU wrote to rtc or timecmp register */
275
-static void sifive_clint_write(void *opaque, hwaddr addr, uint64_t value,
276
- unsigned size)
277
+/* CPU write MTIMER register */
278
+static void riscv_aclint_mtimer_write(void *opaque, hwaddr addr,
279
+ uint64_t value, unsigned size)
280
{
281
- SiFiveCLINTState *clint = opaque;
282
+ RISCVAclintMTimerState *mtimer = opaque;
283
284
- if (addr >= clint->sip_base &&
285
- addr < clint->sip_base + (clint->num_harts << 2)) {
286
- size_t hartid = clint->hartid_base + ((addr - clint->sip_base) >> 2);
287
- CPUState *cpu = qemu_get_cpu(hartid);
288
- CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
289
- if (!env) {
290
- error_report("clint: invalid timecmp hartid: %zu", hartid);
291
- } else if ((addr & 0x3) == 0) {
292
- qemu_set_irq(clint->soft_irqs[hartid - clint->hartid_base], value);
293
- } else {
294
- error_report("clint: invalid sip write: %08x", (uint32_t)addr);
295
- }
296
- return;
297
- } else if (addr >= clint->timecmp_base &&
298
- addr < clint->timecmp_base + (clint->num_harts << 3)) {
299
- size_t hartid = clint->hartid_base +
300
- ((addr - clint->timecmp_base) >> 3);
301
+ if (addr >= mtimer->timecmp_base &&
302
+ addr < (mtimer->timecmp_base + (mtimer->num_harts << 3))) {
303
+ size_t hartid = mtimer->hartid_base +
304
+ ((addr - mtimer->timecmp_base) >> 3);
305
CPUState *cpu = qemu_get_cpu(hartid);
306
CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
307
if (!env) {
308
- error_report("clint: invalid timecmp hartid: %zu", hartid);
309
+ qemu_log_mask(LOG_GUEST_ERROR,
310
+ "aclint-mtimer: invalid hartid: %zu", hartid);
311
} else if ((addr & 0x7) == 0) {
312
/* timecmp_lo */
313
uint64_t timecmp_hi = env->timecmp >> 32;
314
- sifive_clint_write_timecmp(clint, RISCV_CPU(cpu), hartid,
315
- timecmp_hi << 32 | (value & 0xFFFFFFFF), clint->timebase_freq);
316
+ riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), hartid,
317
+ timecmp_hi << 32 | (value & 0xFFFFFFFF),
318
+ mtimer->timebase_freq);
319
return;
320
} else if ((addr & 0x7) == 4) {
321
/* timecmp_hi */
322
uint64_t timecmp_lo = env->timecmp;
323
- sifive_clint_write_timecmp(clint, RISCV_CPU(cpu), hartid,
324
- value << 32 | (timecmp_lo & 0xFFFFFFFF), clint->timebase_freq);
325
+ riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), hartid,
326
+ value << 32 | (timecmp_lo & 0xFFFFFFFF),
327
+ mtimer->timebase_freq);
328
} else {
329
- error_report("clint: invalid timecmp write: %08x", (uint32_t)addr);
330
+ qemu_log_mask(LOG_UNIMP,
331
+ "aclint-mtimer: invalid timecmp write: %08x",
332
+ (uint32_t)addr);
333
}
334
return;
335
- } else if (addr == clint->time_base) {
336
+ } else if (addr == mtimer->time_base) {
337
/* time_lo */
338
- error_report("clint: time_lo write not implemented");
339
+ qemu_log_mask(LOG_UNIMP,
340
+ "aclint-mtimer: time_lo write not implemented");
341
return;
342
- } else if (addr == clint->time_base + 4) {
343
+ } else if (addr == mtimer->time_base + 4) {
344
/* time_hi */
345
- error_report("clint: time_hi write not implemented");
346
+ qemu_log_mask(LOG_UNIMP,
347
+ "aclint-mtimer: time_hi write not implemented");
348
return;
349
}
350
351
- error_report("clint: invalid write: %08x", (uint32_t)addr);
352
+ qemu_log_mask(LOG_UNIMP,
353
+ "aclint-mtimer: invalid write: %08x", (uint32_t)addr);
354
}
355
356
-static const MemoryRegionOps sifive_clint_ops = {
357
- .read = sifive_clint_read,
358
- .write = sifive_clint_write,
359
+static const MemoryRegionOps riscv_aclint_mtimer_ops = {
360
+ .read = riscv_aclint_mtimer_read,
361
+ .write = riscv_aclint_mtimer_write,
362
.endianness = DEVICE_LITTLE_ENDIAN,
363
.valid = {
364
.min_access_size = 4,
365
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps sifive_clint_ops = {
366
}
367
};
368
369
-static Property sifive_clint_properties[] = {
370
- DEFINE_PROP_UINT32("hartid-base", SiFiveCLINTState, hartid_base, 0),
371
- DEFINE_PROP_UINT32("num-harts", SiFiveCLINTState, num_harts, 0),
372
- DEFINE_PROP_UINT32("sip-base", SiFiveCLINTState, sip_base, 0),
373
- DEFINE_PROP_UINT32("timecmp-base", SiFiveCLINTState, timecmp_base, 0),
374
- DEFINE_PROP_UINT32("time-base", SiFiveCLINTState, time_base, 0),
375
- DEFINE_PROP_UINT32("aperture-size", SiFiveCLINTState, aperture_size, 0),
376
- DEFINE_PROP_UINT32("timebase-freq", SiFiveCLINTState, timebase_freq, 0),
377
+static Property riscv_aclint_mtimer_properties[] = {
378
+ DEFINE_PROP_UINT32("hartid-base", RISCVAclintMTimerState,
379
+ hartid_base, 0),
380
+ DEFINE_PROP_UINT32("num-harts", RISCVAclintMTimerState, num_harts, 1),
381
+ DEFINE_PROP_UINT32("timecmp-base", RISCVAclintMTimerState,
382
+ timecmp_base, RISCV_ACLINT_DEFAULT_MTIMECMP),
383
+ DEFINE_PROP_UINT32("time-base", RISCVAclintMTimerState,
384
+ time_base, RISCV_ACLINT_DEFAULT_MTIME),
385
+ DEFINE_PROP_UINT32("aperture-size", RISCVAclintMTimerState,
386
+ aperture_size, RISCV_ACLINT_DEFAULT_MTIMER_SIZE),
387
+ DEFINE_PROP_UINT32("timebase-freq", RISCVAclintMTimerState,
388
+ timebase_freq, 0),
389
DEFINE_PROP_END_OF_LIST(),
390
};
391
392
-static void sifive_clint_realize(DeviceState *dev, Error **errp)
393
+static void riscv_aclint_mtimer_realize(DeviceState *dev, Error **errp)
394
{
395
- SiFiveCLINTState *s = SIFIVE_CLINT(dev);
396
- memory_region_init_io(&s->mmio, OBJECT(dev), &sifive_clint_ops, s,
397
- TYPE_SIFIVE_CLINT, s->aperture_size);
398
+ RISCVAclintMTimerState *s = RISCV_ACLINT_MTIMER(dev);
399
+ int i;
400
+
401
+ memory_region_init_io(&s->mmio, OBJECT(dev), &riscv_aclint_mtimer_ops,
402
+ s, TYPE_RISCV_ACLINT_MTIMER, s->aperture_size);
403
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
404
405
s->timer_irqs = g_malloc(sizeof(qemu_irq) * s->num_harts);
406
qdev_init_gpio_out(dev, s->timer_irqs, s->num_harts);
407
408
- s->soft_irqs = g_malloc(sizeof(qemu_irq) * s->num_harts);
409
- qdev_init_gpio_out(dev, s->soft_irqs, s->num_harts);
410
+ /* Claim timer interrupt bits */
411
+ for (i = 0; i < s->num_harts; i++) {
412
+ RISCVCPU *cpu = RISCV_CPU(qemu_get_cpu(s->hartid_base + i));
413
+ if (riscv_cpu_claim_interrupts(cpu, MIP_MTIP) < 0) {
414
+ error_report("MTIP already claimed");
415
+ exit(1);
416
+ }
417
+ }
418
}
419
420
-static void sifive_clint_class_init(ObjectClass *klass, void *data)
421
+static void riscv_aclint_mtimer_class_init(ObjectClass *klass, void *data)
422
{
423
DeviceClass *dc = DEVICE_CLASS(klass);
424
- dc->realize = sifive_clint_realize;
425
- device_class_set_props(dc, sifive_clint_properties);
426
+ dc->realize = riscv_aclint_mtimer_realize;
427
+ device_class_set_props(dc, riscv_aclint_mtimer_properties);
428
}
429
430
-static const TypeInfo sifive_clint_info = {
431
- .name = TYPE_SIFIVE_CLINT,
432
+static const TypeInfo riscv_aclint_mtimer_info = {
433
+ .name = TYPE_RISCV_ACLINT_MTIMER,
434
.parent = TYPE_SYS_BUS_DEVICE,
435
- .instance_size = sizeof(SiFiveCLINTState),
436
- .class_init = sifive_clint_class_init,
437
+ .instance_size = sizeof(RISCVAclintMTimerState),
438
+ .class_init = riscv_aclint_mtimer_class_init,
439
};
440
441
-static void sifive_clint_register_types(void)
442
-{
443
- type_register_static(&sifive_clint_info);
444
-}
445
-
446
-type_init(sifive_clint_register_types)
447
-
448
/*
449
- * Create CLINT device.
450
+ * Create ACLINT MTIMER device.
451
*/
452
-DeviceState *sifive_clint_create(hwaddr addr, hwaddr size,
453
- uint32_t hartid_base, uint32_t num_harts, uint32_t sip_base,
454
+DeviceState *riscv_aclint_mtimer_create(hwaddr addr, hwaddr size,
455
+ uint32_t hartid_base, uint32_t num_harts,
456
uint32_t timecmp_base, uint32_t time_base, uint32_t timebase_freq,
457
bool provide_rdtime)
458
{
459
int i;
460
+ DeviceState *dev = qdev_new(TYPE_RISCV_ACLINT_MTIMER);
461
+
462
+ assert(num_harts <= RISCV_ACLINT_MAX_HARTS);
463
+ assert(!(addr & 0x7));
464
+ assert(!(timecmp_base & 0x7));
465
+ assert(!(time_base & 0x7));
466
467
- DeviceState *dev = qdev_new(TYPE_SIFIVE_CLINT);
468
qdev_prop_set_uint32(dev, "hartid-base", hartid_base);
469
qdev_prop_set_uint32(dev, "num-harts", num_harts);
470
- qdev_prop_set_uint32(dev, "sip-base", sip_base);
471
qdev_prop_set_uint32(dev, "timecmp-base", timecmp_base);
472
qdev_prop_set_uint32(dev, "time-base", time_base);
473
qdev_prop_set_uint32(dev, "aperture-size", size);
474
@@ -XXX,XX +XXX,XX @@ DeviceState *sifive_clint_create(hwaddr addr, hwaddr size,
475
CPUState *cpu = qemu_get_cpu(hartid_base + i);
476
RISCVCPU *rvcpu = RISCV_CPU(cpu);
477
CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
478
- sifive_clint_callback *cb = g_malloc0(sizeof(sifive_clint_callback));
479
+ riscv_aclint_mtimer_callback *cb =
480
+ g_malloc0(sizeof(riscv_aclint_mtimer_callback));
481
482
if (!env) {
483
g_free(cb);
484
@@ -XXX,XX +XXX,XX @@ DeviceState *sifive_clint_create(hwaddr addr, hwaddr size,
485
riscv_cpu_set_rdtime_fn(env, cpu_riscv_read_rtc, timebase_freq);
486
}
487
488
- cb->s = SIFIVE_CLINT(dev);
489
+ cb->s = RISCV_ACLINT_MTIMER(dev);
490
cb->num = i;
491
env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
492
- &sifive_clint_timer_cb, cb);
493
+ &riscv_aclint_mtimer_cb, cb);
494
env->timecmp = 0;
495
496
qdev_connect_gpio_out(dev, i,
497
qdev_get_gpio_in(DEVICE(rvcpu), IRQ_M_TIMER));
498
- qdev_connect_gpio_out(dev, num_harts + i,
499
- qdev_get_gpio_in(DEVICE(rvcpu), IRQ_M_SOFT));
500
}
501
502
return dev;
503
}
504
+
505
+/* CPU read [M|S]SWI register */
506
+static uint64_t riscv_aclint_swi_read(void *opaque, hwaddr addr,
507
+ unsigned size)
508
+{
258
+{
509
+ RISCVAclintSwiState *swi = opaque;
259
+ val = ((val & 0x5555555555555555ull) << 1) |
510
+
260
+ ((val & 0xAAAAAAAAAAAAAAAAull) >> 1);
511
+ if (addr < (swi->num_harts << 2)) {
261
+ val = ((val & 0x3333333333333333ull) << 2) |
512
+ size_t hartid = swi->hartid_base + (addr >> 2);
262
+ ((val & 0xCCCCCCCCCCCCCCCCull) >> 2);
513
+ CPUState *cpu = qemu_get_cpu(hartid);
263
+ val = ((val & 0x0F0F0F0F0F0F0F0Full) << 4) |
514
+ CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
264
+ ((val & 0xF0F0F0F0F0F0F0F0ull) >> 4);
515
+ if (!env) {
265
+
516
+ qemu_log_mask(LOG_GUEST_ERROR,
266
+ return val;
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
+ }
522
+
523
+ qemu_log_mask(LOG_UNIMP,
524
+ "aclint-swi: invalid read: %08x", (uint32_t)addr);
525
+ return 0;
526
+}
267
+}
527
+
268
+
528
+/* CPU write [M|S]SWI register */
269
+RVVCALL(OPIVV1, vbrev8_v_b, OP_UU_B, H1, H1, brev8)
529
+static void riscv_aclint_swi_write(void *opaque, hwaddr addr, uint64_t value,
270
+RVVCALL(OPIVV1, vbrev8_v_h, OP_UU_H, H2, H2, brev8)
530
+ unsigned size)
271
+RVVCALL(OPIVV1, vbrev8_v_w, OP_UU_W, H4, H4, brev8)
272
+RVVCALL(OPIVV1, vbrev8_v_d, OP_UU_D, H8, H8, brev8)
273
+GEN_VEXT_V(vbrev8_v_b, 1)
274
+GEN_VEXT_V(vbrev8_v_h, 2)
275
+GEN_VEXT_V(vbrev8_v_w, 4)
276
+GEN_VEXT_V(vbrev8_v_d, 8)
277
+
278
+#define DO_IDENTITY(a) (a)
279
+RVVCALL(OPIVV1, vrev8_v_b, OP_UU_B, H1, H1, DO_IDENTITY)
280
+RVVCALL(OPIVV1, vrev8_v_h, OP_UU_H, H2, H2, bswap16)
281
+RVVCALL(OPIVV1, vrev8_v_w, OP_UU_W, H4, H4, bswap32)
282
+RVVCALL(OPIVV1, vrev8_v_d, OP_UU_D, H8, H8, bswap64)
283
+GEN_VEXT_V(vrev8_v_b, 1)
284
+GEN_VEXT_V(vrev8_v_h, 2)
285
+GEN_VEXT_V(vrev8_v_w, 4)
286
+GEN_VEXT_V(vrev8_v_d, 8)
287
+
288
+#define DO_ANDN(a, b) ((a) & ~(b))
289
+RVVCALL(OPIVV2, vandn_vv_b, OP_UUU_B, H1, H1, H1, DO_ANDN)
290
+RVVCALL(OPIVV2, vandn_vv_h, OP_UUU_H, H2, H2, H2, DO_ANDN)
291
+RVVCALL(OPIVV2, vandn_vv_w, OP_UUU_W, H4, H4, H4, DO_ANDN)
292
+RVVCALL(OPIVV2, vandn_vv_d, OP_UUU_D, H8, H8, H8, DO_ANDN)
293
+GEN_VEXT_VV(vandn_vv_b, 1)
294
+GEN_VEXT_VV(vandn_vv_h, 2)
295
+GEN_VEXT_VV(vandn_vv_w, 4)
296
+GEN_VEXT_VV(vandn_vv_d, 8)
297
+
298
+RVVCALL(OPIVX2, vandn_vx_b, OP_UUU_B, H1, H1, DO_ANDN)
299
+RVVCALL(OPIVX2, vandn_vx_h, OP_UUU_H, H2, H2, DO_ANDN)
300
+RVVCALL(OPIVX2, vandn_vx_w, OP_UUU_W, H4, H4, DO_ANDN)
301
+RVVCALL(OPIVX2, vandn_vx_d, OP_UUU_D, H8, H8, DO_ANDN)
302
+GEN_VEXT_VX(vandn_vx_b, 1)
303
+GEN_VEXT_VX(vandn_vx_h, 2)
304
+GEN_VEXT_VX(vandn_vx_w, 4)
305
+GEN_VEXT_VX(vandn_vx_d, 8)
306
+
307
+RVVCALL(OPIVV1, vbrev_v_b, OP_UU_B, H1, H1, revbit8)
308
+RVVCALL(OPIVV1, vbrev_v_h, OP_UU_H, H2, H2, revbit16)
309
+RVVCALL(OPIVV1, vbrev_v_w, OP_UU_W, H4, H4, revbit32)
310
+RVVCALL(OPIVV1, vbrev_v_d, OP_UU_D, H8, H8, revbit64)
311
+GEN_VEXT_V(vbrev_v_b, 1)
312
+GEN_VEXT_V(vbrev_v_h, 2)
313
+GEN_VEXT_V(vbrev_v_w, 4)
314
+GEN_VEXT_V(vbrev_v_d, 8)
315
+
316
+RVVCALL(OPIVV1, vclz_v_b, OP_UU_B, H1, H1, clz8)
317
+RVVCALL(OPIVV1, vclz_v_h, OP_UU_H, H2, H2, clz16)
318
+RVVCALL(OPIVV1, vclz_v_w, OP_UU_W, H4, H4, clz32)
319
+RVVCALL(OPIVV1, vclz_v_d, OP_UU_D, H8, H8, clz64)
320
+GEN_VEXT_V(vclz_v_b, 1)
321
+GEN_VEXT_V(vclz_v_h, 2)
322
+GEN_VEXT_V(vclz_v_w, 4)
323
+GEN_VEXT_V(vclz_v_d, 8)
324
+
325
+RVVCALL(OPIVV1, vctz_v_b, OP_UU_B, H1, H1, ctz8)
326
+RVVCALL(OPIVV1, vctz_v_h, OP_UU_H, H2, H2, ctz16)
327
+RVVCALL(OPIVV1, vctz_v_w, OP_UU_W, H4, H4, ctz32)
328
+RVVCALL(OPIVV1, vctz_v_d, OP_UU_D, H8, H8, ctz64)
329
+GEN_VEXT_V(vctz_v_b, 1)
330
+GEN_VEXT_V(vctz_v_h, 2)
331
+GEN_VEXT_V(vctz_v_w, 4)
332
+GEN_VEXT_V(vctz_v_d, 8)
333
+
334
+RVVCALL(OPIVV1, vcpop_v_b, OP_UU_B, H1, H1, ctpop8)
335
+RVVCALL(OPIVV1, vcpop_v_h, OP_UU_H, H2, H2, ctpop16)
336
+RVVCALL(OPIVV1, vcpop_v_w, OP_UU_W, H4, H4, ctpop32)
337
+RVVCALL(OPIVV1, vcpop_v_d, OP_UU_D, H8, H8, ctpop64)
338
+GEN_VEXT_V(vcpop_v_b, 1)
339
+GEN_VEXT_V(vcpop_v_h, 2)
340
+GEN_VEXT_V(vcpop_v_w, 4)
341
+GEN_VEXT_V(vcpop_v_d, 8)
342
+
343
+#define DO_SLL(N, M) (N << (M & (sizeof(N) * 8 - 1)))
344
+RVVCALL(OPIVV2, vwsll_vv_b, WOP_UUU_B, H2, H1, H1, DO_SLL)
345
+RVVCALL(OPIVV2, vwsll_vv_h, WOP_UUU_H, H4, H2, H2, DO_SLL)
346
+RVVCALL(OPIVV2, vwsll_vv_w, WOP_UUU_W, H8, H4, H4, DO_SLL)
347
+GEN_VEXT_VV(vwsll_vv_b, 2)
348
+GEN_VEXT_VV(vwsll_vv_h, 4)
349
+GEN_VEXT_VV(vwsll_vv_w, 8)
350
+
351
+RVVCALL(OPIVX2, vwsll_vx_b, WOP_UUU_B, H2, H1, DO_SLL)
352
+RVVCALL(OPIVX2, vwsll_vx_h, WOP_UUU_H, H4, H2, DO_SLL)
353
+RVVCALL(OPIVX2, vwsll_vx_w, WOP_UUU_W, H8, H4, DO_SLL)
354
+GEN_VEXT_VX(vwsll_vx_b, 2)
355
+GEN_VEXT_VX(vwsll_vx_h, 4)
356
+GEN_VEXT_VX(vwsll_vx_w, 8)
357
diff --git a/target/riscv/insn_trans/trans_rvvk.c.inc b/target/riscv/insn_trans/trans_rvvk.c.inc
358
index XXXXXXX..XXXXXXX 100644
359
--- a/target/riscv/insn_trans/trans_rvvk.c.inc
360
+++ b/target/riscv/insn_trans/trans_rvvk.c.inc
361
@@ -XXX,XX +XXX,XX @@ static bool vclmul_vx_check(DisasContext *s, arg_rmrr *a)
362
363
GEN_VX_MASKED_TRANS(vclmul_vx, vclmul_vx_check)
364
GEN_VX_MASKED_TRANS(vclmulh_vx, vclmul_vx_check)
365
+
366
+/*
367
+ * Zvbb
368
+ */
369
+
370
+#define GEN_OPIVI_GVEC_TRANS_CHECK(NAME, IMM_MODE, OPIVX, SUF, CHECK) \
371
+ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
372
+ { \
373
+ if (CHECK(s, a)) { \
374
+ static gen_helper_opivx *const fns[4] = { \
375
+ gen_helper_##OPIVX##_b, \
376
+ gen_helper_##OPIVX##_h, \
377
+ gen_helper_##OPIVX##_w, \
378
+ gen_helper_##OPIVX##_d, \
379
+ }; \
380
+ return do_opivi_gvec(s, a, tcg_gen_gvec_##SUF, fns[s->sew], \
381
+ IMM_MODE); \
382
+ } \
383
+ return false; \
384
+ }
385
+
386
+#define GEN_OPIVV_GVEC_TRANS_CHECK(NAME, SUF, CHECK) \
387
+ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
388
+ { \
389
+ if (CHECK(s, a)) { \
390
+ static gen_helper_gvec_4_ptr *const fns[4] = { \
391
+ gen_helper_##NAME##_b, \
392
+ gen_helper_##NAME##_h, \
393
+ gen_helper_##NAME##_w, \
394
+ gen_helper_##NAME##_d, \
395
+ }; \
396
+ return do_opivv_gvec(s, a, tcg_gen_gvec_##SUF, fns[s->sew]); \
397
+ } \
398
+ return false; \
399
+ }
400
+
401
+#define GEN_OPIVX_GVEC_SHIFT_TRANS_CHECK(NAME, SUF, CHECK) \
402
+ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
403
+ { \
404
+ if (CHECK(s, a)) { \
405
+ static gen_helper_opivx *const fns[4] = { \
406
+ gen_helper_##NAME##_b, \
407
+ gen_helper_##NAME##_h, \
408
+ gen_helper_##NAME##_w, \
409
+ gen_helper_##NAME##_d, \
410
+ }; \
411
+ return do_opivx_gvec_shift(s, a, tcg_gen_gvec_##SUF, \
412
+ fns[s->sew]); \
413
+ } \
414
+ return false; \
415
+ }
416
+
417
+static bool zvbb_vv_check(DisasContext *s, arg_rmrr *a)
531
+{
418
+{
532
+ RISCVAclintSwiState *swi = opaque;
419
+ return opivv_check(s, a) && s->cfg_ptr->ext_zvbb == true;
533
+
534
+ if (addr < (swi->num_harts << 2)) {
535
+ size_t hartid = swi->hartid_base + (addr >> 2);
536
+ CPUState *cpu = qemu_get_cpu(hartid);
537
+ CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
538
+ if (!env) {
539
+ qemu_log_mask(LOG_GUEST_ERROR,
540
+ "aclint-swi: invalid hartid: %zu", hartid);
541
+ } else if ((addr & 0x3) == 0) {
542
+ if (value & 0x1) {
543
+ qemu_irq_raise(swi->soft_irqs[hartid - swi->hartid_base]);
544
+ } else {
545
+ if (!swi->sswi) {
546
+ qemu_irq_lower(swi->soft_irqs[hartid - swi->hartid_base]);
547
+ }
548
+ }
549
+ return;
550
+ }
551
+ }
552
+
553
+ qemu_log_mask(LOG_UNIMP,
554
+ "aclint-swi: invalid write: %08x", (uint32_t)addr);
555
+}
420
+}
556
+
421
+
557
+static const MemoryRegionOps riscv_aclint_swi_ops = {
422
+static bool zvbb_vx_check(DisasContext *s, arg_rmrr *a)
558
+ .read = riscv_aclint_swi_read,
559
+ .write = riscv_aclint_swi_write,
560
+ .endianness = DEVICE_LITTLE_ENDIAN,
561
+ .valid = {
562
+ .min_access_size = 4,
563
+ .max_access_size = 4
564
+ }
565
+};
566
+
567
+static Property riscv_aclint_swi_properties[] = {
568
+ DEFINE_PROP_UINT32("hartid-base", RISCVAclintSwiState, hartid_base, 0),
569
+ DEFINE_PROP_UINT32("num-harts", RISCVAclintSwiState, num_harts, 1),
570
+ DEFINE_PROP_UINT32("sswi", RISCVAclintSwiState, sswi, false),
571
+ DEFINE_PROP_END_OF_LIST(),
572
+};
573
+
574
+static void riscv_aclint_swi_realize(DeviceState *dev, Error **errp)
575
+{
423
+{
576
+ RISCVAclintSwiState *swi = RISCV_ACLINT_SWI(dev);
424
+ return opivx_check(s, a) && s->cfg_ptr->ext_zvbb == true;
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
+}
425
+}
596
+
426
+
597
+static void riscv_aclint_swi_class_init(ObjectClass *klass, void *data)
427
+/* vrol.v[vx] */
428
+GEN_OPIVV_GVEC_TRANS_CHECK(vrol_vv, rotlv, zvbb_vv_check)
429
+GEN_OPIVX_GVEC_SHIFT_TRANS_CHECK(vrol_vx, rotls, zvbb_vx_check)
430
+
431
+/* vror.v[vxi] */
432
+GEN_OPIVV_GVEC_TRANS_CHECK(vror_vv, rotrv, zvbb_vv_check)
433
+GEN_OPIVX_GVEC_SHIFT_TRANS_CHECK(vror_vx, rotrs, zvbb_vx_check)
434
+GEN_OPIVI_GVEC_TRANS_CHECK(vror_vi, IMM_TRUNC_SEW, vror_vx, rotri, zvbb_vx_check)
435
+
436
+#define GEN_OPIVX_GVEC_TRANS_CHECK(NAME, SUF, CHECK) \
437
+ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
438
+ { \
439
+ if (CHECK(s, a)) { \
440
+ static gen_helper_opivx *const fns[4] = { \
441
+ gen_helper_##NAME##_b, \
442
+ gen_helper_##NAME##_h, \
443
+ gen_helper_##NAME##_w, \
444
+ gen_helper_##NAME##_d, \
445
+ }; \
446
+ return do_opivx_gvec(s, a, tcg_gen_gvec_##SUF, fns[s->sew]); \
447
+ } \
448
+ return false; \
449
+ }
450
+
451
+/* vandn.v[vx] */
452
+GEN_OPIVV_GVEC_TRANS_CHECK(vandn_vv, andc, zvbb_vv_check)
453
+GEN_OPIVX_GVEC_TRANS_CHECK(vandn_vx, andcs, zvbb_vx_check)
454
+
455
+#define GEN_OPIV_TRANS(NAME, CHECK) \
456
+ static bool trans_##NAME(DisasContext *s, arg_rmr *a) \
457
+ { \
458
+ if (CHECK(s, a)) { \
459
+ uint32_t data = 0; \
460
+ static gen_helper_gvec_3_ptr *const fns[4] = { \
461
+ gen_helper_##NAME##_b, \
462
+ gen_helper_##NAME##_h, \
463
+ gen_helper_##NAME##_w, \
464
+ gen_helper_##NAME##_d, \
465
+ }; \
466
+ TCGLabel *over = gen_new_label(); \
467
+ tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); \
468
+ \
469
+ data = FIELD_DP32(data, VDATA, VM, a->vm); \
470
+ data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \
471
+ data = FIELD_DP32(data, VDATA, VTA, s->vta); \
472
+ data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s); \
473
+ data = FIELD_DP32(data, VDATA, VMA, s->vma); \
474
+ tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \
475
+ vreg_ofs(s, a->rs2), cpu_env, \
476
+ s->cfg_ptr->vlen / 8, s->cfg_ptr->vlen / 8, \
477
+ data, fns[s->sew]); \
478
+ mark_vs_dirty(s); \
479
+ gen_set_label(over); \
480
+ return true; \
481
+ } \
482
+ return false; \
483
+ }
484
+
485
+static bool zvbb_opiv_check(DisasContext *s, arg_rmr *a)
598
+{
486
+{
599
+ DeviceClass *dc = DEVICE_CLASS(klass);
487
+ return s->cfg_ptr->ext_zvbb == true &&
600
+ dc->realize = riscv_aclint_swi_realize;
488
+ require_rvv(s) &&
601
+ device_class_set_props(dc, riscv_aclint_swi_properties);
489
+ vext_check_isa_ill(s) &&
490
+ vext_check_ss(s, a->rd, a->rs2, a->vm);
602
+}
491
+}
603
+
492
+
604
+static const TypeInfo riscv_aclint_swi_info = {
493
+GEN_OPIV_TRANS(vbrev8_v, zvbb_opiv_check)
605
+ .name = TYPE_RISCV_ACLINT_SWI,
494
+GEN_OPIV_TRANS(vrev8_v, zvbb_opiv_check)
606
+ .parent = TYPE_SYS_BUS_DEVICE,
495
+GEN_OPIV_TRANS(vbrev_v, zvbb_opiv_check)
607
+ .instance_size = sizeof(RISCVAclintSwiState),
496
+GEN_OPIV_TRANS(vclz_v, zvbb_opiv_check)
608
+ .class_init = riscv_aclint_swi_class_init,
497
+GEN_OPIV_TRANS(vctz_v, zvbb_opiv_check)
609
+};
498
+GEN_OPIV_TRANS(vcpop_v, zvbb_opiv_check)
610
+
499
+
611
+/*
500
+static bool vwsll_vv_check(DisasContext *s, arg_rmrr *a)
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
+{
501
+{
617
+ int i;
502
+ return s->cfg_ptr->ext_zvbb && opivv_widen_check(s, a);
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
+}
503
+}
640
+
504
+
641
+static void riscv_aclint_register_types(void)
505
+static bool vwsll_vx_check(DisasContext *s, arg_rmrr *a)
642
+{
506
+{
643
+ type_register_static(&riscv_aclint_mtimer_info);
507
+ return s->cfg_ptr->ext_zvbb && opivx_widen_check(s, a);
644
+ type_register_static(&riscv_aclint_swi_info);
645
+}
508
+}
646
+
509
+
647
+type_init(riscv_aclint_register_types)
510
+/* OPIVI without GVEC IR */
648
diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
511
+#define GEN_OPIVI_WIDEN_TRANS(NAME, IMM_MODE, OPIVX, CHECK) \
649
index XXXXXXX..XXXXXXX 100644
512
+ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
650
--- a/hw/riscv/microchip_pfsoc.c
513
+ { \
651
+++ b/hw/riscv/microchip_pfsoc.c
514
+ if (CHECK(s, a)) { \
652
@@ -XXX,XX +XXX,XX @@ static void microchip_pfsoc_soc_realize(DeviceState *dev, Error **errp)
515
+ static gen_helper_opivx *const fns[3] = { \
653
memmap[MICROCHIP_PFSOC_BUSERR_UNIT4].size);
516
+ gen_helper_##OPIVX##_b, \
654
517
+ gen_helper_##OPIVX##_h, \
655
/* CLINT */
518
+ gen_helper_##OPIVX##_w, \
656
- sifive_clint_create(memmap[MICROCHIP_PFSOC_CLINT].base,
519
+ }; \
657
- memmap[MICROCHIP_PFSOC_CLINT].size, 0, ms->smp.cpus,
520
+ return opivi_trans(a->rd, a->rs1, a->rs2, a->vm, fns[s->sew], s, \
658
- SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE,
521
+ IMM_MODE); \
659
+ riscv_aclint_swi_create(memmap[MICROCHIP_PFSOC_CLINT].base,
522
+ } \
660
+ 0, ms->smp.cpus, false);
523
+ return false; \
661
+ riscv_aclint_mtimer_create(
524
+ }
662
+ memmap[MICROCHIP_PFSOC_CLINT].base + RISCV_ACLINT_SWI_SIZE,
525
+
663
+ RISCV_ACLINT_DEFAULT_MTIMER_SIZE, 0, ms->smp.cpus,
526
+GEN_OPIVV_WIDEN_TRANS(vwsll_vv, vwsll_vv_check)
664
+ RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME,
527
+GEN_OPIVX_WIDEN_TRANS(vwsll_vx, vwsll_vx_check)
665
CLINT_TIMEBASE_FREQ, false);
528
+GEN_OPIVI_WIDEN_TRANS(vwsll_vi, IMM_ZX, vwsll_vx, vwsll_vx_check)
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
}
763
764
/* register system main memory (actual RAM) */
765
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
766
index XXXXXXX..XXXXXXX 100644
767
--- a/hw/riscv/virt.c
768
+++ b/hw/riscv/virt.c
769
@@ -XXX,XX +XXX,XX @@ static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap,
770
771
qemu_fdt_add_subnode(fdt, "/cpus");
772
qemu_fdt_setprop_cell(fdt, "/cpus", "timebase-frequency",
773
- SIFIVE_CLINT_TIMEBASE_FREQ);
774
+ RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ);
775
qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0x0);
776
qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 0x1);
777
qemu_fdt_add_subnode(fdt, "/cpus/cpu-map");
778
@@ -XXX,XX +XXX,XX @@ static void virt_machine_init(MachineState *machine)
779
sysbus_realize(SYS_BUS_DEVICE(&s->soc[i]), &error_abort);
780
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
--
529
--
799
2.31.1
530
2.41.0
800
801
diff view generated by jsdifflib
New patch
1
From: Nazar Kazakov <nazar.kazakov@codethink.co.uk>
1
2
3
This commit adds support for the Zvkned vector-crypto extension, which
4
consists of the following instructions:
5
6
* vaesef.[vv,vs]
7
* vaesdf.[vv,vs]
8
* vaesdm.[vv,vs]
9
* vaesz.vs
10
* vaesem.[vv,vs]
11
* vaeskf1.vi
12
* vaeskf2.vi
13
14
Translation functions are defined in
15
`target/riscv/insn_trans/trans_rvvk.c.inc` and helpers are defined in
16
`target/riscv/vcrypto_helper.c`.
17
18
Co-authored-by: Lawrence Hunter <lawrence.hunter@codethink.co.uk>
19
Co-authored-by: William Salmon <will.salmon@codethink.co.uk>
20
[max.chou@sifive.com: Replaced vstart checking by TCG op]
21
Signed-off-by: Lawrence Hunter <lawrence.hunter@codethink.co.uk>
22
Signed-off-by: William Salmon <will.salmon@codethink.co.uk>
23
Signed-off-by: Nazar Kazakov <nazar.kazakov@codethink.co.uk>
24
Signed-off-by: Max Chou <max.chou@sifive.com>
25
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
26
[max.chou@sifive.com: Imported aes-round.h and exposed x-zvkned
27
property]
28
[max.chou@sifive.com: Fixed endian issues and replaced the vstart & vl
29
egs checking by helper function]
30
[max.chou@sifive.com: Replaced bswap32 calls in aes key expanding]
31
Message-ID: <20230711165917.2629866-10-max.chou@sifive.com>
32
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
33
---
34
target/riscv/cpu_cfg.h | 1 +
35
target/riscv/helper.h | 14 ++
36
target/riscv/insn32.decode | 14 ++
37
target/riscv/cpu.c | 4 +-
38
target/riscv/vcrypto_helper.c | 202 +++++++++++++++++++++++
39
target/riscv/insn_trans/trans_rvvk.c.inc | 147 +++++++++++++++++
40
6 files changed, 381 insertions(+), 1 deletion(-)
41
42
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/riscv/cpu_cfg.h
45
+++ b/target/riscv/cpu_cfg.h
46
@@ -XXX,XX +XXX,XX @@ struct RISCVCPUConfig {
47
bool ext_zve64d;
48
bool ext_zvbb;
49
bool ext_zvbc;
50
+ bool ext_zvkned;
51
bool ext_zmmul;
52
bool ext_zvfbfmin;
53
bool ext_zvfbfwma;
54
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
55
index XXXXXXX..XXXXXXX 100644
56
--- a/target/riscv/helper.h
57
+++ b/target/riscv/helper.h
58
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_6(vandn_vx_b, void, ptr, ptr, tl, ptr, env, i32)
59
DEF_HELPER_6(vandn_vx_h, void, ptr, ptr, tl, ptr, env, i32)
60
DEF_HELPER_6(vandn_vx_w, void, ptr, ptr, tl, ptr, env, i32)
61
DEF_HELPER_6(vandn_vx_d, void, ptr, ptr, tl, ptr, env, i32)
62
+
63
+DEF_HELPER_2(egs_check, void, i32, env)
64
+
65
+DEF_HELPER_4(vaesef_vv, void, ptr, ptr, env, i32)
66
+DEF_HELPER_4(vaesef_vs, void, ptr, ptr, env, i32)
67
+DEF_HELPER_4(vaesdf_vv, void, ptr, ptr, env, i32)
68
+DEF_HELPER_4(vaesdf_vs, void, ptr, ptr, env, i32)
69
+DEF_HELPER_4(vaesem_vv, void, ptr, ptr, env, i32)
70
+DEF_HELPER_4(vaesem_vs, void, ptr, ptr, env, i32)
71
+DEF_HELPER_4(vaesdm_vv, void, ptr, ptr, env, i32)
72
+DEF_HELPER_4(vaesdm_vs, void, ptr, ptr, env, i32)
73
+DEF_HELPER_4(vaesz_vs, void, ptr, ptr, env, i32)
74
+DEF_HELPER_5(vaeskf1_vi, void, ptr, ptr, i32, env, i32)
75
+DEF_HELPER_5(vaeskf2_vi, void, ptr, ptr, i32, env, i32)
76
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
77
index XXXXXXX..XXXXXXX 100644
78
--- a/target/riscv/insn32.decode
79
+++ b/target/riscv/insn32.decode
80
@@ -XXX,XX +XXX,XX @@
81
@r_rm ....... ..... ..... ... ..... ....... %rs2 %rs1 %rm %rd
82
@r2_rm ....... ..... ..... ... ..... ....... %rs1 %rm %rd
83
@r2 ....... ..... ..... ... ..... ....... &r2 %rs1 %rd
84
+@r2_vm_1 ...... . ..... ..... ... ..... ....... &rmr vm=1 %rs2 %rd
85
@r2_nfvm ... ... vm:1 ..... ..... ... ..... ....... &r2nfvm %nf %rs1 %rd
86
@r2_vm ...... vm:1 ..... ..... ... ..... ....... &rmr %rs2 %rd
87
@r1_vm ...... vm:1 ..... ..... ... ..... ....... %rd
88
@@ -XXX,XX +XXX,XX @@ vcpop_v 010010 . ..... 01110 010 ..... 1010111 @r2_vm
89
vwsll_vv 110101 . ..... ..... 000 ..... 1010111 @r_vm
90
vwsll_vx 110101 . ..... ..... 100 ..... 1010111 @r_vm
91
vwsll_vi 110101 . ..... ..... 011 ..... 1010111 @r_vm
92
+
93
+# *** Zvkned vector crypto extension ***
94
+vaesef_vv 101000 1 ..... 00011 010 ..... 1110111 @r2_vm_1
95
+vaesef_vs 101001 1 ..... 00011 010 ..... 1110111 @r2_vm_1
96
+vaesdf_vv 101000 1 ..... 00001 010 ..... 1110111 @r2_vm_1
97
+vaesdf_vs 101001 1 ..... 00001 010 ..... 1110111 @r2_vm_1
98
+vaesem_vv 101000 1 ..... 00010 010 ..... 1110111 @r2_vm_1
99
+vaesem_vs 101001 1 ..... 00010 010 ..... 1110111 @r2_vm_1
100
+vaesdm_vv 101000 1 ..... 00000 010 ..... 1110111 @r2_vm_1
101
+vaesdm_vs 101001 1 ..... 00000 010 ..... 1110111 @r2_vm_1
102
+vaesz_vs 101001 1 ..... 00111 010 ..... 1110111 @r2_vm_1
103
+vaeskf1_vi 100010 1 ..... ..... 010 ..... 1110111 @r_vm_1
104
+vaeskf2_vi 101010 1 ..... ..... 010 ..... 1110111 @r_vm_1
105
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
106
index XXXXXXX..XXXXXXX 100644
107
--- a/target/riscv/cpu.c
108
+++ b/target/riscv/cpu.c
109
@@ -XXX,XX +XXX,XX @@ static const struct isa_ext_data isa_edata_arr[] = {
110
ISA_EXT_DATA_ENTRY(zvfbfwma, PRIV_VERSION_1_12_0, ext_zvfbfwma),
111
ISA_EXT_DATA_ENTRY(zvfh, PRIV_VERSION_1_12_0, ext_zvfh),
112
ISA_EXT_DATA_ENTRY(zvfhmin, PRIV_VERSION_1_12_0, ext_zvfhmin),
113
+ ISA_EXT_DATA_ENTRY(zvkned, PRIV_VERSION_1_12_0, ext_zvkned),
114
ISA_EXT_DATA_ENTRY(zhinx, PRIV_VERSION_1_12_0, ext_zhinx),
115
ISA_EXT_DATA_ENTRY(zhinxmin, PRIV_VERSION_1_12_0, ext_zhinxmin),
116
ISA_EXT_DATA_ENTRY(smaia, PRIV_VERSION_1_12_0, ext_smaia),
117
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
118
* In principle Zve*x would also suffice here, were they supported
119
* in qemu
120
*/
121
- if (cpu->cfg.ext_zvbb && !cpu->cfg.ext_zve32f) {
122
+ if ((cpu->cfg.ext_zvbb || cpu->cfg.ext_zvkned) && !cpu->cfg.ext_zve32f) {
123
error_setg(errp,
124
"Vector crypto extensions require V or Zve* extensions");
125
return;
126
@@ -XXX,XX +XXX,XX @@ static Property riscv_cpu_extensions[] = {
127
/* Vector cryptography extensions */
128
DEFINE_PROP_BOOL("x-zvbb", RISCVCPU, cfg.ext_zvbb, false),
129
DEFINE_PROP_BOOL("x-zvbc", RISCVCPU, cfg.ext_zvbc, false),
130
+ DEFINE_PROP_BOOL("x-zvkned", RISCVCPU, cfg.ext_zvkned, false),
131
132
DEFINE_PROP_END_OF_LIST(),
133
};
134
diff --git a/target/riscv/vcrypto_helper.c b/target/riscv/vcrypto_helper.c
135
index XXXXXXX..XXXXXXX 100644
136
--- a/target/riscv/vcrypto_helper.c
137
+++ b/target/riscv/vcrypto_helper.c
138
@@ -XXX,XX +XXX,XX @@
139
#include "qemu/bitops.h"
140
#include "qemu/bswap.h"
141
#include "cpu.h"
142
+#include "crypto/aes.h"
143
+#include "crypto/aes-round.h"
144
#include "exec/memop.h"
145
#include "exec/exec-all.h"
146
#include "exec/helper-proto.h"
147
@@ -XXX,XX +XXX,XX @@ RVVCALL(OPIVX2, vwsll_vx_w, WOP_UUU_W, H8, H4, DO_SLL)
148
GEN_VEXT_VX(vwsll_vx_b, 2)
149
GEN_VEXT_VX(vwsll_vx_h, 4)
150
GEN_VEXT_VX(vwsll_vx_w, 8)
151
+
152
+void HELPER(egs_check)(uint32_t egs, CPURISCVState *env)
153
+{
154
+ uint32_t vl = env->vl;
155
+ uint32_t vstart = env->vstart;
156
+
157
+ if (vl % egs != 0 || vstart % egs != 0) {
158
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
159
+ }
160
+}
161
+
162
+static inline void xor_round_key(AESState *round_state, AESState *round_key)
163
+{
164
+ round_state->v = round_state->v ^ round_key->v;
165
+}
166
+
167
+#define GEN_ZVKNED_HELPER_VV(NAME, ...) \
168
+ void HELPER(NAME)(void *vd, void *vs2, CPURISCVState *env, \
169
+ uint32_t desc) \
170
+ { \
171
+ uint32_t vl = env->vl; \
172
+ uint32_t total_elems = vext_get_total_elems(env, desc, 4); \
173
+ uint32_t vta = vext_vta(desc); \
174
+ \
175
+ for (uint32_t i = env->vstart / 4; i < env->vl / 4; i++) { \
176
+ AESState round_key; \
177
+ round_key.d[0] = *((uint64_t *)vs2 + H8(i * 2 + 0)); \
178
+ round_key.d[1] = *((uint64_t *)vs2 + H8(i * 2 + 1)); \
179
+ AESState round_state; \
180
+ round_state.d[0] = *((uint64_t *)vd + H8(i * 2 + 0)); \
181
+ round_state.d[1] = *((uint64_t *)vd + H8(i * 2 + 1)); \
182
+ __VA_ARGS__; \
183
+ *((uint64_t *)vd + H8(i * 2 + 0)) = round_state.d[0]; \
184
+ *((uint64_t *)vd + H8(i * 2 + 1)) = round_state.d[1]; \
185
+ } \
186
+ env->vstart = 0; \
187
+ /* set tail elements to 1s */ \
188
+ vext_set_elems_1s(vd, vta, vl * 4, total_elems * 4); \
189
+ }
190
+
191
+#define GEN_ZVKNED_HELPER_VS(NAME, ...) \
192
+ void HELPER(NAME)(void *vd, void *vs2, CPURISCVState *env, \
193
+ uint32_t desc) \
194
+ { \
195
+ uint32_t vl = env->vl; \
196
+ uint32_t total_elems = vext_get_total_elems(env, desc, 4); \
197
+ uint32_t vta = vext_vta(desc); \
198
+ \
199
+ for (uint32_t i = env->vstart / 4; i < env->vl / 4; i++) { \
200
+ AESState round_key; \
201
+ round_key.d[0] = *((uint64_t *)vs2 + H8(0)); \
202
+ round_key.d[1] = *((uint64_t *)vs2 + H8(1)); \
203
+ AESState round_state; \
204
+ round_state.d[0] = *((uint64_t *)vd + H8(i * 2 + 0)); \
205
+ round_state.d[1] = *((uint64_t *)vd + H8(i * 2 + 1)); \
206
+ __VA_ARGS__; \
207
+ *((uint64_t *)vd + H8(i * 2 + 0)) = round_state.d[0]; \
208
+ *((uint64_t *)vd + H8(i * 2 + 1)) = round_state.d[1]; \
209
+ } \
210
+ env->vstart = 0; \
211
+ /* set tail elements to 1s */ \
212
+ vext_set_elems_1s(vd, vta, vl * 4, total_elems * 4); \
213
+ }
214
+
215
+GEN_ZVKNED_HELPER_VV(vaesef_vv, aesenc_SB_SR_AK(&round_state,
216
+ &round_state,
217
+ &round_key,
218
+ false);)
219
+GEN_ZVKNED_HELPER_VS(vaesef_vs, aesenc_SB_SR_AK(&round_state,
220
+ &round_state,
221
+ &round_key,
222
+ false);)
223
+GEN_ZVKNED_HELPER_VV(vaesdf_vv, aesdec_ISB_ISR_AK(&round_state,
224
+ &round_state,
225
+ &round_key,
226
+ false);)
227
+GEN_ZVKNED_HELPER_VS(vaesdf_vs, aesdec_ISB_ISR_AK(&round_state,
228
+ &round_state,
229
+ &round_key,
230
+ false);)
231
+GEN_ZVKNED_HELPER_VV(vaesem_vv, aesenc_SB_SR_MC_AK(&round_state,
232
+ &round_state,
233
+ &round_key,
234
+ false);)
235
+GEN_ZVKNED_HELPER_VS(vaesem_vs, aesenc_SB_SR_MC_AK(&round_state,
236
+ &round_state,
237
+ &round_key,
238
+ false);)
239
+GEN_ZVKNED_HELPER_VV(vaesdm_vv, aesdec_ISB_ISR_AK_IMC(&round_state,
240
+ &round_state,
241
+ &round_key,
242
+ false);)
243
+GEN_ZVKNED_HELPER_VS(vaesdm_vs, aesdec_ISB_ISR_AK_IMC(&round_state,
244
+ &round_state,
245
+ &round_key,
246
+ false);)
247
+GEN_ZVKNED_HELPER_VS(vaesz_vs, xor_round_key(&round_state, &round_key);)
248
+
249
+void HELPER(vaeskf1_vi)(void *vd_vptr, void *vs2_vptr, uint32_t uimm,
250
+ CPURISCVState *env, uint32_t desc)
251
+{
252
+ uint32_t *vd = vd_vptr;
253
+ uint32_t *vs2 = vs2_vptr;
254
+ uint32_t vl = env->vl;
255
+ uint32_t total_elems = vext_get_total_elems(env, desc, 4);
256
+ uint32_t vta = vext_vta(desc);
257
+
258
+ uimm &= 0b1111;
259
+ if (uimm > 10 || uimm == 0) {
260
+ uimm ^= 0b1000;
261
+ }
262
+
263
+ for (uint32_t i = env->vstart / 4; i < env->vl / 4; i++) {
264
+ uint32_t rk[8], tmp;
265
+ static const uint32_t rcon[] = {
266
+ 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010,
267
+ 0x00000020, 0x00000040, 0x00000080, 0x0000001B, 0x00000036,
268
+ };
269
+
270
+ rk[0] = vs2[i * 4 + H4(0)];
271
+ rk[1] = vs2[i * 4 + H4(1)];
272
+ rk[2] = vs2[i * 4 + H4(2)];
273
+ rk[3] = vs2[i * 4 + H4(3)];
274
+ tmp = ror32(rk[3], 8);
275
+
276
+ rk[4] = rk[0] ^ (((uint32_t)AES_sbox[(tmp >> 24) & 0xff] << 24) |
277
+ ((uint32_t)AES_sbox[(tmp >> 16) & 0xff] << 16) |
278
+ ((uint32_t)AES_sbox[(tmp >> 8) & 0xff] << 8) |
279
+ ((uint32_t)AES_sbox[(tmp >> 0) & 0xff] << 0))
280
+ ^ rcon[uimm - 1];
281
+ rk[5] = rk[1] ^ rk[4];
282
+ rk[6] = rk[2] ^ rk[5];
283
+ rk[7] = rk[3] ^ rk[6];
284
+
285
+ vd[i * 4 + H4(0)] = rk[4];
286
+ vd[i * 4 + H4(1)] = rk[5];
287
+ vd[i * 4 + H4(2)] = rk[6];
288
+ vd[i * 4 + H4(3)] = rk[7];
289
+ }
290
+ env->vstart = 0;
291
+ /* set tail elements to 1s */
292
+ vext_set_elems_1s(vd, vta, vl * 4, total_elems * 4);
293
+}
294
+
295
+void HELPER(vaeskf2_vi)(void *vd_vptr, void *vs2_vptr, uint32_t uimm,
296
+ CPURISCVState *env, uint32_t desc)
297
+{
298
+ uint32_t *vd = vd_vptr;
299
+ uint32_t *vs2 = vs2_vptr;
300
+ uint32_t vl = env->vl;
301
+ uint32_t total_elems = vext_get_total_elems(env, desc, 4);
302
+ uint32_t vta = vext_vta(desc);
303
+
304
+ uimm &= 0b1111;
305
+ if (uimm > 14 || uimm < 2) {
306
+ uimm ^= 0b1000;
307
+ }
308
+
309
+ for (uint32_t i = env->vstart / 4; i < env->vl / 4; i++) {
310
+ uint32_t rk[12], tmp;
311
+ static const uint32_t rcon[] = {
312
+ 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010,
313
+ 0x00000020, 0x00000040, 0x00000080, 0x0000001B, 0x00000036,
314
+ };
315
+
316
+ rk[0] = vd[i * 4 + H4(0)];
317
+ rk[1] = vd[i * 4 + H4(1)];
318
+ rk[2] = vd[i * 4 + H4(2)];
319
+ rk[3] = vd[i * 4 + H4(3)];
320
+ rk[4] = vs2[i * 4 + H4(0)];
321
+ rk[5] = vs2[i * 4 + H4(1)];
322
+ rk[6] = vs2[i * 4 + H4(2)];
323
+ rk[7] = vs2[i * 4 + H4(3)];
324
+
325
+ if (uimm % 2 == 0) {
326
+ tmp = ror32(rk[7], 8);
327
+ rk[8] = rk[0] ^ (((uint32_t)AES_sbox[(tmp >> 24) & 0xff] << 24) |
328
+ ((uint32_t)AES_sbox[(tmp >> 16) & 0xff] << 16) |
329
+ ((uint32_t)AES_sbox[(tmp >> 8) & 0xff] << 8) |
330
+ ((uint32_t)AES_sbox[(tmp >> 0) & 0xff] << 0))
331
+ ^ rcon[(uimm - 1) / 2];
332
+ } else {
333
+ rk[8] = rk[0] ^ (((uint32_t)AES_sbox[(rk[7] >> 24) & 0xff] << 24) |
334
+ ((uint32_t)AES_sbox[(rk[7] >> 16) & 0xff] << 16) |
335
+ ((uint32_t)AES_sbox[(rk[7] >> 8) & 0xff] << 8) |
336
+ ((uint32_t)AES_sbox[(rk[7] >> 0) & 0xff] << 0));
337
+ }
338
+ rk[9] = rk[1] ^ rk[8];
339
+ rk[10] = rk[2] ^ rk[9];
340
+ rk[11] = rk[3] ^ rk[10];
341
+
342
+ vd[i * 4 + H4(0)] = rk[8];
343
+ vd[i * 4 + H4(1)] = rk[9];
344
+ vd[i * 4 + H4(2)] = rk[10];
345
+ vd[i * 4 + H4(3)] = rk[11];
346
+ }
347
+ env->vstart = 0;
348
+ /* set tail elements to 1s */
349
+ vext_set_elems_1s(vd, vta, vl * 4, total_elems * 4);
350
+}
351
diff --git a/target/riscv/insn_trans/trans_rvvk.c.inc b/target/riscv/insn_trans/trans_rvvk.c.inc
352
index XXXXXXX..XXXXXXX 100644
353
--- a/target/riscv/insn_trans/trans_rvvk.c.inc
354
+++ b/target/riscv/insn_trans/trans_rvvk.c.inc
355
@@ -XXX,XX +XXX,XX @@ static bool vwsll_vx_check(DisasContext *s, arg_rmrr *a)
356
GEN_OPIVV_WIDEN_TRANS(vwsll_vv, vwsll_vv_check)
357
GEN_OPIVX_WIDEN_TRANS(vwsll_vx, vwsll_vx_check)
358
GEN_OPIVI_WIDEN_TRANS(vwsll_vi, IMM_ZX, vwsll_vx, vwsll_vx_check)
359
+
360
+/*
361
+ * Zvkned
362
+ */
363
+
364
+#define ZVKNED_EGS 4
365
+
366
+#define GEN_V_UNMASKED_TRANS(NAME, CHECK, EGS) \
367
+ static bool trans_##NAME(DisasContext *s, arg_##NAME *a) \
368
+ { \
369
+ if (CHECK(s, a)) { \
370
+ TCGv_ptr rd_v, rs2_v; \
371
+ TCGv_i32 desc, egs; \
372
+ uint32_t data = 0; \
373
+ TCGLabel *over = gen_new_label(); \
374
+ \
375
+ if (!s->vstart_eq_zero || !s->vl_eq_vlmax) { \
376
+ /* save opcode for unwinding in case we throw an exception */ \
377
+ decode_save_opc(s); \
378
+ egs = tcg_constant_i32(EGS); \
379
+ gen_helper_egs_check(egs, cpu_env); \
380
+ tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); \
381
+ } \
382
+ \
383
+ data = FIELD_DP32(data, VDATA, VM, a->vm); \
384
+ data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \
385
+ data = FIELD_DP32(data, VDATA, VTA, s->vta); \
386
+ data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s); \
387
+ data = FIELD_DP32(data, VDATA, VMA, s->vma); \
388
+ rd_v = tcg_temp_new_ptr(); \
389
+ rs2_v = tcg_temp_new_ptr(); \
390
+ desc = tcg_constant_i32( \
391
+ simd_desc(s->cfg_ptr->vlen / 8, s->cfg_ptr->vlen / 8, data)); \
392
+ tcg_gen_addi_ptr(rd_v, cpu_env, vreg_ofs(s, a->rd)); \
393
+ tcg_gen_addi_ptr(rs2_v, cpu_env, vreg_ofs(s, a->rs2)); \
394
+ gen_helper_##NAME(rd_v, rs2_v, cpu_env, desc); \
395
+ mark_vs_dirty(s); \
396
+ gen_set_label(over); \
397
+ return true; \
398
+ } \
399
+ return false; \
400
+ }
401
+
402
+static bool vaes_check_vv(DisasContext *s, arg_rmr *a)
403
+{
404
+ int egw_bytes = ZVKNED_EGS << s->sew;
405
+ return s->cfg_ptr->ext_zvkned == true &&
406
+ require_rvv(s) &&
407
+ vext_check_isa_ill(s) &&
408
+ MAXSZ(s) >= egw_bytes &&
409
+ require_align(a->rd, s->lmul) &&
410
+ require_align(a->rs2, s->lmul) &&
411
+ s->sew == MO_32;
412
+}
413
+
414
+static bool vaes_check_overlap(DisasContext *s, int vd, int vs2)
415
+{
416
+ int8_t op_size = s->lmul <= 0 ? 1 : 1 << s->lmul;
417
+ return !is_overlapped(vd, op_size, vs2, 1);
418
+}
419
+
420
+static bool vaes_check_vs(DisasContext *s, arg_rmr *a)
421
+{
422
+ int egw_bytes = ZVKNED_EGS << s->sew;
423
+ return vaes_check_overlap(s, a->rd, a->rs2) &&
424
+ MAXSZ(s) >= egw_bytes &&
425
+ s->cfg_ptr->ext_zvkned == true &&
426
+ require_rvv(s) &&
427
+ vext_check_isa_ill(s) &&
428
+ require_align(a->rd, s->lmul) &&
429
+ s->sew == MO_32;
430
+}
431
+
432
+GEN_V_UNMASKED_TRANS(vaesef_vv, vaes_check_vv, ZVKNED_EGS)
433
+GEN_V_UNMASKED_TRANS(vaesef_vs, vaes_check_vs, ZVKNED_EGS)
434
+GEN_V_UNMASKED_TRANS(vaesdf_vv, vaes_check_vv, ZVKNED_EGS)
435
+GEN_V_UNMASKED_TRANS(vaesdf_vs, vaes_check_vs, ZVKNED_EGS)
436
+GEN_V_UNMASKED_TRANS(vaesdm_vv, vaes_check_vv, ZVKNED_EGS)
437
+GEN_V_UNMASKED_TRANS(vaesdm_vs, vaes_check_vs, ZVKNED_EGS)
438
+GEN_V_UNMASKED_TRANS(vaesz_vs, vaes_check_vs, ZVKNED_EGS)
439
+GEN_V_UNMASKED_TRANS(vaesem_vv, vaes_check_vv, ZVKNED_EGS)
440
+GEN_V_UNMASKED_TRANS(vaesem_vs, vaes_check_vs, ZVKNED_EGS)
441
+
442
+#define GEN_VI_UNMASKED_TRANS(NAME, CHECK, EGS) \
443
+ static bool trans_##NAME(DisasContext *s, arg_##NAME *a) \
444
+ { \
445
+ if (CHECK(s, a)) { \
446
+ TCGv_ptr rd_v, rs2_v; \
447
+ TCGv_i32 uimm_v, desc, egs; \
448
+ uint32_t data = 0; \
449
+ TCGLabel *over = gen_new_label(); \
450
+ \
451
+ if (!s->vstart_eq_zero || !s->vl_eq_vlmax) { \
452
+ /* save opcode for unwinding in case we throw an exception */ \
453
+ decode_save_opc(s); \
454
+ egs = tcg_constant_i32(EGS); \
455
+ gen_helper_egs_check(egs, cpu_env); \
456
+ tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); \
457
+ } \
458
+ \
459
+ data = FIELD_DP32(data, VDATA, VM, a->vm); \
460
+ data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \
461
+ data = FIELD_DP32(data, VDATA, VTA, s->vta); \
462
+ data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s); \
463
+ data = FIELD_DP32(data, VDATA, VMA, s->vma); \
464
+ \
465
+ rd_v = tcg_temp_new_ptr(); \
466
+ rs2_v = tcg_temp_new_ptr(); \
467
+ uimm_v = tcg_constant_i32(a->rs1); \
468
+ desc = tcg_constant_i32( \
469
+ simd_desc(s->cfg_ptr->vlen / 8, s->cfg_ptr->vlen / 8, data)); \
470
+ tcg_gen_addi_ptr(rd_v, cpu_env, vreg_ofs(s, a->rd)); \
471
+ tcg_gen_addi_ptr(rs2_v, cpu_env, vreg_ofs(s, a->rs2)); \
472
+ gen_helper_##NAME(rd_v, rs2_v, uimm_v, cpu_env, desc); \
473
+ mark_vs_dirty(s); \
474
+ gen_set_label(over); \
475
+ return true; \
476
+ } \
477
+ return false; \
478
+ }
479
+
480
+static bool vaeskf1_check(DisasContext *s, arg_vaeskf1_vi *a)
481
+{
482
+ int egw_bytes = ZVKNED_EGS << s->sew;
483
+ return s->cfg_ptr->ext_zvkned == true &&
484
+ require_rvv(s) &&
485
+ vext_check_isa_ill(s) &&
486
+ MAXSZ(s) >= egw_bytes &&
487
+ s->sew == MO_32 &&
488
+ require_align(a->rd, s->lmul) &&
489
+ require_align(a->rs2, s->lmul);
490
+}
491
+
492
+static bool vaeskf2_check(DisasContext *s, arg_vaeskf2_vi *a)
493
+{
494
+ int egw_bytes = ZVKNED_EGS << s->sew;
495
+ return s->cfg_ptr->ext_zvkned == true &&
496
+ require_rvv(s) &&
497
+ vext_check_isa_ill(s) &&
498
+ MAXSZ(s) >= egw_bytes &&
499
+ s->sew == MO_32 &&
500
+ require_align(a->rd, s->lmul) &&
501
+ require_align(a->rs2, s->lmul);
502
+}
503
+
504
+GEN_VI_UNMASKED_TRANS(vaeskf1_vi, vaeskf1_check, ZVKNED_EGS)
505
+GEN_VI_UNMASKED_TRANS(vaeskf2_vi, vaeskf2_check, ZVKNED_EGS)
506
--
507
2.41.0
diff view generated by jsdifflib
New patch
1
From: Kiran Ostrolenk <kiran.ostrolenk@codethink.co.uk>
1
2
3
This commit adds support for the Zvknh vector-crypto extension, which
4
consists of the following instructions:
5
6
* vsha2ms.vv
7
* vsha2c[hl].vv
8
9
Translation functions are defined in
10
`target/riscv/insn_trans/trans_rvvk.c.inc` and helpers are defined in
11
`target/riscv/vcrypto_helper.c`.
12
13
Co-authored-by: Nazar Kazakov <nazar.kazakov@codethink.co.uk>
14
Co-authored-by: Lawrence Hunter <lawrence.hunter@codethink.co.uk>
15
[max.chou@sifive.com: Replaced vstart checking by TCG op]
16
Signed-off-by: Nazar Kazakov <nazar.kazakov@codethink.co.uk>
17
Signed-off-by: Lawrence Hunter <lawrence.hunter@codethink.co.uk>
18
Signed-off-by: Kiran Ostrolenk <kiran.ostrolenk@codethink.co.uk>
19
Signed-off-by: Max Chou <max.chou@sifive.com>
20
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
21
[max.chou@sifive.com: Exposed x-zvknha & x-zvknhb properties]
22
[max.chou@sifive.com: Replaced SEW selection to happened during
23
translation]
24
Message-ID: <20230711165917.2629866-11-max.chou@sifive.com>
25
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
26
---
27
target/riscv/cpu_cfg.h | 2 +
28
target/riscv/helper.h | 6 +
29
target/riscv/insn32.decode | 5 +
30
target/riscv/cpu.c | 13 +-
31
target/riscv/vcrypto_helper.c | 238 +++++++++++++++++++++++
32
target/riscv/insn_trans/trans_rvvk.c.inc | 129 ++++++++++++
33
6 files changed, 390 insertions(+), 3 deletions(-)
34
35
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/riscv/cpu_cfg.h
38
+++ b/target/riscv/cpu_cfg.h
39
@@ -XXX,XX +XXX,XX @@ struct RISCVCPUConfig {
40
bool ext_zvbb;
41
bool ext_zvbc;
42
bool ext_zvkned;
43
+ bool ext_zvknha;
44
+ bool ext_zvknhb;
45
bool ext_zmmul;
46
bool ext_zvfbfmin;
47
bool ext_zvfbfwma;
48
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
49
index XXXXXXX..XXXXXXX 100644
50
--- a/target/riscv/helper.h
51
+++ b/target/riscv/helper.h
52
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_4(vaesdm_vs, void, ptr, ptr, env, i32)
53
DEF_HELPER_4(vaesz_vs, void, ptr, ptr, env, i32)
54
DEF_HELPER_5(vaeskf1_vi, void, ptr, ptr, i32, env, i32)
55
DEF_HELPER_5(vaeskf2_vi, void, ptr, ptr, i32, env, i32)
56
+
57
+DEF_HELPER_5(vsha2ms_vv, void, ptr, ptr, ptr, env, i32)
58
+DEF_HELPER_5(vsha2ch32_vv, void, ptr, ptr, ptr, env, i32)
59
+DEF_HELPER_5(vsha2ch64_vv, void, ptr, ptr, ptr, env, i32)
60
+DEF_HELPER_5(vsha2cl32_vv, void, ptr, ptr, ptr, env, i32)
61
+DEF_HELPER_5(vsha2cl64_vv, void, ptr, ptr, ptr, env, i32)
62
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
63
index XXXXXXX..XXXXXXX 100644
64
--- a/target/riscv/insn32.decode
65
+++ b/target/riscv/insn32.decode
66
@@ -XXX,XX +XXX,XX @@ vaesdm_vs 101001 1 ..... 00000 010 ..... 1110111 @r2_vm_1
67
vaesz_vs 101001 1 ..... 00111 010 ..... 1110111 @r2_vm_1
68
vaeskf1_vi 100010 1 ..... ..... 010 ..... 1110111 @r_vm_1
69
vaeskf2_vi 101010 1 ..... ..... 010 ..... 1110111 @r_vm_1
70
+
71
+# *** Zvknh vector crypto extension ***
72
+vsha2ms_vv 101101 1 ..... ..... 010 ..... 1110111 @r_vm_1
73
+vsha2ch_vv 101110 1 ..... ..... 010 ..... 1110111 @r_vm_1
74
+vsha2cl_vv 101111 1 ..... ..... 010 ..... 1110111 @r_vm_1
75
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/target/riscv/cpu.c
78
+++ b/target/riscv/cpu.c
79
@@ -XXX,XX +XXX,XX @@ static const struct isa_ext_data isa_edata_arr[] = {
80
ISA_EXT_DATA_ENTRY(zvfh, PRIV_VERSION_1_12_0, ext_zvfh),
81
ISA_EXT_DATA_ENTRY(zvfhmin, PRIV_VERSION_1_12_0, ext_zvfhmin),
82
ISA_EXT_DATA_ENTRY(zvkned, PRIV_VERSION_1_12_0, ext_zvkned),
83
+ ISA_EXT_DATA_ENTRY(zvknha, PRIV_VERSION_1_12_0, ext_zvknha),
84
+ ISA_EXT_DATA_ENTRY(zvknhb, PRIV_VERSION_1_12_0, ext_zvknhb),
85
ISA_EXT_DATA_ENTRY(zhinx, PRIV_VERSION_1_12_0, ext_zhinx),
86
ISA_EXT_DATA_ENTRY(zhinxmin, PRIV_VERSION_1_12_0, ext_zhinxmin),
87
ISA_EXT_DATA_ENTRY(smaia, PRIV_VERSION_1_12_0, ext_smaia),
88
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
89
* In principle Zve*x would also suffice here, were they supported
90
* in qemu
91
*/
92
- if ((cpu->cfg.ext_zvbb || cpu->cfg.ext_zvkned) && !cpu->cfg.ext_zve32f) {
93
+ if ((cpu->cfg.ext_zvbb || cpu->cfg.ext_zvkned || cpu->cfg.ext_zvknha) &&
94
+ !cpu->cfg.ext_zve32f) {
95
error_setg(errp,
96
"Vector crypto extensions require V or Zve* extensions");
97
return;
98
}
99
100
- if (cpu->cfg.ext_zvbc && !cpu->cfg.ext_zve64f) {
101
- error_setg(errp, "Zvbc extension requires V or Zve64{f,d} extensions");
102
+ if ((cpu->cfg.ext_zvbc || cpu->cfg.ext_zvknhb) && !cpu->cfg.ext_zve64f) {
103
+ error_setg(
104
+ errp,
105
+ "Zvbc and Zvknhb extensions require V or Zve64{f,d} extensions");
106
return;
107
}
108
109
@@ -XXX,XX +XXX,XX @@ static Property riscv_cpu_extensions[] = {
110
DEFINE_PROP_BOOL("x-zvbb", RISCVCPU, cfg.ext_zvbb, false),
111
DEFINE_PROP_BOOL("x-zvbc", RISCVCPU, cfg.ext_zvbc, false),
112
DEFINE_PROP_BOOL("x-zvkned", RISCVCPU, cfg.ext_zvkned, false),
113
+ DEFINE_PROP_BOOL("x-zvknha", RISCVCPU, cfg.ext_zvknha, false),
114
+ DEFINE_PROP_BOOL("x-zvknhb", RISCVCPU, cfg.ext_zvknhb, false),
115
116
DEFINE_PROP_END_OF_LIST(),
117
};
118
diff --git a/target/riscv/vcrypto_helper.c b/target/riscv/vcrypto_helper.c
119
index XXXXXXX..XXXXXXX 100644
120
--- a/target/riscv/vcrypto_helper.c
121
+++ b/target/riscv/vcrypto_helper.c
122
@@ -XXX,XX +XXX,XX @@ void HELPER(vaeskf2_vi)(void *vd_vptr, void *vs2_vptr, uint32_t uimm,
123
/* set tail elements to 1s */
124
vext_set_elems_1s(vd, vta, vl * 4, total_elems * 4);
125
}
126
+
127
+static inline uint32_t sig0_sha256(uint32_t x)
128
+{
129
+ return ror32(x, 7) ^ ror32(x, 18) ^ (x >> 3);
130
+}
131
+
132
+static inline uint32_t sig1_sha256(uint32_t x)
133
+{
134
+ return ror32(x, 17) ^ ror32(x, 19) ^ (x >> 10);
135
+}
136
+
137
+static inline uint64_t sig0_sha512(uint64_t x)
138
+{
139
+ return ror64(x, 1) ^ ror64(x, 8) ^ (x >> 7);
140
+}
141
+
142
+static inline uint64_t sig1_sha512(uint64_t x)
143
+{
144
+ return ror64(x, 19) ^ ror64(x, 61) ^ (x >> 6);
145
+}
146
+
147
+static inline void vsha2ms_e32(uint32_t *vd, uint32_t *vs1, uint32_t *vs2)
148
+{
149
+ uint32_t res[4];
150
+ res[0] = sig1_sha256(vs1[H4(2)]) + vs2[H4(1)] + sig0_sha256(vd[H4(1)]) +
151
+ vd[H4(0)];
152
+ res[1] = sig1_sha256(vs1[H4(3)]) + vs2[H4(2)] + sig0_sha256(vd[H4(2)]) +
153
+ vd[H4(1)];
154
+ res[2] =
155
+ sig1_sha256(res[0]) + vs2[H4(3)] + sig0_sha256(vd[H4(3)]) + vd[H4(2)];
156
+ res[3] =
157
+ sig1_sha256(res[1]) + vs1[H4(0)] + sig0_sha256(vs2[H4(0)]) + vd[H4(3)];
158
+ vd[H4(3)] = res[3];
159
+ vd[H4(2)] = res[2];
160
+ vd[H4(1)] = res[1];
161
+ vd[H4(0)] = res[0];
162
+}
163
+
164
+static inline void vsha2ms_e64(uint64_t *vd, uint64_t *vs1, uint64_t *vs2)
165
+{
166
+ uint64_t res[4];
167
+ res[0] = sig1_sha512(vs1[2]) + vs2[1] + sig0_sha512(vd[1]) + vd[0];
168
+ res[1] = sig1_sha512(vs1[3]) + vs2[2] + sig0_sha512(vd[2]) + vd[1];
169
+ res[2] = sig1_sha512(res[0]) + vs2[3] + sig0_sha512(vd[3]) + vd[2];
170
+ res[3] = sig1_sha512(res[1]) + vs1[0] + sig0_sha512(vs2[0]) + vd[3];
171
+ vd[3] = res[3];
172
+ vd[2] = res[2];
173
+ vd[1] = res[1];
174
+ vd[0] = res[0];
175
+}
176
+
177
+void HELPER(vsha2ms_vv)(void *vd, void *vs1, void *vs2, CPURISCVState *env,
178
+ uint32_t desc)
179
+{
180
+ uint32_t sew = FIELD_EX64(env->vtype, VTYPE, VSEW);
181
+ uint32_t esz = sew == MO_32 ? 4 : 8;
182
+ uint32_t total_elems;
183
+ uint32_t vta = vext_vta(desc);
184
+
185
+ for (uint32_t i = env->vstart / 4; i < env->vl / 4; i++) {
186
+ if (sew == MO_32) {
187
+ vsha2ms_e32(((uint32_t *)vd) + i * 4, ((uint32_t *)vs1) + i * 4,
188
+ ((uint32_t *)vs2) + i * 4);
189
+ } else {
190
+ /* If not 32 then SEW should be 64 */
191
+ vsha2ms_e64(((uint64_t *)vd) + i * 4, ((uint64_t *)vs1) + i * 4,
192
+ ((uint64_t *)vs2) + i * 4);
193
+ }
194
+ }
195
+ /* set tail elements to 1s */
196
+ total_elems = vext_get_total_elems(env, desc, esz);
197
+ vext_set_elems_1s(vd, vta, env->vl * esz, total_elems * esz);
198
+ env->vstart = 0;
199
+}
200
+
201
+static inline uint64_t sum0_64(uint64_t x)
202
+{
203
+ return ror64(x, 28) ^ ror64(x, 34) ^ ror64(x, 39);
204
+}
205
+
206
+static inline uint32_t sum0_32(uint32_t x)
207
+{
208
+ return ror32(x, 2) ^ ror32(x, 13) ^ ror32(x, 22);
209
+}
210
+
211
+static inline uint64_t sum1_64(uint64_t x)
212
+{
213
+ return ror64(x, 14) ^ ror64(x, 18) ^ ror64(x, 41);
214
+}
215
+
216
+static inline uint32_t sum1_32(uint32_t x)
217
+{
218
+ return ror32(x, 6) ^ ror32(x, 11) ^ ror32(x, 25);
219
+}
220
+
221
+#define ch(x, y, z) ((x & y) ^ ((~x) & z))
222
+
223
+#define maj(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
224
+
225
+static void vsha2c_64(uint64_t *vs2, uint64_t *vd, uint64_t *vs1)
226
+{
227
+ uint64_t a = vs2[3], b = vs2[2], e = vs2[1], f = vs2[0];
228
+ uint64_t c = vd[3], d = vd[2], g = vd[1], h = vd[0];
229
+ uint64_t W0 = vs1[0], W1 = vs1[1];
230
+ uint64_t T1 = h + sum1_64(e) + ch(e, f, g) + W0;
231
+ uint64_t T2 = sum0_64(a) + maj(a, b, c);
232
+
233
+ h = g;
234
+ g = f;
235
+ f = e;
236
+ e = d + T1;
237
+ d = c;
238
+ c = b;
239
+ b = a;
240
+ a = T1 + T2;
241
+
242
+ T1 = h + sum1_64(e) + ch(e, f, g) + W1;
243
+ T2 = sum0_64(a) + maj(a, b, c);
244
+ h = g;
245
+ g = f;
246
+ f = e;
247
+ e = d + T1;
248
+ d = c;
249
+ c = b;
250
+ b = a;
251
+ a = T1 + T2;
252
+
253
+ vd[0] = f;
254
+ vd[1] = e;
255
+ vd[2] = b;
256
+ vd[3] = a;
257
+}
258
+
259
+static void vsha2c_32(uint32_t *vs2, uint32_t *vd, uint32_t *vs1)
260
+{
261
+ uint32_t a = vs2[H4(3)], b = vs2[H4(2)], e = vs2[H4(1)], f = vs2[H4(0)];
262
+ uint32_t c = vd[H4(3)], d = vd[H4(2)], g = vd[H4(1)], h = vd[H4(0)];
263
+ uint32_t W0 = vs1[H4(0)], W1 = vs1[H4(1)];
264
+ uint32_t T1 = h + sum1_32(e) + ch(e, f, g) + W0;
265
+ uint32_t T2 = sum0_32(a) + maj(a, b, c);
266
+
267
+ h = g;
268
+ g = f;
269
+ f = e;
270
+ e = d + T1;
271
+ d = c;
272
+ c = b;
273
+ b = a;
274
+ a = T1 + T2;
275
+
276
+ T1 = h + sum1_32(e) + ch(e, f, g) + W1;
277
+ T2 = sum0_32(a) + maj(a, b, c);
278
+ h = g;
279
+ g = f;
280
+ f = e;
281
+ e = d + T1;
282
+ d = c;
283
+ c = b;
284
+ b = a;
285
+ a = T1 + T2;
286
+
287
+ vd[H4(0)] = f;
288
+ vd[H4(1)] = e;
289
+ vd[H4(2)] = b;
290
+ vd[H4(3)] = a;
291
+}
292
+
293
+void HELPER(vsha2ch32_vv)(void *vd, void *vs1, void *vs2, CPURISCVState *env,
294
+ uint32_t desc)
295
+{
296
+ const uint32_t esz = 4;
297
+ uint32_t total_elems;
298
+ uint32_t vta = vext_vta(desc);
299
+
300
+ for (uint32_t i = env->vstart / 4; i < env->vl / 4; i++) {
301
+ vsha2c_32(((uint32_t *)vs2) + 4 * i, ((uint32_t *)vd) + 4 * i,
302
+ ((uint32_t *)vs1) + 4 * i + 2);
303
+ }
304
+
305
+ /* set tail elements to 1s */
306
+ total_elems = vext_get_total_elems(env, desc, esz);
307
+ vext_set_elems_1s(vd, vta, env->vl * esz, total_elems * esz);
308
+ env->vstart = 0;
309
+}
310
+
311
+void HELPER(vsha2ch64_vv)(void *vd, void *vs1, void *vs2, CPURISCVState *env,
312
+ uint32_t desc)
313
+{
314
+ const uint32_t esz = 8;
315
+ uint32_t total_elems;
316
+ uint32_t vta = vext_vta(desc);
317
+
318
+ for (uint32_t i = env->vstart / 4; i < env->vl / 4; i++) {
319
+ vsha2c_64(((uint64_t *)vs2) + 4 * i, ((uint64_t *)vd) + 4 * i,
320
+ ((uint64_t *)vs1) + 4 * i + 2);
321
+ }
322
+
323
+ /* set tail elements to 1s */
324
+ total_elems = vext_get_total_elems(env, desc, esz);
325
+ vext_set_elems_1s(vd, vta, env->vl * esz, total_elems * esz);
326
+ env->vstart = 0;
327
+}
328
+
329
+void HELPER(vsha2cl32_vv)(void *vd, void *vs1, void *vs2, CPURISCVState *env,
330
+ uint32_t desc)
331
+{
332
+ const uint32_t esz = 4;
333
+ uint32_t total_elems;
334
+ uint32_t vta = vext_vta(desc);
335
+
336
+ for (uint32_t i = env->vstart / 4; i < env->vl / 4; i++) {
337
+ vsha2c_32(((uint32_t *)vs2) + 4 * i, ((uint32_t *)vd) + 4 * i,
338
+ (((uint32_t *)vs1) + 4 * i));
339
+ }
340
+
341
+ /* set tail elements to 1s */
342
+ total_elems = vext_get_total_elems(env, desc, esz);
343
+ vext_set_elems_1s(vd, vta, env->vl * esz, total_elems * esz);
344
+ env->vstart = 0;
345
+}
346
+
347
+void HELPER(vsha2cl64_vv)(void *vd, void *vs1, void *vs2, CPURISCVState *env,
348
+ uint32_t desc)
349
+{
350
+ uint32_t esz = 8;
351
+ uint32_t total_elems;
352
+ uint32_t vta = vext_vta(desc);
353
+
354
+ for (uint32_t i = env->vstart / 4; i < env->vl / 4; i++) {
355
+ vsha2c_64(((uint64_t *)vs2) + 4 * i, ((uint64_t *)vd) + 4 * i,
356
+ (((uint64_t *)vs1) + 4 * i));
357
+ }
358
+
359
+ /* set tail elements to 1s */
360
+ total_elems = vext_get_total_elems(env, desc, esz);
361
+ vext_set_elems_1s(vd, vta, env->vl * esz, total_elems * esz);
362
+ env->vstart = 0;
363
+}
364
diff --git a/target/riscv/insn_trans/trans_rvvk.c.inc b/target/riscv/insn_trans/trans_rvvk.c.inc
365
index XXXXXXX..XXXXXXX 100644
366
--- a/target/riscv/insn_trans/trans_rvvk.c.inc
367
+++ b/target/riscv/insn_trans/trans_rvvk.c.inc
368
@@ -XXX,XX +XXX,XX @@ static bool vaeskf2_check(DisasContext *s, arg_vaeskf2_vi *a)
369
370
GEN_VI_UNMASKED_TRANS(vaeskf1_vi, vaeskf1_check, ZVKNED_EGS)
371
GEN_VI_UNMASKED_TRANS(vaeskf2_vi, vaeskf2_check, ZVKNED_EGS)
372
+
373
+/*
374
+ * Zvknh
375
+ */
376
+
377
+#define ZVKNH_EGS 4
378
+
379
+#define GEN_VV_UNMASKED_TRANS(NAME, CHECK, EGS) \
380
+ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
381
+ { \
382
+ if (CHECK(s, a)) { \
383
+ uint32_t data = 0; \
384
+ TCGLabel *over = gen_new_label(); \
385
+ TCGv_i32 egs; \
386
+ \
387
+ if (!s->vstart_eq_zero || !s->vl_eq_vlmax) { \
388
+ /* save opcode for unwinding in case we throw an exception */ \
389
+ decode_save_opc(s); \
390
+ egs = tcg_constant_i32(EGS); \
391
+ gen_helper_egs_check(egs, cpu_env); \
392
+ tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); \
393
+ } \
394
+ \
395
+ data = FIELD_DP32(data, VDATA, VM, a->vm); \
396
+ data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \
397
+ data = FIELD_DP32(data, VDATA, VTA, s->vta); \
398
+ data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s); \
399
+ data = FIELD_DP32(data, VDATA, VMA, s->vma); \
400
+ \
401
+ tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, a->rs1), \
402
+ vreg_ofs(s, a->rs2), cpu_env, \
403
+ s->cfg_ptr->vlen / 8, s->cfg_ptr->vlen / 8, \
404
+ data, gen_helper_##NAME); \
405
+ \
406
+ mark_vs_dirty(s); \
407
+ gen_set_label(over); \
408
+ return true; \
409
+ } \
410
+ return false; \
411
+ }
412
+
413
+static bool vsha_check_sew(DisasContext *s)
414
+{
415
+ return (s->cfg_ptr->ext_zvknha == true && s->sew == MO_32) ||
416
+ (s->cfg_ptr->ext_zvknhb == true &&
417
+ (s->sew == MO_32 || s->sew == MO_64));
418
+}
419
+
420
+static bool vsha_check(DisasContext *s, arg_rmrr *a)
421
+{
422
+ int egw_bytes = ZVKNH_EGS << s->sew;
423
+ int mult = 1 << MAX(s->lmul, 0);
424
+ return opivv_check(s, a) &&
425
+ vsha_check_sew(s) &&
426
+ MAXSZ(s) >= egw_bytes &&
427
+ !is_overlapped(a->rd, mult, a->rs1, mult) &&
428
+ !is_overlapped(a->rd, mult, a->rs2, mult) &&
429
+ s->lmul >= 0;
430
+}
431
+
432
+GEN_VV_UNMASKED_TRANS(vsha2ms_vv, vsha_check, ZVKNH_EGS)
433
+
434
+static bool trans_vsha2cl_vv(DisasContext *s, arg_rmrr *a)
435
+{
436
+ if (vsha_check(s, a)) {
437
+ uint32_t data = 0;
438
+ TCGLabel *over = gen_new_label();
439
+ TCGv_i32 egs;
440
+
441
+ if (!s->vstart_eq_zero || !s->vl_eq_vlmax) {
442
+ /* save opcode for unwinding in case we throw an exception */
443
+ decode_save_opc(s);
444
+ egs = tcg_constant_i32(ZVKNH_EGS);
445
+ gen_helper_egs_check(egs, cpu_env);
446
+ tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
447
+ }
448
+
449
+ data = FIELD_DP32(data, VDATA, VM, a->vm);
450
+ data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
451
+ data = FIELD_DP32(data, VDATA, VTA, s->vta);
452
+ data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);
453
+ data = FIELD_DP32(data, VDATA, VMA, s->vma);
454
+
455
+ tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, a->rs1),
456
+ vreg_ofs(s, a->rs2), cpu_env, s->cfg_ptr->vlen / 8,
457
+ s->cfg_ptr->vlen / 8, data,
458
+ s->sew == MO_32 ?
459
+ gen_helper_vsha2cl32_vv : gen_helper_vsha2cl64_vv);
460
+
461
+ mark_vs_dirty(s);
462
+ gen_set_label(over);
463
+ return true;
464
+ }
465
+ return false;
466
+}
467
+
468
+static bool trans_vsha2ch_vv(DisasContext *s, arg_rmrr *a)
469
+{
470
+ if (vsha_check(s, a)) {
471
+ uint32_t data = 0;
472
+ TCGLabel *over = gen_new_label();
473
+ TCGv_i32 egs;
474
+
475
+ if (!s->vstart_eq_zero || !s->vl_eq_vlmax) {
476
+ /* save opcode for unwinding in case we throw an exception */
477
+ decode_save_opc(s);
478
+ egs = tcg_constant_i32(ZVKNH_EGS);
479
+ gen_helper_egs_check(egs, cpu_env);
480
+ tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
481
+ }
482
+
483
+ data = FIELD_DP32(data, VDATA, VM, a->vm);
484
+ data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
485
+ data = FIELD_DP32(data, VDATA, VTA, s->vta);
486
+ data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);
487
+ data = FIELD_DP32(data, VDATA, VMA, s->vma);
488
+
489
+ tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, a->rs1),
490
+ vreg_ofs(s, a->rs2), cpu_env, s->cfg_ptr->vlen / 8,
491
+ s->cfg_ptr->vlen / 8, data,
492
+ s->sew == MO_32 ?
493
+ gen_helper_vsha2ch32_vv : gen_helper_vsha2ch64_vv);
494
+
495
+ mark_vs_dirty(s);
496
+ gen_set_label(over);
497
+ return true;
498
+ }
499
+ return false;
500
+}
501
--
502
2.41.0
diff view generated by jsdifflib
New patch
1
1
From: Lawrence Hunter <lawrence.hunter@codethink.co.uk>
2
3
This commit adds support for the Zvksh vector-crypto extension, which
4
consists of the following instructions:
5
6
* vsm3me.vv
7
* vsm3c.vi
8
9
Translation functions are defined in
10
`target/riscv/insn_trans/trans_rvvk.c.inc` and helpers are defined in
11
`target/riscv/vcrypto_helper.c`.
12
13
Co-authored-by: Kiran Ostrolenk <kiran.ostrolenk@codethink.co.uk>
14
[max.chou@sifive.com: Replaced vstart checking by TCG op]
15
Signed-off-by: Kiran Ostrolenk <kiran.ostrolenk@codethink.co.uk>
16
Signed-off-by: Lawrence Hunter <lawrence.hunter@codethink.co.uk>
17
Signed-off-by: Max Chou <max.chou@sifive.com>
18
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
19
[max.chou@sifive.com: Exposed x-zvksh property]
20
Message-ID: <20230711165917.2629866-12-max.chou@sifive.com>
21
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
22
---
23
target/riscv/cpu_cfg.h | 1 +
24
target/riscv/helper.h | 3 +
25
target/riscv/insn32.decode | 4 +
26
target/riscv/cpu.c | 6 +-
27
target/riscv/vcrypto_helper.c | 134 +++++++++++++++++++++++
28
target/riscv/insn_trans/trans_rvvk.c.inc | 31 ++++++
29
6 files changed, 177 insertions(+), 2 deletions(-)
30
31
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
32
index XXXXXXX..XXXXXXX 100644
33
--- a/target/riscv/cpu_cfg.h
34
+++ b/target/riscv/cpu_cfg.h
35
@@ -XXX,XX +XXX,XX @@ struct RISCVCPUConfig {
36
bool ext_zvkned;
37
bool ext_zvknha;
38
bool ext_zvknhb;
39
+ bool ext_zvksh;
40
bool ext_zmmul;
41
bool ext_zvfbfmin;
42
bool ext_zvfbfwma;
43
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
44
index XXXXXXX..XXXXXXX 100644
45
--- a/target/riscv/helper.h
46
+++ b/target/riscv/helper.h
47
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_5(vsha2ch32_vv, void, ptr, ptr, ptr, env, i32)
48
DEF_HELPER_5(vsha2ch64_vv, void, ptr, ptr, ptr, env, i32)
49
DEF_HELPER_5(vsha2cl32_vv, void, ptr, ptr, ptr, env, i32)
50
DEF_HELPER_5(vsha2cl64_vv, void, ptr, ptr, ptr, env, i32)
51
+
52
+DEF_HELPER_5(vsm3me_vv, void, ptr, ptr, ptr, env, i32)
53
+DEF_HELPER_5(vsm3c_vi, void, ptr, ptr, i32, env, i32)
54
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
55
index XXXXXXX..XXXXXXX 100644
56
--- a/target/riscv/insn32.decode
57
+++ b/target/riscv/insn32.decode
58
@@ -XXX,XX +XXX,XX @@ vaeskf2_vi 101010 1 ..... ..... 010 ..... 1110111 @r_vm_1
59
vsha2ms_vv 101101 1 ..... ..... 010 ..... 1110111 @r_vm_1
60
vsha2ch_vv 101110 1 ..... ..... 010 ..... 1110111 @r_vm_1
61
vsha2cl_vv 101111 1 ..... ..... 010 ..... 1110111 @r_vm_1
62
+
63
+# *** Zvksh vector crypto extension ***
64
+vsm3me_vv 100000 1 ..... ..... 010 ..... 1110111 @r_vm_1
65
+vsm3c_vi 101011 1 ..... ..... 010 ..... 1110111 @r_vm_1
66
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/target/riscv/cpu.c
69
+++ b/target/riscv/cpu.c
70
@@ -XXX,XX +XXX,XX @@ static const struct isa_ext_data isa_edata_arr[] = {
71
ISA_EXT_DATA_ENTRY(zvkned, PRIV_VERSION_1_12_0, ext_zvkned),
72
ISA_EXT_DATA_ENTRY(zvknha, PRIV_VERSION_1_12_0, ext_zvknha),
73
ISA_EXT_DATA_ENTRY(zvknhb, PRIV_VERSION_1_12_0, ext_zvknhb),
74
+ ISA_EXT_DATA_ENTRY(zvksh, PRIV_VERSION_1_12_0, ext_zvksh),
75
ISA_EXT_DATA_ENTRY(zhinx, PRIV_VERSION_1_12_0, ext_zhinx),
76
ISA_EXT_DATA_ENTRY(zhinxmin, PRIV_VERSION_1_12_0, ext_zhinxmin),
77
ISA_EXT_DATA_ENTRY(smaia, PRIV_VERSION_1_12_0, ext_smaia),
78
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
79
* In principle Zve*x would also suffice here, were they supported
80
* in qemu
81
*/
82
- if ((cpu->cfg.ext_zvbb || cpu->cfg.ext_zvkned || cpu->cfg.ext_zvknha) &&
83
- !cpu->cfg.ext_zve32f) {
84
+ if ((cpu->cfg.ext_zvbb || cpu->cfg.ext_zvkned || cpu->cfg.ext_zvknha ||
85
+ cpu->cfg.ext_zvksh) && !cpu->cfg.ext_zve32f) {
86
error_setg(errp,
87
"Vector crypto extensions require V or Zve* extensions");
88
return;
89
@@ -XXX,XX +XXX,XX @@ static Property riscv_cpu_extensions[] = {
90
DEFINE_PROP_BOOL("x-zvkned", RISCVCPU, cfg.ext_zvkned, false),
91
DEFINE_PROP_BOOL("x-zvknha", RISCVCPU, cfg.ext_zvknha, false),
92
DEFINE_PROP_BOOL("x-zvknhb", RISCVCPU, cfg.ext_zvknhb, false),
93
+ DEFINE_PROP_BOOL("x-zvksh", RISCVCPU, cfg.ext_zvksh, false),
94
95
DEFINE_PROP_END_OF_LIST(),
96
};
97
diff --git a/target/riscv/vcrypto_helper.c b/target/riscv/vcrypto_helper.c
98
index XXXXXXX..XXXXXXX 100644
99
--- a/target/riscv/vcrypto_helper.c
100
+++ b/target/riscv/vcrypto_helper.c
101
@@ -XXX,XX +XXX,XX @@ void HELPER(vsha2cl64_vv)(void *vd, void *vs1, void *vs2, CPURISCVState *env,
102
vext_set_elems_1s(vd, vta, env->vl * esz, total_elems * esz);
103
env->vstart = 0;
104
}
105
+
106
+static inline uint32_t p1(uint32_t x)
107
+{
108
+ return x ^ rol32(x, 15) ^ rol32(x, 23);
109
+}
110
+
111
+static inline uint32_t zvksh_w(uint32_t m16, uint32_t m9, uint32_t m3,
112
+ uint32_t m13, uint32_t m6)
113
+{
114
+ return p1(m16 ^ m9 ^ rol32(m3, 15)) ^ rol32(m13, 7) ^ m6;
115
+}
116
+
117
+void HELPER(vsm3me_vv)(void *vd_vptr, void *vs1_vptr, void *vs2_vptr,
118
+ CPURISCVState *env, uint32_t desc)
119
+{
120
+ uint32_t esz = memop_size(FIELD_EX64(env->vtype, VTYPE, VSEW));
121
+ uint32_t total_elems = vext_get_total_elems(env, desc, esz);
122
+ uint32_t vta = vext_vta(desc);
123
+ uint32_t *vd = vd_vptr;
124
+ uint32_t *vs1 = vs1_vptr;
125
+ uint32_t *vs2 = vs2_vptr;
126
+
127
+ for (int i = env->vstart / 8; i < env->vl / 8; i++) {
128
+ uint32_t w[24];
129
+ for (int j = 0; j < 8; j++) {
130
+ w[j] = bswap32(vs1[H4((i * 8) + j)]);
131
+ w[j + 8] = bswap32(vs2[H4((i * 8) + j)]);
132
+ }
133
+ for (int j = 0; j < 8; j++) {
134
+ w[j + 16] =
135
+ zvksh_w(w[j], w[j + 7], w[j + 13], w[j + 3], w[j + 10]);
136
+ }
137
+ for (int j = 0; j < 8; j++) {
138
+ vd[(i * 8) + j] = bswap32(w[H4(j + 16)]);
139
+ }
140
+ }
141
+ vext_set_elems_1s(vd_vptr, vta, env->vl * esz, total_elems * esz);
142
+ env->vstart = 0;
143
+}
144
+
145
+static inline uint32_t ff1(uint32_t x, uint32_t y, uint32_t z)
146
+{
147
+ return x ^ y ^ z;
148
+}
149
+
150
+static inline uint32_t ff2(uint32_t x, uint32_t y, uint32_t z)
151
+{
152
+ return (x & y) | (x & z) | (y & z);
153
+}
154
+
155
+static inline uint32_t ff_j(uint32_t x, uint32_t y, uint32_t z, uint32_t j)
156
+{
157
+ return (j <= 15) ? ff1(x, y, z) : ff2(x, y, z);
158
+}
159
+
160
+static inline uint32_t gg1(uint32_t x, uint32_t y, uint32_t z)
161
+{
162
+ return x ^ y ^ z;
163
+}
164
+
165
+static inline uint32_t gg2(uint32_t x, uint32_t y, uint32_t z)
166
+{
167
+ return (x & y) | (~x & z);
168
+}
169
+
170
+static inline uint32_t gg_j(uint32_t x, uint32_t y, uint32_t z, uint32_t j)
171
+{
172
+ return (j <= 15) ? gg1(x, y, z) : gg2(x, y, z);
173
+}
174
+
175
+static inline uint32_t t_j(uint32_t j)
176
+{
177
+ return (j <= 15) ? 0x79cc4519 : 0x7a879d8a;
178
+}
179
+
180
+static inline uint32_t p_0(uint32_t x)
181
+{
182
+ return x ^ rol32(x, 9) ^ rol32(x, 17);
183
+}
184
+
185
+static void sm3c(uint32_t *vd, uint32_t *vs1, uint32_t *vs2, uint32_t uimm)
186
+{
187
+ uint32_t x0, x1;
188
+ uint32_t j;
189
+ uint32_t ss1, ss2, tt1, tt2;
190
+ x0 = vs2[0] ^ vs2[4];
191
+ x1 = vs2[1] ^ vs2[5];
192
+ j = 2 * uimm;
193
+ ss1 = rol32(rol32(vs1[0], 12) + vs1[4] + rol32(t_j(j), j % 32), 7);
194
+ ss2 = ss1 ^ rol32(vs1[0], 12);
195
+ tt1 = ff_j(vs1[0], vs1[1], vs1[2], j) + vs1[3] + ss2 + x0;
196
+ tt2 = gg_j(vs1[4], vs1[5], vs1[6], j) + vs1[7] + ss1 + vs2[0];
197
+ vs1[3] = vs1[2];
198
+ vd[3] = rol32(vs1[1], 9);
199
+ vs1[1] = vs1[0];
200
+ vd[1] = tt1;
201
+ vs1[7] = vs1[6];
202
+ vd[7] = rol32(vs1[5], 19);
203
+ vs1[5] = vs1[4];
204
+ vd[5] = p_0(tt2);
205
+ j = 2 * uimm + 1;
206
+ ss1 = rol32(rol32(vd[1], 12) + vd[5] + rol32(t_j(j), j % 32), 7);
207
+ ss2 = ss1 ^ rol32(vd[1], 12);
208
+ tt1 = ff_j(vd[1], vs1[1], vd[3], j) + vs1[3] + ss2 + x1;
209
+ tt2 = gg_j(vd[5], vs1[5], vd[7], j) + vs1[7] + ss1 + vs2[1];
210
+ vd[2] = rol32(vs1[1], 9);
211
+ vd[0] = tt1;
212
+ vd[6] = rol32(vs1[5], 19);
213
+ vd[4] = p_0(tt2);
214
+}
215
+
216
+void HELPER(vsm3c_vi)(void *vd_vptr, void *vs2_vptr, uint32_t uimm,
217
+ CPURISCVState *env, uint32_t desc)
218
+{
219
+ uint32_t esz = memop_size(FIELD_EX64(env->vtype, VTYPE, VSEW));
220
+ uint32_t total_elems = vext_get_total_elems(env, desc, esz);
221
+ uint32_t vta = vext_vta(desc);
222
+ uint32_t *vd = vd_vptr;
223
+ uint32_t *vs2 = vs2_vptr;
224
+ uint32_t v1[8], v2[8], v3[8];
225
+
226
+ for (int i = env->vstart / 8; i < env->vl / 8; i++) {
227
+ for (int k = 0; k < 8; k++) {
228
+ v2[k] = bswap32(vd[H4(i * 8 + k)]);
229
+ v3[k] = bswap32(vs2[H4(i * 8 + k)]);
230
+ }
231
+ sm3c(v1, v2, v3, uimm);
232
+ for (int k = 0; k < 8; k++) {
233
+ vd[i * 8 + k] = bswap32(v1[H4(k)]);
234
+ }
235
+ }
236
+ vext_set_elems_1s(vd_vptr, vta, env->vl * esz, total_elems * esz);
237
+ env->vstart = 0;
238
+}
239
diff --git a/target/riscv/insn_trans/trans_rvvk.c.inc b/target/riscv/insn_trans/trans_rvvk.c.inc
240
index XXXXXXX..XXXXXXX 100644
241
--- a/target/riscv/insn_trans/trans_rvvk.c.inc
242
+++ b/target/riscv/insn_trans/trans_rvvk.c.inc
243
@@ -XXX,XX +XXX,XX @@ static bool trans_vsha2ch_vv(DisasContext *s, arg_rmrr *a)
244
}
245
return false;
246
}
247
+
248
+/*
249
+ * Zvksh
250
+ */
251
+
252
+#define ZVKSH_EGS 8
253
+
254
+static inline bool vsm3_check(DisasContext *s, arg_rmrr *a)
255
+{
256
+ int egw_bytes = ZVKSH_EGS << s->sew;
257
+ int mult = 1 << MAX(s->lmul, 0);
258
+ return s->cfg_ptr->ext_zvksh == true &&
259
+ require_rvv(s) &&
260
+ vext_check_isa_ill(s) &&
261
+ !is_overlapped(a->rd, mult, a->rs2, mult) &&
262
+ MAXSZ(s) >= egw_bytes &&
263
+ s->sew == MO_32;
264
+}
265
+
266
+static inline bool vsm3me_check(DisasContext *s, arg_rmrr *a)
267
+{
268
+ return vsm3_check(s, a) && vext_check_sss(s, a->rd, a->rs1, a->rs2, a->vm);
269
+}
270
+
271
+static inline bool vsm3c_check(DisasContext *s, arg_rmrr *a)
272
+{
273
+ return vsm3_check(s, a) && vext_check_ss(s, a->rd, a->rs2, a->vm);
274
+}
275
+
276
+GEN_VV_UNMASKED_TRANS(vsm3me_vv, vsm3me_check, ZVKSH_EGS)
277
+GEN_VI_UNMASKED_TRANS(vsm3c_vi, vsm3c_check, ZVKSH_EGS)
278
--
279
2.41.0
diff view generated by jsdifflib
New patch
1
1
From: Nazar Kazakov <nazar.kazakov@codethink.co.uk>
2
3
This commit adds support for the Zvkg vector-crypto extension, which
4
consists of the following instructions:
5
6
* vgmul.vv
7
* vghsh.vv
8
9
Translation functions are defined in
10
`target/riscv/insn_trans/trans_rvvk.c.inc` and helpers are defined in
11
`target/riscv/vcrypto_helper.c`.
12
13
Co-authored-by: Lawrence Hunter <lawrence.hunter@codethink.co.uk>
14
[max.chou@sifive.com: Replaced vstart checking by TCG op]
15
Signed-off-by: Lawrence Hunter <lawrence.hunter@codethink.co.uk>
16
Signed-off-by: Nazar Kazakov <nazar.kazakov@codethink.co.uk>
17
Signed-off-by: Max Chou <max.chou@sifive.com>
18
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
19
[max.chou@sifive.com: Exposed x-zvkg property]
20
[max.chou@sifive.com: Replaced uint by int for cross win32 build]
21
Message-ID: <20230711165917.2629866-13-max.chou@sifive.com>
22
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
23
---
24
target/riscv/cpu_cfg.h | 1 +
25
target/riscv/helper.h | 3 +
26
target/riscv/insn32.decode | 4 ++
27
target/riscv/cpu.c | 6 +-
28
target/riscv/vcrypto_helper.c | 72 ++++++++++++++++++++++++
29
target/riscv/insn_trans/trans_rvvk.c.inc | 30 ++++++++++
30
6 files changed, 114 insertions(+), 2 deletions(-)
31
32
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/riscv/cpu_cfg.h
35
+++ b/target/riscv/cpu_cfg.h
36
@@ -XXX,XX +XXX,XX @@ struct RISCVCPUConfig {
37
bool ext_zve64d;
38
bool ext_zvbb;
39
bool ext_zvbc;
40
+ bool ext_zvkg;
41
bool ext_zvkned;
42
bool ext_zvknha;
43
bool ext_zvknhb;
44
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
45
index XXXXXXX..XXXXXXX 100644
46
--- a/target/riscv/helper.h
47
+++ b/target/riscv/helper.h
48
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_5(vsha2cl64_vv, void, ptr, ptr, ptr, env, i32)
49
50
DEF_HELPER_5(vsm3me_vv, void, ptr, ptr, ptr, env, i32)
51
DEF_HELPER_5(vsm3c_vi, void, ptr, ptr, i32, env, i32)
52
+
53
+DEF_HELPER_5(vghsh_vv, void, ptr, ptr, ptr, env, i32)
54
+DEF_HELPER_4(vgmul_vv, void, ptr, ptr, env, i32)
55
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
56
index XXXXXXX..XXXXXXX 100644
57
--- a/target/riscv/insn32.decode
58
+++ b/target/riscv/insn32.decode
59
@@ -XXX,XX +XXX,XX @@ vsha2cl_vv 101111 1 ..... ..... 010 ..... 1110111 @r_vm_1
60
# *** Zvksh vector crypto extension ***
61
vsm3me_vv 100000 1 ..... ..... 010 ..... 1110111 @r_vm_1
62
vsm3c_vi 101011 1 ..... ..... 010 ..... 1110111 @r_vm_1
63
+
64
+# *** Zvkg vector crypto extension ***
65
+vghsh_vv 101100 1 ..... ..... 010 ..... 1110111 @r_vm_1
66
+vgmul_vv 101000 1 ..... 10001 010 ..... 1110111 @r2_vm_1
67
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
68
index XXXXXXX..XXXXXXX 100644
69
--- a/target/riscv/cpu.c
70
+++ b/target/riscv/cpu.c
71
@@ -XXX,XX +XXX,XX @@ static const struct isa_ext_data isa_edata_arr[] = {
72
ISA_EXT_DATA_ENTRY(zvfbfwma, PRIV_VERSION_1_12_0, ext_zvfbfwma),
73
ISA_EXT_DATA_ENTRY(zvfh, PRIV_VERSION_1_12_0, ext_zvfh),
74
ISA_EXT_DATA_ENTRY(zvfhmin, PRIV_VERSION_1_12_0, ext_zvfhmin),
75
+ ISA_EXT_DATA_ENTRY(zvkg, PRIV_VERSION_1_12_0, ext_zvkg),
76
ISA_EXT_DATA_ENTRY(zvkned, PRIV_VERSION_1_12_0, ext_zvkned),
77
ISA_EXT_DATA_ENTRY(zvknha, PRIV_VERSION_1_12_0, ext_zvknha),
78
ISA_EXT_DATA_ENTRY(zvknhb, PRIV_VERSION_1_12_0, ext_zvknhb),
79
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
80
* In principle Zve*x would also suffice here, were they supported
81
* in qemu
82
*/
83
- if ((cpu->cfg.ext_zvbb || cpu->cfg.ext_zvkned || cpu->cfg.ext_zvknha ||
84
- cpu->cfg.ext_zvksh) && !cpu->cfg.ext_zve32f) {
85
+ if ((cpu->cfg.ext_zvbb || cpu->cfg.ext_zvkg || cpu->cfg.ext_zvkned ||
86
+ cpu->cfg.ext_zvknha || cpu->cfg.ext_zvksh) && !cpu->cfg.ext_zve32f) {
87
error_setg(errp,
88
"Vector crypto extensions require V or Zve* extensions");
89
return;
90
@@ -XXX,XX +XXX,XX @@ static Property riscv_cpu_extensions[] = {
91
/* Vector cryptography extensions */
92
DEFINE_PROP_BOOL("x-zvbb", RISCVCPU, cfg.ext_zvbb, false),
93
DEFINE_PROP_BOOL("x-zvbc", RISCVCPU, cfg.ext_zvbc, false),
94
+ DEFINE_PROP_BOOL("x-zvkg", RISCVCPU, cfg.ext_zvkg, false),
95
DEFINE_PROP_BOOL("x-zvkned", RISCVCPU, cfg.ext_zvkned, false),
96
DEFINE_PROP_BOOL("x-zvknha", RISCVCPU, cfg.ext_zvknha, false),
97
DEFINE_PROP_BOOL("x-zvknhb", RISCVCPU, cfg.ext_zvknhb, false),
98
diff --git a/target/riscv/vcrypto_helper.c b/target/riscv/vcrypto_helper.c
99
index XXXXXXX..XXXXXXX 100644
100
--- a/target/riscv/vcrypto_helper.c
101
+++ b/target/riscv/vcrypto_helper.c
102
@@ -XXX,XX +XXX,XX @@ void HELPER(vsm3c_vi)(void *vd_vptr, void *vs2_vptr, uint32_t uimm,
103
vext_set_elems_1s(vd_vptr, vta, env->vl * esz, total_elems * esz);
104
env->vstart = 0;
105
}
106
+
107
+void HELPER(vghsh_vv)(void *vd_vptr, void *vs1_vptr, void *vs2_vptr,
108
+ CPURISCVState *env, uint32_t desc)
109
+{
110
+ uint64_t *vd = vd_vptr;
111
+ uint64_t *vs1 = vs1_vptr;
112
+ uint64_t *vs2 = vs2_vptr;
113
+ uint32_t vta = vext_vta(desc);
114
+ uint32_t total_elems = vext_get_total_elems(env, desc, 4);
115
+
116
+ for (uint32_t i = env->vstart / 4; i < env->vl / 4; i++) {
117
+ uint64_t Y[2] = {vd[i * 2 + 0], vd[i * 2 + 1]};
118
+ uint64_t H[2] = {brev8(vs2[i * 2 + 0]), brev8(vs2[i * 2 + 1])};
119
+ uint64_t X[2] = {vs1[i * 2 + 0], vs1[i * 2 + 1]};
120
+ uint64_t Z[2] = {0, 0};
121
+
122
+ uint64_t S[2] = {brev8(Y[0] ^ X[0]), brev8(Y[1] ^ X[1])};
123
+
124
+ for (int j = 0; j < 128; j++) {
125
+ if ((S[j / 64] >> (j % 64)) & 1) {
126
+ Z[0] ^= H[0];
127
+ Z[1] ^= H[1];
128
+ }
129
+ bool reduce = ((H[1] >> 63) & 1);
130
+ H[1] = H[1] << 1 | H[0] >> 63;
131
+ H[0] = H[0] << 1;
132
+ if (reduce) {
133
+ H[0] ^= 0x87;
134
+ }
135
+ }
136
+
137
+ vd[i * 2 + 0] = brev8(Z[0]);
138
+ vd[i * 2 + 1] = brev8(Z[1]);
139
+ }
140
+ /* set tail elements to 1s */
141
+ vext_set_elems_1s(vd, vta, env->vl * 4, total_elems * 4);
142
+ env->vstart = 0;
143
+}
144
+
145
+void HELPER(vgmul_vv)(void *vd_vptr, void *vs2_vptr, CPURISCVState *env,
146
+ uint32_t desc)
147
+{
148
+ uint64_t *vd = vd_vptr;
149
+ uint64_t *vs2 = vs2_vptr;
150
+ uint32_t vta = vext_vta(desc);
151
+ uint32_t total_elems = vext_get_total_elems(env, desc, 4);
152
+
153
+ for (uint32_t i = env->vstart / 4; i < env->vl / 4; i++) {
154
+ uint64_t Y[2] = {brev8(vd[i * 2 + 0]), brev8(vd[i * 2 + 1])};
155
+ uint64_t H[2] = {brev8(vs2[i * 2 + 0]), brev8(vs2[i * 2 + 1])};
156
+ uint64_t Z[2] = {0, 0};
157
+
158
+ for (int j = 0; j < 128; j++) {
159
+ if ((Y[j / 64] >> (j % 64)) & 1) {
160
+ Z[0] ^= H[0];
161
+ Z[1] ^= H[1];
162
+ }
163
+ bool reduce = ((H[1] >> 63) & 1);
164
+ H[1] = H[1] << 1 | H[0] >> 63;
165
+ H[0] = H[0] << 1;
166
+ if (reduce) {
167
+ H[0] ^= 0x87;
168
+ }
169
+ }
170
+
171
+ vd[i * 2 + 0] = brev8(Z[0]);
172
+ vd[i * 2 + 1] = brev8(Z[1]);
173
+ }
174
+ /* set tail elements to 1s */
175
+ vext_set_elems_1s(vd, vta, env->vl * 4, total_elems * 4);
176
+ env->vstart = 0;
177
+}
178
diff --git a/target/riscv/insn_trans/trans_rvvk.c.inc b/target/riscv/insn_trans/trans_rvvk.c.inc
179
index XXXXXXX..XXXXXXX 100644
180
--- a/target/riscv/insn_trans/trans_rvvk.c.inc
181
+++ b/target/riscv/insn_trans/trans_rvvk.c.inc
182
@@ -XXX,XX +XXX,XX @@ static inline bool vsm3c_check(DisasContext *s, arg_rmrr *a)
183
184
GEN_VV_UNMASKED_TRANS(vsm3me_vv, vsm3me_check, ZVKSH_EGS)
185
GEN_VI_UNMASKED_TRANS(vsm3c_vi, vsm3c_check, ZVKSH_EGS)
186
+
187
+/*
188
+ * Zvkg
189
+ */
190
+
191
+#define ZVKG_EGS 4
192
+
193
+static bool vgmul_check(DisasContext *s, arg_rmr *a)
194
+{
195
+ int egw_bytes = ZVKG_EGS << s->sew;
196
+ return s->cfg_ptr->ext_zvkg == true &&
197
+ vext_check_isa_ill(s) &&
198
+ require_rvv(s) &&
199
+ MAXSZ(s) >= egw_bytes &&
200
+ vext_check_ss(s, a->rd, a->rs2, a->vm) &&
201
+ s->sew == MO_32;
202
+}
203
+
204
+GEN_V_UNMASKED_TRANS(vgmul_vv, vgmul_check, ZVKG_EGS)
205
+
206
+static bool vghsh_check(DisasContext *s, arg_rmrr *a)
207
+{
208
+ int egw_bytes = ZVKG_EGS << s->sew;
209
+ return s->cfg_ptr->ext_zvkg == true &&
210
+ opivv_check(s, a) &&
211
+ MAXSZ(s) >= egw_bytes &&
212
+ s->sew == MO_32;
213
+}
214
+
215
+GEN_VV_UNMASKED_TRANS(vghsh_vv, vghsh_check, ZVKG_EGS)
216
--
217
2.41.0
diff view generated by jsdifflib
New patch
1
From: Max Chou <max.chou@sifive.com>
1
2
3
Allows sharing of sm4_subword between different targets.
4
5
Signed-off-by: Max Chou <max.chou@sifive.com>
6
Reviewed-by: Frank Chang <frank.chang@sifive.com>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Max Chou <max.chou@sifive.com>
9
Message-ID: <20230711165917.2629866-14-max.chou@sifive.com>
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
---
12
include/crypto/sm4.h | 8 ++++++++
13
target/arm/tcg/crypto_helper.c | 10 ++--------
14
2 files changed, 10 insertions(+), 8 deletions(-)
15
16
diff --git a/include/crypto/sm4.h b/include/crypto/sm4.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/crypto/sm4.h
19
+++ b/include/crypto/sm4.h
20
@@ -XXX,XX +XXX,XX @@
21
22
extern const uint8_t sm4_sbox[256];
23
24
+static inline uint32_t sm4_subword(uint32_t word)
25
+{
26
+ return sm4_sbox[word & 0xff] |
27
+ sm4_sbox[(word >> 8) & 0xff] << 8 |
28
+ sm4_sbox[(word >> 16) & 0xff] << 16 |
29
+ sm4_sbox[(word >> 24) & 0xff] << 24;
30
+}
31
+
32
#endif
33
diff --git a/target/arm/tcg/crypto_helper.c b/target/arm/tcg/crypto_helper.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/tcg/crypto_helper.c
36
+++ b/target/arm/tcg/crypto_helper.c
37
@@ -XXX,XX +XXX,XX @@ static void do_crypto_sm4e(uint64_t *rd, uint64_t *rn, uint64_t *rm)
38
CR_ST_WORD(d, (i + 3) % 4) ^
39
CR_ST_WORD(n, i);
40
41
- t = sm4_sbox[t & 0xff] |
42
- sm4_sbox[(t >> 8) & 0xff] << 8 |
43
- sm4_sbox[(t >> 16) & 0xff] << 16 |
44
- sm4_sbox[(t >> 24) & 0xff] << 24;
45
+ t = sm4_subword(t);
46
47
CR_ST_WORD(d, i) ^= t ^ rol32(t, 2) ^ rol32(t, 10) ^ rol32(t, 18) ^
48
rol32(t, 24);
49
@@ -XXX,XX +XXX,XX @@ static void do_crypto_sm4ekey(uint64_t *rd, uint64_t *rn, uint64_t *rm)
50
CR_ST_WORD(d, (i + 3) % 4) ^
51
CR_ST_WORD(m, i);
52
53
- t = sm4_sbox[t & 0xff] |
54
- sm4_sbox[(t >> 8) & 0xff] << 8 |
55
- sm4_sbox[(t >> 16) & 0xff] << 16 |
56
- sm4_sbox[(t >> 24) & 0xff] << 24;
57
+ t = sm4_subword(t);
58
59
CR_ST_WORD(d, i) ^= t ^ rol32(t, 13) ^ rol32(t, 23);
60
}
61
--
62
2.41.0
diff view generated by jsdifflib
New patch
1
From: Max Chou <max.chou@sifive.com>
1
2
3
Adds sm4_ck constant for use in sm4 cryptography across different targets.
4
5
Signed-off-by: Max Chou <max.chou@sifive.com>
6
Reviewed-by: Frank Chang <frank.chang@sifive.com>
7
Signed-off-by: Max Chou <max.chou@sifive.com>
8
Message-ID: <20230711165917.2629866-15-max.chou@sifive.com>
9
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
10
---
11
include/crypto/sm4.h | 1 +
12
crypto/sm4.c | 10 ++++++++++
13
2 files changed, 11 insertions(+)
14
15
diff --git a/include/crypto/sm4.h b/include/crypto/sm4.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/crypto/sm4.h
18
+++ b/include/crypto/sm4.h
19
@@ -XXX,XX +XXX,XX @@
20
#define QEMU_SM4_H
21
22
extern const uint8_t sm4_sbox[256];
23
+extern const uint32_t sm4_ck[32];
24
25
static inline uint32_t sm4_subword(uint32_t word)
26
{
27
diff --git a/crypto/sm4.c b/crypto/sm4.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/crypto/sm4.c
30
+++ b/crypto/sm4.c
31
@@ -XXX,XX +XXX,XX @@ uint8_t const sm4_sbox[] = {
32
0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48,
33
};
34
35
+uint32_t const sm4_ck[] = {
36
+ 0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,
37
+ 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,
38
+ 0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,
39
+ 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,
40
+ 0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,
41
+ 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
42
+ 0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,
43
+ 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279
44
+};
45
--
46
2.41.0
diff view generated by jsdifflib
New patch
1
1
From: Max Chou <max.chou@sifive.com>
2
3
This commit adds support for the Zvksed vector-crypto extension, which
4
consists of the following instructions:
5
6
* vsm4k.vi
7
* vsm4r.[vv,vs]
8
9
Translation functions are defined in
10
`target/riscv/insn_trans/trans_rvvk.c.inc` and helpers are defined in
11
`target/riscv/vcrypto_helper.c`.
12
13
Signed-off-by: Max Chou <max.chou@sifive.com>
14
Reviewed-by: Frank Chang <frank.chang@sifive.com>
15
[lawrence.hunter@codethink.co.uk: Moved SM4 functions from
16
crypto_helper.c to vcrypto_helper.c]
17
[nazar.kazakov@codethink.co.uk: Added alignment checks, refactored code to
18
use macros, and minor style changes]
19
Signed-off-by: Max Chou <max.chou@sifive.com>
20
Message-ID: <20230711165917.2629866-16-max.chou@sifive.com>
21
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
22
---
23
target/riscv/cpu_cfg.h | 1 +
24
target/riscv/helper.h | 4 +
25
target/riscv/insn32.decode | 5 +
26
target/riscv/cpu.c | 5 +-
27
target/riscv/vcrypto_helper.c | 127 +++++++++++++++++++++++
28
target/riscv/insn_trans/trans_rvvk.c.inc | 43 ++++++++
29
6 files changed, 184 insertions(+), 1 deletion(-)
30
31
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
32
index XXXXXXX..XXXXXXX 100644
33
--- a/target/riscv/cpu_cfg.h
34
+++ b/target/riscv/cpu_cfg.h
35
@@ -XXX,XX +XXX,XX @@ struct RISCVCPUConfig {
36
bool ext_zvkned;
37
bool ext_zvknha;
38
bool ext_zvknhb;
39
+ bool ext_zvksed;
40
bool ext_zvksh;
41
bool ext_zmmul;
42
bool ext_zvfbfmin;
43
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
44
index XXXXXXX..XXXXXXX 100644
45
--- a/target/riscv/helper.h
46
+++ b/target/riscv/helper.h
47
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_5(vsm3c_vi, void, ptr, ptr, i32, env, i32)
48
49
DEF_HELPER_5(vghsh_vv, void, ptr, ptr, ptr, env, i32)
50
DEF_HELPER_4(vgmul_vv, void, ptr, ptr, env, i32)
51
+
52
+DEF_HELPER_5(vsm4k_vi, void, ptr, ptr, i32, env, i32)
53
+DEF_HELPER_4(vsm4r_vv, void, ptr, ptr, env, i32)
54
+DEF_HELPER_4(vsm4r_vs, void, ptr, ptr, env, i32)
55
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
56
index XXXXXXX..XXXXXXX 100644
57
--- a/target/riscv/insn32.decode
58
+++ b/target/riscv/insn32.decode
59
@@ -XXX,XX +XXX,XX @@ vsm3c_vi 101011 1 ..... ..... 010 ..... 1110111 @r_vm_1
60
# *** Zvkg vector crypto extension ***
61
vghsh_vv 101100 1 ..... ..... 010 ..... 1110111 @r_vm_1
62
vgmul_vv 101000 1 ..... 10001 010 ..... 1110111 @r2_vm_1
63
+
64
+# *** Zvksed vector crypto extension ***
65
+vsm4k_vi 100001 1 ..... ..... 010 ..... 1110111 @r_vm_1
66
+vsm4r_vv 101000 1 ..... 10000 010 ..... 1110111 @r2_vm_1
67
+vsm4r_vs 101001 1 ..... 10000 010 ..... 1110111 @r2_vm_1
68
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
69
index XXXXXXX..XXXXXXX 100644
70
--- a/target/riscv/cpu.c
71
+++ b/target/riscv/cpu.c
72
@@ -XXX,XX +XXX,XX @@ static const struct isa_ext_data isa_edata_arr[] = {
73
ISA_EXT_DATA_ENTRY(zvkned, PRIV_VERSION_1_12_0, ext_zvkned),
74
ISA_EXT_DATA_ENTRY(zvknha, PRIV_VERSION_1_12_0, ext_zvknha),
75
ISA_EXT_DATA_ENTRY(zvknhb, PRIV_VERSION_1_12_0, ext_zvknhb),
76
+ ISA_EXT_DATA_ENTRY(zvksed, PRIV_VERSION_1_12_0, ext_zvksed),
77
ISA_EXT_DATA_ENTRY(zvksh, PRIV_VERSION_1_12_0, ext_zvksh),
78
ISA_EXT_DATA_ENTRY(zhinx, PRIV_VERSION_1_12_0, ext_zhinx),
79
ISA_EXT_DATA_ENTRY(zhinxmin, PRIV_VERSION_1_12_0, ext_zhinxmin),
80
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
81
* in qemu
82
*/
83
if ((cpu->cfg.ext_zvbb || cpu->cfg.ext_zvkg || cpu->cfg.ext_zvkned ||
84
- cpu->cfg.ext_zvknha || cpu->cfg.ext_zvksh) && !cpu->cfg.ext_zve32f) {
85
+ cpu->cfg.ext_zvknha || cpu->cfg.ext_zvksed || cpu->cfg.ext_zvksh) &&
86
+ !cpu->cfg.ext_zve32f) {
87
error_setg(errp,
88
"Vector crypto extensions require V or Zve* extensions");
89
return;
90
@@ -XXX,XX +XXX,XX @@ static Property riscv_cpu_extensions[] = {
91
DEFINE_PROP_BOOL("x-zvkned", RISCVCPU, cfg.ext_zvkned, false),
92
DEFINE_PROP_BOOL("x-zvknha", RISCVCPU, cfg.ext_zvknha, false),
93
DEFINE_PROP_BOOL("x-zvknhb", RISCVCPU, cfg.ext_zvknhb, false),
94
+ DEFINE_PROP_BOOL("x-zvksed", RISCVCPU, cfg.ext_zvksed, false),
95
DEFINE_PROP_BOOL("x-zvksh", RISCVCPU, cfg.ext_zvksh, false),
96
97
DEFINE_PROP_END_OF_LIST(),
98
diff --git a/target/riscv/vcrypto_helper.c b/target/riscv/vcrypto_helper.c
99
index XXXXXXX..XXXXXXX 100644
100
--- a/target/riscv/vcrypto_helper.c
101
+++ b/target/riscv/vcrypto_helper.c
102
@@ -XXX,XX +XXX,XX @@
103
#include "cpu.h"
104
#include "crypto/aes.h"
105
#include "crypto/aes-round.h"
106
+#include "crypto/sm4.h"
107
#include "exec/memop.h"
108
#include "exec/exec-all.h"
109
#include "exec/helper-proto.h"
110
@@ -XXX,XX +XXX,XX @@ void HELPER(vgmul_vv)(void *vd_vptr, void *vs2_vptr, CPURISCVState *env,
111
vext_set_elems_1s(vd, vta, env->vl * 4, total_elems * 4);
112
env->vstart = 0;
113
}
114
+
115
+void HELPER(vsm4k_vi)(void *vd, void *vs2, uint32_t uimm5, CPURISCVState *env,
116
+ uint32_t desc)
117
+{
118
+ const uint32_t egs = 4;
119
+ uint32_t rnd = uimm5 & 0x7;
120
+ uint32_t group_start = env->vstart / egs;
121
+ uint32_t group_end = env->vl / egs;
122
+ uint32_t esz = sizeof(uint32_t);
123
+ uint32_t total_elems = vext_get_total_elems(env, desc, esz);
124
+
125
+ for (uint32_t i = group_start; i < group_end; ++i) {
126
+ uint32_t vstart = i * egs;
127
+ uint32_t vend = (i + 1) * egs;
128
+ uint32_t rk[4] = {0};
129
+ uint32_t tmp[8] = {0};
130
+
131
+ for (uint32_t j = vstart; j < vend; ++j) {
132
+ rk[j - vstart] = *((uint32_t *)vs2 + H4(j));
133
+ }
134
+
135
+ for (uint32_t j = 0; j < egs; ++j) {
136
+ tmp[j] = rk[j];
137
+ }
138
+
139
+ for (uint32_t j = 0; j < egs; ++j) {
140
+ uint32_t b, s;
141
+ b = tmp[j + 1] ^ tmp[j + 2] ^ tmp[j + 3] ^ sm4_ck[rnd * 4 + j];
142
+
143
+ s = sm4_subword(b);
144
+
145
+ tmp[j + 4] = tmp[j] ^ (s ^ rol32(s, 13) ^ rol32(s, 23));
146
+ }
147
+
148
+ for (uint32_t j = vstart; j < vend; ++j) {
149
+ *((uint32_t *)vd + H4(j)) = tmp[egs + (j - vstart)];
150
+ }
151
+ }
152
+
153
+ env->vstart = 0;
154
+ /* set tail elements to 1s */
155
+ vext_set_elems_1s(vd, vext_vta(desc), env->vl * esz, total_elems * esz);
156
+}
157
+
158
+static void do_sm4_round(uint32_t *rk, uint32_t *buf)
159
+{
160
+ const uint32_t egs = 4;
161
+ uint32_t s, b;
162
+
163
+ for (uint32_t j = egs; j < egs * 2; ++j) {
164
+ b = buf[j - 3] ^ buf[j - 2] ^ buf[j - 1] ^ rk[j - 4];
165
+
166
+ s = sm4_subword(b);
167
+
168
+ buf[j] = buf[j - 4] ^ (s ^ rol32(s, 2) ^ rol32(s, 10) ^ rol32(s, 18) ^
169
+ rol32(s, 24));
170
+ }
171
+}
172
+
173
+void HELPER(vsm4r_vv)(void *vd, void *vs2, CPURISCVState *env, uint32_t desc)
174
+{
175
+ const uint32_t egs = 4;
176
+ uint32_t group_start = env->vstart / egs;
177
+ uint32_t group_end = env->vl / egs;
178
+ uint32_t esz = sizeof(uint32_t);
179
+ uint32_t total_elems = vext_get_total_elems(env, desc, esz);
180
+
181
+ for (uint32_t i = group_start; i < group_end; ++i) {
182
+ uint32_t vstart = i * egs;
183
+ uint32_t vend = (i + 1) * egs;
184
+ uint32_t rk[4] = {0};
185
+ uint32_t tmp[8] = {0};
186
+
187
+ for (uint32_t j = vstart; j < vend; ++j) {
188
+ rk[j - vstart] = *((uint32_t *)vs2 + H4(j));
189
+ }
190
+
191
+ for (uint32_t j = vstart; j < vend; ++j) {
192
+ tmp[j - vstart] = *((uint32_t *)vd + H4(j));
193
+ }
194
+
195
+ do_sm4_round(rk, tmp);
196
+
197
+ for (uint32_t j = vstart; j < vend; ++j) {
198
+ *((uint32_t *)vd + H4(j)) = tmp[egs + (j - vstart)];
199
+ }
200
+ }
201
+
202
+ env->vstart = 0;
203
+ /* set tail elements to 1s */
204
+ vext_set_elems_1s(vd, vext_vta(desc), env->vl * esz, total_elems * esz);
205
+}
206
+
207
+void HELPER(vsm4r_vs)(void *vd, void *vs2, CPURISCVState *env, uint32_t desc)
208
+{
209
+ const uint32_t egs = 4;
210
+ uint32_t group_start = env->vstart / egs;
211
+ uint32_t group_end = env->vl / egs;
212
+ uint32_t esz = sizeof(uint32_t);
213
+ uint32_t total_elems = vext_get_total_elems(env, desc, esz);
214
+
215
+ for (uint32_t i = group_start; i < group_end; ++i) {
216
+ uint32_t vstart = i * egs;
217
+ uint32_t vend = (i + 1) * egs;
218
+ uint32_t rk[4] = {0};
219
+ uint32_t tmp[8] = {0};
220
+
221
+ for (uint32_t j = 0; j < egs; ++j) {
222
+ rk[j] = *((uint32_t *)vs2 + H4(j));
223
+ }
224
+
225
+ for (uint32_t j = vstart; j < vend; ++j) {
226
+ tmp[j - vstart] = *((uint32_t *)vd + H4(j));
227
+ }
228
+
229
+ do_sm4_round(rk, tmp);
230
+
231
+ for (uint32_t j = vstart; j < vend; ++j) {
232
+ *((uint32_t *)vd + H4(j)) = tmp[egs + (j - vstart)];
233
+ }
234
+ }
235
+
236
+ env->vstart = 0;
237
+ /* set tail elements to 1s */
238
+ vext_set_elems_1s(vd, vext_vta(desc), env->vl * esz, total_elems * esz);
239
+}
240
diff --git a/target/riscv/insn_trans/trans_rvvk.c.inc b/target/riscv/insn_trans/trans_rvvk.c.inc
241
index XXXXXXX..XXXXXXX 100644
242
--- a/target/riscv/insn_trans/trans_rvvk.c.inc
243
+++ b/target/riscv/insn_trans/trans_rvvk.c.inc
244
@@ -XXX,XX +XXX,XX @@ static bool vghsh_check(DisasContext *s, arg_rmrr *a)
245
}
246
247
GEN_VV_UNMASKED_TRANS(vghsh_vv, vghsh_check, ZVKG_EGS)
248
+
249
+/*
250
+ * Zvksed
251
+ */
252
+
253
+#define ZVKSED_EGS 4
254
+
255
+static bool zvksed_check(DisasContext *s)
256
+{
257
+ int egw_bytes = ZVKSED_EGS << s->sew;
258
+ return s->cfg_ptr->ext_zvksed == true &&
259
+ require_rvv(s) &&
260
+ vext_check_isa_ill(s) &&
261
+ MAXSZ(s) >= egw_bytes &&
262
+ s->sew == MO_32;
263
+}
264
+
265
+static bool vsm4k_vi_check(DisasContext *s, arg_rmrr *a)
266
+{
267
+ return zvksed_check(s) &&
268
+ require_align(a->rd, s->lmul) &&
269
+ require_align(a->rs2, s->lmul);
270
+}
271
+
272
+GEN_VI_UNMASKED_TRANS(vsm4k_vi, vsm4k_vi_check, ZVKSED_EGS)
273
+
274
+static bool vsm4r_vv_check(DisasContext *s, arg_rmr *a)
275
+{
276
+ return zvksed_check(s) &&
277
+ require_align(a->rd, s->lmul) &&
278
+ require_align(a->rs2, s->lmul);
279
+}
280
+
281
+GEN_V_UNMASKED_TRANS(vsm4r_vv, vsm4r_vv_check, ZVKSED_EGS)
282
+
283
+static bool vsm4r_vs_check(DisasContext *s, arg_rmr *a)
284
+{
285
+ return zvksed_check(s) &&
286
+ !is_overlapped(a->rd, 1 << MAX(s->lmul, 0), a->rs2, 1) &&
287
+ require_align(a->rd, s->lmul);
288
+}
289
+
290
+GEN_V_UNMASKED_TRANS(vsm4r_vs, vsm4r_vs_check, ZVKSED_EGS)
291
--
292
2.41.0
diff view generated by jsdifflib
New patch
1
From: Rob Bradford <rbradford@rivosinc.com>
1
2
3
These are WARL fields - zero out the bits for unavailable counters and
4
special case the TM bit in mcountinhibit which is hardwired to zero.
5
This patch achieves this by modifying the value written so that any use
6
of the field will see the correctly masked bits.
7
8
Tested by modifying OpenSBI to write max value to these CSRs and upon
9
subsequent read the appropriate number of bits for number of PMUs is
10
enabled and the TM bit is zero in mcountinhibit.
11
12
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
13
Acked-by: Alistair Francis <alistair.francis@wdc.com>
14
Reviewed-by: Atish Patra <atishp@rivosinc.com>
15
Message-ID: <20230802124906.24197-1-rbradford@rivosinc.com>
16
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
17
---
18
target/riscv/csr.c | 11 +++++++++--
19
1 file changed, 9 insertions(+), 2 deletions(-)
20
21
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/target/riscv/csr.c
24
+++ b/target/riscv/csr.c
25
@@ -XXX,XX +XXX,XX @@ static RISCVException write_mcountinhibit(CPURISCVState *env, int csrno,
26
{
27
int cidx;
28
PMUCTRState *counter;
29
+ RISCVCPU *cpu = env_archcpu(env);
30
31
- env->mcountinhibit = val;
32
+ /* WARL register - disable unavailable counters; TM bit is always 0 */
33
+ env->mcountinhibit =
34
+ val & (cpu->pmu_avail_ctrs | COUNTEREN_CY | COUNTEREN_IR);
35
36
/* Check if any other counter is also monitoring cycles/instructions */
37
for (cidx = 0; cidx < RV_MAX_MHPMCOUNTERS; cidx++) {
38
@@ -XXX,XX +XXX,XX @@ static RISCVException read_mcounteren(CPURISCVState *env, int csrno,
39
static RISCVException write_mcounteren(CPURISCVState *env, int csrno,
40
target_ulong val)
41
{
42
- env->mcounteren = val;
43
+ RISCVCPU *cpu = env_archcpu(env);
44
+
45
+ /* WARL register - disable unavailable counters */
46
+ env->mcounteren = val & (cpu->pmu_avail_ctrs | COUNTEREN_CY | COUNTEREN_TM |
47
+ COUNTEREN_IR);
48
return RISCV_EXCP_NONE;
49
}
50
51
--
52
2.41.0
diff view generated by jsdifflib
New patch
1
From: Jason Chien <jason.chien@sifive.com>
1
2
3
RVA23 Profiles states:
4
The RVA23 profiles are intended to be used for 64-bit application
5
processors that will run rich OS stacks from standard binary OS
6
distributions and with a substantial number of third-party binary user
7
applications that will be supported over a considerable length of time
8
in the field.
9
10
The chapter 4 of the unprivileged spec introduces the Zihintntl extension
11
and Zihintntl is a mandatory extension presented in RVA23 Profiles, whose
12
purpose is to enable application and operating system portability across
13
different implementations. Thus the DTS should contain the Zihintntl ISA
14
string in order to pass to software.
15
16
The unprivileged spec states:
17
Like any HINTs, these instructions may be freely ignored. Hence, although
18
they are described in terms of cache-based memory hierarchies, they do not
19
mandate the provision of caches.
20
21
These instructions are encoded with non-used opcode, e.g. ADD x0, x0, x2,
22
which QEMU already supports, and QEMU does not emulate cache. Therefore
23
these instructions can be considered as a no-op, and we only need to add
24
a new property for the Zihintntl extension.
25
26
Reviewed-by: Frank Chang <frank.chang@sifive.com>
27
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
28
Signed-off-by: Jason Chien <jason.chien@sifive.com>
29
Message-ID: <20230726074049.19505-2-jason.chien@sifive.com>
30
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
31
---
32
target/riscv/cpu_cfg.h | 1 +
33
target/riscv/cpu.c | 2 ++
34
2 files changed, 3 insertions(+)
35
36
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
37
index XXXXXXX..XXXXXXX 100644
38
--- a/target/riscv/cpu_cfg.h
39
+++ b/target/riscv/cpu_cfg.h
40
@@ -XXX,XX +XXX,XX @@ struct RISCVCPUConfig {
41
bool ext_icbom;
42
bool ext_icboz;
43
bool ext_zicond;
44
+ bool ext_zihintntl;
45
bool ext_zihintpause;
46
bool ext_smstateen;
47
bool ext_sstc;
48
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/target/riscv/cpu.c
51
+++ b/target/riscv/cpu.c
52
@@ -XXX,XX +XXX,XX @@ static const struct isa_ext_data isa_edata_arr[] = {
53
ISA_EXT_DATA_ENTRY(zicond, PRIV_VERSION_1_12_0, ext_zicond),
54
ISA_EXT_DATA_ENTRY(zicsr, PRIV_VERSION_1_10_0, ext_icsr),
55
ISA_EXT_DATA_ENTRY(zifencei, PRIV_VERSION_1_10_0, ext_ifencei),
56
+ ISA_EXT_DATA_ENTRY(zihintntl, PRIV_VERSION_1_10_0, ext_zihintntl),
57
ISA_EXT_DATA_ENTRY(zihintpause, PRIV_VERSION_1_10_0, ext_zihintpause),
58
ISA_EXT_DATA_ENTRY(zmmul, PRIV_VERSION_1_12_0, ext_zmmul),
59
ISA_EXT_DATA_ENTRY(zawrs, PRIV_VERSION_1_12_0, ext_zawrs),
60
@@ -XXX,XX +XXX,XX @@ static Property riscv_cpu_extensions[] = {
61
DEFINE_PROP_BOOL("sscofpmf", RISCVCPU, cfg.ext_sscofpmf, false),
62
DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true),
63
DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true),
64
+ DEFINE_PROP_BOOL("Zihintntl", RISCVCPU, cfg.ext_zihintntl, true),
65
DEFINE_PROP_BOOL("Zihintpause", RISCVCPU, cfg.ext_zihintpause, true),
66
DEFINE_PROP_BOOL("Zawrs", RISCVCPU, cfg.ext_zawrs, true),
67
DEFINE_PROP_BOOL("Zfa", RISCVCPU, cfg.ext_zfa, true),
68
--
69
2.41.0
diff view generated by jsdifflib
New patch
1
From: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
1
2
3
Commit a47842d ("riscv: Add support for the Zfa extension") implemented the zfa extension.
4
However, it has some typos for fleq.d and fltq.d. Both of them misused the fltq.s
5
helper function.
6
7
Fixes: a47842d ("riscv: Add support for the Zfa extension")
8
Signed-off-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
9
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
10
Reviewed-by: Weiwei Li <liweiwei@iscas.ac.cn>
11
Message-ID: <20230728003906.768-1-zhiwei_liu@linux.alibaba.com>
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
13
---
14
target/riscv/insn_trans/trans_rvzfa.c.inc | 4 ++--
15
1 file changed, 2 insertions(+), 2 deletions(-)
16
17
diff --git a/target/riscv/insn_trans/trans_rvzfa.c.inc b/target/riscv/insn_trans/trans_rvzfa.c.inc
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/riscv/insn_trans/trans_rvzfa.c.inc
20
+++ b/target/riscv/insn_trans/trans_rvzfa.c.inc
21
@@ -XXX,XX +XXX,XX @@ bool trans_fleq_d(DisasContext *ctx, arg_fleq_d *a)
22
TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
23
TCGv_i64 src2 = get_fpr_hs(ctx, a->rs2);
24
25
- gen_helper_fltq_s(dest, cpu_env, src1, src2);
26
+ gen_helper_fleq_d(dest, cpu_env, src1, src2);
27
gen_set_gpr(ctx, a->rd, dest);
28
return true;
29
}
30
@@ -XXX,XX +XXX,XX @@ bool trans_fltq_d(DisasContext *ctx, arg_fltq_d *a)
31
TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
32
TCGv_i64 src2 = get_fpr_hs(ctx, a->rs2);
33
34
- gen_helper_fltq_s(dest, cpu_env, src1, src2);
35
+ gen_helper_fltq_d(dest, cpu_env, src1, src2);
36
gen_set_gpr(ctx, a->rd, dest);
37
return true;
38
}
39
--
40
2.41.0
diff view generated by jsdifflib
New patch
1
From: Jason Chien <jason.chien@sifive.com>
1
2
3
When writing the upper mtime, we should keep the original lower mtime
4
whose value is given by cpu_riscv_read_rtc() instead of
5
cpu_riscv_read_rtc_raw(). The same logic applies to writes to lower mtime.
6
7
Signed-off-by: Jason Chien <jason.chien@sifive.com>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Message-ID: <20230728082502.26439-1-jason.chien@sifive.com>
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
---
12
hw/intc/riscv_aclint.c | 5 +++--
13
1 file changed, 3 insertions(+), 2 deletions(-)
14
15
diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/intc/riscv_aclint.c
18
+++ b/hw/intc/riscv_aclint.c
19
@@ -XXX,XX +XXX,XX @@ static void riscv_aclint_mtimer_write(void *opaque, hwaddr addr,
20
return;
21
} else if (addr == mtimer->time_base || addr == mtimer->time_base + 4) {
22
uint64_t rtc_r = cpu_riscv_read_rtc_raw(mtimer->timebase_freq);
23
+ uint64_t rtc = cpu_riscv_read_rtc(mtimer);
24
25
if (addr == mtimer->time_base) {
26
if (size == 4) {
27
/* time_lo for RV32/RV64 */
28
- mtimer->time_delta = ((rtc_r & ~0xFFFFFFFFULL) | value) - rtc_r;
29
+ mtimer->time_delta = ((rtc & ~0xFFFFFFFFULL) | value) - rtc_r;
30
} else {
31
/* time for RV64 */
32
mtimer->time_delta = value - rtc_r;
33
@@ -XXX,XX +XXX,XX @@ static void riscv_aclint_mtimer_write(void *opaque, hwaddr addr,
34
} else {
35
if (size == 4) {
36
/* time_hi for RV32/RV64 */
37
- mtimer->time_delta = (value << 32 | (rtc_r & 0xFFFFFFFF)) - rtc_r;
38
+ mtimer->time_delta = (value << 32 | (rtc & 0xFFFFFFFF)) - rtc_r;
39
} else {
40
qemu_log_mask(LOG_GUEST_ERROR,
41
"aclint-mtimer: invalid time_hi write: %08x",
42
--
43
2.41.0
diff view generated by jsdifflib
1
From: Bin Meng <bmeng.cn@gmail.com>
1
From: Jason Chien <jason.chien@sifive.com>
2
2
3
In U-Boot v2021.07 release, there were 2 major changes for the
3
The variables whose values are given by cpu_riscv_read_rtc() should be named
4
SiFive Unleashed board support:
4
"rtc". The variables whose value are given by cpu_riscv_read_rtc_raw()
5
should be named "rtc_r".
5
6
6
- Board config name was changed from sifive_fu540_defconfig to
7
Signed-off-by: Jason Chien <jason.chien@sifive.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>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
17
Message-id: 20210911153431.10362-1-bmeng.cn@gmail.com
9
Message-ID: <20230728082502.26439-2-jason.chien@sifive.com>
18
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
19
---
11
---
20
docs/system/riscv/sifive_u.rst | 49 ++++++++++++++++++----------------
12
hw/intc/riscv_aclint.c | 6 +++---
21
1 file changed, 26 insertions(+), 23 deletions(-)
13
1 file changed, 3 insertions(+), 3 deletions(-)
22
14
23
diff --git a/docs/system/riscv/sifive_u.rst b/docs/system/riscv/sifive_u.rst
15
diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c
24
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
25
--- a/docs/system/riscv/sifive_u.rst
17
--- a/hw/intc/riscv_aclint.c
26
+++ b/docs/system/riscv/sifive_u.rst
18
+++ b/hw/intc/riscv_aclint.c
27
@@ -XXX,XX +XXX,XX @@ command line options with ``qemu-system-riscv32``.
19
@@ -XXX,XX +XXX,XX @@ static void riscv_aclint_mtimer_write_timecmp(RISCVAclintMTimerState *mtimer,
28
Running U-Boot
20
uint64_t next;
29
--------------
21
uint64_t diff;
30
22
31
-U-Boot mainline v2021.01 release is tested at the time of writing. To build a
23
- uint64_t rtc_r = cpu_riscv_read_rtc(mtimer);
32
+U-Boot mainline v2021.07 release is tested at the time of writing. To build a
24
+ uint64_t rtc = cpu_riscv_read_rtc(mtimer);
33
U-Boot mainline bootloader that can be booted by the ``sifive_u`` machine, use
25
34
-the sifive_fu540_defconfig with similar commands as described above for Linux:
26
/* Compute the relative hartid w.r.t the socket */
35
+the sifive_unleashed_defconfig with similar commands as described above for
27
hartid = hartid - mtimer->hartid_base;
36
+Linux:
28
37
29
mtimer->timecmp[hartid] = value;
38
.. code-block:: bash
30
- if (mtimer->timecmp[hartid] <= rtc_r) {
39
31
+ if (mtimer->timecmp[hartid] <= rtc) {
40
$ export CROSS_COMPILE=riscv64-linux-
32
/*
41
$ export OPENSBI=/path/to/opensbi-riscv64-generic-fw_dynamic.bin
33
* If we're setting an MTIMECMP value in the "past",
42
- $ make sifive_fu540_defconfig
34
* immediately raise the timer interrupt
43
+ $ make sifive_unleashed_defconfig
35
@@ -XXX,XX +XXX,XX @@ static void riscv_aclint_mtimer_write_timecmp(RISCVAclintMTimerState *mtimer,
44
36
45
You will get spl/u-boot-spl.bin and u-boot.itb file in the build tree.
37
/* otherwise, set up the future timer interrupt */
46
38
qemu_irq_lower(mtimer->timer_irqs[hartid]);
47
@@ -XXX,XX +XXX,XX @@ board on QEMU ``sifive_u`` machine out of the box. This allows users to
39
- diff = mtimer->timecmp[hartid] - rtc_r;
48
develop and test the recommended RISC-V boot flow with a real world use
40
+ diff = mtimer->timecmp[hartid] - rtc;
49
case: ZSBL (in QEMU) loads U-Boot SPL from SD card or SPI flash to L2LIM,
41
/* back to ns (note args switched in muldiv64) */
50
then U-Boot SPL loads the combined payload image of OpenSBI fw_dynamic
42
uint64_t ns_diff = muldiv64(diff, NANOSECONDS_PER_SECOND, timebase_freq);
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
43
116
--
44
--
117
2.31.1
45
2.41.0
118
119
diff view generated by jsdifflib
1
From: Frank Chang <frank.chang@sifive.com>
1
From: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
2
2
3
Real PDMA must have Control.claim bit to be set before
3
We should not use types dependend on host arch for target_ucontext.
4
Control.run bit is set to start any DMA transactions.
4
This bug is found when run rv32 applications.
5
Otherwise nothing will be transferred.
6
5
7
The following result is PDMA tested in U-Boot on Unmatched board:
6
Signed-off-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
8
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
=> mw.l 0x3000000 0x0 <= Disclaim channel 0
8
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
10
(Channel 0 is not claimed)
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
=> mw.l 0x3000004 0x55000000 <= wsize = rsize = 5 (2^5 = 32 bytes)
10
Message-ID: <20230811055438.1945-1-zhiwei_liu@linux.alibaba.com>
12
=> mw.q 0x3000008 0x2 <= NextBytes = 2
13
=> mw.q 0x3000010 0x84000000 <= NextDestination = 0x84000000
14
=> mw.q 0x3000018 0x84001000 <= NextSource = 0x84001000
15
=> mw.l 0x84000000 0x87654321 <= Fill test data to dst
16
=> mw.l 0x84001000 0x12345678 <= Fill test data to src
17
=> md.l 0x84000000 1; md.l 0x84001000 1 <= Dump src/dst memory contents
18
84000000: 87654321 !Ce.
19
84001000: 12345678 xV4.
20
=> md.l 0x3000000 8 <= Dump PDMA status
21
03000000: 00000000 55000000 00000002 00000000 .......U........
22
03000010: 84000000 00000000 84001000 00000000 ................
23
=> mw.l 0x3000000 0x3 <= Set channel 0 run and claim bits
24
=> md.l 0x3000000 8 <= Dump PDMA status
25
03000000: 00000001 66000000 00000000 00000000 .......f........
26
03000010: 00000000 00000000 00000000 00000000 ................
27
=> md.l 0x84000000 1; md.l 0x84001000 1 <= Dump src/dst memory contents
28
84000000: 87654321 !Ce.
29
84001000: 12345678 xV4.
30
31
Signed-off-by: Frank Chang <frank.chang@sifive.com>
32
Tested-by: Max Hsu <max.hsu@sifive.com>
33
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
34
Tested-by: Bin Meng <bmeng.cn@gmail.com>
35
Message-id: 20210912130553.179501-3-frank.chang@sifive.com
36
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
37
---
12
---
38
hw/dma/sifive_pdma.c | 9 +++++++++
13
linux-user/riscv/signal.c | 4 ++--
39
1 file changed, 9 insertions(+)
14
1 file changed, 2 insertions(+), 2 deletions(-)
40
15
41
diff --git a/hw/dma/sifive_pdma.c b/hw/dma/sifive_pdma.c
16
diff --git a/linux-user/riscv/signal.c b/linux-user/riscv/signal.c
42
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
43
--- a/hw/dma/sifive_pdma.c
18
--- a/linux-user/riscv/signal.c
44
+++ b/hw/dma/sifive_pdma.c
19
+++ b/linux-user/riscv/signal.c
45
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_write(void *opaque, hwaddr offset,
20
@@ -XXX,XX +XXX,XX @@ struct target_sigcontext {
46
21
}; /* cf. riscv-linux:arch/riscv/include/uapi/asm/ptrace.h */
47
s->chan[ch].control = value;
22
48
23
struct target_ucontext {
49
+ /*
24
- unsigned long uc_flags;
50
+ * If channel was not claimed before run bit is set,
25
- struct target_ucontext *uc_link;
51
+ * DMA won't run.
26
+ abi_ulong uc_flags;
52
+ */
27
+ abi_ptr uc_link;
53
+ if (!claimed) {
28
target_stack_t uc_stack;
54
+ s->chan[ch].control &= ~CONTROL_RUN;
29
target_sigset_t uc_sigmask;
55
+ return;
30
uint8_t __unused[1024 / 8 - sizeof(target_sigset_t)];
56
+ }
57
+
58
if (value & CONTROL_RUN) {
59
sifive_pdma_run(s, ch);
60
}
61
--
31
--
62
2.31.1
32
2.41.0
63
33
64
34
diff view generated by jsdifflib
1
From: Anup Patel <anup.patel@wdc.com>
1
From: Yong-Xuan Wang <yongxuan.wang@sifive.com>
2
2
3
We extend virt machine to emulate ACLINT devices only when "aclint=on"
3
In this patch, we create the APLIC and IMSIC FDT helper functions and
4
parameter is passed along with machine name in QEMU command-line.
4
remove M mode AIA devices when using KVM acceleration.
5
5
6
Signed-off-by: Anup Patel <anup.patel@wdc.com>
6
Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
7
Reviewed-by: Jim Shu <jim.shu@sifive.com>
8
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
8
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
9
Message-id: 20210831110603.338681-5-anup.patel@wdc.com
9
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
10
Message-ID: <20230727102439.22554-2-yongxuan.wang@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
hw/riscv/virt.c | 290 +++++++++++++++++++++++-------------------------
13
include/hw/riscv/virt.h | 2 +
14
1 file changed, 137 insertions(+), 153 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
18
index XXXXXXX..XXXXXXX 100644
19
--- a/docs/system/riscv/virt.rst
20
+++ b/docs/system/riscv/virt.rst
21
@@ -XXX,XX +XXX,XX @@ with the default OpenSBI firmware image as the -bios. It also supports
22
the recommended RISC-V bootflow: U-Boot SPL (M-mode) loads OpenSBI fw_dynamic
23
firmware and U-Boot proper (S-mode), using the standard -bios functionality.
24
25
+Machine-specific options
26
+------------------------
27
+
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
16
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
59
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
60
--- a/hw/riscv/virt.c
18
--- a/hw/riscv/virt.c
61
+++ b/hw/riscv/virt.c
19
+++ b/hw/riscv/virt.c
62
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry virt_memmap[] = {
20
@@ -XXX,XX +XXX,XX @@ static uint32_t imsic_num_bits(uint32_t count)
63
[VIRT_TEST] = { 0x100000, 0x1000 },
21
return ret;
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
}
22
}
73
23
74
+static void create_fdt_socket_aclint(RISCVVirtState *s,
24
-static void create_fdt_imsic(RISCVVirtState *s, const MemMapEntry *memmap,
75
+ const MemMapEntry *memmap, int socket,
25
- uint32_t *phandle, uint32_t *intc_phandles,
76
+ uint32_t *intc_phandles)
26
- uint32_t *msi_m_phandle, uint32_t *msi_s_phandle)
27
+static void create_fdt_one_imsic(RISCVVirtState *s, hwaddr base_addr,
28
+ uint32_t *intc_phandles, uint32_t msi_phandle,
29
+ bool m_mode, uint32_t imsic_guest_bits)
30
{
31
int cpu, socket;
32
char *imsic_name;
33
MachineState *ms = MACHINE(s);
34
int socket_count = riscv_socket_count(ms);
35
- uint32_t imsic_max_hart_per_socket, imsic_guest_bits;
36
+ uint32_t imsic_max_hart_per_socket;
37
uint32_t *imsic_cells, *imsic_regs, imsic_addr, imsic_size;
38
39
- *msi_m_phandle = (*phandle)++;
40
- *msi_s_phandle = (*phandle)++;
41
imsic_cells = g_new0(uint32_t, ms->smp.cpus * 2);
42
imsic_regs = g_new0(uint32_t, socket_count * 4);
43
44
- /* M-level IMSIC node */
45
for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
46
imsic_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
47
- imsic_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_M_EXT);
48
+ imsic_cells[cpu * 2 + 1] = cpu_to_be32(m_mode ? IRQ_M_EXT : IRQ_S_EXT);
49
}
50
- imsic_max_hart_per_socket = 0;
51
- for (socket = 0; socket < socket_count; socket++) {
52
- imsic_addr = memmap[VIRT_IMSIC_M].base +
53
- socket * VIRT_IMSIC_GROUP_MAX_SIZE;
54
- imsic_size = IMSIC_HART_SIZE(0) * s->soc[socket].num_harts;
55
- imsic_regs[socket * 4 + 0] = 0;
56
- imsic_regs[socket * 4 + 1] = cpu_to_be32(imsic_addr);
57
- imsic_regs[socket * 4 + 2] = 0;
58
- imsic_regs[socket * 4 + 3] = cpu_to_be32(imsic_size);
59
- if (imsic_max_hart_per_socket < s->soc[socket].num_harts) {
60
- imsic_max_hart_per_socket = s->soc[socket].num_harts;
61
- }
62
- }
63
- imsic_name = g_strdup_printf("/soc/imsics@%lx",
64
- (unsigned long)memmap[VIRT_IMSIC_M].base);
65
- qemu_fdt_add_subnode(ms->fdt, imsic_name);
66
- qemu_fdt_setprop_string(ms->fdt, imsic_name, "compatible",
67
- "riscv,imsics");
68
- qemu_fdt_setprop_cell(ms->fdt, imsic_name, "#interrupt-cells",
69
- FDT_IMSIC_INT_CELLS);
70
- qemu_fdt_setprop(ms->fdt, imsic_name, "interrupt-controller",
71
- NULL, 0);
72
- qemu_fdt_setprop(ms->fdt, imsic_name, "msi-controller",
73
- NULL, 0);
74
- qemu_fdt_setprop(ms->fdt, imsic_name, "interrupts-extended",
75
- imsic_cells, ms->smp.cpus * sizeof(uint32_t) * 2);
76
- qemu_fdt_setprop(ms->fdt, imsic_name, "reg", imsic_regs,
77
- socket_count * sizeof(uint32_t) * 4);
78
- qemu_fdt_setprop_cell(ms->fdt, imsic_name, "riscv,num-ids",
79
- VIRT_IRQCHIP_NUM_MSIS);
80
- if (socket_count > 1) {
81
- qemu_fdt_setprop_cell(ms->fdt, imsic_name, "riscv,hart-index-bits",
82
- imsic_num_bits(imsic_max_hart_per_socket));
83
- qemu_fdt_setprop_cell(ms->fdt, imsic_name, "riscv,group-index-bits",
84
- imsic_num_bits(socket_count));
85
- qemu_fdt_setprop_cell(ms->fdt, imsic_name, "riscv,group-index-shift",
86
- IMSIC_MMIO_GROUP_MIN_SHIFT);
87
- }
88
- qemu_fdt_setprop_cell(ms->fdt, imsic_name, "phandle", *msi_m_phandle);
89
-
90
- g_free(imsic_name);
91
92
- /* S-level IMSIC node */
93
- for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
94
- imsic_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
95
- imsic_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_S_EXT);
96
- }
97
- imsic_guest_bits = imsic_num_bits(s->aia_guests + 1);
98
imsic_max_hart_per_socket = 0;
99
for (socket = 0; socket < socket_count; socket++) {
100
- imsic_addr = memmap[VIRT_IMSIC_S].base +
101
- socket * VIRT_IMSIC_GROUP_MAX_SIZE;
102
+ imsic_addr = base_addr + socket * VIRT_IMSIC_GROUP_MAX_SIZE;
103
imsic_size = IMSIC_HART_SIZE(imsic_guest_bits) *
104
s->soc[socket].num_harts;
105
imsic_regs[socket * 4 + 0] = 0;
106
@@ -XXX,XX +XXX,XX @@ static void create_fdt_imsic(RISCVVirtState *s, const MemMapEntry *memmap,
107
imsic_max_hart_per_socket = s->soc[socket].num_harts;
108
}
109
}
110
- imsic_name = g_strdup_printf("/soc/imsics@%lx",
111
- (unsigned long)memmap[VIRT_IMSIC_S].base);
112
+
113
+ imsic_name = g_strdup_printf("/soc/imsics@%lx", (unsigned long)base_addr);
114
qemu_fdt_add_subnode(ms->fdt, imsic_name);
115
- qemu_fdt_setprop_string(ms->fdt, imsic_name, "compatible",
116
- "riscv,imsics");
117
+ qemu_fdt_setprop_string(ms->fdt, imsic_name, "compatible", "riscv,imsics");
118
qemu_fdt_setprop_cell(ms->fdt, imsic_name, "#interrupt-cells",
119
- FDT_IMSIC_INT_CELLS);
120
- qemu_fdt_setprop(ms->fdt, imsic_name, "interrupt-controller",
121
- NULL, 0);
122
- qemu_fdt_setprop(ms->fdt, imsic_name, "msi-controller",
123
- NULL, 0);
124
+ FDT_IMSIC_INT_CELLS);
125
+ qemu_fdt_setprop(ms->fdt, imsic_name, "interrupt-controller", NULL, 0);
126
+ qemu_fdt_setprop(ms->fdt, imsic_name, "msi-controller", NULL, 0);
127
qemu_fdt_setprop(ms->fdt, imsic_name, "interrupts-extended",
128
- imsic_cells, ms->smp.cpus * sizeof(uint32_t) * 2);
129
+ imsic_cells, ms->smp.cpus * sizeof(uint32_t) * 2);
130
qemu_fdt_setprop(ms->fdt, imsic_name, "reg", imsic_regs,
131
- socket_count * sizeof(uint32_t) * 4);
132
+ socket_count * sizeof(uint32_t) * 4);
133
qemu_fdt_setprop_cell(ms->fdt, imsic_name, "riscv,num-ids",
134
- VIRT_IRQCHIP_NUM_MSIS);
135
+ VIRT_IRQCHIP_NUM_MSIS);
136
+
137
if (imsic_guest_bits) {
138
qemu_fdt_setprop_cell(ms->fdt, imsic_name, "riscv,guest-index-bits",
139
- imsic_guest_bits);
140
+ imsic_guest_bits);
141
}
142
+
143
if (socket_count > 1) {
144
qemu_fdt_setprop_cell(ms->fdt, imsic_name, "riscv,hart-index-bits",
145
- imsic_num_bits(imsic_max_hart_per_socket));
146
+ imsic_num_bits(imsic_max_hart_per_socket));
147
qemu_fdt_setprop_cell(ms->fdt, imsic_name, "riscv,group-index-bits",
148
- imsic_num_bits(socket_count));
149
+ imsic_num_bits(socket_count));
150
qemu_fdt_setprop_cell(ms->fdt, imsic_name, "riscv,group-index-shift",
151
- IMSIC_MMIO_GROUP_MIN_SHIFT);
152
+ IMSIC_MMIO_GROUP_MIN_SHIFT);
153
}
154
- qemu_fdt_setprop_cell(ms->fdt, imsic_name, "phandle", *msi_s_phandle);
155
- g_free(imsic_name);
156
+ qemu_fdt_setprop_cell(ms->fdt, imsic_name, "phandle", msi_phandle);
157
158
+ g_free(imsic_name);
159
g_free(imsic_regs);
160
g_free(imsic_cells);
161
}
162
163
-static void create_fdt_socket_aplic(RISCVVirtState *s,
164
- const MemMapEntry *memmap, int socket,
165
- uint32_t msi_m_phandle,
166
- uint32_t msi_s_phandle,
167
- uint32_t *phandle,
168
- uint32_t *intc_phandles,
169
- uint32_t *aplic_phandles)
170
+static void create_fdt_imsic(RISCVVirtState *s, const MemMapEntry *memmap,
171
+ uint32_t *phandle, uint32_t *intc_phandles,
172
+ uint32_t *msi_m_phandle, uint32_t *msi_s_phandle)
77
+{
173
+{
78
+ int cpu;
174
+ *msi_m_phandle = (*phandle)++;
79
+ char *name;
175
+ *msi_s_phandle = (*phandle)++;
80
+ unsigned long addr;
176
+
81
+ uint32_t aclint_cells_size;
177
+ if (!kvm_enabled()) {
82
+ uint32_t *aclint_mswi_cells;
178
+ /* M-level IMSIC node */
83
+ uint32_t *aclint_sswi_cells;
179
+ create_fdt_one_imsic(s, memmap[VIRT_IMSIC_M].base, intc_phandles,
84
+ uint32_t *aclint_mtimer_cells;
180
+ *msi_m_phandle, true, 0);
85
+ MachineState *mc = MACHINE(s);
86
+
87
+ aclint_mswi_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2);
88
+ aclint_mtimer_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2);
89
+ aclint_sswi_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2);
90
+
91
+ for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) {
92
+ aclint_mswi_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
93
+ aclint_mswi_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_M_SOFT);
94
+ aclint_mtimer_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
95
+ aclint_mtimer_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_M_TIMER);
96
+ aclint_sswi_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
97
+ aclint_sswi_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_S_SOFT);
98
+ }
181
+ }
99
+ aclint_cells_size = s->soc[socket].num_harts * sizeof(uint32_t) * 2;
182
+
100
+
183
+ /* S-level IMSIC node */
101
+ addr = memmap[VIRT_CLINT].base + (memmap[VIRT_CLINT].size * socket);
184
+ create_fdt_one_imsic(s, memmap[VIRT_IMSIC_S].base, intc_phandles,
102
+ name = g_strdup_printf("/soc/mswi@%lx", addr);
185
+ *msi_s_phandle, false,
103
+ qemu_fdt_add_subnode(mc->fdt, name);
186
+ imsic_num_bits(s->aia_guests + 1));
104
+ qemu_fdt_setprop_string(mc->fdt, name, "compatible", "riscv,aclint-mswi");
187
+
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
+}
188
+}
149
+
189
+
150
static void create_fdt_socket_plic(RISCVVirtState *s,
190
+static void create_fdt_one_aplic(RISCVVirtState *s, int socket,
151
const MemMapEntry *memmap, int socket,
191
+ unsigned long aplic_addr, uint32_t aplic_size,
152
uint32_t *phandle, uint32_t *intc_phandles,
192
+ uint32_t msi_phandle,
153
@@ -XXX,XX +XXX,XX @@ static void create_fdt_sockets(RISCVVirtState *s, const MemMapEntry *memmap,
193
+ uint32_t *intc_phandles,
154
194
+ uint32_t aplic_phandle,
155
create_fdt_socket_memory(s, memmap, socket);
195
+ uint32_t aplic_child_phandle,
156
196
+ bool m_mode)
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
{
197
{
198
int cpu;
199
char *aplic_name;
200
uint32_t *aplic_cells;
201
- unsigned long aplic_addr;
202
MachineState *ms = MACHINE(s);
203
- uint32_t aplic_m_phandle, aplic_s_phandle;
204
205
- aplic_m_phandle = (*phandle)++;
206
- aplic_s_phandle = (*phandle)++;
207
aplic_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2);
208
209
- /* M-level APLIC node */
210
for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) {
211
aplic_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
212
- aplic_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_M_EXT);
213
+ aplic_cells[cpu * 2 + 1] = cpu_to_be32(m_mode ? IRQ_M_EXT : IRQ_S_EXT);
214
}
215
- aplic_addr = memmap[VIRT_APLIC_M].base +
216
- (memmap[VIRT_APLIC_M].size * socket);
217
+
218
aplic_name = g_strdup_printf("/soc/aplic@%lx", aplic_addr);
219
qemu_fdt_add_subnode(ms->fdt, aplic_name);
220
qemu_fdt_setprop_string(ms->fdt, aplic_name, "compatible", "riscv,aplic");
221
qemu_fdt_setprop_cell(ms->fdt, aplic_name,
222
- "#interrupt-cells", FDT_APLIC_INT_CELLS);
223
+ "#interrupt-cells", FDT_APLIC_INT_CELLS);
224
qemu_fdt_setprop(ms->fdt, aplic_name, "interrupt-controller", NULL, 0);
225
+
226
if (s->aia_type == VIRT_AIA_TYPE_APLIC) {
227
qemu_fdt_setprop(ms->fdt, aplic_name, "interrupts-extended",
228
- aplic_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 2);
229
+ aplic_cells,
230
+ s->soc[socket].num_harts * sizeof(uint32_t) * 2);
231
} else {
232
- qemu_fdt_setprop_cell(ms->fdt, aplic_name, "msi-parent",
233
- msi_m_phandle);
234
+ qemu_fdt_setprop_cell(ms->fdt, aplic_name, "msi-parent", msi_phandle);
235
}
236
+
237
qemu_fdt_setprop_cells(ms->fdt, aplic_name, "reg",
238
- 0x0, aplic_addr, 0x0, memmap[VIRT_APLIC_M].size);
239
+ 0x0, aplic_addr, 0x0, aplic_size);
240
qemu_fdt_setprop_cell(ms->fdt, aplic_name, "riscv,num-sources",
241
- VIRT_IRQCHIP_NUM_SOURCES);
242
- qemu_fdt_setprop_cell(ms->fdt, aplic_name, "riscv,children",
243
- aplic_s_phandle);
244
- qemu_fdt_setprop_cells(ms->fdt, aplic_name, "riscv,delegate",
245
- aplic_s_phandle, 0x1, VIRT_IRQCHIP_NUM_SOURCES);
246
+ VIRT_IRQCHIP_NUM_SOURCES);
247
+
248
+ if (aplic_child_phandle) {
249
+ qemu_fdt_setprop_cell(ms->fdt, aplic_name, "riscv,children",
250
+ aplic_child_phandle);
251
+ qemu_fdt_setprop_cells(ms->fdt, aplic_name, "riscv,delegate",
252
+ aplic_child_phandle, 0x1,
253
+ VIRT_IRQCHIP_NUM_SOURCES);
254
+ }
255
+
256
riscv_socket_fdt_write_id(ms, aplic_name, socket);
257
- qemu_fdt_setprop_cell(ms->fdt, aplic_name, "phandle", aplic_m_phandle);
258
+ qemu_fdt_setprop_cell(ms->fdt, aplic_name, "phandle", aplic_phandle);
259
+
260
g_free(aplic_name);
261
+ g_free(aplic_cells);
262
+}
263
264
- /* S-level APLIC node */
265
- for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) {
266
- aplic_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
267
- aplic_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_S_EXT);
268
+static void create_fdt_socket_aplic(RISCVVirtState *s,
269
+ const MemMapEntry *memmap, int socket,
270
+ uint32_t msi_m_phandle,
271
+ uint32_t msi_s_phandle,
272
+ uint32_t *phandle,
273
+ uint32_t *intc_phandles,
274
+ uint32_t *aplic_phandles)
275
+{
276
+ char *aplic_name;
277
+ unsigned long aplic_addr;
278
+ MachineState *ms = MACHINE(s);
279
+ uint32_t aplic_m_phandle, aplic_s_phandle;
280
+
281
+ aplic_m_phandle = (*phandle)++;
282
+ aplic_s_phandle = (*phandle)++;
283
+
284
+ if (!kvm_enabled()) {
285
+ /* M-level APLIC node */
286
+ aplic_addr = memmap[VIRT_APLIC_M].base +
287
+ (memmap[VIRT_APLIC_M].size * socket);
288
+ create_fdt_one_aplic(s, socket, aplic_addr, memmap[VIRT_APLIC_M].size,
289
+ msi_m_phandle, intc_phandles,
290
+ aplic_m_phandle, aplic_s_phandle,
291
+ true);
292
}
293
+
294
+ /* S-level APLIC node */
295
aplic_addr = memmap[VIRT_APLIC_S].base +
296
(memmap[VIRT_APLIC_S].size * socket);
297
+ create_fdt_one_aplic(s, socket, aplic_addr, memmap[VIRT_APLIC_S].size,
298
+ msi_s_phandle, intc_phandles,
299
+ aplic_s_phandle, 0,
300
+ false);
301
+
302
aplic_name = g_strdup_printf("/soc/aplic@%lx", aplic_addr);
303
- qemu_fdt_add_subnode(ms->fdt, aplic_name);
304
- qemu_fdt_setprop_string(ms->fdt, aplic_name, "compatible", "riscv,aplic");
305
- qemu_fdt_setprop_cell(ms->fdt, aplic_name,
306
- "#interrupt-cells", FDT_APLIC_INT_CELLS);
307
- qemu_fdt_setprop(ms->fdt, aplic_name, "interrupt-controller", NULL, 0);
308
- if (s->aia_type == VIRT_AIA_TYPE_APLIC) {
309
- qemu_fdt_setprop(ms->fdt, aplic_name, "interrupts-extended",
310
- aplic_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 2);
311
- } else {
312
- qemu_fdt_setprop_cell(ms->fdt, aplic_name, "msi-parent",
313
- msi_s_phandle);
314
- }
315
- qemu_fdt_setprop_cells(ms->fdt, aplic_name, "reg",
316
- 0x0, aplic_addr, 0x0, memmap[VIRT_APLIC_S].size);
317
- qemu_fdt_setprop_cell(ms->fdt, aplic_name, "riscv,num-sources",
318
- VIRT_IRQCHIP_NUM_SOURCES);
319
- riscv_socket_fdt_write_id(ms, aplic_name, socket);
320
- qemu_fdt_setprop_cell(ms->fdt, aplic_name, "phandle", aplic_s_phandle);
321
322
if (!socket) {
323
platform_bus_add_all_fdt_nodes(ms->fdt, aplic_name,
324
@@ -XXX,XX +XXX,XX @@ static void create_fdt_socket_aplic(RISCVVirtState *s,
325
326
g_free(aplic_name);
327
328
- g_free(aplic_cells);
329
aplic_phandles[socket] = aplic_s_phandle;
183
}
330
}
184
331
185
+static bool virt_get_aclint(Object *obj, Error **errp)
332
@@ -XXX,XX +XXX,XX @@ static DeviceState *virt_create_aia(RISCVVirtAIAType aia_type, int aia_guests,
186
+{
333
int i;
187
+ MachineState *ms = MACHINE(obj);
334
hwaddr addr;
188
+ RISCVVirtState *s = RISCV_VIRT_MACHINE(ms);
335
uint32_t guest_bits;
189
+
336
- DeviceState *aplic_m;
190
+ return s->have_aclint;
337
- bool msimode = (aia_type == VIRT_AIA_TYPE_APLIC_IMSIC) ? true : false;
191
+}
338
+ DeviceState *aplic_s = NULL;
192
+
339
+ DeviceState *aplic_m = NULL;
193
+static void virt_set_aclint(Object *obj, bool value, Error **errp)
340
+ bool msimode = aia_type == VIRT_AIA_TYPE_APLIC_IMSIC;
194
+{
341
195
+ MachineState *ms = MACHINE(obj);
342
if (msimode) {
196
+ RISCVVirtState *s = RISCV_VIRT_MACHINE(ms);
343
- /* Per-socket M-level IMSICs */
197
+
344
- addr = memmap[VIRT_IMSIC_M].base + socket * VIRT_IMSIC_GROUP_MAX_SIZE;
198
+ s->have_aclint = value;
345
- for (i = 0; i < hart_count; i++) {
199
+}
346
- riscv_imsic_create(addr + i * IMSIC_HART_SIZE(0),
200
+
347
- base_hartid + i, true, 1,
201
static void virt_machine_class_init(ObjectClass *oc, void *data)
348
- VIRT_IRQCHIP_NUM_MSIS);
202
{
349
+ if (!kvm_enabled()) {
203
MachineClass *mc = MACHINE_CLASS(oc);
350
+ /* Per-socket M-level IMSICs */
204
@@ -XXX,XX +XXX,XX @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
351
+ addr = memmap[VIRT_IMSIC_M].base +
205
mc->numa_mem_supported = true;
352
+ socket * VIRT_IMSIC_GROUP_MAX_SIZE;
206
353
+ for (i = 0; i < hart_count; i++) {
207
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
354
+ riscv_imsic_create(addr + i * IMSIC_HART_SIZE(0),
208
+
355
+ base_hartid + i, true, 1,
209
+ object_class_property_add_bool(oc, "aclint", virt_get_aclint,
356
+ VIRT_IRQCHIP_NUM_MSIS);
210
+ virt_set_aclint);
357
+ }
211
+ object_class_property_set_description(oc, "aclint",
358
}
212
+ "Set on/off to enable/disable "
359
213
+ "emulating ACLINT devices");
360
/* Per-socket S-level IMSICs */
361
@@ -XXX,XX +XXX,XX @@ static DeviceState *virt_create_aia(RISCVVirtAIAType aia_type, int aia_guests,
362
}
363
}
364
365
- /* Per-socket M-level APLIC */
366
- aplic_m = riscv_aplic_create(
367
- memmap[VIRT_APLIC_M].base + socket * memmap[VIRT_APLIC_M].size,
368
- memmap[VIRT_APLIC_M].size,
369
- (msimode) ? 0 : base_hartid,
370
- (msimode) ? 0 : hart_count,
371
- VIRT_IRQCHIP_NUM_SOURCES,
372
- VIRT_IRQCHIP_NUM_PRIO_BITS,
373
- msimode, true, NULL);
374
-
375
- if (aplic_m) {
376
- /* Per-socket S-level APLIC */
377
- riscv_aplic_create(
378
- memmap[VIRT_APLIC_S].base + socket * memmap[VIRT_APLIC_S].size,
379
- memmap[VIRT_APLIC_S].size,
380
- (msimode) ? 0 : base_hartid,
381
- (msimode) ? 0 : hart_count,
382
- VIRT_IRQCHIP_NUM_SOURCES,
383
- VIRT_IRQCHIP_NUM_PRIO_BITS,
384
- msimode, false, aplic_m);
385
+ if (!kvm_enabled()) {
386
+ /* Per-socket M-level APLIC */
387
+ aplic_m = riscv_aplic_create(memmap[VIRT_APLIC_M].base +
388
+ socket * memmap[VIRT_APLIC_M].size,
389
+ memmap[VIRT_APLIC_M].size,
390
+ (msimode) ? 0 : base_hartid,
391
+ (msimode) ? 0 : hart_count,
392
+ VIRT_IRQCHIP_NUM_SOURCES,
393
+ VIRT_IRQCHIP_NUM_PRIO_BITS,
394
+ msimode, true, NULL);
395
}
396
397
- return aplic_m;
398
+ /* Per-socket S-level APLIC */
399
+ aplic_s = riscv_aplic_create(memmap[VIRT_APLIC_S].base +
400
+ socket * memmap[VIRT_APLIC_S].size,
401
+ memmap[VIRT_APLIC_S].size,
402
+ (msimode) ? 0 : base_hartid,
403
+ (msimode) ? 0 : hart_count,
404
+ VIRT_IRQCHIP_NUM_SOURCES,
405
+ VIRT_IRQCHIP_NUM_PRIO_BITS,
406
+ msimode, false, aplic_m);
407
+
408
+ return kvm_enabled() ? aplic_s : aplic_m;
214
}
409
}
215
410
216
static const TypeInfo virt_machine_typeinfo = {
411
static void create_platform_bus(RISCVVirtState *s, DeviceState *irqchip)
217
--
412
--
218
2.31.1
413
2.41.0
219
220
diff view generated by jsdifflib
New patch
1
From: Yong-Xuan Wang <yongxuan.wang@sifive.com>
1
2
3
We check the in-kernel irqchip support when using KVM acceleration.
4
5
Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com>
6
Reviewed-by: Jim Shu <jim.shu@sifive.com>
7
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
8
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
9
Message-ID: <20230727102439.22554-3-yongxuan.wang@sifive.com>
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
---
12
target/riscv/kvm.c | 10 +++++++++-
13
1 file changed, 9 insertions(+), 1 deletion(-)
14
15
diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/riscv/kvm.c
18
+++ b/target/riscv/kvm.c
19
@@ -XXX,XX +XXX,XX @@ int kvm_arch_init(MachineState *ms, KVMState *s)
20
21
int kvm_arch_irqchip_create(KVMState *s)
22
{
23
- return 0;
24
+ if (kvm_kernel_irqchip_split()) {
25
+ error_report("-machine kernel_irqchip=split is not supported on RISC-V.");
26
+ exit(1);
27
+ }
28
+
29
+ /*
30
+ * We can create the VAIA using the newer device control API.
31
+ */
32
+ return kvm_check_extension(s, KVM_CAP_DEVICE_CTRL);
33
}
34
35
int kvm_arch_process_async_events(CPUState *cs)
36
--
37
2.41.0
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@wdc.com>
1
From: Yong-Xuan Wang <yongxuan.wang@sifive.com>
2
2
3
Connect the SiFive PWM device and expose it via the device tree.
3
We create a vAIA chip by using the KVM_DEV_TYPE_RISCV_AIA and then set up
4
the chip with the KVM_DEV_RISCV_AIA_GRP_* APIs.
5
We also extend KVM accelerator to specify the KVM AIA mode. The "riscv-aia"
6
parameter is passed along with --accel in QEMU command-line.
7
1) "riscv-aia=emul": IMSIC is emulated by hypervisor
8
2) "riscv-aia=hwaccel": use hardware guest IMSIC
9
3) "riscv-aia=auto": use the hardware guest IMSICs whenever available
10
otherwise we fallback to software emulation.
4
11
12
Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com>
13
Reviewed-by: Jim Shu <jim.shu@sifive.com>
14
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
15
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
16
Message-ID: <20230727102439.22554-4-yongxuan.wang@sifive.com>
5
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
17
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
6
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
7
Message-id: 22f98648b4e012f78529a56f5ca60b0b27852a4d.1631159656.git.alistair.francis@wdc.com
8
---
18
---
9
docs/system/riscv/sifive_u.rst | 1 +
19
target/riscv/kvm_riscv.h | 4 +
10
include/hw/riscv/sifive_u.h | 14 ++++++++-
20
target/riscv/kvm.c | 186 +++++++++++++++++++++++++++++++++++++++
11
hw/riscv/sifive_u.c | 55 +++++++++++++++++++++++++++++++++-
21
2 files changed, 190 insertions(+)
12
hw/riscv/Kconfig | 1 +
13
4 files changed, 69 insertions(+), 2 deletions(-)
14
22
15
diff --git a/docs/system/riscv/sifive_u.rst b/docs/system/riscv/sifive_u.rst
23
diff --git a/target/riscv/kvm_riscv.h b/target/riscv/kvm_riscv.h
16
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
17
--- a/docs/system/riscv/sifive_u.rst
25
--- a/target/riscv/kvm_riscv.h
18
+++ b/docs/system/riscv/sifive_u.rst
26
+++ b/target/riscv/kvm_riscv.h
19
@@ -XXX,XX +XXX,XX @@ The ``sifive_u`` machine supports the following devices:
27
@@ -XXX,XX +XXX,XX @@
20
* 2 QSPI controllers
28
void kvm_riscv_init_user_properties(Object *cpu_obj);
21
* 1 ISSI 25WP256 flash
29
void kvm_riscv_reset_vcpu(RISCVCPU *cpu);
22
* 1 SD card in SPI mode
30
void kvm_riscv_set_irq(RISCVCPU *cpu, int irq, int level);
23
+* PWM0 and PWM1
31
+void kvm_riscv_aia_create(MachineState *machine, uint64_t group_shift,
24
32
+ uint64_t aia_irq_num, uint64_t aia_msi_num,
25
Please note the real world HiFive Unleashed board has a fixed configuration of
33
+ uint64_t aplic_base, uint64_t imsic_base,
26
1 E51 core and 4 U54 core combination and the RISC-V core boots in 64-bit mode.
34
+ uint64_t guest_num);
27
diff --git a/include/hw/riscv/sifive_u.h b/include/hw/riscv/sifive_u.h
35
36
#endif
37
diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c
28
index XXXXXXX..XXXXXXX 100644
38
index XXXXXXX..XXXXXXX 100644
29
--- a/include/hw/riscv/sifive_u.h
39
--- a/target/riscv/kvm.c
30
+++ b/include/hw/riscv/sifive_u.h
40
+++ b/target/riscv/kvm.c
31
@@ -XXX,XX +XXX,XX @@
41
@@ -XXX,XX +XXX,XX @@
32
#include "hw/misc/sifive_u_otp.h"
42
#include "exec/address-spaces.h"
33
#include "hw/misc/sifive_u_prci.h"
43
#include "hw/boards.h"
34
#include "hw/ssi/sifive_spi.h"
44
#include "hw/irq.h"
35
+#include "hw/timer/sifive_pwm.h"
45
+#include "hw/intc/riscv_imsic.h"
36
46
#include "qemu/log.h"
37
#define TYPE_RISCV_U_SOC "riscv.sifive.u.soc"
47
#include "hw/loader.h"
38
#define RISCV_U_SOC(obj) \
48
#include "kvm_riscv.h"
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 @@
49
@@ -XXX,XX +XXX,XX @@
78
* 7) DMA (Direct Memory Access Controller)
50
#include "chardev/char-fe.h"
79
* 8) SPI0 connected to an SPI flash
51
#include "migration/migration.h"
80
* 9) SPI2 connected to an SD card
52
#include "sysemu/runstate.h"
81
+ * 10) PWM0 and PWM1
53
+#include "hw/riscv/numa.h"
82
*
54
83
* This board currently generates devicetree dynamically that indicates at least
55
static uint64_t kvm_riscv_reg_id(CPURISCVState *env, uint64_t type,
84
* two harts and up to five harts.
56
uint64_t idx)
85
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry sifive_u_memmap[] = {
57
@@ -XXX,XX +XXX,XX @@ bool kvm_arch_cpu_check_are_resettable(void)
86
[SIFIVE_U_DEV_PRCI] = { 0x10000000, 0x1000 },
58
return true;
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
+
114
+ nodename = g_strdup_printf("/soc/pwm@%lx",
115
+ (long)memmap[SIFIVE_U_DEV_PWM1].base);
116
+ qemu_fdt_add_subnode(fdt, nodename);
117
+ qemu_fdt_setprop_string(fdt, nodename, "compatible", "sifive,pwm0");
118
+ qemu_fdt_setprop_cells(fdt, nodename, "reg",
119
+ 0x0, memmap[SIFIVE_U_DEV_PWM1].base,
120
+ 0x0, memmap[SIFIVE_U_DEV_PWM1].size);
121
+ qemu_fdt_setprop_cell(fdt, nodename, "interrupt-parent", plic_phandle);
122
+ qemu_fdt_setprop_cells(fdt, nodename, "interrupts",
123
+ SIFIVE_U_PWM1_IRQ0, SIFIVE_U_PWM1_IRQ1,
124
+ SIFIVE_U_PWM1_IRQ2, SIFIVE_U_PWM1_IRQ3);
125
+ qemu_fdt_setprop_cells(fdt, nodename, "clocks",
126
+ prci_phandle, PRCI_CLK_TLCLK);
127
+ qemu_fdt_setprop_cell(fdt, nodename, "#pwm-cells", 0);
128
+ g_free(nodename);
129
+
130
nodename = g_strdup_printf("/soc/serial@%lx",
131
(long)memmap[SIFIVE_U_DEV_UART1].base);
132
qemu_fdt_add_subnode(fdt, nodename);
133
@@ -XXX,XX +XXX,XX @@ static void sifive_u_soc_instance_init(Object *obj)
134
object_initialize_child(obj, "pdma", &s->dma, TYPE_SIFIVE_PDMA);
135
object_initialize_child(obj, "spi0", &s->spi0, TYPE_SIFIVE_SPI);
136
object_initialize_child(obj, "spi2", &s->spi2, TYPE_SIFIVE_SPI);
137
+ object_initialize_child(obj, "pwm0", &s->pwm[0], TYPE_SIFIVE_PWM);
138
+ object_initialize_child(obj, "pwm1", &s->pwm[1], TYPE_SIFIVE_PWM);
139
}
59
}
140
60
141
static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
61
+static int aia_mode;
142
@@ -XXX,XX +XXX,XX @@ static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
62
+
143
MemoryRegion *l2lim_mem = g_new(MemoryRegion, 1);
63
+static const char *kvm_aia_mode_str(uint64_t mode)
144
char *plic_hart_config;
64
+{
145
size_t plic_hart_config_len;
65
+ switch (mode) {
146
- int i;
66
+ case KVM_DEV_RISCV_AIA_MODE_EMUL:
147
+ int i, j;
67
+ return "emul";
148
NICInfo *nd = &nd_table[0];
68
+ case KVM_DEV_RISCV_AIA_MODE_HWACCEL:
149
69
+ return "hwaccel";
150
qdev_prop_set_uint32(DEVICE(&s->u_cpus), "num-harts", ms->smp.cpus - 1);
70
+ case KVM_DEV_RISCV_AIA_MODE_AUTO:
151
@@ -XXX,XX +XXX,XX @@ static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
71
+ default:
152
sysbus_connect_irq(SYS_BUS_DEVICE(&s->gem), 0,
72
+ return "auto";
153
qdev_get_gpio_in(DEVICE(s->plic), SIFIVE_U_GEM_IRQ));
73
+ };
154
74
+}
155
+ /* PWM */
75
+
156
+ for (i = 0; i < 2; i++) {
76
+static char *riscv_get_kvm_aia(Object *obj, Error **errp)
157
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->pwm[i]), errp)) {
77
+{
158
+ return;
78
+ return g_strdup(kvm_aia_mode_str(aia_mode));
79
+}
80
+
81
+static void riscv_set_kvm_aia(Object *obj, const char *val, Error **errp)
82
+{
83
+ if (!strcmp(val, "emul")) {
84
+ aia_mode = KVM_DEV_RISCV_AIA_MODE_EMUL;
85
+ } else if (!strcmp(val, "hwaccel")) {
86
+ aia_mode = KVM_DEV_RISCV_AIA_MODE_HWACCEL;
87
+ } else if (!strcmp(val, "auto")) {
88
+ aia_mode = KVM_DEV_RISCV_AIA_MODE_AUTO;
89
+ } else {
90
+ error_setg(errp, "Invalid KVM AIA mode");
91
+ error_append_hint(errp, "Valid values are emul, hwaccel, and auto.\n");
92
+ }
93
+}
94
+
95
void kvm_arch_accel_class_init(ObjectClass *oc)
96
{
97
+ object_class_property_add_str(oc, "riscv-aia", riscv_get_kvm_aia,
98
+ riscv_set_kvm_aia);
99
+ object_class_property_set_description(oc, "riscv-aia",
100
+ "Set KVM AIA mode. Valid values are "
101
+ "emul, hwaccel, and auto. Default "
102
+ "is auto.");
103
+ object_property_set_default_str(object_class_property_find(oc, "riscv-aia"),
104
+ "auto");
105
+}
106
+
107
+void kvm_riscv_aia_create(MachineState *machine, uint64_t group_shift,
108
+ uint64_t aia_irq_num, uint64_t aia_msi_num,
109
+ uint64_t aplic_base, uint64_t imsic_base,
110
+ uint64_t guest_num)
111
+{
112
+ int ret, i;
113
+ int aia_fd = -1;
114
+ uint64_t default_aia_mode;
115
+ uint64_t socket_count = riscv_socket_count(machine);
116
+ uint64_t max_hart_per_socket = 0;
117
+ uint64_t socket, base_hart, hart_count, socket_imsic_base, imsic_addr;
118
+ uint64_t socket_bits, hart_bits, guest_bits;
119
+
120
+ aia_fd = kvm_create_device(kvm_state, KVM_DEV_TYPE_RISCV_AIA, false);
121
+
122
+ if (aia_fd < 0) {
123
+ error_report("Unable to create in-kernel irqchip");
124
+ exit(1);
125
+ }
126
+
127
+ ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
128
+ KVM_DEV_RISCV_AIA_CONFIG_MODE,
129
+ &default_aia_mode, false, NULL);
130
+ if (ret < 0) {
131
+ error_report("KVM AIA: failed to get current KVM AIA mode");
132
+ exit(1);
133
+ }
134
+ qemu_log("KVM AIA: default mode is %s\n",
135
+ kvm_aia_mode_str(default_aia_mode));
136
+
137
+ if (default_aia_mode != aia_mode) {
138
+ ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
139
+ KVM_DEV_RISCV_AIA_CONFIG_MODE,
140
+ &aia_mode, true, NULL);
141
+ if (ret < 0)
142
+ warn_report("KVM AIA: failed to set KVM AIA mode");
143
+ else
144
+ qemu_log("KVM AIA: set current mode to %s\n",
145
+ kvm_aia_mode_str(aia_mode));
146
+ }
147
+
148
+ ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
149
+ KVM_DEV_RISCV_AIA_CONFIG_SRCS,
150
+ &aia_irq_num, true, NULL);
151
+ if (ret < 0) {
152
+ error_report("KVM AIA: failed to set number of input irq lines");
153
+ exit(1);
154
+ }
155
+
156
+ ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
157
+ KVM_DEV_RISCV_AIA_CONFIG_IDS,
158
+ &aia_msi_num, true, NULL);
159
+ if (ret < 0) {
160
+ error_report("KVM AIA: failed to set number of msi");
161
+ exit(1);
162
+ }
163
+
164
+ socket_bits = find_last_bit(&socket_count, BITS_PER_LONG) + 1;
165
+ ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
166
+ KVM_DEV_RISCV_AIA_CONFIG_GROUP_BITS,
167
+ &socket_bits, true, NULL);
168
+ if (ret < 0) {
169
+ error_report("KVM AIA: failed to set group_bits");
170
+ exit(1);
171
+ }
172
+
173
+ ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
174
+ KVM_DEV_RISCV_AIA_CONFIG_GROUP_SHIFT,
175
+ &group_shift, true, NULL);
176
+ if (ret < 0) {
177
+ error_report("KVM AIA: failed to set group_shift");
178
+ exit(1);
179
+ }
180
+
181
+ guest_bits = guest_num == 0 ? 0 :
182
+ find_last_bit(&guest_num, BITS_PER_LONG) + 1;
183
+ ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
184
+ KVM_DEV_RISCV_AIA_CONFIG_GUEST_BITS,
185
+ &guest_bits, true, NULL);
186
+ if (ret < 0) {
187
+ error_report("KVM AIA: failed to set guest_bits");
188
+ exit(1);
189
+ }
190
+
191
+ ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_ADDR,
192
+ KVM_DEV_RISCV_AIA_ADDR_APLIC,
193
+ &aplic_base, true, NULL);
194
+ if (ret < 0) {
195
+ error_report("KVM AIA: failed to set the base address of APLIC");
196
+ exit(1);
197
+ }
198
+
199
+ for (socket = 0; socket < socket_count; socket++) {
200
+ socket_imsic_base = imsic_base + socket * (1U << group_shift);
201
+ hart_count = riscv_socket_hart_count(machine, socket);
202
+ base_hart = riscv_socket_first_hartid(machine, socket);
203
+
204
+ if (max_hart_per_socket < hart_count) {
205
+ max_hart_per_socket = hart_count;
159
+ }
206
+ }
160
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->pwm[i]), 0,
207
+
161
+ memmap[SIFIVE_U_DEV_PWM0].base + (0x1000 * i));
208
+ for (i = 0; i < hart_count; i++) {
162
+
209
+ imsic_addr = socket_imsic_base + i * IMSIC_HART_SIZE(guest_bits);
163
+ /* Connect PWM interrupts to the PLIC */
210
+ ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_ADDR,
164
+ for (j = 0; j < SIFIVE_PWM_IRQS; j++) {
211
+ KVM_DEV_RISCV_AIA_ADDR_IMSIC(i + base_hart),
165
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->pwm[i]), j,
212
+ &imsic_addr, true, NULL);
166
+ qdev_get_gpio_in(DEVICE(s->plic),
213
+ if (ret < 0) {
167
+ SIFIVE_U_PWM0_IRQ0 + (i * 4) + j));
214
+ error_report("KVM AIA: failed to set the IMSIC address for hart %d", i);
215
+ exit(1);
216
+ }
168
+ }
217
+ }
169
+ }
218
+ }
170
+
219
+
171
create_unimplemented_device("riscv.sifive.u.gem-mgmt",
220
+ hart_bits = find_last_bit(&max_hart_per_socket, BITS_PER_LONG) + 1;
172
memmap[SIFIVE_U_DEV_GEM_MGMT].base, memmap[SIFIVE_U_DEV_GEM_MGMT].size);
221
+ ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
173
222
+ KVM_DEV_RISCV_AIA_CONFIG_HART_BITS,
174
diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
223
+ &hart_bits, true, NULL);
175
index XXXXXXX..XXXXXXX 100644
224
+ if (ret < 0) {
176
--- a/hw/riscv/Kconfig
225
+ error_report("KVM AIA: failed to set hart_bits");
177
+++ b/hw/riscv/Kconfig
226
+ exit(1);
178
@@ -XXX,XX +XXX,XX @@ config SIFIVE_U
227
+ }
179
select SIFIVE_UART
228
+
180
select SIFIVE_U_OTP
229
+ if (kvm_has_gsi_routing()) {
181
select SIFIVE_U_PRCI
230
+ for (uint64_t idx = 0; idx < aia_irq_num + 1; ++idx) {
182
+ select SIFIVE_PWM
231
+ /* KVM AIA only has one APLIC instance */
183
select SSI_M25P80
232
+ kvm_irqchip_add_irq_route(kvm_state, idx, 0, idx);
184
select SSI_SD
233
+ }
185
select UNIMP
234
+ kvm_gsi_routing_allowed = true;
235
+ kvm_irqchip_commit_routes(kvm_state);
236
+ }
237
+
238
+ ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CTRL,
239
+ KVM_DEV_RISCV_AIA_CTRL_INIT,
240
+ NULL, true, NULL);
241
+ if (ret < 0) {
242
+ error_report("KVM AIA: initialized fail");
243
+ exit(1);
244
+ }
245
+
246
+ kvm_msi_via_irqfd_allowed = kvm_irqfds_enabled();
247
}
186
--
248
--
187
2.31.1
249
2.41.0
188
189
diff view generated by jsdifflib
1
From: Frank Chang <frank.chang@sifive.com>
1
From: Yong-Xuan Wang <yongxuan.wang@sifive.com>
2
2
3
Setting Control.claim clears all of the chanel's Next registers.
3
KVM AIA can't emulate APLIC only. When "aia=aplic" parameter is passed,
4
This is effective only when Control.claim is set from 0 to 1.
4
APLIC devices is emulated by QEMU. For "aia=aplic-imsic", remove the
5
mmio operations of APLIC when using KVM AIA and send wired interrupt
6
signal via KVM_IRQ_LINE API.
7
After KVM AIA enabled, MSI messages are delivered by KVM_SIGNAL_MSI API
8
when the IMSICs receive mmio write requests.
5
9
6
Signed-off-by: Frank Chang <frank.chang@sifive.com>
10
Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com>
7
Tested-by: Max Hsu <max.hsu@sifive.com>
11
Reviewed-by: Jim Shu <jim.shu@sifive.com>
8
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
12
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
9
Tested-by: Bin Meng <bmeng.cn@gmail.com>
13
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
10
Message-id: 20210912130553.179501-2-frank.chang@sifive.com
14
Message-ID: <20230727102439.22554-5-yongxuan.wang@sifive.com>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
15
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
---
16
---
13
hw/dma/sifive_pdma.c | 19 +++++++++++++++++++
17
hw/intc/riscv_aplic.c | 56 ++++++++++++++++++++++++++++++-------------
14
1 file changed, 19 insertions(+)
18
hw/intc/riscv_imsic.c | 25 +++++++++++++++----
19
2 files changed, 61 insertions(+), 20 deletions(-)
15
20
16
diff --git a/hw/dma/sifive_pdma.c b/hw/dma/sifive_pdma.c
21
diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
17
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/dma/sifive_pdma.c
23
--- a/hw/intc/riscv_aplic.c
19
+++ b/hw/dma/sifive_pdma.c
24
+++ b/hw/intc/riscv_aplic.c
20
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@
21
#define DMA_EXEC_DST 0x110
26
#include "hw/irq.h"
22
#define DMA_EXEC_SRC 0x118
27
#include "target/riscv/cpu.h"
28
#include "sysemu/sysemu.h"
29
+#include "sysemu/kvm.h"
30
#include "migration/vmstate.h"
31
32
#define APLIC_MAX_IDC (1UL << 14)
33
@@ -XXX,XX +XXX,XX @@
34
35
#define APLIC_IDC_CLAIMI 0x1c
23
36
24
+/*
37
+/*
25
+ * FU540/FU740 docs are incorrect with NextConfig.wsize/rsize reset values.
38
+ * KVM AIA only supports APLIC MSI, fallback to QEMU emulation if we want to use
26
+ * The reset values tested on Unleashed/Unmatched boards are 6 instead of 0.
39
+ * APLIC Wired.
27
+ */
40
+ */
28
+#define CONFIG_WRSZ_DEFAULT 6
41
+static bool is_kvm_aia(bool msimode)
29
+#define CONFIG_RDSZ_DEFAULT 6
42
+{
43
+ return kvm_irqchip_in_kernel() && msimode;
44
+}
30
+
45
+
31
enum dma_chan_state {
46
static uint32_t riscv_aplic_read_input_word(RISCVAPLICState *aplic,
32
DMA_CHAN_STATE_IDLE,
47
uint32_t word)
33
DMA_CHAN_STATE_STARTED,
34
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_write(void *opaque, hwaddr offset,
35
{
48
{
36
SiFivePDMAState *s = opaque;
49
@@ -XXX,XX +XXX,XX @@ static uint32_t riscv_aplic_idc_claimi(RISCVAPLICState *aplic, uint32_t idc)
37
int ch = SIFIVE_PDMA_CHAN_NO(offset);
50
return topi;
38
+ bool claimed;
51
}
39
52
40
if (ch >= SIFIVE_PDMA_CHANS) {
53
+static void riscv_kvm_aplic_request(void *opaque, int irq, int level)
41
qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid channel no %d\n",
54
+{
42
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_write(void *opaque, hwaddr offset,
55
+ kvm_set_irq(kvm_state, irq, !!level);
43
offset &= 0xfff;
56
+}
44
switch (offset) {
45
case DMA_CONTROL:
46
+ claimed = !!s->chan[ch].control & CONTROL_CLAIM;
47
+
57
+
48
+ if (!claimed && (value & CONTROL_CLAIM)) {
58
static void riscv_aplic_request(void *opaque, int irq, int level)
49
+ /* reset Next* registers */
59
{
50
+ s->chan[ch].next_config = (CONFIG_RDSZ_DEFAULT << CONFIG_RDSZ_SHIFT) |
60
bool update = false;
51
+ (CONFIG_WRSZ_DEFAULT << CONFIG_WRSZ_SHIFT);
61
@@ -XXX,XX +XXX,XX @@ static void riscv_aplic_realize(DeviceState *dev, Error **errp)
52
+ s->chan[ch].next_bytes = 0;
62
uint32_t i;
53
+ s->chan[ch].next_dst = 0;
63
RISCVAPLICState *aplic = RISCV_APLIC(dev);
54
+ s->chan[ch].next_src = 0;
64
65
- aplic->bitfield_words = (aplic->num_irqs + 31) >> 5;
66
- aplic->sourcecfg = g_new0(uint32_t, aplic->num_irqs);
67
- aplic->state = g_new0(uint32_t, aplic->num_irqs);
68
- aplic->target = g_new0(uint32_t, aplic->num_irqs);
69
- if (!aplic->msimode) {
70
- for (i = 0; i < aplic->num_irqs; i++) {
71
- aplic->target[i] = 1;
72
+ if (!is_kvm_aia(aplic->msimode)) {
73
+ aplic->bitfield_words = (aplic->num_irqs + 31) >> 5;
74
+ aplic->sourcecfg = g_new0(uint32_t, aplic->num_irqs);
75
+ aplic->state = g_new0(uint32_t, aplic->num_irqs);
76
+ aplic->target = g_new0(uint32_t, aplic->num_irqs);
77
+ if (!aplic->msimode) {
78
+ for (i = 0; i < aplic->num_irqs; i++) {
79
+ aplic->target[i] = 1;
80
+ }
81
}
82
- }
83
- aplic->idelivery = g_new0(uint32_t, aplic->num_harts);
84
- aplic->iforce = g_new0(uint32_t, aplic->num_harts);
85
- aplic->ithreshold = g_new0(uint32_t, aplic->num_harts);
86
+ aplic->idelivery = g_new0(uint32_t, aplic->num_harts);
87
+ aplic->iforce = g_new0(uint32_t, aplic->num_harts);
88
+ aplic->ithreshold = g_new0(uint32_t, aplic->num_harts);
89
90
- memory_region_init_io(&aplic->mmio, OBJECT(dev), &riscv_aplic_ops, aplic,
91
- TYPE_RISCV_APLIC, aplic->aperture_size);
92
- sysbus_init_mmio(SYS_BUS_DEVICE(dev), &aplic->mmio);
93
+ memory_region_init_io(&aplic->mmio, OBJECT(dev), &riscv_aplic_ops,
94
+ aplic, TYPE_RISCV_APLIC, aplic->aperture_size);
95
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &aplic->mmio);
96
+ }
97
98
/*
99
* Only root APLICs have hardware IRQ lines. All non-root APLICs
100
* have IRQ lines delegated by their parent APLIC.
101
*/
102
if (!aplic->parent) {
103
- qdev_init_gpio_in(dev, riscv_aplic_request, aplic->num_irqs);
104
+ if (is_kvm_aia(aplic->msimode)) {
105
+ qdev_init_gpio_in(dev, riscv_kvm_aplic_request, aplic->num_irqs);
106
+ } else {
107
+ qdev_init_gpio_in(dev, riscv_aplic_request, aplic->num_irqs);
55
+ }
108
+ }
109
}
110
111
/* Create output IRQ lines for non-MSI mode */
112
@@ -XXX,XX +XXX,XX @@ DeviceState *riscv_aplic_create(hwaddr addr, hwaddr size,
113
qdev_prop_set_bit(dev, "mmode", mmode);
114
115
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
116
- sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
56
+
117
+
57
s->chan[ch].control = value;
118
+ if (!is_kvm_aia(msimode)) {
58
119
+ sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
59
if (value & CONTROL_RUN) {
120
+ }
121
122
if (parent) {
123
riscv_aplic_add_child(parent, dev);
124
diff --git a/hw/intc/riscv_imsic.c b/hw/intc/riscv_imsic.c
125
index XXXXXXX..XXXXXXX 100644
126
--- a/hw/intc/riscv_imsic.c
127
+++ b/hw/intc/riscv_imsic.c
128
@@ -XXX,XX +XXX,XX @@
129
#include "target/riscv/cpu.h"
130
#include "target/riscv/cpu_bits.h"
131
#include "sysemu/sysemu.h"
132
+#include "sysemu/kvm.h"
133
#include "migration/vmstate.h"
134
135
#define IMSIC_MMIO_PAGE_LE 0x00
136
@@ -XXX,XX +XXX,XX @@ static void riscv_imsic_write(void *opaque, hwaddr addr, uint64_t value,
137
goto err;
138
}
139
140
+#if defined(CONFIG_KVM)
141
+ if (kvm_irqchip_in_kernel()) {
142
+ struct kvm_msi msi;
143
+
144
+ msi.address_lo = extract64(imsic->mmio.addr + addr, 0, 32);
145
+ msi.address_hi = extract64(imsic->mmio.addr + addr, 32, 32);
146
+ msi.data = le32_to_cpu(value);
147
+
148
+ kvm_vm_ioctl(kvm_state, KVM_SIGNAL_MSI, &msi);
149
+
150
+ return;
151
+ }
152
+#endif
153
+
154
/* Writes only supported for MSI little-endian registers */
155
page = addr >> IMSIC_MMIO_PAGE_SHIFT;
156
if ((addr & (IMSIC_MMIO_PAGE_SZ - 1)) == IMSIC_MMIO_PAGE_LE) {
157
@@ -XXX,XX +XXX,XX @@ static void riscv_imsic_realize(DeviceState *dev, Error **errp)
158
CPUState *cpu = cpu_by_arch_id(imsic->hartid);
159
CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
160
161
- imsic->num_eistate = imsic->num_pages * imsic->num_irqs;
162
- imsic->eidelivery = g_new0(uint32_t, imsic->num_pages);
163
- imsic->eithreshold = g_new0(uint32_t, imsic->num_pages);
164
- imsic->eistate = g_new0(uint32_t, imsic->num_eistate);
165
+ if (!kvm_irqchip_in_kernel()) {
166
+ imsic->num_eistate = imsic->num_pages * imsic->num_irqs;
167
+ imsic->eidelivery = g_new0(uint32_t, imsic->num_pages);
168
+ imsic->eithreshold = g_new0(uint32_t, imsic->num_pages);
169
+ imsic->eistate = g_new0(uint32_t, imsic->num_eistate);
170
+ }
171
172
memory_region_init_io(&imsic->mmio, OBJECT(dev), &riscv_imsic_ops,
173
imsic, TYPE_RISCV_IMSIC,
60
--
174
--
61
2.31.1
175
2.41.0
62
63
diff view generated by jsdifflib
1
From: Anup Patel <anup.patel@wdc.com>
1
From: Yong-Xuan Wang <yongxuan.wang@sifive.com>
2
2
3
We will be upgrading SiFive CLINT implementation into RISC-V ACLINT
3
Select KVM AIA when the host kernel has in-kernel AIA chip support.
4
implementation so let's first rename the sources.
4
Since KVM AIA only has one APLIC instance, we map the QEMU APLIC
5
devices to KVM APLIC.
5
6
6
Signed-off-by: Anup Patel <anup.patel@wdc.com>
7
Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Reviewed-by: Jim Shu <jim.shu@sifive.com>
8
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
9
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
9
Message-id: 20210831110603.338681-2-anup.patel@wdc.com
10
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
11
Message-ID: <20230727102439.22554-6-yongxuan.wang@sifive.com>
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
---
13
---
12
include/hw/intc/{sifive_clint.h => riscv_aclint.h} | 0
14
hw/riscv/virt.c | 94 +++++++++++++++++++++++++++++++++----------------
13
hw/intc/{sifive_clint.c => riscv_aclint.c} | 2 +-
15
1 file changed, 63 insertions(+), 31 deletions(-)
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
16
27
diff --git a/include/hw/intc/sifive_clint.h b/include/hw/intc/riscv_aclint.h
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
36
--- a/hw/intc/sifive_clint.c
37
+++ b/hw/intc/riscv_aclint.c
38
@@ -XXX,XX +XXX,XX @@
39
#include "hw/sysbus.h"
40
#include "target/riscv/cpu.h"
41
#include "hw/qdev-properties.h"
42
-#include "hw/intc/sifive_clint.h"
43
+#include "hw/intc/riscv_aclint.h"
44
#include "qemu/timer.h"
45
#include "hw/irq.h"
46
47
diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/hw/riscv/microchip_pfsoc.c
50
+++ b/hw/riscv/microchip_pfsoc.c
51
@@ -XXX,XX +XXX,XX @@
52
#include "hw/riscv/boot.h"
53
#include "hw/riscv/riscv_hart.h"
54
#include "hw/riscv/microchip_pfsoc.h"
55
-#include "hw/intc/sifive_clint.h"
56
+#include "hw/intc/riscv_aclint.h"
57
#include "hw/intc/sifive_plic.h"
58
#include "sysemu/device_tree.h"
59
#include "sysemu/sysemu.h"
60
diff --git a/hw/riscv/shakti_c.c b/hw/riscv/shakti_c.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/hw/riscv/shakti_c.c
63
+++ b/hw/riscv/shakti_c.c
64
@@ -XXX,XX +XXX,XX @@
65
#include "hw/riscv/shakti_c.h"
66
#include "qapi/error.h"
67
#include "hw/intc/sifive_plic.h"
68
-#include "hw/intc/sifive_clint.h"
69
+#include "hw/intc/riscv_aclint.h"
70
#include "sysemu/sysemu.h"
71
#include "hw/qdev-properties.h"
72
#include "exec/address-spaces.h"
73
diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/hw/riscv/sifive_e.c
76
+++ b/hw/riscv/sifive_e.c
77
@@ -XXX,XX +XXX,XX @@
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
17
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
113
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
114
--- a/hw/riscv/virt.c
19
--- a/hw/riscv/virt.c
115
+++ b/hw/riscv/virt.c
20
+++ b/hw/riscv/virt.c
116
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@
117
#include "hw/riscv/virt.h"
22
#include "hw/riscv/virt.h"
118
#include "hw/riscv/boot.h"
23
#include "hw/riscv/boot.h"
119
#include "hw/riscv/numa.h"
24
#include "hw/riscv/numa.h"
120
-#include "hw/intc/sifive_clint.h"
25
+#include "kvm_riscv.h"
121
+#include "hw/intc/riscv_aclint.h"
26
#include "hw/intc/riscv_aclint.h"
122
#include "hw/intc/sifive_plic.h"
27
#include "hw/intc/riscv_aplic.h"
123
#include "hw/misc/sifive_test.h"
28
#include "hw/intc/riscv_imsic.h"
124
#include "chardev/char.h"
29
@@ -XXX,XX +XXX,XX @@
125
diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
30
#error "Can't accommodate all IMSIC groups in address space"
126
index XXXXXXX..XXXXXXX 100644
31
#endif
127
--- a/hw/intc/Kconfig
32
128
+++ b/hw/intc/Kconfig
33
+/* KVM AIA only supports APLIC MSI. APLIC Wired is always emulated by QEMU. */
129
@@ -XXX,XX +XXX,XX @@ config RX_ICU
34
+static bool virt_use_kvm_aia(RISCVVirtState *s)
130
config LOONGSON_LIOINTC
35
+{
131
bool
36
+ return kvm_irqchip_in_kernel() && s->aia_type == VIRT_AIA_TYPE_APLIC_IMSIC;
132
37
+}
133
-config SIFIVE_CLINT
38
+
134
+config RISCV_ACLINT
39
static const MemMapEntry virt_memmap[] = {
135
bool
40
[VIRT_DEBUG] = { 0x0, 0x100 },
136
41
[VIRT_MROM] = { 0x1000, 0xf000 },
137
config SIFIVE_PLIC
42
@@ -XXX,XX +XXX,XX @@ static void create_fdt_one_aplic(RISCVVirtState *s, int socket,
138
diff --git a/hw/intc/meson.build b/hw/intc/meson.build
43
uint32_t *intc_phandles,
139
index XXXXXXX..XXXXXXX 100644
44
uint32_t aplic_phandle,
140
--- a/hw/intc/meson.build
45
uint32_t aplic_child_phandle,
141
+++ b/hw/intc/meson.build
46
- bool m_mode)
142
@@ -XXX,XX +XXX,XX @@ specific_ss.add(when: 'CONFIG_RX_ICU', if_true: files('rx_icu.c'))
47
+ bool m_mode, int num_harts)
143
specific_ss.add(when: 'CONFIG_S390_FLIC', if_true: files('s390_flic.c'))
48
{
144
specific_ss.add(when: 'CONFIG_S390_FLIC_KVM', if_true: files('s390_flic_kvm.c'))
49
int cpu;
145
specific_ss.add(when: 'CONFIG_SH_INTC', if_true: files('sh_intc.c'))
50
char *aplic_name;
146
-specific_ss.add(when: 'CONFIG_SIFIVE_CLINT', if_true: files('sifive_clint.c'))
51
uint32_t *aplic_cells;
147
+specific_ss.add(when: 'CONFIG_RISCV_ACLINT', if_true: files('riscv_aclint.c'))
52
MachineState *ms = MACHINE(s);
148
specific_ss.add(when: 'CONFIG_SIFIVE_PLIC', if_true: files('sifive_plic.c'))
53
149
specific_ss.add(when: 'CONFIG_XICS', if_true: files('xics.c'))
54
- aplic_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2);
150
specific_ss.add(when: ['CONFIG_KVM', 'CONFIG_XICS'],
55
+ aplic_cells = g_new0(uint32_t, num_harts * 2);
151
diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
56
152
index XXXXXXX..XXXXXXX 100644
57
- for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) {
153
--- a/hw/riscv/Kconfig
58
+ for (cpu = 0; cpu < num_harts; cpu++) {
154
+++ b/hw/riscv/Kconfig
59
aplic_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
155
@@ -XXX,XX +XXX,XX @@ config MICROCHIP_PFSOC
60
aplic_cells[cpu * 2 + 1] = cpu_to_be32(m_mode ? IRQ_M_EXT : IRQ_S_EXT);
156
select MCHP_PFSOC_MMUART
61
}
157
select MCHP_PFSOC_SYSREG
62
@@ -XXX,XX +XXX,XX @@ static void create_fdt_one_aplic(RISCVVirtState *s, int socket,
158
select MSI_NONBROKEN
63
159
- select SIFIVE_CLINT
64
if (s->aia_type == VIRT_AIA_TYPE_APLIC) {
160
+ select RISCV_ACLINT
65
qemu_fdt_setprop(ms->fdt, aplic_name, "interrupts-extended",
161
select SIFIVE_PDMA
66
- aplic_cells,
162
select SIFIVE_PLIC
67
- s->soc[socket].num_harts * sizeof(uint32_t) * 2);
163
select UNIMP
68
+ aplic_cells, num_harts * sizeof(uint32_t) * 2);
164
@@ -XXX,XX +XXX,XX @@ config SHAKTI_C
69
} else {
165
bool
70
qemu_fdt_setprop_cell(ms->fdt, aplic_name, "msi-parent", msi_phandle);
166
select UNIMP
71
}
167
select SHAKTI_UART
72
@@ -XXX,XX +XXX,XX @@ static void create_fdt_socket_aplic(RISCVVirtState *s,
168
- select SIFIVE_CLINT
73
uint32_t msi_s_phandle,
169
+ select RISCV_ACLINT
74
uint32_t *phandle,
170
select SIFIVE_PLIC
75
uint32_t *intc_phandles,
171
76
- uint32_t *aplic_phandles)
172
config RISCV_VIRT
77
+ uint32_t *aplic_phandles,
173
@@ -XXX,XX +XXX,XX @@ config RISCV_VIRT
78
+ int num_harts)
174
select PCI_EXPRESS_GENERIC_BRIDGE
79
{
175
select PFLASH_CFI01
80
char *aplic_name;
176
select SERIAL
81
unsigned long aplic_addr;
177
- select SIFIVE_CLINT
82
@@ -XXX,XX +XXX,XX @@ static void create_fdt_socket_aplic(RISCVVirtState *s,
178
+ select RISCV_ACLINT
83
create_fdt_one_aplic(s, socket, aplic_addr, memmap[VIRT_APLIC_M].size,
179
select SIFIVE_PLIC
84
msi_m_phandle, intc_phandles,
180
select SIFIVE_TEST
85
aplic_m_phandle, aplic_s_phandle,
181
select VIRTIO_MMIO
86
- true);
182
@@ -XXX,XX +XXX,XX @@ config RISCV_VIRT
87
+ true, num_harts);
183
config SIFIVE_E
88
}
184
bool
89
185
select MSI_NONBROKEN
90
/* S-level APLIC node */
186
- select SIFIVE_CLINT
91
@@ -XXX,XX +XXX,XX @@ static void create_fdt_socket_aplic(RISCVVirtState *s,
187
+ select RISCV_ACLINT
92
create_fdt_one_aplic(s, socket, aplic_addr, memmap[VIRT_APLIC_S].size,
188
select SIFIVE_GPIO
93
msi_s_phandle, intc_phandles,
189
select SIFIVE_PLIC
94
aplic_s_phandle, 0,
190
select SIFIVE_UART
95
- false);
191
@@ -XXX,XX +XXX,XX @@ config SIFIVE_U
96
+ false, num_harts);
192
bool
97
193
select CADENCE
98
aplic_name = g_strdup_printf("/soc/aplic@%lx", aplic_addr);
194
select MSI_NONBROKEN
99
195
- select SIFIVE_CLINT
100
@@ -XXX,XX +XXX,XX @@ static void create_fdt_sockets(RISCVVirtState *s, const MemMapEntry *memmap,
196
+ select RISCV_ACLINT
101
*msi_pcie_phandle = msi_s_phandle;
197
select SIFIVE_GPIO
102
}
198
select SIFIVE_PDMA
103
199
select SIFIVE_PLIC
104
- phandle_pos = ms->smp.cpus;
200
@@ -XXX,XX +XXX,XX @@ config SPIKE
105
- for (socket = (socket_count - 1); socket >= 0; socket--) {
201
select RISCV_NUMA
106
- phandle_pos -= s->soc[socket].num_harts;
202
select HTIF
107
-
203
select MSI_NONBROKEN
108
- if (s->aia_type == VIRT_AIA_TYPE_NONE) {
204
- select SIFIVE_CLINT
109
- create_fdt_socket_plic(s, memmap, socket, phandle,
205
+ select RISCV_ACLINT
110
- &intc_phandles[phandle_pos], xplic_phandles);
206
select SIFIVE_PLIC
111
- } else {
112
- create_fdt_socket_aplic(s, memmap, socket,
113
- msi_m_phandle, msi_s_phandle, phandle,
114
- &intc_phandles[phandle_pos], xplic_phandles);
115
+ /* KVM AIA only has one APLIC instance */
116
+ if (virt_use_kvm_aia(s)) {
117
+ create_fdt_socket_aplic(s, memmap, 0,
118
+ msi_m_phandle, msi_s_phandle, phandle,
119
+ &intc_phandles[0], xplic_phandles,
120
+ ms->smp.cpus);
121
+ } else {
122
+ phandle_pos = ms->smp.cpus;
123
+ for (socket = (socket_count - 1); socket >= 0; socket--) {
124
+ phandle_pos -= s->soc[socket].num_harts;
125
+
126
+ if (s->aia_type == VIRT_AIA_TYPE_NONE) {
127
+ create_fdt_socket_plic(s, memmap, socket, phandle,
128
+ &intc_phandles[phandle_pos],
129
+ xplic_phandles);
130
+ } else {
131
+ create_fdt_socket_aplic(s, memmap, socket,
132
+ msi_m_phandle, msi_s_phandle, phandle,
133
+ &intc_phandles[phandle_pos],
134
+ xplic_phandles,
135
+ s->soc[socket].num_harts);
136
+ }
137
}
138
}
139
140
g_free(intc_phandles);
141
142
- for (socket = 0; socket < socket_count; socket++) {
143
- if (socket == 0) {
144
- *irq_mmio_phandle = xplic_phandles[socket];
145
- *irq_virtio_phandle = xplic_phandles[socket];
146
- *irq_pcie_phandle = xplic_phandles[socket];
147
- }
148
- if (socket == 1) {
149
- *irq_virtio_phandle = xplic_phandles[socket];
150
- *irq_pcie_phandle = xplic_phandles[socket];
151
- }
152
- if (socket == 2) {
153
- *irq_pcie_phandle = xplic_phandles[socket];
154
+ if (virt_use_kvm_aia(s)) {
155
+ *irq_mmio_phandle = xplic_phandles[0];
156
+ *irq_virtio_phandle = xplic_phandles[0];
157
+ *irq_pcie_phandle = xplic_phandles[0];
158
+ } else {
159
+ for (socket = 0; socket < socket_count; socket++) {
160
+ if (socket == 0) {
161
+ *irq_mmio_phandle = xplic_phandles[socket];
162
+ *irq_virtio_phandle = xplic_phandles[socket];
163
+ *irq_pcie_phandle = xplic_phandles[socket];
164
+ }
165
+ if (socket == 1) {
166
+ *irq_virtio_phandle = xplic_phandles[socket];
167
+ *irq_pcie_phandle = xplic_phandles[socket];
168
+ }
169
+ if (socket == 2) {
170
+ *irq_pcie_phandle = xplic_phandles[socket];
171
+ }
172
}
173
}
174
175
@@ -XXX,XX +XXX,XX @@ static void virt_machine_init(MachineState *machine)
176
}
177
}
178
179
+ if (virt_use_kvm_aia(s)) {
180
+ kvm_riscv_aia_create(machine, IMSIC_MMIO_GROUP_MIN_SHIFT,
181
+ VIRT_IRQCHIP_NUM_SOURCES, VIRT_IRQCHIP_NUM_MSIS,
182
+ memmap[VIRT_APLIC_S].base,
183
+ memmap[VIRT_IMSIC_S].base,
184
+ s->aia_guests);
185
+ }
186
+
187
if (riscv_is_32bit(&s->soc[0])) {
188
#if HOST_LONG_BITS == 64
189
/* limit RAM size in a 32-bit system */
207
--
190
--
208
2.31.1
191
2.41.0
209
210
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@wdc.com>
1
From: Conor Dooley <conor.dooley@microchip.com>
2
2
3
Instead of using riscv_cpu_update_mip() let's instead use the new RISC-V
3
On a dtb dumped from the virt machine, dt-validate complains:
4
CPU GPIO lines to set the external MIP bits.
4
soc: pmu: {'riscv,event-to-mhpmcounters': [[1, 1, 524281], [2, 2, 524284], [65561, 65561, 524280], [65563, 65563, 524280], [65569, 65569, 524280]], 'compatible': ['riscv,pmu']} should not be valid under {'type': 'object'}
5
from schema $id: http://devicetree.org/schemas/simple-bus.yaml#
6
That's pretty cryptic, but running the dtb back through dtc produces
7
something a lot more reasonable:
8
Warning (simple_bus_reg): /soc/pmu: missing or empty reg/ranges property
5
9
10
Moving the riscv,pmu node out of the soc bus solves the problem.
11
12
Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
13
Acked-by: Alistair Francis <alistair.francis@wdc.com>
14
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
15
Message-ID: <20230727-groom-decline-2c57ce42841c@spud>
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
hw/riscv/virt.c | 2 +-
14
hw/intc/sifive_plic.c | 30 +++++++++++++++++++++++-------
19
1 file changed, 1 insertion(+), 1 deletion(-)
15
hw/riscv/microchip_pfsoc.c | 2 +-
16
hw/riscv/shakti_c.c | 3 ++-
17
hw/riscv/sifive_e.c | 2 +-
18
hw/riscv/sifive_u.c | 2 +-
19
hw/riscv/virt.c | 2 +-
20
7 files changed, 33 insertions(+), 12 deletions(-)
21
20
22
diff --git a/include/hw/intc/sifive_plic.h b/include/hw/intc/sifive_plic.h
23
index XXXXXXX..XXXXXXX 100644
24
--- a/include/hw/intc/sifive_plic.h
25
+++ b/include/hw/intc/sifive_plic.h
26
@@ -XXX,XX +XXX,XX @@ struct SiFivePLICState {
27
uint32_t context_base;
28
uint32_t context_stride;
29
uint32_t aperture_size;
30
+
31
+ qemu_irq *m_external_irqs;
32
+ qemu_irq *s_external_irqs;
33
};
34
35
DeviceState *sifive_plic_create(hwaddr addr, char *hart_config,
36
+ uint32_t num_harts,
37
uint32_t hartid_base, uint32_t num_sources,
38
uint32_t num_priorities, uint32_t priority_base,
39
uint32_t pending_base, uint32_t enable_base,
40
diff --git a/hw/intc/sifive_plic.c b/hw/intc/sifive_plic.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/intc/sifive_plic.c
43
+++ b/hw/intc/sifive_plic.c
44
@@ -XXX,XX +XXX,XX @@
45
#include "hw/intc/sifive_plic.h"
46
#include "target/riscv/cpu.h"
47
#include "migration/vmstate.h"
48
+#include "hw/irq.h"
49
50
#define RISCV_DEBUG_PLIC 0
51
52
@@ -XXX,XX +XXX,XX @@ static void sifive_plic_update(SiFivePLICState *plic)
53
for (addrid = 0; addrid < plic->num_addrs; addrid++) {
54
uint32_t hartid = plic->addr_config[addrid].hartid;
55
PLICMode mode = plic->addr_config[addrid].mode;
56
- CPUState *cpu = qemu_get_cpu(hartid);
57
- CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
58
- if (!env) {
59
- continue;
60
- }
61
int level = sifive_plic_irqs_pending(plic, addrid);
62
+
63
switch (mode) {
64
case PLICMode_M:
65
- riscv_cpu_update_mip(RISCV_CPU(cpu), MIP_MEIP, BOOL_TO_MASK(level));
66
+ qemu_set_irq(plic->m_external_irqs[hartid - plic->hartid_base], level);
67
break;
68
case PLICMode_S:
69
- riscv_cpu_update_mip(RISCV_CPU(cpu), MIP_SEIP, BOOL_TO_MASK(level));
70
+ qemu_set_irq(plic->s_external_irqs[hartid - plic->hartid_base], level);
71
break;
72
default:
73
break;
74
@@ -XXX,XX +XXX,XX @@ static void sifive_plic_realize(DeviceState *dev, Error **errp)
75
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &plic->mmio);
76
qdev_init_gpio_in(dev, sifive_plic_irq_request, plic->num_sources);
77
78
+ plic->s_external_irqs = g_malloc(sizeof(qemu_irq) * plic->num_harts);
79
+ qdev_init_gpio_out(dev, plic->s_external_irqs, plic->num_harts);
80
+
81
+ plic->m_external_irqs = g_malloc(sizeof(qemu_irq) * plic->num_harts);
82
+ qdev_init_gpio_out(dev, plic->m_external_irqs, plic->num_harts);
83
+
84
/* We can't allow the supervisor to control SEIP as this would allow the
85
* supervisor to clear a pending external interrupt which will result in
86
* lost a interrupt in the case a PLIC is attached. The SEIP bit must be
87
@@ -XXX,XX +XXX,XX @@ type_init(sifive_plic_register_types)
88
* Create PLIC device.
89
*/
90
DeviceState *sifive_plic_create(hwaddr addr, char *hart_config,
91
+ uint32_t num_harts,
92
uint32_t hartid_base, uint32_t num_sources,
93
uint32_t num_priorities, uint32_t priority_base,
94
uint32_t pending_base, uint32_t enable_base,
95
@@ -XXX,XX +XXX,XX @@ DeviceState *sifive_plic_create(hwaddr addr, char *hart_config,
96
uint32_t context_stride, uint32_t aperture_size)
97
{
98
DeviceState *dev = qdev_new(TYPE_SIFIVE_PLIC);
99
+ int i;
100
+
101
assert(enable_stride == (enable_stride & -enable_stride));
102
assert(context_stride == (context_stride & -context_stride));
103
qdev_prop_set_string(dev, "hart-config", hart_config);
104
@@ -XXX,XX +XXX,XX @@ DeviceState *sifive_plic_create(hwaddr addr, char *hart_config,
105
qdev_prop_set_uint32(dev, "aperture-size", aperture_size);
106
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
107
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
108
+
109
+ for (i = 0; i < num_harts; i++) {
110
+ CPUState *cpu = qemu_get_cpu(hartid_base + i);
111
+
112
+ qdev_connect_gpio_out(dev, i,
113
+ qdev_get_gpio_in(DEVICE(cpu), IRQ_S_EXT));
114
+ qdev_connect_gpio_out(dev, num_harts + i,
115
+ qdev_get_gpio_in(DEVICE(cpu), IRQ_M_EXT));
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
21
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
180
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
181
--- a/hw/riscv/virt.c
23
--- a/hw/riscv/virt.c
182
+++ b/hw/riscv/virt.c
24
+++ b/hw/riscv/virt.c
183
@@ -XXX,XX +XXX,XX @@ static void virt_machine_init(MachineState *machine)
25
@@ -XXX,XX +XXX,XX @@ static void create_fdt_pmu(RISCVVirtState *s)
184
/* Per-socket PLIC */
26
MachineState *ms = MACHINE(s);
185
s->plic[i] = sifive_plic_create(
27
RISCVCPU hart = s->soc[0].harts[0];
186
memmap[VIRT_PLIC].base + i * memmap[VIRT_PLIC].size,
28
187
- plic_hart_config, base_hartid,
29
- pmu_name = g_strdup_printf("/soc/pmu");
188
+ plic_hart_config, hart_count, base_hartid,
30
+ pmu_name = g_strdup_printf("/pmu");
189
VIRT_PLIC_NUM_SOURCES,
31
qemu_fdt_add_subnode(ms->fdt, pmu_name);
190
VIRT_PLIC_NUM_PRIORITIES,
32
qemu_fdt_setprop_string(ms->fdt, pmu_name, "compatible", "riscv,pmu");
191
VIRT_PLIC_PRIORITY_BASE,
33
riscv_pmu_generate_fdt_node(ms->fdt, hart.cfg.pmu_num, pmu_name);
192
--
34
--
193
2.31.1
35
2.41.0
194
195
diff view generated by jsdifflib
1
From: Bin Meng <bmeng.cn@gmail.com>
1
From: Weiwei Li <liweiwei@iscas.ac.cn>
2
2
3
The macro name HCOUNTEREN_CY suggests it is for CSR HCOUNTEREN, but
3
The Svadu specification updated the name of the *envcfg bit from
4
in fact it applies to M-mode and S-mode CSR too. Rename these macros
4
HADE to ADUE.
5
to have the COUNTEREN_ prefix.
6
5
7
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
6
Signed-off-by: Weiwei Li <liweiwei@iscas.ac.cn>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
7
Signed-off-by: Junqiang Wang <wangjunqiang@iscas.ac.cn>
9
Message-id: 20210915084601.24304-1-bmeng.cn@gmail.com
8
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
9
Message-ID: <20230816141916.66898-1-liweiwei@iscas.ac.cn>
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
11
---
11
---
12
target/riscv/cpu_bits.h | 8 ++++----
12
target/riscv/cpu_bits.h | 8 ++++----
13
target/riscv/csr.c | 24 ++++++++++++------------
13
target/riscv/cpu.c | 4 ++--
14
2 files changed, 16 insertions(+), 16 deletions(-)
14
target/riscv/cpu_helper.c | 6 +++---
15
target/riscv/csr.c | 12 ++++++------
16
4 files changed, 15 insertions(+), 15 deletions(-)
15
17
16
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
18
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
17
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
18
--- a/target/riscv/cpu_bits.h
20
--- a/target/riscv/cpu_bits.h
19
+++ b/target/riscv/cpu_bits.h
21
+++ b/target/riscv/cpu_bits.h
20
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ typedef enum RISCVException {
21
#define HSTATUS32_WPRI 0xFF8FF87E
23
#define MENVCFG_CBIE (3UL << 4)
22
#define HSTATUS64_WPRI 0xFFFFFFFFFF8FF87EULL
24
#define MENVCFG_CBCFE BIT(6)
23
25
#define MENVCFG_CBZE BIT(7)
24
-#define HCOUNTEREN_CY (1 << 0)
26
-#define MENVCFG_HADE (1ULL << 61)
25
-#define HCOUNTEREN_TM (1 << 1)
27
+#define MENVCFG_ADUE (1ULL << 61)
26
-#define HCOUNTEREN_IR (1 << 2)
28
#define MENVCFG_PBMTE (1ULL << 62)
27
-#define HCOUNTEREN_HPM3 (1 << 3)
29
#define MENVCFG_STCE (1ULL << 63)
28
+#define COUNTEREN_CY (1 << 0)
30
29
+#define COUNTEREN_TM (1 << 1)
31
/* For RV32 */
30
+#define COUNTEREN_IR (1 << 2)
32
-#define MENVCFGH_HADE BIT(29)
31
+#define COUNTEREN_HPM3 (1 << 3)
33
+#define MENVCFGH_ADUE BIT(29)
32
34
#define MENVCFGH_PBMTE BIT(30)
33
/* Privilege modes */
35
#define MENVCFGH_STCE BIT(31)
34
#define PRV_U 0
36
37
@@ -XXX,XX +XXX,XX @@ typedef enum RISCVException {
38
#define HENVCFG_CBIE MENVCFG_CBIE
39
#define HENVCFG_CBCFE MENVCFG_CBCFE
40
#define HENVCFG_CBZE MENVCFG_CBZE
41
-#define HENVCFG_HADE MENVCFG_HADE
42
+#define HENVCFG_ADUE MENVCFG_ADUE
43
#define HENVCFG_PBMTE MENVCFG_PBMTE
44
#define HENVCFG_STCE MENVCFG_STCE
45
46
/* For RV32 */
47
-#define HENVCFGH_HADE MENVCFGH_HADE
48
+#define HENVCFGH_ADUE MENVCFGH_ADUE
49
#define HENVCFGH_PBMTE MENVCFGH_PBMTE
50
#define HENVCFGH_STCE MENVCFGH_STCE
51
52
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/target/riscv/cpu.c
55
+++ b/target/riscv/cpu.c
56
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_reset_hold(Object *obj)
57
env->two_stage_lookup = false;
58
59
env->menvcfg = (cpu->cfg.ext_svpbmt ? MENVCFG_PBMTE : 0) |
60
- (cpu->cfg.ext_svadu ? MENVCFG_HADE : 0);
61
+ (cpu->cfg.ext_svadu ? MENVCFG_ADUE : 0);
62
env->henvcfg = (cpu->cfg.ext_svpbmt ? HENVCFG_PBMTE : 0) |
63
- (cpu->cfg.ext_svadu ? HENVCFG_HADE : 0);
64
+ (cpu->cfg.ext_svadu ? HENVCFG_ADUE : 0);
65
66
/* Initialized default priorities of local interrupts. */
67
for (i = 0; i < ARRAY_SIZE(env->miprio); i++) {
68
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
69
index XXXXXXX..XXXXXXX 100644
70
--- a/target/riscv/cpu_helper.c
71
+++ b/target/riscv/cpu_helper.c
72
@@ -XXX,XX +XXX,XX @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
73
}
74
75
bool pbmte = env->menvcfg & MENVCFG_PBMTE;
76
- bool hade = env->menvcfg & MENVCFG_HADE;
77
+ bool adue = env->menvcfg & MENVCFG_ADUE;
78
79
if (first_stage && two_stage && env->virt_enabled) {
80
pbmte = pbmte && (env->henvcfg & HENVCFG_PBMTE);
81
- hade = hade && (env->henvcfg & HENVCFG_HADE);
82
+ adue = adue && (env->henvcfg & HENVCFG_ADUE);
83
}
84
85
int ptshift = (levels - 1) * ptidxbits;
86
@@ -XXX,XX +XXX,XX @@ restart:
87
88
/* Page table updates need to be atomic with MTTCG enabled */
89
if (updated_pte != pte && !is_debug) {
90
- if (!hade) {
91
+ if (!adue) {
92
return TRANSLATE_FAIL;
93
}
94
35
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
95
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
36
index XXXXXXX..XXXXXXX 100644
96
index XXXXXXX..XXXXXXX 100644
37
--- a/target/riscv/csr.c
97
--- a/target/riscv/csr.c
38
+++ b/target/riscv/csr.c
98
+++ b/target/riscv/csr.c
39
@@ -XXX,XX +XXX,XX @@ static RISCVException ctr(CPURISCVState *env, int csrno)
99
@@ -XXX,XX +XXX,XX @@ static RISCVException write_menvcfg(CPURISCVState *env, int csrno,
40
if (riscv_cpu_virt_enabled(env)) {
100
if (riscv_cpu_mxl(env) == MXL_RV64) {
41
switch (csrno) {
101
mask |= (cfg->ext_svpbmt ? MENVCFG_PBMTE : 0) |
42
case CSR_CYCLE:
102
(cfg->ext_sstc ? MENVCFG_STCE : 0) |
43
- if (!get_field(env->hcounteren, HCOUNTEREN_CY) &&
103
- (cfg->ext_svadu ? MENVCFG_HADE : 0);
44
- get_field(env->mcounteren, HCOUNTEREN_CY)) {
104
+ (cfg->ext_svadu ? MENVCFG_ADUE : 0);
45
+ if (!get_field(env->hcounteren, COUNTEREN_CY) &&
105
}
46
+ get_field(env->mcounteren, COUNTEREN_CY)) {
106
env->menvcfg = (env->menvcfg & ~mask) | (val & mask);
47
return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
107
48
}
108
@@ -XXX,XX +XXX,XX @@ static RISCVException write_menvcfgh(CPURISCVState *env, int csrno,
49
break;
109
const RISCVCPUConfig *cfg = riscv_cpu_cfg(env);
50
case CSR_TIME:
110
uint64_t mask = (cfg->ext_svpbmt ? MENVCFG_PBMTE : 0) |
51
- if (!get_field(env->hcounteren, HCOUNTEREN_TM) &&
111
(cfg->ext_sstc ? MENVCFG_STCE : 0) |
52
- get_field(env->mcounteren, HCOUNTEREN_TM)) {
112
- (cfg->ext_svadu ? MENVCFG_HADE : 0);
53
+ if (!get_field(env->hcounteren, COUNTEREN_TM) &&
113
+ (cfg->ext_svadu ? MENVCFG_ADUE : 0);
54
+ get_field(env->mcounteren, COUNTEREN_TM)) {
114
uint64_t valh = (uint64_t)val << 32;
55
return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
115
56
}
116
env->menvcfg = (env->menvcfg & ~mask) | (valh & mask);
57
break;
117
@@ -XXX,XX +XXX,XX @@ static RISCVException read_henvcfg(CPURISCVState *env, int csrno,
58
case CSR_INSTRET:
118
* henvcfg.stce is read_only 0 when menvcfg.stce = 0
59
- if (!get_field(env->hcounteren, HCOUNTEREN_IR) &&
119
* henvcfg.hade is read_only 0 when menvcfg.hade = 0
60
- get_field(env->mcounteren, HCOUNTEREN_IR)) {
120
*/
61
+ if (!get_field(env->hcounteren, COUNTEREN_IR) &&
121
- *val = env->henvcfg & (~(HENVCFG_PBMTE | HENVCFG_STCE | HENVCFG_HADE) |
62
+ get_field(env->mcounteren, COUNTEREN_IR)) {
122
+ *val = env->henvcfg & (~(HENVCFG_PBMTE | HENVCFG_STCE | HENVCFG_ADUE) |
63
return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
123
env->menvcfg);
64
}
124
return RISCV_EXCP_NONE;
65
break;
125
}
66
@@ -XXX,XX +XXX,XX @@ static RISCVException ctr(CPURISCVState *env, int csrno)
126
@@ -XXX,XX +XXX,XX @@ static RISCVException write_henvcfg(CPURISCVState *env, int csrno,
67
if (riscv_cpu_is_32bit(env)) {
127
}
68
switch (csrno) {
128
69
case CSR_CYCLEH:
129
if (riscv_cpu_mxl(env) == MXL_RV64) {
70
- if (!get_field(env->hcounteren, HCOUNTEREN_CY) &&
130
- mask |= env->menvcfg & (HENVCFG_PBMTE | HENVCFG_STCE | HENVCFG_HADE);
71
- get_field(env->mcounteren, HCOUNTEREN_CY)) {
131
+ mask |= env->menvcfg & (HENVCFG_PBMTE | HENVCFG_STCE | HENVCFG_ADUE);
72
+ if (!get_field(env->hcounteren, COUNTEREN_CY) &&
132
}
73
+ get_field(env->mcounteren, COUNTEREN_CY)) {
133
74
return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
134
env->henvcfg = (env->henvcfg & ~mask) | (val & mask);
75
}
135
@@ -XXX,XX +XXX,XX @@ static RISCVException read_henvcfgh(CPURISCVState *env, int csrno,
76
break;
136
return ret;
77
case CSR_TIMEH:
137
}
78
- if (!get_field(env->hcounteren, HCOUNTEREN_TM) &&
138
79
- get_field(env->mcounteren, HCOUNTEREN_TM)) {
139
- *val = (env->henvcfg & (~(HENVCFG_PBMTE | HENVCFG_STCE | HENVCFG_HADE) |
80
+ if (!get_field(env->hcounteren, COUNTEREN_TM) &&
140
+ *val = (env->henvcfg & (~(HENVCFG_PBMTE | HENVCFG_STCE | HENVCFG_ADUE) |
81
+ get_field(env->mcounteren, COUNTEREN_TM)) {
141
env->menvcfg)) >> 32;
82
return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
142
return RISCV_EXCP_NONE;
83
}
143
}
84
break;
144
@@ -XXX,XX +XXX,XX @@ static RISCVException write_henvcfgh(CPURISCVState *env, int csrno,
85
case CSR_INSTRETH:
145
target_ulong val)
86
- if (!get_field(env->hcounteren, HCOUNTEREN_IR) &&
146
{
87
- get_field(env->mcounteren, HCOUNTEREN_IR)) {
147
uint64_t mask = env->menvcfg & (HENVCFG_PBMTE | HENVCFG_STCE |
88
+ if (!get_field(env->hcounteren, COUNTEREN_IR) &&
148
- HENVCFG_HADE);
89
+ get_field(env->mcounteren, COUNTEREN_IR)) {
149
+ HENVCFG_ADUE);
90
return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
150
uint64_t valh = (uint64_t)val << 32;
91
}
151
RISCVException ret;
92
break;
152
93
--
153
--
94
2.31.1
154
2.41.0
95
96
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@wdc.com>
1
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
2
2
3
Update the ePMP CSRs to match the 0.9.3 ePMP spec
3
In the same emulated RISC-V host, the 'host' KVM CPU takes 4 times
4
https://github.com/riscv/riscv-tee/blob/61455747230a26002d741f64879dd78cc9689323/Smepmp/Smepmp.pdf
4
longer to boot than the 'rv64' KVM CPU.
5
5
6
The reason is an unintended behavior of riscv_cpu_satp_mode_finalize()
7
when satp_mode.supported = 0, i.e. when cpu_init() does not set
8
satp_mode_max_supported(). satp_mode_max_from_map(map) does:
9
10
31 - __builtin_clz(map)
11
12
This means that, if satp_mode.supported = 0, satp_mode_supported_max
13
wil be '31 - 32'. But this is C, so satp_mode_supported_max will gladly
14
set it to UINT_MAX (4294967295). After that, if the user didn't set a
15
satp_mode, set_satp_mode_default_map(cpu) will make
16
17
cfg.satp_mode.map = cfg.satp_mode.supported
18
19
So satp_mode.map = 0. And then satp_mode_map_max will be set to
20
satp_mode_max_from_map(cpu->cfg.satp_mode.map), i.e. also UINT_MAX. The
21
guard "satp_mode_map_max > satp_mode_supported_max" doesn't protect us
22
here since both are UINT_MAX.
23
24
And finally we have 2 loops:
25
26
for (int i = satp_mode_map_max - 1; i >= 0; --i) {
27
28
Which are, in fact, 2 loops from UINT_MAX -1 to -1. This is where the
29
extra delay when booting the 'host' CPU is coming from.
30
31
Commit 43d1de32f8 already set a precedence for satp_mode.supported = 0
32
in a different manner. We're doing the same here. If supported == 0,
33
interpret as 'the CPU wants the OS to handle satp mode alone' and skip
34
satp_mode_finalize().
35
36
We'll also put a guard in satp_mode_max_from_map() to assert out if map
37
is 0 since the function is not ready to deal with it.
38
39
Cc: Alexandre Ghiti <alexghiti@rivosinc.com>
40
Fixes: 6f23aaeb9b ("riscv: Allow user to set the satp mode")
41
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
42
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
43
Message-ID: <20230817152903.694926-1-dbarboza@ventanamicro.com>
6
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
44
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
---
45
---
10
target/riscv/cpu_bits.h | 4 ++--
46
target/riscv/cpu.c | 23 ++++++++++++++++++++---
11
target/riscv/cpu.c | 1 +
47
1 file changed, 20 insertions(+), 3 deletions(-)
12
2 files changed, 3 insertions(+), 2 deletions(-)
13
48
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
49
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
30
index XXXXXXX..XXXXXXX 100644
50
index XXXXXXX..XXXXXXX 100644
31
--- a/target/riscv/cpu.c
51
--- a/target/riscv/cpu.c
32
+++ b/target/riscv/cpu.c
52
+++ b/target/riscv/cpu.c
33
@@ -XXX,XX +XXX,XX @@ static Property riscv_cpu_properties[] = {
53
@@ -XXX,XX +XXX,XX @@ static uint8_t satp_mode_from_str(const char *satp_mode_str)
34
DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
54
35
DEFINE_PROP_BOOL("mmu", RISCVCPU, cfg.mmu, true),
55
uint8_t satp_mode_max_from_map(uint32_t map)
36
DEFINE_PROP_BOOL("pmp", RISCVCPU, cfg.pmp, true),
56
{
37
+ /* ePMP 0.9.3 */
57
+ /*
38
DEFINE_PROP_BOOL("x-epmp", RISCVCPU, cfg.epmp, false),
58
+ * 'map = 0' will make us return (31 - 32), which C will
39
59
+ * happily overflow to UINT_MAX. There's no good result to
40
DEFINE_PROP_UINT64("resetvec", RISCVCPU, cfg.resetvec, DEFAULT_RSTVEC),
60
+ * return if 'map = 0' (e.g. returning 0 will be ambiguous
61
+ * with the result for 'map = 1').
62
+ *
63
+ * Assert out if map = 0. Callers will have to deal with
64
+ * it outside of this function.
65
+ */
66
+ g_assert(map > 0);
67
+
68
/* map here has at least one bit set, so no problem with clz */
69
return 31 - __builtin_clz(map);
70
}
71
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
72
static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp)
73
{
74
bool rv32 = riscv_cpu_mxl(&cpu->env) == MXL_RV32;
75
- uint8_t satp_mode_map_max;
76
- uint8_t satp_mode_supported_max =
77
- satp_mode_max_from_map(cpu->cfg.satp_mode.supported);
78
+ uint8_t satp_mode_map_max, satp_mode_supported_max;
79
+
80
+ /* The CPU wants the OS to decide which satp mode to use */
81
+ if (cpu->cfg.satp_mode.supported == 0) {
82
+ return;
83
+ }
84
+
85
+ satp_mode_supported_max =
86
+ satp_mode_max_from_map(cpu->cfg.satp_mode.supported);
87
88
if (cpu->cfg.satp_mode.map == 0) {
89
if (cpu->cfg.satp_mode.init == 0) {
41
--
90
--
42
2.31.1
91
2.41.0
43
44
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@wdc.com>
1
From: Vineet Gupta <vineetg@rivosinc.com>
2
2
3
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
3
zicond is now codegen supported in both llvm and gcc.
4
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
4
5
Message-id: d6cb4dfe75a2f536f217d7075b750ece3acb1535.1631767043.git.alistair.francis@wdc.com
5
This change allows seamless enabling/testing of zicond in downstream
6
projects. e.g. currently riscv-gnu-toolchain parses elf attributes
7
to create a cmdline for qemu but fails short of enabling it because of
8
the "x-" prefix.
9
10
Signed-off-by: Vineet Gupta <vineetg@rivosinc.com>
11
Message-ID: <20230808181715.436395-1-vineetg@rivosinc.com>
12
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
6
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
13
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
7
---
14
---
8
hw/riscv/opentitan.c | 2 +-
15
target/riscv/cpu.c | 2 +-
9
1 file changed, 1 insertion(+), 1 deletion(-)
16
1 file changed, 1 insertion(+), 1 deletion(-)
10
17
11
diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c
18
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
12
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/riscv/opentitan.c
20
--- a/target/riscv/cpu.c
14
+++ b/hw/riscv/opentitan.c
21
+++ b/target/riscv/cpu.c
15
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry ibex_memmap[] = {
22
@@ -XXX,XX +XXX,XX @@ static Property riscv_cpu_extensions[] = {
16
[IBEX_DEV_TIMER] = { 0x40100000, 0x1000 },
23
DEFINE_PROP_BOOL("zcf", RISCVCPU, cfg.ext_zcf, false),
17
[IBEX_DEV_SENSOR_CTRL] = { 0x40110000, 0x1000 },
24
DEFINE_PROP_BOOL("zcmp", RISCVCPU, cfg.ext_zcmp, false),
18
[IBEX_DEV_OTP_CTRL] = { 0x40130000, 0x4000 },
25
DEFINE_PROP_BOOL("zcmt", RISCVCPU, cfg.ext_zcmt, false),
19
+ [IBEX_DEV_USBDEV] = { 0x40150000, 0x1000 },
26
+ DEFINE_PROP_BOOL("zicond", RISCVCPU, cfg.ext_zicond, false),
20
[IBEX_DEV_PWRMGR] = { 0x40400000, 0x1000 },
27
21
[IBEX_DEV_RSTMGR] = { 0x40410000, 0x1000 },
28
/* Vendor-specific custom extensions */
22
[IBEX_DEV_CLKMGR] = { 0x40420000, 0x1000 },
29
DEFINE_PROP_BOOL("xtheadba", RISCVCPU, cfg.ext_xtheadba, false),
23
[IBEX_DEV_PINMUX] = { 0x40460000, 0x1000 },
30
@@ -XXX,XX +XXX,XX @@ static Property riscv_cpu_extensions[] = {
24
[IBEX_DEV_PADCTRL] = { 0x40470000, 0x1000 },
31
DEFINE_PROP_BOOL("xventanacondops", RISCVCPU, cfg.ext_XVentanaCondOps, false),
25
- [IBEX_DEV_USBDEV] = { 0x40500000, 0x1000 },
32
26
[IBEX_DEV_FLASH_CTRL] = { 0x41000000, 0x1000 },
33
/* These are experimental so mark with 'x-' */
27
[IBEX_DEV_PLIC] = { 0x41010000, 0x1000 },
34
- DEFINE_PROP_BOOL("x-zicond", RISCVCPU, cfg.ext_zicond, false),
28
[IBEX_DEV_AES] = { 0x41100000, 0x1000 },
35
36
/* ePMP 0.9.3 */
37
DEFINE_PROP_BOOL("x-epmp", RISCVCPU, cfg.epmp, false),
29
--
38
--
30
2.31.1
39
2.41.0
31
32
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
A build with --enable-debug and without KVM will fail as follows:
4
so that it is easier to modify FDT generation for different
5
configurations of virt machine.
6
4
7
Signed-off-by: Anup Patel <anup.patel@wdc.com>
5
/usr/bin/ld: libqemu-riscv64-softmmu.fa.p/hw_riscv_virt.c.o: in function `virt_machine_init':
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
6
./qemu/build/../hw/riscv/virt.c:1465: undefined reference to `kvm_riscv_aia_create'
9
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
7
10
Message-id: 20210831110603.338681-4-anup.patel@wdc.com
8
This happens because the code block with "if virt_use_kvm_aia(s)" isn't
9
being ignored by the debug build, resulting in an undefined reference to
10
a KVM only function.
11
12
Add a 'kvm_enabled()' conditional together with virt_use_kvm_aia() will
13
make the compiler crop the kvm_riscv_aia_create() call entirely from a
14
non-KVM build. Note that adding the 'kvm_enabled()' conditional inside
15
virt_use_kvm_aia() won't fix the build because this function would need
16
to be inlined multiple times to make the compiler zero out the entire
17
block.
18
19
While we're at it, use kvm_enabled() in all instances where
20
virt_use_kvm_aia() is checked to allow the compiler to elide these other
21
kvm-only instances as well.
22
23
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
24
Fixes: dbdb99948e ("target/riscv: select KVM AIA in riscv virt machine")
25
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
26
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
27
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
28
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
29
Message-ID: <20230830133503.711138-2-dbarboza@ventanamicro.com>
11
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
30
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
12
---
31
---
13
hw/riscv/virt.c | 527 ++++++++++++++++++++++++++++++------------------
32
hw/riscv/virt.c | 6 +++---
14
1 file changed, 327 insertions(+), 200 deletions(-)
33
1 file changed, 3 insertions(+), 3 deletions(-)
15
34
16
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
35
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
17
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/riscv/virt.c
37
--- a/hw/riscv/virt.c
19
+++ b/hw/riscv/virt.c
38
+++ b/hw/riscv/virt.c
20
@@ -XXX,XX +XXX,XX @@ static void create_pcie_irq_map(void *fdt, char *nodename,
39
@@ -XXX,XX +XXX,XX @@ static void create_fdt_sockets(RISCVVirtState *s, const MemMapEntry *memmap,
21
0x1800, 0, 0, 0x7);
22
}
23
24
-static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap,
25
- uint64_t mem_size, const char *cmdline, bool is_32_bit)
26
+static void create_fdt_socket_cpus(RISCVVirtState *s, int socket,
27
+ char *clust_name, uint32_t *phandle,
28
+ bool is_32_bit, uint32_t *intc_phandles)
29
{
30
- void *fdt;
31
- int i, cpu, socket;
32
+ int cpu;
33
+ uint32_t cpu_phandle;
34
MachineState *mc = MACHINE(s);
35
+ char *name, *cpu_name, *core_name, *intc_name;
36
+
37
+ for (cpu = s->soc[socket].num_harts - 1; cpu >= 0; cpu--) {
38
+ cpu_phandle = (*phandle)++;
39
+
40
+ cpu_name = g_strdup_printf("/cpus/cpu@%d",
41
+ s->soc[socket].hartid_base + cpu);
42
+ qemu_fdt_add_subnode(mc->fdt, cpu_name);
43
+ qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
44
+ (is_32_bit) ? "riscv,sv32" : "riscv,sv48");
45
+ name = riscv_isa_string(&s->soc[socket].harts[cpu]);
46
+ qemu_fdt_setprop_string(mc->fdt, cpu_name, "riscv,isa", name);
47
+ g_free(name);
48
+ qemu_fdt_setprop_string(mc->fdt, cpu_name, "compatible", "riscv");
49
+ qemu_fdt_setprop_string(mc->fdt, cpu_name, "status", "okay");
50
+ qemu_fdt_setprop_cell(mc->fdt, cpu_name, "reg",
51
+ s->soc[socket].hartid_base + cpu);
52
+ qemu_fdt_setprop_string(mc->fdt, cpu_name, "device_type", "cpu");
53
+ riscv_socket_fdt_write_id(mc, mc->fdt, cpu_name, socket);
54
+ qemu_fdt_setprop_cell(mc->fdt, cpu_name, "phandle", cpu_phandle);
55
+
56
+ intc_phandles[cpu] = (*phandle)++;
57
+
58
+ intc_name = g_strdup_printf("%s/interrupt-controller", cpu_name);
59
+ qemu_fdt_add_subnode(mc->fdt, intc_name);
60
+ qemu_fdt_setprop_cell(mc->fdt, intc_name, "phandle",
61
+ intc_phandles[cpu]);
62
+ qemu_fdt_setprop_string(mc->fdt, intc_name, "compatible",
63
+ "riscv,cpu-intc");
64
+ qemu_fdt_setprop(mc->fdt, intc_name, "interrupt-controller", NULL, 0);
65
+ qemu_fdt_setprop_cell(mc->fdt, intc_name, "#interrupt-cells", 1);
66
+
67
+ core_name = g_strdup_printf("%s/core%d", clust_name, cpu);
68
+ qemu_fdt_add_subnode(mc->fdt, core_name);
69
+ qemu_fdt_setprop_cell(mc->fdt, core_name, "cpu", cpu_phandle);
70
+
71
+ g_free(core_name);
72
+ g_free(intc_name);
73
+ g_free(cpu_name);
74
+ }
75
+}
76
+
77
+static void create_fdt_socket_memory(RISCVVirtState *s,
78
+ const MemMapEntry *memmap, int socket)
79
+{
80
+ char *mem_name;
81
uint64_t addr, size;
82
- uint32_t *clint_cells, *plic_cells;
83
- unsigned long clint_addr, plic_addr;
84
- uint32_t plic_phandle[MAX_NODES];
85
- uint32_t cpu_phandle, intc_phandle, test_phandle;
86
- uint32_t phandle = 1, plic_mmio_phandle = 1;
87
- uint32_t plic_pcie_phandle = 1, plic_virtio_phandle = 1;
88
- char *mem_name, *cpu_name, *core_name, *intc_name;
89
- char *name, *clint_name, *plic_name, *clust_name;
90
- hwaddr flashsize = virt_memmap[VIRT_FLASH].size / 2;
91
- hwaddr flashbase = virt_memmap[VIRT_FLASH].base;
92
+ MachineState *mc = MACHINE(s);
93
+
94
+ addr = memmap[VIRT_DRAM].base + riscv_socket_mem_offset(mc, socket);
95
+ size = riscv_socket_mem_size(mc, socket);
96
+ mem_name = g_strdup_printf("/memory@%lx", (long)addr);
97
+ qemu_fdt_add_subnode(mc->fdt, mem_name);
98
+ qemu_fdt_setprop_cells(mc->fdt, mem_name, "reg",
99
+ addr >> 32, addr, size >> 32, size);
100
+ qemu_fdt_setprop_string(mc->fdt, mem_name, "device_type", "memory");
101
+ riscv_socket_fdt_write_id(mc, mc->fdt, mem_name, socket);
102
+ g_free(mem_name);
103
+}
104
+
105
+static void create_fdt_socket_clint(RISCVVirtState *s,
106
+ const MemMapEntry *memmap, int socket,
107
+ uint32_t *intc_phandles)
108
+{
109
+ int cpu;
110
+ char *clint_name;
111
+ uint32_t *clint_cells;
112
+ unsigned long clint_addr;
113
+ MachineState *mc = MACHINE(s);
114
static const char * const clint_compat[2] = {
115
"sifive,clint0", "riscv,clint0"
116
};
117
+
118
+ clint_cells = g_new0(uint32_t, s->soc[socket].num_harts * 4);
119
+
120
+ for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) {
121
+ clint_cells[cpu * 4 + 0] = cpu_to_be32(intc_phandles[cpu]);
122
+ clint_cells[cpu * 4 + 1] = cpu_to_be32(IRQ_M_SOFT);
123
+ clint_cells[cpu * 4 + 2] = cpu_to_be32(intc_phandles[cpu]);
124
+ clint_cells[cpu * 4 + 3] = cpu_to_be32(IRQ_M_TIMER);
125
+ }
126
+
127
+ clint_addr = memmap[VIRT_CLINT].base + (memmap[VIRT_CLINT].size * socket);
128
+ clint_name = g_strdup_printf("/soc/clint@%lx", clint_addr);
129
+ qemu_fdt_add_subnode(mc->fdt, clint_name);
130
+ qemu_fdt_setprop_string_array(mc->fdt, clint_name, "compatible",
131
+ (char **)&clint_compat,
132
+ ARRAY_SIZE(clint_compat));
133
+ qemu_fdt_setprop_cells(mc->fdt, clint_name, "reg",
134
+ 0x0, clint_addr, 0x0, memmap[VIRT_CLINT].size);
135
+ qemu_fdt_setprop(mc->fdt, clint_name, "interrupts-extended",
136
+ clint_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 4);
137
+ riscv_socket_fdt_write_id(mc, mc->fdt, clint_name, socket);
138
+ g_free(clint_name);
139
+
140
+ g_free(clint_cells);
141
+}
142
+
143
+static void create_fdt_socket_plic(RISCVVirtState *s,
144
+ const MemMapEntry *memmap, int socket,
145
+ uint32_t *phandle, uint32_t *intc_phandles,
146
+ uint32_t *plic_phandles)
147
+{
148
+ int cpu;
149
+ char *plic_name;
150
+ uint32_t *plic_cells;
151
+ unsigned long plic_addr;
152
+ MachineState *mc = MACHINE(s);
153
static const char * const plic_compat[2] = {
154
"sifive,plic-1.0.0", "riscv,plic0"
155
};
156
157
- if (mc->dtb) {
158
- fdt = mc->fdt = load_device_tree(mc->dtb, &s->fdt_size);
159
- if (!fdt) {
160
- error_report("load_device_tree() failed");
161
- exit(1);
162
- }
163
- goto update_bootargs;
164
- } else {
165
- fdt = mc->fdt = create_device_tree(&s->fdt_size);
166
- if (!fdt) {
167
- error_report("create_device_tree() failed");
168
- exit(1);
169
- }
170
+ plic_cells = g_new0(uint32_t, s->soc[socket].num_harts * 4);
171
+
172
+ for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) {
173
+ plic_cells[cpu * 4 + 0] = cpu_to_be32(intc_phandles[cpu]);
174
+ plic_cells[cpu * 4 + 1] = cpu_to_be32(IRQ_M_EXT);
175
+ plic_cells[cpu * 4 + 2] = cpu_to_be32(intc_phandles[cpu]);
176
+ plic_cells[cpu * 4 + 3] = cpu_to_be32(IRQ_S_EXT);
177
}
40
}
178
41
179
- qemu_fdt_setprop_string(fdt, "/", "model", "riscv-virtio,qemu");
42
/* KVM AIA only has one APLIC instance */
180
- qemu_fdt_setprop_string(fdt, "/", "compatible", "riscv-virtio");
43
- if (virt_use_kvm_aia(s)) {
181
- qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 0x2);
44
+ if (kvm_enabled() && virt_use_kvm_aia(s)) {
182
- qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 0x2);
45
create_fdt_socket_aplic(s, memmap, 0,
183
+ plic_phandles[socket] = (*phandle)++;
46
msi_m_phandle, msi_s_phandle, phandle,
184
+ plic_addr = memmap[VIRT_PLIC].base + (memmap[VIRT_PLIC].size * socket);
47
&intc_phandles[0], xplic_phandles,
185
+ plic_name = g_strdup_printf("/soc/plic@%lx", plic_addr);
48
@@ -XXX,XX +XXX,XX @@ static void create_fdt_sockets(RISCVVirtState *s, const MemMapEntry *memmap,
186
+ qemu_fdt_add_subnode(mc->fdt, plic_name);
49
187
+ qemu_fdt_setprop_cell(mc->fdt, plic_name,
50
g_free(intc_phandles);
188
+ "#address-cells", FDT_PLIC_ADDR_CELLS);
51
189
+ qemu_fdt_setprop_cell(mc->fdt, plic_name,
52
- if (virt_use_kvm_aia(s)) {
190
+ "#interrupt-cells", FDT_PLIC_INT_CELLS);
53
+ if (kvm_enabled() && virt_use_kvm_aia(s)) {
191
+ qemu_fdt_setprop_string_array(mc->fdt, plic_name, "compatible",
54
*irq_mmio_phandle = xplic_phandles[0];
192
+ (char **)&plic_compat,
55
*irq_virtio_phandle = xplic_phandles[0];
193
+ ARRAY_SIZE(plic_compat));
56
*irq_pcie_phandle = xplic_phandles[0];
194
+ qemu_fdt_setprop(mc->fdt, plic_name, "interrupt-controller", NULL, 0);
57
@@ -XXX,XX +XXX,XX @@ static void virt_machine_init(MachineState *machine)
195
+ qemu_fdt_setprop(mc->fdt, plic_name, "interrupts-extended",
196
+ plic_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 4);
197
+ qemu_fdt_setprop_cells(mc->fdt, plic_name, "reg",
198
+ 0x0, plic_addr, 0x0, memmap[VIRT_PLIC].size);
199
+ qemu_fdt_setprop_cell(mc->fdt, plic_name, "riscv,ndev", VIRTIO_NDEV);
200
+ riscv_socket_fdt_write_id(mc, mc->fdt, plic_name, socket);
201
+ qemu_fdt_setprop_cell(mc->fdt, plic_name, "phandle",
202
+ plic_phandles[socket]);
203
+ g_free(plic_name);
204
+
205
+ g_free(plic_cells);
206
+}
207
208
- qemu_fdt_add_subnode(fdt, "/soc");
209
- qemu_fdt_setprop(fdt, "/soc", "ranges", NULL, 0);
210
- qemu_fdt_setprop_string(fdt, "/soc", "compatible", "simple-bus");
211
- qemu_fdt_setprop_cell(fdt, "/soc", "#size-cells", 0x2);
212
- qemu_fdt_setprop_cell(fdt, "/soc", "#address-cells", 0x2);
213
+static void create_fdt_sockets(RISCVVirtState *s, const MemMapEntry *memmap,
214
+ bool is_32_bit, uint32_t *phandle,
215
+ uint32_t *irq_mmio_phandle,
216
+ uint32_t *irq_pcie_phandle,
217
+ uint32_t *irq_virtio_phandle)
218
+{
219
+ int socket;
220
+ char *clust_name;
221
+ uint32_t *intc_phandles;
222
+ MachineState *mc = MACHINE(s);
223
+ uint32_t xplic_phandles[MAX_NODES];
224
225
- qemu_fdt_add_subnode(fdt, "/cpus");
226
- qemu_fdt_setprop_cell(fdt, "/cpus", "timebase-frequency",
227
+ qemu_fdt_add_subnode(mc->fdt, "/cpus");
228
+ qemu_fdt_setprop_cell(mc->fdt, "/cpus", "timebase-frequency",
229
RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ);
230
- qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0x0);
231
- qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 0x1);
232
- qemu_fdt_add_subnode(fdt, "/cpus/cpu-map");
233
+ qemu_fdt_setprop_cell(mc->fdt, "/cpus", "#size-cells", 0x0);
234
+ qemu_fdt_setprop_cell(mc->fdt, "/cpus", "#address-cells", 0x1);
235
+ qemu_fdt_add_subnode(mc->fdt, "/cpus/cpu-map");
236
237
for (socket = (riscv_socket_count(mc) - 1); socket >= 0; socket--) {
238
clust_name = g_strdup_printf("/cpus/cpu-map/cluster%d", socket);
239
- qemu_fdt_add_subnode(fdt, clust_name);
240
-
241
- plic_cells = g_new0(uint32_t, s->soc[socket].num_harts * 4);
242
- clint_cells = g_new0(uint32_t, s->soc[socket].num_harts * 4);
243
-
244
- for (cpu = s->soc[socket].num_harts - 1; cpu >= 0; cpu--) {
245
- cpu_phandle = phandle++;
246
-
247
- cpu_name = g_strdup_printf("/cpus/cpu@%d",
248
- s->soc[socket].hartid_base + cpu);
249
- qemu_fdt_add_subnode(fdt, cpu_name);
250
- if (is_32_bit) {
251
- qemu_fdt_setprop_string(fdt, cpu_name, "mmu-type", "riscv,sv32");
252
- } else {
253
- qemu_fdt_setprop_string(fdt, cpu_name, "mmu-type", "riscv,sv48");
254
- }
255
- name = riscv_isa_string(&s->soc[socket].harts[cpu]);
256
- qemu_fdt_setprop_string(fdt, cpu_name, "riscv,isa", name);
257
- g_free(name);
258
- qemu_fdt_setprop_string(fdt, cpu_name, "compatible", "riscv");
259
- qemu_fdt_setprop_string(fdt, cpu_name, "status", "okay");
260
- qemu_fdt_setprop_cell(fdt, cpu_name, "reg",
261
- s->soc[socket].hartid_base + cpu);
262
- qemu_fdt_setprop_string(fdt, cpu_name, "device_type", "cpu");
263
- riscv_socket_fdt_write_id(mc, fdt, cpu_name, socket);
264
- qemu_fdt_setprop_cell(fdt, cpu_name, "phandle", cpu_phandle);
265
-
266
- intc_name = g_strdup_printf("%s/interrupt-controller", cpu_name);
267
- qemu_fdt_add_subnode(fdt, intc_name);
268
- intc_phandle = phandle++;
269
- qemu_fdt_setprop_cell(fdt, intc_name, "phandle", intc_phandle);
270
- qemu_fdt_setprop_string(fdt, intc_name, "compatible",
271
- "riscv,cpu-intc");
272
- qemu_fdt_setprop(fdt, intc_name, "interrupt-controller", NULL, 0);
273
- qemu_fdt_setprop_cell(fdt, intc_name, "#interrupt-cells", 1);
274
-
275
- clint_cells[cpu * 4 + 0] = cpu_to_be32(intc_phandle);
276
- clint_cells[cpu * 4 + 1] = cpu_to_be32(IRQ_M_SOFT);
277
- clint_cells[cpu * 4 + 2] = cpu_to_be32(intc_phandle);
278
- clint_cells[cpu * 4 + 3] = cpu_to_be32(IRQ_M_TIMER);
279
-
280
- plic_cells[cpu * 4 + 0] = cpu_to_be32(intc_phandle);
281
- plic_cells[cpu * 4 + 1] = cpu_to_be32(IRQ_M_EXT);
282
- plic_cells[cpu * 4 + 2] = cpu_to_be32(intc_phandle);
283
- plic_cells[cpu * 4 + 3] = cpu_to_be32(IRQ_S_EXT);
284
-
285
- core_name = g_strdup_printf("%s/core%d", clust_name, cpu);
286
- qemu_fdt_add_subnode(fdt, core_name);
287
- qemu_fdt_setprop_cell(fdt, core_name, "cpu", cpu_phandle);
288
-
289
- g_free(core_name);
290
- g_free(intc_name);
291
- g_free(cpu_name);
292
- }
293
+ qemu_fdt_add_subnode(mc->fdt, clust_name);
294
+
295
+ intc_phandles = g_new0(uint32_t, s->soc[socket].num_harts);
296
+
297
+ create_fdt_socket_cpus(s, socket, clust_name, phandle,
298
+ is_32_bit, intc_phandles);
299
300
- addr = memmap[VIRT_DRAM].base + riscv_socket_mem_offset(mc, socket);
301
- size = riscv_socket_mem_size(mc, socket);
302
- mem_name = g_strdup_printf("/memory@%lx", (long)addr);
303
- qemu_fdt_add_subnode(fdt, mem_name);
304
- qemu_fdt_setprop_cells(fdt, mem_name, "reg",
305
- addr >> 32, addr, size >> 32, size);
306
- qemu_fdt_setprop_string(fdt, mem_name, "device_type", "memory");
307
- riscv_socket_fdt_write_id(mc, fdt, mem_name, socket);
308
- g_free(mem_name);
309
-
310
- clint_addr = memmap[VIRT_CLINT].base +
311
- (memmap[VIRT_CLINT].size * socket);
312
- clint_name = g_strdup_printf("/soc/clint@%lx", clint_addr);
313
- qemu_fdt_add_subnode(fdt, clint_name);
314
- qemu_fdt_setprop_string_array(fdt, clint_name, "compatible",
315
- (char **)&clint_compat, ARRAY_SIZE(clint_compat));
316
- qemu_fdt_setprop_cells(fdt, clint_name, "reg",
317
- 0x0, clint_addr, 0x0, memmap[VIRT_CLINT].size);
318
- qemu_fdt_setprop(fdt, clint_name, "interrupts-extended",
319
- clint_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 4);
320
- riscv_socket_fdt_write_id(mc, fdt, clint_name, socket);
321
- g_free(clint_name);
322
-
323
- plic_phandle[socket] = phandle++;
324
- plic_addr = memmap[VIRT_PLIC].base + (memmap[VIRT_PLIC].size * socket);
325
- plic_name = g_strdup_printf("/soc/plic@%lx", plic_addr);
326
- qemu_fdt_add_subnode(fdt, plic_name);
327
- qemu_fdt_setprop_cell(fdt, plic_name,
328
- "#address-cells", FDT_PLIC_ADDR_CELLS);
329
- qemu_fdt_setprop_cell(fdt, plic_name,
330
- "#interrupt-cells", FDT_PLIC_INT_CELLS);
331
- qemu_fdt_setprop_string_array(fdt, plic_name, "compatible",
332
- (char **)&plic_compat, ARRAY_SIZE(plic_compat));
333
- qemu_fdt_setprop(fdt, plic_name, "interrupt-controller", NULL, 0);
334
- qemu_fdt_setprop(fdt, plic_name, "interrupts-extended",
335
- plic_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 4);
336
- qemu_fdt_setprop_cells(fdt, plic_name, "reg",
337
- 0x0, plic_addr, 0x0, memmap[VIRT_PLIC].size);
338
- qemu_fdt_setprop_cell(fdt, plic_name, "riscv,ndev", VIRTIO_NDEV);
339
- riscv_socket_fdt_write_id(mc, fdt, plic_name, socket);
340
- qemu_fdt_setprop_cell(fdt, plic_name, "phandle", plic_phandle[socket]);
341
- g_free(plic_name);
342
-
343
- g_free(clint_cells);
344
- g_free(plic_cells);
345
+ create_fdt_socket_memory(s, memmap, socket);
346
+
347
+ create_fdt_socket_clint(s, memmap, socket, intc_phandles);
348
+
349
+ create_fdt_socket_plic(s, memmap, socket, phandle,
350
+ intc_phandles, xplic_phandles);
351
+
352
+ g_free(intc_phandles);
353
g_free(clust_name);
354
}
355
356
for (socket = 0; socket < riscv_socket_count(mc); socket++) {
357
if (socket == 0) {
358
- plic_mmio_phandle = plic_phandle[socket];
359
- plic_virtio_phandle = plic_phandle[socket];
360
- plic_pcie_phandle = plic_phandle[socket];
361
+ *irq_mmio_phandle = xplic_phandles[socket];
362
+ *irq_virtio_phandle = xplic_phandles[socket];
363
+ *irq_pcie_phandle = xplic_phandles[socket];
364
}
365
if (socket == 1) {
366
- plic_virtio_phandle = plic_phandle[socket];
367
- plic_pcie_phandle = plic_phandle[socket];
368
+ *irq_virtio_phandle = xplic_phandles[socket];
369
+ *irq_pcie_phandle = xplic_phandles[socket];
370
}
371
if (socket == 2) {
372
- plic_pcie_phandle = plic_phandle[socket];
373
+ *irq_pcie_phandle = xplic_phandles[socket];
374
}
58
}
375
}
59
}
376
60
377
- riscv_socket_fdt_write_distance_matrix(mc, fdt);
61
- if (virt_use_kvm_aia(s)) {
378
+ riscv_socket_fdt_write_distance_matrix(mc, mc->fdt);
62
+ if (kvm_enabled() && virt_use_kvm_aia(s)) {
379
+}
63
kvm_riscv_aia_create(machine, IMSIC_MMIO_GROUP_MIN_SHIFT,
380
+
64
VIRT_IRQCHIP_NUM_SOURCES, VIRT_IRQCHIP_NUM_MSIS,
381
+static void create_fdt_virtio(RISCVVirtState *s, const MemMapEntry *memmap,
65
memmap[VIRT_APLIC_S].base,
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
--
66
--
641
2.31.1
67
2.41.0
642
68
643
69
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@wdc.com>
1
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
2
2
3
Instead of using riscv_cpu_update_mip() let's instead use the new RISC-V
3
Commit 6df0b37e2ab breaks a --enable-debug build in a non-KVM
4
CPU GPIO lines to set the timer MIP bits.
4
environment with the following error:
5
5
6
/usr/bin/ld: libqemu-riscv64-softmmu.fa.p/hw_intc_riscv_aplic.c.o: in function `riscv_kvm_aplic_request':
7
./qemu/build/../hw/intc/riscv_aplic.c:486: undefined reference to `kvm_set_irq'
8
collect2: error: ld returned 1 exit status
9
10
This happens because the debug build will poke into the
11
'if (is_kvm_aia(aplic->msimode))' block and fail to find a reference to
12
the KVM only function riscv_kvm_aplic_request().
13
14
There are multiple solutions to fix this. We'll go with the same
15
solution from the previous patch, i.e. add a kvm_enabled() conditional
16
to filter out the block. But there's a catch: riscv_kvm_aplic_request()
17
is a local function that would end up being used if the compiler crops
18
the block, and this won't work. Quoting Richard Henderson's explanation
19
in [1]:
20
21
"(...) the compiler won't eliminate entire unused functions with -O0"
22
23
We'll solve it by moving riscv_kvm_aplic_request() to kvm.c and add its
24
declaration in kvm_riscv.h, where all other KVM specific public
25
functions are already declared. Other archs handles KVM specific code in
26
this manner and we expect to do the same from now on.
27
28
[1] https://lore.kernel.org/qemu-riscv/d2f1ad02-eb03-138f-9d08-db676deeed05@linaro.org/
29
30
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
31
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
32
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
33
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
34
Message-ID: <20230830133503.711138-3-dbarboza@ventanamicro.com>
6
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
35
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
---
36
---
11
include/hw/timer/ibex_timer.h | 2 ++
37
target/riscv/kvm_riscv.h | 1 +
12
hw/riscv/opentitan.c | 3 +++
38
hw/intc/riscv_aplic.c | 8 ++------
13
hw/timer/ibex_timer.c | 17 ++++++++++++-----
39
target/riscv/kvm.c | 5 +++++
14
3 files changed, 17 insertions(+), 5 deletions(-)
40
3 files changed, 8 insertions(+), 6 deletions(-)
15
41
16
diff --git a/include/hw/timer/ibex_timer.h b/include/hw/timer/ibex_timer.h
42
diff --git a/target/riscv/kvm_riscv.h b/target/riscv/kvm_riscv.h
17
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/timer/ibex_timer.h
44
--- a/target/riscv/kvm_riscv.h
19
+++ b/include/hw/timer/ibex_timer.h
45
+++ b/target/riscv/kvm_riscv.h
20
@@ -XXX,XX +XXX,XX @@ struct IbexTimerState {
46
@@ -XXX,XX +XXX,XX @@ void kvm_riscv_aia_create(MachineState *machine, uint64_t group_shift,
21
uint32_t timebase_freq;
47
uint64_t aia_irq_num, uint64_t aia_msi_num,
22
48
uint64_t aplic_base, uint64_t imsic_base,
23
qemu_irq irq;
49
uint64_t guest_num);
24
+
50
+void riscv_kvm_aplic_request(void *opaque, int irq, int level);
25
+ qemu_irq m_timer_irq;
51
26
};
52
#endif
27
#endif /* HW_IBEX_TIMER_H */
53
diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
28
diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c
29
index XXXXXXX..XXXXXXX 100644
54
index XXXXXXX..XXXXXXX 100644
30
--- a/hw/riscv/opentitan.c
55
--- a/hw/intc/riscv_aplic.c
31
+++ b/hw/riscv/opentitan.c
56
+++ b/hw/intc/riscv_aplic.c
32
@@ -XXX,XX +XXX,XX @@ static void lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp)
57
@@ -XXX,XX +XXX,XX @@
33
sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer),
58
#include "target/riscv/cpu.h"
34
0, qdev_get_gpio_in(DEVICE(&s->plic),
59
#include "sysemu/sysemu.h"
35
IBEX_TIMER_TIMEREXPIRED0_0));
60
#include "sysemu/kvm.h"
36
+ qdev_connect_gpio_out(DEVICE(&s->timer), 0,
61
+#include "kvm_riscv.h"
37
+ qdev_get_gpio_in(DEVICE(qemu_get_cpu(0)),
62
#include "migration/vmstate.h"
38
+ IRQ_M_TIMER));
63
39
64
#define APLIC_MAX_IDC (1UL << 14)
40
create_unimplemented_device("riscv.lowrisc.ibex.gpio",
65
@@ -XXX,XX +XXX,XX @@ static uint32_t riscv_aplic_idc_claimi(RISCVAPLICState *aplic, uint32_t idc)
41
memmap[IBEX_DEV_GPIO].base, memmap[IBEX_DEV_GPIO].size);
66
return topi;
42
diff --git a/hw/timer/ibex_timer.c b/hw/timer/ibex_timer.c
67
}
68
69
-static void riscv_kvm_aplic_request(void *opaque, int irq, int level)
70
-{
71
- kvm_set_irq(kvm_state, irq, !!level);
72
-}
73
-
74
static void riscv_aplic_request(void *opaque, int irq, int level)
75
{
76
bool update = false;
77
@@ -XXX,XX +XXX,XX @@ static void riscv_aplic_realize(DeviceState *dev, Error **errp)
78
* have IRQ lines delegated by their parent APLIC.
79
*/
80
if (!aplic->parent) {
81
- if (is_kvm_aia(aplic->msimode)) {
82
+ if (kvm_enabled() && is_kvm_aia(aplic->msimode)) {
83
qdev_init_gpio_in(dev, riscv_kvm_aplic_request, aplic->num_irqs);
84
} else {
85
qdev_init_gpio_in(dev, riscv_aplic_request, aplic->num_irqs);
86
diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c
43
index XXXXXXX..XXXXXXX 100644
87
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/timer/ibex_timer.c
88
--- a/target/riscv/kvm.c
45
+++ b/hw/timer/ibex_timer.c
89
+++ b/target/riscv/kvm.c
46
@@ -XXX,XX +XXX,XX @@ static void ibex_timer_update_irqs(IbexTimerState *s)
90
@@ -XXX,XX +XXX,XX @@
47
/*
91
#include "sysemu/runstate.h"
48
* If the mtimecmp was in the past raise the interrupt now.
92
#include "hw/riscv/numa.h"
49
*/
93
50
- riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(1));
94
+void riscv_kvm_aplic_request(void *opaque, int irq, int level)
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
}
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
}
79
80
+static void ibex_timer_realize(DeviceState *dev, Error **errp)
81
+{
95
+{
82
+ IbexTimerState *s = IBEX_TIMER(dev);
96
+ kvm_set_irq(kvm_state, irq, !!level);
83
+
84
+ qdev_init_gpio_out(dev, &s->m_timer_irq, 1);
85
+}
97
+}
86
+
98
+
87
+
99
static uint64_t kvm_riscv_reg_id(CPURISCVState *env, uint64_t type,
88
static void ibex_timer_class_init(ObjectClass *klass, void *data)
100
uint64_t idx)
89
{
101
{
90
DeviceClass *dc = DEVICE_CLASS(klass);
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
--
102
--
99
2.31.1
103
2.41.0
100
104
101
105
diff view generated by jsdifflib
New patch
1
From: Robbin Ehn <rehn@rivosinc.com>
1
2
3
This patch adds the new extensions in
4
linux 6.5 to the hwprobe syscall.
5
6
And fixes RVC check to OR with correct value.
7
The previous variable contains 0 therefore it
8
did work.
9
10
Signed-off-by: Robbin Ehn <rehn@rivosinc.com>
11
Acked-by: Richard Henderson <richard.henderson@linaro.org>
12
Acked-by: Alistair Francis <alistair.francis@wdc.com>
13
Message-ID: <bc82203b72d7efb30f1b4a8f9eb3d94699799dc8.camel@rivosinc.com>
14
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
15
---
16
linux-user/syscall.c | 14 +++++++++++++-
17
1 file changed, 13 insertions(+), 1 deletion(-)
18
19
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/linux-user/syscall.c
22
+++ b/linux-user/syscall.c
23
@@ -XXX,XX +XXX,XX @@ static int do_getdents64(abi_long dirfd, abi_long arg2, abi_long count)
24
#define RISCV_HWPROBE_KEY_IMA_EXT_0 4
25
#define RISCV_HWPROBE_IMA_FD (1 << 0)
26
#define RISCV_HWPROBE_IMA_C (1 << 1)
27
+#define RISCV_HWPROBE_IMA_V (1 << 2)
28
+#define RISCV_HWPROBE_EXT_ZBA (1 << 3)
29
+#define RISCV_HWPROBE_EXT_ZBB (1 << 4)
30
+#define RISCV_HWPROBE_EXT_ZBS (1 << 5)
31
32
#define RISCV_HWPROBE_KEY_CPUPERF_0 5
33
#define RISCV_HWPROBE_MISALIGNED_UNKNOWN (0 << 0)
34
@@ -XXX,XX +XXX,XX @@ static void risc_hwprobe_fill_pairs(CPURISCVState *env,
35
riscv_has_ext(env, RVD) ?
36
RISCV_HWPROBE_IMA_FD : 0;
37
value |= riscv_has_ext(env, RVC) ?
38
- RISCV_HWPROBE_IMA_C : pair->value;
39
+ RISCV_HWPROBE_IMA_C : 0;
40
+ value |= riscv_has_ext(env, RVV) ?
41
+ RISCV_HWPROBE_IMA_V : 0;
42
+ value |= cfg->ext_zba ?
43
+ RISCV_HWPROBE_EXT_ZBA : 0;
44
+ value |= cfg->ext_zbb ?
45
+ RISCV_HWPROBE_EXT_ZBB : 0;
46
+ value |= cfg->ext_zbs ?
47
+ RISCV_HWPROBE_EXT_ZBS : 0;
48
__put_user(value, &pair->value);
49
break;
50
case RISCV_HWPROBE_KEY_CPUPERF_0:
51
--
52
2.41.0
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@wdc.com>
1
From: Ard Biesheuvel <ardb@kernel.org>
2
2
3
Instead of using riscv_cpu_update_mip() let's instead use the new RISC-V
3
Use the accelerated SubBytes/ShiftRows/AddRoundKey AES helper to
4
CPU GPIO lines to set the timer and soft MIP bits.
4
implement the first half of the key schedule derivation. This does not
5
actually involve shifting rows, so clone the same value into all four
6
columns of the AES vector to counter that operation.
5
7
8
Cc: Richard Henderson <richard.henderson@linaro.org>
9
Cc: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Cc: Palmer Dabbelt <palmer@dabbelt.com>
11
Cc: Alistair Francis <alistair.francis@wdc.com>
12
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
13
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-ID: <20230831154118.138727-1-ardb@kernel.org>
6
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
16
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
---
17
---
12
include/hw/intc/sifive_clint.h | 2 +
18
target/riscv/crypto_helper.c | 17 +++++------------
13
hw/intc/sifive_clint.c | 68 ++++++++++++++++++++++++----------
19
1 file changed, 5 insertions(+), 12 deletions(-)
14
2 files changed, 50 insertions(+), 20 deletions(-)
15
20
16
diff --git a/include/hw/intc/sifive_clint.h b/include/hw/intc/sifive_clint.h
21
diff --git a/target/riscv/crypto_helper.c b/target/riscv/crypto_helper.c
17
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/intc/sifive_clint.h
23
--- a/target/riscv/crypto_helper.c
19
+++ b/include/hw/intc/sifive_clint.h
24
+++ b/target/riscv/crypto_helper.c
20
@@ -XXX,XX +XXX,XX @@ typedef struct SiFiveCLINTState {
25
@@ -XXX,XX +XXX,XX @@ target_ulong HELPER(aes64ks1i)(target_ulong rs1, target_ulong rnum)
21
uint32_t time_base;
26
22
uint32_t aperture_size;
27
uint8_t enc_rnum = rnum;
23
uint32_t timebase_freq;
28
uint32_t temp = (RS1 >> 32) & 0xFFFFFFFF;
24
+ qemu_irq *timer_irqs;
29
- uint8_t rcon_ = 0;
25
+ qemu_irq *soft_irqs;
30
- target_ulong result;
26
} SiFiveCLINTState;
31
+ AESState t, rc = {};
27
32
28
DeviceState *sifive_clint_create(hwaddr addr, hwaddr size,
33
if (enc_rnum != 0xA) {
29
diff --git a/hw/intc/sifive_clint.c b/hw/intc/sifive_clint.c
34
temp = ror32(temp, 8); /* Rotate right by 8 */
30
index XXXXXXX..XXXXXXX 100644
35
- rcon_ = round_consts[enc_rnum];
31
--- a/hw/intc/sifive_clint.c
36
+ rc.w[0] = rc.w[1] = round_consts[enc_rnum];
32
+++ b/hw/intc/sifive_clint.c
33
@@ -XXX,XX +XXX,XX @@
34
#include "hw/qdev-properties.h"
35
#include "hw/intc/sifive_clint.h"
36
#include "qemu/timer.h"
37
+#include "hw/irq.h"
38
+
39
+typedef struct sifive_clint_callback {
40
+ SiFiveCLINTState *s;
41
+ int num;
42
+} sifive_clint_callback;
43
44
static uint64_t cpu_riscv_read_rtc(uint32_t timebase_freq)
45
{
46
@@ -XXX,XX +XXX,XX @@ static uint64_t cpu_riscv_read_rtc(uint32_t timebase_freq)
47
* Called when timecmp is written to update the QEMU timer or immediately
48
* trigger timer interrupt if mtimecmp <= current timer value.
49
*/
50
-static void sifive_clint_write_timecmp(RISCVCPU *cpu, uint64_t value,
51
+static void sifive_clint_write_timecmp(SiFiveCLINTState *s, RISCVCPU *cpu,
52
+ int hartid,
53
+ uint64_t value,
54
uint32_t timebase_freq)
55
{
56
uint64_t next;
57
@@ -XXX,XX +XXX,XX @@ static void sifive_clint_write_timecmp(RISCVCPU *cpu, uint64_t value,
58
if (cpu->env.timecmp <= rtc_r) {
59
/* if we're setting an MTIMECMP value in the "past",
60
immediately raise the timer interrupt */
61
- riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(1));
62
+ qemu_irq_raise(s->timer_irqs[hartid - s->hartid_base]);
63
return;
64
}
37
}
65
38
66
/* otherwise, set up the future timer interrupt */
39
- temp = ((uint32_t)AES_sbox[(temp >> 24) & 0xFF] << 24) |
67
- riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(0));
40
- ((uint32_t)AES_sbox[(temp >> 16) & 0xFF] << 16) |
68
+ qemu_irq_lower(s->timer_irqs[hartid - s->hartid_base]);
41
- ((uint32_t)AES_sbox[(temp >> 8) & 0xFF] << 8) |
69
diff = cpu->env.timecmp - rtc_r;
42
- ((uint32_t)AES_sbox[(temp >> 0) & 0xFF] << 0);
70
/* back to ns (note args switched in muldiv64) */
43
+ t.w[0] = t.w[1] = t.w[2] = t.w[3] = temp;
71
uint64_t ns_diff = muldiv64(diff, NANOSECONDS_PER_SECOND, timebase_freq);
44
+ aesenc_SB_SR_AK(&t, &t, &rc, false);
72
@@ -XXX,XX +XXX,XX @@ static void sifive_clint_write_timecmp(RISCVCPU *cpu, uint64_t value,
45
73
*/
46
- temp ^= rcon_;
74
static void sifive_clint_timer_cb(void *opaque)
47
-
75
{
48
- result = ((uint64_t)temp << 32) | temp;
76
- RISCVCPU *cpu = opaque;
49
-
77
- riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(1));
50
- return result;
78
+ sifive_clint_callback *state = opaque;
51
+ return t.d[0];
79
+
80
+ qemu_irq_raise(state->s->timer_irqs[state->num]);
81
}
52
}
82
53
83
/* CPU wants to read rtc or timecmp register */
54
target_ulong HELPER(aes64im)(target_ulong rs1)
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
}
172
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
--
55
--
186
2.31.1
56
2.41.0
187
57
188
58
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@wdc.com>
1
From: Akihiko Odaki <akihiko.odaki@daynix.com>
2
2
3
Expose the 12 interrupt pending bits in MIP as GPIO lines.
3
riscv_trigger_init() had been called on reset events that can happen
4
several times for a CPU and it allocated timers for itrigger. If old
5
timers were present, they were simply overwritten by the new timers,
6
resulting in a memory leak.
4
7
8
Divide riscv_trigger_init() into two functions, namely
9
riscv_trigger_realize() and riscv_trigger_reset() and call them in
10
appropriate timing. The timer allocation will happen only once for a
11
CPU in riscv_trigger_realize().
12
13
Fixes: 5a4ae64cac ("target/riscv: Add itrigger support when icount is enabled")
14
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
15
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
16
Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
17
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
18
Message-ID: <20230818034059.9146-1-akihiko.odaki@daynix.com>
5
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
19
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
---
20
---
12
target/riscv/cpu.c | 30 ++++++++++++++++++++++++++++++
21
target/riscv/debug.h | 3 ++-
13
1 file changed, 30 insertions(+)
22
target/riscv/cpu.c | 8 +++++++-
23
target/riscv/debug.c | 15 ++++++++++++---
24
3 files changed, 21 insertions(+), 5 deletions(-)
14
25
26
diff --git a/target/riscv/debug.h b/target/riscv/debug.h
27
index XXXXXXX..XXXXXXX 100644
28
--- a/target/riscv/debug.h
29
+++ b/target/riscv/debug.h
30
@@ -XXX,XX +XXX,XX @@ void riscv_cpu_debug_excp_handler(CPUState *cs);
31
bool riscv_cpu_debug_check_breakpoint(CPUState *cs);
32
bool riscv_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp);
33
34
-void riscv_trigger_init(CPURISCVState *env);
35
+void riscv_trigger_realize(CPURISCVState *env);
36
+void riscv_trigger_reset_hold(CPURISCVState *env);
37
38
bool riscv_itrigger_enabled(CPURISCVState *env);
39
void riscv_itrigger_update_priv(CPURISCVState *env);
15
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
40
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
16
index XXXXXXX..XXXXXXX 100644
41
index XXXXXXX..XXXXXXX 100644
17
--- a/target/riscv/cpu.c
42
--- a/target/riscv/cpu.c
18
+++ b/target/riscv/cpu.c
43
+++ b/target/riscv/cpu.c
44
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_reset_hold(Object *obj)
45
46
#ifndef CONFIG_USER_ONLY
47
if (cpu->cfg.debug) {
48
- riscv_trigger_init(env);
49
+ riscv_trigger_reset_hold(env);
50
}
51
52
if (kvm_enabled()) {
19
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
53
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
20
mcc->parent_realize(dev, errp);
54
55
riscv_cpu_register_gdb_regs_for_features(cs);
56
57
+#ifndef CONFIG_USER_ONLY
58
+ if (cpu->cfg.debug) {
59
+ riscv_trigger_realize(&cpu->env);
60
+ }
61
+#endif
62
+
63
qemu_init_vcpu(cs);
64
cpu_reset(cs);
65
66
diff --git a/target/riscv/debug.c b/target/riscv/debug.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/target/riscv/debug.c
69
+++ b/target/riscv/debug.c
70
@@ -XXX,XX +XXX,XX @@ bool riscv_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp)
71
return false;
21
}
72
}
22
73
23
+#ifndef CONFIG_USER_ONLY
74
-void riscv_trigger_init(CPURISCVState *env)
24
+static void riscv_cpu_set_irq(void *opaque, int irq, int level)
75
+void riscv_trigger_realize(CPURISCVState *env)
25
+{
76
+{
26
+ RISCVCPU *cpu = RISCV_CPU(opaque);
77
+ int i;
27
+
78
+
28
+ switch (irq) {
79
+ for (i = 0; i < RV_MAX_TRIGGERS; i++) {
29
+ case IRQ_U_SOFT:
80
+ env->itrigger_timer[i] = timer_new_ns(QEMU_CLOCK_VIRTUAL,
30
+ case IRQ_S_SOFT:
81
+ riscv_itrigger_timer_cb, env);
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
+ }
82
+ }
46
+}
83
+}
47
+#endif /* CONFIG_USER_ONLY */
48
+
84
+
49
static void riscv_cpu_init(Object *obj)
85
+void riscv_trigger_reset_hold(CPURISCVState *env)
50
{
86
{
51
RISCVCPU *cpu = RISCV_CPU(obj);
87
target_ulong tdata1 = build_tdata1(env, TRIGGER_TYPE_AD_MATCH, 0, 0);
52
88
int i;
53
cpu_set_cpustate_pointers(cpu);
89
@@ -XXX,XX +XXX,XX @@ void riscv_trigger_init(CPURISCVState *env)
54
+
90
env->tdata3[i] = 0;
55
+#ifndef CONFIG_USER_ONLY
91
env->cpu_breakpoint[i] = NULL;
56
+ qdev_init_gpio_in(DEVICE(cpu), riscv_cpu_set_irq, 12);
92
env->cpu_watchpoint[i] = NULL;
57
+#endif /* CONFIG_USER_ONLY */
93
- env->itrigger_timer[i] = timer_new_ns(QEMU_CLOCK_VIRTUAL,
94
- riscv_itrigger_timer_cb, env);
95
+ timer_del(env->itrigger_timer[i]);
96
}
58
}
97
}
59
60
static Property riscv_cpu_properties[] = {
61
--
98
--
62
2.31.1
99
2.41.0
63
100
64
101
diff view generated by jsdifflib
New patch
1
From: Leon Schuermann <leons@opentitan.org>
1
2
3
When the rule-lock bypass (RLB) bit is set in the mseccfg CSR, the PMP
4
configuration lock bits must not apply. While this behavior is
5
implemented for the pmpcfgX CSRs, this bit is not respected for
6
changes to the pmpaddrX CSRs. This patch ensures that pmpaddrX CSR
7
writes work even on locked regions when the global rule-lock bypass is
8
enabled.
9
10
Signed-off-by: Leon Schuermann <leons@opentitan.org>
11
Reviewed-by: Mayuresh Chitale <mchitale@ventanamicro.com>
12
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
13
Message-ID: <20230829215046.1430463-1-leon@is.currently.online>
14
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
15
---
16
target/riscv/pmp.c | 4 ++++
17
1 file changed, 4 insertions(+)
18
19
diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/riscv/pmp.c
22
+++ b/target/riscv/pmp.c
23
@@ -XXX,XX +XXX,XX @@ static inline uint8_t pmp_get_a_field(uint8_t cfg)
24
*/
25
static inline int pmp_is_locked(CPURISCVState *env, uint32_t pmp_index)
26
{
27
+ /* mseccfg.RLB is set */
28
+ if (MSECCFG_RLB_ISSET(env)) {
29
+ return 0;
30
+ }
31
32
if (env->pmp_state.pmp[pmp_index].cfg_reg & PMP_LOCK) {
33
return 1;
34
--
35
2.41.0
diff view generated by jsdifflib
1
From: LIU Zhiwei <zhiwei_liu@c-sky.com>
1
From: Tommy Wu <tommy.wu@sifive.com>
2
2
3
These variables should be target_ulong. If truncated to int,
3
According to the new spec, when vsiselect has a reserved value, attempts
4
the bool conditions they indicate will be wrong.
4
from M-mode or HS-mode to access vsireg, or from VS-mode to access
5
sireg, should preferably raise an illegal instruction exception.
5
6
6
As satp is very important for Linux, this bug almost fails every boot.
7
Signed-off-by: Tommy Wu <tommy.wu@sifive.com>
7
8
Reviewed-by: Frank Chang <frank.chang@sifive.com>
8
Signed-off-by: LIU Zhiwei <zhiwei_liu@c-sky.com>
9
Message-ID: <20230816061647.600672-1-tommy.wu@sifive.com>
9
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
10
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
11
Message-id: 20210901124539.222868-1-zhiwei_liu@c-sky.com
12
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
10
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
13
---
11
---
14
target/riscv/csr.c | 2 +-
12
target/riscv/csr.c | 7 +++++--
15
1 file changed, 1 insertion(+), 1 deletion(-)
13
1 file changed, 5 insertions(+), 2 deletions(-)
16
14
17
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
15
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
18
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
19
--- a/target/riscv/csr.c
17
--- a/target/riscv/csr.c
20
+++ b/target/riscv/csr.c
18
+++ b/target/riscv/csr.c
21
@@ -XXX,XX +XXX,XX @@ static RISCVException read_satp(CPURISCVState *env, int csrno,
19
@@ -XXX,XX +XXX,XX @@ static int rmw_iprio(target_ulong xlen,
22
static RISCVException write_satp(CPURISCVState *env, int csrno,
20
static int rmw_xireg(CPURISCVState *env, int csrno, target_ulong *val,
23
target_ulong val)
21
target_ulong new_val, target_ulong wr_mask)
24
{
22
{
25
- int vm, mask, asid;
23
- bool virt;
26
+ target_ulong vm, mask, asid;
24
+ bool virt, isel_reserved;
27
25
uint8_t *iprio;
28
if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
26
int ret = -EINVAL;
29
return RISCV_EXCP_NONE;
27
target_ulong priv, isel, vgein;
28
@@ -XXX,XX +XXX,XX @@ static int rmw_xireg(CPURISCVState *env, int csrno, target_ulong *val,
29
30
/* Decode register details from CSR number */
31
virt = false;
32
+ isel_reserved = false;
33
switch (csrno) {
34
case CSR_MIREG:
35
iprio = env->miprio;
36
@@ -XXX,XX +XXX,XX @@ static int rmw_xireg(CPURISCVState *env, int csrno, target_ulong *val,
37
riscv_cpu_mxl_bits(env)),
38
val, new_val, wr_mask);
39
}
40
+ } else {
41
+ isel_reserved = true;
42
}
43
44
done:
45
if (ret) {
46
- return (env->virt_enabled && virt) ?
47
+ return (env->virt_enabled && virt && !isel_reserved) ?
48
RISCV_EXCP_VIRT_INSTRUCTION_FAULT : RISCV_EXCP_ILLEGAL_INST;
49
}
50
return RISCV_EXCP_NONE;
30
--
51
--
31
2.31.1
52
2.41.0
32
33
diff view generated by jsdifflib
1
From: Frank Chang <frank.chang@sifive.com>
1
From: Nikita Shubin <n.shubin@yadro.com>
2
2
3
Real PDMA doesn't set Control.error if there are 0 bytes to be
3
As per ISA:
4
transferred. The DMA transfer is still success.
5
4
6
The following result is PDMA tested in U-Boot on Unmatched board:
5
"For CSRRWI, if rd=x0, then the instruction shall not read the CSR and
6
shall not cause any of the side effects that might occur on a CSR read."
7
7
8
=> mw.l 0x3000000 0x0 <= Disclaim channel 0
8
trans_csrrwi() and trans_csrrw() call do_csrw() if rd=x0, do_csrw() calls
9
=> mw.l 0x3000000 0x1 <= Claim channel 0
9
riscv_csrrw_do64(), via helper_csrw() passing NULL as *ret_value.
10
=> mw.l 0x3000004 0x55000000 <= wsize = rsize = 5 (2^5 = 32 bytes)
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
10
30
Signed-off-by: Frank Chang <frank.chang@sifive.com>
11
Signed-off-by: Nikita Shubin <n.shubin@yadro.com>
31
Tested-by: Max Hsu <max.hsu@sifive.com>
12
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
32
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
13
Message-ID: <20230808090914.17634-1-nikita.shubin@maquefel.me>
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>
14
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
36
---
15
---
37
hw/dma/sifive_pdma.c | 12 ++++++------
16
target/riscv/csr.c | 24 +++++++++++++++---------
38
1 file changed, 6 insertions(+), 6 deletions(-)
17
1 file changed, 15 insertions(+), 9 deletions(-)
39
18
40
diff --git a/hw/dma/sifive_pdma.c b/hw/dma/sifive_pdma.c
19
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
41
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/dma/sifive_pdma.c
21
--- a/target/riscv/csr.c
43
+++ b/hw/dma/sifive_pdma.c
22
+++ b/target/riscv/csr.c
44
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_run(SiFivePDMAState *s, int ch)
23
@@ -XXX,XX +XXX,XX @@ static RISCVException riscv_csrrw_do64(CPURISCVState *env, int csrno,
45
24
target_ulong write_mask)
46
/* do nothing if bytes to transfer is zero */
25
{
47
if (!bytes) {
26
RISCVException ret;
48
- goto error;
27
- target_ulong old_value;
49
+ goto done;
28
+ target_ulong old_value = 0;
29
30
/* execute combined read/write operation if it exists */
31
if (csr_ops[csrno].op) {
32
return csr_ops[csrno].op(env, csrno, ret_value, new_value, write_mask);
50
}
33
}
51
34
52
/*
35
- /* if no accessor exists then return failure */
53
@@ -XXX,XX +XXX,XX @@ static void sifive_pdma_run(SiFivePDMAState *s, int ch)
36
- if (!csr_ops[csrno].read) {
54
s->chan[ch].exec_bytes -= remainder;
37
- return RISCV_EXCP_ILLEGAL_INST;
38
- }
39
- /* read old value */
40
- ret = csr_ops[csrno].read(env, csrno, &old_value);
41
- if (ret != RISCV_EXCP_NONE) {
42
- return ret;
43
+ /*
44
+ * ret_value == NULL means that rd=x0 and we're coming from helper_csrw()
45
+ * and we can't throw side effects caused by CSR reads.
46
+ */
47
+ if (ret_value) {
48
+ /* if no accessor exists then return failure */
49
+ if (!csr_ops[csrno].read) {
50
+ return RISCV_EXCP_ILLEGAL_INST;
51
+ }
52
+ /* read old value */
53
+ ret = csr_ops[csrno].read(env, csrno, &old_value);
54
+ if (ret != RISCV_EXCP_NONE) {
55
+ return ret;
56
+ }
55
}
57
}
56
58
57
- /* indicate a DMA transfer is done */
59
/* write value if writable and write mask set, otherwise drop writes */
58
- s->chan[ch].state = DMA_CHAN_STATE_DONE;
59
- s->chan[ch].control &= ~CONTROL_RUN;
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
}
68
69
+done:
70
+ /* indicate a DMA transfer is done */
71
+ s->chan[ch].state = DMA_CHAN_STATE_DONE;
72
+ s->chan[ch].control &= ~CONTROL_RUN;
73
+ s->chan[ch].control |= CONTROL_DONE;
74
return;
75
76
error:
77
--
60
--
78
2.31.1
61
2.41.0
79
80
diff view generated by jsdifflib