1
A mixed bag, all bug fixes or similar small stuff.
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
7
The following changes since commit 19eb2d4e736dc895f31fbd6b520e514f10cc08e0:
8
9
Merge remote-tracking branch 'remotes/thibault/tags/samuel-thibault' into staging (2019-05-07 10:43:32 +0100)
10
4
11
are available in the Git repository at:
5
are available in the Git repository at:
12
6
13
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20190507
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20240308
14
8
15
for you to fetch changes up to 63159601fb3e396b28da14cbb71e50ed3f5a0331:
9
for you to fetch changes up to bbf6c6dbead82292a20951eb1204442a6b838de9:
16
10
17
target/arm: Stop using variable length array in dc_zva (2019-05-07 12:55:04 +0100)
11
target/arm: Move v7m-related code from cpu32.c into a separate file (2024-03-08 14:45:03 +0000)
18
12
19
----------------------------------------------------------------
13
----------------------------------------------------------------
20
target-arm queue:
14
target-arm queue:
21
* Stop using variable length array in dc_zva
15
* Implement FEAT_ECV
22
* Implement M-profile XPSR GE bits
16
* STM32L4x5: Implement GPIO device
23
* Don't enable ARMV7M_EXCP_DEBUG from reset
17
* Fix 32-bit SMOPA
24
* armv7m_nvic: NS BFAR and BFSR are RAZ/WI if BFHFNMINS == 0
18
* Refactor v7m related code from cpu32.c into its own file
25
* armv7m_nvic: Check subpriority in nvic_recompute_state_secure()
19
* hw/rtc/sun4v-rtc: Relicense to GPLv2-or-later
26
* fix various minor issues to allow building for Windows-on-ARM64
27
* aspeed: Set SDRAM size
28
* Allow system registers for KVM guests to be changed by QEMU code
29
* raspi: Diagnose requests for too much RAM
30
* virt: Support firmware configuration with -blockdev
31
20
32
----------------------------------------------------------------
21
----------------------------------------------------------------
33
Cao Jiaxi (4):
22
Inès Varhol (3):
34
QEMU_PACKED: Remove gcc_struct attribute in Windows non x86 targets
23
hw/gpio: Implement STM32L4x5 GPIO
35
qga: Fix mingw compilation warnings on enum conversion
24
hw/arm: Connect STM32L4x5 GPIO to STM32L4x5 SoC
36
util/cacheinfo: Use uint64_t on LLP64 model to satisfy Windows ARM64
25
tests/qtest: Add STM32L4x5 GPIO QTest testcase
37
osdep: Fix mingw compilation regarding stdio formats
38
26
39
Joel Stanley (1):
27
Peter Maydell (9):
40
arm: aspeed: Set SDRAM size
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
41
37
42
Markus Armbruster (3):
38
Richard Henderson (1):
43
pc: Rearrange pc_system_firmware_init()'s legacy -drive loop
39
target/arm: Fix 32-bit SMOPA
44
pflash_cfi01: New pflash_cfi01_legacy_drive()
45
hw/arm/virt: Support firmware configuration with -blockdev
46
40
47
Peter Maydell (7):
41
Thomas Huth (1):
48
hw/arm/raspi: Diagnose requests for too much RAM
42
target/arm: Move v7m-related code from cpu32.c into a separate file
49
arm: Allow system registers for KVM guests to be changed by QEMU code
50
hw/arm/armv7m_nvic: Check subpriority in nvic_recompute_state_secure()
51
hw/intc/armv7m_nvic: NS BFAR and BFSR are RAZ/WI if BFHFNMINS == 0
52
hw/intc/armv7m_nvic: Don't enable ARMV7M_EXCP_DEBUG from reset
53
target/arm: Implement XPSR GE bits
54
target/arm: Stop using variable length array in dc_zva
55
43
56
contrib/libvhost-user/libvhost-user.h | 2 +-
44
MAINTAINERS | 1 +
57
include/hw/arm/aspeed.h | 1 +
45
docs/system/arm/b-l475e-iot01a.rst | 2 +-
58
include/hw/arm/virt.h | 2 +
46
docs/system/arm/emulation.rst | 1 +
59
include/hw/block/flash.h | 1 +
47
include/hw/arm/stm32l4x5_soc.h | 2 +
60
include/qemu/compiler.h | 2 +-
48
include/hw/gpio/stm32l4x5_gpio.h | 71 +++++
61
include/qemu/osdep.h | 10 +-
49
include/hw/misc/stm32l4x5_syscfg.h | 3 +-
62
scripts/cocci-macro-file.h | 7 +-
50
include/hw/rtc/sun4v-rtc.h | 2 +-
63
target/arm/cpu.h | 13 ++-
51
target/arm/cpu-features.h | 10 +
64
hw/arm/aspeed.c | 8 ++
52
target/arm/cpu.h | 129 +--------
65
hw/arm/raspi.c | 7 ++
53
target/arm/internals.h | 151 ++++++++++
66
hw/arm/virt.c | 202 ++++++++++++++++++++++------------
54
hw/arm/stm32l4x5_soc.c | 71 ++++-
67
hw/block/pflash_cfi01.c | 28 +++++
55
hw/gpio/stm32l4x5_gpio.c | 477 ++++++++++++++++++++++++++++++++
68
hw/i386/pc_sysfw.c | 18 +--
56
hw/misc/stm32l4x5_syscfg.c | 1 +
69
hw/intc/armv7m_nvic.c | 40 ++++++-
57
hw/rtc/sun4v-rtc.c | 2 +-
70
qga/commands-win32.c | 2 +-
58
target/arm/helper.c | 189 ++++++++++++-
71
target/arm/helper.c | 47 +++++++-
59
target/arm/tcg/cpu-v7m.c | 290 +++++++++++++++++++
72
target/arm/kvm.c | 8 ++
60
target/arm/tcg/cpu32.c | 261 ------------------
73
target/arm/kvm32.c | 20 +---
61
target/arm/tcg/cpu64.c | 1 +
74
target/arm/kvm64.c | 2 +
62
target/arm/tcg/sme_helper.c | 77 +++---
75
target/arm/machine.c | 2 +-
63
tests/qtest/stm32l4x5_gpio-test.c | 551 +++++++++++++++++++++++++++++++++++++
76
util/cacheinfo.c | 2 +-
64
tests/tcg/aarch64/sme-smopa-1.c | 47 ++++
77
21 files changed, 294 insertions(+), 130 deletions(-)
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
78
82
diff view generated by jsdifflib
1
From: Cao Jiaxi <driver1998@foxmail.com>
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.
2
5
3
I encountered the following compilation error on mingw:
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(-)
4
14
5
/mnt/d/qemu/include/qemu/osdep.h:97:9: error: '__USE_MINGW_ANSI_STDIO' macro redefined [-Werror,-Wmacro-redefined]
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
6
#define __USE_MINGW_ANSI_STDIO 1
7
^
8
/mnt/d/llvm-mingw/aarch64-w64-mingw32/include/_mingw.h:433:9: note: previous definition is here
9
#define __USE_MINGW_ANSI_STDIO 0 /* was not defined so it should be 0 */
10
11
It turns out that __USE_MINGW_ANSI_STDIO must be set before any
12
system headers are included, not just before stdio.h.
13
14
Signed-off-by: Cao Jiaxi <driver1998@foxmail.com>
15
Reviewed-by: Thomas Huth <thuth@redhat.com>
16
Reviewed-by: Stefan Weil <sw@weilnetz.de>
17
Message-id: 20190503003719.10233-1-driver1998@foxmail.com
18
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
---
21
include/qemu/osdep.h | 10 +++++-----
22
1 file changed, 5 insertions(+), 5 deletions(-)
23
24
diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
25
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
26
--- a/include/qemu/osdep.h
17
--- a/target/arm/cpu.h
27
+++ b/include/qemu/osdep.h
18
+++ b/target/arm/cpu.h
28
@@ -XXX,XX +XXX,XX @@ extern int daemon(int, int);
19
@@ -XXX,XX +XXX,XX @@ typedef struct ARMGenericTimer {
29
#endif
20
uint64_t ctl; /* Timer Control register */
30
#endif
21
} ARMGenericTimer;
31
22
32
+/* enable C99/POSIX format strings (needs mingw32-runtime 3.15 or later) */
23
-#define VTCR_NSW (1u << 29)
33
+#ifdef __MINGW32__
24
-#define VTCR_NSA (1u << 30)
34
+#define __USE_MINGW_ANSI_STDIO 1
25
-#define VSTCR_SW VTCR_NSW
35
+#endif
26
-#define VSTCR_SA VTCR_NSA
36
+
27
-
37
#include <stdarg.h>
28
/* Define a maximum sized vector register.
38
#include <stddef.h>
29
* For 32-bit, this is a 128-bit NEON/AdvSIMD register.
39
#include <stdbool.h>
30
* For 64-bit, this is a 2048-bit SVE register.
40
#include <stdint.h>
31
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
41
#include <sys/types.h>
32
#define SCTLR_SPINTMASK (1ULL << 62) /* FEAT_NMI */
42
#include <stdlib.h>
33
#define SCTLR_TIDCP (1ULL << 63) /* FEAT_TIDCP1 */
43
-
34
44
-/* enable C99/POSIX format strings (needs mingw32-runtime 3.15 or later) */
35
-/* Bit definitions for CPACR (AArch32 only) */
45
-#ifdef __MINGW32__
36
-FIELD(CPACR, CP10, 20, 2)
46
-#define __USE_MINGW_ANSI_STDIO 1
37
-FIELD(CPACR, CP11, 22, 2)
47
-#endif
38
-FIELD(CPACR, TRCDIS, 28, 1) /* matches CPACR_EL1.TTA */
48
#include <stdio.h>
39
-FIELD(CPACR, D32DIS, 30, 1) /* up to v7; RAZ in v8 */
49
40
-FIELD(CPACR, ASEDIS, 31, 1)
50
#include <string.h>
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
51
--
321
--
52
2.20.1
322
2.34.1
53
323
54
324
diff view generated by jsdifflib
1
The M-profile architecture specifies that the DebugMonitor exception
1
The timer _EL02 registers should UNDEF for invalid accesses from EL2
2
should be initially disabled, not enabled. It should be controlled
2
or EL3 when HCR_EL2.E2H == 0, not take a cp access trap. We were
3
by the DEMCR register's MON_EN bit, but we don't implement that
3
delivering the exception to EL2 with the wrong syndrome.
4
register yet (like most of the debug architecture for M-profile).
5
6
Note that BKPT instructions will still work, because they
7
will be escalated to HardFault.
8
4
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20190430131439.25251-4-peter.maydell@linaro.org
7
Message-id: 20240301183219.2424889-3-peter.maydell@linaro.org
12
---
8
---
13
hw/intc/armv7m_nvic.c | 4 +++-
9
target/arm/helper.c | 2 +-
14
1 file changed, 3 insertions(+), 1 deletion(-)
10
1 file changed, 1 insertion(+), 1 deletion(-)
15
11
16
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
12
diff --git a/target/arm/helper.c b/target/arm/helper.c
17
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/intc/armv7m_nvic.c
14
--- a/target/arm/helper.c
19
+++ b/hw/intc/armv7m_nvic.c
15
+++ b/target/arm/helper.c
20
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_reset(DeviceState *dev)
16
@@ -XXX,XX +XXX,XX @@ static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
21
* the System Handler Control register
17
return CP_ACCESS_OK;
22
*/
18
}
23
s->vectors[ARMV7M_EXCP_SVC].enabled = 1;
19
if (!(arm_hcr_el2_eff(env) & HCR_E2H)) {
24
- s->vectors[ARMV7M_EXCP_DEBUG].enabled = 1;
20
- return CP_ACCESS_TRAP;
25
s->vectors[ARMV7M_EXCP_PENDSV].enabled = 1;
21
+ return CP_ACCESS_TRAP_UNCATEGORIZED;
26
s->vectors[ARMV7M_EXCP_SYSTICK].enabled = 1;
22
}
27
23
return CP_ACCESS_OK;
28
+ /* DebugMonitor is enabled via DEMCR.MON_EN */
24
}
29
+ s->vectors[ARMV7M_EXCP_DEBUG].enabled = 0;
30
+
31
resetprio = arm_feature(&s->cpu->env, ARM_FEATURE_V8) ? -4 : -3;
32
s->vectors[ARMV7M_EXCP_RESET].prio = resetprio;
33
s->vectors[ARMV7M_EXCP_NMI].prio = -2;
34
--
25
--
35
2.20.1
26
2.34.1
36
37
diff view generated by jsdifflib
1
From: Markus Armbruster <armbru@redhat.com>
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.
2
3
3
The loop does two things: map legacy -drive to properties, and collect
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
all the backends for use after the loop. The next patch will factor
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
out the former for reuse in hw/arm/virt.c. To make that easier,
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
rearrange the loop so it does the first thing first, and the second
7
Message-id: 20240301183219.2424889-4-peter.maydell@linaro.org
7
thing second.
8
---
9
target/arm/internals.h | 27 +++++++++++++++++++++++++--
10
target/arm/helper.c | 9 ++++-----
11
2 files changed, 29 insertions(+), 7 deletions(-)
8
12
9
Signed-off-by: Markus Armbruster <armbru@redhat.com>
13
diff --git a/target/arm/internals.h b/target/arm/internals.h
10
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
12
Message-id: 20190416091348.26075-2-armbru@redhat.com
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
hw/i386/pc_sysfw.c | 24 +++++++++++-------------
16
1 file changed, 11 insertions(+), 13 deletions(-)
17
18
diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
19
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/i386/pc_sysfw.c
15
--- a/target/arm/internals.h
21
+++ b/hw/i386/pc_sysfw.c
16
+++ b/target/arm/internals.h
22
@@ -XXX,XX +XXX,XX @@ void pc_system_firmware_init(PCMachineState *pcms,
17
@@ -XXX,XX +XXX,XX @@ FIELD(VTCR, SL2, 33, 1)
23
18
#define HSTR_TTEE (1 << 16)
24
/* Map legacy -drive if=pflash to machine properties */
19
#define HSTR_TJDBX (1 << 17)
25
for (i = 0; i < ARRAY_SIZE(pcms->flash); i++) {
20
26
- pflash_blk[i] = pflash_cfi01_get_blk(pcms->flash[i]);
21
-#define CNTHCTL_CNTVMASK (1 << 18)
27
pflash_drv = drive_get(IF_PFLASH, 0, i);
22
-#define CNTHCTL_CNTPMASK (1 << 19)
28
- if (!pflash_drv) {
23
+/*
29
- continue;
24
+ * Depending on the value of HCR_EL2.E2H, bits 0 and 1
30
+ if (pflash_drv) {
25
+ * have different bit definitions, and EL1PCTEN might be
31
+ loc_push_none(&loc);
26
+ * bit 0 or bit 10. We use _E2H1 and _E2H0 suffixes to
32
+ qemu_opts_loc_restore(pflash_drv->opts);
27
+ * disambiguate if necessary.
33
+ if (pflash_cfi01_get_blk(pcms->flash[i])) {
28
+ */
34
+ error_report("clashes with -machine");
29
+FIELD(CNTHCTL, EL0PCTEN_E2H1, 0, 1)
35
+ exit(1);
30
+FIELD(CNTHCTL, EL0VCTEN_E2H1, 1, 1)
36
+ }
31
+FIELD(CNTHCTL, EL1PCTEN_E2H0, 0, 1)
37
+ qdev_prop_set_drive(DEVICE(pcms->flash[i]), "drive",
32
+FIELD(CNTHCTL, EL1PCEN_E2H0, 1, 1)
38
+ blk_by_legacy_dinfo(pflash_drv), &error_fatal);
33
+FIELD(CNTHCTL, EVNTEN, 2, 1)
39
+ loc_pop(&loc);
34
+FIELD(CNTHCTL, EVNTDIR, 3, 1)
40
}
35
+FIELD(CNTHCTL, EVNTI, 4, 4)
41
- loc_push_none(&loc);
36
+FIELD(CNTHCTL, EL0VTEN, 8, 1)
42
- qemu_opts_loc_restore(pflash_drv->opts);
37
+FIELD(CNTHCTL, EL0PTEN, 9, 1)
43
- if (pflash_blk[i]) {
38
+FIELD(CNTHCTL, EL1PCTEN_E2H1, 10, 1)
44
- error_report("clashes with -machine");
39
+FIELD(CNTHCTL, EL1PTEN, 11, 1)
45
- exit(1);
40
+FIELD(CNTHCTL, ECV, 12, 1)
46
- }
41
+FIELD(CNTHCTL, EL1TVT, 13, 1)
47
- pflash_blk[i] = blk_by_legacy_dinfo(pflash_drv);
42
+FIELD(CNTHCTL, EL1TVCT, 14, 1)
48
- qdev_prop_set_drive(DEVICE(pcms->flash[i]),
43
+FIELD(CNTHCTL, EL1NVPCT, 15, 1)
49
- "drive", pflash_blk[i], &error_fatal);
44
+FIELD(CNTHCTL, EL1NVVCT, 16, 1)
50
- loc_pop(&loc);
45
+FIELD(CNTHCTL, EVNTIS, 17, 1)
51
+ pflash_blk[i] = pflash_cfi01_get_blk(pcms->flash[i]);
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;
52
}
64
}
53
65
54
/* Reject gaps */
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
}
55
--
81
--
56
2.20.1
82
2.34.1
57
83
58
84
diff view generated by jsdifflib
1
Currently the dc_zva helper function uses a variable length
1
Don't allow the guest to write CNTHCTL_EL2 bits which don't exist.
2
array. In fact we know (as the comment above remarks) that
2
This is not strictly architecturally required, but it is how we've
3
the length of this array is bounded because the architecture
3
tended to implement registers more recently.
4
limits the block size and QEMU limits the target page size.
4
5
Use a fixed array size and assert that we don't run off it.
5
In particular, bits [19:18] are only present with FEAT_RME,
6
and bits [17:12] will only be present with FEAT_ECV.
6
7
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Message-id: 20240301183219.2424889-5-peter.maydell@linaro.org
10
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Message-id: 20190503120448.13385-1-peter.maydell@linaro.org
12
---
11
---
13
target/arm/helper.c | 8 ++++++--
12
target/arm/helper.c | 18 ++++++++++++++++++
14
1 file changed, 6 insertions(+), 2 deletions(-)
13
1 file changed, 18 insertions(+)
15
14
16
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
17
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/helper.c
17
--- a/target/arm/helper.c
19
+++ b/target/arm/helper.c
18
+++ b/target/arm/helper.c
20
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
21
#include "qemu/osdep.h"
20
{
22
+#include "qemu/units.h"
21
ARMCPU *cpu = env_archcpu(env);
23
#include "target/arm/idau.h"
22
uint32_t oldval = env->cp15.cnthctl_el2;
24
#include "trace.h"
23
+ uint32_t valid_mask =
25
#include "cpu.h"
24
+ R_CNTHCTL_EL0PCTEN_E2H1_MASK |
26
@@ -XXX,XX +XXX,XX @@ void HELPER(dc_zva)(CPUARMState *env, uint64_t vaddr_in)
25
+ R_CNTHCTL_EL0VCTEN_E2H1_MASK |
27
* We know that in fact for any v8 CPU the page size is at least 4K
26
+ R_CNTHCTL_EVNTEN_MASK |
28
* and the block size must be 2K or less, but TARGET_PAGE_SIZE is only
27
+ R_CNTHCTL_EVNTDIR_MASK |
29
* 1K as an artefact of legacy v5 subpage support being present in the
28
+ R_CNTHCTL_EVNTI_MASK |
30
- * same QEMU executable.
29
+ R_CNTHCTL_EL0VTEN_MASK |
31
+ * same QEMU executable. So in practice the hostaddr[] array has
30
+ R_CNTHCTL_EL0PTEN_MASK |
32
+ * two entries, given the current setting of TARGET_PAGE_BITS_MIN.
31
+ R_CNTHCTL_EL1PCTEN_E2H1_MASK |
33
*/
32
+ R_CNTHCTL_EL1PTEN_MASK;
34
int maxidx = DIV_ROUND_UP(blocklen, TARGET_PAGE_SIZE);
35
- void *hostaddr[maxidx];
36
+ void *hostaddr[DIV_ROUND_UP(2 * KiB, 1 << TARGET_PAGE_BITS_MIN)];
37
int try, i;
38
unsigned mmu_idx = cpu_mmu_index(env, false);
39
TCGMemOpIdx oi = make_memop_idx(MO_UB, mmu_idx);
40
41
+ assert(maxidx <= ARRAY_SIZE(hostaddr));
42
+
33
+
43
for (try = 0; try < 2; try++) {
34
+ if (cpu_isar_feature(aa64_rme, cpu)) {
44
35
+ valid_mask |= R_CNTHCTL_CNTVMASK_MASK | R_CNTHCTL_CNTPMASK_MASK;
45
for (i = 0; i < maxidx; i++) {
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) {
46
--
44
--
47
2.20.1
45
2.34.1
48
49
diff view generated by jsdifflib
1
In the M-profile architecture, if the CPU implements the DSP extension
1
The functionality defined by ID_AA64MMFR0_EL1.ECV == 1 is:
2
then the XPSR has GE bits, in the same way as the A-profile CPSR. When
2
* four new trap bits for various counter and timer registers
3
we added DSP extension support we forgot to add support for reading
3
* the CNTHCTL_EL2.EVNTIS and CNTKCTL_EL1.EVNTIS bits which control
4
and writing the GE bits, which are stored in env->GE. We did put in
4
scaling of the event stream. This is a no-op for us, because we don't
5
the code to add XPSR_GE to the mask of bits to update in the v7m_msr
5
implement the event stream (our WFE is a NOP): all we need to do is
6
helper, but forgot it in v7m_mrs. We also must not allow the XPSR we
6
allow CNTHCTL_EL2.ENVTIS to be read and written.
7
pull off the stack on exception return to set the nonexistent GE bits.
7
* extensions to PMSCR_EL1.PCT, PMSCR_EL2.PCT, TRFCR_EL1.TS and
8
Correct these errors:
8
TRFCR_EL2.TS: these are all no-ops for us, because we don't implement
9
* read and write env->GE in xpsr_read() and xpsr_write()
9
FEAT_SPE or FEAT_TRF.
10
* only set GE bits on exception return if DSP present
10
* new registers CNTPCTSS_EL0 and NCTVCTSS_EL0 which are
11
* read GE bits for MRS if DSP present
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.
15
16
In this commit we implement the trap handling and permit the new
17
CNTHCTL_EL2 bits to be written.
12
18
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20190430131439.25251-5-peter.maydell@linaro.org
21
Message-id: 20240301183219.2424889-6-peter.maydell@linaro.org
16
---
22
---
17
target/arm/cpu.h | 4 ++++
23
target/arm/cpu-features.h | 5 ++++
18
target/arm/helper.c | 12 ++++++++++--
24
target/arm/helper.c | 51 +++++++++++++++++++++++++++++++++++----
19
2 files changed, 14 insertions(+), 2 deletions(-)
25
2 files changed, 51 insertions(+), 5 deletions(-)
20
26
21
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
27
diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
22
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/cpu.h
29
--- a/target/arm/cpu-features.h
24
+++ b/target/arm/cpu.h
30
+++ b/target/arm/cpu-features.h
25
@@ -XXX,XX +XXX,XX @@ static inline uint32_t xpsr_read(CPUARMState *env)
31
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_fgt(const ARMISARegisters *id)
26
| (env->CF << 29) | ((env->VF & 0x80000000) >> 3) | (env->QF << 27)
32
return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, FGT) != 0;
27
| (env->thumb << 24) | ((env->condexec_bits & 3) << 25)
28
| ((env->condexec_bits & 0xfc) << 8)
29
+ | (env->GE << 16)
30
| env->v7m.exception;
31
}
33
}
32
34
33
@@ -XXX,XX +XXX,XX @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
35
+static inline bool isar_feature_aa64_ecv_traps(const ARMISARegisters *id)
34
if (mask & XPSR_Q) {
36
+{
35
env->QF = ((val & XPSR_Q) != 0);
37
+ return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, ECV) > 0;
36
}
38
+}
37
+ if (mask & XPSR_GE) {
39
+
38
+ env->GE = (val & XPSR_GE) >> 16;
40
static inline bool isar_feature_aa64_vh(const ARMISARegisters *id)
39
+ }
41
{
40
if (mask & XPSR_T) {
42
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0;
41
env->thumb = ((val & XPSR_T) != 0);
42
}
43
diff --git a/target/arm/helper.c b/target/arm/helper.c
43
diff --git a/target/arm/helper.c b/target/arm/helper.c
44
index XXXXXXX..XXXXXXX 100644
44
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/helper.c
45
--- a/target/arm/helper.c
46
+++ b/target/arm/helper.c
46
+++ b/target/arm/helper.c
47
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
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,
48
{
87
{
49
CPUARMState *env = &cpu->env;
88
if (arm_current_el(env) == 1) {
50
uint32_t excret;
89
/* This must be a FEAT_NV access */
51
- uint32_t xpsr;
90
- /* TODO: FEAT_ECV will need to check CNTHCTL_EL2 here */
52
+ uint32_t xpsr, xpsr_mask;
91
return CP_ACCESS_OK;
53
bool ufault = false;
54
bool sfault = false;
55
bool return_to_sp_process;
56
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
57
}
58
*frame_sp_p = frameptr;
59
}
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
+}
60
+
109
+
61
+ xpsr_mask = ~(XPSR_SPREALIGN | XPSR_SFPA);
110
+static CPAccessResult access_el1nvvct(CPUARMState *env, const ARMCPRegInfo *ri,
62
+ if (!arm_feature(env, ARM_FEATURE_THUMB_DSP)) {
111
+ bool isread)
63
+ xpsr_mask &= ~XPSR_GE;
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
+ }
64
+ }
118
+ }
65
/* This xpsr_write() will invalidate frame_sp_p as it may switch stack */
119
+ return e2h_access(env, ri, isread);
66
- xpsr_write(env, xpsr, ~(XPSR_SPREALIGN | XPSR_SFPA));
120
+}
67
+ xpsr_write(env, xpsr, xpsr_mask);
121
+
68
122
/* Test if system register redirection is to occur in the current state. */
69
if (env->v7m.secure) {
123
static bool redirect_for_e2h(CPUARMState *env)
70
bool sfpa = xpsr & XPSR_SFPA;
124
{
71
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
125
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vhe_reginfo[] = {
72
}
126
{ .name = "CNTP_CTL_EL02", .state = ARM_CP_STATE_AA64,
73
if (!(reg & 4)) {
127
.opc0 = 3, .opc1 = 5, .crn = 14, .crm = 2, .opc2 = 1,
74
mask |= XPSR_NZCV | XPSR_Q; /* APSR */
128
.type = ARM_CP_IO | ARM_CP_ALIAS,
75
+ if (arm_feature(env, ARM_FEATURE_THUMB_DSP)) {
129
- .access = PL2_RW, .accessfn = e2h_access,
76
+ mask |= XPSR_GE;
130
+ .access = PL2_RW, .accessfn = access_el1nvpct,
77
+ }
131
.nv2_redirect_offset = 0x180 | NV2_REDIR_NO_NV1,
78
}
132
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].ctl),
79
/* EPSR reads as zero */
133
.writefn = gt_phys_ctl_write, .raw_writefn = raw_write },
80
return xpsr_read(env) & mask;
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
};
81
--
159
--
82
2.20.1
160
2.34.1
83
84
diff view generated by jsdifflib
1
The non-secure versions of the BFAR and BFSR registers are
1
For FEAT_ECV, new registers CNTPCTSS_EL0 and CNTVCTSS_EL0 are
2
supposed to be RAZ/WI if AICR.BFHFNMINS == 0; we were
2
defined, which are "self-synchronized" views of the physical and
3
incorrectly allowing NS code to access the real values.
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).
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.
4
14
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20190430131439.25251-3-peter.maydell@linaro.org
17
Message-id: 20240301183219.2424889-7-peter.maydell@linaro.org
8
---
18
---
9
hw/intc/armv7m_nvic.c | 27 ++++++++++++++++++++++++---
19
target/arm/helper.c | 43 +++++++++++++++++++++++++++++++++++++++++++
10
1 file changed, 24 insertions(+), 3 deletions(-)
20
1 file changed, 43 insertions(+)
11
21
12
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
22
diff --git a/target/arm/helper.c b/target/arm/helper.c
13
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/intc/armv7m_nvic.c
24
--- a/target/arm/helper.c
15
+++ b/hw/intc/armv7m_nvic.c
25
+++ b/target/arm/helper.c
16
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
26
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
17
if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
27
},
18
goto bad_offset;
28
};
19
}
29
20
+ if (!attrs.secure &&
30
+/*
21
+ !(s->cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK)) {
31
+ * FEAT_ECV adds extra views of CNTVCT_EL0 and CNTPCT_EL0 which
22
+ return 0;
32
+ * are "self-synchronizing". For QEMU all sysregs are self-synchronizing,
23
+ }
33
+ * so our implementations here are identical to the normal registers.
24
return cpu->env.v7m.bfar;
34
+ */
25
case 0xd3c: /* Aux Fault Status. */
35
+static const ARMCPRegInfo gen_timer_ecv_cp_reginfo[] = {
26
/* TODO: Implement fault status registers. */
36
+ { .name = "CNTVCTSS", .cp = 15, .crm = 14, .opc1 = 9,
27
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
37
+ .access = PL0_R, .type = ARM_CP_64BIT | ARM_CP_NO_RAW | ARM_CP_IO,
28
if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
38
+ .accessfn = gt_vct_access,
29
goto bad_offset;
39
+ .readfn = gt_virt_cnt_read, .resetfn = arm_cp_reset_ignore,
30
}
40
+ },
31
+ if (!attrs.secure &&
41
+ { .name = "CNTVCTSS_EL0", .state = ARM_CP_STATE_AA64,
32
+ !(s->cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK)) {
42
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 6,
33
+ return;
43
+ .access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
34
+ }
44
+ .accessfn = gt_vct_access, .readfn = gt_virt_cnt_read,
35
cpu->env.v7m.bfar = value;
45
+ },
36
return;
46
+ { .name = "CNTPCTSS", .cp = 15, .crm = 14, .opc1 = 8,
37
case 0xd3c: /* Aux Fault Status. */
47
+ .access = PL0_R, .type = ARM_CP_64BIT | ARM_CP_NO_RAW | ARM_CP_IO,
38
@@ -XXX,XX +XXX,XX @@ static MemTxResult nvic_sysreg_read(void *opaque, hwaddr addr,
48
+ .accessfn = gt_pct_access,
39
val = 0;
49
+ .readfn = gt_cnt_read, .resetfn = arm_cp_reset_ignore,
40
break;
50
+ },
41
};
51
+ { .name = "CNTPCTSS_EL0", .state = ARM_CP_STATE_AA64,
42
- /* The BFSR bits [15:8] are shared between security states
52
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 5,
43
- * and we store them in the NS copy
53
+ .access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
44
+ /*
54
+ .accessfn = gt_pct_access, .readfn = gt_cnt_read,
45
+ * The BFSR bits [15:8] are shared between security states
55
+ },
46
+ * and we store them in the NS copy. They are RAZ/WI for
56
+};
47
+ * NS code if AIRCR.BFHFNMINS is 0.
48
*/
49
val = s->cpu->env.v7m.cfsr[attrs.secure];
50
- val |= s->cpu->env.v7m.cfsr[M_REG_NS] & R_V7M_CFSR_BFSR_MASK;
51
+ if (!attrs.secure &&
52
+ !(s->cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK)) {
53
+ val &= ~R_V7M_CFSR_BFSR_MASK;
54
+ } else {
55
+ val |= s->cpu->env.v7m.cfsr[M_REG_NS] & R_V7M_CFSR_BFSR_MASK;
56
+ }
57
val = extract32(val, (offset - 0xd28) * 8, size * 8);
58
break;
59
case 0xfe0 ... 0xfff: /* ID. */
60
@@ -XXX,XX +XXX,XX @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr,
61
*/
62
value <<= ((offset - 0xd28) * 8);
63
64
+ if (!attrs.secure &&
65
+ !(s->cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK)) {
66
+ /* BFSR bits are RAZ/WI for NS if BFHFNMINS is set */
67
+ value &= ~R_V7M_CFSR_BFSR_MASK;
68
+ }
69
+
57
+
70
s->cpu->env.v7m.cfsr[attrs.secure] &= ~value;
58
#else
71
if (attrs.secure) {
59
72
/* The BFSR bits [15:8] are shared between security states
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,
73
--
90
--
74
2.20.1
91
2.34.1
75
76
diff view generated by jsdifflib
1
At the moment the Arm implementations of kvm_arch_{get,put}_registers()
1
When ID_AA64MMFR0_EL1.ECV is 0b0010, a new register CNTPOFF_EL2 is
2
don't support having QEMU change the values of system registers
2
implemented. This is similar to the existing CNTVOFF_EL2, except
3
(aka coprocessor registers for AArch32). This is because although
3
that it controls a hypervisor-adjustable offset made to the physical
4
kvm_arch_get_registers() calls write_list_to_cpustate() to
4
counter and timer.
5
update the CPU state struct fields (so QEMU code can read the
6
values in the usual way), kvm_arch_put_registers() does not
7
call write_cpustate_to_list(), meaning that any changes to
8
the CPU state struct fields will not be passed back to KVM.
9
5
10
The rationale for this design is documented in a comment in the
6
Implement the handling for this register, which includes control/trap
11
AArch32 kvm_arch_put_registers() -- writing the values in the
7
bits in SCR_EL3 and CNTHCTL_EL2.
12
cpregs list into the CPU state struct is "lossy" because the
13
write of a register might not succeed, and so if we blindly
14
copy the CPU state values back again we will incorrectly
15
change register values for the guest. The assumption was that
16
no QEMU code would need to write to the registers.
17
18
However, when we implemented debug support for KVM guests, we
19
broke that assumption: the code to handle "set the guest up
20
to take a breakpoint exception" does so by updating various
21
guest registers including ESR_EL1.
22
23
Support this by making kvm_arch_put_registers() synchronize
24
CPU state back into the list. We sync only those registers
25
where the initial write succeeds, which should be sufficient.
26
27
This commit is the same as commit 823e1b3818f9b10b824ddc which we
28
had to revert in commit 942f99c825fc94c8b1a4, except that the bug
29
which was preventing EDK2 guest firmware running has been fixed:
30
kvm_arm_reset_vcpu() now calls write_list_to_cpustate().
31
8
32
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
33
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
34
Tested-by: Eric Auger <eric.auger@redhat.com>
11
Message-id: 20240301183219.2424889-8-peter.maydell@linaro.org
35
---
12
---
36
target/arm/cpu.h | 9 ++++++++-
13
target/arm/cpu-features.h | 5 +++
37
target/arm/helper.c | 27 +++++++++++++++++++++++++--
14
target/arm/cpu.h | 1 +
38
target/arm/kvm.c | 8 ++++++++
15
target/arm/helper.c | 68 +++++++++++++++++++++++++++++++++++++--
39
target/arm/kvm32.c | 20 ++------------------
16
target/arm/trace-events | 1 +
40
target/arm/kvm64.c | 2 ++
17
4 files changed, 73 insertions(+), 2 deletions(-)
41
target/arm/machine.c | 2 +-
42
6 files changed, 46 insertions(+), 22 deletions(-)
43
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;
44
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
35
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
45
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
46
--- a/target/arm/cpu.h
37
--- a/target/arm/cpu.h
47
+++ b/target/arm/cpu.h
38
+++ b/target/arm/cpu.h
48
@@ -XXX,XX +XXX,XX @@ bool write_list_to_cpustate(ARMCPU *cpu);
39
@@ -XXX,XX +XXX,XX @@ typedef struct CPUArchState {
49
/**
40
uint64_t c14_cntkctl; /* Timer Control register */
50
* write_cpustate_to_list:
41
uint64_t cnthctl_el2; /* Counter/Timer Hyp Control register */
51
* @cpu: ARMCPU
42
uint64_t cntvoff_el2; /* Counter Virtual Offset register */
52
+ * @kvm_sync: true if this is for syncing back to KVM
43
+ uint64_t cntpoff_el2; /* Counter Physical Offset register */
53
*
44
ARMGenericTimer c14_timer[NUM_GTIMERS];
54
* For each register listed in the ARMCPU cpreg_indexes list, write
45
uint32_t c15_cpar; /* XScale Coprocessor Access Register */
55
* its value from the ARMCPUState structure into the cpreg_values list.
46
uint32_t c15_ticonfig; /* TI925T configuration byte. */
56
* This is used to copy info from TCG's working data structures into
57
* KVM or for outbound migration.
58
*
59
+ * @kvm_sync is true if we are doing this in order to sync the
60
+ * register state back to KVM. In this case we will only update
61
+ * values in the list if the previous list->cpustate sync actually
62
+ * successfully wrote the CPU state. Otherwise we will keep the value
63
+ * that is in the list.
64
+ *
65
* Returns: true if all register values were read correctly,
66
* false if some register was unknown or could not be read.
67
* Note that we do not stop early on failure -- we will attempt
68
* reading all registers in the list.
69
*/
70
-bool write_cpustate_to_list(ARMCPU *cpu);
71
+bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync);
72
73
#define ARM_CPUID_TI915T 0x54029152
74
#define ARM_CPUID_TI925T 0x54029252
75
diff --git a/target/arm/helper.c b/target/arm/helper.c
47
diff --git a/target/arm/helper.c b/target/arm/helper.c
76
index XXXXXXX..XXXXXXX 100644
48
index XXXXXXX..XXXXXXX 100644
77
--- a/target/arm/helper.c
49
--- a/target/arm/helper.c
78
+++ b/target/arm/helper.c
50
+++ b/target/arm/helper.c
79
@@ -XXX,XX +XXX,XX @@ static bool raw_accessors_invalid(const ARMCPRegInfo *ri)
51
@@ -XXX,XX +XXX,XX @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
80
return true;
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);
81
}
63
}
82
64
83
-bool write_cpustate_to_list(ARMCPU *cpu)
65
+static uint64_t gt_phys_raw_cnt_offset(CPUARMState *env)
84
+bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync)
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
{
85
{
86
/* Write the coprocessor state from cpu->env to the (index,value) list. */
86
ARMGenericTimer *gt = &cpu->env.cp15.c14_timer[timeridx];
87
int i;
87
@@ -XXX,XX +XXX,XX @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
88
@@ -XXX,XX +XXX,XX @@ bool write_cpustate_to_list(ARMCPU *cpu)
88
* reset timer to when ISTATUS next has to change
89
for (i = 0; i < cpu->cpreg_array_len; i++) {
89
*/
90
uint32_t regidx = kvm_to_cpreg_id(cpu->cpreg_indexes[i]);
90
uint64_t offset = timeridx == GTIMER_VIRT ?
91
const ARMCPRegInfo *ri;
91
- cpu->env.cp15.cntvoff_el2 : 0;
92
+ uint64_t newval;
92
+ cpu->env.cp15.cntvoff_el2 : gt_phys_raw_cnt_offset(&cpu->env);
93
93
uint64_t count = gt_get_countervalue(&cpu->env);
94
ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
94
/* Note that this must be unsigned 64 bit arithmetic: */
95
if (!ri) {
95
int istatus = count - offset >= gt->cval;
96
@@ -XXX,XX +XXX,XX @@ bool write_cpustate_to_list(ARMCPU *cpu)
96
@@ -XXX,XX +XXX,XX @@ static void gt_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri,
97
if (ri->type & ARM_CP_NO_RAW) {
97
98
continue;
98
static uint64_t gt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
99
}
99
{
100
- cpu->cpreg_values[i] = read_raw_cp_reg(&cpu->env, ri);
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
+}
101
+
148
+
102
+ newval = read_raw_cp_reg(&cpu->env, ri);
149
+static void gt_cntpoff_write(CPUARMState *env, const ARMCPRegInfo *ri,
103
+ if (kvm_sync) {
150
+ uint64_t value)
104
+ /*
151
+{
105
+ * Only sync if the previous list->cpustate sync succeeded.
152
+ ARMCPU *cpu = env_archcpu(env);
106
+ * Rather than tracking the success/failure state for every
107
+ * item in the list, we just recheck "does the raw write we must
108
+ * have made in write_list_to_cpustate() read back OK" here.
109
+ */
110
+ uint64_t oldval = cpu->cpreg_values[i];
111
+
153
+
112
+ if (oldval == newval) {
154
+ trace_arm_gt_cntpoff_write(value);
113
+ continue;
155
+ raw_write(env, ri, value);
114
+ }
156
+ gt_recalc_timer(cpu, GTIMER_PHYS);
157
+}
115
+
158
+
116
+ write_raw_cp_reg(&cpu->env, ri, oldval);
159
+static const ARMCPRegInfo gen_timer_cntpoff_reginfo = {
117
+ if (read_raw_cp_reg(&cpu->env, ri) != oldval) {
160
+ .name = "CNTPOFF_EL2", .state = ARM_CP_STATE_AA64,
118
+ continue;
161
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 0, .opc2 = 6,
119
+ }
162
+ .access = PL2_RW, .type = ARM_CP_IO, .resetvalue = 0,
120
+
163
+ .accessfn = gt_cntpoff_access, .writefn = gt_cntpoff_write,
121
+ write_raw_cp_reg(&cpu->env, ri, newval);
164
+ .nv2_redirect_offset = 0x1a8,
122
+ }
165
+ .fieldoffset = offsetof(CPUARMState, cp15.cntpoff_el2),
123
+ cpu->cpreg_values[i] = newval;
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);
124
}
173
}
125
return ok;
174
+#ifndef CONFIG_USER_ONLY
126
}
175
+ if (cpu_isar_feature(aa64_ecv, cpu)) {
127
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
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
128
index XXXXXXX..XXXXXXX 100644
183
index XXXXXXX..XXXXXXX 100644
129
--- a/target/arm/kvm.c
184
--- a/target/arm/trace-events
130
+++ b/target/arm/kvm.c
185
+++ b/target/arm/trace-events
131
@@ -XXX,XX +XXX,XX @@ void kvm_arm_reset_vcpu(ARMCPU *cpu)
186
@@ -XXX,XX +XXX,XX @@ arm_gt_tval_write(int timer, uint64_t value) "gt_tval_write: timer %d value 0x%"
132
fprintf(stderr, "write_kvmstate_to_list failed\n");
187
arm_gt_ctl_write(int timer, uint64_t value) "gt_ctl_write: timer %d value 0x%" PRIx64
133
abort();
188
arm_gt_imask_toggle(int timer) "gt_ctl_write: timer %d IMASK toggle"
134
}
189
arm_gt_cntvoff_write(uint64_t value) "gt_cntvoff_write: value 0x%" PRIx64
135
+ /*
190
+arm_gt_cntpoff_write(uint64_t value) "gt_cntpoff_write: value 0x%" PRIx64
136
+ * Sync the reset values also into the CPUState. This is necessary
191
arm_gt_update_irq(int timer, int irqstate) "gt_update_irq: timer %d irqstate %d"
137
+ * because the next thing we do will be a kvm_arch_put_registers()
192
138
+ * which will update the list values from the CPUState before copying
193
# kvm.c
139
+ * the list values back to KVM. It's OK to ignore failure returns here
140
+ * for the same reason we do so in kvm_arch_get_registers().
141
+ */
142
+ write_list_to_cpustate(cpu);
143
}
144
145
/*
146
diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c
147
index XXXXXXX..XXXXXXX 100644
148
--- a/target/arm/kvm32.c
149
+++ b/target/arm/kvm32.c
150
@@ -XXX,XX +XXX,XX @@ int kvm_arch_put_registers(CPUState *cs, int level)
151
return ret;
152
}
153
154
- /* Note that we do not call write_cpustate_to_list()
155
- * here, so we are only writing the tuple list back to
156
- * KVM. This is safe because nothing can change the
157
- * CPUARMState cp15 fields (in particular gdb accesses cannot)
158
- * and so there are no changes to sync. In fact syncing would
159
- * be wrong at this point: for a constant register where TCG and
160
- * KVM disagree about its value, the preceding write_list_to_cpustate()
161
- * would not have had any effect on the CPUARMState value (since the
162
- * register is read-only), and a write_cpustate_to_list() here would
163
- * then try to write the TCG value back into KVM -- this would either
164
- * fail or incorrectly change the value the guest sees.
165
- *
166
- * If we ever want to allow the user to modify cp15 registers via
167
- * the gdb stub, we would need to be more clever here (for instance
168
- * tracking the set of registers kvm_arch_get_registers() successfully
169
- * managed to update the CPUARMState with, and only allowing those
170
- * to be written back up into the kernel).
171
- */
172
+ write_cpustate_to_list(cpu, true);
173
+
174
if (!write_list_to_kvmstate(cpu, level)) {
175
return EINVAL;
176
}
177
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
178
index XXXXXXX..XXXXXXX 100644
179
--- a/target/arm/kvm64.c
180
+++ b/target/arm/kvm64.c
181
@@ -XXX,XX +XXX,XX @@ int kvm_arch_put_registers(CPUState *cs, int level)
182
return ret;
183
}
184
185
+ write_cpustate_to_list(cpu, true);
186
+
187
if (!write_list_to_kvmstate(cpu, level)) {
188
return EINVAL;
189
}
190
diff --git a/target/arm/machine.c b/target/arm/machine.c
191
index XXXXXXX..XXXXXXX 100644
192
--- a/target/arm/machine.c
193
+++ b/target/arm/machine.c
194
@@ -XXX,XX +XXX,XX @@ static int cpu_pre_save(void *opaque)
195
abort();
196
}
197
} else {
198
- if (!write_cpustate_to_list(cpu)) {
199
+ if (!write_cpustate_to_list(cpu, false)) {
200
/* This should never fail. */
201
abort();
202
}
203
--
194
--
204
2.20.1
195
2.34.1
205
206
diff view generated by jsdifflib
1
Rule R_CQRV says that if two pending interrupts have the same
1
Enable all FEAT_ECV features on the 'max' CPU.
2
group priority then ties are broken by looking at the subpriority.
3
We had a comment describing this but had forgotten to actually
4
implement the subpriority comparison. Correct the omission.
5
6
(The further tie break rules of "lowest exception number" and
7
"secure before non-secure" are handled implicitly by the order
8
in which we iterate through the exceptions in the loops.)
9
2
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20190430131439.25251-2-peter.maydell@linaro.org
6
Message-id: 20240301183219.2424889-9-peter.maydell@linaro.org
13
---
7
---
14
hw/intc/armv7m_nvic.c | 9 +++++++--
8
docs/system/arm/emulation.rst | 1 +
15
1 file changed, 7 insertions(+), 2 deletions(-)
9
target/arm/tcg/cpu64.c | 1 +
10
2 files changed, 2 insertions(+)
16
11
17
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
12
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
18
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/intc/armv7m_nvic.c
14
--- a/docs/system/arm/emulation.rst
20
+++ b/hw/intc/armv7m_nvic.c
15
+++ b/docs/system/arm/emulation.rst
21
@@ -XXX,XX +XXX,XX @@ static void nvic_recompute_state_secure(NVICState *s)
16
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
22
int active_prio = NVIC_NOEXC_PRIO;
17
- FEAT_DotProd (Advanced SIMD dot product instructions)
23
int pend_irq = 0;
18
- FEAT_DoubleFault (Double Fault Extension)
24
bool pending_is_s_banked = false;
19
- FEAT_E0PD (Preventing EL0 access to halves of address maps)
25
+ int pend_subprio = 0;
20
+- FEAT_ECV (Enhanced Counter Virtualization)
26
21
- FEAT_EPAC (Enhanced pointer authentication)
27
/* R_CQRV: precedence is by:
22
- FEAT_ETS (Enhanced Translation Synchronization)
28
* - lowest group priority; if both the same then
23
- FEAT_EVT (Enhanced Virtualization Traps)
29
@@ -XXX,XX +XXX,XX @@ static void nvic_recompute_state_secure(NVICState *s)
24
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
30
for (i = 1; i < s->num_irq; i++) {
25
index XXXXXXX..XXXXXXX 100644
31
for (bank = M_REG_S; bank >= M_REG_NS; bank--) {
26
--- a/target/arm/tcg/cpu64.c
32
VecInfo *vec;
27
+++ b/target/arm/tcg/cpu64.c
33
- int prio;
28
@@ -XXX,XX +XXX,XX @@ void aarch64_max_tcg_initfn(Object *obj)
34
+ int prio, subprio;
29
t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN64_2, 2); /* 64k stage2 supported */
35
bool targets_secure;
30
t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN4_2, 2); /* 4k stage2 supported */
36
31
t = FIELD_DP64(t, ID_AA64MMFR0, FGT, 1); /* FEAT_FGT */
37
if (bank == M_REG_S) {
32
+ t = FIELD_DP64(t, ID_AA64MMFR0, ECV, 2); /* FEAT_ECV */
38
@@ -XXX,XX +XXX,XX @@ static void nvic_recompute_state_secure(NVICState *s)
33
cpu->isar.id_aa64mmfr0 = t;
39
}
34
40
35
t = cpu->isar.id_aa64mmfr1;
41
prio = exc_group_prio(s, vec->prio, targets_secure);
42
- if (vec->enabled && vec->pending && prio < pend_prio) {
43
+ subprio = vec->prio & ~nvic_gprio_mask(s, targets_secure);
44
+ if (vec->enabled && vec->pending &&
45
+ ((prio < pend_prio) ||
46
+ (prio == pend_prio && prio >= 0 && subprio < pend_subprio))) {
47
pend_prio = prio;
48
+ pend_subprio = subprio;
49
pend_irq = i;
50
pending_is_s_banked = (bank == M_REG_S);
51
}
52
--
36
--
53
2.20.1
37
2.34.1
54
38
55
39
diff view generated by jsdifflib
1
From: Cao Jiaxi <driver1998@foxmail.com>
1
From: Inès Varhol <ines.varhol@telecom-paris.fr>
2
2
3
Windows ARM64 uses LLP64 model, which breaks current assumptions.
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: Cao Jiaxi <driver1998@foxmail.com>
13
Difference with the real GPIOs :
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
- Alternate Function and Analog mode aren't implemented :
7
Reviewed-by: Thomas Huth <thuth@redhat.com>
15
pins in AF/Analog behave like pins in input mode
8
Message-id: 20190503003707.10185-1-driver1998@foxmail.com
16
- floating pins stay at their last value
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
17
- register IDR reset values differ from the real one :
10
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
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
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
31
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
32
---
13
util/cacheinfo.c | 2 +-
33
MAINTAINERS | 1 +
14
1 file changed, 1 insertion(+), 1 deletion(-)
34
docs/system/arm/b-l475e-iot01a.rst | 2 +-
35
include/hw/gpio/stm32l4x5_gpio.h | 70 +++++
36
hw/gpio/stm32l4x5_gpio.c | 477 +++++++++++++++++++++++++++++
37
hw/gpio/Kconfig | 3 +
38
hw/gpio/meson.build | 1 +
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
15
43
16
diff --git a/util/cacheinfo.c b/util/cacheinfo.c
44
diff --git a/MAINTAINERS b/MAINTAINERS
17
index XXXXXXX..XXXXXXX 100644
45
index XXXXXXX..XXXXXXX 100644
18
--- a/util/cacheinfo.c
46
--- a/MAINTAINERS
19
+++ b/util/cacheinfo.c
47
+++ b/MAINTAINERS
20
@@ -XXX,XX +XXX,XX @@ static void sys_cache_info(int *isize, int *dsize)
48
@@ -XXX,XX +XXX,XX @@ F: hw/arm/stm32l4x5_soc.c
21
static void arch_cache_info(int *isize, int *dsize)
49
F: hw/misc/stm32l4x5_exti.c
22
{
50
F: hw/misc/stm32l4x5_syscfg.c
23
if (*isize == 0 || *dsize == 0) {
51
F: hw/misc/stm32l4x5_rcc.c
24
- unsigned long ctr;
52
+F: hw/gpio/stm32l4x5_gpio.c
25
+ uint64_t ctr;
53
F: include/hw/*/stm32l4x5_*.h
26
54
27
/* The real cache geometry is in CCSIDR_EL1/CLIDR_EL1/CSSELR_EL1,
55
B-L475E-IOT01A IoT Node
28
but (at least under Linux) these are marked protected by the
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
77
new file mode 100644
78
index XXXXXXX..XXXXXXX
79
--- /dev/null
80
+++ b/include/hw/gpio/stm32l4x5_gpio.h
81
@@ -XXX,XX +XXX,XX @@
82
+/*
83
+ * STM32L4x5 GPIO (General Purpose Input/Ouput)
84
+ *
85
+ * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
86
+ * Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
87
+ *
88
+ * SPDX-License-Identifier: GPL-2.0-or-later
89
+ *
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.
92
+ */
93
+
94
+/*
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
102
+
103
+#include "hw/sysbus.h"
104
+#include "qom/object.h"
105
+
106
+#define TYPE_STM32L4X5_GPIO "stm32l4x5-gpio"
107
+OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5GpioState, STM32L4X5_GPIO)
108
+
109
+#define GPIO_NUM_PINS 16
110
+
111
+struct Stm32l4x5GpioState {
112
+ SysBusDevice parent_obj;
113
+
114
+ MemoryRegion mmio;
115
+
116
+ /* GPIO registers */
117
+ uint32_t moder;
118
+ uint32_t otyper;
119
+ uint32_t ospeedr;
120
+ uint32_t pupdr;
121
+ uint32_t idr;
122
+ uint32_t odr;
123
+ uint32_t lckr;
124
+ uint32_t afrl;
125
+ uint32_t afrh;
126
+ uint32_t ascr;
127
+
128
+ /* GPIO registers reset values */
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
+};
150
+
151
+#endif
152
diff --git a/hw/gpio/stm32l4x5_gpio.c b/hw/gpio/stm32l4x5_gpio.c
153
new file mode 100644
154
index XXXXXXX..XXXXXXX
155
--- /dev/null
156
+++ b/hw/gpio/stm32l4x5_gpio.c
157
@@ -XXX,XX +XXX,XX @@
158
+/*
159
+ * STM32L4x5 GPIO (General Purpose Input/Ouput)
160
+ *
161
+ * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
162
+ * Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
163
+ *
164
+ * SPDX-License-Identifier: GPL-2.0-or-later
165
+ *
166
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
167
+ * See the COPYING file in the top-level directory.
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
174
+ */
175
+
176
+#include "qemu/osdep.h"
177
+#include "qemu/log.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"
185
+#include "trace.h"
186
+
187
+#define GPIO_MODER 0x00
188
+#define GPIO_OTYPER 0x04
189
+#define GPIO_OSPEEDR 0x08
190
+#define GPIO_PUPDR 0x0C
191
+#define GPIO_IDR 0x10
192
+#define GPIO_ODR 0x14
193
+#define GPIO_BSRR 0x18
194
+#define GPIO_LCKR 0x1C
195
+#define GPIO_AFRL 0x20
196
+#define GPIO_AFRH 0x24
197
+#define GPIO_BRR 0x28
198
+#define GPIO_ASCR 0x2C
199
+
200
+/* 0b11111111_11111111_00000000_00000000 */
201
+#define RESERVED_BITS_MASK 0xFFFF0000
202
+
203
+static void update_gpio_idr(Stm32l4x5GpioState *s);
204
+
205
+static bool is_pull_up(Stm32l4x5GpioState *s, unsigned pin)
206
+{
207
+ return extract32(s->pupdr, 2 * pin, 2) == 1;
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:
520
+ return 0;
521
+ case GPIO_LCKR:
522
+ return s->lckr;
523
+ case GPIO_AFRL:
524
+ return s->afrl;
525
+ case GPIO_AFRH:
526
+ return s->afrh;
527
+ case GPIO_BRR:
528
+ return 0;
529
+ case GPIO_ASCR:
530
+ return s->ascr;
531
+ default:
532
+ qemu_log_mask(LOG_GUEST_ERROR,
533
+ "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
534
+ return 0;
535
+ }
536
+}
537
+
538
+static const MemoryRegionOps stm32l4x5_gpio_ops = {
539
+ .read = stm32l4x5_gpio_read,
540
+ .write = stm32l4x5_gpio_write,
541
+ .endianness = DEVICE_NATIVE_ENDIAN,
542
+ .impl = {
543
+ .min_access_size = 4,
544
+ .max_access_size = 4,
545
+ .unaligned = false,
546
+ },
547
+ .valid = {
548
+ .min_access_size = 4,
549
+ .max_access_size = 4,
550
+ .unaligned = false,
551
+ },
552
+};
553
+
554
+static void stm32l4x5_gpio_init(Object *obj)
555
+{
556
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
557
+
558
+ memory_region_init_io(&s->mmio, obj, &stm32l4x5_gpio_ops, s,
559
+ TYPE_STM32L4X5_GPIO, 0x400);
560
+
561
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
562
+
563
+ qdev_init_gpio_out(DEVICE(obj), s->pin, GPIO_NUM_PINS);
564
+ qdev_init_gpio_in(DEVICE(obj), stm32l4x5_gpio_set, GPIO_NUM_PINS);
565
+
566
+ s->clk = qdev_init_clock_in(DEVICE(s), "clk", NULL, s, 0);
567
+
568
+ object_property_add(obj, "disconnected-pins", "uint16",
569
+ disconnected_pins_get, disconnected_pins_set,
570
+ NULL, &s->disconnected_pins);
571
+ object_property_add(obj, "clock-freq-hz", "uint32",
572
+ clock_freq_get, NULL, NULL, NULL);
573
+}
574
+
575
+static void stm32l4x5_gpio_realize(DeviceState *dev, Error **errp)
576
+{
577
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(dev);
578
+ if (!clock_has_source(s->clk)) {
579
+ error_setg(errp, "GPIO: clk input must be connected");
580
+ return;
581
+ }
582
+}
583
+
584
+static const VMStateDescription vmstate_stm32l4x5_gpio = {
585
+ .name = TYPE_STM32L4X5_GPIO,
586
+ .version_id = 1,
587
+ .minimum_version_id = 1,
588
+ .fields = (VMStateField[]){
589
+ VMSTATE_UINT32(moder, Stm32l4x5GpioState),
590
+ VMSTATE_UINT32(otyper, Stm32l4x5GpioState),
591
+ VMSTATE_UINT32(ospeedr, Stm32l4x5GpioState),
592
+ VMSTATE_UINT32(pupdr, Stm32l4x5GpioState),
593
+ VMSTATE_UINT32(idr, Stm32l4x5GpioState),
594
+ VMSTATE_UINT32(odr, Stm32l4x5GpioState),
595
+ VMSTATE_UINT32(lckr, Stm32l4x5GpioState),
596
+ VMSTATE_UINT32(afrl, Stm32l4x5GpioState),
597
+ VMSTATE_UINT32(afrh, Stm32l4x5GpioState),
598
+ VMSTATE_UINT32(ascr, Stm32l4x5GpioState),
599
+ VMSTATE_UINT16(disconnected_pins, Stm32l4x5GpioState),
600
+ VMSTATE_UINT16(pins_connected_high, Stm32l4x5GpioState),
601
+ VMSTATE_END_OF_LIST()
602
+ }
603
+};
604
+
605
+static Property stm32l4x5_gpio_properties[] = {
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),
610
+ DEFINE_PROP_END_OF_LIST(),
611
+};
612
+
613
+static void stm32l4x5_gpio_class_init(ObjectClass *klass, void *data)
614
+{
615
+ DeviceClass *dc = DEVICE_CLASS(klass);
616
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
617
+
618
+ device_class_set_props(dc, stm32l4x5_gpio_properties);
619
+ dc->vmsd = &vmstate_stm32l4x5_gpio;
620
+ dc->realize = stm32l4x5_gpio_realize;
621
+ rc->phases.hold = stm32l4x5_gpio_reset_hold;
622
+}
623
+
624
+static const TypeInfo stm32l4x5_gpio_types[] = {
625
+ {
626
+ .name = TYPE_STM32L4X5_GPIO,
627
+ .parent = TYPE_SYS_BUS_DEVICE,
628
+ .instance_size = sizeof(Stm32l4x5GpioState),
629
+ .instance_init = stm32l4x5_gpio_init,
630
+ .class_init = stm32l4x5_gpio_class_init,
631
+ },
632
+};
633
+
634
+DEFINE_TYPES(stm32l4x5_gpio_types)
635
diff --git a/hw/gpio/Kconfig b/hw/gpio/Kconfig
636
index XXXXXXX..XXXXXXX 100644
637
--- a/hw/gpio/Kconfig
638
+++ b/hw/gpio/Kconfig
639
@@ -XXX,XX +XXX,XX @@ config GPIO_PWR
640
641
config SIFIVE_GPIO
642
bool
643
+
644
+config STM32L4X5_GPIO
645
+ bool
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"
29
--
671
--
30
2.20.1
672
2.34.1
31
673
32
674
diff view generated by jsdifflib
1
From: Markus Armbruster <armbru@redhat.com>
1
From: Inès Varhol <ines.varhol@telecom-paris.fr>
2
2
3
Factored out of pc_system_firmware_init() so the next commit can reuse
3
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
4
it in hw/arm/virt.c.
4
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
5
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Signed-off-by: Markus Armbruster <armbru@redhat.com>
6
Acked-by: Alistair Francis <alistair.francis@wdc.com>
7
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
7
Message-id: 20240305210444.310665-3-ines.varhol@telecom-paris.fr
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Message-id: 20190416091348.26075-3-armbru@redhat.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
9
---
12
include/hw/block/flash.h | 1 +
10
include/hw/arm/stm32l4x5_soc.h | 2 +
13
hw/block/pflash_cfi01.c | 28 ++++++++++++++++++++++++++++
11
include/hw/gpio/stm32l4x5_gpio.h | 1 +
14
hw/i386/pc_sysfw.c | 16 ++--------------
12
include/hw/misc/stm32l4x5_syscfg.h | 3 +-
15
3 files changed, 31 insertions(+), 14 deletions(-)
13
hw/arm/stm32l4x5_soc.c | 71 +++++++++++++++++++++++-------
16
14
hw/misc/stm32l4x5_syscfg.c | 1 +
17
diff --git a/include/hw/block/flash.h b/include/hw/block/flash.h
15
hw/arm/Kconfig | 3 +-
18
index XXXXXXX..XXXXXXX 100644
16
6 files changed, 63 insertions(+), 18 deletions(-)
19
--- a/include/hw/block/flash.h
17
20
+++ b/include/hw/block/flash.h
18
diff --git a/include/hw/arm/stm32l4x5_soc.h b/include/hw/arm/stm32l4x5_soc.h
21
@@ -XXX,XX +XXX,XX @@ PFlashCFI01 *pflash_cfi01_register(hwaddr base,
19
index XXXXXXX..XXXXXXX 100644
22
int be);
20
--- a/include/hw/arm/stm32l4x5_soc.h
23
BlockBackend *pflash_cfi01_get_blk(PFlashCFI01 *fl);
21
+++ b/include/hw/arm/stm32l4x5_soc.h
24
MemoryRegion *pflash_cfi01_get_memory(PFlashCFI01 *fl);
22
@@ -XXX,XX +XXX,XX @@
25
+void pflash_cfi01_legacy_drive(PFlashCFI01 *dev, DriveInfo *dinfo);
23
#include "hw/misc/stm32l4x5_syscfg.h"
26
24
#include "hw/misc/stm32l4x5_exti.h"
27
/* pflash_cfi02.c */
25
#include "hw/misc/stm32l4x5_rcc.h"
28
26
+#include "hw/gpio/stm32l4x5_gpio.h"
29
diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c
27
#include "qom/object.h"
30
index XXXXXXX..XXXXXXX 100644
28
31
--- a/hw/block/pflash_cfi01.c
29
#define TYPE_STM32L4X5_SOC "stm32l4x5-soc"
32
+++ b/hw/block/pflash_cfi01.c
30
@@ -XXX,XX +XXX,XX @@ struct Stm32l4x5SocState {
33
@@ -XXX,XX +XXX,XX @@
31
OrIRQState exti_or_gates[NUM_EXTI_OR_GATES];
34
#include "qapi/error.h"
32
Stm32l4x5SyscfgState syscfg;
35
#include "qemu/timer.h"
33
Stm32l4x5RccState rcc;
36
#include "qemu/bitops.h"
34
+ Stm32l4x5GpioState gpio[NUM_GPIOS];
37
+#include "qemu/error-report.h"
35
38
#include "qemu/host-utils.h"
36
MemoryRegion sram1;
39
#include "qemu/log.h"
37
MemoryRegion sram2;
40
+#include "qemu/option.h"
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 @@
55
41
#include "hw/sysbus.h"
56
#include "hw/sysbus.h"
42
+#include "sysemu/blockdev.h"
57
#include "qom/object.h"
58
+#include "hw/gpio/stm32l4x5_gpio.h"
59
60
#define TYPE_STM32L4X5_SYSCFG "stm32l4x5-syscfg"
61
OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5SyscfgState, STM32L4X5_SYSCFG)
62
63
-#define NUM_GPIOS 8
64
-#define GPIO_NUM_PINS 16
65
#define SYSCFG_NUM_EXTICR 4
66
67
struct Stm32l4x5SyscfgState {
68
diff --git a/hw/arm/stm32l4x5_soc.c b/hw/arm/stm32l4x5_soc.c
69
index XXXXXXX..XXXXXXX 100644
70
--- a/hw/arm/stm32l4x5_soc.c
71
+++ b/hw/arm/stm32l4x5_soc.c
72
@@ -XXX,XX +XXX,XX @@
43
#include "sysemu/sysemu.h"
73
#include "sysemu/sysemu.h"
44
#include "trace.h"
74
#include "hw/or-irq.h"
45
75
#include "hw/arm/stm32l4x5_soc.h"
46
@@ -XXX,XX +XXX,XX @@ MemoryRegion *pflash_cfi01_get_memory(PFlashCFI01 *fl)
76
+#include "hw/gpio/stm32l4x5_gpio.h"
47
return &fl->mem;
77
#include "hw/qdev-clock.h"
78
#include "hw/misc/unimp.h"
79
80
@@ -XXX,XX +XXX,XX @@ static const int exti_or_gate1_lines_in[EXTI_OR_GATE1_NUM_LINES_IN] = {
81
16, 35, 36, 37, 38,
82
};
83
84
+static const struct {
85
+ uint32_t addr;
86
+ uint32_t moder_reset;
87
+ uint32_t ospeedr_reset;
88
+ uint32_t pupdr_reset;
89
+} stm32l4x5_gpio_cfg[NUM_GPIOS] = {
90
+ { 0x48000000, 0xABFFFFFF, 0x0C000000, 0x64000000 },
91
+ { 0x48000400, 0xFFFFFEBF, 0x00000000, 0x00000100 },
92
+ { 0x48000800, 0xFFFFFFFF, 0x00000000, 0x00000000 },
93
+ { 0x48000C00, 0xFFFFFFFF, 0x00000000, 0x00000000 },
94
+ { 0x48001000, 0xFFFFFFFF, 0x00000000, 0x00000000 },
95
+ { 0x48001400, 0xFFFFFFFF, 0x00000000, 0x00000000 },
96
+ { 0x48001800, 0xFFFFFFFF, 0x00000000, 0x00000000 },
97
+ { 0x48001C00, 0x0000000F, 0x00000000, 0x00000000 },
98
+};
99
+
100
static void stm32l4x5_soc_initfn(Object *obj)
101
{
102
Stm32l4x5SocState *s = STM32L4X5_SOC(obj);
103
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_initfn(Object *obj)
104
}
105
object_initialize_child(obj, "syscfg", &s->syscfg, TYPE_STM32L4X5_SYSCFG);
106
object_initialize_child(obj, "rcc", &s->rcc, TYPE_STM32L4X5_RCC);
107
+
108
+ for (unsigned i = 0; i < NUM_GPIOS; i++) {
109
+ g_autofree char *name = g_strdup_printf("gpio%c", 'a' + i);
110
+ object_initialize_child(obj, name, &s->gpio[i], TYPE_STM32L4X5_GPIO);
111
+ }
48
}
112
}
49
113
50
+/*
114
static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
51
+ * Handle -drive if=pflash for machines that use properties.
115
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
52
+ * If @dinfo is null, do nothing.
116
Stm32l4x5SocState *s = STM32L4X5_SOC(dev_soc);
53
+ * Else if @fl's property "drive" is already set, fatal error.
117
const Stm32l4x5SocClass *sc = STM32L4X5_SOC_GET_CLASS(dev_soc);
54
+ * Else set it to the BlockBackend with @dinfo.
118
MemoryRegion *system_memory = get_system_memory();
55
+ */
119
- DeviceState *armv7m;
56
+void pflash_cfi01_legacy_drive(PFlashCFI01 *fl, DriveInfo *dinfo)
120
+ DeviceState *armv7m, *dev;
57
+{
121
SysBusDevice *busdev;
58
+ Location loc;
122
+ uint32_t pin_index;
59
+
123
60
+ if (!dinfo) {
124
if (!memory_region_init_rom(&s->flash, OBJECT(dev_soc), "flash",
61
+ return;
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);
62
+ }
150
+ }
63
+
151
+
64
+ loc_push_none(&loc);
152
/* System configuration controller */
65
+ qemu_opts_loc_restore(dinfo->opts);
153
busdev = SYS_BUS_DEVICE(&s->syscfg);
66
+ if (fl->blk) {
154
if (!sysbus_realize(busdev, errp)) {
67
+ error_report("clashes with -machine");
155
return;
68
+ exit(1);
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
+ }
69
+ }
171
+ }
70
+ qdev_prop_set_drive(DEVICE(fl), "drive",
172
71
+ blk_by_legacy_dinfo(dinfo), &error_fatal);
173
/* EXTI device */
72
+ loc_pop(&loc);
174
busdev = SYS_BUS_DEVICE(&s->exti);
73
+}
175
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
74
+
176
}
75
static void postload_update_cb(void *opaque, int running, RunState state)
177
}
76
{
178
77
PFlashCFI01 *pfl = opaque;
179
- for (unsigned i = 0; i < 16; i++) {
78
diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
180
+ for (unsigned i = 0; i < GPIO_NUM_PINS; i++) {
79
index XXXXXXX..XXXXXXX 100644
181
qdev_connect_gpio_out(DEVICE(&s->syscfg), i,
80
--- a/hw/i386/pc_sysfw.c
182
qdev_get_gpio_in(DEVICE(&s->exti), i));
81
+++ b/hw/i386/pc_sysfw.c
183
}
82
@@ -XXX,XX +XXX,XX @@ void pc_system_firmware_init(PCMachineState *pcms,
184
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
83
{
185
/* RESERVED: 0x40024400, 0x7FDBC00 */
84
PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
186
85
int i;
187
/* AHB2 BUS */
86
- DriveInfo *pflash_drv;
188
- create_unimplemented_device("GPIOA", 0x48000000, 0x400);
87
BlockBackend *pflash_blk[ARRAY_SIZE(pcms->flash)];
189
- create_unimplemented_device("GPIOB", 0x48000400, 0x400);
88
- Location loc;
190
- create_unimplemented_device("GPIOC", 0x48000800, 0x400);
89
191
- create_unimplemented_device("GPIOD", 0x48000C00, 0x400);
90
if (!pcmc->pci_enabled) {
192
- create_unimplemented_device("GPIOE", 0x48001000, 0x400);
91
old_pc_system_rom_init(rom_memory, true);
193
- create_unimplemented_device("GPIOF", 0x48001400, 0x400);
92
@@ -XXX,XX +XXX,XX @@ void pc_system_firmware_init(PCMachineState *pcms,
194
- create_unimplemented_device("GPIOG", 0x48001800, 0x400);
93
195
- create_unimplemented_device("GPIOH", 0x48001C00, 0x400);
94
/* Map legacy -drive if=pflash to machine properties */
196
/* RESERVED: 0x48002000, 0x7FDBC00 */
95
for (i = 0; i < ARRAY_SIZE(pcms->flash); i++) {
197
create_unimplemented_device("OTG_FS", 0x50000000, 0x40000);
96
- pflash_drv = drive_get(IF_PFLASH, 0, i);
198
create_unimplemented_device("ADC", 0x50040000, 0x400);
97
- if (pflash_drv) {
199
diff --git a/hw/misc/stm32l4x5_syscfg.c b/hw/misc/stm32l4x5_syscfg.c
98
- loc_push_none(&loc);
200
index XXXXXXX..XXXXXXX 100644
99
- qemu_opts_loc_restore(pflash_drv->opts);
201
--- a/hw/misc/stm32l4x5_syscfg.c
100
- if (pflash_cfi01_get_blk(pcms->flash[i])) {
202
+++ b/hw/misc/stm32l4x5_syscfg.c
101
- error_report("clashes with -machine");
203
@@ -XXX,XX +XXX,XX @@
102
- exit(1);
204
#include "hw/irq.h"
103
- }
205
#include "migration/vmstate.h"
104
- qdev_prop_set_drive(DEVICE(pcms->flash[i]), "drive",
206
#include "hw/misc/stm32l4x5_syscfg.h"
105
- blk_by_legacy_dinfo(pflash_drv), &error_fatal);
207
+#include "hw/gpio/stm32l4x5_gpio.h"
106
- loc_pop(&loc);
208
107
- }
209
#define SYSCFG_MEMRMP 0x00
108
+ pflash_cfi01_legacy_drive(pcms->flash[i],
210
#define SYSCFG_CFGR1 0x04
109
+ drive_get(IF_PFLASH, 0, i));
211
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
110
pflash_blk[i] = pflash_cfi01_get_blk(pcms->flash[i]);
212
index XXXXXXX..XXXXXXX 100644
111
}
213
--- a/hw/arm/Kconfig
112
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
113
--
227
--
114
2.20.1
228
2.34.1
115
229
116
230
diff view generated by jsdifflib
1
From: Cao Jiaxi <driver1998@foxmail.com>
1
From: Inès Varhol <ines.varhol@telecom-paris.fr>
2
2
3
The win2qemu[] is supposed to be the conversion table to convert between
3
The testcase contains :
4
STORAGE_BUS_TYPE in Windows SDK and GuestDiskBusType in qga.
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.
5
24
6
But it was incorrectly written that it forces to set a GuestDiskBusType
25
Acked-by: Thomas Huth <thuth@redhat.com>
7
value to STORAGE_BUS_TYPE, which generates an enum conversion warning in clang.
26
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
8
27
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
9
Suggested-by: Eric Blake <eblake@redhat.com>
28
Message-id: 20240305210444.310665-4-ines.varhol@telecom-paris.fr
10
Signed-off-by: Cao Jiaxi <driver1998@foxmail.com>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Thomas Huth <thuth@redhat.com>
13
Message-id: 20190503003650.10137-1-driver1998@foxmail.com
14
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
15
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
29
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
30
---
18
qga/commands-win32.c | 2 +-
31
tests/qtest/stm32l4x5_gpio-test.c | 551 ++++++++++++++++++++++++++++++
19
1 file changed, 1 insertion(+), 1 deletion(-)
32
tests/qtest/meson.build | 3 +-
33
2 files changed, 553 insertions(+), 1 deletion(-)
34
create mode 100644 tests/qtest/stm32l4x5_gpio-test.c
20
35
21
diff --git a/qga/commands-win32.c b/qga/commands-win32.c
36
diff --git a/tests/qtest/stm32l4x5_gpio-test.c b/tests/qtest/stm32l4x5_gpio-test.c
37
new file mode 100644
38
index XXXXXXX..XXXXXXX
39
--- /dev/null
40
+++ b/tests/qtest/stm32l4x5_gpio-test.c
41
@@ -XXX,XX +XXX,XX @@
42
+/*
43
+ * QTest testcase for STM32L4x5_GPIO
44
+ *
45
+ * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
46
+ * Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
47
+ *
48
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
49
+ * See the COPYING file in the top-level directory.
50
+ */
51
+
52
+#include "qemu/osdep.h"
53
+#include "libqtest-single.h"
54
+
55
+#define GPIO_BASE_ADDR 0x48000000
56
+#define GPIO_SIZE 0x400
57
+#define NUM_GPIOS 8
58
+#define NUM_GPIO_PINS 16
59
+
60
+#define GPIO_A 0x48000000
61
+#define GPIO_B 0x48000400
62
+#define GPIO_C 0x48000800
63
+#define GPIO_D 0x48000C00
64
+#define GPIO_E 0x48001000
65
+#define GPIO_F 0x48001400
66
+#define GPIO_G 0x48001800
67
+#define GPIO_H 0x48001C00
68
+
69
+#define MODER 0x00
70
+#define OTYPER 0x04
71
+#define PUPDR 0x0C
72
+#define IDR 0x10
73
+#define ODR 0x14
74
+#define BSRR 0x18
75
+#define BRR 0x28
76
+
77
+#define MODER_INPUT 0
78
+#define MODER_OUTPUT 1
79
+
80
+#define PUPDR_NONE 0
81
+#define PUPDR_PULLUP 1
82
+#define PUPDR_PULLDOWN 2
83
+
84
+#define OTYPER_PUSH_PULL 0
85
+#define OTYPER_OPEN_DRAIN 1
86
+
87
+const uint32_t moder_reset[NUM_GPIOS] = {
88
+ 0xABFFFFFF,
89
+ 0xFFFFFEBF,
90
+ 0xFFFFFFFF,
91
+ 0xFFFFFFFF,
92
+ 0xFFFFFFFF,
93
+ 0xFFFFFFFF,
94
+ 0xFFFFFFFF,
95
+ 0x0000000F
96
+};
97
+
98
+const uint32_t pupdr_reset[NUM_GPIOS] = {
99
+ 0x64000000,
100
+ 0x00000100,
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)];
194
+ }
195
+ return 0x0;
196
+}
197
+
198
+static void system_reset(void)
199
+{
200
+ QDict *r;
201
+ r = qtest_qmp(global_qtest, "{'execute': 'system_reset'}");
202
+ g_assert_false(qdict_haskey(r, "error"));
203
+ qobject_unref(r);
204
+}
205
+
206
+static void test_idr_reset_value(void)
207
+{
208
+ /*
209
+ * Checks that the values in MODER, OTYPER, PUPDR and ODR
210
+ * after reset are correct, and that the value in IDR is
211
+ * coherent.
212
+ * Since AF and analog modes aren't implemented, IDR reset
213
+ * values aren't the same as with a real board.
214
+ *
215
+ * Register IDR contains the actual values of all GPIO pins.
216
+ * Its value depends on the pins' configuration
217
+ * (intput/output/analog : register MODER, push-pull/open-drain :
218
+ * register OTYPER, pull-up/pull-down/none : register PUPDR)
219
+ * and on the values stored in register ODR
220
+ * (in case the pin is in output mode).
221
+ */
222
+
223
+ gpio_writel(GPIO_A, MODER, 0xDEADBEEF);
224
+ gpio_writel(GPIO_A, ODR, 0xDEADBEEF);
225
+ gpio_writel(GPIO_A, OTYPER, 0xDEADBEEF);
226
+ gpio_writel(GPIO_A, PUPDR, 0xDEADBEEF);
227
+
228
+ gpio_writel(GPIO_B, MODER, 0xDEADBEEF);
229
+ gpio_writel(GPIO_B, ODR, 0xDEADBEEF);
230
+ gpio_writel(GPIO_B, OTYPER, 0xDEADBEEF);
231
+ gpio_writel(GPIO_B, PUPDR, 0xDEADBEEF);
232
+
233
+ gpio_writel(GPIO_C, MODER, 0xDEADBEEF);
234
+ gpio_writel(GPIO_C, ODR, 0xDEADBEEF);
235
+ gpio_writel(GPIO_C, OTYPER, 0xDEADBEEF);
236
+ gpio_writel(GPIO_C, PUPDR, 0xDEADBEEF);
237
+
238
+ gpio_writel(GPIO_H, MODER, 0xDEADBEEF);
239
+ gpio_writel(GPIO_H, ODR, 0xDEADBEEF);
240
+ gpio_writel(GPIO_H, OTYPER, 0xDEADBEEF);
241
+ gpio_writel(GPIO_H, PUPDR, 0xDEADBEEF);
242
+
243
+ system_reset();
244
+
245
+ uint32_t moder = gpio_readl(GPIO_A, MODER);
246
+ uint32_t odr = gpio_readl(GPIO_A, ODR);
247
+ uint32_t otyper = gpio_readl(GPIO_A, OTYPER);
248
+ uint32_t pupdr = gpio_readl(GPIO_A, PUPDR);
249
+ uint32_t idr = gpio_readl(GPIO_A, IDR);
250
+ /* 15: AF, 14: AF, 13: AF, 12: Analog ... */
251
+ /* here AF is the same as Analog and Input mode */
252
+ g_assert_cmphex(moder, ==, reset(GPIO_A, MODER));
253
+ g_assert_cmphex(odr, ==, reset(GPIO_A, ODR));
254
+ g_assert_cmphex(otyper, ==, reset(GPIO_A, OTYPER));
255
+ /* 15: pull-up, 14: pull-down, 13: pull-up, 12: neither ... */
256
+ g_assert_cmphex(pupdr, ==, reset(GPIO_A, PUPDR));
257
+ /* 15 : 1, 14: 0, 13: 1, 12 : reset value ... */
258
+ g_assert_cmphex(idr, ==, reset(GPIO_A, IDR));
259
+
260
+ moder = gpio_readl(GPIO_B, MODER);
261
+ odr = gpio_readl(GPIO_B, ODR);
262
+ otyper = gpio_readl(GPIO_B, OTYPER);
263
+ pupdr = gpio_readl(GPIO_B, PUPDR);
264
+ idr = gpio_readl(GPIO_B, IDR);
265
+ /* ... 5: Analog, 4: AF, 3: AF, 2: Analog ... */
266
+ /* here AF is the same as Analog and Input mode */
267
+ g_assert_cmphex(moder, ==, reset(GPIO_B, MODER));
268
+ g_assert_cmphex(odr, ==, reset(GPIO_B, ODR));
269
+ g_assert_cmphex(otyper, ==, reset(GPIO_B, OTYPER));
270
+ /* ... 5: neither, 4: pull-up, 3: neither ... */
271
+ g_assert_cmphex(pupdr, ==, reset(GPIO_B, PUPDR));
272
+ /* ... 5 : reset value, 4 : 1, 3 : reset value ... */
273
+ g_assert_cmphex(idr, ==, reset(GPIO_B, IDR));
274
+
275
+ moder = gpio_readl(GPIO_C, MODER);
276
+ odr = gpio_readl(GPIO_C, ODR);
277
+ otyper = gpio_readl(GPIO_C, OTYPER);
278
+ pupdr = gpio_readl(GPIO_C, PUPDR);
279
+ idr = gpio_readl(GPIO_C, IDR);
280
+ /* Analog, same as Input mode*/
281
+ g_assert_cmphex(moder, ==, reset(GPIO_C, MODER));
282
+ g_assert_cmphex(odr, ==, reset(GPIO_C, ODR));
283
+ g_assert_cmphex(otyper, ==, reset(GPIO_C, OTYPER));
284
+ /* no pull-up or pull-down */
285
+ g_assert_cmphex(pupdr, ==, reset(GPIO_C, PUPDR));
286
+ /* reset value */
287
+ g_assert_cmphex(idr, ==, reset(GPIO_C, IDR));
288
+
289
+ moder = gpio_readl(GPIO_H, MODER);
290
+ odr = gpio_readl(GPIO_H, ODR);
291
+ otyper = gpio_readl(GPIO_H, OTYPER);
292
+ pupdr = gpio_readl(GPIO_H, PUPDR);
293
+ idr = gpio_readl(GPIO_H, IDR);
294
+ /* Analog, same as Input mode */
295
+ g_assert_cmphex(moder, ==, reset(GPIO_H, MODER));
296
+ g_assert_cmphex(odr, ==, reset(GPIO_H, ODR));
297
+ g_assert_cmphex(otyper, ==, reset(GPIO_H, OTYPER));
298
+ /* no pull-up or pull-down */
299
+ g_assert_cmphex(pupdr, ==, reset(GPIO_H, PUPDR));
300
+ /* reset value */
301
+ g_assert_cmphex(idr, ==, reset(GPIO_H, IDR));
302
+}
303
+
304
+static void test_gpio_output_mode(const void *data)
305
+{
306
+ /*
307
+ * Checks that setting a bit in ODR sets the corresponding
308
+ * GPIO line high : it should set the right bit in IDR
309
+ * and send an irq to syscfg.
310
+ * Additionally, it checks that values written to ODR
311
+ * when not in output mode are stored and not discarded.
312
+ */
313
+ unsigned int pin = ((uint64_t)data) & 0xF;
314
+ uint32_t gpio = ((uint64_t)data) >> 32;
315
+ unsigned int gpio_id = get_gpio_id(gpio);
316
+
317
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
318
+
319
+ /* Set a bit in ODR and check nothing happens */
320
+ gpio_set_bit(gpio, ODR, pin, 1);
321
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
322
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
323
+
324
+ /* Configure the relevant line as output and check the pin is high */
325
+ gpio_set_2bits(gpio, MODER, pin, MODER_OUTPUT);
326
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) | (1 << pin));
327
+ g_assert_true(get_irq(gpio_id * NUM_GPIO_PINS + pin));
328
+
329
+ /* Reset the bit in ODR and check the pin is low */
330
+ gpio_set_bit(gpio, ODR, pin, 0);
331
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
332
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
333
+
334
+ /* Clean the test */
335
+ gpio_writel(gpio, ODR, reset(gpio, ODR));
336
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
337
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
338
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
339
+}
340
+
341
+static void test_gpio_input_mode(const void *data)
342
+{
343
+ /*
344
+ * Test that setting a line high/low externally sets the
345
+ * corresponding GPIO line high/low : it should set the
346
+ * right bit in IDR and send an irq to syscfg.
347
+ */
348
+ unsigned int pin = ((uint64_t)data) & 0xF;
349
+ uint32_t gpio = ((uint64_t)data) >> 32;
350
+ unsigned int gpio_id = get_gpio_id(gpio);
351
+
352
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
353
+
354
+ /* Configure a line as input, raise it, and check that the pin is high */
355
+ gpio_set_2bits(gpio, MODER, pin, MODER_INPUT);
356
+ gpio_set_irq(gpio, pin, 1);
357
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) | (1 << pin));
358
+ g_assert_true(get_irq(gpio_id * NUM_GPIO_PINS + pin));
359
+
360
+ /* Lower the line and check that the pin is low */
361
+ gpio_set_irq(gpio, pin, 0);
362
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
363
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
364
+
365
+ /* Clean the test */
366
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
367
+ disconnect_all_pins(gpio);
368
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
369
+}
370
+
371
+static void test_pull_up_pull_down(const void *data)
372
+{
373
+ /*
374
+ * Test that a floating pin with pull-up sets the pin
375
+ * high and vice-versa.
376
+ */
377
+ unsigned int pin = ((uint64_t)data) & 0xF;
378
+ uint32_t gpio = ((uint64_t)data) >> 32;
379
+ unsigned int gpio_id = get_gpio_id(gpio);
380
+
381
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
382
+
383
+ /* Configure a line as input with pull-up, check the line is set high */
384
+ gpio_set_2bits(gpio, MODER, pin, MODER_INPUT);
385
+ gpio_set_2bits(gpio, PUPDR, pin, PUPDR_PULLUP);
386
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) | (1 << pin));
387
+ g_assert_true(get_irq(gpio_id * NUM_GPIO_PINS + pin));
388
+
389
+ /* Configure the line with pull-down, check the line is low */
390
+ gpio_set_2bits(gpio, PUPDR, pin, PUPDR_PULLDOWN);
391
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
392
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
393
+
394
+ /* Clean the test */
395
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
396
+ gpio_writel(gpio, PUPDR, reset(gpio, PUPDR));
397
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
398
+}
399
+
400
+static void test_push_pull(const void *data)
401
+{
402
+ /*
403
+ * Test that configuring a line in push-pull output mode
404
+ * disconnects the pin, that the pin can't be set or reset
405
+ * externally afterwards.
406
+ */
407
+ unsigned int pin = ((uint64_t)data) & 0xF;
408
+ uint32_t gpio = ((uint64_t)data) >> 32;
409
+ uint32_t gpio2 = GPIO_BASE_ADDR + (GPIO_H - gpio);
410
+
411
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
412
+
413
+ /* Setting a line high externally, configuring it in push-pull output */
414
+ /* And checking the pin was disconnected */
415
+ gpio_set_irq(gpio, pin, 1);
416
+ gpio_set_2bits(gpio, MODER, pin, MODER_OUTPUT);
417
+ g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
418
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
419
+
420
+ /* Setting a line low externally, configuring it in push-pull output */
421
+ /* And checking the pin was disconnected */
422
+ gpio_set_irq(gpio2, pin, 0);
423
+ gpio_set_bit(gpio2, ODR, pin, 1);
424
+ gpio_set_2bits(gpio2, MODER, pin, MODER_OUTPUT);
425
+ g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF);
426
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==, reset(gpio2, IDR) | (1 << pin));
427
+
428
+ /* Trying to set a push-pull output pin, checking it doesn't work */
429
+ gpio_set_irq(gpio, pin, 1);
430
+ g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
431
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
432
+
433
+ /* Trying to reset a push-pull output pin, checking it doesn't work */
434
+ gpio_set_irq(gpio2, pin, 0);
435
+ g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF);
436
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==, reset(gpio2, IDR) | (1 << pin));
437
+
438
+ /* Clean the test */
439
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
440
+ gpio_writel(gpio2, ODR, reset(gpio2, ODR));
441
+ gpio_writel(gpio2, MODER, reset(gpio2, MODER));
442
+}
443
+
444
+static void test_open_drain(const void *data)
445
+{
446
+ /*
447
+ * Test that configuring a line in open-drain output mode
448
+ * disconnects a pin set high externally and that the pin
449
+ * can't be set high externally while configured in open-drain.
450
+ *
451
+ * However a pin set low externally shouldn't be disconnected,
452
+ * and it can be set low externally when in open-drain mode.
453
+ */
454
+ unsigned int pin = ((uint64_t)data) & 0xF;
455
+ uint32_t gpio = ((uint64_t)data) >> 32;
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
22
index XXXXXXX..XXXXXXX 100644
594
index XXXXXXX..XXXXXXX 100644
23
--- a/qga/commands-win32.c
595
--- a/tests/qtest/meson.build
24
+++ b/qga/commands-win32.c
596
+++ b/tests/qtest/meson.build
25
@@ -XXX,XX +XXX,XX @@ void qmp_guest_file_flush(int64_t handle, Error **errp)
597
@@ -XXX,XX +XXX,XX @@ qtests_aspeed = \
26
598
qtests_stm32l4x5 = \
27
#ifdef CONFIG_QGA_NTDDSCSI
599
['stm32l4x5_exti-test',
28
600
'stm32l4x5_syscfg-test',
29
-static STORAGE_BUS_TYPE win2qemu[] = {
601
- 'stm32l4x5_rcc-test']
30
+static GuestDiskBusType win2qemu[] = {
602
+ 'stm32l4x5_rcc-test',
31
[BusTypeUnknown] = GUEST_DISK_BUS_TYPE_UNKNOWN,
603
+ 'stm32l4x5_gpio-test']
32
[BusTypeScsi] = GUEST_DISK_BUS_TYPE_SCSI,
604
33
[BusTypeAtapi] = GUEST_DISK_BUS_TYPE_IDE,
605
qtests_arm = \
606
(config_all_devices.has_key('CONFIG_MPS2') ? ['sse-timer-test'] : []) + \
34
--
607
--
35
2.20.1
608
2.34.1
36
609
37
610
diff view generated by jsdifflib
1
From: Markus Armbruster <armbru@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The ARM virt machines put firmware in flash memory. To configure it,
3
While the 8-bit input elements are sequential in the input vector,
4
you use -drive if=pflash,unit=0,... and optionally -drive
4
the 32-bit output elements are not sequential in the output matrix.
5
if=pflash,unit=1,...
5
Do not attempt to compute 2 32-bit outputs at the same time.
6
6
7
Why two -drive? This permits setting up one part of the flash memory
7
Cc: qemu-stable@nongnu.org
8
read-only, and the other part read/write. It also makes upgrading
8
Fixes: 23a5e3859f5 ("target/arm: Implement SME integer outer product")
9
firmware on the host easier. Below the hood, we get two separate
9
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2083
10
flash devices, because we were too lazy to improve our flash device
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
models to support sector protection.
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
12
12
Message-id: 20240305163931.242795-1-richard.henderson@linaro.org
13
The problem at hand is to do the same with -blockdev somehow, as one
14
more step towards deprecating -drive.
15
16
We recently solved this problem for x86 PC machines, in commit
17
ebc29e1beab. See the commit message for design rationale.
18
19
This commit solves it for ARM virt basically the same way: new machine
20
properties pflash0, pflash1 forward to the onboard flash devices'
21
properties. Requires creating the onboard devices in the
22
.instance_init() method virt_instance_init(). The existing code to
23
pick up drives defined with -drive if=pflash is replaced by code to
24
desugar into the machine properties.
25
26
There are a few behavioral differences, though:
27
28
* The flash devices are always present (x86: only present if
29
configured)
30
31
* Flash base addresses and sizes are fixed (x86: sizes depend on
32
images, mapped back to back below a fixed address)
33
34
* -bios configures contents of first pflash (x86: -bios configures ROM
35
contents)
36
37
* -bios is rejected when first pflash is also configured with -machine
38
pflash0=... (x86: bios is silently ignored then)
39
40
* -machine pflash1=... does not require -machine pflash0=... (x86: it
41
does).
42
43
The actual code is a bit simpler than for x86 mostly due to the first
44
two differences.
45
46
Before the patch, all the action is in create_flash(), called from the
47
machine's .init() method machvirt_init():
48
49
main()
50
machine_run_board_init()
51
machvirt_init()
52
create_flash()
53
create_one_flash() for flash[0]
54
create
55
configure
56
includes obeying -drive if=pflash,unit=0
57
realize
58
map
59
fall back to -bios
60
create_one_flash() for flash[1]
61
create
62
configure
63
includes obeying -drive if=pflash,unit=1
64
realize
65
map
66
update FDT
67
68
To make the machine properties work, we need to move device creation
69
to its .instance_init() method virt_instance_init().
70
71
Another complication is machvirt_init()'s computation of
72
@firmware_loaded: it predicts what create_flash() will do. Instead of
73
predicting what create_flash()'s replacement virt_firmware_init() will
74
do, I decided to have virt_firmware_init() return what it did.
75
Requires calling it a bit earlier.
76
77
Resulting call tree:
78
79
main()
80
current_machine = object_new()
81
...
82
virt_instance_init()
83
virt_flash_create()
84
virt_flash_create1() for flash[0]
85
create
86
configure: set defaults
87
become child of machine [NEW]
88
add machine prop pflash0 as alias for drive [NEW]
89
virt_flash_create1() for flash[1]
90
create
91
configure: set defaults
92
become child of machine [NEW]
93
add machine prop pflash1 as alias for drive [NEW]
94
for all machine props from the command line: machine_set_property()
95
...
96
property_set_alias() for machine props pflash0, pflash1
97
...
98
set_drive() for cfi.pflash01 prop drive
99
this is how -machine pflash0=... etc set
100
machine_run_board_init(current_machine);
101
virt_firmware_init()
102
pflash_cfi01_legacy_drive()
103
legacy -drive if=pflash,unit=0 and =1 [NEW]
104
virt_flash_map()
105
virt_flash_map1() for flash[0]
106
configure: num-blocks
107
realize
108
map
109
virt_flash_map1() for flash[1]
110
configure: num-blocks
111
realize
112
map
113
fall back to -bios
114
virt_flash_fdt()
115
update FDT
116
117
You have László to thank for making me explain this in detail.
118
119
Signed-off-by: Markus Armbruster <armbru@redhat.com>
120
Acked-by: Laszlo Ersek <lersek@redhat.com>
121
Message-id: 20190416091348.26075-4-armbru@redhat.com
122
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
123
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
124
---
14
---
125
include/hw/arm/virt.h | 2 +
15
target/arm/tcg/sme_helper.c | 77 ++++++++++++++++++-------------
126
hw/arm/virt.c | 202 +++++++++++++++++++++++++++---------------
16
tests/tcg/aarch64/sme-smopa-1.c | 47 +++++++++++++++++++
127
2 files changed, 132 insertions(+), 72 deletions(-)
17
tests/tcg/aarch64/sme-smopa-2.c | 54 ++++++++++++++++++++++
128
18
tests/tcg/aarch64/Makefile.target | 2 +-
129
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
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
130
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
131
--- a/include/hw/arm/virt.h
25
--- a/target/arm/tcg/sme_helper.c
132
+++ b/include/hw/arm/virt.h
26
+++ b/target/arm/tcg/sme_helper.c
133
@@ -XXX,XX +XXX,XX @@
27
@@ -XXX,XX +XXX,XX @@ void HELPER(sme_bfmopa)(void *vza, void *vzn, void *vzm, void *vpn,
134
#include "qemu/notify.h"
135
#include "hw/boards.h"
136
#include "hw/arm/arm.h"
137
+#include "hw/block/flash.h"
138
#include "sysemu/kvm.h"
139
#include "hw/intc/arm_gicv3_common.h"
140
141
@@ -XXX,XX +XXX,XX @@ typedef struct {
142
Notifier machine_done;
143
DeviceState *platform_bus_dev;
144
FWCfgState *fw_cfg;
145
+ PFlashCFI01 *flash[2];
146
bool secure;
147
bool highmem;
148
bool highmem_ecam;
149
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
150
index XXXXXXX..XXXXXXX 100644
151
--- a/hw/arm/virt.c
152
+++ b/hw/arm/virt.c
153
@@ -XXX,XX +XXX,XX @@
154
155
#include "qemu/osdep.h"
156
#include "qemu/units.h"
157
+#include "qemu/option.h"
158
#include "qapi/error.h"
159
#include "hw/sysbus.h"
160
#include "hw/arm/arm.h"
161
@@ -XXX,XX +XXX,XX @@ static void create_virtio_devices(const VirtMachineState *vms, qemu_irq *pic)
162
}
28
}
163
}
29
}
164
30
165
-static void create_one_flash(const char *name, hwaddr flashbase,
31
-typedef uint64_t IMOPFn(uint64_t, uint64_t, uint64_t, uint8_t, bool);
166
- hwaddr flashsize, const char *file,
32
+typedef uint32_t IMOPFn32(uint32_t, uint32_t, uint32_t, uint8_t, bool);
167
- MemoryRegion *sysmem)
33
+static inline void do_imopa_s(uint32_t *za, uint32_t *zn, uint32_t *zm,
168
+#define VIRT_FLASH_SECTOR_SIZE (256 * KiB)
34
+ uint8_t *pn, uint8_t *pm,
169
+
35
+ uint32_t desc, IMOPFn32 *fn)
170
+static PFlashCFI01 *virt_flash_create1(VirtMachineState *vms,
36
+{
171
+ const char *name,
37
+ intptr_t row, col, oprsz = simd_oprsz(desc) / 4;
172
+ const char *alias_prop_name)
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)
173
{
61
{
174
- /* Create and map a single flash device. We use the same
62
intptr_t row, col, oprsz = simd_oprsz(desc) / 8;
175
- * parameters as the flash devices on the Versatile Express board.
63
bool neg = simd_data(desc);
176
+ /*
64
@@ -XXX,XX +XXX,XX @@ static inline void do_imopa(uint64_t *za, uint64_t *zn, uint64_t *zm,
177
+ * Create a single flash device. We use the same parameters as
178
+ * the flash devices on the Versatile Express board.
179
*/
180
- DriveInfo *dinfo = drive_get_next(IF_PFLASH);
181
DeviceState *dev = qdev_create(NULL, TYPE_PFLASH_CFI01);
182
- SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
183
- const uint64_t sectorlength = 256 * 1024;
184
185
- if (dinfo) {
186
- qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo),
187
- &error_abort);
188
- }
189
-
190
- qdev_prop_set_uint32(dev, "num-blocks", flashsize / sectorlength);
191
- qdev_prop_set_uint64(dev, "sector-length", sectorlength);
192
+ qdev_prop_set_uint64(dev, "sector-length", VIRT_FLASH_SECTOR_SIZE);
193
qdev_prop_set_uint8(dev, "width", 4);
194
qdev_prop_set_uint8(dev, "device-width", 2);
195
qdev_prop_set_bit(dev, "big-endian", false);
196
@@ -XXX,XX +XXX,XX @@ static void create_one_flash(const char *name, hwaddr flashbase,
197
qdev_prop_set_uint16(dev, "id2", 0x00);
198
qdev_prop_set_uint16(dev, "id3", 0x00);
199
qdev_prop_set_string(dev, "name", name);
200
- qdev_init_nofail(dev);
201
-
202
- memory_region_add_subregion(sysmem, flashbase,
203
- sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0));
204
-
205
- if (file) {
206
- char *fn;
207
- int image_size;
208
-
209
- if (drive_get(IF_PFLASH, 0, 0)) {
210
- error_report("The contents of the first flash device may be "
211
- "specified with -bios or with -drive if=pflash... "
212
- "but you cannot use both options at once");
213
- exit(1);
214
- }
215
- fn = qemu_find_file(QEMU_FILE_TYPE_BIOS, file);
216
- if (!fn) {
217
- error_report("Could not find ROM image '%s'", file);
218
- exit(1);
219
- }
220
- image_size = load_image_mr(fn, sysbus_mmio_get_region(sbd, 0));
221
- g_free(fn);
222
- if (image_size < 0) {
223
- error_report("Could not load ROM image '%s'", file);
224
- exit(1);
225
- }
226
- }
227
+ object_property_add_child(OBJECT(vms), name, OBJECT(dev),
228
+ &error_abort);
229
+ object_property_add_alias(OBJECT(vms), alias_prop_name,
230
+ OBJECT(dev), "drive", &error_abort);
231
+ return PFLASH_CFI01(dev);
232
}
65
}
233
66
234
-static void create_flash(const VirtMachineState *vms,
67
#define DEF_IMOP_32(NAME, NTYPE, MTYPE) \
235
- MemoryRegion *sysmem,
68
-static uint64_t NAME(uint64_t n, uint64_t m, uint64_t a, uint8_t p, bool neg) \
236
- MemoryRegion *secure_sysmem)
69
+static uint32_t NAME(uint32_t n, uint32_t m, uint32_t a, uint8_t p, bool neg) \
237
+static void virt_flash_create(VirtMachineState *vms)
70
{ \
238
{
71
- uint32_t sum0 = 0, sum1 = 0; \
239
- /* Create two flash devices to fill the VIRT_FLASH space in the memmap.
72
+ uint32_t sum = 0; \
240
- * Any file passed via -bios goes in the first of these.
73
/* Apply P to N as a mask, making the inactive elements 0. */ \
241
+ vms->flash[0] = virt_flash_create1(vms, "virt.flash0", "pflash0");
74
n &= expand_pred_b(p); \
242
+ vms->flash[1] = virt_flash_create1(vms, "virt.flash1", "pflash1");
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;
243
+}
179
+}
244
+
180
diff --git a/tests/tcg/aarch64/sme-smopa-2.c b/tests/tcg/aarch64/sme-smopa-2.c
245
+static void virt_flash_map1(PFlashCFI01 *flash,
181
new file mode 100644
246
+ hwaddr base, hwaddr size,
182
index XXXXXXX..XXXXXXX
247
+ MemoryRegion *sysmem)
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()
248
+{
190
+{
249
+ DeviceState *dev = DEVICE(flash);
191
+ static const long cmp[4][4] = {
250
+
192
+ { 110, 134, 158, 182 },
251
+ assert(size % VIRT_FLASH_SECTOR_SIZE == 0);
193
+ { 390, 478, 566, 654 },
252
+ assert(size / VIRT_FLASH_SECTOR_SIZE <= UINT32_MAX);
194
+ { 670, 822, 974, 1126 },
253
+ qdev_prop_set_uint32(dev, "num-blocks", size / VIRT_FLASH_SECTOR_SIZE);
195
+ { 950, 1166, 1382, 1598 }
254
+ qdev_init_nofail(dev);
196
+ };
255
+
197
+ long dst[4][4];
256
+ memory_region_add_subregion(sysmem, base,
198
+ long *tmp = &dst[0][0];
257
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(dev),
199
+ long svl;
258
+ 0));
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;
259
+}
239
+}
260
+
240
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
261
+static void virt_flash_map(VirtMachineState *vms,
241
index XXXXXXX..XXXXXXX 100644
262
+ MemoryRegion *sysmem,
242
--- a/tests/tcg/aarch64/Makefile.target
263
+ MemoryRegion *secure_sysmem)
243
+++ b/tests/tcg/aarch64/Makefile.target
264
+{
244
@@ -XXX,XX +XXX,XX @@ endif
265
+ /*
245
266
+ * Map two flash devices to fill the VIRT_FLASH space in the memmap.
246
# SME Tests
267
* sysmem is the system memory space. secure_sysmem is the secure view
247
ifneq ($(CROSS_AS_HAS_ARMV9_SME),)
268
* of the system, and the first flash device should be made visible only
248
-AARCH64_TESTS += sme-outprod1
269
* there. The second flash device is visible to both secure and nonsecure.
249
+AARCH64_TESTS += sme-outprod1 sme-smopa-1 sme-smopa-2
270
@@ -XXX,XX +XXX,XX @@ static void create_flash(const VirtMachineState *vms,
250
endif
271
*/
251
272
hwaddr flashsize = vms->memmap[VIRT_FLASH].size / 2;
252
# System Registers Tests
273
hwaddr flashbase = vms->memmap[VIRT_FLASH].base;
274
- char *nodename;
275
276
- create_one_flash("virt.flash0", flashbase, flashsize,
277
- bios_name, secure_sysmem);
278
- create_one_flash("virt.flash1", flashbase + flashsize, flashsize,
279
- NULL, sysmem);
280
+ virt_flash_map1(vms->flash[0], flashbase, flashsize,
281
+ secure_sysmem);
282
+ virt_flash_map1(vms->flash[1], flashbase + flashsize, flashsize,
283
+ sysmem);
284
+}
285
+
286
+static void virt_flash_fdt(VirtMachineState *vms,
287
+ MemoryRegion *sysmem,
288
+ MemoryRegion *secure_sysmem)
289
+{
290
+ hwaddr flashsize = vms->memmap[VIRT_FLASH].size / 2;
291
+ hwaddr flashbase = vms->memmap[VIRT_FLASH].base;
292
+ char *nodename;
293
294
if (sysmem == secure_sysmem) {
295
/* Report both flash devices as a single node in the DT */
296
@@ -XXX,XX +XXX,XX @@ static void create_flash(const VirtMachineState *vms,
297
qemu_fdt_setprop_cell(vms->fdt, nodename, "bank-width", 4);
298
g_free(nodename);
299
} else {
300
- /* Report the devices as separate nodes so we can mark one as
301
+ /*
302
+ * Report the devices as separate nodes so we can mark one as
303
* only visible to the secure world.
304
*/
305
nodename = g_strdup_printf("/secflash@%" PRIx64, flashbase);
306
@@ -XXX,XX +XXX,XX @@ static void create_flash(const VirtMachineState *vms,
307
}
308
}
309
310
+static bool virt_firmware_init(VirtMachineState *vms,
311
+ MemoryRegion *sysmem,
312
+ MemoryRegion *secure_sysmem)
313
+{
314
+ int i;
315
+ BlockBackend *pflash_blk0;
316
+
317
+ /* Map legacy -drive if=pflash to machine properties */
318
+ for (i = 0; i < ARRAY_SIZE(vms->flash); i++) {
319
+ pflash_cfi01_legacy_drive(vms->flash[i],
320
+ drive_get(IF_PFLASH, 0, i));
321
+ }
322
+
323
+ virt_flash_map(vms, sysmem, secure_sysmem);
324
+
325
+ pflash_blk0 = pflash_cfi01_get_blk(vms->flash[0]);
326
+
327
+ if (bios_name) {
328
+ char *fname;
329
+ MemoryRegion *mr;
330
+ int image_size;
331
+
332
+ if (pflash_blk0) {
333
+ error_report("The contents of the first flash device may be "
334
+ "specified with -bios or with -drive if=pflash... "
335
+ "but you cannot use both options at once");
336
+ exit(1);
337
+ }
338
+
339
+ /* Fall back to -bios */
340
+
341
+ fname = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
342
+ if (!fname) {
343
+ error_report("Could not find ROM image '%s'", bios_name);
344
+ exit(1);
345
+ }
346
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(vms->flash[0]), 0);
347
+ image_size = load_image_mr(fname, mr);
348
+ g_free(fname);
349
+ if (image_size < 0) {
350
+ error_report("Could not load ROM image '%s'", bios_name);
351
+ exit(1);
352
+ }
353
+ }
354
+
355
+ return pflash_blk0 || bios_name;
356
+}
357
+
358
static FWCfgState *create_fw_cfg(const VirtMachineState *vms, AddressSpace *as)
359
{
360
hwaddr base = vms->memmap[VIRT_FW_CFG].base;
361
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
362
MemoryRegion *secure_sysmem = NULL;
363
int n, virt_max_cpus;
364
MemoryRegion *ram = g_new(MemoryRegion, 1);
365
- bool firmware_loaded = bios_name || drive_get(IF_PFLASH, 0, 0);
366
+ bool firmware_loaded;
367
bool aarch64 = true;
368
369
/*
370
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
371
exit(1);
372
}
373
374
+ if (vms->secure) {
375
+ if (kvm_enabled()) {
376
+ error_report("mach-virt: KVM does not support Security extensions");
377
+ exit(1);
378
+ }
379
+
380
+ /*
381
+ * The Secure view of the world is the same as the NonSecure,
382
+ * but with a few extra devices. Create it as a container region
383
+ * containing the system memory at low priority; any secure-only
384
+ * devices go in at higher priority and take precedence.
385
+ */
386
+ secure_sysmem = g_new(MemoryRegion, 1);
387
+ memory_region_init(secure_sysmem, OBJECT(machine), "secure-memory",
388
+ UINT64_MAX);
389
+ memory_region_add_subregion_overlap(secure_sysmem, 0, sysmem, -1);
390
+ }
391
+
392
+ firmware_loaded = virt_firmware_init(vms, sysmem,
393
+ secure_sysmem ?: sysmem);
394
+
395
/* If we have an EL3 boot ROM then the assumption is that it will
396
* implement PSCI itself, so disable QEMU's internal implementation
397
* so it doesn't get in the way. Instead of starting secondary
398
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
399
exit(1);
400
}
401
402
- if (vms->secure) {
403
- if (kvm_enabled()) {
404
- error_report("mach-virt: KVM does not support Security extensions");
405
- exit(1);
406
- }
407
-
408
- /* The Secure view of the world is the same as the NonSecure,
409
- * but with a few extra devices. Create it as a container region
410
- * containing the system memory at low priority; any secure-only
411
- * devices go in at higher priority and take precedence.
412
- */
413
- secure_sysmem = g_new(MemoryRegion, 1);
414
- memory_region_init(secure_sysmem, OBJECT(machine), "secure-memory",
415
- UINT64_MAX);
416
- memory_region_add_subregion_overlap(secure_sysmem, 0, sysmem, -1);
417
- }
418
-
419
create_fdt(vms);
420
421
possible_cpus = mc->possible_cpu_arch_ids(machine);
422
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
423
&machine->device_memory->mr);
424
}
425
426
- create_flash(vms, sysmem, secure_sysmem ? secure_sysmem : sysmem);
427
+ virt_flash_fdt(vms, sysmem, secure_sysmem);
428
429
create_gic(vms, pic);
430
431
@@ -XXX,XX +XXX,XX @@ static void virt_instance_init(Object *obj)
432
NULL);
433
434
vms->irqmap = a15irqmap;
435
+
436
+ virt_flash_create(vms);
437
}
438
439
static const TypeInfo virt_machine_info = {
440
--
253
--
441
2.20.1
254
2.34.1
442
255
443
256
diff view generated by jsdifflib
Deleted patch
1
The Raspberry Pi boards have a physical memory map which does
2
not allow for more than 1GB of RAM. Currently if the user tries
3
to ask for more then we fail in a confusing way:
4
1
5
$ qemu-system-aarch64 --machine raspi3 -m 8G
6
Unexpected error in visit_type_uintN() at qapi/qapi-visit-core.c:164:
7
qemu-system-aarch64: Parameter 'vcram-base' expects uint32_t
8
Aborted (core dumped)
9
10
Catch this earlier and diagnose it with a more friendly message:
11
$ qemu-system-aarch64 --machine raspi3 -m 8G
12
qemu-system-aarch64: Requested ram size is too large for this machine: maximum is 1GB
13
14
Fixes: https://bugs.launchpad.net/qemu/+bug/1794187
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Reviewed-by: Wainer dos Santos Moschetta <wainersm@redhat.com>
19
---
20
hw/arm/raspi.c | 7 +++++++
21
1 file changed, 7 insertions(+)
22
23
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
24
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/arm/raspi.c
26
+++ b/hw/arm/raspi.c
27
@@ -XXX,XX +XXX,XX @@
28
*/
29
30
#include "qemu/osdep.h"
31
+#include "qemu/units.h"
32
#include "qapi/error.h"
33
#include "qemu-common.h"
34
#include "cpu.h"
35
@@ -XXX,XX +XXX,XX @@ static void raspi_init(MachineState *machine, int version)
36
BusState *bus;
37
DeviceState *carddev;
38
39
+ if (machine->ram_size > 1 * GiB) {
40
+ error_report("Requested ram size is too large for this machine: "
41
+ "maximum is 1GB");
42
+ exit(1);
43
+ }
44
+
45
object_initialize(&s->soc, sizeof(s->soc),
46
version == 3 ? TYPE_BCM2837 : TYPE_BCM2836);
47
object_property_add_child(OBJECT(machine), "soc", OBJECT(&s->soc),
48
--
49
2.20.1
50
51
diff view generated by jsdifflib
1
From: Joel Stanley <joel@jms.id.au>
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 currently use Qemu's default of 128MB. As we know how much ram each
5
Relicense the code in the .c and the .h file to GPL-v2-or-later,
4
machine ships with, make it easier on users by setting a default.
6
to make it compatible with the rest of QEMU.
5
7
6
It can still be overridden with -m on the command line.
8
Cc: qemu-stable@nongnu.org
7
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Joel Stanley <joel@jms.id.au>
10
Signed-off-by: Paolo Bonzini (for Red Hat) <pbonzini@redhat.com>
9
Reviewed-by: Andrew Jeffery <andrew@aj.id.au>
11
Signed-off-by: Artyom Tarasenko <atar4qemu@gmail.com>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Signed-off-by: Markus Armbruster <armbru@redhat.com>
11
Message-id: 20190503022958.1394-1-joel@jms.id.au
13
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
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
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
19
---
15
include/hw/arm/aspeed.h | 1 +
20
include/hw/rtc/sun4v-rtc.h | 2 +-
16
hw/arm/aspeed.c | 8 ++++++++
21
hw/rtc/sun4v-rtc.c | 2 +-
17
2 files changed, 9 insertions(+)
22
2 files changed, 2 insertions(+), 2 deletions(-)
18
23
19
diff --git a/include/hw/arm/aspeed.h b/include/hw/arm/aspeed.h
24
diff --git a/include/hw/rtc/sun4v-rtc.h b/include/hw/rtc/sun4v-rtc.h
20
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
21
--- a/include/hw/arm/aspeed.h
26
--- a/include/hw/rtc/sun4v-rtc.h
22
+++ b/include/hw/arm/aspeed.h
27
+++ b/include/hw/rtc/sun4v-rtc.h
23
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedBoardConfig {
28
@@ -XXX,XX +XXX,XX @@
24
const char *spi_model;
29
*
25
uint32_t num_cs;
30
* Copyright (c) 2016 Artyom Tarasenko
26
void (*i2c_init)(AspeedBoardState *bmc);
31
*
27
+ uint32_t ram;
32
- * This code is licensed under the GNU GPL v3 or (at your option) any later
28
} AspeedBoardConfig;
33
+ * This code is licensed under the GNU GPL v2 or (at your option) any later
29
34
* version.
30
#define TYPE_ASPEED_MACHINE MACHINE_TYPE_NAME("aspeed")
35
*/
31
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
36
37
diff --git a/hw/rtc/sun4v-rtc.c b/hw/rtc/sun4v-rtc.c
32
index XXXXXXX..XXXXXXX 100644
38
index XXXXXXX..XXXXXXX 100644
33
--- a/hw/arm/aspeed.c
39
--- a/hw/rtc/sun4v-rtc.c
34
+++ b/hw/arm/aspeed.c
40
+++ b/hw/rtc/sun4v-rtc.c
35
@@ -XXX,XX +XXX,XX @@
41
@@ -XXX,XX +XXX,XX @@
36
#include "sysemu/block-backend.h"
42
*
37
#include "hw/loader.h"
43
* Copyright (c) 2016 Artyom Tarasenko
38
#include "qemu/error-report.h"
44
*
39
+#include "qemu/units.h"
45
- * This code is licensed under the GNU GPL v3 or (at your option) any later
40
46
+ * This code is licensed under the GNU GPL v2 or (at your option) any later
41
static struct arm_boot_info aspeed_board_binfo = {
47
* version.
42
.board_id = -1, /* device-tree-only board */
48
*/
43
@@ -XXX,XX +XXX,XX @@ static void aspeed_machine_class_init(ObjectClass *oc, void *data)
44
mc->no_floppy = 1;
45
mc->no_cdrom = 1;
46
mc->no_parallel = 1;
47
+ if (board->ram) {
48
+ mc->default_ram_size = board->ram;
49
+ }
50
amc->board = board;
51
}
52
53
@@ -XXX,XX +XXX,XX @@ static const AspeedBoardConfig aspeed_boards[] = {
54
.spi_model = "mx25l25635e",
55
.num_cs = 1,
56
.i2c_init = palmetto_bmc_i2c_init,
57
+ .ram = 256 * MiB,
58
}, {
59
.name = MACHINE_TYPE_NAME("ast2500-evb"),
60
.desc = "Aspeed AST2500 EVB (ARM1176)",
61
@@ -XXX,XX +XXX,XX @@ static const AspeedBoardConfig aspeed_boards[] = {
62
.spi_model = "mx25l25635e",
63
.num_cs = 1,
64
.i2c_init = ast2500_evb_i2c_init,
65
+ .ram = 512 * MiB,
66
}, {
67
.name = MACHINE_TYPE_NAME("romulus-bmc"),
68
.desc = "OpenPOWER Romulus BMC (ARM1176)",
69
@@ -XXX,XX +XXX,XX @@ static const AspeedBoardConfig aspeed_boards[] = {
70
.spi_model = "mx66l1g45g",
71
.num_cs = 2,
72
.i2c_init = romulus_bmc_i2c_init,
73
+ .ram = 512 * MiB,
74
}, {
75
.name = MACHINE_TYPE_NAME("witherspoon-bmc"),
76
.desc = "OpenPOWER Witherspoon BMC (ARM1176)",
77
@@ -XXX,XX +XXX,XX @@ static const AspeedBoardConfig aspeed_boards[] = {
78
.spi_model = "mx66l1g45g",
79
.num_cs = 2,
80
.i2c_init = witherspoon_bmc_i2c_init,
81
+ .ram = 512 * MiB,
82
},
83
};
84
49
85
--
50
--
86
2.20.1
51
2.34.1
87
52
88
53
diff view generated by jsdifflib
1
From: Cao Jiaxi <driver1998@foxmail.com>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
gcc_struct is for x86 only, and it generates an warning on ARM64 Clang/MinGW targets.
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
Signed-off-by: Cao Jiaxi <driver1998@foxmail.com>
6
Signed-off-by: Thomas Huth <thuth@redhat.com>
6
Reviewed-by: Thomas Huth <thuth@redhat.com>
7
Message-id: 20240308141051.536599-2-thuth@redhat.com
7
Message-id: 20190503003618.10089-1-driver1998@foxmail.com
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
[PMM: dropped the slirp change as slirp is now a submodule]
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
10
---
11
contrib/libvhost-user/libvhost-user.h | 2 +-
11
target/arm/tcg/cpu-v7m.c | 290 +++++++++++++++++++++++++++++++++++++
12
include/qemu/compiler.h | 2 +-
12
target/arm/tcg/cpu32.c | 261 ---------------------------------
13
scripts/cocci-macro-file.h | 7 ++++++-
13
target/arm/meson.build | 3 +
14
3 files changed, 8 insertions(+), 3 deletions(-)
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
15
17
16
diff --git a/contrib/libvhost-user/libvhost-user.h b/contrib/libvhost-user/libvhost-user.h
18
diff --git a/target/arm/tcg/cpu-v7m.c b/target/arm/tcg/cpu-v7m.c
19
new file mode 100644
20
index XXXXXXX..XXXXXXX
21
--- /dev/null
22
+++ b/target/arm/tcg/cpu-v7m.c
23
@@ -XXX,XX +XXX,XX @@
24
+/*
25
+ * QEMU ARMv7-M TCG-only CPUs.
26
+ *
27
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
28
+ *
29
+ * This code is licensed under the GNU GPL v2 or later.
30
+ *
31
+ * SPDX-License-Identifier: GPL-2.0-or-later
32
+ */
33
+
34
+#include "qemu/osdep.h"
35
+#include "cpu.h"
36
+#include "hw/core/tcg-cpu-ops.h"
37
+#include "internals.h"
38
+
39
+#if !defined(CONFIG_USER_ONLY)
40
+
41
+#include "hw/intc/armv7m_nvic.h"
42
+
43
+static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
44
+{
45
+ CPUClass *cc = CPU_GET_CLASS(cs);
46
+ ARMCPU *cpu = ARM_CPU(cs);
47
+ CPUARMState *env = &cpu->env;
48
+ bool ret = false;
49
+
50
+ /*
51
+ * ARMv7-M interrupt masking works differently than -A or -R.
52
+ * There is no FIQ/IRQ distinction. Instead of I and F bits
53
+ * masking FIQ and IRQ interrupts, an exception is taken only
54
+ * if it is higher priority than the current execution priority
55
+ * (which depends on state like BASEPRI, FAULTMASK and the
56
+ * currently active exception).
57
+ */
58
+ if (interrupt_request & CPU_INTERRUPT_HARD
59
+ && (armv7m_nvic_can_take_pending_exception(env->nvic))) {
60
+ cs->exception_index = EXCP_IRQ;
61
+ cc->tcg_ops->do_interrupt(cs);
62
+ ret = true;
63
+ }
64
+ return ret;
65
+}
66
+
67
+#endif /* !CONFIG_USER_ONLY */
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]);
310
+ }
311
+}
312
+
313
+type_init(arm_v7m_cpu_register_types)
314
diff --git a/target/arm/tcg/cpu32.c b/target/arm/tcg/cpu32.c
17
index XXXXXXX..XXXXXXX 100644
315
index XXXXXXX..XXXXXXX 100644
18
--- a/contrib/libvhost-user/libvhost-user.h
316
--- a/target/arm/tcg/cpu32.c
19
+++ b/contrib/libvhost-user/libvhost-user.h
317
+++ b/target/arm/tcg/cpu32.c
20
@@ -XXX,XX +XXX,XX @@ typedef struct VhostUserInflight {
318
@@ -XXX,XX +XXX,XX @@
21
uint16_t queue_size;
319
#include "hw/boards.h"
22
} VhostUserInflight;
320
#endif
23
321
#include "cpregs.h"
24
-#if defined(_WIN32)
322
-#if !defined(CONFIG_USER_ONLY) && defined(CONFIG_TCG)
25
+#if defined(_WIN32) && (defined(__x86_64__) || defined(__i386__))
323
-#include "hw/intc/armv7m_nvic.h"
26
# define VU_PACKED __attribute__((gcc_struct, packed))
324
-#endif
27
#else
325
28
# define VU_PACKED __attribute__((packed))
326
29
diff --git a/include/qemu/compiler.h b/include/qemu/compiler.h
327
/* Share AArch32 -cpu max features with AArch64. */
328
@@ -XXX,XX +XXX,XX @@ void aa32_max_features(ARMCPU *cpu)
329
/* CPU models. These are not needed for the AArch64 linux-user build. */
330
#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
331
332
-#if !defined(CONFIG_USER_ONLY)
333
-static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
334
-{
335
- CPUClass *cc = CPU_GET_CLASS(cs);
336
- ARMCPU *cpu = ARM_CPU(cs);
337
- CPUARMState *env = &cpu->env;
338
- bool ret = false;
339
-
340
- /*
341
- * ARMv7-M interrupt masking works differently than -A or -R.
342
- * There is no FIQ/IRQ distinction. Instead of I and F bits
343
- * masking FIQ and IRQ interrupts, an exception is taken only
344
- * if it is higher priority than the current execution priority
345
- * (which depends on state like BASEPRI, FAULTMASK and the
346
- * currently active exception).
347
- */
348
- if (interrupt_request & CPU_INTERRUPT_HARD
349
- && (armv7m_nvic_can_take_pending_exception(env->nvic))) {
350
- cs->exception_index = EXCP_IRQ;
351
- cc->tcg_ops->do_interrupt(cs);
352
- ret = true;
353
- }
354
- return ret;
355
-}
356
-#endif /* !CONFIG_USER_ONLY */
357
-
358
static void arm926_initfn(Object *obj)
359
{
360
ARMCPU *cpu = ARM_CPU(obj);
361
@@ -XXX,XX +XXX,XX @@ static void cortex_a15_initfn(Object *obj)
362
define_arm_cp_regs(cpu, cortexa15_cp_reginfo);
363
}
364
365
-static void cortex_m0_initfn(Object *obj)
366
-{
367
- ARMCPU *cpu = ARM_CPU(obj);
368
- set_feature(&cpu->env, ARM_FEATURE_V6);
369
- set_feature(&cpu->env, ARM_FEATURE_M);
370
-
371
- cpu->midr = 0x410cc200;
372
-
373
- /*
374
- * These ID register values are not guest visible, because
375
- * we do not implement the Main Extension. They must be set
376
- * to values corresponding to the Cortex-M0's implemented
377
- * features, because QEMU generally controls its emulation
378
- * by looking at ID register fields. We use the same values as
379
- * for the M3.
380
- */
381
- cpu->isar.id_pfr0 = 0x00000030;
382
- cpu->isar.id_pfr1 = 0x00000200;
383
- cpu->isar.id_dfr0 = 0x00100000;
384
- cpu->id_afr0 = 0x00000000;
385
- cpu->isar.id_mmfr0 = 0x00000030;
386
- cpu->isar.id_mmfr1 = 0x00000000;
387
- cpu->isar.id_mmfr2 = 0x00000000;
388
- cpu->isar.id_mmfr3 = 0x00000000;
389
- cpu->isar.id_isar0 = 0x01141110;
390
- cpu->isar.id_isar1 = 0x02111000;
391
- cpu->isar.id_isar2 = 0x21112231;
392
- cpu->isar.id_isar3 = 0x01111110;
393
- cpu->isar.id_isar4 = 0x01310102;
394
- cpu->isar.id_isar5 = 0x00000000;
395
- cpu->isar.id_isar6 = 0x00000000;
396
-}
397
-
398
-static void cortex_m3_initfn(Object *obj)
399
-{
400
- ARMCPU *cpu = ARM_CPU(obj);
401
- set_feature(&cpu->env, ARM_FEATURE_V7);
402
- set_feature(&cpu->env, ARM_FEATURE_M);
403
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
404
- cpu->midr = 0x410fc231;
405
- cpu->pmsav7_dregion = 8;
406
- cpu->isar.id_pfr0 = 0x00000030;
407
- cpu->isar.id_pfr1 = 0x00000200;
408
- cpu->isar.id_dfr0 = 0x00100000;
409
- cpu->id_afr0 = 0x00000000;
410
- cpu->isar.id_mmfr0 = 0x00000030;
411
- cpu->isar.id_mmfr1 = 0x00000000;
412
- cpu->isar.id_mmfr2 = 0x00000000;
413
- cpu->isar.id_mmfr3 = 0x00000000;
414
- cpu->isar.id_isar0 = 0x01141110;
415
- cpu->isar.id_isar1 = 0x02111000;
416
- cpu->isar.id_isar2 = 0x21112231;
417
- cpu->isar.id_isar3 = 0x01111110;
418
- cpu->isar.id_isar4 = 0x01310102;
419
- cpu->isar.id_isar5 = 0x00000000;
420
- cpu->isar.id_isar6 = 0x00000000;
421
-}
422
-
423
-static void cortex_m4_initfn(Object *obj)
424
-{
425
- ARMCPU *cpu = ARM_CPU(obj);
426
-
427
- set_feature(&cpu->env, ARM_FEATURE_V7);
428
- set_feature(&cpu->env, ARM_FEATURE_M);
429
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
430
- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
431
- cpu->midr = 0x410fc240; /* r0p0 */
432
- cpu->pmsav7_dregion = 8;
433
- cpu->isar.mvfr0 = 0x10110021;
434
- cpu->isar.mvfr1 = 0x11000011;
435
- cpu->isar.mvfr2 = 0x00000000;
436
- cpu->isar.id_pfr0 = 0x00000030;
437
- cpu->isar.id_pfr1 = 0x00000200;
438
- cpu->isar.id_dfr0 = 0x00100000;
439
- cpu->id_afr0 = 0x00000000;
440
- cpu->isar.id_mmfr0 = 0x00000030;
441
- cpu->isar.id_mmfr1 = 0x00000000;
442
- cpu->isar.id_mmfr2 = 0x00000000;
443
- cpu->isar.id_mmfr3 = 0x00000000;
444
- cpu->isar.id_isar0 = 0x01141110;
445
- cpu->isar.id_isar1 = 0x02111000;
446
- cpu->isar.id_isar2 = 0x21112231;
447
- cpu->isar.id_isar3 = 0x01111110;
448
- cpu->isar.id_isar4 = 0x01310102;
449
- cpu->isar.id_isar5 = 0x00000000;
450
- cpu->isar.id_isar6 = 0x00000000;
451
-}
452
-
453
-static void cortex_m7_initfn(Object *obj)
454
-{
455
- ARMCPU *cpu = ARM_CPU(obj);
456
-
457
- set_feature(&cpu->env, ARM_FEATURE_V7);
458
- set_feature(&cpu->env, ARM_FEATURE_M);
459
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
460
- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
461
- cpu->midr = 0x411fc272; /* r1p2 */
462
- cpu->pmsav7_dregion = 8;
463
- cpu->isar.mvfr0 = 0x10110221;
464
- cpu->isar.mvfr1 = 0x12000011;
465
- cpu->isar.mvfr2 = 0x00000040;
466
- cpu->isar.id_pfr0 = 0x00000030;
467
- cpu->isar.id_pfr1 = 0x00000200;
468
- cpu->isar.id_dfr0 = 0x00100000;
469
- cpu->id_afr0 = 0x00000000;
470
- cpu->isar.id_mmfr0 = 0x00100030;
471
- cpu->isar.id_mmfr1 = 0x00000000;
472
- cpu->isar.id_mmfr2 = 0x01000000;
473
- cpu->isar.id_mmfr3 = 0x00000000;
474
- cpu->isar.id_isar0 = 0x01101110;
475
- cpu->isar.id_isar1 = 0x02112000;
476
- cpu->isar.id_isar2 = 0x20232231;
477
- cpu->isar.id_isar3 = 0x01111131;
478
- cpu->isar.id_isar4 = 0x01310132;
479
- cpu->isar.id_isar5 = 0x00000000;
480
- cpu->isar.id_isar6 = 0x00000000;
481
-}
482
-
483
-static void cortex_m33_initfn(Object *obj)
484
-{
485
- ARMCPU *cpu = ARM_CPU(obj);
486
-
487
- set_feature(&cpu->env, ARM_FEATURE_V8);
488
- set_feature(&cpu->env, ARM_FEATURE_M);
489
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
490
- set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
491
- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
492
- cpu->midr = 0x410fd213; /* r0p3 */
493
- cpu->pmsav7_dregion = 16;
494
- cpu->sau_sregion = 8;
495
- cpu->isar.mvfr0 = 0x10110021;
496
- cpu->isar.mvfr1 = 0x11000011;
497
- cpu->isar.mvfr2 = 0x00000040;
498
- cpu->isar.id_pfr0 = 0x00000030;
499
- cpu->isar.id_pfr1 = 0x00000210;
500
- cpu->isar.id_dfr0 = 0x00200000;
501
- cpu->id_afr0 = 0x00000000;
502
- cpu->isar.id_mmfr0 = 0x00101F40;
503
- cpu->isar.id_mmfr1 = 0x00000000;
504
- cpu->isar.id_mmfr2 = 0x01000000;
505
- cpu->isar.id_mmfr3 = 0x00000000;
506
- cpu->isar.id_isar0 = 0x01101110;
507
- cpu->isar.id_isar1 = 0x02212000;
508
- cpu->isar.id_isar2 = 0x20232232;
509
- cpu->isar.id_isar3 = 0x01111131;
510
- cpu->isar.id_isar4 = 0x01310132;
511
- cpu->isar.id_isar5 = 0x00000000;
512
- cpu->isar.id_isar6 = 0x00000000;
513
- cpu->clidr = 0x00000000;
514
- cpu->ctr = 0x8000c000;
515
-}
516
-
517
-static void cortex_m55_initfn(Object *obj)
518
-{
519
- ARMCPU *cpu = ARM_CPU(obj);
520
-
521
- set_feature(&cpu->env, ARM_FEATURE_V8);
522
- set_feature(&cpu->env, ARM_FEATURE_V8_1M);
523
- set_feature(&cpu->env, ARM_FEATURE_M);
524
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
525
- set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
526
- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
527
- cpu->midr = 0x410fd221; /* r0p1 */
528
- cpu->revidr = 0;
529
- cpu->pmsav7_dregion = 16;
530
- cpu->sau_sregion = 8;
531
- /* These are the MVFR* values for the FPU + full MVE configuration */
532
- cpu->isar.mvfr0 = 0x10110221;
533
- cpu->isar.mvfr1 = 0x12100211;
534
- cpu->isar.mvfr2 = 0x00000040;
535
- cpu->isar.id_pfr0 = 0x20000030;
536
- cpu->isar.id_pfr1 = 0x00000230;
537
- cpu->isar.id_dfr0 = 0x10200000;
538
- cpu->id_afr0 = 0x00000000;
539
- cpu->isar.id_mmfr0 = 0x00111040;
540
- cpu->isar.id_mmfr1 = 0x00000000;
541
- cpu->isar.id_mmfr2 = 0x01000000;
542
- cpu->isar.id_mmfr3 = 0x00000011;
543
- cpu->isar.id_isar0 = 0x01103110;
544
- cpu->isar.id_isar1 = 0x02212000;
545
- cpu->isar.id_isar2 = 0x20232232;
546
- cpu->isar.id_isar3 = 0x01111131;
547
- cpu->isar.id_isar4 = 0x01310132;
548
- cpu->isar.id_isar5 = 0x00000000;
549
- cpu->isar.id_isar6 = 0x00000000;
550
- cpu->clidr = 0x00000000; /* caches not implemented */
551
- cpu->ctr = 0x8303c003;
552
-}
553
-
554
static const ARMCPRegInfo cortexr5_cp_reginfo[] = {
555
/* Dummy the TCM region regs for the moment */
556
{ .name = "ATCM", .cp = 15, .opc1 = 0, .crn = 9, .crm = 1, .opc2 = 0,
557
@@ -XXX,XX +XXX,XX @@ static void pxa270c5_initfn(Object *obj)
558
cpu->reset_sctlr = 0x00000078;
559
}
560
561
-static const TCGCPUOps arm_v7m_tcg_ops = {
562
- .initialize = arm_translate_init,
563
- .synchronize_from_tb = arm_cpu_synchronize_from_tb,
564
- .debug_excp_handler = arm_debug_excp_handler,
565
- .restore_state_to_opc = arm_restore_state_to_opc,
566
-
567
-#ifdef CONFIG_USER_ONLY
568
- .record_sigsegv = arm_cpu_record_sigsegv,
569
- .record_sigbus = arm_cpu_record_sigbus,
570
-#else
571
- .tlb_fill = arm_cpu_tlb_fill,
572
- .cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt,
573
- .do_interrupt = arm_v7m_cpu_do_interrupt,
574
- .do_transaction_failed = arm_cpu_do_transaction_failed,
575
- .do_unaligned_access = arm_cpu_do_unaligned_access,
576
- .adjust_watchpoint_address = arm_adjust_watchpoint_address,
577
- .debug_check_watchpoint = arm_debug_check_watchpoint,
578
- .debug_check_breakpoint = arm_debug_check_breakpoint,
579
-#endif /* !CONFIG_USER_ONLY */
580
-};
581
-
582
-static void arm_v7m_class_init(ObjectClass *oc, void *data)
583
-{
584
- ARMCPUClass *acc = ARM_CPU_CLASS(oc);
585
- CPUClass *cc = CPU_CLASS(oc);
586
-
587
- acc->info = data;
588
- cc->tcg_ops = &arm_v7m_tcg_ops;
589
- cc->gdb_core_xml_file = "arm-m-profile.xml";
590
-}
591
-
592
#ifndef TARGET_AARCH64
593
/*
594
* -cpu max: a CPU with as many features enabled as our emulation supports.
595
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo arm_tcg_cpus[] = {
596
{ .name = "cortex-a8", .initfn = cortex_a8_initfn },
597
{ .name = "cortex-a9", .initfn = cortex_a9_initfn },
598
{ .name = "cortex-a15", .initfn = cortex_a15_initfn },
599
- { .name = "cortex-m0", .initfn = cortex_m0_initfn,
600
- .class_init = arm_v7m_class_init },
601
- { .name = "cortex-m3", .initfn = cortex_m3_initfn,
602
- .class_init = arm_v7m_class_init },
603
- { .name = "cortex-m4", .initfn = cortex_m4_initfn,
604
- .class_init = arm_v7m_class_init },
605
- { .name = "cortex-m7", .initfn = cortex_m7_initfn,
606
- .class_init = arm_v7m_class_init },
607
- { .name = "cortex-m33", .initfn = cortex_m33_initfn,
608
- .class_init = arm_v7m_class_init },
609
- { .name = "cortex-m55", .initfn = cortex_m55_initfn,
610
- .class_init = arm_v7m_class_init },
611
{ .name = "cortex-r5", .initfn = cortex_r5_initfn },
612
{ .name = "cortex-r5f", .initfn = cortex_r5f_initfn },
613
{ .name = "cortex-r52", .initfn = cortex_r52_initfn },
614
diff --git a/target/arm/meson.build b/target/arm/meson.build
30
index XXXXXXX..XXXXXXX 100644
615
index XXXXXXX..XXXXXXX 100644
31
--- a/include/qemu/compiler.h
616
--- a/target/arm/meson.build
32
+++ b/include/qemu/compiler.h
617
+++ b/target/arm/meson.build
33
@@ -XXX,XX +XXX,XX @@
618
@@ -XXX,XX +XXX,XX @@ arm_system_ss.add(files(
34
619
'ptw.c',
35
#define QEMU_SENTINEL __attribute__((sentinel))
620
))
36
621
37
-#if defined(_WIN32)
622
+arm_user_ss = ss.source_set()
38
+#if defined(_WIN32) && (defined(__x86_64__) || defined(__i386__))
623
+
39
# define QEMU_PACKED __attribute__((gcc_struct, packed))
624
subdir('hvf')
40
#else
625
41
# define QEMU_PACKED __attribute__((packed))
626
if 'CONFIG_TCG' in config_all_accel
42
diff --git a/scripts/cocci-macro-file.h b/scripts/cocci-macro-file.h
627
@@ -XXX,XX +XXX,XX @@ endif
628
629
target_arch += {'arm': arm_ss}
630
target_system_arch += {'arm': arm_system_ss}
631
+target_user_arch += {'arm': arm_user_ss}
632
diff --git a/target/arm/tcg/meson.build b/target/arm/tcg/meson.build
43
index XXXXXXX..XXXXXXX 100644
633
index XXXXXXX..XXXXXXX 100644
44
--- a/scripts/cocci-macro-file.h
634
--- a/target/arm/tcg/meson.build
45
+++ b/scripts/cocci-macro-file.h
635
+++ b/target/arm/tcg/meson.build
46
@@ -XXX,XX +XXX,XX @@
636
@@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
47
#define QEMU_NORETURN __attribute__ ((__noreturn__))
637
arm_system_ss.add(files(
48
#define QEMU_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
638
'psci.c',
49
#define QEMU_SENTINEL __attribute__((sentinel))
639
))
50
-#define QEMU_PACKED __attribute__((gcc_struct, packed))
640
+
51
+
641
+arm_system_ss.add(when: 'CONFIG_ARM_V7M', if_true: files('cpu-v7m.c'))
52
+#if defined(_WIN32) && (defined(__x86_64__) || defined(__i386__))
642
+arm_user_ss.add(when: 'TARGET_AARCH64', if_false: files('cpu-v7m.c'))
53
+# define QEMU_PACKED __attribute__((gcc_struct, packed))
54
+#else
55
+# define QEMU_PACKED __attribute__((packed))
56
+#endif
57
58
#define cat(x,y) x ## y
59
#define cat2(x,y) cat(x,y)
60
--
643
--
61
2.20.1
644
2.34.1
62
63
diff view generated by jsdifflib