1
Last lot of patches for arm before softfreeze tomorrow...
1
The following changes since commit 8f6330a807f2642dc2a3cdf33347aa28a4c00a87:
2
2
3
thanks
3
Merge tag 'pull-maintainer-updates-060324-1' of https://gitlab.com/stsquad/qemu into staging (2024-03-06 16:56:20 +0000)
4
-- PMM
5
6
The following changes since commit ef3a6af5e789ff078d1fef880f9dfb6adf18e8f1:
7
8
Merge remote-tracking branch 'remotes/kraxel/tags/vga-20181029-pull-request' into staging (2018-10-29 12:59:15 +0000)
9
4
10
are available in the Git repository at:
5
are available in the Git repository at:
11
6
12
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20181029
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20240308
13
8
14
for you to fetch changes up to 20cf5663734310a282e27b7389bc9f53ffe227e6:
9
for you to fetch changes up to bbf6c6dbead82292a20951eb1204442a6b838de9:
15
10
16
tests/boot-serial-test: Add microbit board testcase (2018-10-29 15:19:48 +0000)
11
target/arm: Move v7m-related code from cpu32.c into a separate file (2024-03-08 14:45:03 +0000)
17
12
18
----------------------------------------------------------------
13
----------------------------------------------------------------
19
target-arm queue:
14
target-arm queue:
20
* microbit: Add the UART to our nRF51 SoC model
15
* Implement FEAT_ECV
21
* Add a virtual Xilinx Versal board "xlnx-versal-virt"
16
* STM32L4x5: Implement GPIO device
22
* hw/arm/virt: Set VIRT_COMPAT_3_0 compat
17
* Fix 32-bit SMOPA
18
* Refactor v7m related code from cpu32.c into its own file
19
* hw/rtc/sun4v-rtc: Relicense to GPLv2-or-later
23
20
24
----------------------------------------------------------------
21
----------------------------------------------------------------
25
Edgar E. Iglesias (2):
22
Inès Varhol (3):
26
hw/arm: versal: Add a model of Xilinx Versal SoC
23
hw/gpio: Implement STM32L4x5 GPIO
27
hw/arm: versal: Add a virtual Xilinx Versal board
24
hw/arm: Connect STM32L4x5 GPIO to STM32L4x5 SoC
25
tests/qtest: Add STM32L4x5 GPIO QTest testcase
28
26
29
Eric Auger (1):
27
Peter Maydell (9):
30
hw/arm/virt: Set VIRT_COMPAT_3_0 compat
28
target/arm: Move some register related defines to internals.h
29
target/arm: Timer _EL02 registers UNDEF for E2H == 0
30
target/arm: use FIELD macro for CNTHCTL bit definitions
31
target/arm: Don't allow RES0 CNTHCTL_EL2 bits to be written
32
target/arm: Implement new FEAT_ECV trap bits
33
target/arm: Define CNTPCTSS_EL0 and CNTVCTSS_EL0
34
target/arm: Implement FEAT_ECV CNTPOFF_EL2 handling
35
target/arm: Enable FEAT_ECV for 'max' CPU
36
hw/rtc/sun4v-rtc: Relicense to GPLv2-or-later
31
37
32
Julia Suvorova (3):
38
Richard Henderson (1):
33
hw/char: Implement nRF51 SoC UART
39
target/arm: Fix 32-bit SMOPA
34
hw/arm/nrf51_soc: Connect UART to nRF51 SoC
35
tests/boot-serial-test: Add microbit board testcase
36
40
37
hw/arm/Makefile.objs | 1 +
41
Thomas Huth (1):
38
hw/char/Makefile.objs | 1 +
42
target/arm: Move v7m-related code from cpu32.c into a separate file
39
include/hw/arm/nrf51_soc.h | 3 +
40
include/hw/arm/xlnx-versal.h | 122 +++++++++
41
include/hw/char/nrf51_uart.h | 78 ++++++
42
hw/arm/microbit.c | 2 +
43
hw/arm/nrf51_soc.c | 20 ++
44
hw/arm/virt.c | 4 +
45
hw/arm/xlnx-versal-virt.c | 493 ++++++++++++++++++++++++++++++++++++
46
hw/arm/xlnx-versal.c | 323 +++++++++++++++++++++++
47
hw/char/nrf51_uart.c | 330 ++++++++++++++++++++++++
48
tests/boot-serial-test.c | 19 ++
49
default-configs/aarch64-softmmu.mak | 1 +
50
hw/char/trace-events | 4 +
51
14 files changed, 1401 insertions(+)
52
create mode 100644 include/hw/arm/xlnx-versal.h
53
create mode 100644 include/hw/char/nrf51_uart.h
54
create mode 100644 hw/arm/xlnx-versal-virt.c
55
create mode 100644 hw/arm/xlnx-versal.c
56
create mode 100644 hw/char/nrf51_uart.c
57
43
44
MAINTAINERS | 1 +
45
docs/system/arm/b-l475e-iot01a.rst | 2 +-
46
docs/system/arm/emulation.rst | 1 +
47
include/hw/arm/stm32l4x5_soc.h | 2 +
48
include/hw/gpio/stm32l4x5_gpio.h | 71 +++++
49
include/hw/misc/stm32l4x5_syscfg.h | 3 +-
50
include/hw/rtc/sun4v-rtc.h | 2 +-
51
target/arm/cpu-features.h | 10 +
52
target/arm/cpu.h | 129 +--------
53
target/arm/internals.h | 151 ++++++++++
54
hw/arm/stm32l4x5_soc.c | 71 ++++-
55
hw/gpio/stm32l4x5_gpio.c | 477 ++++++++++++++++++++++++++++++++
56
hw/misc/stm32l4x5_syscfg.c | 1 +
57
hw/rtc/sun4v-rtc.c | 2 +-
58
target/arm/helper.c | 189 ++++++++++++-
59
target/arm/tcg/cpu-v7m.c | 290 +++++++++++++++++++
60
target/arm/tcg/cpu32.c | 261 ------------------
61
target/arm/tcg/cpu64.c | 1 +
62
target/arm/tcg/sme_helper.c | 77 +++---
63
tests/qtest/stm32l4x5_gpio-test.c | 551 +++++++++++++++++++++++++++++++++++++
64
tests/tcg/aarch64/sme-smopa-1.c | 47 ++++
65
tests/tcg/aarch64/sme-smopa-2.c | 54 ++++
66
hw/arm/Kconfig | 3 +-
67
hw/gpio/Kconfig | 3 +
68
hw/gpio/meson.build | 1 +
69
hw/gpio/trace-events | 6 +
70
target/arm/meson.build | 3 +
71
target/arm/tcg/meson.build | 3 +
72
target/arm/trace-events | 1 +
73
tests/qtest/meson.build | 3 +-
74
tests/tcg/aarch64/Makefile.target | 2 +-
75
31 files changed, 1962 insertions(+), 456 deletions(-)
76
create mode 100644 include/hw/gpio/stm32l4x5_gpio.h
77
create mode 100644 hw/gpio/stm32l4x5_gpio.c
78
create mode 100644 target/arm/tcg/cpu-v7m.c
79
create mode 100644 tests/qtest/stm32l4x5_gpio-test.c
80
create mode 100644 tests/tcg/aarch64/sme-smopa-1.c
81
create mode 100644 tests/tcg/aarch64/sme-smopa-2.c
82
diff view generated by jsdifflib
New patch
1
cpu.h has a lot of #defines relating to CPU register fields.
2
Most of these aren't actually used outside target/arm code,
3
so there's no point in cluttering up the cpu.h file with them.
4
Move some easy ones to internals.h.
1
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20240301183219.2424889-2-peter.maydell@linaro.org
10
---
11
target/arm/cpu.h | 128 -----------------------------------------
12
target/arm/internals.h | 128 +++++++++++++++++++++++++++++++++++++++++
13
2 files changed, 128 insertions(+), 128 deletions(-)
14
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/cpu.h
18
+++ b/target/arm/cpu.h
19
@@ -XXX,XX +XXX,XX @@ typedef struct ARMGenericTimer {
20
uint64_t ctl; /* Timer Control register */
21
} ARMGenericTimer;
22
23
-#define VTCR_NSW (1u << 29)
24
-#define VTCR_NSA (1u << 30)
25
-#define VSTCR_SW VTCR_NSW
26
-#define VSTCR_SA VTCR_NSA
27
-
28
/* Define a maximum sized vector register.
29
* For 32-bit, this is a 128-bit NEON/AdvSIMD register.
30
* For 64-bit, this is a 2048-bit SVE register.
31
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
32
#define SCTLR_SPINTMASK (1ULL << 62) /* FEAT_NMI */
33
#define SCTLR_TIDCP (1ULL << 63) /* FEAT_TIDCP1 */
34
35
-/* Bit definitions for CPACR (AArch32 only) */
36
-FIELD(CPACR, CP10, 20, 2)
37
-FIELD(CPACR, CP11, 22, 2)
38
-FIELD(CPACR, TRCDIS, 28, 1) /* matches CPACR_EL1.TTA */
39
-FIELD(CPACR, D32DIS, 30, 1) /* up to v7; RAZ in v8 */
40
-FIELD(CPACR, ASEDIS, 31, 1)
41
-
42
-/* Bit definitions for CPACR_EL1 (AArch64 only) */
43
-FIELD(CPACR_EL1, ZEN, 16, 2)
44
-FIELD(CPACR_EL1, FPEN, 20, 2)
45
-FIELD(CPACR_EL1, SMEN, 24, 2)
46
-FIELD(CPACR_EL1, TTA, 28, 1) /* matches CPACR.TRCDIS */
47
-
48
-/* Bit definitions for HCPTR (AArch32 only) */
49
-FIELD(HCPTR, TCP10, 10, 1)
50
-FIELD(HCPTR, TCP11, 11, 1)
51
-FIELD(HCPTR, TASE, 15, 1)
52
-FIELD(HCPTR, TTA, 20, 1)
53
-FIELD(HCPTR, TAM, 30, 1) /* matches CPTR_EL2.TAM */
54
-FIELD(HCPTR, TCPAC, 31, 1) /* matches CPTR_EL2.TCPAC */
55
-
56
-/* Bit definitions for CPTR_EL2 (AArch64 only) */
57
-FIELD(CPTR_EL2, TZ, 8, 1) /* !E2H */
58
-FIELD(CPTR_EL2, TFP, 10, 1) /* !E2H, matches HCPTR.TCP10 */
59
-FIELD(CPTR_EL2, TSM, 12, 1) /* !E2H */
60
-FIELD(CPTR_EL2, ZEN, 16, 2) /* E2H */
61
-FIELD(CPTR_EL2, FPEN, 20, 2) /* E2H */
62
-FIELD(CPTR_EL2, SMEN, 24, 2) /* E2H */
63
-FIELD(CPTR_EL2, TTA, 28, 1)
64
-FIELD(CPTR_EL2, TAM, 30, 1) /* matches HCPTR.TAM */
65
-FIELD(CPTR_EL2, TCPAC, 31, 1) /* matches HCPTR.TCPAC */
66
-
67
-/* Bit definitions for CPTR_EL3 (AArch64 only) */
68
-FIELD(CPTR_EL3, EZ, 8, 1)
69
-FIELD(CPTR_EL3, TFP, 10, 1)
70
-FIELD(CPTR_EL3, ESM, 12, 1)
71
-FIELD(CPTR_EL3, TTA, 20, 1)
72
-FIELD(CPTR_EL3, TAM, 30, 1)
73
-FIELD(CPTR_EL3, TCPAC, 31, 1)
74
-
75
-#define MDCR_MTPME (1U << 28)
76
-#define MDCR_TDCC (1U << 27)
77
-#define MDCR_HLP (1U << 26) /* MDCR_EL2 */
78
-#define MDCR_SCCD (1U << 23) /* MDCR_EL3 */
79
-#define MDCR_HCCD (1U << 23) /* MDCR_EL2 */
80
-#define MDCR_EPMAD (1U << 21)
81
-#define MDCR_EDAD (1U << 20)
82
-#define MDCR_TTRF (1U << 19)
83
-#define MDCR_STE (1U << 18) /* MDCR_EL3 */
84
-#define MDCR_SPME (1U << 17) /* MDCR_EL3 */
85
-#define MDCR_HPMD (1U << 17) /* MDCR_EL2 */
86
-#define MDCR_SDD (1U << 16)
87
-#define MDCR_SPD (3U << 14)
88
-#define MDCR_TDRA (1U << 11)
89
-#define MDCR_TDOSA (1U << 10)
90
-#define MDCR_TDA (1U << 9)
91
-#define MDCR_TDE (1U << 8)
92
-#define MDCR_HPME (1U << 7)
93
-#define MDCR_TPM (1U << 6)
94
-#define MDCR_TPMCR (1U << 5)
95
-#define MDCR_HPMN (0x1fU)
96
-
97
-/* Not all of the MDCR_EL3 bits are present in the 32-bit SDCR */
98
-#define SDCR_VALID_MASK (MDCR_MTPME | MDCR_TDCC | MDCR_SCCD | \
99
- MDCR_EPMAD | MDCR_EDAD | MDCR_TTRF | \
100
- MDCR_STE | MDCR_SPME | MDCR_SPD)
101
-
102
#define CPSR_M (0x1fU)
103
#define CPSR_T (1U << 5)
104
#define CPSR_F (1U << 6)
105
@@ -XXX,XX +XXX,XX @@ FIELD(CPTR_EL3, TCPAC, 31, 1)
106
#define XPSR_NZCV CPSR_NZCV
107
#define XPSR_IT CPSR_IT
108
109
-#define TTBCR_N (7U << 0) /* TTBCR.EAE==0 */
110
-#define TTBCR_T0SZ (7U << 0) /* TTBCR.EAE==1 */
111
-#define TTBCR_PD0 (1U << 4)
112
-#define TTBCR_PD1 (1U << 5)
113
-#define TTBCR_EPD0 (1U << 7)
114
-#define TTBCR_IRGN0 (3U << 8)
115
-#define TTBCR_ORGN0 (3U << 10)
116
-#define TTBCR_SH0 (3U << 12)
117
-#define TTBCR_T1SZ (3U << 16)
118
-#define TTBCR_A1 (1U << 22)
119
-#define TTBCR_EPD1 (1U << 23)
120
-#define TTBCR_IRGN1 (3U << 24)
121
-#define TTBCR_ORGN1 (3U << 26)
122
-#define TTBCR_SH1 (1U << 28)
123
-#define TTBCR_EAE (1U << 31)
124
-
125
-FIELD(VTCR, T0SZ, 0, 6)
126
-FIELD(VTCR, SL0, 6, 2)
127
-FIELD(VTCR, IRGN0, 8, 2)
128
-FIELD(VTCR, ORGN0, 10, 2)
129
-FIELD(VTCR, SH0, 12, 2)
130
-FIELD(VTCR, TG0, 14, 2)
131
-FIELD(VTCR, PS, 16, 3)
132
-FIELD(VTCR, VS, 19, 1)
133
-FIELD(VTCR, HA, 21, 1)
134
-FIELD(VTCR, HD, 22, 1)
135
-FIELD(VTCR, HWU59, 25, 1)
136
-FIELD(VTCR, HWU60, 26, 1)
137
-FIELD(VTCR, HWU61, 27, 1)
138
-FIELD(VTCR, HWU62, 28, 1)
139
-FIELD(VTCR, NSW, 29, 1)
140
-FIELD(VTCR, NSA, 30, 1)
141
-FIELD(VTCR, DS, 32, 1)
142
-FIELD(VTCR, SL2, 33, 1)
143
-
144
/* Bit definitions for ARMv8 SPSR (PSTATE) format.
145
* Only these are valid when in AArch64 mode; in
146
* AArch32 mode SPSRs are basically CPSR-format.
147
@@ -XXX,XX +XXX,XX @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
148
#define HCR_TWEDEN (1ULL << 59)
149
#define HCR_TWEDEL MAKE_64BIT_MASK(60, 4)
150
151
-#define HCRX_ENAS0 (1ULL << 0)
152
-#define HCRX_ENALS (1ULL << 1)
153
-#define HCRX_ENASR (1ULL << 2)
154
-#define HCRX_FNXS (1ULL << 3)
155
-#define HCRX_FGTNXS (1ULL << 4)
156
-#define HCRX_SMPME (1ULL << 5)
157
-#define HCRX_TALLINT (1ULL << 6)
158
-#define HCRX_VINMI (1ULL << 7)
159
-#define HCRX_VFNMI (1ULL << 8)
160
-#define HCRX_CMOW (1ULL << 9)
161
-#define HCRX_MCE2 (1ULL << 10)
162
-#define HCRX_MSCEN (1ULL << 11)
163
-
164
-#define HPFAR_NS (1ULL << 63)
165
-
166
#define SCR_NS (1ULL << 0)
167
#define SCR_IRQ (1ULL << 1)
168
#define SCR_FIQ (1ULL << 2)
169
@@ -XXX,XX +XXX,XX @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
170
#define SCR_GPF (1ULL << 48)
171
#define SCR_NSE (1ULL << 62)
172
173
-#define HSTR_TTEE (1 << 16)
174
-#define HSTR_TJDBX (1 << 17)
175
-
176
-#define CNTHCTL_CNTVMASK (1 << 18)
177
-#define CNTHCTL_CNTPMASK (1 << 19)
178
-
179
/* Return the current FPSCR value. */
180
uint32_t vfp_get_fpscr(CPUARMState *env);
181
void vfp_set_fpscr(CPUARMState *env, uint32_t val);
182
diff --git a/target/arm/internals.h b/target/arm/internals.h
183
index XXXXXXX..XXXXXXX 100644
184
--- a/target/arm/internals.h
185
+++ b/target/arm/internals.h
186
@@ -XXX,XX +XXX,XX @@ FIELD(DBGWCR, WT, 20, 1)
187
FIELD(DBGWCR, MASK, 24, 5)
188
FIELD(DBGWCR, SSCE, 29, 1)
189
190
+#define VTCR_NSW (1u << 29)
191
+#define VTCR_NSA (1u << 30)
192
+#define VSTCR_SW VTCR_NSW
193
+#define VSTCR_SA VTCR_NSA
194
+
195
+/* Bit definitions for CPACR (AArch32 only) */
196
+FIELD(CPACR, CP10, 20, 2)
197
+FIELD(CPACR, CP11, 22, 2)
198
+FIELD(CPACR, TRCDIS, 28, 1) /* matches CPACR_EL1.TTA */
199
+FIELD(CPACR, D32DIS, 30, 1) /* up to v7; RAZ in v8 */
200
+FIELD(CPACR, ASEDIS, 31, 1)
201
+
202
+/* Bit definitions for CPACR_EL1 (AArch64 only) */
203
+FIELD(CPACR_EL1, ZEN, 16, 2)
204
+FIELD(CPACR_EL1, FPEN, 20, 2)
205
+FIELD(CPACR_EL1, SMEN, 24, 2)
206
+FIELD(CPACR_EL1, TTA, 28, 1) /* matches CPACR.TRCDIS */
207
+
208
+/* Bit definitions for HCPTR (AArch32 only) */
209
+FIELD(HCPTR, TCP10, 10, 1)
210
+FIELD(HCPTR, TCP11, 11, 1)
211
+FIELD(HCPTR, TASE, 15, 1)
212
+FIELD(HCPTR, TTA, 20, 1)
213
+FIELD(HCPTR, TAM, 30, 1) /* matches CPTR_EL2.TAM */
214
+FIELD(HCPTR, TCPAC, 31, 1) /* matches CPTR_EL2.TCPAC */
215
+
216
+/* Bit definitions for CPTR_EL2 (AArch64 only) */
217
+FIELD(CPTR_EL2, TZ, 8, 1) /* !E2H */
218
+FIELD(CPTR_EL2, TFP, 10, 1) /* !E2H, matches HCPTR.TCP10 */
219
+FIELD(CPTR_EL2, TSM, 12, 1) /* !E2H */
220
+FIELD(CPTR_EL2, ZEN, 16, 2) /* E2H */
221
+FIELD(CPTR_EL2, FPEN, 20, 2) /* E2H */
222
+FIELD(CPTR_EL2, SMEN, 24, 2) /* E2H */
223
+FIELD(CPTR_EL2, TTA, 28, 1)
224
+FIELD(CPTR_EL2, TAM, 30, 1) /* matches HCPTR.TAM */
225
+FIELD(CPTR_EL2, TCPAC, 31, 1) /* matches HCPTR.TCPAC */
226
+
227
+/* Bit definitions for CPTR_EL3 (AArch64 only) */
228
+FIELD(CPTR_EL3, EZ, 8, 1)
229
+FIELD(CPTR_EL3, TFP, 10, 1)
230
+FIELD(CPTR_EL3, ESM, 12, 1)
231
+FIELD(CPTR_EL3, TTA, 20, 1)
232
+FIELD(CPTR_EL3, TAM, 30, 1)
233
+FIELD(CPTR_EL3, TCPAC, 31, 1)
234
+
235
+#define MDCR_MTPME (1U << 28)
236
+#define MDCR_TDCC (1U << 27)
237
+#define MDCR_HLP (1U << 26) /* MDCR_EL2 */
238
+#define MDCR_SCCD (1U << 23) /* MDCR_EL3 */
239
+#define MDCR_HCCD (1U << 23) /* MDCR_EL2 */
240
+#define MDCR_EPMAD (1U << 21)
241
+#define MDCR_EDAD (1U << 20)
242
+#define MDCR_TTRF (1U << 19)
243
+#define MDCR_STE (1U << 18) /* MDCR_EL3 */
244
+#define MDCR_SPME (1U << 17) /* MDCR_EL3 */
245
+#define MDCR_HPMD (1U << 17) /* MDCR_EL2 */
246
+#define MDCR_SDD (1U << 16)
247
+#define MDCR_SPD (3U << 14)
248
+#define MDCR_TDRA (1U << 11)
249
+#define MDCR_TDOSA (1U << 10)
250
+#define MDCR_TDA (1U << 9)
251
+#define MDCR_TDE (1U << 8)
252
+#define MDCR_HPME (1U << 7)
253
+#define MDCR_TPM (1U << 6)
254
+#define MDCR_TPMCR (1U << 5)
255
+#define MDCR_HPMN (0x1fU)
256
+
257
+/* Not all of the MDCR_EL3 bits are present in the 32-bit SDCR */
258
+#define SDCR_VALID_MASK (MDCR_MTPME | MDCR_TDCC | MDCR_SCCD | \
259
+ MDCR_EPMAD | MDCR_EDAD | MDCR_TTRF | \
260
+ MDCR_STE | MDCR_SPME | MDCR_SPD)
261
+
262
+#define TTBCR_N (7U << 0) /* TTBCR.EAE==0 */
263
+#define TTBCR_T0SZ (7U << 0) /* TTBCR.EAE==1 */
264
+#define TTBCR_PD0 (1U << 4)
265
+#define TTBCR_PD1 (1U << 5)
266
+#define TTBCR_EPD0 (1U << 7)
267
+#define TTBCR_IRGN0 (3U << 8)
268
+#define TTBCR_ORGN0 (3U << 10)
269
+#define TTBCR_SH0 (3U << 12)
270
+#define TTBCR_T1SZ (3U << 16)
271
+#define TTBCR_A1 (1U << 22)
272
+#define TTBCR_EPD1 (1U << 23)
273
+#define TTBCR_IRGN1 (3U << 24)
274
+#define TTBCR_ORGN1 (3U << 26)
275
+#define TTBCR_SH1 (1U << 28)
276
+#define TTBCR_EAE (1U << 31)
277
+
278
+FIELD(VTCR, T0SZ, 0, 6)
279
+FIELD(VTCR, SL0, 6, 2)
280
+FIELD(VTCR, IRGN0, 8, 2)
281
+FIELD(VTCR, ORGN0, 10, 2)
282
+FIELD(VTCR, SH0, 12, 2)
283
+FIELD(VTCR, TG0, 14, 2)
284
+FIELD(VTCR, PS, 16, 3)
285
+FIELD(VTCR, VS, 19, 1)
286
+FIELD(VTCR, HA, 21, 1)
287
+FIELD(VTCR, HD, 22, 1)
288
+FIELD(VTCR, HWU59, 25, 1)
289
+FIELD(VTCR, HWU60, 26, 1)
290
+FIELD(VTCR, HWU61, 27, 1)
291
+FIELD(VTCR, HWU62, 28, 1)
292
+FIELD(VTCR, NSW, 29, 1)
293
+FIELD(VTCR, NSA, 30, 1)
294
+FIELD(VTCR, DS, 32, 1)
295
+FIELD(VTCR, SL2, 33, 1)
296
+
297
+#define HCRX_ENAS0 (1ULL << 0)
298
+#define HCRX_ENALS (1ULL << 1)
299
+#define HCRX_ENASR (1ULL << 2)
300
+#define HCRX_FNXS (1ULL << 3)
301
+#define HCRX_FGTNXS (1ULL << 4)
302
+#define HCRX_SMPME (1ULL << 5)
303
+#define HCRX_TALLINT (1ULL << 6)
304
+#define HCRX_VINMI (1ULL << 7)
305
+#define HCRX_VFNMI (1ULL << 8)
306
+#define HCRX_CMOW (1ULL << 9)
307
+#define HCRX_MCE2 (1ULL << 10)
308
+#define HCRX_MSCEN (1ULL << 11)
309
+
310
+#define HPFAR_NS (1ULL << 63)
311
+
312
+#define HSTR_TTEE (1 << 16)
313
+#define HSTR_TJDBX (1 << 17)
314
+
315
+#define CNTHCTL_CNTVMASK (1 << 18)
316
+#define CNTHCTL_CNTPMASK (1 << 19)
317
+
318
/* We use a few fake FSR values for internal purposes in M profile.
319
* M profile cores don't have A/R format FSRs, but currently our
320
* get_phys_addr() code assumes A/R profile and reports failures via
321
--
322
2.34.1
323
324
diff view generated by jsdifflib
New patch
1
The timer _EL02 registers should UNDEF for invalid accesses from EL2
2
or EL3 when HCR_EL2.E2H == 0, not take a cp access trap. We were
3
delivering the exception to EL2 with the wrong syndrome.
1
4
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20240301183219.2424889-3-peter.maydell@linaro.org
8
---
9
target/arm/helper.c | 2 +-
10
1 file changed, 1 insertion(+), 1 deletion(-)
11
12
diff --git a/target/arm/helper.c b/target/arm/helper.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/helper.c
15
+++ b/target/arm/helper.c
16
@@ -XXX,XX +XXX,XX @@ static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
17
return CP_ACCESS_OK;
18
}
19
if (!(arm_hcr_el2_eff(env) & HCR_E2H)) {
20
- return CP_ACCESS_TRAP;
21
+ return CP_ACCESS_TRAP_UNCATEGORIZED;
22
}
23
return CP_ACCESS_OK;
24
}
25
--
26
2.34.1
diff view generated by jsdifflib
New patch
1
We prefer the FIELD macro over ad-hoc #defines for register bits;
2
switch CNTHCTL to that style before we add any more bits.
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20240301183219.2424889-4-peter.maydell@linaro.org
8
---
9
target/arm/internals.h | 27 +++++++++++++++++++++++++--
10
target/arm/helper.c | 9 ++++-----
11
2 files changed, 29 insertions(+), 7 deletions(-)
12
13
diff --git a/target/arm/internals.h b/target/arm/internals.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/internals.h
16
+++ b/target/arm/internals.h
17
@@ -XXX,XX +XXX,XX @@ FIELD(VTCR, SL2, 33, 1)
18
#define HSTR_TTEE (1 << 16)
19
#define HSTR_TJDBX (1 << 17)
20
21
-#define CNTHCTL_CNTVMASK (1 << 18)
22
-#define CNTHCTL_CNTPMASK (1 << 19)
23
+/*
24
+ * Depending on the value of HCR_EL2.E2H, bits 0 and 1
25
+ * have different bit definitions, and EL1PCTEN might be
26
+ * bit 0 or bit 10. We use _E2H1 and _E2H0 suffixes to
27
+ * disambiguate if necessary.
28
+ */
29
+FIELD(CNTHCTL, EL0PCTEN_E2H1, 0, 1)
30
+FIELD(CNTHCTL, EL0VCTEN_E2H1, 1, 1)
31
+FIELD(CNTHCTL, EL1PCTEN_E2H0, 0, 1)
32
+FIELD(CNTHCTL, EL1PCEN_E2H0, 1, 1)
33
+FIELD(CNTHCTL, EVNTEN, 2, 1)
34
+FIELD(CNTHCTL, EVNTDIR, 3, 1)
35
+FIELD(CNTHCTL, EVNTI, 4, 4)
36
+FIELD(CNTHCTL, EL0VTEN, 8, 1)
37
+FIELD(CNTHCTL, EL0PTEN, 9, 1)
38
+FIELD(CNTHCTL, EL1PCTEN_E2H1, 10, 1)
39
+FIELD(CNTHCTL, EL1PTEN, 11, 1)
40
+FIELD(CNTHCTL, ECV, 12, 1)
41
+FIELD(CNTHCTL, EL1TVT, 13, 1)
42
+FIELD(CNTHCTL, EL1TVCT, 14, 1)
43
+FIELD(CNTHCTL, EL1NVPCT, 15, 1)
44
+FIELD(CNTHCTL, EL1NVVCT, 16, 1)
45
+FIELD(CNTHCTL, EVNTIS, 17, 1)
46
+FIELD(CNTHCTL, CNTVMASK, 18, 1)
47
+FIELD(CNTHCTL, CNTPMASK, 19, 1)
48
49
/* We use a few fake FSR values for internal purposes in M profile.
50
* M profile cores don't have A/R format FSRs, but currently our
51
diff --git a/target/arm/helper.c b/target/arm/helper.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/helper.c
54
+++ b/target/arm/helper.c
55
@@ -XXX,XX +XXX,XX @@ static void gt_update_irq(ARMCPU *cpu, int timeridx)
56
* It is RES0 in Secure and NonSecure state.
57
*/
58
if ((ss == ARMSS_Root || ss == ARMSS_Realm) &&
59
- ((timeridx == GTIMER_VIRT && (cnthctl & CNTHCTL_CNTVMASK)) ||
60
- (timeridx == GTIMER_PHYS && (cnthctl & CNTHCTL_CNTPMASK)))) {
61
+ ((timeridx == GTIMER_VIRT && (cnthctl & R_CNTHCTL_CNTVMASK_MASK)) ||
62
+ (timeridx == GTIMER_PHYS && (cnthctl & R_CNTHCTL_CNTPMASK_MASK)))) {
63
irqstate = 0;
64
}
65
66
@@ -XXX,XX +XXX,XX @@ static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
67
{
68
ARMCPU *cpu = env_archcpu(env);
69
uint32_t oldval = env->cp15.cnthctl_el2;
70
-
71
raw_write(env, ri, value);
72
73
- if ((oldval ^ value) & CNTHCTL_CNTVMASK) {
74
+ if ((oldval ^ value) & R_CNTHCTL_CNTVMASK_MASK) {
75
gt_update_irq(cpu, GTIMER_VIRT);
76
- } else if ((oldval ^ value) & CNTHCTL_CNTPMASK) {
77
+ } else if ((oldval ^ value) & R_CNTHCTL_CNTPMASK_MASK) {
78
gt_update_irq(cpu, GTIMER_PHYS);
79
}
80
}
81
--
82
2.34.1
83
84
diff view generated by jsdifflib
New patch
1
Don't allow the guest to write CNTHCTL_EL2 bits which don't exist.
2
This is not strictly architecturally required, but it is how we've
3
tended to implement registers more recently.
1
4
5
In particular, bits [19:18] are only present with FEAT_RME,
6
and bits [17:12] will only be present with FEAT_ECV.
7
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20240301183219.2424889-5-peter.maydell@linaro.org
11
---
12
target/arm/helper.c | 18 ++++++++++++++++++
13
1 file changed, 18 insertions(+)
14
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.c
18
+++ b/target/arm/helper.c
19
@@ -XXX,XX +XXX,XX @@ static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
20
{
21
ARMCPU *cpu = env_archcpu(env);
22
uint32_t oldval = env->cp15.cnthctl_el2;
23
+ uint32_t valid_mask =
24
+ R_CNTHCTL_EL0PCTEN_E2H1_MASK |
25
+ R_CNTHCTL_EL0VCTEN_E2H1_MASK |
26
+ R_CNTHCTL_EVNTEN_MASK |
27
+ R_CNTHCTL_EVNTDIR_MASK |
28
+ R_CNTHCTL_EVNTI_MASK |
29
+ R_CNTHCTL_EL0VTEN_MASK |
30
+ R_CNTHCTL_EL0PTEN_MASK |
31
+ R_CNTHCTL_EL1PCTEN_E2H1_MASK |
32
+ R_CNTHCTL_EL1PTEN_MASK;
33
+
34
+ if (cpu_isar_feature(aa64_rme, cpu)) {
35
+ valid_mask |= R_CNTHCTL_CNTVMASK_MASK | R_CNTHCTL_CNTPMASK_MASK;
36
+ }
37
+
38
+ /* Clear RES0 bits */
39
+ value &= valid_mask;
40
+
41
raw_write(env, ri, value);
42
43
if ((oldval ^ value) & R_CNTHCTL_CNTVMASK_MASK) {
44
--
45
2.34.1
diff view generated by jsdifflib
New patch
1
The functionality defined by ID_AA64MMFR0_EL1.ECV == 1 is:
2
* four new trap bits for various counter and timer registers
3
* the CNTHCTL_EL2.EVNTIS and CNTKCTL_EL1.EVNTIS bits which control
4
scaling of the event stream. This is a no-op for us, because we don't
5
implement the event stream (our WFE is a NOP): all we need to do is
6
allow CNTHCTL_EL2.ENVTIS to be read and written.
7
* extensions to PMSCR_EL1.PCT, PMSCR_EL2.PCT, TRFCR_EL1.TS and
8
TRFCR_EL2.TS: these are all no-ops for us, because we don't implement
9
FEAT_SPE or FEAT_TRF.
10
* new registers CNTPCTSS_EL0 and NCTVCTSS_EL0 which are
11
"self-sychronizing" views of the CNTPCT_EL0 and CNTVCT_EL0, meaning
12
that no barriers are needed around their accesses. For us these
13
are just the same as the normal views, because all our sysregs are
14
inherently self-sychronizing.
1
15
16
In this commit we implement the trap handling and permit the new
17
CNTHCTL_EL2 bits to be written.
18
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 20240301183219.2424889-6-peter.maydell@linaro.org
22
---
23
target/arm/cpu-features.h | 5 ++++
24
target/arm/helper.c | 51 +++++++++++++++++++++++++++++++++++----
25
2 files changed, 51 insertions(+), 5 deletions(-)
26
27
diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
28
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/cpu-features.h
30
+++ b/target/arm/cpu-features.h
31
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_fgt(const ARMISARegisters *id)
32
return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, FGT) != 0;
33
}
34
35
+static inline bool isar_feature_aa64_ecv_traps(const ARMISARegisters *id)
36
+{
37
+ return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, ECV) > 0;
38
+}
39
+
40
static inline bool isar_feature_aa64_vh(const ARMISARegisters *id)
41
{
42
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0;
43
diff --git a/target/arm/helper.c b/target/arm/helper.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/helper.c
46
+++ b/target/arm/helper.c
47
@@ -XXX,XX +XXX,XX @@ static CPAccessResult gt_counter_access(CPUARMState *env, int timeridx,
48
: !extract32(env->cp15.cnthctl_el2, 0, 1))) {
49
return CP_ACCESS_TRAP_EL2;
50
}
51
+ if (has_el2 && timeridx == GTIMER_VIRT) {
52
+ if (FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, EL1TVCT)) {
53
+ return CP_ACCESS_TRAP_EL2;
54
+ }
55
+ }
56
break;
57
}
58
return CP_ACCESS_OK;
59
@@ -XXX,XX +XXX,XX @@ static CPAccessResult gt_timer_access(CPUARMState *env, int timeridx,
60
}
61
}
62
}
63
+ if (has_el2 && timeridx == GTIMER_VIRT) {
64
+ if (FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, EL1TVT)) {
65
+ return CP_ACCESS_TRAP_EL2;
66
+ }
67
+ }
68
break;
69
}
70
return CP_ACCESS_OK;
71
@@ -XXX,XX +XXX,XX @@ static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
72
if (cpu_isar_feature(aa64_rme, cpu)) {
73
valid_mask |= R_CNTHCTL_CNTVMASK_MASK | R_CNTHCTL_CNTPMASK_MASK;
74
}
75
+ if (cpu_isar_feature(aa64_ecv_traps, cpu)) {
76
+ valid_mask |=
77
+ R_CNTHCTL_EL1TVT_MASK |
78
+ R_CNTHCTL_EL1TVCT_MASK |
79
+ R_CNTHCTL_EL1NVPCT_MASK |
80
+ R_CNTHCTL_EL1NVVCT_MASK |
81
+ R_CNTHCTL_EVNTIS_MASK;
82
+ }
83
84
/* Clear RES0 bits */
85
value &= valid_mask;
86
@@ -XXX,XX +XXX,XX @@ static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
87
{
88
if (arm_current_el(env) == 1) {
89
/* This must be a FEAT_NV access */
90
- /* TODO: FEAT_ECV will need to check CNTHCTL_EL2 here */
91
return CP_ACCESS_OK;
92
}
93
if (!(arm_hcr_el2_eff(env) & HCR_E2H)) {
94
@@ -XXX,XX +XXX,XX @@ static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
95
return CP_ACCESS_OK;
96
}
97
98
+static CPAccessResult access_el1nvpct(CPUARMState *env, const ARMCPRegInfo *ri,
99
+ bool isread)
100
+{
101
+ if (arm_current_el(env) == 1) {
102
+ /* This must be a FEAT_NV access with NVx == 101 */
103
+ if (FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, EL1NVPCT)) {
104
+ return CP_ACCESS_TRAP_EL2;
105
+ }
106
+ }
107
+ return e2h_access(env, ri, isread);
108
+}
109
+
110
+static CPAccessResult access_el1nvvct(CPUARMState *env, const ARMCPRegInfo *ri,
111
+ bool isread)
112
+{
113
+ if (arm_current_el(env) == 1) {
114
+ /* This must be a FEAT_NV access with NVx == 101 */
115
+ if (FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, EL1NVVCT)) {
116
+ return CP_ACCESS_TRAP_EL2;
117
+ }
118
+ }
119
+ return e2h_access(env, ri, isread);
120
+}
121
+
122
/* Test if system register redirection is to occur in the current state. */
123
static bool redirect_for_e2h(CPUARMState *env)
124
{
125
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vhe_reginfo[] = {
126
{ .name = "CNTP_CTL_EL02", .state = ARM_CP_STATE_AA64,
127
.opc0 = 3, .opc1 = 5, .crn = 14, .crm = 2, .opc2 = 1,
128
.type = ARM_CP_IO | ARM_CP_ALIAS,
129
- .access = PL2_RW, .accessfn = e2h_access,
130
+ .access = PL2_RW, .accessfn = access_el1nvpct,
131
.nv2_redirect_offset = 0x180 | NV2_REDIR_NO_NV1,
132
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].ctl),
133
.writefn = gt_phys_ctl_write, .raw_writefn = raw_write },
134
{ .name = "CNTV_CTL_EL02", .state = ARM_CP_STATE_AA64,
135
.opc0 = 3, .opc1 = 5, .crn = 14, .crm = 3, .opc2 = 1,
136
.type = ARM_CP_IO | ARM_CP_ALIAS,
137
- .access = PL2_RW, .accessfn = e2h_access,
138
+ .access = PL2_RW, .accessfn = access_el1nvvct,
139
.nv2_redirect_offset = 0x170 | NV2_REDIR_NO_NV1,
140
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].ctl),
141
.writefn = gt_virt_ctl_write, .raw_writefn = raw_write },
142
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vhe_reginfo[] = {
143
.type = ARM_CP_IO | ARM_CP_ALIAS,
144
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].cval),
145
.nv2_redirect_offset = 0x178 | NV2_REDIR_NO_NV1,
146
- .access = PL2_RW, .accessfn = e2h_access,
147
+ .access = PL2_RW, .accessfn = access_el1nvpct,
148
.writefn = gt_phys_cval_write, .raw_writefn = raw_write },
149
{ .name = "CNTV_CVAL_EL02", .state = ARM_CP_STATE_AA64,
150
.opc0 = 3, .opc1 = 5, .crn = 14, .crm = 3, .opc2 = 2,
151
.type = ARM_CP_IO | ARM_CP_ALIAS,
152
.nv2_redirect_offset = 0x168 | NV2_REDIR_NO_NV1,
153
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].cval),
154
- .access = PL2_RW, .accessfn = e2h_access,
155
+ .access = PL2_RW, .accessfn = access_el1nvvct,
156
.writefn = gt_virt_cval_write, .raw_writefn = raw_write },
157
#endif
158
};
159
--
160
2.34.1
diff view generated by jsdifflib
New patch
1
For FEAT_ECV, new registers CNTPCTSS_EL0 and CNTVCTSS_EL0 are
2
defined, which are "self-synchronized" views of the physical and
3
virtual counts as seen in the CNTPCT_EL0 and CNTVCT_EL0 registers
4
(meaning that no barriers are needed around accesses to them to
5
ensure that reads of them do not occur speculatively and out-of-order
6
with other instructions).
1
7
8
For QEMU, all our system registers are self-synchronized, so we can
9
simply copy the existing implementation of CNTPCT_EL0 and CNTVCT_EL0
10
to the new register encodings.
11
12
This means we now implement all the functionality required for
13
ID_AA64MMFR0_EL1.ECV == 0b0001.
14
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20240301183219.2424889-7-peter.maydell@linaro.org
18
---
19
target/arm/helper.c | 43 +++++++++++++++++++++++++++++++++++++++++++
20
1 file changed, 43 insertions(+)
21
22
diff --git a/target/arm/helper.c b/target/arm/helper.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/helper.c
25
+++ b/target/arm/helper.c
26
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
27
},
28
};
29
30
+/*
31
+ * FEAT_ECV adds extra views of CNTVCT_EL0 and CNTPCT_EL0 which
32
+ * are "self-synchronizing". For QEMU all sysregs are self-synchronizing,
33
+ * so our implementations here are identical to the normal registers.
34
+ */
35
+static const ARMCPRegInfo gen_timer_ecv_cp_reginfo[] = {
36
+ { .name = "CNTVCTSS", .cp = 15, .crm = 14, .opc1 = 9,
37
+ .access = PL0_R, .type = ARM_CP_64BIT | ARM_CP_NO_RAW | ARM_CP_IO,
38
+ .accessfn = gt_vct_access,
39
+ .readfn = gt_virt_cnt_read, .resetfn = arm_cp_reset_ignore,
40
+ },
41
+ { .name = "CNTVCTSS_EL0", .state = ARM_CP_STATE_AA64,
42
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 6,
43
+ .access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
44
+ .accessfn = gt_vct_access, .readfn = gt_virt_cnt_read,
45
+ },
46
+ { .name = "CNTPCTSS", .cp = 15, .crm = 14, .opc1 = 8,
47
+ .access = PL0_R, .type = ARM_CP_64BIT | ARM_CP_NO_RAW | ARM_CP_IO,
48
+ .accessfn = gt_pct_access,
49
+ .readfn = gt_cnt_read, .resetfn = arm_cp_reset_ignore,
50
+ },
51
+ { .name = "CNTPCTSS_EL0", .state = ARM_CP_STATE_AA64,
52
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 5,
53
+ .access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
54
+ .accessfn = gt_pct_access, .readfn = gt_cnt_read,
55
+ },
56
+};
57
+
58
#else
59
60
/*
61
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
62
},
63
};
64
65
+/*
66
+ * CNTVCTSS_EL0 has the same trap conditions as CNTVCT_EL0, so it also
67
+ * is exposed to userspace by Linux.
68
+ */
69
+static const ARMCPRegInfo gen_timer_ecv_cp_reginfo[] = {
70
+ { .name = "CNTVCTSS_EL0", .state = ARM_CP_STATE_AA64,
71
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 6,
72
+ .access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
73
+ .readfn = gt_virt_cnt_read,
74
+ },
75
+};
76
+
77
#endif
78
79
static void par_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
80
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
81
if (arm_feature(env, ARM_FEATURE_GENERIC_TIMER)) {
82
define_arm_cp_regs(cpu, generic_timer_cp_reginfo);
83
}
84
+ if (cpu_isar_feature(aa64_ecv_traps, cpu)) {
85
+ define_arm_cp_regs(cpu, gen_timer_ecv_cp_reginfo);
86
+ }
87
if (arm_feature(env, ARM_FEATURE_VAPA)) {
88
ARMCPRegInfo vapa_cp_reginfo[] = {
89
{ .name = "PAR", .cp = 15, .crn = 7, .crm = 4, .opc1 = 0, .opc2 = 0,
90
--
91
2.34.1
diff view generated by jsdifflib
New patch
1
When ID_AA64MMFR0_EL1.ECV is 0b0010, a new register CNTPOFF_EL2 is
2
implemented. This is similar to the existing CNTVOFF_EL2, except
3
that it controls a hypervisor-adjustable offset made to the physical
4
counter and timer.
1
5
6
Implement the handling for this register, which includes control/trap
7
bits in SCR_EL3 and CNTHCTL_EL2.
8
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20240301183219.2424889-8-peter.maydell@linaro.org
12
---
13
target/arm/cpu-features.h | 5 +++
14
target/arm/cpu.h | 1 +
15
target/arm/helper.c | 68 +++++++++++++++++++++++++++++++++++++--
16
target/arm/trace-events | 1 +
17
4 files changed, 73 insertions(+), 2 deletions(-)
18
19
diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/cpu-features.h
22
+++ b/target/arm/cpu-features.h
23
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_ecv_traps(const ARMISARegisters *id)
24
return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, ECV) > 0;
25
}
26
27
+static inline bool isar_feature_aa64_ecv(const ARMISARegisters *id)
28
+{
29
+ return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, ECV) > 1;
30
+}
31
+
32
static inline bool isar_feature_aa64_vh(const ARMISARegisters *id)
33
{
34
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0;
35
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/cpu.h
38
+++ b/target/arm/cpu.h
39
@@ -XXX,XX +XXX,XX @@ typedef struct CPUArchState {
40
uint64_t c14_cntkctl; /* Timer Control register */
41
uint64_t cnthctl_el2; /* Counter/Timer Hyp Control register */
42
uint64_t cntvoff_el2; /* Counter Virtual Offset register */
43
+ uint64_t cntpoff_el2; /* Counter Physical Offset register */
44
ARMGenericTimer c14_timer[NUM_GTIMERS];
45
uint32_t c15_cpar; /* XScale Coprocessor Access Register */
46
uint32_t c15_ticonfig; /* TI925T configuration byte. */
47
diff --git a/target/arm/helper.c b/target/arm/helper.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/helper.c
50
+++ b/target/arm/helper.c
51
@@ -XXX,XX +XXX,XX @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
52
if (cpu_isar_feature(aa64_rme, cpu)) {
53
valid_mask |= SCR_NSE | SCR_GPF;
54
}
55
+ if (cpu_isar_feature(aa64_ecv, cpu)) {
56
+ valid_mask |= SCR_ECVEN;
57
+ }
58
} else {
59
valid_mask &= ~(SCR_RW | SCR_ST);
60
if (cpu_isar_feature(aa32_ras, cpu)) {
61
@@ -XXX,XX +XXX,XX @@ void gt_rme_post_el_change(ARMCPU *cpu, void *ignored)
62
gt_update_irq(cpu, GTIMER_PHYS);
63
}
64
65
+static uint64_t gt_phys_raw_cnt_offset(CPUARMState *env)
66
+{
67
+ if ((env->cp15.scr_el3 & SCR_ECVEN) &&
68
+ FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, ECV) &&
69
+ arm_is_el2_enabled(env) &&
70
+ (arm_hcr_el2_eff(env) & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE)) {
71
+ return env->cp15.cntpoff_el2;
72
+ }
73
+ return 0;
74
+}
75
+
76
+static uint64_t gt_phys_cnt_offset(CPUARMState *env)
77
+{
78
+ if (arm_current_el(env) >= 2) {
79
+ return 0;
80
+ }
81
+ return gt_phys_raw_cnt_offset(env);
82
+}
83
+
84
static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
85
{
86
ARMGenericTimer *gt = &cpu->env.cp15.c14_timer[timeridx];
87
@@ -XXX,XX +XXX,XX @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
88
* reset timer to when ISTATUS next has to change
89
*/
90
uint64_t offset = timeridx == GTIMER_VIRT ?
91
- cpu->env.cp15.cntvoff_el2 : 0;
92
+ cpu->env.cp15.cntvoff_el2 : gt_phys_raw_cnt_offset(&cpu->env);
93
uint64_t count = gt_get_countervalue(&cpu->env);
94
/* Note that this must be unsigned 64 bit arithmetic: */
95
int istatus = count - offset >= gt->cval;
96
@@ -XXX,XX +XXX,XX @@ static void gt_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri,
97
98
static uint64_t gt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
99
{
100
- return gt_get_countervalue(env);
101
+ return gt_get_countervalue(env) - gt_phys_cnt_offset(env);
102
}
103
104
static uint64_t gt_virt_cnt_offset(CPUARMState *env)
105
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
106
case GTIMER_HYPVIRT:
107
offset = gt_virt_cnt_offset(env);
108
break;
109
+ case GTIMER_PHYS:
110
+ offset = gt_phys_cnt_offset(env);
111
+ break;
112
}
113
114
return (uint32_t)(env->cp15.c14_timer[timeridx].cval -
115
@@ -XXX,XX +XXX,XX @@ static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
116
case GTIMER_HYPVIRT:
117
offset = gt_virt_cnt_offset(env);
118
break;
119
+ case GTIMER_PHYS:
120
+ offset = gt_phys_cnt_offset(env);
121
+ break;
122
}
123
124
trace_arm_gt_tval_write(timeridx, value);
125
@@ -XXX,XX +XXX,XX @@ static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
126
R_CNTHCTL_EL1NVVCT_MASK |
127
R_CNTHCTL_EVNTIS_MASK;
128
}
129
+ if (cpu_isar_feature(aa64_ecv, cpu)) {
130
+ valid_mask |= R_CNTHCTL_ECV_MASK;
131
+ }
132
133
/* Clear RES0 bits */
134
value &= valid_mask;
135
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo gen_timer_ecv_cp_reginfo[] = {
136
},
137
};
138
139
+static CPAccessResult gt_cntpoff_access(CPUARMState *env,
140
+ const ARMCPRegInfo *ri,
141
+ bool isread)
142
+{
143
+ if (arm_current_el(env) == 2 && !(env->cp15.scr_el3 & SCR_ECVEN)) {
144
+ return CP_ACCESS_TRAP_EL3;
145
+ }
146
+ return CP_ACCESS_OK;
147
+}
148
+
149
+static void gt_cntpoff_write(CPUARMState *env, const ARMCPRegInfo *ri,
150
+ uint64_t value)
151
+{
152
+ ARMCPU *cpu = env_archcpu(env);
153
+
154
+ trace_arm_gt_cntpoff_write(value);
155
+ raw_write(env, ri, value);
156
+ gt_recalc_timer(cpu, GTIMER_PHYS);
157
+}
158
+
159
+static const ARMCPRegInfo gen_timer_cntpoff_reginfo = {
160
+ .name = "CNTPOFF_EL2", .state = ARM_CP_STATE_AA64,
161
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 0, .opc2 = 6,
162
+ .access = PL2_RW, .type = ARM_CP_IO, .resetvalue = 0,
163
+ .accessfn = gt_cntpoff_access, .writefn = gt_cntpoff_write,
164
+ .nv2_redirect_offset = 0x1a8,
165
+ .fieldoffset = offsetof(CPUARMState, cp15.cntpoff_el2),
166
+};
167
#else
168
169
/*
170
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
171
if (cpu_isar_feature(aa64_ecv_traps, cpu)) {
172
define_arm_cp_regs(cpu, gen_timer_ecv_cp_reginfo);
173
}
174
+#ifndef CONFIG_USER_ONLY
175
+ if (cpu_isar_feature(aa64_ecv, cpu)) {
176
+ define_one_arm_cp_reg(cpu, &gen_timer_cntpoff_reginfo);
177
+ }
178
+#endif
179
if (arm_feature(env, ARM_FEATURE_VAPA)) {
180
ARMCPRegInfo vapa_cp_reginfo[] = {
181
{ .name = "PAR", .cp = 15, .crn = 7, .crm = 4, .opc1 = 0, .opc2 = 0,
182
diff --git a/target/arm/trace-events b/target/arm/trace-events
183
index XXXXXXX..XXXXXXX 100644
184
--- a/target/arm/trace-events
185
+++ b/target/arm/trace-events
186
@@ -XXX,XX +XXX,XX @@ arm_gt_tval_write(int timer, uint64_t value) "gt_tval_write: timer %d value 0x%"
187
arm_gt_ctl_write(int timer, uint64_t value) "gt_ctl_write: timer %d value 0x%" PRIx64
188
arm_gt_imask_toggle(int timer) "gt_ctl_write: timer %d IMASK toggle"
189
arm_gt_cntvoff_write(uint64_t value) "gt_cntvoff_write: value 0x%" PRIx64
190
+arm_gt_cntpoff_write(uint64_t value) "gt_cntpoff_write: value 0x%" PRIx64
191
arm_gt_update_irq(int timer, int irqstate) "gt_update_irq: timer %d irqstate %d"
192
193
# kvm.c
194
--
195
2.34.1
diff view generated by jsdifflib
1
From: Julia Suvorova via Qemu-devel <qemu-devel@nongnu.org>
1
Enable all FEAT_ECV features on the 'max' CPU.
2
2
3
New mini-kernel test for nRF51 SoC UART.
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20240301183219.2424889-9-peter.maydell@linaro.org
7
---
8
docs/system/arm/emulation.rst | 1 +
9
target/arm/tcg/cpu64.c | 1 +
10
2 files changed, 2 insertions(+)
4
11
5
Signed-off-by: Julia Suvorova <jusual@mail.ru>
12
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
6
Acked-by: Thomas Huth <thuth@redhat.com>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
tests/boot-serial-test.c | 19 +++++++++++++++++++
11
1 file changed, 19 insertions(+)
12
13
diff --git a/tests/boot-serial-test.c b/tests/boot-serial-test.c
14
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
15
--- a/tests/boot-serial-test.c
14
--- a/docs/system/arm/emulation.rst
16
+++ b/tests/boot-serial-test.c
15
+++ b/docs/system/arm/emulation.rst
17
@@ -XXX,XX +XXX,XX @@ static const uint8_t kernel_aarch64[] = {
16
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
18
0xfd, 0xff, 0xff, 0x17, /* b -12 (loop) */
17
- FEAT_DotProd (Advanced SIMD dot product instructions)
19
};
18
- FEAT_DoubleFault (Double Fault Extension)
20
19
- FEAT_E0PD (Preventing EL0 access to halves of address maps)
21
+static const uint8_t kernel_nrf51[] = {
20
+- FEAT_ECV (Enhanced Counter Virtualization)
22
+ 0x00, 0x00, 0x00, 0x00, /* Stack top address */
21
- FEAT_EPAC (Enhanced pointer authentication)
23
+ 0x09, 0x00, 0x00, 0x00, /* Reset handler address */
22
- FEAT_ETS (Enhanced Translation Synchronization)
24
+ 0x04, 0x4a, /* ldr r2, [pc, #16] Get ENABLE */
23
- FEAT_EVT (Enhanced Virtualization Traps)
25
+ 0x04, 0x21, /* movs r1, #4 */
24
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
26
+ 0x11, 0x60, /* str r1, [r2] */
25
index XXXXXXX..XXXXXXX 100644
27
+ 0x04, 0x4a, /* ldr r2, [pc, #16] Get STARTTX */
26
--- a/target/arm/tcg/cpu64.c
28
+ 0x01, 0x21, /* movs r1, #1 */
27
+++ b/target/arm/tcg/cpu64.c
29
+ 0x11, 0x60, /* str r1, [r2] */
28
@@ -XXX,XX +XXX,XX @@ void aarch64_max_tcg_initfn(Object *obj)
30
+ 0x03, 0x4a, /* ldr r2, [pc, #12] Get TXD */
29
t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN64_2, 2); /* 64k stage2 supported */
31
+ 0x54, 0x21, /* movs r1, 'T' */
30
t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN4_2, 2); /* 4k stage2 supported */
32
+ 0x11, 0x60, /* str r1, [r2] */
31
t = FIELD_DP64(t, ID_AA64MMFR0, FGT, 1); /* FEAT_FGT */
33
+ 0xfe, 0xe7, /* b . */
32
+ t = FIELD_DP64(t, ID_AA64MMFR0, ECV, 2); /* FEAT_ECV */
34
+ 0x00, 0x25, 0x00, 0x40, /* 0x40002500 = UART ENABLE */
33
cpu->isar.id_aa64mmfr0 = t;
35
+ 0x08, 0x20, 0x00, 0x40, /* 0x40002008 = UART STARTTX */
34
36
+ 0x1c, 0x25, 0x00, 0x40 /* 0x4000251c = UART TXD */
35
t = cpu->isar.id_aa64mmfr1;
37
+};
38
+
39
typedef struct testdef {
40
const char *arch; /* Target architecture */
41
const char *machine; /* Name of the machine */
42
@@ -XXX,XX +XXX,XX @@ static testdef_t tests[] = {
43
{ "hppa", "hppa", "", "SeaBIOS wants SYSTEM HALT" },
44
{ "aarch64", "virt", "-cpu cortex-a57", "TT", sizeof(kernel_aarch64),
45
kernel_aarch64 },
46
+ { "arm", "microbit", "", "T", sizeof(kernel_nrf51), kernel_nrf51 },
47
48
{ NULL }
49
};
50
--
36
--
51
2.19.1
37
2.34.1
52
38
53
39
diff view generated by jsdifflib
1
From: Julia Suvorova via Qemu-devel <qemu-devel@nongnu.org>
1
From: Inès Varhol <ines.varhol@telecom-paris.fr>
2
2
3
Not implemented: CTS/NCTS, PSEL*.
3
Features supported :
4
- the 8 STM32L4x5 GPIOs are initialized with their reset values
5
(except IDR, see below)
6
- input mode : setting a pin in input mode "externally" (using input
7
irqs) results in an out irq (transmitted to SYSCFG)
8
- output mode : setting a bit in ODR sets the corresponding out irq
9
(if this line is configured in output mode)
10
- pull-up, pull-down
11
- push-pull, open-drain
4
12
5
Signed-off-by: Julia Suvorova <jusual@mail.ru>
13
Difference with the real GPIOs :
6
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
14
- Alternate Function and Analog mode aren't implemented :
15
pins in AF/Analog behave like pins in input mode
16
- floating pins stay at their last value
17
- register IDR reset values differ from the real one :
18
values are coherent with the other registers reset values
19
and the fact that AF/Analog modes aren't implemented
20
- setting I/O output speed isn't supported
21
- locking port bits isn't supported
22
- ADC function isn't supported
23
- GPIOH has 16 pins instead of 2 pins
24
- writing to registers LCKR, AFRL, AFRH and ASCR is ineffective
25
26
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
27
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
28
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
29
Acked-by: Alistair Francis <alistair.francis@wdc.com>
30
Message-id: 20240305210444.310665-2-ines.varhol@telecom-paris.fr
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
31
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
32
---
9
hw/char/Makefile.objs | 1 +
33
MAINTAINERS | 1 +
10
include/hw/char/nrf51_uart.h | 78 +++++++++
34
docs/system/arm/b-l475e-iot01a.rst | 2 +-
11
hw/char/nrf51_uart.c | 330 +++++++++++++++++++++++++++++++++++
35
include/hw/gpio/stm32l4x5_gpio.h | 70 +++++
12
hw/char/trace-events | 4 +
36
hw/gpio/stm32l4x5_gpio.c | 477 +++++++++++++++++++++++++++++
13
4 files changed, 413 insertions(+)
37
hw/gpio/Kconfig | 3 +
14
create mode 100644 include/hw/char/nrf51_uart.h
38
hw/gpio/meson.build | 1 +
15
create mode 100644 hw/char/nrf51_uart.c
39
hw/gpio/trace-events | 6 +
40
7 files changed, 559 insertions(+), 1 deletion(-)
41
create mode 100644 include/hw/gpio/stm32l4x5_gpio.h
42
create mode 100644 hw/gpio/stm32l4x5_gpio.c
16
43
17
diff --git a/hw/char/Makefile.objs b/hw/char/Makefile.objs
44
diff --git a/MAINTAINERS b/MAINTAINERS
18
index XXXXXXX..XXXXXXX 100644
45
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/char/Makefile.objs
46
--- a/MAINTAINERS
20
+++ b/hw/char/Makefile.objs
47
+++ b/MAINTAINERS
21
@@ -XXX,XX +XXX,XX @@
48
@@ -XXX,XX +XXX,XX @@ F: hw/arm/stm32l4x5_soc.c
22
common-obj-$(CONFIG_IPACK) += ipoctal232.o
49
F: hw/misc/stm32l4x5_exti.c
23
common-obj-$(CONFIG_ESCC) += escc.o
50
F: hw/misc/stm32l4x5_syscfg.c
24
+common-obj-$(CONFIG_NRF51_SOC) += nrf51_uart.o
51
F: hw/misc/stm32l4x5_rcc.c
25
common-obj-$(CONFIG_PARALLEL) += parallel.o
52
+F: hw/gpio/stm32l4x5_gpio.c
26
common-obj-$(CONFIG_PARALLEL) += parallel-isa.o
53
F: include/hw/*/stm32l4x5_*.h
27
common-obj-$(CONFIG_PL011) += pl011.o
54
28
diff --git a/include/hw/char/nrf51_uart.h b/include/hw/char/nrf51_uart.h
55
B-L475E-IOT01A IoT Node
56
diff --git a/docs/system/arm/b-l475e-iot01a.rst b/docs/system/arm/b-l475e-iot01a.rst
57
index XXXXXXX..XXXXXXX 100644
58
--- a/docs/system/arm/b-l475e-iot01a.rst
59
+++ b/docs/system/arm/b-l475e-iot01a.rst
60
@@ -XXX,XX +XXX,XX @@ Currently B-L475E-IOT01A machine's only supports the following devices:
61
- STM32L4x5 EXTI (Extended interrupts and events controller)
62
- STM32L4x5 SYSCFG (System configuration controller)
63
- STM32L4x5 RCC (Reset and clock control)
64
+- STM32L4x5 GPIOs (General-purpose I/Os)
65
66
Missing devices
67
"""""""""""""""
68
@@ -XXX,XX +XXX,XX @@ Missing devices
69
The B-L475E-IOT01A does *not* support the following devices:
70
71
- Serial ports (UART)
72
-- General-purpose I/Os (GPIO)
73
- Analog to Digital Converter (ADC)
74
- SPI controller
75
- Timer controller (TIMER)
76
diff --git a/include/hw/gpio/stm32l4x5_gpio.h b/include/hw/gpio/stm32l4x5_gpio.h
29
new file mode 100644
77
new file mode 100644
30
index XXXXXXX..XXXXXXX
78
index XXXXXXX..XXXXXXX
31
--- /dev/null
79
--- /dev/null
32
+++ b/include/hw/char/nrf51_uart.h
80
+++ b/include/hw/gpio/stm32l4x5_gpio.h
33
@@ -XXX,XX +XXX,XX @@
81
@@ -XXX,XX +XXX,XX @@
34
+/*
82
+/*
35
+ * nRF51 SoC UART emulation
83
+ * STM32L4x5 GPIO (General Purpose Input/Ouput)
36
+ *
84
+ *
37
+ * Copyright (c) 2018 Julia Suvorova <jusual@mail.ru>
85
+ * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
86
+ * Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
38
+ *
87
+ *
39
+ * This program is free software; you can redistribute it and/or modify
88
+ * SPDX-License-Identifier: GPL-2.0-or-later
40
+ * it under the terms of the GNU General Public License version 2 or
89
+ *
41
+ * (at your option) any later version.
90
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
91
+ * See the COPYING file in the top-level directory.
42
+ */
92
+ */
43
+
93
+
44
+#ifndef NRF51_UART_H
94
+/*
45
+#define NRF51_UART_H
95
+ * The reference used is the STMicroElectronics RM0351 Reference manual
96
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
97
+ * https://www.st.com/en/microcontrollers-microprocessors/stm32l4x5/documentation.html
98
+ */
99
+
100
+#ifndef HW_STM32L4X5_GPIO_H
101
+#define HW_STM32L4X5_GPIO_H
46
+
102
+
47
+#include "hw/sysbus.h"
103
+#include "hw/sysbus.h"
48
+#include "chardev/char-fe.h"
104
+#include "qom/object.h"
49
+#include "hw/registerfields.h"
105
+
50
+
106
+#define TYPE_STM32L4X5_GPIO "stm32l4x5-gpio"
51
+#define UART_FIFO_LENGTH 6
107
+OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5GpioState, STM32L4X5_GPIO)
52
+#define UART_BASE 0x40002000
108
+
53
+#define UART_SIZE 0x1000
109
+#define GPIO_NUM_PINS 16
54
+
110
+
55
+#define TYPE_NRF51_UART "nrf51_soc.uart"
111
+struct Stm32l4x5GpioState {
56
+#define NRF51_UART(obj) OBJECT_CHECK(NRF51UARTState, (obj), TYPE_NRF51_UART)
57
+
58
+REG32(UART_STARTRX, 0x000)
59
+REG32(UART_STOPRX, 0x004)
60
+REG32(UART_STARTTX, 0x008)
61
+REG32(UART_STOPTX, 0x00C)
62
+REG32(UART_SUSPEND, 0x01C)
63
+
64
+REG32(UART_CTS, 0x100)
65
+REG32(UART_NCTS, 0x104)
66
+REG32(UART_RXDRDY, 0x108)
67
+REG32(UART_TXDRDY, 0x11C)
68
+REG32(UART_ERROR, 0x124)
69
+REG32(UART_RXTO, 0x144)
70
+
71
+REG32(UART_INTEN, 0x300)
72
+ FIELD(UART_INTEN, CTS, 0, 1)
73
+ FIELD(UART_INTEN, NCTS, 1, 1)
74
+ FIELD(UART_INTEN, RXDRDY, 2, 1)
75
+ FIELD(UART_INTEN, TXDRDY, 7, 1)
76
+ FIELD(UART_INTEN, ERROR, 9, 1)
77
+ FIELD(UART_INTEN, RXTO, 17, 1)
78
+REG32(UART_INTENSET, 0x304)
79
+REG32(UART_INTENCLR, 0x308)
80
+REG32(UART_ERRORSRC, 0x480)
81
+REG32(UART_ENABLE, 0x500)
82
+REG32(UART_PSELRTS, 0x508)
83
+REG32(UART_PSELTXD, 0x50C)
84
+REG32(UART_PSELCTS, 0x510)
85
+REG32(UART_PSELRXD, 0x514)
86
+REG32(UART_RXD, 0x518)
87
+REG32(UART_TXD, 0x51C)
88
+REG32(UART_BAUDRATE, 0x524)
89
+REG32(UART_CONFIG, 0x56C)
90
+
91
+typedef struct NRF51UARTState {
92
+ SysBusDevice parent_obj;
112
+ SysBusDevice parent_obj;
93
+
113
+
94
+ MemoryRegion iomem;
114
+ MemoryRegion mmio;
95
+ CharBackend chr;
115
+
96
+ qemu_irq irq;
116
+ /* GPIO registers */
97
+ guint watch_tag;
117
+ uint32_t moder;
98
+
118
+ uint32_t otyper;
99
+ uint8_t rx_fifo[UART_FIFO_LENGTH];
119
+ uint32_t ospeedr;
100
+ unsigned int rx_fifo_pos;
120
+ uint32_t pupdr;
101
+ unsigned int rx_fifo_len;
121
+ uint32_t idr;
102
+
122
+ uint32_t odr;
103
+ uint32_t reg[0x56C];
123
+ uint32_t lckr;
104
+
124
+ uint32_t afrl;
105
+ bool rx_started;
125
+ uint32_t afrh;
106
+ bool tx_started;
126
+ uint32_t ascr;
107
+ bool pending_tx_byte;
127
+
108
+ bool enabled;
128
+ /* GPIO registers reset values */
109
+} NRF51UARTState;
129
+ uint32_t moder_reset;
130
+ uint32_t ospeedr_reset;
131
+ uint32_t pupdr_reset;
132
+
133
+ /*
134
+ * External driving of pins.
135
+ * The pins can be set externally through the device
136
+ * anonymous input GPIOs lines under certain conditions.
137
+ * The pin must not be in push-pull output mode,
138
+ * and can't be set high in open-drain mode.
139
+ * Pins driven externally and configured to
140
+ * output mode will in general be "disconnected"
141
+ * (see `get_gpio_pinmask_to_disconnect()`)
142
+ */
143
+ uint16_t disconnected_pins;
144
+ uint16_t pins_connected_high;
145
+
146
+ char *name;
147
+ Clock *clk;
148
+ qemu_irq pin[GPIO_NUM_PINS];
149
+};
110
+
150
+
111
+#endif
151
+#endif
112
diff --git a/hw/char/nrf51_uart.c b/hw/char/nrf51_uart.c
152
diff --git a/hw/gpio/stm32l4x5_gpio.c b/hw/gpio/stm32l4x5_gpio.c
113
new file mode 100644
153
new file mode 100644
114
index XXXXXXX..XXXXXXX
154
index XXXXXXX..XXXXXXX
115
--- /dev/null
155
--- /dev/null
116
+++ b/hw/char/nrf51_uart.c
156
+++ b/hw/gpio/stm32l4x5_gpio.c
117
@@ -XXX,XX +XXX,XX @@
157
@@ -XXX,XX +XXX,XX @@
118
+/*
158
+/*
119
+ * nRF51 SoC UART emulation
159
+ * STM32L4x5 GPIO (General Purpose Input/Ouput)
120
+ *
160
+ *
121
+ * See nRF51 Series Reference Manual, "29 Universal Asynchronous
161
+ * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
122
+ * Receiver/Transmitter" for hardware specifications:
162
+ * Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
123
+ * http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf
124
+ *
163
+ *
125
+ * Copyright (c) 2018 Julia Suvorova <jusual@mail.ru>
164
+ * SPDX-License-Identifier: GPL-2.0-or-later
126
+ *
165
+ *
127
+ * This program is free software; you can redistribute it and/or modify
166
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
128
+ * it under the terms of the GNU General Public License version 2 or
167
+ * See the COPYING file in the top-level directory.
129
+ * (at your option) any later version.
168
+ */
169
+
170
+/*
171
+ * The reference used is the STMicroElectronics RM0351 Reference manual
172
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
173
+ * https://www.st.com/en/microcontrollers-microprocessors/stm32l4x5/documentation.html
130
+ */
174
+ */
131
+
175
+
132
+#include "qemu/osdep.h"
176
+#include "qemu/osdep.h"
133
+#include "qemu/log.h"
177
+#include "qemu/log.h"
134
+#include "hw/char/nrf51_uart.h"
178
+#include "hw/gpio/stm32l4x5_gpio.h"
179
+#include "hw/irq.h"
180
+#include "hw/qdev-clock.h"
181
+#include "hw/qdev-properties.h"
182
+#include "qapi/visitor.h"
183
+#include "qapi/error.h"
184
+#include "migration/vmstate.h"
135
+#include "trace.h"
185
+#include "trace.h"
136
+
186
+
137
+static void nrf51_uart_update_irq(NRF51UARTState *s)
187
+#define GPIO_MODER 0x00
138
+{
188
+#define GPIO_OTYPER 0x04
139
+ bool irq = false;
189
+#define GPIO_OSPEEDR 0x08
140
+
190
+#define GPIO_PUPDR 0x0C
141
+ irq |= (s->reg[R_UART_RXDRDY] &&
191
+#define GPIO_IDR 0x10
142
+ (s->reg[R_UART_INTEN] & R_UART_INTEN_RXDRDY_MASK));
192
+#define GPIO_ODR 0x14
143
+ irq |= (s->reg[R_UART_TXDRDY] &&
193
+#define GPIO_BSRR 0x18
144
+ (s->reg[R_UART_INTEN] & R_UART_INTEN_TXDRDY_MASK));
194
+#define GPIO_LCKR 0x1C
145
+ irq |= (s->reg[R_UART_ERROR] &&
195
+#define GPIO_AFRL 0x20
146
+ (s->reg[R_UART_INTEN] & R_UART_INTEN_ERROR_MASK));
196
+#define GPIO_AFRH 0x24
147
+ irq |= (s->reg[R_UART_RXTO] &&
197
+#define GPIO_BRR 0x28
148
+ (s->reg[R_UART_INTEN] & R_UART_INTEN_RXTO_MASK));
198
+#define GPIO_ASCR 0x2C
149
+
199
+
150
+ qemu_set_irq(s->irq, irq);
200
+/* 0b11111111_11111111_00000000_00000000 */
151
+}
201
+#define RESERVED_BITS_MASK 0xFFFF0000
152
+
202
+
153
+static uint64_t uart_read(void *opaque, hwaddr addr, unsigned int size)
203
+static void update_gpio_idr(Stm32l4x5GpioState *s);
154
+{
204
+
155
+ NRF51UARTState *s = NRF51_UART(opaque);
205
+static bool is_pull_up(Stm32l4x5GpioState *s, unsigned pin)
156
+ uint64_t r;
206
+{
157
+
207
+ return extract32(s->pupdr, 2 * pin, 2) == 1;
158
+ if (!s->enabled) {
208
+}
209
+
210
+static bool is_pull_down(Stm32l4x5GpioState *s, unsigned pin)
211
+{
212
+ return extract32(s->pupdr, 2 * pin, 2) == 2;
213
+}
214
+
215
+static bool is_output(Stm32l4x5GpioState *s, unsigned pin)
216
+{
217
+ return extract32(s->moder, 2 * pin, 2) == 1;
218
+}
219
+
220
+static bool is_open_drain(Stm32l4x5GpioState *s, unsigned pin)
221
+{
222
+ return extract32(s->otyper, pin, 1) == 1;
223
+}
224
+
225
+static bool is_push_pull(Stm32l4x5GpioState *s, unsigned pin)
226
+{
227
+ return extract32(s->otyper, pin, 1) == 0;
228
+}
229
+
230
+static void stm32l4x5_gpio_reset_hold(Object *obj)
231
+{
232
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
233
+
234
+ s->moder = s->moder_reset;
235
+ s->otyper = 0x00000000;
236
+ s->ospeedr = s->ospeedr_reset;
237
+ s->pupdr = s->pupdr_reset;
238
+ s->idr = 0x00000000;
239
+ s->odr = 0x00000000;
240
+ s->lckr = 0x00000000;
241
+ s->afrl = 0x00000000;
242
+ s->afrh = 0x00000000;
243
+ s->ascr = 0x00000000;
244
+
245
+ s->disconnected_pins = 0xFFFF;
246
+ s->pins_connected_high = 0x0000;
247
+ update_gpio_idr(s);
248
+}
249
+
250
+static void stm32l4x5_gpio_set(void *opaque, int line, int level)
251
+{
252
+ Stm32l4x5GpioState *s = opaque;
253
+ /*
254
+ * The pin isn't set if line is configured in output mode
255
+ * except if level is 0 and the output is open-drain.
256
+ * This way there will be no short-circuit prone situations.
257
+ */
258
+ if (is_output(s, line) && !(is_open_drain(s, line) && (level == 0))) {
259
+ qemu_log_mask(LOG_GUEST_ERROR, "Line %d can't be driven externally\n",
260
+ line);
261
+ return;
262
+ }
263
+
264
+ s->disconnected_pins &= ~(1 << line);
265
+ if (level) {
266
+ s->pins_connected_high |= (1 << line);
267
+ } else {
268
+ s->pins_connected_high &= ~(1 << line);
269
+ }
270
+ trace_stm32l4x5_gpio_pins(s->name, s->disconnected_pins,
271
+ s->pins_connected_high);
272
+ update_gpio_idr(s);
273
+}
274
+
275
+
276
+static void update_gpio_idr(Stm32l4x5GpioState *s)
277
+{
278
+ uint32_t new_idr_mask = 0;
279
+ uint32_t new_idr = s->odr;
280
+ uint32_t old_idr = s->idr;
281
+ int new_pin_state, old_pin_state;
282
+
283
+ for (int i = 0; i < GPIO_NUM_PINS; i++) {
284
+ if (is_output(s, i)) {
285
+ if (is_push_pull(s, i)) {
286
+ new_idr_mask |= (1 << i);
287
+ } else if (!(s->odr & (1 << i))) {
288
+ /* open-drain ODR 0 */
289
+ new_idr_mask |= (1 << i);
290
+ /* open-drain ODR 1 */
291
+ } else if (!(s->disconnected_pins & (1 << i)) &&
292
+ !(s->pins_connected_high & (1 << i))) {
293
+ /* open-drain ODR 1 with pin connected low */
294
+ new_idr_mask |= (1 << i);
295
+ new_idr &= ~(1 << i);
296
+ /* open-drain ODR 1 with unactive pin */
297
+ } else if (is_pull_up(s, i)) {
298
+ new_idr_mask |= (1 << i);
299
+ } else if (is_pull_down(s, i)) {
300
+ new_idr_mask |= (1 << i);
301
+ new_idr &= ~(1 << i);
302
+ }
303
+ /*
304
+ * The only case left is for open-drain ODR 1
305
+ * with unactive pin without pull-up or pull-down :
306
+ * the value is floating.
307
+ */
308
+ /* input or analog mode with connected pin */
309
+ } else if (!(s->disconnected_pins & (1 << i))) {
310
+ if (s->pins_connected_high & (1 << i)) {
311
+ /* pin high */
312
+ new_idr_mask |= (1 << i);
313
+ new_idr |= (1 << i);
314
+ } else {
315
+ /* pin low */
316
+ new_idr_mask |= (1 << i);
317
+ new_idr &= ~(1 << i);
318
+ }
319
+ /* input or analog mode with disconnected pin */
320
+ } else {
321
+ if (is_pull_up(s, i)) {
322
+ /* pull-up */
323
+ new_idr_mask |= (1 << i);
324
+ new_idr |= (1 << i);
325
+ } else if (is_pull_down(s, i)) {
326
+ /* pull-down */
327
+ new_idr_mask |= (1 << i);
328
+ new_idr &= ~(1 << i);
329
+ }
330
+ /*
331
+ * The only case left is for a disconnected pin
332
+ * without pull-up or pull-down :
333
+ * the value is floating.
334
+ */
335
+ }
336
+ }
337
+
338
+ s->idr = (old_idr & ~new_idr_mask) | (new_idr & new_idr_mask);
339
+ trace_stm32l4x5_gpio_update_idr(s->name, old_idr, s->idr);
340
+
341
+ for (int i = 0; i < GPIO_NUM_PINS; i++) {
342
+ if (new_idr_mask & (1 << i)) {
343
+ new_pin_state = (new_idr & (1 << i)) > 0;
344
+ old_pin_state = (old_idr & (1 << i)) > 0;
345
+ if (new_pin_state > old_pin_state) {
346
+ qemu_irq_raise(s->pin[i]);
347
+ } else if (new_pin_state < old_pin_state) {
348
+ qemu_irq_lower(s->pin[i]);
349
+ }
350
+ }
351
+ }
352
+}
353
+
354
+/*
355
+ * Return mask of pins that are both configured in output
356
+ * mode and externally driven (except pins in open-drain
357
+ * mode externally set to 0).
358
+ */
359
+static uint32_t get_gpio_pinmask_to_disconnect(Stm32l4x5GpioState *s)
360
+{
361
+ uint32_t pins_to_disconnect = 0;
362
+ for (int i = 0; i < GPIO_NUM_PINS; i++) {
363
+ /* for each connected pin in output mode */
364
+ if (!(s->disconnected_pins & (1 << i)) && is_output(s, i)) {
365
+ /* if either push-pull or high level */
366
+ if (is_push_pull(s, i) || s->pins_connected_high & (1 << i)) {
367
+ pins_to_disconnect |= (1 << i);
368
+ qemu_log_mask(LOG_GUEST_ERROR,
369
+ "Line %d can't be driven externally\n",
370
+ i);
371
+ }
372
+ }
373
+ }
374
+ return pins_to_disconnect;
375
+}
376
+
377
+/*
378
+ * Set field `disconnected_pins` and call `update_gpio_idr()`
379
+ */
380
+static void disconnect_gpio_pins(Stm32l4x5GpioState *s, uint16_t lines)
381
+{
382
+ s->disconnected_pins |= lines;
383
+ trace_stm32l4x5_gpio_pins(s->name, s->disconnected_pins,
384
+ s->pins_connected_high);
385
+ update_gpio_idr(s);
386
+}
387
+
388
+static void disconnected_pins_set(Object *obj, Visitor *v,
389
+ const char *name, void *opaque, Error **errp)
390
+{
391
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
392
+ uint16_t value;
393
+ if (!visit_type_uint16(v, name, &value, errp)) {
394
+ return;
395
+ }
396
+ disconnect_gpio_pins(s, value);
397
+}
398
+
399
+static void disconnected_pins_get(Object *obj, Visitor *v,
400
+ const char *name, void *opaque, Error **errp)
401
+{
402
+ visit_type_uint16(v, name, (uint16_t *)opaque, errp);
403
+}
404
+
405
+static void clock_freq_get(Object *obj, Visitor *v,
406
+ const char *name, void *opaque, Error **errp)
407
+{
408
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
409
+ uint32_t clock_freq_hz = clock_get_hz(s->clk);
410
+ visit_type_uint32(v, name, &clock_freq_hz, errp);
411
+}
412
+
413
+static void stm32l4x5_gpio_write(void *opaque, hwaddr addr,
414
+ uint64_t val64, unsigned int size)
415
+{
416
+ Stm32l4x5GpioState *s = opaque;
417
+
418
+ uint32_t value = val64;
419
+ trace_stm32l4x5_gpio_write(s->name, addr, val64);
420
+
421
+ switch (addr) {
422
+ case GPIO_MODER:
423
+ s->moder = value;
424
+ disconnect_gpio_pins(s, get_gpio_pinmask_to_disconnect(s));
425
+ qemu_log_mask(LOG_UNIMP,
426
+ "%s: Analog and AF modes aren't supported\n\
427
+ Analog and AF mode behave like input mode\n",
428
+ __func__);
429
+ return;
430
+ case GPIO_OTYPER:
431
+ s->otyper = value & ~RESERVED_BITS_MASK;
432
+ disconnect_gpio_pins(s, get_gpio_pinmask_to_disconnect(s));
433
+ return;
434
+ case GPIO_OSPEEDR:
435
+ qemu_log_mask(LOG_UNIMP,
436
+ "%s: Changing I/O output speed isn't supported\n\
437
+ I/O speed is already maximal\n",
438
+ __func__);
439
+ s->ospeedr = value;
440
+ return;
441
+ case GPIO_PUPDR:
442
+ s->pupdr = value;
443
+ update_gpio_idr(s);
444
+ return;
445
+ case GPIO_IDR:
446
+ qemu_log_mask(LOG_UNIMP,
447
+ "%s: GPIO->IDR is read-only\n",
448
+ __func__);
449
+ return;
450
+ case GPIO_ODR:
451
+ s->odr = value & ~RESERVED_BITS_MASK;
452
+ update_gpio_idr(s);
453
+ return;
454
+ case GPIO_BSRR: {
455
+ uint32_t bits_to_reset = (value & RESERVED_BITS_MASK) >> GPIO_NUM_PINS;
456
+ uint32_t bits_to_set = value & ~RESERVED_BITS_MASK;
457
+ /* If both BSx and BRx are set, BSx has priority.*/
458
+ s->odr &= ~bits_to_reset;
459
+ s->odr |= bits_to_set;
460
+ update_gpio_idr(s);
461
+ return;
462
+ }
463
+ case GPIO_LCKR:
464
+ qemu_log_mask(LOG_UNIMP,
465
+ "%s: Locking port bits configuration isn't supported\n",
466
+ __func__);
467
+ s->lckr = value & ~RESERVED_BITS_MASK;
468
+ return;
469
+ case GPIO_AFRL:
470
+ qemu_log_mask(LOG_UNIMP,
471
+ "%s: Alternate functions aren't supported\n",
472
+ __func__);
473
+ s->afrl = value;
474
+ return;
475
+ case GPIO_AFRH:
476
+ qemu_log_mask(LOG_UNIMP,
477
+ "%s: Alternate functions aren't supported\n",
478
+ __func__);
479
+ s->afrh = value;
480
+ return;
481
+ case GPIO_BRR: {
482
+ uint32_t bits_to_reset = value & ~RESERVED_BITS_MASK;
483
+ s->odr &= ~bits_to_reset;
484
+ update_gpio_idr(s);
485
+ return;
486
+ }
487
+ case GPIO_ASCR:
488
+ qemu_log_mask(LOG_UNIMP,
489
+ "%s: ADC function isn't supported\n",
490
+ __func__);
491
+ s->ascr = value & ~RESERVED_BITS_MASK;
492
+ return;
493
+ default:
494
+ qemu_log_mask(LOG_GUEST_ERROR,
495
+ "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
496
+ }
497
+}
498
+
499
+static uint64_t stm32l4x5_gpio_read(void *opaque, hwaddr addr,
500
+ unsigned int size)
501
+{
502
+ Stm32l4x5GpioState *s = opaque;
503
+
504
+ trace_stm32l4x5_gpio_read(s->name, addr);
505
+
506
+ switch (addr) {
507
+ case GPIO_MODER:
508
+ return s->moder;
509
+ case GPIO_OTYPER:
510
+ return s->otyper;
511
+ case GPIO_OSPEEDR:
512
+ return s->ospeedr;
513
+ case GPIO_PUPDR:
514
+ return s->pupdr;
515
+ case GPIO_IDR:
516
+ return s->idr;
517
+ case GPIO_ODR:
518
+ return s->odr;
519
+ case GPIO_BSRR:
159
+ return 0;
520
+ return 0;
160
+ }
521
+ case GPIO_LCKR:
161
+
522
+ return s->lckr;
162
+ switch (addr) {
523
+ case GPIO_AFRL:
163
+ case A_UART_RXD:
524
+ return s->afrl;
164
+ r = s->rx_fifo[s->rx_fifo_pos];
525
+ case GPIO_AFRH:
165
+ if (s->rx_started && s->rx_fifo_len) {
526
+ return s->afrh;
166
+ s->rx_fifo_pos = (s->rx_fifo_pos + 1) % UART_FIFO_LENGTH;
527
+ case GPIO_BRR:
167
+ s->rx_fifo_len--;
528
+ return 0;
168
+ if (s->rx_fifo_len) {
529
+ case GPIO_ASCR:
169
+ s->reg[R_UART_RXDRDY] = 1;
530
+ return s->ascr;
170
+ nrf51_uart_update_irq(s);
171
+ }
172
+ qemu_chr_fe_accept_input(&s->chr);
173
+ }
174
+ break;
175
+ case A_UART_INTENSET:
176
+ case A_UART_INTENCLR:
177
+ case A_UART_INTEN:
178
+ r = s->reg[R_UART_INTEN];
179
+ break;
180
+ default:
531
+ default:
181
+ r = s->reg[addr / 4];
532
+ qemu_log_mask(LOG_GUEST_ERROR,
182
+ break;
533
+ "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
183
+ }
534
+ return 0;
184
+
535
+ }
185
+ trace_nrf51_uart_read(addr, r, size);
536
+}
186
+
537
+
187
+ return r;
538
+static const MemoryRegionOps stm32l4x5_gpio_ops = {
188
+}
539
+ .read = stm32l4x5_gpio_read,
189
+
540
+ .write = stm32l4x5_gpio_write,
190
+static gboolean uart_transmit(GIOChannel *chan, GIOCondition cond, void *opaque)
541
+ .endianness = DEVICE_NATIVE_ENDIAN,
191
+{
542
+ .impl = {
192
+ NRF51UARTState *s = NRF51_UART(opaque);
543
+ .min_access_size = 4,
193
+ int r;
544
+ .max_access_size = 4,
194
+ uint8_t c = s->reg[R_UART_TXD];
545
+ .unaligned = false,
195
+
546
+ },
196
+ s->watch_tag = 0;
547
+ .valid = {
197
+
548
+ .min_access_size = 4,
198
+ r = qemu_chr_fe_write(&s->chr, &c, 1);
549
+ .max_access_size = 4,
199
+ if (r <= 0) {
550
+ .unaligned = false,
200
+ s->watch_tag = qemu_chr_fe_add_watch(&s->chr, G_IO_OUT | G_IO_HUP,
551
+ },
201
+ uart_transmit, s);
202
+ if (!s->watch_tag) {
203
+ /* The hardware has no transmit error reporting,
204
+ * so silently drop the byte
205
+ */
206
+ goto buffer_drained;
207
+ }
208
+ return FALSE;
209
+ }
210
+
211
+buffer_drained:
212
+ s->reg[R_UART_TXDRDY] = 1;
213
+ s->pending_tx_byte = false;
214
+ return FALSE;
215
+}
216
+
217
+static void uart_cancel_transmit(NRF51UARTState *s)
218
+{
219
+ if (s->watch_tag) {
220
+ g_source_remove(s->watch_tag);
221
+ s->watch_tag = 0;
222
+ }
223
+}
224
+
225
+static void uart_write(void *opaque, hwaddr addr,
226
+ uint64_t value, unsigned int size)
227
+{
228
+ NRF51UARTState *s = NRF51_UART(opaque);
229
+
230
+ trace_nrf51_uart_write(addr, value, size);
231
+
232
+ if (!s->enabled && (addr != A_UART_ENABLE)) {
233
+ return;
234
+ }
235
+
236
+ switch (addr) {
237
+ case A_UART_TXD:
238
+ if (!s->pending_tx_byte && s->tx_started) {
239
+ s->reg[R_UART_TXD] = value;
240
+ s->pending_tx_byte = true;
241
+ uart_transmit(NULL, G_IO_OUT, s);
242
+ }
243
+ break;
244
+ case A_UART_INTEN:
245
+ s->reg[R_UART_INTEN] = value;
246
+ break;
247
+ case A_UART_INTENSET:
248
+ s->reg[R_UART_INTEN] |= value;
249
+ break;
250
+ case A_UART_INTENCLR:
251
+ s->reg[R_UART_INTEN] &= ~value;
252
+ break;
253
+ case A_UART_TXDRDY ... A_UART_RXTO:
254
+ s->reg[addr / 4] = value;
255
+ break;
256
+ case A_UART_ERRORSRC:
257
+ s->reg[addr / 4] &= ~value;
258
+ break;
259
+ case A_UART_RXD:
260
+ break;
261
+ case A_UART_RXDRDY:
262
+ if (value == 0) {
263
+ s->reg[R_UART_RXDRDY] = 0;
264
+ }
265
+ break;
266
+ case A_UART_STARTTX:
267
+ if (value == 1) {
268
+ s->tx_started = true;
269
+ }
270
+ break;
271
+ case A_UART_STARTRX:
272
+ if (value == 1) {
273
+ s->rx_started = true;
274
+ }
275
+ break;
276
+ case A_UART_ENABLE:
277
+ if (value) {
278
+ if (value == 4) {
279
+ s->enabled = true;
280
+ }
281
+ break;
282
+ }
283
+ s->enabled = false;
284
+ value = 1;
285
+ /* fall through */
286
+ case A_UART_SUSPEND:
287
+ case A_UART_STOPTX:
288
+ if (value == 1) {
289
+ s->tx_started = false;
290
+ }
291
+ /* fall through */
292
+ case A_UART_STOPRX:
293
+ if (addr != A_UART_STOPTX && value == 1) {
294
+ s->rx_started = false;
295
+ s->reg[R_UART_RXTO] = 1;
296
+ }
297
+ break;
298
+ default:
299
+ s->reg[addr / 4] = value;
300
+ break;
301
+ }
302
+ nrf51_uart_update_irq(s);
303
+}
304
+
305
+static const MemoryRegionOps uart_ops = {
306
+ .read = uart_read,
307
+ .write = uart_write,
308
+ .endianness = DEVICE_LITTLE_ENDIAN,
309
+};
552
+};
310
+
553
+
311
+static void nrf51_uart_reset(DeviceState *dev)
554
+static void stm32l4x5_gpio_init(Object *obj)
312
+{
555
+{
313
+ NRF51UARTState *s = NRF51_UART(dev);
556
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
314
+
557
+
315
+ s->pending_tx_byte = 0;
558
+ memory_region_init_io(&s->mmio, obj, &stm32l4x5_gpio_ops, s,
316
+
559
+ TYPE_STM32L4X5_GPIO, 0x400);
317
+ uart_cancel_transmit(s);
560
+
318
+
561
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
319
+ memset(s->reg, 0, sizeof(s->reg));
562
+
320
+
563
+ qdev_init_gpio_out(DEVICE(obj), s->pin, GPIO_NUM_PINS);
321
+ s->reg[R_UART_PSELRTS] = 0xFFFFFFFF;
564
+ qdev_init_gpio_in(DEVICE(obj), stm32l4x5_gpio_set, GPIO_NUM_PINS);
322
+ s->reg[R_UART_PSELTXD] = 0xFFFFFFFF;
565
+
323
+ s->reg[R_UART_PSELCTS] = 0xFFFFFFFF;
566
+ s->clk = qdev_init_clock_in(DEVICE(s), "clk", NULL, s, 0);
324
+ s->reg[R_UART_PSELRXD] = 0xFFFFFFFF;
567
+
325
+ s->reg[R_UART_BAUDRATE] = 0x4000000;
568
+ object_property_add(obj, "disconnected-pins", "uint16",
326
+
569
+ disconnected_pins_get, disconnected_pins_set,
327
+ s->rx_fifo_len = 0;
570
+ NULL, &s->disconnected_pins);
328
+ s->rx_fifo_pos = 0;
571
+ object_property_add(obj, "clock-freq-hz", "uint32",
329
+ s->rx_started = false;
572
+ clock_freq_get, NULL, NULL, NULL);
330
+ s->tx_started = false;
573
+}
331
+ s->enabled = false;
574
+
332
+}
575
+static void stm32l4x5_gpio_realize(DeviceState *dev, Error **errp)
333
+
576
+{
334
+static void uart_receive(void *opaque, const uint8_t *buf, int size)
577
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(dev);
335
+{
578
+ if (!clock_has_source(s->clk)) {
336
+
579
+ error_setg(errp, "GPIO: clk input must be connected");
337
+ NRF51UARTState *s = NRF51_UART(opaque);
580
+ return;
338
+ int i;
581
+ }
339
+
582
+}
340
+ if (size == 0 || s->rx_fifo_len >= UART_FIFO_LENGTH) {
583
+
341
+ return;
584
+static const VMStateDescription vmstate_stm32l4x5_gpio = {
342
+ }
585
+ .name = TYPE_STM32L4X5_GPIO,
343
+
586
+ .version_id = 1,
344
+ for (i = 0; i < size; i++) {
587
+ .minimum_version_id = 1,
345
+ uint32_t pos = (s->rx_fifo_pos + s->rx_fifo_len) % UART_FIFO_LENGTH;
588
+ .fields = (VMStateField[]){
346
+ s->rx_fifo[pos] = buf[i];
589
+ VMSTATE_UINT32(moder, Stm32l4x5GpioState),
347
+ s->rx_fifo_len++;
590
+ VMSTATE_UINT32(otyper, Stm32l4x5GpioState),
348
+ }
591
+ VMSTATE_UINT32(ospeedr, Stm32l4x5GpioState),
349
+
592
+ VMSTATE_UINT32(pupdr, Stm32l4x5GpioState),
350
+ s->reg[R_UART_RXDRDY] = 1;
593
+ VMSTATE_UINT32(idr, Stm32l4x5GpioState),
351
+ nrf51_uart_update_irq(s);
594
+ VMSTATE_UINT32(odr, Stm32l4x5GpioState),
352
+}
595
+ VMSTATE_UINT32(lckr, Stm32l4x5GpioState),
353
+
596
+ VMSTATE_UINT32(afrl, Stm32l4x5GpioState),
354
+static int uart_can_receive(void *opaque)
597
+ VMSTATE_UINT32(afrh, Stm32l4x5GpioState),
355
+{
598
+ VMSTATE_UINT32(ascr, Stm32l4x5GpioState),
356
+ NRF51UARTState *s = NRF51_UART(opaque);
599
+ VMSTATE_UINT16(disconnected_pins, Stm32l4x5GpioState),
357
+
600
+ VMSTATE_UINT16(pins_connected_high, Stm32l4x5GpioState),
358
+ return s->rx_started ? (UART_FIFO_LENGTH - s->rx_fifo_len) : 0;
359
+}
360
+
361
+static void uart_event(void *opaque, int event)
362
+{
363
+ NRF51UARTState *s = NRF51_UART(opaque);
364
+
365
+ if (event == CHR_EVENT_BREAK) {
366
+ s->reg[R_UART_ERRORSRC] |= 3;
367
+ s->reg[R_UART_ERROR] = 1;
368
+ nrf51_uart_update_irq(s);
369
+ }
370
+}
371
+
372
+static void nrf51_uart_realize(DeviceState *dev, Error **errp)
373
+{
374
+ NRF51UARTState *s = NRF51_UART(dev);
375
+
376
+ qemu_chr_fe_set_handlers(&s->chr, uart_can_receive, uart_receive,
377
+ uart_event, NULL, s, NULL, true);
378
+}
379
+
380
+static void nrf51_uart_init(Object *obj)
381
+{
382
+ NRF51UARTState *s = NRF51_UART(obj);
383
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
384
+
385
+ memory_region_init_io(&s->iomem, obj, &uart_ops, s,
386
+ "nrf51_soc.uart", UART_SIZE);
387
+ sysbus_init_mmio(sbd, &s->iomem);
388
+ sysbus_init_irq(sbd, &s->irq);
389
+}
390
+
391
+static int nrf51_uart_post_load(void *opaque, int version_id)
392
+{
393
+ NRF51UARTState *s = NRF51_UART(opaque);
394
+
395
+ if (s->pending_tx_byte) {
396
+ s->watch_tag = qemu_chr_fe_add_watch(&s->chr, G_IO_OUT | G_IO_HUP,
397
+ uart_transmit, s);
398
+ }
399
+
400
+ return 0;
401
+}
402
+
403
+static const VMStateDescription nrf51_uart_vmstate = {
404
+ .name = "nrf51_soc.uart",
405
+ .post_load = nrf51_uart_post_load,
406
+ .fields = (VMStateField[]) {
407
+ VMSTATE_UINT32_ARRAY(reg, NRF51UARTState, 0x56C),
408
+ VMSTATE_UINT8_ARRAY(rx_fifo, NRF51UARTState, UART_FIFO_LENGTH),
409
+ VMSTATE_UINT32(rx_fifo_pos, NRF51UARTState),
410
+ VMSTATE_UINT32(rx_fifo_len, NRF51UARTState),
411
+ VMSTATE_BOOL(rx_started, NRF51UARTState),
412
+ VMSTATE_BOOL(tx_started, NRF51UARTState),
413
+ VMSTATE_BOOL(pending_tx_byte, NRF51UARTState),
414
+ VMSTATE_BOOL(enabled, NRF51UARTState),
415
+ VMSTATE_END_OF_LIST()
601
+ VMSTATE_END_OF_LIST()
416
+ }
602
+ }
417
+};
603
+};
418
+
604
+
419
+static Property nrf51_uart_properties[] = {
605
+static Property stm32l4x5_gpio_properties[] = {
420
+ DEFINE_PROP_CHR("chardev", NRF51UARTState, chr),
606
+ DEFINE_PROP_STRING("name", Stm32l4x5GpioState, name),
607
+ DEFINE_PROP_UINT32("mode-reset", Stm32l4x5GpioState, moder_reset, 0),
608
+ DEFINE_PROP_UINT32("ospeed-reset", Stm32l4x5GpioState, ospeedr_reset, 0),
609
+ DEFINE_PROP_UINT32("pupd-reset", Stm32l4x5GpioState, pupdr_reset, 0),
421
+ DEFINE_PROP_END_OF_LIST(),
610
+ DEFINE_PROP_END_OF_LIST(),
422
+};
611
+};
423
+
612
+
424
+static void nrf51_uart_class_init(ObjectClass *klass, void *data)
613
+static void stm32l4x5_gpio_class_init(ObjectClass *klass, void *data)
425
+{
614
+{
426
+ DeviceClass *dc = DEVICE_CLASS(klass);
615
+ DeviceClass *dc = DEVICE_CLASS(klass);
427
+
616
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
428
+ dc->reset = nrf51_uart_reset;
617
+
429
+ dc->realize = nrf51_uart_realize;
618
+ device_class_set_props(dc, stm32l4x5_gpio_properties);
430
+ dc->props = nrf51_uart_properties;
619
+ dc->vmsd = &vmstate_stm32l4x5_gpio;
431
+ dc->vmsd = &nrf51_uart_vmstate;
620
+ dc->realize = stm32l4x5_gpio_realize;
432
+}
621
+ rc->phases.hold = stm32l4x5_gpio_reset_hold;
433
+
622
+}
434
+static const TypeInfo nrf51_uart_info = {
623
+
435
+ .name = TYPE_NRF51_UART,
624
+static const TypeInfo stm32l4x5_gpio_types[] = {
436
+ .parent = TYPE_SYS_BUS_DEVICE,
625
+ {
437
+ .instance_size = sizeof(NRF51UARTState),
626
+ .name = TYPE_STM32L4X5_GPIO,
438
+ .instance_init = nrf51_uart_init,
627
+ .parent = TYPE_SYS_BUS_DEVICE,
439
+ .class_init = nrf51_uart_class_init
628
+ .instance_size = sizeof(Stm32l4x5GpioState),
629
+ .instance_init = stm32l4x5_gpio_init,
630
+ .class_init = stm32l4x5_gpio_class_init,
631
+ },
440
+};
632
+};
441
+
633
+
442
+static void nrf51_uart_register_types(void)
634
+DEFINE_TYPES(stm32l4x5_gpio_types)
443
+{
635
diff --git a/hw/gpio/Kconfig b/hw/gpio/Kconfig
444
+ type_register_static(&nrf51_uart_info);
445
+}
446
+
447
+type_init(nrf51_uart_register_types)
448
diff --git a/hw/char/trace-events b/hw/char/trace-events
449
index XXXXXXX..XXXXXXX 100644
636
index XXXXXXX..XXXXXXX 100644
450
--- a/hw/char/trace-events
637
--- a/hw/gpio/Kconfig
451
+++ b/hw/char/trace-events
638
+++ b/hw/gpio/Kconfig
452
@@ -XXX,XX +XXX,XX @@ cmsdk_apb_uart_receive(uint8_t c) "CMSDK APB UART: got character 0x%x from backe
639
@@ -XXX,XX +XXX,XX @@ config GPIO_PWR
453
cmsdk_apb_uart_tx_pending(void) "CMSDK APB UART: character send to backend pending"
640
454
cmsdk_apb_uart_tx(uint8_t c) "CMSDK APB UART: character 0x%x sent to backend"
641
config SIFIVE_GPIO
455
cmsdk_apb_uart_set_params(int speed) "CMSDK APB UART: params set to %d 8N1"
642
bool
456
+
643
+
457
+# hw/char/nrf51_uart.c
644
+config STM32L4X5_GPIO
458
+nrf51_uart_read(uint64_t addr, uint64_t r, unsigned int size) "addr 0x%" PRIx64 " value 0x%" PRIx64 " size %u"
645
+ bool
459
+nrf51_uart_write(uint64_t addr, uint64_t value, unsigned int size) "addr 0x%" PRIx64 " value 0x%" PRIx64 " size %u"
646
diff --git a/hw/gpio/meson.build b/hw/gpio/meson.build
647
index XXXXXXX..XXXXXXX 100644
648
--- a/hw/gpio/meson.build
649
+++ b/hw/gpio/meson.build
650
@@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_RASPI', if_true: files(
651
'bcm2835_gpio.c',
652
'bcm2838_gpio.c'
653
))
654
+system_ss.add(when: 'CONFIG_STM32L4X5_SOC', if_true: files('stm32l4x5_gpio.c'))
655
system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_gpio.c'))
656
system_ss.add(when: 'CONFIG_SIFIVE_GPIO', if_true: files('sifive_gpio.c'))
657
diff --git a/hw/gpio/trace-events b/hw/gpio/trace-events
658
index XXXXXXX..XXXXXXX 100644
659
--- a/hw/gpio/trace-events
660
+++ b/hw/gpio/trace-events
661
@@ -XXX,XX +XXX,XX @@ sifive_gpio_update_output_irq(int64_t line, int64_t value) "line %" PRIi64 " val
662
# aspeed_gpio.c
663
aspeed_gpio_read(uint64_t offset, uint64_t value) "offset: 0x%" PRIx64 " value 0x%" PRIx64
664
aspeed_gpio_write(uint64_t offset, uint64_t value) "offset: 0x%" PRIx64 " value 0x%" PRIx64
665
+
666
+# stm32l4x5_gpio.c
667
+stm32l4x5_gpio_read(char *gpio, uint64_t addr) "GPIO%s addr: 0x%" PRIx64 " "
668
+stm32l4x5_gpio_write(char *gpio, uint64_t addr, uint64_t data) "GPIO%s addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
669
+stm32l4x5_gpio_update_idr(char *gpio, uint32_t old_idr, uint32_t new_idr) "GPIO%s from: 0x%x to: 0x%x"
670
+stm32l4x5_gpio_pins(char *gpio, uint16_t disconnected, uint16_t high) "GPIO%s disconnected pins: 0x%x levels: 0x%x"
460
--
671
--
461
2.19.1
672
2.34.1
462
673
463
674
diff view generated by jsdifflib
1
From: Julia Suvorova via Qemu-devel <qemu-devel@nongnu.org>
1
From: Inès Varhol <ines.varhol@telecom-paris.fr>
2
2
3
Wire up nRF51 UART in the corresponding SoC.
3
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
4
4
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
5
Signed-off-by: Julia Suvorova <jusual@mail.ru>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
Acked-by: Alistair Francis <alistair.francis@wdc.com>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
7
Message-id: 20240305210444.310665-3-ines.varhol@telecom-paris.fr
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
9
---
11
include/hw/arm/nrf51_soc.h | 3 +++
10
include/hw/arm/stm32l4x5_soc.h | 2 +
12
hw/arm/microbit.c | 2 ++
11
include/hw/gpio/stm32l4x5_gpio.h | 1 +
13
hw/arm/nrf51_soc.c | 20 ++++++++++++++++++++
12
include/hw/misc/stm32l4x5_syscfg.h | 3 +-
14
3 files changed, 25 insertions(+)
13
hw/arm/stm32l4x5_soc.c | 71 +++++++++++++++++++++++-------
15
14
hw/misc/stm32l4x5_syscfg.c | 1 +
16
diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h
15
hw/arm/Kconfig | 3 +-
17
index XXXXXXX..XXXXXXX 100644
16
6 files changed, 63 insertions(+), 18 deletions(-)
18
--- a/include/hw/arm/nrf51_soc.h
17
19
+++ b/include/hw/arm/nrf51_soc.h
18
diff --git a/include/hw/arm/stm32l4x5_soc.h b/include/hw/arm/stm32l4x5_soc.h
20
@@ -XXX,XX +XXX,XX @@
19
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/arm/stm32l4x5_soc.h
21
+++ b/include/hw/arm/stm32l4x5_soc.h
22
@@ -XXX,XX +XXX,XX @@
23
#include "hw/misc/stm32l4x5_syscfg.h"
24
#include "hw/misc/stm32l4x5_exti.h"
25
#include "hw/misc/stm32l4x5_rcc.h"
26
+#include "hw/gpio/stm32l4x5_gpio.h"
27
#include "qom/object.h"
28
29
#define TYPE_STM32L4X5_SOC "stm32l4x5-soc"
30
@@ -XXX,XX +XXX,XX @@ struct Stm32l4x5SocState {
31
OrIRQState exti_or_gates[NUM_EXTI_OR_GATES];
32
Stm32l4x5SyscfgState syscfg;
33
Stm32l4x5RccState rcc;
34
+ Stm32l4x5GpioState gpio[NUM_GPIOS];
35
36
MemoryRegion sram1;
37
MemoryRegion sram2;
38
diff --git a/include/hw/gpio/stm32l4x5_gpio.h b/include/hw/gpio/stm32l4x5_gpio.h
39
index XXXXXXX..XXXXXXX 100644
40
--- a/include/hw/gpio/stm32l4x5_gpio.h
41
+++ b/include/hw/gpio/stm32l4x5_gpio.h
42
@@ -XXX,XX +XXX,XX @@
43
#define TYPE_STM32L4X5_GPIO "stm32l4x5-gpio"
44
OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5GpioState, STM32L4X5_GPIO)
45
46
+#define NUM_GPIOS 8
47
#define GPIO_NUM_PINS 16
48
49
struct Stm32l4x5GpioState {
50
diff --git a/include/hw/misc/stm32l4x5_syscfg.h b/include/hw/misc/stm32l4x5_syscfg.h
51
index XXXXXXX..XXXXXXX 100644
52
--- a/include/hw/misc/stm32l4x5_syscfg.h
53
+++ b/include/hw/misc/stm32l4x5_syscfg.h
54
@@ -XXX,XX +XXX,XX @@
21
55
22
#include "hw/sysbus.h"
56
#include "hw/sysbus.h"
23
#include "hw/arm/armv7m.h"
57
#include "qom/object.h"
24
+#include "hw/char/nrf51_uart.h"
58
+#include "hw/gpio/stm32l4x5_gpio.h"
25
59
26
#define TYPE_NRF51_SOC "nrf51-soc"
60
#define TYPE_STM32L4X5_SYSCFG "stm32l4x5-syscfg"
27
#define NRF51_SOC(obj) \
61
OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5SyscfgState, STM32L4X5_SYSCFG)
28
@@ -XXX,XX +XXX,XX @@ typedef struct NRF51State {
62
29
/*< public >*/
63
-#define NUM_GPIOS 8
30
ARMv7MState cpu;
64
-#define GPIO_NUM_PINS 16
31
65
#define SYSCFG_NUM_EXTICR 4
32
+ NRF51UARTState uart;
66
33
+
67
struct Stm32l4x5SyscfgState {
34
MemoryRegion iomem;
68
diff --git a/hw/arm/stm32l4x5_soc.c b/hw/arm/stm32l4x5_soc.c
35
MemoryRegion sram;
69
index XXXXXXX..XXXXXXX 100644
36
MemoryRegion flash;
70
--- a/hw/arm/stm32l4x5_soc.c
37
diff --git a/hw/arm/microbit.c b/hw/arm/microbit.c
71
+++ b/hw/arm/stm32l4x5_soc.c
38
index XXXXXXX..XXXXXXX 100644
72
@@ -XXX,XX +XXX,XX @@
39
--- a/hw/arm/microbit.c
73
#include "sysemu/sysemu.h"
40
+++ b/hw/arm/microbit.c
74
#include "hw/or-irq.h"
41
@@ -XXX,XX +XXX,XX @@
75
#include "hw/arm/stm32l4x5_soc.h"
42
#include "qapi/error.h"
76
+#include "hw/gpio/stm32l4x5_gpio.h"
43
#include "hw/boards.h"
77
#include "hw/qdev-clock.h"
44
#include "hw/arm/arm.h"
78
#include "hw/misc/unimp.h"
45
+#include "sysemu/sysemu.h"
79
46
#include "exec/address-spaces.h"
80
@@ -XXX,XX +XXX,XX @@ static const int exti_or_gate1_lines_in[EXTI_OR_GATE1_NUM_LINES_IN] = {
47
81
16, 35, 36, 37, 38,
48
#include "hw/arm/nrf51_soc.h"
82
};
49
@@ -XXX,XX +XXX,XX @@ static void microbit_init(MachineState *machine)
83
50
84
+static const struct {
51
sysbus_init_child_obj(OBJECT(machine), "nrf51", soc, sizeof(s->nrf51),
85
+ uint32_t addr;
52
TYPE_NRF51_SOC);
86
+ uint32_t moder_reset;
53
+ qdev_prop_set_chr(DEVICE(&s->nrf51), "serial0", serial_hd(0));
87
+ uint32_t ospeedr_reset;
54
object_property_set_link(soc, OBJECT(system_memory), "memory",
88
+ uint32_t pupdr_reset;
55
&error_fatal);
89
+} stm32l4x5_gpio_cfg[NUM_GPIOS] = {
56
object_property_set_bool(soc, true, "realized", &error_fatal);
90
+ { 0x48000000, 0xABFFFFFF, 0x0C000000, 0x64000000 },
57
diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c
91
+ { 0x48000400, 0xFFFFFEBF, 0x00000000, 0x00000100 },
58
index XXXXXXX..XXXXXXX 100644
92
+ { 0x48000800, 0xFFFFFFFF, 0x00000000, 0x00000000 },
59
--- a/hw/arm/nrf51_soc.c
93
+ { 0x48000C00, 0xFFFFFFFF, 0x00000000, 0x00000000 },
60
+++ b/hw/arm/nrf51_soc.c
94
+ { 0x48001000, 0xFFFFFFFF, 0x00000000, 0x00000000 },
61
@@ -XXX,XX +XXX,XX @@
95
+ { 0x48001400, 0xFFFFFFFF, 0x00000000, 0x00000000 },
62
#define NRF51822_FLASH_SIZE (256 * 1024)
96
+ { 0x48001800, 0xFFFFFFFF, 0x00000000, 0x00000000 },
63
#define NRF51822_SRAM_SIZE (16 * 1024)
97
+ { 0x48001C00, 0x0000000F, 0x00000000, 0x00000000 },
64
98
+};
65
+#define BASE_TO_IRQ(base) ((base >> 12) & 0x1F)
99
+
66
+
100
static void stm32l4x5_soc_initfn(Object *obj)
67
static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
68
{
101
{
69
NRF51State *s = NRF51_SOC(dev_soc);
102
Stm32l4x5SocState *s = STM32L4X5_SOC(obj);
70
+ MemoryRegion *mr;
103
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_initfn(Object *obj)
71
Error *err = NULL;
104
}
72
105
object_initialize_child(obj, "syscfg", &s->syscfg, TYPE_STM32L4X5_SYSCFG);
73
if (!s->board_memory) {
106
object_initialize_child(obj, "rcc", &s->rcc, TYPE_STM32L4X5_RCC);
74
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
107
+
75
}
108
+ for (unsigned i = 0; i < NUM_GPIOS; i++) {
76
memory_region_add_subregion(&s->container, SRAM_BASE, &s->sram);
109
+ g_autofree char *name = g_strdup_printf("gpio%c", 'a' + i);
77
110
+ object_initialize_child(obj, name, &s->gpio[i], TYPE_STM32L4X5_GPIO);
78
+ /* UART */
79
+ object_property_set_bool(OBJECT(&s->uart), true, "realized", &err);
80
+ if (err) {
81
+ error_propagate(errp, err);
82
+ return;
83
+ }
111
+ }
84
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->uart), 0);
85
+ memory_region_add_subregion_overlap(&s->container, UART_BASE, mr, 0);
86
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart), 0,
87
+ qdev_get_gpio_in(DEVICE(&s->cpu),
88
+ BASE_TO_IRQ(UART_BASE)));
89
+
90
create_unimplemented_device("nrf51_soc.io", IOMEM_BASE, IOMEM_SIZE);
91
create_unimplemented_device("nrf51_soc.ficr", FICR_BASE, FICR_SIZE);
92
create_unimplemented_device("nrf51_soc.private",
93
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_init(Object *obj)
94
qdev_prop_set_string(DEVICE(&s->cpu), "cpu-type",
95
ARM_CPU_TYPE_NAME("cortex-m0"));
96
qdev_prop_set_uint32(DEVICE(&s->cpu), "num-irq", 32);
97
+
98
+ sysbus_init_child_obj(obj, "uart", &s->uart, sizeof(s->uart),
99
+ TYPE_NRF51_UART);
100
+ object_property_add_alias(obj, "serial0", OBJECT(&s->uart), "chardev",
101
+ &error_abort);
102
}
112
}
103
113
104
static Property nrf51_soc_properties[] = {
114
static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
115
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
116
Stm32l4x5SocState *s = STM32L4X5_SOC(dev_soc);
117
const Stm32l4x5SocClass *sc = STM32L4X5_SOC_GET_CLASS(dev_soc);
118
MemoryRegion *system_memory = get_system_memory();
119
- DeviceState *armv7m;
120
+ DeviceState *armv7m, *dev;
121
SysBusDevice *busdev;
122
+ uint32_t pin_index;
123
124
if (!memory_region_init_rom(&s->flash, OBJECT(dev_soc), "flash",
125
sc->flash_size, errp)) {
126
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
127
return;
128
}
129
130
+ /* GPIOs */
131
+ for (unsigned i = 0; i < NUM_GPIOS; i++) {
132
+ g_autofree char *name = g_strdup_printf("%c", 'A' + i);
133
+ dev = DEVICE(&s->gpio[i]);
134
+ qdev_prop_set_string(dev, "name", name);
135
+ qdev_prop_set_uint32(dev, "mode-reset",
136
+ stm32l4x5_gpio_cfg[i].moder_reset);
137
+ qdev_prop_set_uint32(dev, "ospeed-reset",
138
+ stm32l4x5_gpio_cfg[i].ospeedr_reset);
139
+ qdev_prop_set_uint32(dev, "pupd-reset",
140
+ stm32l4x5_gpio_cfg[i].pupdr_reset);
141
+ busdev = SYS_BUS_DEVICE(&s->gpio[i]);
142
+ g_free(name);
143
+ name = g_strdup_printf("gpio%c-out", 'a' + i);
144
+ qdev_connect_clock_in(DEVICE(&s->gpio[i]), "clk",
145
+ qdev_get_clock_out(DEVICE(&(s->rcc)), name));
146
+ if (!sysbus_realize(busdev, errp)) {
147
+ return;
148
+ }
149
+ sysbus_mmio_map(busdev, 0, stm32l4x5_gpio_cfg[i].addr);
150
+ }
151
+
152
/* System configuration controller */
153
busdev = SYS_BUS_DEVICE(&s->syscfg);
154
if (!sysbus_realize(busdev, errp)) {
155
return;
156
}
157
sysbus_mmio_map(busdev, 0, SYSCFG_ADDR);
158
- /*
159
- * TODO: when the GPIO device is implemented, connect it
160
- * to SYCFG using `qdev_connect_gpio_out`, NUM_GPIOS and
161
- * GPIO_NUM_PINS.
162
- */
163
+
164
+ for (unsigned i = 0; i < NUM_GPIOS; i++) {
165
+ for (unsigned j = 0; j < GPIO_NUM_PINS; j++) {
166
+ pin_index = GPIO_NUM_PINS * i + j;
167
+ qdev_connect_gpio_out(DEVICE(&s->gpio[i]), j,
168
+ qdev_get_gpio_in(DEVICE(&s->syscfg),
169
+ pin_index));
170
+ }
171
+ }
172
173
/* EXTI device */
174
busdev = SYS_BUS_DEVICE(&s->exti);
175
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
176
}
177
}
178
179
- for (unsigned i = 0; i < 16; i++) {
180
+ for (unsigned i = 0; i < GPIO_NUM_PINS; i++) {
181
qdev_connect_gpio_out(DEVICE(&s->syscfg), i,
182
qdev_get_gpio_in(DEVICE(&s->exti), i));
183
}
184
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
185
/* RESERVED: 0x40024400, 0x7FDBC00 */
186
187
/* AHB2 BUS */
188
- create_unimplemented_device("GPIOA", 0x48000000, 0x400);
189
- create_unimplemented_device("GPIOB", 0x48000400, 0x400);
190
- create_unimplemented_device("GPIOC", 0x48000800, 0x400);
191
- create_unimplemented_device("GPIOD", 0x48000C00, 0x400);
192
- create_unimplemented_device("GPIOE", 0x48001000, 0x400);
193
- create_unimplemented_device("GPIOF", 0x48001400, 0x400);
194
- create_unimplemented_device("GPIOG", 0x48001800, 0x400);
195
- create_unimplemented_device("GPIOH", 0x48001C00, 0x400);
196
/* RESERVED: 0x48002000, 0x7FDBC00 */
197
create_unimplemented_device("OTG_FS", 0x50000000, 0x40000);
198
create_unimplemented_device("ADC", 0x50040000, 0x400);
199
diff --git a/hw/misc/stm32l4x5_syscfg.c b/hw/misc/stm32l4x5_syscfg.c
200
index XXXXXXX..XXXXXXX 100644
201
--- a/hw/misc/stm32l4x5_syscfg.c
202
+++ b/hw/misc/stm32l4x5_syscfg.c
203
@@ -XXX,XX +XXX,XX @@
204
#include "hw/irq.h"
205
#include "migration/vmstate.h"
206
#include "hw/misc/stm32l4x5_syscfg.h"
207
+#include "hw/gpio/stm32l4x5_gpio.h"
208
209
#define SYSCFG_MEMRMP 0x00
210
#define SYSCFG_CFGR1 0x04
211
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
212
index XXXXXXX..XXXXXXX 100644
213
--- a/hw/arm/Kconfig
214
+++ b/hw/arm/Kconfig
215
@@ -XXX,XX +XXX,XX @@ config STM32L4X5_SOC
216
bool
217
select ARM_V7M
218
select OR_IRQ
219
- select STM32L4X5_SYSCFG
220
select STM32L4X5_EXTI
221
+ select STM32L4X5_SYSCFG
222
select STM32L4X5_RCC
223
+ select STM32L4X5_GPIO
224
225
config XLNX_ZYNQMP_ARM
226
bool
105
--
227
--
106
2.19.1
228
2.34.1
107
229
108
230
diff view generated by jsdifflib
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
1
From: Inès Varhol <ines.varhol@telecom-paris.fr>
2
2
3
Add a model of Xilinx Versal SoC.
3
The testcase contains :
4
- `test_idr_reset_value()` :
5
Checks the reset values of MODER, OTYPER, PUPDR, ODR and IDR.
6
- `test_gpio_output_mode()` :
7
Checks that writing a bit in register ODR results in the corresponding
8
pin rising or lowering, if this pin is configured in output mode.
9
- `test_gpio_input_mode()` :
10
Checks that a input pin set high or low externally results
11
in the pin rising and lowering.
12
- `test_pull_up_pull_down()` :
13
Checks that a floating pin in pull-up/down mode is actually high/down.
14
- `test_push_pull()` :
15
Checks that a pin set externally is disconnected when configured in
16
push-pull output mode, and can't be set externally while in this mode.
17
- `test_open_drain()` :
18
Checks that a pin set externally high is disconnected when configured
19
in open-drain output mode, and can't be set high while in this mode.
20
- `test_bsrr_brr()` :
21
Checks that writing to BSRR and BRR has the desired result in ODR.
22
- `test_clock_enable()` :
23
Checks that GPIO clock is at the right frequency after enabling it.
4
24
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
25
Acked-by: Thomas Huth <thuth@redhat.com>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
26
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
27
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
28
Message-id: 20240305210444.310665-4-ines.varhol@telecom-paris.fr
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
29
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
30
---
9
hw/arm/Makefile.objs | 1 +
31
tests/qtest/stm32l4x5_gpio-test.c | 551 ++++++++++++++++++++++++++++++
10
include/hw/arm/xlnx-versal.h | 122 +++++++++++
32
tests/qtest/meson.build | 3 +-
11
hw/arm/xlnx-versal.c | 323 ++++++++++++++++++++++++++++
33
2 files changed, 553 insertions(+), 1 deletion(-)
12
default-configs/aarch64-softmmu.mak | 1 +
34
create mode 100644 tests/qtest/stm32l4x5_gpio-test.c
13
4 files changed, 447 insertions(+)
14
create mode 100644 include/hw/arm/xlnx-versal.h
15
create mode 100644 hw/arm/xlnx-versal.c
16
35
17
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
36
diff --git a/tests/qtest/stm32l4x5_gpio-test.c b/tests/qtest/stm32l4x5_gpio-test.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/Makefile.objs
20
+++ b/hw/arm/Makefile.objs
21
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
22
obj-$(CONFIG_RASPI) += bcm2835_peripherals.o bcm2836.o raspi.o
23
obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
24
obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx-zynqmp.o xlnx-zcu102.o
25
+obj-$(CONFIG_XLNX_VERSAL) += xlnx-versal.o
26
obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
27
obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o
28
obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
29
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
30
new file mode 100644
37
new file mode 100644
31
index XXXXXXX..XXXXXXX
38
index XXXXXXX..XXXXXXX
32
--- /dev/null
39
--- /dev/null
33
+++ b/include/hw/arm/xlnx-versal.h
40
+++ b/tests/qtest/stm32l4x5_gpio-test.c
34
@@ -XXX,XX +XXX,XX @@
41
@@ -XXX,XX +XXX,XX @@
35
+/*
42
+/*
36
+ * Model of the Xilinx Versal
43
+ * QTest testcase for STM32L4x5_GPIO
37
+ *
44
+ *
38
+ * Copyright (c) 2018 Xilinx Inc.
45
+ * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
39
+ * Written by Edgar E. Iglesias
46
+ * Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
40
+ *
47
+ *
41
+ * This program is free software; you can redistribute it and/or modify
48
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
42
+ * it under the terms of the GNU General Public License version 2 or
49
+ * See the COPYING file in the top-level directory.
43
+ * (at your option) any later version.
44
+ */
50
+ */
45
+
51
+
46
+#ifndef XLNX_VERSAL_H
47
+#define XLNX_VERSAL_H
48
+
49
+#include "hw/sysbus.h"
50
+#include "hw/arm/arm.h"
51
+#include "hw/intc/arm_gicv3.h"
52
+
53
+#define TYPE_XLNX_VERSAL "xlnx-versal"
54
+#define XLNX_VERSAL(obj) OBJECT_CHECK(Versal, (obj), TYPE_XLNX_VERSAL)
55
+
56
+#define XLNX_VERSAL_NR_ACPUS 2
57
+#define XLNX_VERSAL_NR_UARTS 2
58
+#define XLNX_VERSAL_NR_GEMS 2
59
+#define XLNX_VERSAL_NR_IRQS 256
60
+
61
+typedef struct Versal {
62
+ /*< private >*/
63
+ SysBusDevice parent_obj;
64
+
65
+ /*< public >*/
66
+ struct {
67
+ struct {
68
+ MemoryRegion mr;
69
+ ARMCPU *cpu[XLNX_VERSAL_NR_ACPUS];
70
+ GICv3State gic;
71
+ } apu;
72
+ } fpd;
73
+
74
+ MemoryRegion mr_ps;
75
+
76
+ struct {
77
+ /* 4 ranges to access DDR. */
78
+ MemoryRegion mr_ddr_ranges[4];
79
+ } noc;
80
+
81
+ struct {
82
+ MemoryRegion mr_ocm;
83
+
84
+ struct {
85
+ SysBusDevice *uart[XLNX_VERSAL_NR_UARTS];
86
+ SysBusDevice *gem[XLNX_VERSAL_NR_GEMS];
87
+ } iou;
88
+ } lpd;
89
+
90
+ struct {
91
+ MemoryRegion *mr_ddr;
92
+ uint32_t psci_conduit;
93
+ } cfg;
94
+} Versal;
95
+
96
+/* Memory-map and IRQ definitions. Copied a subset from
97
+ * auto-generated files. */
98
+
99
+#define VERSAL_GIC_MAINT_IRQ 9
100
+#define VERSAL_TIMER_VIRT_IRQ 11
101
+#define VERSAL_TIMER_S_EL1_IRQ 13
102
+#define VERSAL_TIMER_NS_EL1_IRQ 14
103
+#define VERSAL_TIMER_NS_EL2_IRQ 10
104
+
105
+#define VERSAL_UART0_IRQ_0 18
106
+#define VERSAL_UART1_IRQ_0 19
107
+#define VERSAL_GEM0_IRQ_0 56
108
+#define VERSAL_GEM0_WAKE_IRQ_0 57
109
+#define VERSAL_GEM1_IRQ_0 58
110
+#define VERSAL_GEM1_WAKE_IRQ_0 59
111
+
112
+/* Architecturally eserved IRQs suitable for virtualization. */
113
+#define VERSAL_RSVD_HIGH_IRQ_FIRST 160
114
+#define VERSAL_RSVD_HIGH_IRQ_LAST 255
115
+
116
+#define MM_TOP_RSVD 0xa0000000U
117
+#define MM_TOP_RSVD_SIZE 0x4000000
118
+#define MM_GIC_APU_DIST_MAIN 0xf9000000U
119
+#define MM_GIC_APU_DIST_MAIN_SIZE 0x10000
120
+#define MM_GIC_APU_REDIST_0 0xf9080000U
121
+#define MM_GIC_APU_REDIST_0_SIZE 0x80000
122
+
123
+#define MM_UART0 0xff000000U
124
+#define MM_UART0_SIZE 0x10000
125
+#define MM_UART1 0xff010000U
126
+#define MM_UART1_SIZE 0x10000
127
+
128
+#define MM_GEM0 0xff0c0000U
129
+#define MM_GEM0_SIZE 0x10000
130
+#define MM_GEM1 0xff0d0000U
131
+#define MM_GEM1_SIZE 0x10000
132
+
133
+#define MM_OCM 0xfffc0000U
134
+#define MM_OCM_SIZE 0x40000
135
+
136
+#define MM_TOP_DDR 0x0
137
+#define MM_TOP_DDR_SIZE 0x80000000U
138
+#define MM_TOP_DDR_2 0x800000000ULL
139
+#define MM_TOP_DDR_2_SIZE 0x800000000ULL
140
+#define MM_TOP_DDR_3 0xc000000000ULL
141
+#define MM_TOP_DDR_3_SIZE 0x4000000000ULL
142
+#define MM_TOP_DDR_4 0x10000000000ULL
143
+#define MM_TOP_DDR_4_SIZE 0xb780000000ULL
144
+
145
+#define MM_PSM_START 0xffc80000U
146
+#define MM_PSM_END 0xffcf0000U
147
+
148
+#define MM_CRL 0xff5e0000U
149
+#define MM_CRL_SIZE 0x300000
150
+#define MM_IOU_SCNTR 0xff130000U
151
+#define MM_IOU_SCNTR_SIZE 0x10000
152
+#define MM_IOU_SCNTRS 0xff140000U
153
+#define MM_IOU_SCNTRS_SIZE 0x10000
154
+#define MM_FPD_CRF 0xfd1a0000U
155
+#define MM_FPD_CRF_SIZE 0x140000
156
+#endif
157
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
158
new file mode 100644
159
index XXXXXXX..XXXXXXX
160
--- /dev/null
161
+++ b/hw/arm/xlnx-versal.c
162
@@ -XXX,XX +XXX,XX @@
163
+/*
164
+ * Xilinx Versal SoC model.
165
+ *
166
+ * Copyright (c) 2018 Xilinx Inc.
167
+ * Written by Edgar E. Iglesias
168
+ *
169
+ * This program is free software; you can redistribute it and/or modify
170
+ * it under the terms of the GNU General Public License version 2 or
171
+ * (at your option) any later version.
172
+ */
173
+
174
+#include "qemu/osdep.h"
52
+#include "qemu/osdep.h"
175
+#include "qapi/error.h"
53
+#include "libqtest-single.h"
176
+#include "qemu-common.h"
54
+
177
+#include "qemu/log.h"
55
+#define GPIO_BASE_ADDR 0x48000000
178
+#include "hw/sysbus.h"
56
+#define GPIO_SIZE 0x400
179
+#include "net/net.h"
57
+#define NUM_GPIOS 8
180
+#include "sysemu/sysemu.h"
58
+#define NUM_GPIO_PINS 16
181
+#include "sysemu/kvm.h"
59
+
182
+#include "hw/arm/arm.h"
60
+#define GPIO_A 0x48000000
183
+#include "kvm_arm.h"
61
+#define GPIO_B 0x48000400
184
+#include "hw/misc/unimp.h"
62
+#define GPIO_C 0x48000800
185
+#include "hw/intc/arm_gicv3_common.h"
63
+#define GPIO_D 0x48000C00
186
+#include "hw/arm/xlnx-versal.h"
64
+#define GPIO_E 0x48001000
187
+
65
+#define GPIO_F 0x48001400
188
+#define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
66
+#define GPIO_G 0x48001800
189
+#define GEM_REVISION 0x40070106
67
+#define GPIO_H 0x48001C00
190
+
68
+
191
+static void versal_create_apu_cpus(Versal *s)
69
+#define MODER 0x00
192
+{
70
+#define OTYPER 0x04
193
+ int i;
71
+#define PUPDR 0x0C
194
+
72
+#define IDR 0x10
195
+ for (i = 0; i < ARRAY_SIZE(s->fpd.apu.cpu); i++) {
73
+#define ODR 0x14
196
+ Object *obj;
74
+#define BSRR 0x18
197
+ char *name;
75
+#define BRR 0x28
198
+
76
+
199
+ obj = object_new(XLNX_VERSAL_ACPU_TYPE);
77
+#define MODER_INPUT 0
200
+ if (!obj) {
78
+#define MODER_OUTPUT 1
201
+ /* Secondary CPUs start in PSCI powered-down state */
79
+
202
+ error_report("Unable to create apu.cpu[%d] of type %s",
80
+#define PUPDR_NONE 0
203
+ i, XLNX_VERSAL_ACPU_TYPE);
81
+#define PUPDR_PULLUP 1
204
+ exit(EXIT_FAILURE);
82
+#define PUPDR_PULLDOWN 2
205
+ }
83
+
206
+
84
+#define OTYPER_PUSH_PULL 0
207
+ name = g_strdup_printf("apu-cpu[%d]", i);
85
+#define OTYPER_OPEN_DRAIN 1
208
+ object_property_add_child(OBJECT(s), name, obj, &error_fatal);
86
+
209
+ g_free(name);
87
+const uint32_t moder_reset[NUM_GPIOS] = {
210
+
88
+ 0xABFFFFFF,
211
+ object_property_set_int(obj, s->cfg.psci_conduit,
89
+ 0xFFFFFEBF,
212
+ "psci-conduit", &error_abort);
90
+ 0xFFFFFFFF,
213
+ if (i) {
91
+ 0xFFFFFFFF,
214
+ object_property_set_bool(obj, true,
92
+ 0xFFFFFFFF,
215
+ "start-powered-off", &error_abort);
93
+ 0xFFFFFFFF,
216
+ }
94
+ 0xFFFFFFFF,
217
+
95
+ 0x0000000F
218
+ object_property_set_int(obj, ARRAY_SIZE(s->fpd.apu.cpu),
96
+};
219
+ "core-count", &error_abort);
97
+
220
+ object_property_set_link(obj, OBJECT(&s->fpd.apu.mr), "memory",
98
+const uint32_t pupdr_reset[NUM_GPIOS] = {
221
+ &error_abort);
99
+ 0x64000000,
222
+ object_property_set_bool(obj, true, "realized", &error_fatal);
100
+ 0x00000100,
223
+ s->fpd.apu.cpu[i] = ARM_CPU(obj);
101
+ 0x00000000,
102
+ 0x00000000,
103
+ 0x00000000,
104
+ 0x00000000,
105
+ 0x00000000,
106
+ 0x00000000
107
+};
108
+
109
+const uint32_t idr_reset[NUM_GPIOS] = {
110
+ 0x0000A000,
111
+ 0x00000010,
112
+ 0x00000000,
113
+ 0x00000000,
114
+ 0x00000000,
115
+ 0x00000000,
116
+ 0x00000000,
117
+ 0x00000000
118
+};
119
+
120
+static uint32_t gpio_readl(unsigned int gpio, unsigned int offset)
121
+{
122
+ return readl(gpio + offset);
123
+}
124
+
125
+static void gpio_writel(unsigned int gpio, unsigned int offset, uint32_t value)
126
+{
127
+ writel(gpio + offset, value);
128
+}
129
+
130
+static void gpio_set_bit(unsigned int gpio, unsigned int reg,
131
+ unsigned int pin, uint32_t value)
132
+{
133
+ uint32_t mask = 0xFFFFFFFF & ~(0x1 << pin);
134
+ gpio_writel(gpio, reg, (gpio_readl(gpio, reg) & mask) | value << pin);
135
+}
136
+
137
+static void gpio_set_2bits(unsigned int gpio, unsigned int reg,
138
+ unsigned int pin, uint32_t value)
139
+{
140
+ uint32_t offset = 2 * pin;
141
+ uint32_t mask = 0xFFFFFFFF & ~(0x3 << offset);
142
+ gpio_writel(gpio, reg, (gpio_readl(gpio, reg) & mask) | value << offset);
143
+}
144
+
145
+static unsigned int get_gpio_id(uint32_t gpio_addr)
146
+{
147
+ return (gpio_addr - GPIO_BASE_ADDR) / GPIO_SIZE;
148
+}
149
+
150
+static void gpio_set_irq(unsigned int gpio, int num, int level)
151
+{
152
+ g_autofree char *name = g_strdup_printf("/machine/soc/gpio%c",
153
+ get_gpio_id(gpio) + 'a');
154
+ qtest_set_irq_in(global_qtest, name, NULL, num, level);
155
+}
156
+
157
+static void disconnect_all_pins(unsigned int gpio)
158
+{
159
+ g_autofree char *path = g_strdup_printf("/machine/soc/gpio%c",
160
+ get_gpio_id(gpio) + 'a');
161
+ QDict *r;
162
+
163
+ r = qtest_qmp(global_qtest, "{ 'execute': 'qom-set', 'arguments': "
164
+ "{ 'path': %s, 'property': 'disconnected-pins', 'value': %d } }",
165
+ path, 0xFFFF);
166
+ g_assert_false(qdict_haskey(r, "error"));
167
+ qobject_unref(r);
168
+}
169
+
170
+static uint32_t get_disconnected_pins(unsigned int gpio)
171
+{
172
+ g_autofree char *path = g_strdup_printf("/machine/soc/gpio%c",
173
+ get_gpio_id(gpio) + 'a');
174
+ uint32_t disconnected_pins = 0;
175
+ QDict *r;
176
+
177
+ r = qtest_qmp(global_qtest, "{ 'execute': 'qom-get', 'arguments':"
178
+ " { 'path': %s, 'property': 'disconnected-pins'} }", path);
179
+ g_assert_false(qdict_haskey(r, "error"));
180
+ disconnected_pins = qdict_get_int(r, "return");
181
+ qobject_unref(r);
182
+ return disconnected_pins;
183
+}
184
+
185
+static uint32_t reset(uint32_t gpio, unsigned int offset)
186
+{
187
+ switch (offset) {
188
+ case MODER:
189
+ return moder_reset[get_gpio_id(gpio)];
190
+ case PUPDR:
191
+ return pupdr_reset[get_gpio_id(gpio)];
192
+ case IDR:
193
+ return idr_reset[get_gpio_id(gpio)];
224
+ }
194
+ }
225
+}
195
+ return 0x0;
226
+
196
+}
227
+static void versal_create_apu_gic(Versal *s, qemu_irq *pic)
197
+
228
+{
198
+static void system_reset(void)
229
+ static const uint64_t addrs[] = {
199
+{
230
+ MM_GIC_APU_DIST_MAIN,
200
+ QDict *r;
231
+ MM_GIC_APU_REDIST_0
201
+ r = qtest_qmp(global_qtest, "{'execute': 'system_reset'}");
232
+ };
202
+ g_assert_false(qdict_haskey(r, "error"));
233
+ SysBusDevice *gicbusdev;
203
+ qobject_unref(r);
234
+ DeviceState *gicdev;
204
+}
235
+ int nr_apu_cpus = ARRAY_SIZE(s->fpd.apu.cpu);
205
+
236
+ int i;
206
+static void test_idr_reset_value(void)
237
+
207
+{
238
+ sysbus_init_child_obj(OBJECT(s), "apu-gic",
208
+ /*
239
+ &s->fpd.apu.gic, sizeof(s->fpd.apu.gic),
209
+ * Checks that the values in MODER, OTYPER, PUPDR and ODR
240
+ gicv3_class_name());
210
+ * after reset are correct, and that the value in IDR is
241
+ gicbusdev = SYS_BUS_DEVICE(&s->fpd.apu.gic);
211
+ * coherent.
242
+ gicdev = DEVICE(&s->fpd.apu.gic);
212
+ * Since AF and analog modes aren't implemented, IDR reset
243
+ qdev_prop_set_uint32(gicdev, "revision", 3);
213
+ * values aren't the same as with a real board.
244
+ qdev_prop_set_uint32(gicdev, "num-cpu", 2);
214
+ *
245
+ qdev_prop_set_uint32(gicdev, "num-irq", XLNX_VERSAL_NR_IRQS + 32);
215
+ * Register IDR contains the actual values of all GPIO pins.
246
+ qdev_prop_set_uint32(gicdev, "len-redist-region-count", 1);
216
+ * Its value depends on the pins' configuration
247
+ qdev_prop_set_uint32(gicdev, "redist-region-count[0]", 2);
217
+ * (intput/output/analog : register MODER, push-pull/open-drain :
248
+ qdev_prop_set_bit(gicdev, "has-security-extensions", true);
218
+ * register OTYPER, pull-up/pull-down/none : register PUPDR)
249
+
219
+ * and on the values stored in register ODR
250
+ object_property_set_bool(OBJECT(&s->fpd.apu.gic), true, "realized",
220
+ * (in case the pin is in output mode).
251
+ &error_fatal);
221
+ */
252
+
222
+
253
+ for (i = 0; i < ARRAY_SIZE(addrs); i++) {
223
+ gpio_writel(GPIO_A, MODER, 0xDEADBEEF);
254
+ MemoryRegion *mr;
224
+ gpio_writel(GPIO_A, ODR, 0xDEADBEEF);
255
+
225
+ gpio_writel(GPIO_A, OTYPER, 0xDEADBEEF);
256
+ mr = sysbus_mmio_get_region(gicbusdev, i);
226
+ gpio_writel(GPIO_A, PUPDR, 0xDEADBEEF);
257
+ memory_region_add_subregion(&s->fpd.apu.mr, addrs[i], mr);
227
+
258
+ }
228
+ gpio_writel(GPIO_B, MODER, 0xDEADBEEF);
259
+
229
+ gpio_writel(GPIO_B, ODR, 0xDEADBEEF);
260
+ for (i = 0; i < nr_apu_cpus; i++) {
230
+ gpio_writel(GPIO_B, OTYPER, 0xDEADBEEF);
261
+ DeviceState *cpudev = DEVICE(s->fpd.apu.cpu[i]);
231
+ gpio_writel(GPIO_B, PUPDR, 0xDEADBEEF);
262
+ int ppibase = XLNX_VERSAL_NR_IRQS + i * GIC_INTERNAL + GIC_NR_SGIS;
232
+
263
+ qemu_irq maint_irq;
233
+ gpio_writel(GPIO_C, MODER, 0xDEADBEEF);
264
+ int ti;
234
+ gpio_writel(GPIO_C, ODR, 0xDEADBEEF);
265
+ /* Mapping from the output timer irq lines from the CPU to the
235
+ gpio_writel(GPIO_C, OTYPER, 0xDEADBEEF);
266
+ * GIC PPI inputs.
236
+ gpio_writel(GPIO_C, PUPDR, 0xDEADBEEF);
267
+ */
237
+
268
+ const int timer_irq[] = {
238
+ gpio_writel(GPIO_H, MODER, 0xDEADBEEF);
269
+ [GTIMER_PHYS] = VERSAL_TIMER_NS_EL1_IRQ,
239
+ gpio_writel(GPIO_H, ODR, 0xDEADBEEF);
270
+ [GTIMER_VIRT] = VERSAL_TIMER_VIRT_IRQ,
240
+ gpio_writel(GPIO_H, OTYPER, 0xDEADBEEF);
271
+ [GTIMER_HYP] = VERSAL_TIMER_NS_EL2_IRQ,
241
+ gpio_writel(GPIO_H, PUPDR, 0xDEADBEEF);
272
+ [GTIMER_SEC] = VERSAL_TIMER_S_EL1_IRQ,
242
+
273
+ };
243
+ system_reset();
274
+
244
+
275
+ for (ti = 0; ti < ARRAY_SIZE(timer_irq); ti++) {
245
+ uint32_t moder = gpio_readl(GPIO_A, MODER);
276
+ qdev_connect_gpio_out(cpudev, ti,
246
+ uint32_t odr = gpio_readl(GPIO_A, ODR);
277
+ qdev_get_gpio_in(gicdev,
247
+ uint32_t otyper = gpio_readl(GPIO_A, OTYPER);
278
+ ppibase + timer_irq[ti]));
248
+ uint32_t pupdr = gpio_readl(GPIO_A, PUPDR);
279
+ }
249
+ uint32_t idr = gpio_readl(GPIO_A, IDR);
280
+ maint_irq = qdev_get_gpio_in(gicdev,
250
+ /* 15: AF, 14: AF, 13: AF, 12: Analog ... */
281
+ ppibase + VERSAL_GIC_MAINT_IRQ);
251
+ /* here AF is the same as Analog and Input mode */
282
+ qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
252
+ g_assert_cmphex(moder, ==, reset(GPIO_A, MODER));
283
+ 0, maint_irq);
253
+ g_assert_cmphex(odr, ==, reset(GPIO_A, ODR));
284
+ sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
254
+ g_assert_cmphex(otyper, ==, reset(GPIO_A, OTYPER));
285
+ sysbus_connect_irq(gicbusdev, i + nr_apu_cpus,
255
+ /* 15: pull-up, 14: pull-down, 13: pull-up, 12: neither ... */
286
+ qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
256
+ g_assert_cmphex(pupdr, ==, reset(GPIO_A, PUPDR));
287
+ sysbus_connect_irq(gicbusdev, i + 2 * nr_apu_cpus,
257
+ /* 15 : 1, 14: 0, 13: 1, 12 : reset value ... */
288
+ qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
258
+ g_assert_cmphex(idr, ==, reset(GPIO_A, IDR));
289
+ sysbus_connect_irq(gicbusdev, i + 3 * nr_apu_cpus,
259
+
290
+ qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
260
+ moder = gpio_readl(GPIO_B, MODER);
291
+ }
261
+ odr = gpio_readl(GPIO_B, ODR);
292
+
262
+ otyper = gpio_readl(GPIO_B, OTYPER);
293
+ for (i = 0; i < XLNX_VERSAL_NR_IRQS; i++) {
263
+ pupdr = gpio_readl(GPIO_B, PUPDR);
294
+ pic[i] = qdev_get_gpio_in(gicdev, i);
264
+ idr = gpio_readl(GPIO_B, IDR);
295
+ }
265
+ /* ... 5: Analog, 4: AF, 3: AF, 2: Analog ... */
296
+}
266
+ /* here AF is the same as Analog and Input mode */
297
+
267
+ g_assert_cmphex(moder, ==, reset(GPIO_B, MODER));
298
+static void versal_create_uarts(Versal *s, qemu_irq *pic)
268
+ g_assert_cmphex(odr, ==, reset(GPIO_B, ODR));
299
+{
269
+ g_assert_cmphex(otyper, ==, reset(GPIO_B, OTYPER));
300
+ int i;
270
+ /* ... 5: neither, 4: pull-up, 3: neither ... */
301
+
271
+ g_assert_cmphex(pupdr, ==, reset(GPIO_B, PUPDR));
302
+ for (i = 0; i < ARRAY_SIZE(s->lpd.iou.uart); i++) {
272
+ /* ... 5 : reset value, 4 : 1, 3 : reset value ... */
303
+ static const int irqs[] = { VERSAL_UART0_IRQ_0, VERSAL_UART1_IRQ_0};
273
+ g_assert_cmphex(idr, ==, reset(GPIO_B, IDR));
304
+ static const uint64_t addrs[] = { MM_UART0, MM_UART1 };
274
+
305
+ char *name = g_strdup_printf("uart%d", i);
275
+ moder = gpio_readl(GPIO_C, MODER);
306
+ DeviceState *dev;
276
+ odr = gpio_readl(GPIO_C, ODR);
307
+ MemoryRegion *mr;
277
+ otyper = gpio_readl(GPIO_C, OTYPER);
308
+
278
+ pupdr = gpio_readl(GPIO_C, PUPDR);
309
+ dev = qdev_create(NULL, "pl011");
279
+ idr = gpio_readl(GPIO_C, IDR);
310
+ s->lpd.iou.uart[i] = SYS_BUS_DEVICE(dev);
280
+ /* Analog, same as Input mode*/
311
+ qdev_prop_set_chr(dev, "chardev", serial_hd(i));
281
+ g_assert_cmphex(moder, ==, reset(GPIO_C, MODER));
312
+ object_property_add_child(OBJECT(s), name, OBJECT(dev), &error_fatal);
282
+ g_assert_cmphex(odr, ==, reset(GPIO_C, ODR));
313
+ qdev_init_nofail(dev);
283
+ g_assert_cmphex(otyper, ==, reset(GPIO_C, OTYPER));
314
+
284
+ /* no pull-up or pull-down */
315
+ mr = sysbus_mmio_get_region(s->lpd.iou.uart[i], 0);
285
+ g_assert_cmphex(pupdr, ==, reset(GPIO_C, PUPDR));
316
+ memory_region_add_subregion(&s->mr_ps, addrs[i], mr);
286
+ /* reset value */
317
+
287
+ g_assert_cmphex(idr, ==, reset(GPIO_C, IDR));
318
+ sysbus_connect_irq(s->lpd.iou.uart[i], 0, pic[irqs[i]]);
288
+
319
+ g_free(name);
289
+ moder = gpio_readl(GPIO_H, MODER);
320
+ }
290
+ odr = gpio_readl(GPIO_H, ODR);
321
+}
291
+ otyper = gpio_readl(GPIO_H, OTYPER);
322
+
292
+ pupdr = gpio_readl(GPIO_H, PUPDR);
323
+static void versal_create_gems(Versal *s, qemu_irq *pic)
293
+ idr = gpio_readl(GPIO_H, IDR);
324
+{
294
+ /* Analog, same as Input mode */
325
+ int i;
295
+ g_assert_cmphex(moder, ==, reset(GPIO_H, MODER));
326
+
296
+ g_assert_cmphex(odr, ==, reset(GPIO_H, ODR));
327
+ for (i = 0; i < ARRAY_SIZE(s->lpd.iou.gem); i++) {
297
+ g_assert_cmphex(otyper, ==, reset(GPIO_H, OTYPER));
328
+ static const int irqs[] = { VERSAL_GEM0_IRQ_0, VERSAL_GEM1_IRQ_0};
298
+ /* no pull-up or pull-down */
329
+ static const uint64_t addrs[] = { MM_GEM0, MM_GEM1 };
299
+ g_assert_cmphex(pupdr, ==, reset(GPIO_H, PUPDR));
330
+ char *name = g_strdup_printf("gem%d", i);
300
+ /* reset value */
331
+ NICInfo *nd = &nd_table[i];
301
+ g_assert_cmphex(idr, ==, reset(GPIO_H, IDR));
332
+ DeviceState *dev;
302
+}
333
+ MemoryRegion *mr;
303
+
334
+
304
+static void test_gpio_output_mode(const void *data)
335
+ dev = qdev_create(NULL, "cadence_gem");
305
+{
336
+ s->lpd.iou.gem[i] = SYS_BUS_DEVICE(dev);
306
+ /*
337
+ object_property_add_child(OBJECT(s), name, OBJECT(dev), &error_fatal);
307
+ * Checks that setting a bit in ODR sets the corresponding
338
+ if (nd->used) {
308
+ * GPIO line high : it should set the right bit in IDR
339
+ qemu_check_nic_model(nd, "cadence_gem");
309
+ * and send an irq to syscfg.
340
+ qdev_set_nic_properties(dev, nd);
310
+ * Additionally, it checks that values written to ODR
341
+ }
311
+ * when not in output mode are stored and not discarded.
342
+ object_property_set_int(OBJECT(s->lpd.iou.gem[i]),
312
+ */
343
+ 2, "num-priority-queues",
313
+ unsigned int pin = ((uint64_t)data) & 0xF;
344
+ &error_abort);
314
+ uint32_t gpio = ((uint64_t)data) >> 32;
345
+ object_property_set_link(OBJECT(s->lpd.iou.gem[i]),
315
+ unsigned int gpio_id = get_gpio_id(gpio);
346
+ OBJECT(&s->mr_ps), "dma",
316
+
347
+ &error_abort);
317
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
348
+ qdev_init_nofail(dev);
318
+
349
+
319
+ /* Set a bit in ODR and check nothing happens */
350
+ mr = sysbus_mmio_get_region(s->lpd.iou.gem[i], 0);
320
+ gpio_set_bit(gpio, ODR, pin, 1);
351
+ memory_region_add_subregion(&s->mr_ps, addrs[i], mr);
321
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
352
+
322
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
353
+ sysbus_connect_irq(s->lpd.iou.gem[i], 0, pic[irqs[i]]);
323
+
354
+ g_free(name);
324
+ /* Configure the relevant line as output and check the pin is high */
355
+ }
325
+ gpio_set_2bits(gpio, MODER, pin, MODER_OUTPUT);
356
+}
326
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) | (1 << pin));
357
+
327
+ g_assert_true(get_irq(gpio_id * NUM_GPIO_PINS + pin));
358
+/* This takes the board allocated linear DDR memory and creates aliases
328
+
359
+ * for each split DDR range/aperture on the Versal address map.
329
+ /* Reset the bit in ODR and check the pin is low */
360
+ */
330
+ gpio_set_bit(gpio, ODR, pin, 0);
361
+static void versal_map_ddr(Versal *s)
331
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
362
+{
332
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
363
+ uint64_t size = memory_region_size(s->cfg.mr_ddr);
333
+
364
+ /* Describes the various split DDR access regions. */
334
+ /* Clean the test */
365
+ static const struct {
335
+ gpio_writel(gpio, ODR, reset(gpio, ODR));
366
+ uint64_t base;
336
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
367
+ uint64_t size;
337
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
368
+ } addr_ranges[] = {
338
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
369
+ { MM_TOP_DDR, MM_TOP_DDR_SIZE },
339
+}
370
+ { MM_TOP_DDR_2, MM_TOP_DDR_2_SIZE },
340
+
371
+ { MM_TOP_DDR_3, MM_TOP_DDR_3_SIZE },
341
+static void test_gpio_input_mode(const void *data)
372
+ { MM_TOP_DDR_4, MM_TOP_DDR_4_SIZE }
342
+{
373
+ };
343
+ /*
374
+ uint64_t offset = 0;
344
+ * Test that setting a line high/low externally sets the
375
+ int i;
345
+ * corresponding GPIO line high/low : it should set the
376
+
346
+ * right bit in IDR and send an irq to syscfg.
377
+ assert(ARRAY_SIZE(addr_ranges) == ARRAY_SIZE(s->noc.mr_ddr_ranges));
347
+ */
378
+ for (i = 0; i < ARRAY_SIZE(addr_ranges) && size; i++) {
348
+ unsigned int pin = ((uint64_t)data) & 0xF;
379
+ char *name;
349
+ uint32_t gpio = ((uint64_t)data) >> 32;
380
+ uint64_t mapsize;
350
+ unsigned int gpio_id = get_gpio_id(gpio);
381
+
351
+
382
+ mapsize = size < addr_ranges[i].size ? size : addr_ranges[i].size;
352
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
383
+ name = g_strdup_printf("noc-ddr-range%d", i);
353
+
384
+ /* Create the MR alias. */
354
+ /* Configure a line as input, raise it, and check that the pin is high */
385
+ memory_region_init_alias(&s->noc.mr_ddr_ranges[i], OBJECT(s),
355
+ gpio_set_2bits(gpio, MODER, pin, MODER_INPUT);
386
+ name, s->cfg.mr_ddr,
356
+ gpio_set_irq(gpio, pin, 1);
387
+ offset, mapsize);
357
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) | (1 << pin));
388
+
358
+ g_assert_true(get_irq(gpio_id * NUM_GPIO_PINS + pin));
389
+ /* Map it onto the NoC MR. */
359
+
390
+ memory_region_add_subregion(&s->mr_ps, addr_ranges[i].base,
360
+ /* Lower the line and check that the pin is low */
391
+ &s->noc.mr_ddr_ranges[i]);
361
+ gpio_set_irq(gpio, pin, 0);
392
+ offset += mapsize;
362
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
393
+ size -= mapsize;
363
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
394
+ g_free(name);
364
+
395
+ }
365
+ /* Clean the test */
396
+}
366
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
397
+
367
+ disconnect_all_pins(gpio);
398
+static void versal_unimp_area(Versal *s, const char *name,
368
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
399
+ MemoryRegion *mr,
369
+}
400
+ hwaddr base, hwaddr size)
370
+
401
+{
371
+static void test_pull_up_pull_down(const void *data)
402
+ DeviceState *dev = qdev_create(NULL, TYPE_UNIMPLEMENTED_DEVICE);
372
+{
403
+ MemoryRegion *mr_dev;
373
+ /*
404
+
374
+ * Test that a floating pin with pull-up sets the pin
405
+ qdev_prop_set_string(dev, "name", name);
375
+ * high and vice-versa.
406
+ qdev_prop_set_uint64(dev, "size", size);
376
+ */
407
+ object_property_add_child(OBJECT(s), name, OBJECT(dev), &error_fatal);
377
+ unsigned int pin = ((uint64_t)data) & 0xF;
408
+ qdev_init_nofail(dev);
378
+ uint32_t gpio = ((uint64_t)data) >> 32;
409
+
379
+ unsigned int gpio_id = get_gpio_id(gpio);
410
+ mr_dev = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
380
+
411
+ memory_region_add_subregion(mr, base, mr_dev);
381
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
412
+}
382
+
413
+
383
+ /* Configure a line as input with pull-up, check the line is set high */
414
+static void versal_unimp(Versal *s)
384
+ gpio_set_2bits(gpio, MODER, pin, MODER_INPUT);
415
+{
385
+ gpio_set_2bits(gpio, PUPDR, pin, PUPDR_PULLUP);
416
+ versal_unimp_area(s, "psm", &s->mr_ps,
386
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) | (1 << pin));
417
+ MM_PSM_START, MM_PSM_END - MM_PSM_START);
387
+ g_assert_true(get_irq(gpio_id * NUM_GPIO_PINS + pin));
418
+ versal_unimp_area(s, "crl", &s->mr_ps,
388
+
419
+ MM_CRL, MM_CRL_SIZE);
389
+ /* Configure the line with pull-down, check the line is low */
420
+ versal_unimp_area(s, "crf", &s->mr_ps,
390
+ gpio_set_2bits(gpio, PUPDR, pin, PUPDR_PULLDOWN);
421
+ MM_FPD_CRF, MM_FPD_CRF_SIZE);
391
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
422
+ versal_unimp_area(s, "iou-scntr", &s->mr_ps,
392
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
423
+ MM_IOU_SCNTR, MM_IOU_SCNTR_SIZE);
393
+
424
+ versal_unimp_area(s, "iou-scntr-seucre", &s->mr_ps,
394
+ /* Clean the test */
425
+ MM_IOU_SCNTRS, MM_IOU_SCNTRS_SIZE);
395
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
426
+}
396
+ gpio_writel(gpio, PUPDR, reset(gpio, PUPDR));
427
+
397
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
428
+static void versal_realize(DeviceState *dev, Error **errp)
398
+}
429
+{
399
+
430
+ Versal *s = XLNX_VERSAL(dev);
400
+static void test_push_pull(const void *data)
431
+ qemu_irq pic[XLNX_VERSAL_NR_IRQS];
401
+{
432
+
402
+ /*
433
+ versal_create_apu_cpus(s);
403
+ * Test that configuring a line in push-pull output mode
434
+ versal_create_apu_gic(s, pic);
404
+ * disconnects the pin, that the pin can't be set or reset
435
+ versal_create_uarts(s, pic);
405
+ * externally afterwards.
436
+ versal_create_gems(s, pic);
406
+ */
437
+ versal_map_ddr(s);
407
+ unsigned int pin = ((uint64_t)data) & 0xF;
438
+ versal_unimp(s);
408
+ uint32_t gpio = ((uint64_t)data) >> 32;
439
+
409
+ uint32_t gpio2 = GPIO_BASE_ADDR + (GPIO_H - gpio);
440
+ /* Create the On Chip Memory (OCM). */
410
+
441
+ memory_region_init_ram(&s->lpd.mr_ocm, OBJECT(s), "ocm",
411
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
442
+ MM_OCM_SIZE, &error_fatal);
412
+
443
+
413
+ /* Setting a line high externally, configuring it in push-pull output */
444
+ memory_region_add_subregion_overlap(&s->mr_ps, MM_OCM, &s->lpd.mr_ocm, 0);
414
+ /* And checking the pin was disconnected */
445
+ memory_region_add_subregion_overlap(&s->fpd.apu.mr, 0, &s->mr_ps, 0);
415
+ gpio_set_irq(gpio, pin, 1);
446
+}
416
+ gpio_set_2bits(gpio, MODER, pin, MODER_OUTPUT);
447
+
417
+ g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
448
+static void versal_init(Object *obj)
418
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
449
+{
419
+
450
+ Versal *s = XLNX_VERSAL(obj);
420
+ /* Setting a line low externally, configuring it in push-pull output */
451
+
421
+ /* And checking the pin was disconnected */
452
+ memory_region_init(&s->fpd.apu.mr, obj, "mr-apu", UINT64_MAX);
422
+ gpio_set_irq(gpio2, pin, 0);
453
+ memory_region_init(&s->mr_ps, obj, "mr-ps-switch", UINT64_MAX);
423
+ gpio_set_bit(gpio2, ODR, pin, 1);
454
+}
424
+ gpio_set_2bits(gpio2, MODER, pin, MODER_OUTPUT);
455
+
425
+ g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF);
456
+static Property versal_properties[] = {
426
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==, reset(gpio2, IDR) | (1 << pin));
457
+ DEFINE_PROP_LINK("ddr", Versal, cfg.mr_ddr, TYPE_MEMORY_REGION,
427
+
458
+ MemoryRegion *),
428
+ /* Trying to set a push-pull output pin, checking it doesn't work */
459
+ DEFINE_PROP_UINT32("psci-conduit", Versal, cfg.psci_conduit, 0),
429
+ gpio_set_irq(gpio, pin, 1);
460
+ DEFINE_PROP_END_OF_LIST()
430
+ g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
461
+};
431
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
462
+
432
+
463
+static void versal_class_init(ObjectClass *klass, void *data)
433
+ /* Trying to reset a push-pull output pin, checking it doesn't work */
464
+{
434
+ gpio_set_irq(gpio2, pin, 0);
465
+ DeviceClass *dc = DEVICE_CLASS(klass);
435
+ g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF);
466
+
436
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==, reset(gpio2, IDR) | (1 << pin));
467
+ dc->realize = versal_realize;
437
+
468
+ dc->props = versal_properties;
438
+ /* Clean the test */
469
+ /* No VMSD since we haven't got any top-level SoC state to save. */
439
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
470
+}
440
+ gpio_writel(gpio2, ODR, reset(gpio2, ODR));
471
+
441
+ gpio_writel(gpio2, MODER, reset(gpio2, MODER));
472
+static const TypeInfo versal_info = {
442
+}
473
+ .name = TYPE_XLNX_VERSAL,
443
+
474
+ .parent = TYPE_SYS_BUS_DEVICE,
444
+static void test_open_drain(const void *data)
475
+ .instance_size = sizeof(Versal),
445
+{
476
+ .instance_init = versal_init,
446
+ /*
477
+ .class_init = versal_class_init,
447
+ * Test that configuring a line in open-drain output mode
478
+};
448
+ * disconnects a pin set high externally and that the pin
479
+
449
+ * can't be set high externally while configured in open-drain.
480
+static void versal_register_types(void)
450
+ *
481
+{
451
+ * However a pin set low externally shouldn't be disconnected,
482
+ type_register_static(&versal_info);
452
+ * and it can be set low externally when in open-drain mode.
483
+}
453
+ */
484
+
454
+ unsigned int pin = ((uint64_t)data) & 0xF;
485
+type_init(versal_register_types);
455
+ uint32_t gpio = ((uint64_t)data) >> 32;
486
diff --git a/default-configs/aarch64-softmmu.mak b/default-configs/aarch64-softmmu.mak
456
+ uint32_t gpio2 = GPIO_BASE_ADDR + (GPIO_H - gpio);
457
+
458
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
459
+
460
+ /* Setting a line high externally, configuring it in open-drain output */
461
+ /* And checking the pin was disconnected */
462
+ gpio_set_irq(gpio, pin, 1);
463
+ gpio_set_bit(gpio, OTYPER, pin, OTYPER_OPEN_DRAIN);
464
+ gpio_set_2bits(gpio, MODER, pin, MODER_OUTPUT);
465
+ g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
466
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
467
+
468
+ /* Setting a line low externally, configuring it in open-drain output */
469
+ /* And checking the pin wasn't disconnected */
470
+ gpio_set_irq(gpio2, pin, 0);
471
+ gpio_set_bit(gpio2, ODR, pin, 1);
472
+ gpio_set_bit(gpio2, OTYPER, pin, OTYPER_OPEN_DRAIN);
473
+ gpio_set_2bits(gpio2, MODER, pin, MODER_OUTPUT);
474
+ g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF & ~(1 << pin));
475
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==,
476
+ reset(gpio2, IDR) & ~(1 << pin));
477
+
478
+ /* Trying to set a open-drain output pin, checking it doesn't work */
479
+ gpio_set_irq(gpio, pin, 1);
480
+ g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
481
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
482
+
483
+ /* Trying to reset a open-drain output pin, checking it works */
484
+ gpio_set_bit(gpio, ODR, pin, 1);
485
+ gpio_set_irq(gpio, pin, 0);
486
+ g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF & ~(1 << pin));
487
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==,
488
+ reset(gpio2, IDR) & ~(1 << pin));
489
+
490
+ /* Clean the test */
491
+ disconnect_all_pins(gpio2);
492
+ gpio_writel(gpio2, OTYPER, reset(gpio2, OTYPER));
493
+ gpio_writel(gpio2, ODR, reset(gpio2, ODR));
494
+ gpio_writel(gpio2, MODER, reset(gpio2, MODER));
495
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==, reset(gpio2, IDR));
496
+ disconnect_all_pins(gpio);
497
+ gpio_writel(gpio, OTYPER, reset(gpio, OTYPER));
498
+ gpio_writel(gpio, ODR, reset(gpio, ODR));
499
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
500
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
501
+}
502
+
503
+static void test_bsrr_brr(const void *data)
504
+{
505
+ /*
506
+ * Test that writing a '1' in BSS and BSRR
507
+ * has the desired effect on ODR.
508
+ * In BSRR, BSx has priority over BRx.
509
+ */
510
+ unsigned int pin = ((uint64_t)data) & 0xF;
511
+ uint32_t gpio = ((uint64_t)data) >> 32;
512
+
513
+ gpio_writel(gpio, BSRR, (1 << pin));
514
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR) | (1 << pin));
515
+
516
+ gpio_writel(gpio, BSRR, (1 << (pin + NUM_GPIO_PINS)));
517
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR));
518
+
519
+ gpio_writel(gpio, BSRR, (1 << pin));
520
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR) | (1 << pin));
521
+
522
+ gpio_writel(gpio, BRR, (1 << pin));
523
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR));
524
+
525
+ /* BSx should have priority over BRx */
526
+ gpio_writel(gpio, BSRR, (1 << pin) | (1 << (pin + NUM_GPIO_PINS)));
527
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR) | (1 << pin));
528
+
529
+ gpio_writel(gpio, BRR, (1 << pin));
530
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR));
531
+
532
+ gpio_writel(gpio, ODR, reset(gpio, ODR));
533
+}
534
+
535
+int main(int argc, char **argv)
536
+{
537
+ int ret;
538
+
539
+ g_test_init(&argc, &argv, NULL);
540
+ g_test_set_nonfatal_assertions();
541
+ qtest_add_func("stm32l4x5/gpio/test_idr_reset_value",
542
+ test_idr_reset_value);
543
+ /*
544
+ * The inputs for the tests (gpio and pin) can be changed,
545
+ * but the tests don't work for pins that are high at reset
546
+ * (GPIOA15, GPIO13 and GPIOB5).
547
+ * Specifically, rising the pin then checking `get_irq()`
548
+ * is problematic since the pin was already high.
549
+ */
550
+ qtest_add_data_func("stm32l4x5/gpio/test_gpioc5_output_mode",
551
+ (void *)((uint64_t)GPIO_C << 32 | 5),
552
+ test_gpio_output_mode);
553
+ qtest_add_data_func("stm32l4x5/gpio/test_gpioh3_output_mode",
554
+ (void *)((uint64_t)GPIO_H << 32 | 3),
555
+ test_gpio_output_mode);
556
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_input_mode1",
557
+ (void *)((uint64_t)GPIO_D << 32 | 6),
558
+ test_gpio_input_mode);
559
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_input_mode2",
560
+ (void *)((uint64_t)GPIO_C << 32 | 10),
561
+ test_gpio_input_mode);
562
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_pull_up_pull_down1",
563
+ (void *)((uint64_t)GPIO_B << 32 | 5),
564
+ test_pull_up_pull_down);
565
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_pull_up_pull_down2",
566
+ (void *)((uint64_t)GPIO_F << 32 | 1),
567
+ test_pull_up_pull_down);
568
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_push_pull1",
569
+ (void *)((uint64_t)GPIO_G << 32 | 6),
570
+ test_push_pull);
571
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_push_pull2",
572
+ (void *)((uint64_t)GPIO_H << 32 | 3),
573
+ test_push_pull);
574
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_open_drain1",
575
+ (void *)((uint64_t)GPIO_C << 32 | 4),
576
+ test_open_drain);
577
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_open_drain2",
578
+ (void *)((uint64_t)GPIO_E << 32 | 11),
579
+ test_open_drain);
580
+ qtest_add_data_func("stm32l4x5/gpio/test_bsrr_brr1",
581
+ (void *)((uint64_t)GPIO_A << 32 | 12),
582
+ test_bsrr_brr);
583
+ qtest_add_data_func("stm32l4x5/gpio/test_bsrr_brr2",
584
+ (void *)((uint64_t)GPIO_D << 32 | 0),
585
+ test_bsrr_brr);
586
+
587
+ qtest_start("-machine b-l475e-iot01a");
588
+ ret = g_test_run();
589
+ qtest_end();
590
+
591
+ return ret;
592
+}
593
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
487
index XXXXXXX..XXXXXXX 100644
594
index XXXXXXX..XXXXXXX 100644
488
--- a/default-configs/aarch64-softmmu.mak
595
--- a/tests/qtest/meson.build
489
+++ b/default-configs/aarch64-softmmu.mak
596
+++ b/tests/qtest/meson.build
490
@@ -XXX,XX +XXX,XX @@ CONFIG_DDC=y
597
@@ -XXX,XX +XXX,XX @@ qtests_aspeed = \
491
CONFIG_DPCD=y
598
qtests_stm32l4x5 = \
492
CONFIG_XLNX_ZYNQMP=y
599
['stm32l4x5_exti-test',
493
CONFIG_XLNX_ZYNQMP_ARM=y
600
'stm32l4x5_syscfg-test',
494
+CONFIG_XLNX_VERSAL=y
601
- 'stm32l4x5_rcc-test']
495
CONFIG_ARM_SMMUV3=y
602
+ 'stm32l4x5_rcc-test',
603
+ 'stm32l4x5_gpio-test']
604
605
qtests_arm = \
606
(config_all_devices.has_key('CONFIG_MPS2') ? ['sse-timer-test'] : []) + \
496
--
607
--
497
2.19.1
608
2.34.1
498
609
499
610
diff view generated by jsdifflib
New patch
1
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
While the 8-bit input elements are sequential in the input vector,
4
the 32-bit output elements are not sequential in the output matrix.
5
Do not attempt to compute 2 32-bit outputs at the same time.
6
7
Cc: qemu-stable@nongnu.org
8
Fixes: 23a5e3859f5 ("target/arm: Implement SME integer outer product")
9
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2083
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
12
Message-id: 20240305163931.242795-1-richard.henderson@linaro.org
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
target/arm/tcg/sme_helper.c | 77 ++++++++++++++++++-------------
16
tests/tcg/aarch64/sme-smopa-1.c | 47 +++++++++++++++++++
17
tests/tcg/aarch64/sme-smopa-2.c | 54 ++++++++++++++++++++++
18
tests/tcg/aarch64/Makefile.target | 2 +-
19
4 files changed, 147 insertions(+), 33 deletions(-)
20
create mode 100644 tests/tcg/aarch64/sme-smopa-1.c
21
create mode 100644 tests/tcg/aarch64/sme-smopa-2.c
22
23
diff --git a/target/arm/tcg/sme_helper.c b/target/arm/tcg/sme_helper.c
24
index XXXXXXX..XXXXXXX 100644
25
--- a/target/arm/tcg/sme_helper.c
26
+++ b/target/arm/tcg/sme_helper.c
27
@@ -XXX,XX +XXX,XX @@ void HELPER(sme_bfmopa)(void *vza, void *vzn, void *vzm, void *vpn,
28
}
29
}
30
31
-typedef uint64_t IMOPFn(uint64_t, uint64_t, uint64_t, uint8_t, bool);
32
+typedef uint32_t IMOPFn32(uint32_t, uint32_t, uint32_t, uint8_t, bool);
33
+static inline void do_imopa_s(uint32_t *za, uint32_t *zn, uint32_t *zm,
34
+ uint8_t *pn, uint8_t *pm,
35
+ uint32_t desc, IMOPFn32 *fn)
36
+{
37
+ intptr_t row, col, oprsz = simd_oprsz(desc) / 4;
38
+ bool neg = simd_data(desc);
39
40
-static inline void do_imopa(uint64_t *za, uint64_t *zn, uint64_t *zm,
41
- uint8_t *pn, uint8_t *pm,
42
- uint32_t desc, IMOPFn *fn)
43
+ for (row = 0; row < oprsz; ++row) {
44
+ uint8_t pa = (pn[H1(row >> 1)] >> ((row & 1) * 4)) & 0xf;
45
+ uint32_t *za_row = &za[tile_vslice_index(row)];
46
+ uint32_t n = zn[H4(row)];
47
+
48
+ for (col = 0; col < oprsz; ++col) {
49
+ uint8_t pb = pm[H1(col >> 1)] >> ((col & 1) * 4);
50
+ uint32_t *a = &za_row[H4(col)];
51
+
52
+ *a = fn(n, zm[H4(col)], *a, pa & pb, neg);
53
+ }
54
+ }
55
+}
56
+
57
+typedef uint64_t IMOPFn64(uint64_t, uint64_t, uint64_t, uint8_t, bool);
58
+static inline void do_imopa_d(uint64_t *za, uint64_t *zn, uint64_t *zm,
59
+ uint8_t *pn, uint8_t *pm,
60
+ uint32_t desc, IMOPFn64 *fn)
61
{
62
intptr_t row, col, oprsz = simd_oprsz(desc) / 8;
63
bool neg = simd_data(desc);
64
@@ -XXX,XX +XXX,XX @@ static inline void do_imopa(uint64_t *za, uint64_t *zn, uint64_t *zm,
65
}
66
67
#define DEF_IMOP_32(NAME, NTYPE, MTYPE) \
68
-static uint64_t NAME(uint64_t n, uint64_t m, uint64_t a, uint8_t p, bool neg) \
69
+static uint32_t NAME(uint32_t n, uint32_t m, uint32_t a, uint8_t p, bool neg) \
70
{ \
71
- uint32_t sum0 = 0, sum1 = 0; \
72
+ uint32_t sum = 0; \
73
/* Apply P to N as a mask, making the inactive elements 0. */ \
74
n &= expand_pred_b(p); \
75
- sum0 += (NTYPE)(n >> 0) * (MTYPE)(m >> 0); \
76
- sum0 += (NTYPE)(n >> 8) * (MTYPE)(m >> 8); \
77
- sum0 += (NTYPE)(n >> 16) * (MTYPE)(m >> 16); \
78
- sum0 += (NTYPE)(n >> 24) * (MTYPE)(m >> 24); \
79
- sum1 += (NTYPE)(n >> 32) * (MTYPE)(m >> 32); \
80
- sum1 += (NTYPE)(n >> 40) * (MTYPE)(m >> 40); \
81
- sum1 += (NTYPE)(n >> 48) * (MTYPE)(m >> 48); \
82
- sum1 += (NTYPE)(n >> 56) * (MTYPE)(m >> 56); \
83
- if (neg) { \
84
- sum0 = (uint32_t)a - sum0, sum1 = (uint32_t)(a >> 32) - sum1; \
85
- } else { \
86
- sum0 = (uint32_t)a + sum0, sum1 = (uint32_t)(a >> 32) + sum1; \
87
- } \
88
- return ((uint64_t)sum1 << 32) | sum0; \
89
+ sum += (NTYPE)(n >> 0) * (MTYPE)(m >> 0); \
90
+ sum += (NTYPE)(n >> 8) * (MTYPE)(m >> 8); \
91
+ sum += (NTYPE)(n >> 16) * (MTYPE)(m >> 16); \
92
+ sum += (NTYPE)(n >> 24) * (MTYPE)(m >> 24); \
93
+ return neg ? a - sum : a + sum; \
94
}
95
96
#define DEF_IMOP_64(NAME, NTYPE, MTYPE) \
97
@@ -XXX,XX +XXX,XX @@ DEF_IMOP_64(umopa_d, uint16_t, uint16_t)
98
DEF_IMOP_64(sumopa_d, int16_t, uint16_t)
99
DEF_IMOP_64(usmopa_d, uint16_t, int16_t)
100
101
-#define DEF_IMOPH(NAME) \
102
- void HELPER(sme_##NAME)(void *vza, void *vzn, void *vzm, void *vpn, \
103
- void *vpm, uint32_t desc) \
104
- { do_imopa(vza, vzn, vzm, vpn, vpm, desc, NAME); }
105
+#define DEF_IMOPH(NAME, S) \
106
+ void HELPER(sme_##NAME##_##S)(void *vza, void *vzn, void *vzm, \
107
+ void *vpn, void *vpm, uint32_t desc) \
108
+ { do_imopa_##S(vza, vzn, vzm, vpn, vpm, desc, NAME##_##S); }
109
110
-DEF_IMOPH(smopa_s)
111
-DEF_IMOPH(umopa_s)
112
-DEF_IMOPH(sumopa_s)
113
-DEF_IMOPH(usmopa_s)
114
-DEF_IMOPH(smopa_d)
115
-DEF_IMOPH(umopa_d)
116
-DEF_IMOPH(sumopa_d)
117
-DEF_IMOPH(usmopa_d)
118
+DEF_IMOPH(smopa, s)
119
+DEF_IMOPH(umopa, s)
120
+DEF_IMOPH(sumopa, s)
121
+DEF_IMOPH(usmopa, s)
122
+
123
+DEF_IMOPH(smopa, d)
124
+DEF_IMOPH(umopa, d)
125
+DEF_IMOPH(sumopa, d)
126
+DEF_IMOPH(usmopa, d)
127
diff --git a/tests/tcg/aarch64/sme-smopa-1.c b/tests/tcg/aarch64/sme-smopa-1.c
128
new file mode 100644
129
index XXXXXXX..XXXXXXX
130
--- /dev/null
131
+++ b/tests/tcg/aarch64/sme-smopa-1.c
132
@@ -XXX,XX +XXX,XX @@
133
+#include <stdio.h>
134
+#include <string.h>
135
+
136
+int main()
137
+{
138
+ static const int cmp[4][4] = {
139
+ { 110, 134, 158, 182 },
140
+ { 390, 478, 566, 654 },
141
+ { 670, 822, 974, 1126 },
142
+ { 950, 1166, 1382, 1598 }
143
+ };
144
+ int dst[4][4];
145
+ int *tmp = &dst[0][0];
146
+
147
+ asm volatile(
148
+ ".arch armv8-r+sme\n\t"
149
+ "smstart\n\t"
150
+ "index z0.b, #0, #1\n\t"
151
+ "movprfx z1, z0\n\t"
152
+ "add z1.b, z1.b, #16\n\t"
153
+ "ptrue p0.b\n\t"
154
+ "smopa za0.s, p0/m, p0/m, z0.b, z1.b\n\t"
155
+ "ptrue p0.s, vl4\n\t"
156
+ "mov w12, #0\n\t"
157
+ "st1w { za0h.s[w12, #0] }, p0, [%0]\n\t"
158
+ "add %0, %0, #16\n\t"
159
+ "st1w { za0h.s[w12, #1] }, p0, [%0]\n\t"
160
+ "add %0, %0, #16\n\t"
161
+ "st1w { za0h.s[w12, #2] }, p0, [%0]\n\t"
162
+ "add %0, %0, #16\n\t"
163
+ "st1w { za0h.s[w12, #3] }, p0, [%0]\n\t"
164
+ "smstop"
165
+ : "+r"(tmp) : : "memory");
166
+
167
+ if (memcmp(cmp, dst, sizeof(dst)) == 0) {
168
+ return 0;
169
+ }
170
+
171
+ /* See above for correct results. */
172
+ for (int i = 0; i < 4; ++i) {
173
+ for (int j = 0; j < 4; ++j) {
174
+ printf("%6d", dst[i][j]);
175
+ }
176
+ printf("\n");
177
+ }
178
+ return 1;
179
+}
180
diff --git a/tests/tcg/aarch64/sme-smopa-2.c b/tests/tcg/aarch64/sme-smopa-2.c
181
new file mode 100644
182
index XXXXXXX..XXXXXXX
183
--- /dev/null
184
+++ b/tests/tcg/aarch64/sme-smopa-2.c
185
@@ -XXX,XX +XXX,XX @@
186
+#include <stdio.h>
187
+#include <string.h>
188
+
189
+int main()
190
+{
191
+ static const long cmp[4][4] = {
192
+ { 110, 134, 158, 182 },
193
+ { 390, 478, 566, 654 },
194
+ { 670, 822, 974, 1126 },
195
+ { 950, 1166, 1382, 1598 }
196
+ };
197
+ long dst[4][4];
198
+ long *tmp = &dst[0][0];
199
+ long svl;
200
+
201
+ /* Validate that we have a wide enough vector for 4 elements. */
202
+ asm(".arch armv8-r+sme-i64\n\trdsvl %0, #1" : "=r"(svl));
203
+ if (svl < 32) {
204
+ return 0;
205
+ }
206
+
207
+ asm volatile(
208
+ "smstart\n\t"
209
+ "index z0.h, #0, #1\n\t"
210
+ "movprfx z1, z0\n\t"
211
+ "add z1.h, z1.h, #16\n\t"
212
+ "ptrue p0.b\n\t"
213
+ "smopa za0.d, p0/m, p0/m, z0.h, z1.h\n\t"
214
+ "ptrue p0.d, vl4\n\t"
215
+ "mov w12, #0\n\t"
216
+ "st1d { za0h.d[w12, #0] }, p0, [%0]\n\t"
217
+ "add %0, %0, #32\n\t"
218
+ "st1d { za0h.d[w12, #1] }, p0, [%0]\n\t"
219
+ "mov w12, #2\n\t"
220
+ "add %0, %0, #32\n\t"
221
+ "st1d { za0h.d[w12, #0] }, p0, [%0]\n\t"
222
+ "add %0, %0, #32\n\t"
223
+ "st1d { za0h.d[w12, #1] }, p0, [%0]\n\t"
224
+ "smstop"
225
+ : "+r"(tmp) : : "memory");
226
+
227
+ if (memcmp(cmp, dst, sizeof(dst)) == 0) {
228
+ return 0;
229
+ }
230
+
231
+ /* See above for correct results. */
232
+ for (int i = 0; i < 4; ++i) {
233
+ for (int j = 0; j < 4; ++j) {
234
+ printf("%6ld", dst[i][j]);
235
+ }
236
+ printf("\n");
237
+ }
238
+ return 1;
239
+}
240
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
241
index XXXXXXX..XXXXXXX 100644
242
--- a/tests/tcg/aarch64/Makefile.target
243
+++ b/tests/tcg/aarch64/Makefile.target
244
@@ -XXX,XX +XXX,XX @@ endif
245
246
# SME Tests
247
ifneq ($(CROSS_AS_HAS_ARMV9_SME),)
248
-AARCH64_TESTS += sme-outprod1
249
+AARCH64_TESTS += sme-outprod1 sme-smopa-1 sme-smopa-2
250
endif
251
252
# System Registers Tests
253
--
254
2.34.1
255
256
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
The sun4v RTC device model added under commit a0e893039cf2ce0 in 2016
2
was unfortunately added with a license of GPL-v3-or-later, which is
3
not compatible with other QEMU code which has a GPL-v2-only license.
2
4
3
We are missing the VIRT_COMPAT_3_0 definition and setting.
5
Relicense the code in the .c and the .h file to GPL-v2-or-later,
4
Let's add them.
6
to make it compatible with the rest of QEMU.
5
7
6
Signed-off-by: Eric Auger <eric.auger@redhat.com>
8
Cc: qemu-stable@nongnu.org
7
Reviewed-by: Andrew Jones <drjones@redhat.com>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20181024085602.16611-1-eric.auger@redhat.com
10
Signed-off-by: Paolo Bonzini (for Red Hat) <pbonzini@redhat.com>
11
Signed-off-by: Artyom Tarasenko <atar4qemu@gmail.com>
12
Signed-off-by: Markus Armbruster <armbru@redhat.com>
13
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
14
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
15
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
16
Acked-by: Alex Bennée <alex.bennee@linaro.org>
17
Message-id: 20240223161300.938542-1-peter.maydell@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
19
---
11
hw/arm/virt.c | 4 ++++
20
include/hw/rtc/sun4v-rtc.h | 2 +-
12
1 file changed, 4 insertions(+)
21
hw/rtc/sun4v-rtc.c | 2 +-
22
2 files changed, 2 insertions(+), 2 deletions(-)
13
23
14
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
24
diff --git a/include/hw/rtc/sun4v-rtc.h b/include/hw/rtc/sun4v-rtc.h
15
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/virt.c
26
--- a/include/hw/rtc/sun4v-rtc.h
17
+++ b/hw/arm/virt.c
27
+++ b/include/hw/rtc/sun4v-rtc.h
18
@@ -XXX,XX +XXX,XX @@ static void virt_machine_3_1_options(MachineClass *mc)
28
@@ -XXX,XX +XXX,XX @@
19
}
29
*
20
DEFINE_VIRT_MACHINE_AS_LATEST(3, 1)
30
* Copyright (c) 2016 Artyom Tarasenko
21
31
*
22
+#define VIRT_COMPAT_3_0 \
32
- * This code is licensed under the GNU GPL v3 or (at your option) any later
23
+ HW_COMPAT_3_0
33
+ * This code is licensed under the GNU GPL v2 or (at your option) any later
24
+
34
* version.
25
static void virt_3_0_instance_init(Object *obj)
35
*/
26
{
36
27
virt_3_1_instance_init(obj);
37
diff --git a/hw/rtc/sun4v-rtc.c b/hw/rtc/sun4v-rtc.c
28
@@ -XXX,XX +XXX,XX @@ static void virt_3_0_instance_init(Object *obj)
38
index XXXXXXX..XXXXXXX 100644
29
static void virt_machine_3_0_options(MachineClass *mc)
39
--- a/hw/rtc/sun4v-rtc.c
30
{
40
+++ b/hw/rtc/sun4v-rtc.c
31
virt_machine_3_1_options(mc);
41
@@ -XXX,XX +XXX,XX @@
32
+ SET_MACHINE_COMPAT(mc, VIRT_COMPAT_3_0);
42
*
33
}
43
* Copyright (c) 2016 Artyom Tarasenko
34
DEFINE_VIRT_MACHINE(3, 0)
44
*
45
- * This code is licensed under the GNU GPL v3 or (at your option) any later
46
+ * This code is licensed under the GNU GPL v2 or (at your option) any later
47
* version.
48
*/
35
49
36
--
50
--
37
2.19.1
51
2.34.1
38
52
39
53
diff view generated by jsdifflib
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
Add a virtual Xilinx Versal board.
3
Move the code to a separate file so that we do not have to compile
4
it anymore if CONFIG_ARM_V7M is not set.
4
5
5
This board is based on the Xilinx Versal SoC. The exact
6
Signed-off-by: Thomas Huth <thuth@redhat.com>
6
details of what peripherals are attached to this board
7
Message-id: 20240308141051.536599-2-thuth@redhat.com
7
will remain in control of QEMU. QEMU will generate an
8
FDT on the fly for Linux and other software to auto-discover
9
peripherals.
10
11
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
12
[PMM: removed stray blank line at EOF]
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
10
---
16
hw/arm/Makefile.objs | 2 +-
11
target/arm/tcg/cpu-v7m.c | 290 +++++++++++++++++++++++++++++++++++++
17
hw/arm/xlnx-versal-virt.c | 493 ++++++++++++++++++++++++++++++++++++++
12
target/arm/tcg/cpu32.c | 261 ---------------------------------
18
2 files changed, 494 insertions(+), 1 deletion(-)
13
target/arm/meson.build | 3 +
19
create mode 100644 hw/arm/xlnx-versal-virt.c
14
target/arm/tcg/meson.build | 3 +
15
4 files changed, 296 insertions(+), 261 deletions(-)
16
create mode 100644 target/arm/tcg/cpu-v7m.c
20
17
21
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
18
diff --git a/target/arm/tcg/cpu-v7m.c b/target/arm/tcg/cpu-v7m.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/arm/Makefile.objs
24
+++ b/hw/arm/Makefile.objs
25
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
26
obj-$(CONFIG_RASPI) += bcm2835_peripherals.o bcm2836.o raspi.o
27
obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
28
obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx-zynqmp.o xlnx-zcu102.o
29
-obj-$(CONFIG_XLNX_VERSAL) += xlnx-versal.o
30
+obj-$(CONFIG_XLNX_VERSAL) += xlnx-versal.o xlnx-versal-virt.o
31
obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
32
obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o
33
obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
34
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
35
new file mode 100644
19
new file mode 100644
36
index XXXXXXX..XXXXXXX
20
index XXXXXXX..XXXXXXX
37
--- /dev/null
21
--- /dev/null
38
+++ b/hw/arm/xlnx-versal-virt.c
22
+++ b/target/arm/tcg/cpu-v7m.c
39
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@
40
+/*
24
+/*
41
+ * Xilinx Versal Virtual board.
25
+ * QEMU ARMv7-M TCG-only CPUs.
42
+ *
26
+ *
43
+ * Copyright (c) 2018 Xilinx Inc.
27
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
44
+ * Written by Edgar E. Iglesias
45
+ *
28
+ *
46
+ * This program is free software; you can redistribute it and/or modify
29
+ * This code is licensed under the GNU GPL v2 or later.
47
+ * it under the terms of the GNU General Public License version 2 or
30
+ *
48
+ * (at your option) any later version.
31
+ * SPDX-License-Identifier: GPL-2.0-or-later
49
+ */
32
+ */
50
+
33
+
51
+#include "qemu/osdep.h"
34
+#include "qemu/osdep.h"
52
+#include "qemu/log.h"
53
+#include "qemu/error-report.h"
54
+#include "qapi/error.h"
55
+#include "sysemu/device_tree.h"
56
+#include "exec/address-spaces.h"
57
+#include "hw/boards.h"
58
+#include "hw/sysbus.h"
59
+#include "hw/arm/sysbus-fdt.h"
60
+#include "hw/arm/fdt.h"
61
+#include "cpu.h"
35
+#include "cpu.h"
62
+#include "hw/arm/xlnx-versal.h"
36
+#include "hw/core/tcg-cpu-ops.h"
63
+
37
+#include "internals.h"
64
+#define TYPE_XLNX_VERSAL_VIRT_MACHINE MACHINE_TYPE_NAME("xlnx-versal-virt")
38
+
65
+#define XLNX_VERSAL_VIRT_MACHINE(obj) \
39
+#if !defined(CONFIG_USER_ONLY)
66
+ OBJECT_CHECK(VersalVirt, (obj), TYPE_XLNX_VERSAL_VIRT_MACHINE)
40
+
67
+
41
+#include "hw/intc/armv7m_nvic.h"
68
+typedef struct VersalVirt {
42
+
69
+ MachineState parent_obj;
43
+static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
70
+
44
+{
71
+ Versal soc;
45
+ CPUClass *cc = CPU_GET_CLASS(cs);
72
+ MemoryRegion mr_ddr;
46
+ ARMCPU *cpu = ARM_CPU(cs);
73
+
47
+ CPUARMState *env = &cpu->env;
74
+ void *fdt;
48
+ bool ret = false;
75
+ int fdt_size;
49
+
76
+ struct {
50
+ /*
77
+ uint32_t gic;
51
+ * ARMv7-M interrupt masking works differently than -A or -R.
78
+ uint32_t ethernet_phy[2];
52
+ * There is no FIQ/IRQ distinction. Instead of I and F bits
79
+ uint32_t clk_125Mhz;
53
+ * masking FIQ and IRQ interrupts, an exception is taken only
80
+ uint32_t clk_25Mhz;
54
+ * if it is higher priority than the current execution priority
81
+ } phandle;
55
+ * (which depends on state like BASEPRI, FAULTMASK and the
82
+ struct arm_boot_info binfo;
56
+ * currently active exception).
83
+
57
+ */
84
+ struct {
58
+ if (interrupt_request & CPU_INTERRUPT_HARD
85
+ bool secure;
59
+ && (armv7m_nvic_can_take_pending_exception(env->nvic))) {
86
+ } cfg;
60
+ cs->exception_index = EXCP_IRQ;
87
+} VersalVirt;
61
+ cc->tcg_ops->do_interrupt(cs);
88
+
62
+ ret = true;
89
+static void fdt_create(VersalVirt *s)
90
+{
91
+ MachineClass *mc = MACHINE_GET_CLASS(s);
92
+ int i;
93
+
94
+ s->fdt = create_device_tree(&s->fdt_size);
95
+ if (!s->fdt) {
96
+ error_report("create_device_tree() failed");
97
+ exit(1);
98
+ }
63
+ }
99
+
64
+ return ret;
100
+ /* Allocate all phandles. */
65
+}
101
+ s->phandle.gic = qemu_fdt_alloc_phandle(s->fdt);
66
+
102
+ for (i = 0; i < ARRAY_SIZE(s->phandle.ethernet_phy); i++) {
67
+#endif /* !CONFIG_USER_ONLY */
103
+ s->phandle.ethernet_phy[i] = qemu_fdt_alloc_phandle(s->fdt);
68
+
69
+static void cortex_m0_initfn(Object *obj)
70
+{
71
+ ARMCPU *cpu = ARM_CPU(obj);
72
+ set_feature(&cpu->env, ARM_FEATURE_V6);
73
+ set_feature(&cpu->env, ARM_FEATURE_M);
74
+
75
+ cpu->midr = 0x410cc200;
76
+
77
+ /*
78
+ * These ID register values are not guest visible, because
79
+ * we do not implement the Main Extension. They must be set
80
+ * to values corresponding to the Cortex-M0's implemented
81
+ * features, because QEMU generally controls its emulation
82
+ * by looking at ID register fields. We use the same values as
83
+ * for the M3.
84
+ */
85
+ cpu->isar.id_pfr0 = 0x00000030;
86
+ cpu->isar.id_pfr1 = 0x00000200;
87
+ cpu->isar.id_dfr0 = 0x00100000;
88
+ cpu->id_afr0 = 0x00000000;
89
+ cpu->isar.id_mmfr0 = 0x00000030;
90
+ cpu->isar.id_mmfr1 = 0x00000000;
91
+ cpu->isar.id_mmfr2 = 0x00000000;
92
+ cpu->isar.id_mmfr3 = 0x00000000;
93
+ cpu->isar.id_isar0 = 0x01141110;
94
+ cpu->isar.id_isar1 = 0x02111000;
95
+ cpu->isar.id_isar2 = 0x21112231;
96
+ cpu->isar.id_isar3 = 0x01111110;
97
+ cpu->isar.id_isar4 = 0x01310102;
98
+ cpu->isar.id_isar5 = 0x00000000;
99
+ cpu->isar.id_isar6 = 0x00000000;
100
+}
101
+
102
+static void cortex_m3_initfn(Object *obj)
103
+{
104
+ ARMCPU *cpu = ARM_CPU(obj);
105
+ set_feature(&cpu->env, ARM_FEATURE_V7);
106
+ set_feature(&cpu->env, ARM_FEATURE_M);
107
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
108
+ cpu->midr = 0x410fc231;
109
+ cpu->pmsav7_dregion = 8;
110
+ cpu->isar.id_pfr0 = 0x00000030;
111
+ cpu->isar.id_pfr1 = 0x00000200;
112
+ cpu->isar.id_dfr0 = 0x00100000;
113
+ cpu->id_afr0 = 0x00000000;
114
+ cpu->isar.id_mmfr0 = 0x00000030;
115
+ cpu->isar.id_mmfr1 = 0x00000000;
116
+ cpu->isar.id_mmfr2 = 0x00000000;
117
+ cpu->isar.id_mmfr3 = 0x00000000;
118
+ cpu->isar.id_isar0 = 0x01141110;
119
+ cpu->isar.id_isar1 = 0x02111000;
120
+ cpu->isar.id_isar2 = 0x21112231;
121
+ cpu->isar.id_isar3 = 0x01111110;
122
+ cpu->isar.id_isar4 = 0x01310102;
123
+ cpu->isar.id_isar5 = 0x00000000;
124
+ cpu->isar.id_isar6 = 0x00000000;
125
+}
126
+
127
+static void cortex_m4_initfn(Object *obj)
128
+{
129
+ ARMCPU *cpu = ARM_CPU(obj);
130
+
131
+ set_feature(&cpu->env, ARM_FEATURE_V7);
132
+ set_feature(&cpu->env, ARM_FEATURE_M);
133
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
134
+ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
135
+ cpu->midr = 0x410fc240; /* r0p0 */
136
+ cpu->pmsav7_dregion = 8;
137
+ cpu->isar.mvfr0 = 0x10110021;
138
+ cpu->isar.mvfr1 = 0x11000011;
139
+ cpu->isar.mvfr2 = 0x00000000;
140
+ cpu->isar.id_pfr0 = 0x00000030;
141
+ cpu->isar.id_pfr1 = 0x00000200;
142
+ cpu->isar.id_dfr0 = 0x00100000;
143
+ cpu->id_afr0 = 0x00000000;
144
+ cpu->isar.id_mmfr0 = 0x00000030;
145
+ cpu->isar.id_mmfr1 = 0x00000000;
146
+ cpu->isar.id_mmfr2 = 0x00000000;
147
+ cpu->isar.id_mmfr3 = 0x00000000;
148
+ cpu->isar.id_isar0 = 0x01141110;
149
+ cpu->isar.id_isar1 = 0x02111000;
150
+ cpu->isar.id_isar2 = 0x21112231;
151
+ cpu->isar.id_isar3 = 0x01111110;
152
+ cpu->isar.id_isar4 = 0x01310102;
153
+ cpu->isar.id_isar5 = 0x00000000;
154
+ cpu->isar.id_isar6 = 0x00000000;
155
+}
156
+
157
+static void cortex_m7_initfn(Object *obj)
158
+{
159
+ ARMCPU *cpu = ARM_CPU(obj);
160
+
161
+ set_feature(&cpu->env, ARM_FEATURE_V7);
162
+ set_feature(&cpu->env, ARM_FEATURE_M);
163
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
164
+ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
165
+ cpu->midr = 0x411fc272; /* r1p2 */
166
+ cpu->pmsav7_dregion = 8;
167
+ cpu->isar.mvfr0 = 0x10110221;
168
+ cpu->isar.mvfr1 = 0x12000011;
169
+ cpu->isar.mvfr2 = 0x00000040;
170
+ cpu->isar.id_pfr0 = 0x00000030;
171
+ cpu->isar.id_pfr1 = 0x00000200;
172
+ cpu->isar.id_dfr0 = 0x00100000;
173
+ cpu->id_afr0 = 0x00000000;
174
+ cpu->isar.id_mmfr0 = 0x00100030;
175
+ cpu->isar.id_mmfr1 = 0x00000000;
176
+ cpu->isar.id_mmfr2 = 0x01000000;
177
+ cpu->isar.id_mmfr3 = 0x00000000;
178
+ cpu->isar.id_isar0 = 0x01101110;
179
+ cpu->isar.id_isar1 = 0x02112000;
180
+ cpu->isar.id_isar2 = 0x20232231;
181
+ cpu->isar.id_isar3 = 0x01111131;
182
+ cpu->isar.id_isar4 = 0x01310132;
183
+ cpu->isar.id_isar5 = 0x00000000;
184
+ cpu->isar.id_isar6 = 0x00000000;
185
+}
186
+
187
+static void cortex_m33_initfn(Object *obj)
188
+{
189
+ ARMCPU *cpu = ARM_CPU(obj);
190
+
191
+ set_feature(&cpu->env, ARM_FEATURE_V8);
192
+ set_feature(&cpu->env, ARM_FEATURE_M);
193
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
194
+ set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
195
+ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
196
+ cpu->midr = 0x410fd213; /* r0p3 */
197
+ cpu->pmsav7_dregion = 16;
198
+ cpu->sau_sregion = 8;
199
+ cpu->isar.mvfr0 = 0x10110021;
200
+ cpu->isar.mvfr1 = 0x11000011;
201
+ cpu->isar.mvfr2 = 0x00000040;
202
+ cpu->isar.id_pfr0 = 0x00000030;
203
+ cpu->isar.id_pfr1 = 0x00000210;
204
+ cpu->isar.id_dfr0 = 0x00200000;
205
+ cpu->id_afr0 = 0x00000000;
206
+ cpu->isar.id_mmfr0 = 0x00101F40;
207
+ cpu->isar.id_mmfr1 = 0x00000000;
208
+ cpu->isar.id_mmfr2 = 0x01000000;
209
+ cpu->isar.id_mmfr3 = 0x00000000;
210
+ cpu->isar.id_isar0 = 0x01101110;
211
+ cpu->isar.id_isar1 = 0x02212000;
212
+ cpu->isar.id_isar2 = 0x20232232;
213
+ cpu->isar.id_isar3 = 0x01111131;
214
+ cpu->isar.id_isar4 = 0x01310132;
215
+ cpu->isar.id_isar5 = 0x00000000;
216
+ cpu->isar.id_isar6 = 0x00000000;
217
+ cpu->clidr = 0x00000000;
218
+ cpu->ctr = 0x8000c000;
219
+}
220
+
221
+static void cortex_m55_initfn(Object *obj)
222
+{
223
+ ARMCPU *cpu = ARM_CPU(obj);
224
+
225
+ set_feature(&cpu->env, ARM_FEATURE_V8);
226
+ set_feature(&cpu->env, ARM_FEATURE_V8_1M);
227
+ set_feature(&cpu->env, ARM_FEATURE_M);
228
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
229
+ set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
230
+ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
231
+ cpu->midr = 0x410fd221; /* r0p1 */
232
+ cpu->revidr = 0;
233
+ cpu->pmsav7_dregion = 16;
234
+ cpu->sau_sregion = 8;
235
+ /* These are the MVFR* values for the FPU + full MVE configuration */
236
+ cpu->isar.mvfr0 = 0x10110221;
237
+ cpu->isar.mvfr1 = 0x12100211;
238
+ cpu->isar.mvfr2 = 0x00000040;
239
+ cpu->isar.id_pfr0 = 0x20000030;
240
+ cpu->isar.id_pfr1 = 0x00000230;
241
+ cpu->isar.id_dfr0 = 0x10200000;
242
+ cpu->id_afr0 = 0x00000000;
243
+ cpu->isar.id_mmfr0 = 0x00111040;
244
+ cpu->isar.id_mmfr1 = 0x00000000;
245
+ cpu->isar.id_mmfr2 = 0x01000000;
246
+ cpu->isar.id_mmfr3 = 0x00000011;
247
+ cpu->isar.id_isar0 = 0x01103110;
248
+ cpu->isar.id_isar1 = 0x02212000;
249
+ cpu->isar.id_isar2 = 0x20232232;
250
+ cpu->isar.id_isar3 = 0x01111131;
251
+ cpu->isar.id_isar4 = 0x01310132;
252
+ cpu->isar.id_isar5 = 0x00000000;
253
+ cpu->isar.id_isar6 = 0x00000000;
254
+ cpu->clidr = 0x00000000; /* caches not implemented */
255
+ cpu->ctr = 0x8303c003;
256
+}
257
+
258
+static const TCGCPUOps arm_v7m_tcg_ops = {
259
+ .initialize = arm_translate_init,
260
+ .synchronize_from_tb = arm_cpu_synchronize_from_tb,
261
+ .debug_excp_handler = arm_debug_excp_handler,
262
+ .restore_state_to_opc = arm_restore_state_to_opc,
263
+
264
+#ifdef CONFIG_USER_ONLY
265
+ .record_sigsegv = arm_cpu_record_sigsegv,
266
+ .record_sigbus = arm_cpu_record_sigbus,
267
+#else
268
+ .tlb_fill = arm_cpu_tlb_fill,
269
+ .cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt,
270
+ .do_interrupt = arm_v7m_cpu_do_interrupt,
271
+ .do_transaction_failed = arm_cpu_do_transaction_failed,
272
+ .do_unaligned_access = arm_cpu_do_unaligned_access,
273
+ .adjust_watchpoint_address = arm_adjust_watchpoint_address,
274
+ .debug_check_watchpoint = arm_debug_check_watchpoint,
275
+ .debug_check_breakpoint = arm_debug_check_breakpoint,
276
+#endif /* !CONFIG_USER_ONLY */
277
+};
278
+
279
+static void arm_v7m_class_init(ObjectClass *oc, void *data)
280
+{
281
+ ARMCPUClass *acc = ARM_CPU_CLASS(oc);
282
+ CPUClass *cc = CPU_CLASS(oc);
283
+
284
+ acc->info = data;
285
+ cc->tcg_ops = &arm_v7m_tcg_ops;
286
+ cc->gdb_core_xml_file = "arm-m-profile.xml";
287
+}
288
+
289
+static const ARMCPUInfo arm_v7m_cpus[] = {
290
+ { .name = "cortex-m0", .initfn = cortex_m0_initfn,
291
+ .class_init = arm_v7m_class_init },
292
+ { .name = "cortex-m3", .initfn = cortex_m3_initfn,
293
+ .class_init = arm_v7m_class_init },
294
+ { .name = "cortex-m4", .initfn = cortex_m4_initfn,
295
+ .class_init = arm_v7m_class_init },
296
+ { .name = "cortex-m7", .initfn = cortex_m7_initfn,
297
+ .class_init = arm_v7m_class_init },
298
+ { .name = "cortex-m33", .initfn = cortex_m33_initfn,
299
+ .class_init = arm_v7m_class_init },
300
+ { .name = "cortex-m55", .initfn = cortex_m55_initfn,
301
+ .class_init = arm_v7m_class_init },
302
+};
303
+
304
+static void arm_v7m_cpu_register_types(void)
305
+{
306
+ size_t i;
307
+
308
+ for (i = 0; i < ARRAY_SIZE(arm_v7m_cpus); ++i) {
309
+ arm_cpu_register(&arm_v7m_cpus[i]);
104
+ }
310
+ }
105
+ s->phandle.clk_25Mhz = qemu_fdt_alloc_phandle(s->fdt);
311
+}
106
+ s->phandle.clk_125Mhz = qemu_fdt_alloc_phandle(s->fdt);
312
+
107
+
313
+type_init(arm_v7m_cpu_register_types)
108
+ /* Create /chosen node for load_dtb. */
314
diff --git a/target/arm/tcg/cpu32.c b/target/arm/tcg/cpu32.c
109
+ qemu_fdt_add_subnode(s->fdt, "/chosen");
315
index XXXXXXX..XXXXXXX 100644
110
+
316
--- a/target/arm/tcg/cpu32.c
111
+ /* Header */
317
+++ b/target/arm/tcg/cpu32.c
112
+ qemu_fdt_setprop_cell(s->fdt, "/", "interrupt-parent", s->phandle.gic);
318
@@ -XXX,XX +XXX,XX @@
113
+ qemu_fdt_setprop_cell(s->fdt, "/", "#size-cells", 0x2);
319
#include "hw/boards.h"
114
+ qemu_fdt_setprop_cell(s->fdt, "/", "#address-cells", 0x2);
320
#endif
115
+ qemu_fdt_setprop_string(s->fdt, "/", "model", mc->desc);
321
#include "cpregs.h"
116
+ qemu_fdt_setprop_string(s->fdt, "/", "compatible", "xlnx-versal-virt");
322
-#if !defined(CONFIG_USER_ONLY) && defined(CONFIG_TCG)
117
+}
323
-#include "hw/intc/armv7m_nvic.h"
118
+
324
-#endif
119
+static void fdt_add_clk_node(VersalVirt *s, const char *name,
325
120
+ unsigned int freq_hz, uint32_t phandle)
326
121
+{
327
/* Share AArch32 -cpu max features with AArch64. */
122
+ qemu_fdt_add_subnode(s->fdt, name);
328
@@ -XXX,XX +XXX,XX @@ void aa32_max_features(ARMCPU *cpu)
123
+ qemu_fdt_setprop_cell(s->fdt, name, "phandle", phandle);
329
/* CPU models. These are not needed for the AArch64 linux-user build. */
124
+ qemu_fdt_setprop_cell(s->fdt, name, "clock-frequency", freq_hz);
330
#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
125
+ qemu_fdt_setprop_cell(s->fdt, name, "#clock-cells", 0x0);
331
126
+ qemu_fdt_setprop_string(s->fdt, name, "compatible", "fixed-clock");
332
-#if !defined(CONFIG_USER_ONLY)
127
+ qemu_fdt_setprop(s->fdt, name, "u-boot,dm-pre-reloc", NULL, 0);
333
-static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
128
+}
334
-{
129
+
335
- CPUClass *cc = CPU_GET_CLASS(cs);
130
+static void fdt_add_cpu_nodes(VersalVirt *s, uint32_t psci_conduit)
336
- ARMCPU *cpu = ARM_CPU(cs);
131
+{
337
- CPUARMState *env = &cpu->env;
132
+ int i;
338
- bool ret = false;
133
+
339
-
134
+ qemu_fdt_add_subnode(s->fdt, "/cpus");
340
- /*
135
+ qemu_fdt_setprop_cell(s->fdt, "/cpus", "#size-cells", 0x0);
341
- * ARMv7-M interrupt masking works differently than -A or -R.
136
+ qemu_fdt_setprop_cell(s->fdt, "/cpus", "#address-cells", 1);
342
- * There is no FIQ/IRQ distinction. Instead of I and F bits
137
+
343
- * masking FIQ and IRQ interrupts, an exception is taken only
138
+ for (i = XLNX_VERSAL_NR_ACPUS - 1; i >= 0; i--) {
344
- * if it is higher priority than the current execution priority
139
+ char *name = g_strdup_printf("/cpus/cpu@%d", i);
345
- * (which depends on state like BASEPRI, FAULTMASK and the
140
+ ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(i));
346
- * currently active exception).
141
+
347
- */
142
+ qemu_fdt_add_subnode(s->fdt, name);
348
- if (interrupt_request & CPU_INTERRUPT_HARD
143
+ qemu_fdt_setprop_cell(s->fdt, name, "reg", armcpu->mp_affinity);
349
- && (armv7m_nvic_can_take_pending_exception(env->nvic))) {
144
+ if (psci_conduit != QEMU_PSCI_CONDUIT_DISABLED) {
350
- cs->exception_index = EXCP_IRQ;
145
+ qemu_fdt_setprop_string(s->fdt, name, "enable-method", "psci");
351
- cc->tcg_ops->do_interrupt(cs);
146
+ }
352
- ret = true;
147
+ qemu_fdt_setprop_string(s->fdt, name, "device_type", "cpu");
353
- }
148
+ qemu_fdt_setprop_string(s->fdt, name, "compatible",
354
- return ret;
149
+ armcpu->dtb_compatible);
355
-}
150
+ g_free(name);
356
-#endif /* !CONFIG_USER_ONLY */
151
+ }
357
-
152
+}
358
static void arm926_initfn(Object *obj)
153
+
359
{
154
+static void fdt_add_gic_nodes(VersalVirt *s)
360
ARMCPU *cpu = ARM_CPU(obj);
155
+{
361
@@ -XXX,XX +XXX,XX @@ static void cortex_a15_initfn(Object *obj)
156
+ char *nodename;
362
define_arm_cp_regs(cpu, cortexa15_cp_reginfo);
157
+
363
}
158
+ nodename = g_strdup_printf("/gic@%x", MM_GIC_APU_DIST_MAIN);
364
159
+ qemu_fdt_add_subnode(s->fdt, nodename);
365
-static void cortex_m0_initfn(Object *obj)
160
+ qemu_fdt_setprop_cell(s->fdt, nodename, "phandle", s->phandle.gic);
366
-{
161
+ qemu_fdt_setprop_cells(s->fdt, nodename, "interrupts",
367
- ARMCPU *cpu = ARM_CPU(obj);
162
+ GIC_FDT_IRQ_TYPE_PPI, VERSAL_GIC_MAINT_IRQ,
368
- set_feature(&cpu->env, ARM_FEATURE_V6);
163
+ GIC_FDT_IRQ_FLAGS_LEVEL_HI);
369
- set_feature(&cpu->env, ARM_FEATURE_M);
164
+ qemu_fdt_setprop(s->fdt, nodename, "interrupt-controller", NULL, 0);
370
-
165
+ qemu_fdt_setprop_sized_cells(s->fdt, nodename, "reg",
371
- cpu->midr = 0x410cc200;
166
+ 2, MM_GIC_APU_DIST_MAIN,
372
-
167
+ 2, MM_GIC_APU_DIST_MAIN_SIZE,
373
- /*
168
+ 2, MM_GIC_APU_REDIST_0,
374
- * These ID register values are not guest visible, because
169
+ 2, MM_GIC_APU_REDIST_0_SIZE);
375
- * we do not implement the Main Extension. They must be set
170
+ qemu_fdt_setprop_cell(s->fdt, nodename, "#interrupt-cells", 3);
376
- * to values corresponding to the Cortex-M0's implemented
171
+ qemu_fdt_setprop_string(s->fdt, nodename, "compatible", "arm,gic-v3");
377
- * features, because QEMU generally controls its emulation
172
+}
378
- * by looking at ID register fields. We use the same values as
173
+
379
- * for the M3.
174
+static void fdt_add_timer_nodes(VersalVirt *s)
380
- */
175
+{
381
- cpu->isar.id_pfr0 = 0x00000030;
176
+ const char compat[] = "arm,armv8-timer";
382
- cpu->isar.id_pfr1 = 0x00000200;
177
+ uint32_t irqflags = GIC_FDT_IRQ_FLAGS_LEVEL_HI;
383
- cpu->isar.id_dfr0 = 0x00100000;
178
+
384
- cpu->id_afr0 = 0x00000000;
179
+ qemu_fdt_add_subnode(s->fdt, "/timer");
385
- cpu->isar.id_mmfr0 = 0x00000030;
180
+ qemu_fdt_setprop_cells(s->fdt, "/timer", "interrupts",
386
- cpu->isar.id_mmfr1 = 0x00000000;
181
+ GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_S_EL1_IRQ, irqflags,
387
- cpu->isar.id_mmfr2 = 0x00000000;
182
+ GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_NS_EL1_IRQ, irqflags,
388
- cpu->isar.id_mmfr3 = 0x00000000;
183
+ GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_VIRT_IRQ, irqflags,
389
- cpu->isar.id_isar0 = 0x01141110;
184
+ GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_NS_EL2_IRQ, irqflags);
390
- cpu->isar.id_isar1 = 0x02111000;
185
+ qemu_fdt_setprop(s->fdt, "/timer", "compatible",
391
- cpu->isar.id_isar2 = 0x21112231;
186
+ compat, sizeof(compat));
392
- cpu->isar.id_isar3 = 0x01111110;
187
+}
393
- cpu->isar.id_isar4 = 0x01310102;
188
+
394
- cpu->isar.id_isar5 = 0x00000000;
189
+static void fdt_add_uart_nodes(VersalVirt *s)
395
- cpu->isar.id_isar6 = 0x00000000;
190
+{
396
-}
191
+ uint64_t addrs[] = { MM_UART1, MM_UART0 };
397
-
192
+ unsigned int irqs[] = { VERSAL_UART1_IRQ_0, VERSAL_UART0_IRQ_0 };
398
-static void cortex_m3_initfn(Object *obj)
193
+ const char compat[] = "arm,pl011\0arm,sbsa-uart";
399
-{
194
+ const char clocknames[] = "uartclk\0apb_pclk";
400
- ARMCPU *cpu = ARM_CPU(obj);
195
+ int i;
401
- set_feature(&cpu->env, ARM_FEATURE_V7);
196
+
402
- set_feature(&cpu->env, ARM_FEATURE_M);
197
+ for (i = 0; i < ARRAY_SIZE(addrs); i++) {
403
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
198
+ char *name = g_strdup_printf("/uart@%" PRIx64, addrs[i]);
404
- cpu->midr = 0x410fc231;
199
+ qemu_fdt_add_subnode(s->fdt, name);
405
- cpu->pmsav7_dregion = 8;
200
+ qemu_fdt_setprop_cell(s->fdt, name, "current-speed", 115200);
406
- cpu->isar.id_pfr0 = 0x00000030;
201
+ qemu_fdt_setprop_cells(s->fdt, name, "clocks",
407
- cpu->isar.id_pfr1 = 0x00000200;
202
+ s->phandle.clk_125Mhz, s->phandle.clk_125Mhz);
408
- cpu->isar.id_dfr0 = 0x00100000;
203
+ qemu_fdt_setprop(s->fdt, name, "clock-names",
409
- cpu->id_afr0 = 0x00000000;
204
+ clocknames, sizeof(clocknames));
410
- cpu->isar.id_mmfr0 = 0x00000030;
205
+
411
- cpu->isar.id_mmfr1 = 0x00000000;
206
+ qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
412
- cpu->isar.id_mmfr2 = 0x00000000;
207
+ GIC_FDT_IRQ_TYPE_SPI, irqs[i],
413
- cpu->isar.id_mmfr3 = 0x00000000;
208
+ GIC_FDT_IRQ_FLAGS_LEVEL_HI);
414
- cpu->isar.id_isar0 = 0x01141110;
209
+ qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
415
- cpu->isar.id_isar1 = 0x02111000;
210
+ 2, addrs[i], 2, 0x1000);
416
- cpu->isar.id_isar2 = 0x21112231;
211
+ qemu_fdt_setprop(s->fdt, name, "compatible",
417
- cpu->isar.id_isar3 = 0x01111110;
212
+ compat, sizeof(compat));
418
- cpu->isar.id_isar4 = 0x01310102;
213
+ qemu_fdt_setprop(s->fdt, name, "u-boot,dm-pre-reloc", NULL, 0);
419
- cpu->isar.id_isar5 = 0x00000000;
214
+
420
- cpu->isar.id_isar6 = 0x00000000;
215
+ if (addrs[i] == MM_UART0) {
421
-}
216
+ /* Select UART0. */
422
-
217
+ qemu_fdt_setprop_string(s->fdt, "/chosen", "stdout-path", name);
423
-static void cortex_m4_initfn(Object *obj)
218
+ }
424
-{
219
+ g_free(name);
425
- ARMCPU *cpu = ARM_CPU(obj);
220
+ }
426
-
221
+}
427
- set_feature(&cpu->env, ARM_FEATURE_V7);
222
+
428
- set_feature(&cpu->env, ARM_FEATURE_M);
223
+static void fdt_add_fixed_link_nodes(VersalVirt *s, char *gemname,
429
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
224
+ uint32_t phandle)
430
- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
225
+{
431
- cpu->midr = 0x410fc240; /* r0p0 */
226
+ char *name = g_strdup_printf("%s/fixed-link", gemname);
432
- cpu->pmsav7_dregion = 8;
227
+
433
- cpu->isar.mvfr0 = 0x10110021;
228
+ qemu_fdt_add_subnode(s->fdt, name);
434
- cpu->isar.mvfr1 = 0x11000011;
229
+ qemu_fdt_setprop_cell(s->fdt, name, "phandle", phandle);
435
- cpu->isar.mvfr2 = 0x00000000;
230
+ qemu_fdt_setprop_cells(s->fdt, name, "full-duplex");
436
- cpu->isar.id_pfr0 = 0x00000030;
231
+ qemu_fdt_setprop_cell(s->fdt, name, "speed", 1000);
437
- cpu->isar.id_pfr1 = 0x00000200;
232
+ g_free(name);
438
- cpu->isar.id_dfr0 = 0x00100000;
233
+}
439
- cpu->id_afr0 = 0x00000000;
234
+
440
- cpu->isar.id_mmfr0 = 0x00000030;
235
+static void fdt_add_gem_nodes(VersalVirt *s)
441
- cpu->isar.id_mmfr1 = 0x00000000;
236
+{
442
- cpu->isar.id_mmfr2 = 0x00000000;
237
+ uint64_t addrs[] = { MM_GEM1, MM_GEM0 };
443
- cpu->isar.id_mmfr3 = 0x00000000;
238
+ unsigned int irqs[] = { VERSAL_GEM1_IRQ_0, VERSAL_GEM0_IRQ_0 };
444
- cpu->isar.id_isar0 = 0x01141110;
239
+ const char clocknames[] = "pclk\0hclk\0tx_clk\0rx_clk";
445
- cpu->isar.id_isar1 = 0x02111000;
240
+ const char compat_gem[] = "cdns,zynqmp-gem\0cdns,gem";
446
- cpu->isar.id_isar2 = 0x21112231;
241
+ int i;
447
- cpu->isar.id_isar3 = 0x01111110;
242
+
448
- cpu->isar.id_isar4 = 0x01310102;
243
+ for (i = 0; i < ARRAY_SIZE(addrs); i++) {
449
- cpu->isar.id_isar5 = 0x00000000;
244
+ char *name = g_strdup_printf("/ethernet@%" PRIx64, addrs[i]);
450
- cpu->isar.id_isar6 = 0x00000000;
245
+ qemu_fdt_add_subnode(s->fdt, name);
451
-}
246
+
452
-
247
+ fdt_add_fixed_link_nodes(s, name, s->phandle.ethernet_phy[i]);
453
-static void cortex_m7_initfn(Object *obj)
248
+ qemu_fdt_setprop_string(s->fdt, name, "phy-mode", "rgmii-id");
454
-{
249
+ qemu_fdt_setprop_cell(s->fdt, name, "phy-handle",
455
- ARMCPU *cpu = ARM_CPU(obj);
250
+ s->phandle.ethernet_phy[i]);
456
-
251
+ qemu_fdt_setprop_cells(s->fdt, name, "clocks",
457
- set_feature(&cpu->env, ARM_FEATURE_V7);
252
+ s->phandle.clk_25Mhz, s->phandle.clk_25Mhz,
458
- set_feature(&cpu->env, ARM_FEATURE_M);
253
+ s->phandle.clk_25Mhz, s->phandle.clk_25Mhz);
459
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
254
+ qemu_fdt_setprop(s->fdt, name, "clock-names",
460
- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
255
+ clocknames, sizeof(clocknames));
461
- cpu->midr = 0x411fc272; /* r1p2 */
256
+ qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
462
- cpu->pmsav7_dregion = 8;
257
+ GIC_FDT_IRQ_TYPE_SPI, irqs[i],
463
- cpu->isar.mvfr0 = 0x10110221;
258
+ GIC_FDT_IRQ_FLAGS_LEVEL_HI,
464
- cpu->isar.mvfr1 = 0x12000011;
259
+ GIC_FDT_IRQ_TYPE_SPI, irqs[i],
465
- cpu->isar.mvfr2 = 0x00000040;
260
+ GIC_FDT_IRQ_FLAGS_LEVEL_HI);
466
- cpu->isar.id_pfr0 = 0x00000030;
261
+ qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
467
- cpu->isar.id_pfr1 = 0x00000200;
262
+ 2, addrs[i], 2, 0x1000);
468
- cpu->isar.id_dfr0 = 0x00100000;
263
+ qemu_fdt_setprop(s->fdt, name, "compatible",
469
- cpu->id_afr0 = 0x00000000;
264
+ compat_gem, sizeof(compat_gem));
470
- cpu->isar.id_mmfr0 = 0x00100030;
265
+ qemu_fdt_setprop_cell(s->fdt, name, "#address-cells", 1);
471
- cpu->isar.id_mmfr1 = 0x00000000;
266
+ qemu_fdt_setprop_cell(s->fdt, name, "#size-cells", 0);
472
- cpu->isar.id_mmfr2 = 0x01000000;
267
+ g_free(name);
473
- cpu->isar.id_mmfr3 = 0x00000000;
268
+ }
474
- cpu->isar.id_isar0 = 0x01101110;
269
+}
475
- cpu->isar.id_isar1 = 0x02112000;
270
+
476
- cpu->isar.id_isar2 = 0x20232231;
271
+static void fdt_nop_memory_nodes(void *fdt, Error **errp)
477
- cpu->isar.id_isar3 = 0x01111131;
272
+{
478
- cpu->isar.id_isar4 = 0x01310132;
273
+ Error *err = NULL;
479
- cpu->isar.id_isar5 = 0x00000000;
274
+ char **node_path;
480
- cpu->isar.id_isar6 = 0x00000000;
275
+ int n = 0;
481
-}
276
+
482
-
277
+ node_path = qemu_fdt_node_unit_path(fdt, "memory", &err);
483
-static void cortex_m33_initfn(Object *obj)
278
+ if (err) {
484
-{
279
+ error_propagate(errp, err);
485
- ARMCPU *cpu = ARM_CPU(obj);
280
+ return;
486
-
281
+ }
487
- set_feature(&cpu->env, ARM_FEATURE_V8);
282
+ while (node_path[n]) {
488
- set_feature(&cpu->env, ARM_FEATURE_M);
283
+ if (g_str_has_prefix(node_path[n], "/memory")) {
489
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
284
+ qemu_fdt_nop_node(fdt, node_path[n]);
490
- set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
285
+ }
491
- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
286
+ n++;
492
- cpu->midr = 0x410fd213; /* r0p3 */
287
+ }
493
- cpu->pmsav7_dregion = 16;
288
+ g_strfreev(node_path);
494
- cpu->sau_sregion = 8;
289
+}
495
- cpu->isar.mvfr0 = 0x10110021;
290
+
496
- cpu->isar.mvfr1 = 0x11000011;
291
+static void fdt_add_memory_nodes(VersalVirt *s, void *fdt, uint64_t ram_size)
497
- cpu->isar.mvfr2 = 0x00000040;
292
+{
498
- cpu->isar.id_pfr0 = 0x00000030;
293
+ /* Describes the various split DDR access regions. */
499
- cpu->isar.id_pfr1 = 0x00000210;
294
+ static const struct {
500
- cpu->isar.id_dfr0 = 0x00200000;
295
+ uint64_t base;
501
- cpu->id_afr0 = 0x00000000;
296
+ uint64_t size;
502
- cpu->isar.id_mmfr0 = 0x00101F40;
297
+ } addr_ranges[] = {
503
- cpu->isar.id_mmfr1 = 0x00000000;
298
+ { MM_TOP_DDR, MM_TOP_DDR_SIZE },
504
- cpu->isar.id_mmfr2 = 0x01000000;
299
+ { MM_TOP_DDR_2, MM_TOP_DDR_2_SIZE },
505
- cpu->isar.id_mmfr3 = 0x00000000;
300
+ { MM_TOP_DDR_3, MM_TOP_DDR_3_SIZE },
506
- cpu->isar.id_isar0 = 0x01101110;
301
+ { MM_TOP_DDR_4, MM_TOP_DDR_4_SIZE }
507
- cpu->isar.id_isar1 = 0x02212000;
302
+ };
508
- cpu->isar.id_isar2 = 0x20232232;
303
+ uint64_t mem_reg_prop[8] = {0};
509
- cpu->isar.id_isar3 = 0x01111131;
304
+ uint64_t size = ram_size;
510
- cpu->isar.id_isar4 = 0x01310132;
305
+ Error *err = NULL;
511
- cpu->isar.id_isar5 = 0x00000000;
306
+ char *name;
512
- cpu->isar.id_isar6 = 0x00000000;
307
+ int i;
513
- cpu->clidr = 0x00000000;
308
+
514
- cpu->ctr = 0x8000c000;
309
+ fdt_nop_memory_nodes(fdt, &err);
515
-}
310
+ if (err) {
516
-
311
+ error_report_err(err);
517
-static void cortex_m55_initfn(Object *obj)
312
+ return;
518
-{
313
+ }
519
- ARMCPU *cpu = ARM_CPU(obj);
314
+
520
-
315
+ name = g_strdup_printf("/memory@%x", MM_TOP_DDR);
521
- set_feature(&cpu->env, ARM_FEATURE_V8);
316
+ for (i = 0; i < ARRAY_SIZE(addr_ranges) && size; i++) {
522
- set_feature(&cpu->env, ARM_FEATURE_V8_1M);
317
+ uint64_t mapsize;
523
- set_feature(&cpu->env, ARM_FEATURE_M);
318
+
524
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
319
+ mapsize = size < addr_ranges[i].size ? size : addr_ranges[i].size;
525
- set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
320
+
526
- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
321
+ mem_reg_prop[i * 2] = addr_ranges[i].base;
527
- cpu->midr = 0x410fd221; /* r0p1 */
322
+ mem_reg_prop[i * 2 + 1] = mapsize;
528
- cpu->revidr = 0;
323
+ size -= mapsize;
529
- cpu->pmsav7_dregion = 16;
324
+ }
530
- cpu->sau_sregion = 8;
325
+ qemu_fdt_add_subnode(fdt, name);
531
- /* These are the MVFR* values for the FPU + full MVE configuration */
326
+ qemu_fdt_setprop_string(fdt, name, "device_type", "memory");
532
- cpu->isar.mvfr0 = 0x10110221;
327
+
533
- cpu->isar.mvfr1 = 0x12100211;
328
+ switch (i) {
534
- cpu->isar.mvfr2 = 0x00000040;
329
+ case 1:
535
- cpu->isar.id_pfr0 = 0x20000030;
330
+ qemu_fdt_setprop_sized_cells(fdt, name, "reg",
536
- cpu->isar.id_pfr1 = 0x00000230;
331
+ 2, mem_reg_prop[0],
537
- cpu->isar.id_dfr0 = 0x10200000;
332
+ 2, mem_reg_prop[1]);
538
- cpu->id_afr0 = 0x00000000;
333
+ break;
539
- cpu->isar.id_mmfr0 = 0x00111040;
334
+ case 2:
540
- cpu->isar.id_mmfr1 = 0x00000000;
335
+ qemu_fdt_setprop_sized_cells(fdt, name, "reg",
541
- cpu->isar.id_mmfr2 = 0x01000000;
336
+ 2, mem_reg_prop[0],
542
- cpu->isar.id_mmfr3 = 0x00000011;
337
+ 2, mem_reg_prop[1],
543
- cpu->isar.id_isar0 = 0x01103110;
338
+ 2, mem_reg_prop[2],
544
- cpu->isar.id_isar1 = 0x02212000;
339
+ 2, mem_reg_prop[3]);
545
- cpu->isar.id_isar2 = 0x20232232;
340
+ break;
546
- cpu->isar.id_isar3 = 0x01111131;
341
+ case 3:
547
- cpu->isar.id_isar4 = 0x01310132;
342
+ qemu_fdt_setprop_sized_cells(fdt, name, "reg",
548
- cpu->isar.id_isar5 = 0x00000000;
343
+ 2, mem_reg_prop[0],
549
- cpu->isar.id_isar6 = 0x00000000;
344
+ 2, mem_reg_prop[1],
550
- cpu->clidr = 0x00000000; /* caches not implemented */
345
+ 2, mem_reg_prop[2],
551
- cpu->ctr = 0x8303c003;
346
+ 2, mem_reg_prop[3],
552
-}
347
+ 2, mem_reg_prop[4],
553
-
348
+ 2, mem_reg_prop[5]);
554
static const ARMCPRegInfo cortexr5_cp_reginfo[] = {
349
+ break;
555
/* Dummy the TCM region regs for the moment */
350
+ case 4:
556
{ .name = "ATCM", .cp = 15, .opc1 = 0, .crn = 9, .crm = 1, .opc2 = 0,
351
+ qemu_fdt_setprop_sized_cells(fdt, name, "reg",
557
@@ -XXX,XX +XXX,XX @@ static void pxa270c5_initfn(Object *obj)
352
+ 2, mem_reg_prop[0],
558
cpu->reset_sctlr = 0x00000078;
353
+ 2, mem_reg_prop[1],
559
}
354
+ 2, mem_reg_prop[2],
560
355
+ 2, mem_reg_prop[3],
561
-static const TCGCPUOps arm_v7m_tcg_ops = {
356
+ 2, mem_reg_prop[4],
562
- .initialize = arm_translate_init,
357
+ 2, mem_reg_prop[5],
563
- .synchronize_from_tb = arm_cpu_synchronize_from_tb,
358
+ 2, mem_reg_prop[6],
564
- .debug_excp_handler = arm_debug_excp_handler,
359
+ 2, mem_reg_prop[7]);
565
- .restore_state_to_opc = arm_restore_state_to_opc,
360
+ break;
566
-
361
+ default:
567
-#ifdef CONFIG_USER_ONLY
362
+ g_assert_not_reached();
568
- .record_sigsegv = arm_cpu_record_sigsegv,
363
+ }
569
- .record_sigbus = arm_cpu_record_sigbus,
364
+ g_free(name);
570
-#else
365
+}
571
- .tlb_fill = arm_cpu_tlb_fill,
366
+
572
- .cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt,
367
+static void versal_virt_modify_dtb(const struct arm_boot_info *binfo,
573
- .do_interrupt = arm_v7m_cpu_do_interrupt,
368
+ void *fdt)
574
- .do_transaction_failed = arm_cpu_do_transaction_failed,
369
+{
575
- .do_unaligned_access = arm_cpu_do_unaligned_access,
370
+ VersalVirt *s = container_of(binfo, VersalVirt, binfo);
576
- .adjust_watchpoint_address = arm_adjust_watchpoint_address,
371
+
577
- .debug_check_watchpoint = arm_debug_check_watchpoint,
372
+ fdt_add_memory_nodes(s, fdt, binfo->ram_size);
578
- .debug_check_breakpoint = arm_debug_check_breakpoint,
373
+}
579
-#endif /* !CONFIG_USER_ONLY */
374
+
580
-};
375
+static void *versal_virt_get_dtb(const struct arm_boot_info *binfo,
581
-
376
+ int *fdt_size)
582
-static void arm_v7m_class_init(ObjectClass *oc, void *data)
377
+{
583
-{
378
+ const VersalVirt *board = container_of(binfo, VersalVirt, binfo);
584
- ARMCPUClass *acc = ARM_CPU_CLASS(oc);
379
+
585
- CPUClass *cc = CPU_CLASS(oc);
380
+ *fdt_size = board->fdt_size;
586
-
381
+ return board->fdt;
587
- acc->info = data;
382
+}
588
- cc->tcg_ops = &arm_v7m_tcg_ops;
383
+
589
- cc->gdb_core_xml_file = "arm-m-profile.xml";
384
+#define NUM_VIRTIO_TRANSPORT 32
590
-}
385
+static void create_virtio_regions(VersalVirt *s)
591
-
386
+{
592
#ifndef TARGET_AARCH64
387
+ int virtio_mmio_size = 0x200;
593
/*
388
+ int i;
594
* -cpu max: a CPU with as many features enabled as our emulation supports.
389
+
595
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo arm_tcg_cpus[] = {
390
+ for (i = 0; i < NUM_VIRTIO_TRANSPORT; i++) {
596
{ .name = "cortex-a8", .initfn = cortex_a8_initfn },
391
+ char *name = g_strdup_printf("virtio%d", i);;
597
{ .name = "cortex-a9", .initfn = cortex_a9_initfn },
392
+ hwaddr base = MM_TOP_RSVD + i * virtio_mmio_size;
598
{ .name = "cortex-a15", .initfn = cortex_a15_initfn },
393
+ int irq = VERSAL_RSVD_HIGH_IRQ_FIRST + i;
599
- { .name = "cortex-m0", .initfn = cortex_m0_initfn,
394
+ MemoryRegion *mr;
600
- .class_init = arm_v7m_class_init },
395
+ DeviceState *dev;
601
- { .name = "cortex-m3", .initfn = cortex_m3_initfn,
396
+ qemu_irq pic_irq;
602
- .class_init = arm_v7m_class_init },
397
+
603
- { .name = "cortex-m4", .initfn = cortex_m4_initfn,
398
+ pic_irq = qdev_get_gpio_in(DEVICE(&s->soc.fpd.apu.gic), irq);
604
- .class_init = arm_v7m_class_init },
399
+ dev = qdev_create(NULL, "virtio-mmio");
605
- { .name = "cortex-m7", .initfn = cortex_m7_initfn,
400
+ object_property_add_child(OBJECT(&s->soc), name, OBJECT(dev),
606
- .class_init = arm_v7m_class_init },
401
+ &error_fatal);
607
- { .name = "cortex-m33", .initfn = cortex_m33_initfn,
402
+ qdev_init_nofail(dev);
608
- .class_init = arm_v7m_class_init },
403
+ sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic_irq);
609
- { .name = "cortex-m55", .initfn = cortex_m55_initfn,
404
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
610
- .class_init = arm_v7m_class_init },
405
+ memory_region_add_subregion(&s->soc.mr_ps, base, mr);
611
{ .name = "cortex-r5", .initfn = cortex_r5_initfn },
406
+ sysbus_create_simple("virtio-mmio", base, pic_irq);
612
{ .name = "cortex-r5f", .initfn = cortex_r5f_initfn },
407
+ }
613
{ .name = "cortex-r52", .initfn = cortex_r52_initfn },
408
+
614
diff --git a/target/arm/meson.build b/target/arm/meson.build
409
+ for (i = 0; i < NUM_VIRTIO_TRANSPORT; i++) {
615
index XXXXXXX..XXXXXXX 100644
410
+ hwaddr base = MM_TOP_RSVD + i * virtio_mmio_size;
616
--- a/target/arm/meson.build
411
+ int irq = VERSAL_RSVD_HIGH_IRQ_FIRST + i;
617
+++ b/target/arm/meson.build
412
+ char *name = g_strdup_printf("/virtio_mmio@%" PRIx64, base);
618
@@ -XXX,XX +XXX,XX @@ arm_system_ss.add(files(
413
+
619
'ptw.c',
414
+ qemu_fdt_add_subnode(s->fdt, name);
620
))
415
+ qemu_fdt_setprop(s->fdt, name, "dma-coherent", NULL, 0);
621
416
+ qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
622
+arm_user_ss = ss.source_set()
417
+ GIC_FDT_IRQ_TYPE_SPI, irq,
623
+
418
+ GIC_FDT_IRQ_FLAGS_EDGE_LO_HI);
624
subdir('hvf')
419
+ qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
625
420
+ 2, base, 2, virtio_mmio_size);
626
if 'CONFIG_TCG' in config_all_accel
421
+ qemu_fdt_setprop_string(s->fdt, name, "compatible", "virtio,mmio");
627
@@ -XXX,XX +XXX,XX @@ endif
422
+ g_free(name);
628
423
+ }
629
target_arch += {'arm': arm_ss}
424
+}
630
target_system_arch += {'arm': arm_system_ss}
425
+
631
+target_user_arch += {'arm': arm_user_ss}
426
+static void versal_virt_init(MachineState *machine)
632
diff --git a/target/arm/tcg/meson.build b/target/arm/tcg/meson.build
427
+{
633
index XXXXXXX..XXXXXXX 100644
428
+ VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(machine);
634
--- a/target/arm/tcg/meson.build
429
+ int psci_conduit = QEMU_PSCI_CONDUIT_DISABLED;
635
+++ b/target/arm/tcg/meson.build
430
+
636
@@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
431
+ /*
637
arm_system_ss.add(files(
432
+ * If the user provides an Operating System to be loaded, we expect them
638
'psci.c',
433
+ * to use the -kernel command line option.
639
))
434
+ *
640
+
435
+ * Users can load firmware or boot-loaders with the -device loader options.
641
+arm_system_ss.add(when: 'CONFIG_ARM_V7M', if_true: files('cpu-v7m.c'))
436
+ *
642
+arm_user_ss.add(when: 'TARGET_AARCH64', if_false: files('cpu-v7m.c'))
437
+ * When loading an OS, we generate a dtb and let arm_load_kernel() select
438
+ * where it gets loaded. This dtb will be passed to the kernel in x0.
439
+ *
440
+ * If there's no -kernel option, we generate a DTB and place it at 0x1000
441
+ * for the bootloaders or firmware to pick up.
442
+ *
443
+ * If users want to provide their own DTB, they can use the -dtb option.
444
+ * These dtb's will have their memory nodes modified to match QEMU's
445
+ * selected ram_size option before they get passed to the kernel or fw.
446
+ *
447
+ * When loading an OS, we turn on QEMU's PSCI implementation with SMC
448
+ * as the PSCI conduit. When there's no -kernel, we assume the user
449
+ * provides EL3 firmware to handle PSCI.
450
+ */
451
+ if (machine->kernel_filename) {
452
+ psci_conduit = QEMU_PSCI_CONDUIT_SMC;
453
+ }
454
+
455
+ memory_region_allocate_system_memory(&s->mr_ddr, NULL, "ddr",
456
+ machine->ram_size);
457
+
458
+ sysbus_init_child_obj(OBJECT(machine), "xlnx-ve", &s->soc,
459
+ sizeof(s->soc), TYPE_XLNX_VERSAL);
460
+ object_property_set_link(OBJECT(&s->soc), OBJECT(&s->mr_ddr),
461
+ "ddr", &error_abort);
462
+ object_property_set_int(OBJECT(&s->soc), psci_conduit,
463
+ "psci-conduit", &error_abort);
464
+ object_property_set_bool(OBJECT(&s->soc), true, "realized", &error_fatal);
465
+
466
+ fdt_create(s);
467
+ create_virtio_regions(s);
468
+ fdt_add_gem_nodes(s);
469
+ fdt_add_uart_nodes(s);
470
+ fdt_add_gic_nodes(s);
471
+ fdt_add_timer_nodes(s);
472
+ fdt_add_cpu_nodes(s, psci_conduit);
473
+ fdt_add_clk_node(s, "/clk125", 125000000, s->phandle.clk_125Mhz);
474
+ fdt_add_clk_node(s, "/clk25", 25000000, s->phandle.clk_25Mhz);
475
+
476
+ /* Make the APU cpu address space visible to virtio and other
477
+ * modules unaware of muliple address-spaces. */
478
+ memory_region_add_subregion_overlap(get_system_memory(),
479
+ 0, &s->soc.fpd.apu.mr, 0);
480
+
481
+ s->binfo.ram_size = machine->ram_size;
482
+ s->binfo.kernel_filename = machine->kernel_filename;
483
+ s->binfo.kernel_cmdline = machine->kernel_cmdline;
484
+ s->binfo.initrd_filename = machine->initrd_filename;
485
+ s->binfo.loader_start = 0x0;
486
+ s->binfo.get_dtb = versal_virt_get_dtb;
487
+ s->binfo.modify_dtb = versal_virt_modify_dtb;
488
+ if (machine->kernel_filename) {
489
+ arm_load_kernel(s->soc.fpd.apu.cpu[0], &s->binfo);
490
+ } else {
491
+ AddressSpace *as = arm_boot_address_space(s->soc.fpd.apu.cpu[0],
492
+ &s->binfo);
493
+ /* Some boot-loaders (e.g u-boot) don't like blobs at address 0 (NULL).
494
+ * Offset things by 4K. */
495
+ s->binfo.loader_start = 0x1000;
496
+ s->binfo.dtb_limit = 0x1000000;
497
+ if (arm_load_dtb(s->binfo.loader_start,
498
+ &s->binfo, s->binfo.dtb_limit, as) < 0) {
499
+ exit(EXIT_FAILURE);
500
+ }
501
+ }
502
+}
503
+
504
+static void versal_virt_machine_instance_init(Object *obj)
505
+{
506
+}
507
+
508
+static void versal_virt_machine_class_init(ObjectClass *oc, void *data)
509
+{
510
+ MachineClass *mc = MACHINE_CLASS(oc);
511
+
512
+ mc->desc = "Xilinx Versal Virtual development board";
513
+ mc->init = versal_virt_init;
514
+ mc->max_cpus = XLNX_VERSAL_NR_ACPUS;
515
+ mc->default_cpus = XLNX_VERSAL_NR_ACPUS;
516
+ mc->no_cdrom = true;
517
+}
518
+
519
+static const TypeInfo versal_virt_machine_init_typeinfo = {
520
+ .name = TYPE_XLNX_VERSAL_VIRT_MACHINE,
521
+ .parent = TYPE_MACHINE,
522
+ .class_init = versal_virt_machine_class_init,
523
+ .instance_init = versal_virt_machine_instance_init,
524
+ .instance_size = sizeof(VersalVirt),
525
+};
526
+
527
+static void versal_virt_machine_init_register_types(void)
528
+{
529
+ type_register_static(&versal_virt_machine_init_typeinfo);
530
+}
531
+
532
+type_init(versal_virt_machine_init_register_types)
533
--
643
--
534
2.19.1
644
2.34.1
535
536
diff view generated by jsdifflib