1
Arm stuff, mostly patches from RTH.
1
The following changes since commit 8f6330a807f2642dc2a3cdf33347aa28a4c00a87:
2
2
3
thanks
3
Merge tag 'pull-maintainer-updates-060324-1' of https://gitlab.com/stsquad/qemu into staging (2024-03-06 16:56:20 +0000)
4
-- PMM
5
6
The following changes since commit 01a9a51ffaf4699827ea6425cb2b834a356e159d:
7
8
Merge remote-tracking branch 'remotes/kraxel/tags/ui-20190205-pull-request' into staging (2019-02-05 14:01:29 +0000)
9
4
10
are available in the Git repository at:
5
are available in the Git repository at:
11
6
12
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20190205
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20240308
13
8
14
for you to fetch changes up to a15945d98d3a3390c3da344d1b47218e91e49d8b:
9
for you to fetch changes up to bbf6c6dbead82292a20951eb1204442a6b838de9:
15
10
16
target/arm: Make FPSCR/FPCR trapped-exception bits RAZ/WI (2019-02-05 16:52:42 +0000)
11
target/arm: Move v7m-related code from cpu32.c into a separate file (2024-03-08 14:45:03 +0000)
17
12
18
----------------------------------------------------------------
13
----------------------------------------------------------------
19
target-arm queue:
14
target-arm queue:
20
* Implement Armv8.5-BTI extension for system emulation mode
15
* Implement FEAT_ECV
21
* Implement the PR_PAC_RESET_KEYS prctl() for linux-user mode's Armv8.3-PAuth support
16
* STM32L4x5: Implement GPIO device
22
* Support TBI (top-byte-ignore) properly for linux-user mode
17
* Fix 32-bit SMOPA
23
* gdbstub: allow killing QEMU via vKill command
18
* Refactor v7m related code from cpu32.c into its own file
24
* hw/arm/boot: Support DTB autoload for firmware-only boots
19
* hw/rtc/sun4v-rtc: Relicense to GPLv2-or-later
25
* target/arm: Make FPSCR/FPCR trapped-exception bits RAZ/WI
26
20
27
----------------------------------------------------------------
21
----------------------------------------------------------------
28
Max Filippov (1):
22
Inès Varhol (3):
29
gdbstub: allow killing QEMU via vKill command
23
hw/gpio: Implement STM32L4x5 GPIO
24
hw/arm: Connect STM32L4x5 GPIO to STM32L4x5 SoC
25
tests/qtest: Add STM32L4x5 GPIO QTest testcase
30
26
31
Peter Maydell (7):
27
Peter Maydell (9):
32
target/arm: Compute TB_FLAGS for TBI for user-only
28
target/arm: Move some register related defines to internals.h
33
hw/arm/boot: Fix block comment style in arm_load_kernel()
29
target/arm: Timer _EL02 registers UNDEF for E2H == 0
34
hw/arm/boot: Factor out "direct kernel boot" code into its own function
30
target/arm: use FIELD macro for CNTHCTL bit definitions
35
hw/arm/boot: Factor out "set up firmware boot" code
31
target/arm: Don't allow RES0 CNTHCTL_EL2 bits to be written
36
hw/arm/boot: Clarify why arm_setup_firmware_boot() doesn't set env->boot_info
32
target/arm: Implement new FEAT_ECV trap bits
37
hw/arm/boot: Support DTB autoload for firmware-only boots
33
target/arm: Define CNTPCTSS_EL0 and CNTVCTSS_EL0
38
target/arm: Make FPSCR/FPCR trapped-exception bits RAZ/WI
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
39
37
40
Richard Henderson (14):
38
Richard Henderson (1):
41
target/arm: Introduce isar_feature_aa64_bti
39
target/arm: Fix 32-bit SMOPA
42
target/arm: Add PSTATE.BTYPE
43
target/arm: Add BT and BTYPE to tb->flags
44
exec: Add target-specific tlb bits to MemTxAttrs
45
target/arm: Cache the GP bit for a page in MemTxAttrs
46
target/arm: Default handling of BTYPE during translation
47
target/arm: Reset btype for direct branches
48
target/arm: Set btype for indirect branches
49
target/arm: Enable BTI for -cpu max
50
linux-user: Implement PR_PAC_RESET_KEYS
51
tests/tcg/aarch64: Add pauth smoke test
52
target/arm: Add TBFLAG_A64_TBID, split out gen_top_byte_ignore
53
target/arm: Clean TBI for data operations in the translator
54
target/arm: Enable TBI for user-only
55
40
56
tests/tcg/aarch64/Makefile.target | 6 +-
41
Thomas Huth (1):
57
include/exec/memattrs.h | 10 +
42
target/arm: Move v7m-related code from cpu32.c into a separate file
58
linux-user/aarch64/target_syscall.h | 7 +
59
target/arm/cpu.h | 27 +-
60
target/arm/internals.h | 27 +-
61
target/arm/translate.h | 12 +-
62
gdbstub.c | 4 +
63
hw/arm/boot.c | 166 +++++++------
64
linux-user/syscall.c | 36 +++
65
target/arm/cpu.c | 6 +
66
target/arm/cpu64.c | 4 +
67
target/arm/helper.c | 80 +++---
68
target/arm/translate-a64.c | 476 +++++++++++++++++++++++++-----------
69
tests/tcg/aarch64/pauth-1.c | 23 ++
70
14 files changed, 623 insertions(+), 261 deletions(-)
71
create mode 100644 tests/tcg/aarch64/pauth-1.c
72
43
44
MAINTAINERS | 1 +
45
docs/system/arm/b-l475e-iot01a.rst | 2 +-
46
docs/system/arm/emulation.rst | 1 +
47
include/hw/arm/stm32l4x5_soc.h | 2 +
48
include/hw/gpio/stm32l4x5_gpio.h | 71 +++++
49
include/hw/misc/stm32l4x5_syscfg.h | 3 +-
50
include/hw/rtc/sun4v-rtc.h | 2 +-
51
target/arm/cpu-features.h | 10 +
52
target/arm/cpu.h | 129 +--------
53
target/arm/internals.h | 151 ++++++++++
54
hw/arm/stm32l4x5_soc.c | 71 ++++-
55
hw/gpio/stm32l4x5_gpio.c | 477 ++++++++++++++++++++++++++++++++
56
hw/misc/stm32l4x5_syscfg.c | 1 +
57
hw/rtc/sun4v-rtc.c | 2 +-
58
target/arm/helper.c | 189 ++++++++++++-
59
target/arm/tcg/cpu-v7m.c | 290 +++++++++++++++++++
60
target/arm/tcg/cpu32.c | 261 ------------------
61
target/arm/tcg/cpu64.c | 1 +
62
target/arm/tcg/sme_helper.c | 77 +++---
63
tests/qtest/stm32l4x5_gpio-test.c | 551 +++++++++++++++++++++++++++++++++++++
64
tests/tcg/aarch64/sme-smopa-1.c | 47 ++++
65
tests/tcg/aarch64/sme-smopa-2.c | 54 ++++
66
hw/arm/Kconfig | 3 +-
67
hw/gpio/Kconfig | 3 +
68
hw/gpio/meson.build | 1 +
69
hw/gpio/trace-events | 6 +
70
target/arm/meson.build | 3 +
71
target/arm/tcg/meson.build | 3 +
72
target/arm/trace-events | 1 +
73
tests/qtest/meson.build | 3 +-
74
tests/tcg/aarch64/Makefile.target | 2 +-
75
31 files changed, 1962 insertions(+), 456 deletions(-)
76
create mode 100644 include/hw/gpio/stm32l4x5_gpio.h
77
create mode 100644 hw/gpio/stm32l4x5_gpio.c
78
create mode 100644 target/arm/tcg/cpu-v7m.c
79
create mode 100644 tests/qtest/stm32l4x5_gpio-test.c
80
create mode 100644 tests/tcg/aarch64/sme-smopa-1.c
81
create mode 100644 tests/tcg/aarch64/sme-smopa-2.c
82
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
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
Also create field definitions for id_aa64pfr1 from ARMv8.5.
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20190128223118.5255-2-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
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
9
---
10
---
10
target/arm/cpu.h | 10 ++++++++++
11
target/arm/cpu.h | 128 -----------------------------------------
11
1 file changed, 10 insertions(+)
12
target/arm/internals.h | 128 +++++++++++++++++++++++++++++++++++++++++
13
2 files changed, 128 insertions(+), 128 deletions(-)
12
14
13
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/cpu.h
17
--- a/target/arm/cpu.h
16
+++ b/target/arm/cpu.h
18
+++ b/target/arm/cpu.h
17
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64PFR0, GIC, 24, 4)
19
@@ -XXX,XX +XXX,XX @@ typedef struct ARMGenericTimer {
18
FIELD(ID_AA64PFR0, RAS, 28, 4)
20
uint64_t ctl; /* Timer Control register */
19
FIELD(ID_AA64PFR0, SVE, 32, 4)
21
} ARMGenericTimer;
20
22
21
+FIELD(ID_AA64PFR1, BT, 0, 4)
23
-#define VTCR_NSW (1u << 29)
22
+FIELD(ID_AA64PFR1, SBSS, 4, 4)
24
-#define VTCR_NSA (1u << 30)
23
+FIELD(ID_AA64PFR1, MTE, 8, 4)
25
-#define VSTCR_SW VTCR_NSW
24
+FIELD(ID_AA64PFR1, RAS_FRAC, 12, 4)
26
-#define VSTCR_SA VTCR_NSA
25
+
27
-
26
FIELD(ID_AA64MMFR0, PARANGE, 0, 4)
28
/* Define a maximum sized vector register.
27
FIELD(ID_AA64MMFR0, ASIDBITS, 4, 4)
29
* For 32-bit, this is a 128-bit NEON/AdvSIMD register.
28
FIELD(ID_AA64MMFR0, BIGEND, 8, 4)
30
* For 64-bit, this is a 2048-bit SVE register.
29
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_lor(const ARMISARegisters *id)
31
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
30
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, LO) != 0;
32
#define SCTLR_SPINTMASK (1ULL << 62) /* FEAT_NMI */
31
}
33
#define SCTLR_TIDCP (1ULL << 63) /* FEAT_TIDCP1 */
32
34
33
+static inline bool isar_feature_aa64_bti(const ARMISARegisters *id)
35
-/* Bit definitions for CPACR (AArch32 only) */
34
+{
36
-FIELD(CPACR, CP10, 20, 2)
35
+ return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0;
37
-FIELD(CPACR, CP11, 22, 2)
36
+}
38
-FIELD(CPACR, TRCDIS, 28, 1) /* matches CPACR_EL1.TTA */
37
+
39
-FIELD(CPACR, D32DIS, 30, 1) /* up to v7; RAZ in v8 */
38
/*
40
-FIELD(CPACR, ASEDIS, 31, 1)
39
* Forward to the above feature tests given an ARMCPU pointer.
41
-
40
*/
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
41
--
321
--
42
2.20.1
322
2.34.1
43
323
44
324
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The timer _EL02 registers should UNDEF for invalid accesses from EL2
2
or EL3 when HCR_EL2.E2H == 0, not take a cp access trap. We were
3
delivering the exception to EL2 with the wrong syndrome.
2
4
3
Caching the bit means that we will not have to re-walk the
4
page tables to look up the bit during translation.
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20190128223118.5255-6-richard.henderson@linaro.org
9
[PMM: no need to OR in guarded bit status]
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20240301183219.2424889-3-peter.maydell@linaro.org
11
---
8
---
12
target/arm/helper.c | 6 ++++++
9
target/arm/helper.c | 2 +-
13
1 file changed, 6 insertions(+)
10
1 file changed, 1 insertion(+), 1 deletion(-)
14
11
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
12
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.c
14
--- a/target/arm/helper.c
18
+++ b/target/arm/helper.c
15
+++ b/target/arm/helper.c
19
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
16
@@ -XXX,XX +XXX,XX @@ static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
20
bool ttbr1_valid;
17
return CP_ACCESS_OK;
21
uint64_t descaddrmask;
22
bool aarch64 = arm_el_is_aa64(env, el);
23
+ bool guarded = false;
24
25
/* TODO:
26
* This code does not handle the different format TCR for VTCR_EL2.
27
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
28
}
29
/* Merge in attributes from table descriptors */
30
attrs |= nstable << 3; /* NS */
31
+ guarded = extract64(descriptor, 50, 1); /* GP */
32
if (param.hpd) {
33
/* HPD disables all the table attributes except NSTable. */
34
break;
35
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
36
*/
37
txattrs->secure = false;
38
}
18
}
39
+ /* When in aarch64 mode, and BTI is enabled, remember GP in the IOTLB. */
19
if (!(arm_hcr_el2_eff(env) & HCR_E2H)) {
40
+ if (aarch64 && guarded && cpu_isar_feature(aa64_bti, cpu)) {
20
- return CP_ACCESS_TRAP;
41
+ txattrs->target_tlb_bit0 = true;
21
+ return CP_ACCESS_TRAP_UNCATEGORIZED;
42
+ }
22
}
43
23
return CP_ACCESS_OK;
44
if (cacheattrs != NULL) {
24
}
45
if (mmu_idx == ARMMMUIdx_S2NS) {
46
--
25
--
47
2.20.1
26
2.34.1
48
49
diff view generated by jsdifflib
1
Enables, but does not turn on, TBI for CONFIG_USER_ONLY.
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
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20190204132126.3255-4-richard.henderson@linaro.org
6
[PMM: adjusted #ifdeffery to placate clang, which otherwise complains
7
about static functions that are unused in the CONFIG_USER_ONLY build]
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20240301183219.2424889-4-peter.maydell@linaro.org
9
---
8
---
10
target/arm/internals.h | 21 --------------------
9
target/arm/internals.h | 27 +++++++++++++++++++++++++--
11
target/arm/helper.c | 45 ++++++++++++++++++++++--------------------
10
target/arm/helper.c | 9 ++++-----
12
2 files changed, 24 insertions(+), 42 deletions(-)
11
2 files changed, 29 insertions(+), 7 deletions(-)
13
12
14
diff --git a/target/arm/internals.h b/target/arm/internals.h
13
diff --git a/target/arm/internals.h b/target/arm/internals.h
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/internals.h
15
--- a/target/arm/internals.h
17
+++ b/target/arm/internals.h
16
+++ b/target/arm/internals.h
18
@@ -XXX,XX +XXX,XX @@ typedef struct ARMVAParameters {
17
@@ -XXX,XX +XXX,XX @@ FIELD(VTCR, SL2, 33, 1)
19
bool using64k : 1;
18
#define HSTR_TTEE (1 << 16)
20
} ARMVAParameters;
19
#define HSTR_TJDBX (1 << 17)
21
20
22
-#ifdef CONFIG_USER_ONLY
21
-#define CNTHCTL_CNTVMASK (1 << 18)
23
-static inline ARMVAParameters aa64_va_parameters_both(CPUARMState *env,
22
-#define CNTHCTL_CNTPMASK (1 << 19)
24
- uint64_t va,
23
+/*
25
- ARMMMUIdx mmu_idx)
24
+ * Depending on the value of HCR_EL2.E2H, bits 0 and 1
26
-{
25
+ * have different bit definitions, and EL1PCTEN might be
27
- return (ARMVAParameters) {
26
+ * bit 0 or bit 10. We use _E2H1 and _E2H0 suffixes to
28
- /* 48-bit address space */
27
+ * disambiguate if necessary.
29
- .tsz = 16,
28
+ */
30
- /* We can't handle tagged addresses properly in user-only mode */
29
+FIELD(CNTHCTL, EL0PCTEN_E2H1, 0, 1)
31
- .tbi = false,
30
+FIELD(CNTHCTL, EL0VCTEN_E2H1, 1, 1)
32
- };
31
+FIELD(CNTHCTL, EL1PCTEN_E2H0, 0, 1)
33
-}
32
+FIELD(CNTHCTL, EL1PCEN_E2H0, 1, 1)
34
-
33
+FIELD(CNTHCTL, EVNTEN, 2, 1)
35
-static inline ARMVAParameters aa64_va_parameters(CPUARMState *env,
34
+FIELD(CNTHCTL, EVNTDIR, 3, 1)
36
- uint64_t va,
35
+FIELD(CNTHCTL, EVNTI, 4, 4)
37
- ARMMMUIdx mmu_idx, bool data)
36
+FIELD(CNTHCTL, EL0VTEN, 8, 1)
38
-{
37
+FIELD(CNTHCTL, EL0PTEN, 9, 1)
39
- return aa64_va_parameters_both(env, va, mmu_idx);
38
+FIELD(CNTHCTL, EL1PCTEN_E2H1, 10, 1)
40
-}
39
+FIELD(CNTHCTL, EL1PTEN, 11, 1)
41
-#else
40
+FIELD(CNTHCTL, ECV, 12, 1)
42
ARMVAParameters aa64_va_parameters_both(CPUARMState *env, uint64_t va,
41
+FIELD(CNTHCTL, EL1TVT, 13, 1)
43
ARMMMUIdx mmu_idx);
42
+FIELD(CNTHCTL, EL1TVCT, 14, 1)
44
ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
43
+FIELD(CNTHCTL, EL1NVPCT, 15, 1)
45
ARMMMUIdx mmu_idx, bool data);
44
+FIELD(CNTHCTL, EL1NVVCT, 16, 1)
46
-#endif
45
+FIELD(CNTHCTL, EVNTIS, 17, 1)
47
46
+FIELD(CNTHCTL, CNTVMASK, 18, 1)
48
#endif
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
49
diff --git a/target/arm/helper.c b/target/arm/helper.c
51
diff --git a/target/arm/helper.c b/target/arm/helper.c
50
index XXXXXXX..XXXXXXX 100644
52
index XXXXXXX..XXXXXXX 100644
51
--- a/target/arm/helper.c
53
--- a/target/arm/helper.c
52
+++ b/target/arm/helper.c
54
+++ b/target/arm/helper.c
53
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(rbit)(uint32_t x)
55
@@ -XXX,XX +XXX,XX @@ static void gt_update_irq(ARMCPU *cpu, int timeridx)
54
return revbit32(x);
56
* It is RES0 in Secure and NonSecure state.
55
}
57
*/
56
58
if ((ss == ARMSS_Root || ss == ARMSS_Realm) &&
57
-#if defined(CONFIG_USER_ONLY)
59
- ((timeridx == GTIMER_VIRT && (cnthctl & CNTHCTL_CNTVMASK)) ||
58
+#ifdef CONFIG_USER_ONLY
60
- (timeridx == GTIMER_PHYS && (cnthctl & CNTHCTL_CNTPMASK)))) {
59
61
+ ((timeridx == GTIMER_VIRT && (cnthctl & R_CNTHCTL_CNTVMASK_MASK)) ||
60
/* These should probably raise undefined insn exceptions. */
62
+ (timeridx == GTIMER_PHYS && (cnthctl & R_CNTHCTL_CNTPMASK_MASK)))) {
61
void HELPER(v7m_msr)(CPUARMState *env, uint32_t reg, uint32_t val)
63
irqstate = 0;
62
@@ -XXX,XX +XXX,XX @@ void arm_cpu_do_interrupt(CPUState *cs)
64
}
63
cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
65
66
@@ -XXX,XX +XXX,XX @@ static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
67
{
68
ARMCPU *cpu = env_archcpu(env);
69
uint32_t oldval = env->cp15.cnthctl_el2;
70
-
71
raw_write(env, ri, value);
72
73
- if ((oldval ^ value) & CNTHCTL_CNTVMASK) {
74
+ if ((oldval ^ value) & R_CNTHCTL_CNTVMASK_MASK) {
75
gt_update_irq(cpu, GTIMER_VIRT);
76
- } else if ((oldval ^ value) & CNTHCTL_CNTPMASK) {
77
+ } else if ((oldval ^ value) & R_CNTHCTL_CNTPMASK_MASK) {
78
gt_update_irq(cpu, GTIMER_PHYS);
64
}
79
}
65
}
80
}
66
+#endif /* !CONFIG_USER_ONLY */
67
68
/* Return the exception level which controls this address translation regime */
69
static inline uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
70
@@ -XXX,XX +XXX,XX @@ static inline uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
71
}
72
}
73
74
+#ifndef CONFIG_USER_ONLY
75
+
76
/* Return the SCTLR value which controls this address translation regime */
77
static inline uint32_t regime_sctlr(CPUARMState *env, ARMMMUIdx mmu_idx)
78
{
79
@@ -XXX,XX +XXX,XX @@ static inline bool regime_translation_big_endian(CPUARMState *env,
80
return (regime_sctlr(env, mmu_idx) & SCTLR_EE) != 0;
81
}
82
83
+/* Return the TTBR associated with this translation regime */
84
+static inline uint64_t regime_ttbr(CPUARMState *env, ARMMMUIdx mmu_idx,
85
+ int ttbrn)
86
+{
87
+ if (mmu_idx == ARMMMUIdx_S2NS) {
88
+ return env->cp15.vttbr_el2;
89
+ }
90
+ if (ttbrn == 0) {
91
+ return env->cp15.ttbr0_el[regime_el(env, mmu_idx)];
92
+ } else {
93
+ return env->cp15.ttbr1_el[regime_el(env, mmu_idx)];
94
+ }
95
+}
96
+
97
+#endif /* !CONFIG_USER_ONLY */
98
+
99
/* Return the TCR controlling this translation regime */
100
static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
101
{
102
@@ -XXX,XX +XXX,XX @@ static inline ARMMMUIdx stage_1_mmu_idx(ARMMMUIdx mmu_idx)
103
return mmu_idx;
104
}
105
106
-/* Return the TTBR associated with this translation regime */
107
-static inline uint64_t regime_ttbr(CPUARMState *env, ARMMMUIdx mmu_idx,
108
- int ttbrn)
109
-{
110
- if (mmu_idx == ARMMMUIdx_S2NS) {
111
- return env->cp15.vttbr_el2;
112
- }
113
- if (ttbrn == 0) {
114
- return env->cp15.ttbr0_el[regime_el(env, mmu_idx)];
115
- } else {
116
- return env->cp15.ttbr1_el[regime_el(env, mmu_idx)];
117
- }
118
-}
119
-
120
/* Return true if the translation regime is using LPAE format page tables */
121
static inline bool regime_using_lpae_format(CPUARMState *env,
122
ARMMMUIdx mmu_idx)
123
@@ -XXX,XX +XXX,XX @@ bool arm_s1_regime_using_lpae_format(CPUARMState *env, ARMMMUIdx mmu_idx)
124
return regime_using_lpae_format(env, mmu_idx);
125
}
126
127
+#ifndef CONFIG_USER_ONLY
128
static inline bool regime_is_user(CPUARMState *env, ARMMMUIdx mmu_idx)
129
{
130
switch (mmu_idx) {
131
@@ -XXX,XX +XXX,XX @@ static uint8_t convert_stage2_attrs(CPUARMState *env, uint8_t s2attrs)
132
133
return (hiattr << 6) | (hihint << 4) | (loattr << 2) | lohint;
134
}
135
+#endif /* !CONFIG_USER_ONLY */
136
137
ARMVAParameters aa64_va_parameters_both(CPUARMState *env, uint64_t va,
138
ARMMMUIdx mmu_idx)
139
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
140
return ret;
141
}
142
143
+#ifndef CONFIG_USER_ONLY
144
static ARMVAParameters aa32_va_parameters(CPUARMState *env, uint32_t va,
145
ARMMMUIdx mmu_idx)
146
{
147
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
148
*pc = env->pc;
149
flags = FIELD_DP32(flags, TBFLAG_ANY, AARCH64_STATE, 1);
150
151
-#ifndef CONFIG_USER_ONLY
152
- /*
153
- * Get control bits for tagged addresses. Note that the
154
- * translator only uses this for instruction addresses.
155
- */
156
+ /* Get control bits for tagged addresses. */
157
{
158
ARMMMUIdx stage1 = stage_1_mmu_idx(mmu_idx);
159
ARMVAParameters p0 = aa64_va_parameters_both(env, 0, stage1);
160
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
161
flags = FIELD_DP32(flags, TBFLAG_A64, TBII, tbii);
162
flags = FIELD_DP32(flags, TBFLAG_A64, TBID, tbid);
163
}
164
-#endif
165
166
if (cpu_isar_feature(aa64_sve, cpu)) {
167
int sve_el = sve_exception_el(env, current_el);
168
--
81
--
169
2.20.1
82
2.34.1
170
83
171
84
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Don't allow the guest to write CNTHCTL_EL2 bits which don't exist.
2
This is not strictly architecturally required, but it is how we've
3
tended to implement registers more recently.
2
4
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
In particular, bits [19:18] are only present with FEAT_RME,
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
and bits [17:12] will only be present with FEAT_ECV.
5
Message-id: 20190128223118.5255-4-richard.henderson@linaro.org
7
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20240301183219.2424889-5-peter.maydell@linaro.org
7
---
11
---
8
target/arm/cpu.h | 2 ++
12
target/arm/helper.c | 18 ++++++++++++++++++
9
target/arm/translate.h | 4 ++++
13
1 file changed, 18 insertions(+)
10
target/arm/helper.c | 22 +++++++++++++++-------
11
target/arm/translate-a64.c | 2 ++
12
4 files changed, 23 insertions(+), 7 deletions(-)
13
14
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
17
+++ b/target/arm/cpu.h
18
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A64, TBII, 0, 2)
19
FIELD(TBFLAG_A64, SVEEXC_EL, 2, 2)
20
FIELD(TBFLAG_A64, ZCR_LEN, 4, 4)
21
FIELD(TBFLAG_A64, PAUTH_ACTIVE, 8, 1)
22
+FIELD(TBFLAG_A64, BT, 9, 1)
23
+FIELD(TBFLAG_A64, BTYPE, 10, 2)
24
25
static inline bool bswap_code(bool sctlr_b)
26
{
27
diff --git a/target/arm/translate.h b/target/arm/translate.h
28
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/translate.h
30
+++ b/target/arm/translate.h
31
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
32
bool ss_same_el;
33
/* True if v8.3-PAuth is active. */
34
bool pauth_active;
35
+ /* True with v8.5-BTI and SCTLR_ELx.BT* set. */
36
+ bool bt;
37
+ /* A copy of PSTATE.BTYPE, which will be 0 without v8.5-BTI. */
38
+ uint8_t btype;
39
/* Bottom two bits of XScale c15_cpar coprocessor access control reg */
40
int c15_cpar;
41
/* TCG op of the current insn_start. */
42
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
43
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/helper.c
17
--- a/target/arm/helper.c
45
+++ b/target/arm/helper.c
18
+++ b/target/arm/helper.c
46
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
19
@@ -XXX,XX +XXX,XX @@ static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
47
20
{
48
if (is_a64(env)) {
21
ARMCPU *cpu = env_archcpu(env);
49
ARMCPU *cpu = arm_env_get_cpu(env);
22
uint32_t oldval = env->cp15.cnthctl_el2;
50
+ uint64_t sctlr;
23
+ uint32_t valid_mask =
51
24
+ R_CNTHCTL_EL0PCTEN_E2H1_MASK |
52
*pc = env->pc;
25
+ R_CNTHCTL_EL0VCTEN_E2H1_MASK |
53
flags = FIELD_DP32(flags, TBFLAG_ANY, AARCH64_STATE, 1);
26
+ R_CNTHCTL_EVNTEN_MASK |
54
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
27
+ R_CNTHCTL_EVNTDIR_MASK |
55
flags = FIELD_DP32(flags, TBFLAG_A64, ZCR_LEN, zcr_len);
28
+ R_CNTHCTL_EVNTI_MASK |
56
}
29
+ R_CNTHCTL_EL0VTEN_MASK |
57
30
+ R_CNTHCTL_EL0PTEN_MASK |
58
+ if (current_el == 0) {
31
+ R_CNTHCTL_EL1PCTEN_E2H1_MASK |
59
+ /* FIXME: ARMv8.1-VHE S2 translation regime. */
32
+ R_CNTHCTL_EL1PTEN_MASK;
60
+ sctlr = env->cp15.sctlr_el[1];
61
+ } else {
62
+ sctlr = env->cp15.sctlr_el[current_el];
63
+ }
64
if (cpu_isar_feature(aa64_pauth, cpu)) {
65
/*
66
* In order to save space in flags, we record only whether
67
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
68
* a nop, or "active" when some action must be performed.
69
* The decision of which action to take is left to a helper.
70
*/
71
- uint64_t sctlr;
72
- if (current_el == 0) {
73
- /* FIXME: ARMv8.1-VHE S2 translation regime. */
74
- sctlr = env->cp15.sctlr_el[1];
75
- } else {
76
- sctlr = env->cp15.sctlr_el[current_el];
77
- }
78
if (sctlr & (SCTLR_EnIA | SCTLR_EnIB | SCTLR_EnDA | SCTLR_EnDB)) {
79
flags = FIELD_DP32(flags, TBFLAG_A64, PAUTH_ACTIVE, 1);
80
}
81
}
82
+
33
+
83
+ if (cpu_isar_feature(aa64_bti, cpu)) {
34
+ if (cpu_isar_feature(aa64_rme, cpu)) {
84
+ /* Note that SCTLR_EL[23].BT == SCTLR_BT1. */
35
+ valid_mask |= R_CNTHCTL_CNTVMASK_MASK | R_CNTHCTL_CNTPMASK_MASK;
85
+ if (sctlr & (current_el == 0 ? SCTLR_BT0 : SCTLR_BT1)) {
36
+ }
86
+ flags = FIELD_DP32(flags, TBFLAG_A64, BT, 1);
37
+
87
+ }
38
+ /* Clear RES0 bits */
88
+ flags = FIELD_DP32(flags, TBFLAG_A64, BTYPE, env->btype);
39
+ value &= valid_mask;
89
+ }
40
+
90
} else {
41
raw_write(env, ri, value);
91
*pc = env->regs[15];
42
92
flags = FIELD_DP32(flags, TBFLAG_A32, THUMB, env->thumb);
43
if ((oldval ^ value) & R_CNTHCTL_CNTVMASK_MASK) {
93
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
94
index XXXXXXX..XXXXXXX 100644
95
--- a/target/arm/translate-a64.c
96
+++ b/target/arm/translate-a64.c
97
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
98
dc->sve_excp_el = FIELD_EX32(tb_flags, TBFLAG_A64, SVEEXC_EL);
99
dc->sve_len = (FIELD_EX32(tb_flags, TBFLAG_A64, ZCR_LEN) + 1) * 16;
100
dc->pauth_active = FIELD_EX32(tb_flags, TBFLAG_A64, PAUTH_ACTIVE);
101
+ dc->bt = FIELD_EX32(tb_flags, TBFLAG_A64, BT);
102
+ dc->btype = FIELD_EX32(tb_flags, TBFLAG_A64, BTYPE);
103
dc->vec_len = 0;
104
dc->vec_stride = 0;
105
dc->cp_regs = arm_cpu->cp_regs;
106
--
44
--
107
2.20.1
45
2.34.1
108
109
diff view generated by jsdifflib
1
Factor out the "boot via firmware" code path from arm_load_kernel()
1
The functionality defined by ID_AA64MMFR0_EL1.ECV == 1 is:
2
into its own function.
2
* four new trap bits for various counter and timer registers
3
* the CNTHCTL_EL2.EVNTIS and CNTKCTL_EL1.EVNTIS bits which control
4
scaling of the event stream. This is a no-op for us, because we don't
5
implement the event stream (our WFE is a NOP): all we need to do is
6
allow CNTHCTL_EL2.ENVTIS to be read and written.
7
* extensions to PMSCR_EL1.PCT, PMSCR_EL2.PCT, TRFCR_EL1.TS and
8
TRFCR_EL2.TS: these are all no-ops for us, because we don't implement
9
FEAT_SPE or FEAT_TRF.
10
* new registers CNTPCTSS_EL0 and NCTVCTSS_EL0 which are
11
"self-sychronizing" views of the CNTPCT_EL0 and CNTVCT_EL0, meaning
12
that no barriers are needed around their accesses. For us these
13
are just the same as the normal views, because all our sysregs are
14
inherently self-sychronizing.
3
15
4
This commit only moves code around; no semantic changes.
16
In this commit we implement the trap handling and permit the new
17
CNTHCTL_EL2 bits to be written.
5
18
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
21
Message-id: 20240301183219.2424889-6-peter.maydell@linaro.org
9
Message-id: 20190131112240.8395-4-peter.maydell@linaro.org
10
---
22
---
11
hw/arm/boot.c | 92 +++++++++++++++++++++++++++------------------------
23
target/arm/cpu-features.h | 5 ++++
12
1 file changed, 49 insertions(+), 43 deletions(-)
24
target/arm/helper.c | 51 +++++++++++++++++++++++++++++++++++----
25
2 files changed, 51 insertions(+), 5 deletions(-)
13
26
14
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
27
diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
15
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/boot.c
29
--- a/target/arm/cpu-features.h
17
+++ b/hw/arm/boot.c
30
+++ b/target/arm/cpu-features.h
18
@@ -XXX,XX +XXX,XX @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
31
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_fgt(const ARMISARegisters *id)
32
return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, FGT) != 0;
33
}
34
35
+static inline bool isar_feature_aa64_ecv_traps(const ARMISARegisters *id)
36
+{
37
+ return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, ECV) > 0;
38
+}
39
+
40
static inline bool isar_feature_aa64_vh(const ARMISARegisters *id)
41
{
42
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0;
43
diff --git a/target/arm/helper.c b/target/arm/helper.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/helper.c
46
+++ b/target/arm/helper.c
47
@@ -XXX,XX +XXX,XX @@ static CPAccessResult gt_counter_access(CPUARMState *env, int timeridx,
48
: !extract32(env->cp15.cnthctl_el2, 0, 1))) {
49
return CP_ACCESS_TRAP_EL2;
50
}
51
+ if (has_el2 && timeridx == GTIMER_VIRT) {
52
+ if (FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, EL1TVCT)) {
53
+ return CP_ACCESS_TRAP_EL2;
54
+ }
55
+ }
56
break;
19
}
57
}
58
return CP_ACCESS_OK;
59
@@ -XXX,XX +XXX,XX @@ static CPAccessResult gt_timer_access(CPUARMState *env, int timeridx,
60
}
61
}
62
}
63
+ if (has_el2 && timeridx == GTIMER_VIRT) {
64
+ if (FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, EL1TVT)) {
65
+ return CP_ACCESS_TRAP_EL2;
66
+ }
67
+ }
68
break;
69
}
70
return CP_ACCESS_OK;
71
@@ -XXX,XX +XXX,XX @@ static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
72
if (cpu_isar_feature(aa64_rme, cpu)) {
73
valid_mask |= R_CNTHCTL_CNTVMASK_MASK | R_CNTHCTL_CNTPMASK_MASK;
74
}
75
+ if (cpu_isar_feature(aa64_ecv_traps, cpu)) {
76
+ valid_mask |=
77
+ R_CNTHCTL_EL1TVT_MASK |
78
+ R_CNTHCTL_EL1TVCT_MASK |
79
+ R_CNTHCTL_EL1NVPCT_MASK |
80
+ R_CNTHCTL_EL1NVVCT_MASK |
81
+ R_CNTHCTL_EVNTIS_MASK;
82
+ }
83
84
/* Clear RES0 bits */
85
value &= valid_mask;
86
@@ -XXX,XX +XXX,XX @@ static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
87
{
88
if (arm_current_el(env) == 1) {
89
/* This must be a FEAT_NV access */
90
- /* TODO: FEAT_ECV will need to check CNTHCTL_EL2 here */
91
return CP_ACCESS_OK;
92
}
93
if (!(arm_hcr_el2_eff(env) & HCR_E2H)) {
94
@@ -XXX,XX +XXX,XX @@ static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
95
return CP_ACCESS_OK;
20
}
96
}
21
97
22
+static void arm_setup_firmware_boot(ARMCPU *cpu, struct arm_boot_info *info)
98
+static CPAccessResult access_el1nvpct(CPUARMState *env, const ARMCPRegInfo *ri,
99
+ bool isread)
23
+{
100
+{
24
+ /* Set up for booting firmware (which might load a kernel via fw_cfg) */
101
+ if (arm_current_el(env) == 1) {
25
+
102
+ /* This must be a FEAT_NV access with NVx == 101 */
26
+ if (have_dtb(info)) {
103
+ if (FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, EL1NVPCT)) {
27
+ /*
104
+ return CP_ACCESS_TRAP_EL2;
28
+ * If we have a device tree blob, but no kernel to supply it to (or
29
+ * the kernel is supposed to be loaded by the bootloader), copy the
30
+ * DTB to the base of RAM for the bootloader to pick up.
31
+ */
32
+ info->dtb_start = info->loader_start;
33
+ }
34
+
35
+ if (info->kernel_filename) {
36
+ FWCfgState *fw_cfg;
37
+ bool try_decompressing_kernel;
38
+
39
+ fw_cfg = fw_cfg_find();
40
+ try_decompressing_kernel = arm_feature(&cpu->env,
41
+ ARM_FEATURE_AARCH64);
42
+
43
+ /*
44
+ * Expose the kernel, the command line, and the initrd in fw_cfg.
45
+ * We don't process them here at all, it's all left to the
46
+ * firmware.
47
+ */
48
+ load_image_to_fw_cfg(fw_cfg,
49
+ FW_CFG_KERNEL_SIZE, FW_CFG_KERNEL_DATA,
50
+ info->kernel_filename,
51
+ try_decompressing_kernel);
52
+ load_image_to_fw_cfg(fw_cfg,
53
+ FW_CFG_INITRD_SIZE, FW_CFG_INITRD_DATA,
54
+ info->initrd_filename, false);
55
+
56
+ if (info->kernel_cmdline) {
57
+ fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
58
+ strlen(info->kernel_cmdline) + 1);
59
+ fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA,
60
+ info->kernel_cmdline);
61
+ }
105
+ }
62
+ }
106
+ }
63
+
107
+ return e2h_access(env, ri, isread);
64
+ /*
65
+ * We will start from address 0 (typically a boot ROM image) in the
66
+ * same way as hardware.
67
+ */
68
+}
108
+}
69
+
109
+
70
void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
110
+static CPAccessResult access_el1nvvct(CPUARMState *env, const ARMCPRegInfo *ri,
111
+ bool isread)
112
+{
113
+ if (arm_current_el(env) == 1) {
114
+ /* This must be a FEAT_NV access with NVx == 101 */
115
+ if (FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, EL1NVVCT)) {
116
+ return CP_ACCESS_TRAP_EL2;
117
+ }
118
+ }
119
+ return e2h_access(env, ri, isread);
120
+}
121
+
122
/* Test if system register redirection is to occur in the current state. */
123
static bool redirect_for_e2h(CPUARMState *env)
71
{
124
{
72
CPUState *cs;
125
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vhe_reginfo[] = {
73
@@ -XXX,XX +XXX,XX @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
126
{ .name = "CNTP_CTL_EL02", .state = ARM_CP_STATE_AA64,
74
127
.opc0 = 3, .opc1 = 5, .crn = 14, .crm = 2, .opc2 = 1,
75
/* Load the kernel. */
128
.type = ARM_CP_IO | ARM_CP_ALIAS,
76
if (!info->kernel_filename || info->firmware_loaded) {
129
- .access = PL2_RW, .accessfn = e2h_access,
77
-
130
+ .access = PL2_RW, .accessfn = access_el1nvpct,
78
- if (have_dtb(info)) {
131
.nv2_redirect_offset = 0x180 | NV2_REDIR_NO_NV1,
79
- /*
132
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].ctl),
80
- * If we have a device tree blob, but no kernel to supply it to (or
133
.writefn = gt_phys_ctl_write, .raw_writefn = raw_write },
81
- * the kernel is supposed to be loaded by the bootloader), copy the
134
{ .name = "CNTV_CTL_EL02", .state = ARM_CP_STATE_AA64,
82
- * DTB to the base of RAM for the bootloader to pick up.
135
.opc0 = 3, .opc1 = 5, .crn = 14, .crm = 3, .opc2 = 1,
83
- */
136
.type = ARM_CP_IO | ARM_CP_ALIAS,
84
- info->dtb_start = info->loader_start;
137
- .access = PL2_RW, .accessfn = e2h_access,
85
- }
138
+ .access = PL2_RW, .accessfn = access_el1nvvct,
86
-
139
.nv2_redirect_offset = 0x170 | NV2_REDIR_NO_NV1,
87
- if (info->kernel_filename) {
140
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].ctl),
88
- FWCfgState *fw_cfg;
141
.writefn = gt_virt_ctl_write, .raw_writefn = raw_write },
89
- bool try_decompressing_kernel;
142
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vhe_reginfo[] = {
90
-
143
.type = ARM_CP_IO | ARM_CP_ALIAS,
91
- fw_cfg = fw_cfg_find();
144
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].cval),
92
- try_decompressing_kernel = arm_feature(&cpu->env,
145
.nv2_redirect_offset = 0x178 | NV2_REDIR_NO_NV1,
93
- ARM_FEATURE_AARCH64);
146
- .access = PL2_RW, .accessfn = e2h_access,
94
-
147
+ .access = PL2_RW, .accessfn = access_el1nvpct,
95
- /*
148
.writefn = gt_phys_cval_write, .raw_writefn = raw_write },
96
- * Expose the kernel, the command line, and the initrd in fw_cfg.
149
{ .name = "CNTV_CVAL_EL02", .state = ARM_CP_STATE_AA64,
97
- * We don't process them here at all, it's all left to the
150
.opc0 = 3, .opc1 = 5, .crn = 14, .crm = 3, .opc2 = 2,
98
- * firmware.
151
.type = ARM_CP_IO | ARM_CP_ALIAS,
99
- */
152
.nv2_redirect_offset = 0x168 | NV2_REDIR_NO_NV1,
100
- load_image_to_fw_cfg(fw_cfg,
153
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].cval),
101
- FW_CFG_KERNEL_SIZE, FW_CFG_KERNEL_DATA,
154
- .access = PL2_RW, .accessfn = e2h_access,
102
- info->kernel_filename,
155
+ .access = PL2_RW, .accessfn = access_el1nvvct,
103
- try_decompressing_kernel);
156
.writefn = gt_virt_cval_write, .raw_writefn = raw_write },
104
- load_image_to_fw_cfg(fw_cfg,
157
#endif
105
- FW_CFG_INITRD_SIZE, FW_CFG_INITRD_DATA,
158
};
106
- info->initrd_filename, false);
107
-
108
- if (info->kernel_cmdline) {
109
- fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
110
- strlen(info->kernel_cmdline) + 1);
111
- fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA,
112
- info->kernel_cmdline);
113
- }
114
- }
115
-
116
- /*
117
- * We will start from address 0 (typically a boot ROM image) in the
118
- * same way as hardware.
119
- */
120
+ arm_setup_firmware_boot(cpu, info);
121
return;
122
} else {
123
arm_setup_direct_kernel_boot(cpu, info);
124
--
159
--
125
2.20.1
160
2.34.1
126
127
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
For FEAT_ECV, new registers CNTPCTSS_EL0 and CNTVCTSS_EL0 are
2
defined, which are "self-synchronized" views of the physical and
3
virtual counts as seen in the CNTPCT_EL0 and CNTVCT_EL0 registers
4
(meaning that no barriers are needed around accesses to them to
5
ensure that reads of them do not occur speculatively and out-of-order
6
with other instructions).
2
7
3
Split out gen_top_byte_ignore in preparation of handling these
8
For QEMU, all our system registers are self-synchronized, so we can
4
data accesses; the new tbflags field is not yet honored.
9
simply copy the existing implementation of CNTPCT_EL0 and CNTVCT_EL0
10
to the new register encodings.
5
11
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
This means we now implement all the functionality required for
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
ID_AA64MMFR0_EL1.ECV == 0b0001.
8
Message-id: 20190204132126.3255-2-richard.henderson@linaro.org
14
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20240301183219.2424889-7-peter.maydell@linaro.org
10
---
18
---
11
target/arm/cpu.h | 1 +
19
target/arm/helper.c | 43 +++++++++++++++++++++++++++++++++++++++++++
12
target/arm/translate.h | 3 +-
20
1 file changed, 43 insertions(+)
13
target/arm/helper.c | 1 +
14
target/arm/translate-a64.c | 72 +++++++++++++++++++-------------------
15
4 files changed, 40 insertions(+), 37 deletions(-)
16
21
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/cpu.h
20
+++ b/target/arm/cpu.h
21
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A64, ZCR_LEN, 4, 4)
22
FIELD(TBFLAG_A64, PAUTH_ACTIVE, 8, 1)
23
FIELD(TBFLAG_A64, BT, 9, 1)
24
FIELD(TBFLAG_A64, BTYPE, 10, 2)
25
+FIELD(TBFLAG_A64, TBID, 12, 2)
26
27
static inline bool bswap_code(bool sctlr_b)
28
{
29
diff --git a/target/arm/translate.h b/target/arm/translate.h
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/translate.h
32
+++ b/target/arm/translate.h
33
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
34
int user;
35
#endif
36
ARMMMUIdx mmu_idx; /* MMU index to use for normal loads/stores */
37
- uint8_t tbii; /* TBI1|TBI0 for EL0/1 or TBI for EL2/3 */
38
+ uint8_t tbii; /* TBI1|TBI0 for insns */
39
+ uint8_t tbid; /* TBI1|TBI0 for data */
40
bool ns; /* Use non-secure CPREG bank on access */
41
int fp_excp_el; /* FP exception EL or 0 if enabled */
42
int sve_excp_el; /* SVE exception EL or 0 if enabled */
43
diff --git a/target/arm/helper.c b/target/arm/helper.c
22
diff --git a/target/arm/helper.c b/target/arm/helper.c
44
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/helper.c
24
--- a/target/arm/helper.c
46
+++ b/target/arm/helper.c
25
+++ b/target/arm/helper.c
47
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
26
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
48
}
27
},
49
28
};
50
flags = FIELD_DP32(flags, TBFLAG_A64, TBII, tbii);
29
51
+ flags = FIELD_DP32(flags, TBFLAG_A64, TBID, tbid);
30
+/*
52
}
31
+ * FEAT_ECV adds extra views of CNTVCT_EL0 and CNTPCT_EL0 which
32
+ * are "self-synchronizing". For QEMU all sysregs are self-synchronizing,
33
+ * so our implementations here are identical to the normal registers.
34
+ */
35
+static const ARMCPRegInfo gen_timer_ecv_cp_reginfo[] = {
36
+ { .name = "CNTVCTSS", .cp = 15, .crm = 14, .opc1 = 9,
37
+ .access = PL0_R, .type = ARM_CP_64BIT | ARM_CP_NO_RAW | ARM_CP_IO,
38
+ .accessfn = gt_vct_access,
39
+ .readfn = gt_virt_cnt_read, .resetfn = arm_cp_reset_ignore,
40
+ },
41
+ { .name = "CNTVCTSS_EL0", .state = ARM_CP_STATE_AA64,
42
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 6,
43
+ .access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
44
+ .accessfn = gt_vct_access, .readfn = gt_virt_cnt_read,
45
+ },
46
+ { .name = "CNTPCTSS", .cp = 15, .crm = 14, .opc1 = 8,
47
+ .access = PL0_R, .type = ARM_CP_64BIT | ARM_CP_NO_RAW | ARM_CP_IO,
48
+ .accessfn = gt_pct_access,
49
+ .readfn = gt_cnt_read, .resetfn = arm_cp_reset_ignore,
50
+ },
51
+ { .name = "CNTPCTSS_EL0", .state = ARM_CP_STATE_AA64,
52
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 5,
53
+ .access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
54
+ .accessfn = gt_pct_access, .readfn = gt_cnt_read,
55
+ },
56
+};
57
+
58
#else
59
60
/*
61
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
62
},
63
};
64
65
+/*
66
+ * CNTVCTSS_EL0 has the same trap conditions as CNTVCT_EL0, so it also
67
+ * is exposed to userspace by Linux.
68
+ */
69
+static const ARMCPRegInfo gen_timer_ecv_cp_reginfo[] = {
70
+ { .name = "CNTVCTSS_EL0", .state = ARM_CP_STATE_AA64,
71
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 6,
72
+ .access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
73
+ .readfn = gt_virt_cnt_read,
74
+ },
75
+};
76
+
53
#endif
77
#endif
54
78
55
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
79
static void par_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
56
index XXXXXXX..XXXXXXX 100644
80
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
57
--- a/target/arm/translate-a64.c
81
if (arm_feature(env, ARM_FEATURE_GENERIC_TIMER)) {
58
+++ b/target/arm/translate-a64.c
82
define_arm_cp_regs(cpu, generic_timer_cp_reginfo);
59
@@ -XXX,XX +XXX,XX @@ void gen_a64_set_pc_im(uint64_t val)
60
tcg_gen_movi_i64(cpu_pc, val);
61
}
62
63
-/* Load the PC from a generic TCG variable.
64
+/*
65
+ * Handle Top Byte Ignore (TBI) bits.
66
*
67
- * If address tagging is enabled via the TCR TBI bits, then loading
68
- * an address into the PC will clear out any tag in it:
69
+ * If address tagging is enabled via the TCR TBI bits:
70
* + for EL2 and EL3 there is only one TBI bit, and if it is set
71
* then the address is zero-extended, clearing bits [63:56]
72
* + for EL0 and EL1, TBI0 controls addresses with bit 55 == 0
73
@@ -XXX,XX +XXX,XX @@ void gen_a64_set_pc_im(uint64_t val)
74
* If the appropriate TBI bit is set for the address then
75
* the address is sign-extended from bit 55 into bits [63:56]
76
*
77
- * We can avoid doing this for relative-branches, because the
78
- * PC + offset can never overflow into the tag bits (assuming
79
- * that virtual addresses are less than 56 bits wide, as they
80
- * are currently), but we must handle it for branch-to-register.
81
+ * Here We have concatenated TBI{1,0} into tbi.
82
*/
83
-static void gen_a64_set_pc(DisasContext *s, TCGv_i64 src)
84
+static void gen_top_byte_ignore(DisasContext *s, TCGv_i64 dst,
85
+ TCGv_i64 src, int tbi)
86
{
87
- /* Note that TBII is TBI1:TBI0. */
88
- int tbi = s->tbii;
89
-
90
- if (s->current_el <= 1) {
91
- if (tbi != 0) {
92
- /* Sign-extend from bit 55. */
93
- tcg_gen_sextract_i64(cpu_pc, src, 0, 56);
94
-
95
- if (tbi != 3) {
96
- TCGv_i64 tcg_zero = tcg_const_i64(0);
97
-
98
- /*
99
- * The two TBI bits differ.
100
- * If tbi0, then !tbi1: only use the extension if positive.
101
- * if !tbi0, then tbi1: only use the extension if negative.
102
- */
103
- tcg_gen_movcond_i64(tbi == 1 ? TCG_COND_GE : TCG_COND_LT,
104
- cpu_pc, cpu_pc, tcg_zero, cpu_pc, src);
105
- tcg_temp_free_i64(tcg_zero);
106
- }
107
- return;
108
- }
109
+ if (tbi == 0) {
110
+ /* Load unmodified address */
111
+ tcg_gen_mov_i64(dst, src);
112
+ } else if (s->current_el >= 2) {
113
+ /* FIXME: ARMv8.1-VHE S2 translation regime. */
114
+ /* Force tag byte to all zero */
115
+ tcg_gen_extract_i64(dst, src, 0, 56);
116
} else {
117
- if (tbi != 0) {
118
- /* Force tag byte to all zero */
119
- tcg_gen_extract_i64(cpu_pc, src, 0, 56);
120
- return;
121
+ /* Sign-extend from bit 55. */
122
+ tcg_gen_sextract_i64(dst, src, 0, 56);
123
+
124
+ if (tbi != 3) {
125
+ TCGv_i64 tcg_zero = tcg_const_i64(0);
126
+
127
+ /*
128
+ * The two TBI bits differ.
129
+ * If tbi0, then !tbi1: only use the extension if positive.
130
+ * if !tbi0, then tbi1: only use the extension if negative.
131
+ */
132
+ tcg_gen_movcond_i64(tbi == 1 ? TCG_COND_GE : TCG_COND_LT,
133
+ dst, dst, tcg_zero, dst, src);
134
+ tcg_temp_free_i64(tcg_zero);
135
}
136
}
83
}
137
+}
84
+ if (cpu_isar_feature(aa64_ecv_traps, cpu)) {
138
85
+ define_arm_cp_regs(cpu, gen_timer_ecv_cp_reginfo);
139
- /* Load unmodified address */
86
+ }
140
- tcg_gen_mov_i64(cpu_pc, src);
87
if (arm_feature(env, ARM_FEATURE_VAPA)) {
141
+static void gen_a64_set_pc(DisasContext *s, TCGv_i64 src)
88
ARMCPRegInfo vapa_cp_reginfo[] = {
142
+{
89
{ .name = "PAR", .cp = 15, .crn = 7, .crm = 4, .opc1 = 0, .opc2 = 0,
143
+ /*
144
+ * If address tagging is enabled for instructions via the TCR TBI bits,
145
+ * then loading an address into the PC will clear out any tag.
146
+ */
147
+ gen_top_byte_ignore(s, cpu_pc, src, s->tbii);
148
}
149
150
typedef struct DisasCompare64 {
151
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
152
core_mmu_idx = FIELD_EX32(tb_flags, TBFLAG_ANY, MMUIDX);
153
dc->mmu_idx = core_to_arm_mmu_idx(env, core_mmu_idx);
154
dc->tbii = FIELD_EX32(tb_flags, TBFLAG_A64, TBII);
155
+ dc->tbid = FIELD_EX32(tb_flags, TBFLAG_A64, TBID);
156
dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
157
#if !defined(CONFIG_USER_ONLY)
158
dc->user = (dc->current_el == 0);
159
--
90
--
160
2.20.1
91
2.34.1
161
162
diff view generated by jsdifflib
1
The {IOE, DZE, OFE, UFE, IXE, IDE} bits in the FPSCR/FPCR are for
1
When ID_AA64MMFR0_EL1.ECV is 0b0010, a new register CNTPOFF_EL2 is
2
enabling trapped IEEE floating point exceptions (where IEEE exception
2
implemented. This is similar to the existing CNTVOFF_EL2, except
3
conditions cause a CPU exception rather than updating the FPSR status
3
that it controls a hypervisor-adjustable offset made to the physical
4
bits). QEMU doesn't implement this (and nor does the hardware we're
4
counter and timer.
5
modelling), but for implementations which don't implement trapped
6
exception handling these control bits are supposed to be RAZ/WI.
7
This allows guest code to test for whether the feature is present
8
by trying to write to the bit and checking whether it sticks.
9
5
10
QEMU is incorrectly making these bits read as written. Make them
6
Implement the handling for this register, which includes control/trap
11
RAZ/WI as the architecture requires.
7
bits in SCR_EL3 and CNTHCTL_EL2.
12
8
13
In particular this was causing problems for the NetBSD automatic
14
test suite.
15
16
Reported-by: Martin Husemann <martin@netbsd.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
Message-id: 20190131130700.28392-1-peter.maydell@linaro.org
11
Message-id: 20240301183219.2424889-8-peter.maydell@linaro.org
20
---
12
---
21
target/arm/cpu.h | 6 ++++++
13
target/arm/cpu-features.h | 5 +++
22
target/arm/helper.c | 6 ++++++
14
target/arm/cpu.h | 1 +
23
2 files changed, 12 insertions(+)
15
target/arm/helper.c | 68 +++++++++++++++++++++++++++++++++++++--
16
target/arm/trace-events | 1 +
17
4 files changed, 73 insertions(+), 2 deletions(-)
24
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;
25
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
26
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
27
--- a/target/arm/cpu.h
37
--- a/target/arm/cpu.h
28
+++ b/target/arm/cpu.h
38
+++ b/target/arm/cpu.h
29
@@ -XXX,XX +XXX,XX @@ void vfp_set_fpscr(CPUARMState *env, uint32_t val);
39
@@ -XXX,XX +XXX,XX @@ typedef struct CPUArchState {
30
#define FPSR_MASK 0xf800009f
40
uint64_t c14_cntkctl; /* Timer Control register */
31
#define FPCR_MASK 0x07ff9f00
41
uint64_t cnthctl_el2; /* Counter/Timer Hyp Control register */
32
42
uint64_t cntvoff_el2; /* Counter Virtual Offset register */
33
+#define FPCR_IOE (1 << 8) /* Invalid Operation exception trap enable */
43
+ uint64_t cntpoff_el2; /* Counter Physical Offset register */
34
+#define FPCR_DZE (1 << 9) /* Divide by Zero exception trap enable */
44
ARMGenericTimer c14_timer[NUM_GTIMERS];
35
+#define FPCR_OFE (1 << 10) /* Overflow exception trap enable */
45
uint32_t c15_cpar; /* XScale Coprocessor Access Register */
36
+#define FPCR_UFE (1 << 11) /* Underflow exception trap enable */
46
uint32_t c15_ticonfig; /* TI925T configuration byte. */
37
+#define FPCR_IXE (1 << 12) /* Inexact exception trap enable */
38
+#define FPCR_IDE (1 << 15) /* Input Denormal exception trap enable */
39
#define FPCR_FZ16 (1 << 19) /* ARMv8.2+, FP16 flush-to-zero */
40
#define FPCR_FZ (1 << 24) /* Flush-to-zero enable bit */
41
#define FPCR_DN (1 << 25) /* Default NaN enable bit */
42
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
43
index XXXXXXX..XXXXXXX 100644
48
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/helper.c
49
--- a/target/arm/helper.c
45
+++ b/target/arm/helper.c
50
+++ b/target/arm/helper.c
46
@@ -XXX,XX +XXX,XX @@ void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
51
@@ -XXX,XX +XXX,XX @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
47
val &= ~FPCR_FZ16;
52
if (cpu_isar_feature(aa64_rme, cpu)) {
53
valid_mask |= SCR_NSE | SCR_GPF;
54
}
55
+ if (cpu_isar_feature(aa64_ecv, cpu)) {
56
+ valid_mask |= SCR_ECVEN;
57
+ }
58
} else {
59
valid_mask &= ~(SCR_RW | SCR_ST);
60
if (cpu_isar_feature(aa32_ras, cpu)) {
61
@@ -XXX,XX +XXX,XX @@ void gt_rme_post_el_change(ARMCPU *cpu, void *ignored)
62
gt_update_irq(cpu, GTIMER_PHYS);
63
}
64
65
+static uint64_t gt_phys_raw_cnt_offset(CPUARMState *env)
66
+{
67
+ if ((env->cp15.scr_el3 & SCR_ECVEN) &&
68
+ FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, ECV) &&
69
+ arm_is_el2_enabled(env) &&
70
+ (arm_hcr_el2_eff(env) & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE)) {
71
+ return env->cp15.cntpoff_el2;
72
+ }
73
+ return 0;
74
+}
75
+
76
+static uint64_t gt_phys_cnt_offset(CPUARMState *env)
77
+{
78
+ if (arm_current_el(env) >= 2) {
79
+ return 0;
80
+ }
81
+ return gt_phys_raw_cnt_offset(env);
82
+}
83
+
84
static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
85
{
86
ARMGenericTimer *gt = &cpu->env.cp15.c14_timer[timeridx];
87
@@ -XXX,XX +XXX,XX @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
88
* reset timer to when ISTATUS next has to change
89
*/
90
uint64_t offset = timeridx == GTIMER_VIRT ?
91
- cpu->env.cp15.cntvoff_el2 : 0;
92
+ cpu->env.cp15.cntvoff_el2 : gt_phys_raw_cnt_offset(&cpu->env);
93
uint64_t count = gt_get_countervalue(&cpu->env);
94
/* Note that this must be unsigned 64 bit arithmetic: */
95
int istatus = count - offset >= gt->cval;
96
@@ -XXX,XX +XXX,XX @@ static void gt_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri,
97
98
static uint64_t gt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
99
{
100
- return gt_get_countervalue(env);
101
+ return gt_get_countervalue(env) - gt_phys_cnt_offset(env);
102
}
103
104
static uint64_t gt_virt_cnt_offset(CPUARMState *env)
105
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
106
case GTIMER_HYPVIRT:
107
offset = gt_virt_cnt_offset(env);
108
break;
109
+ case GTIMER_PHYS:
110
+ offset = gt_phys_cnt_offset(env);
111
+ break;
48
}
112
}
49
113
50
+ /*
114
return (uint32_t)(env->cp15.c14_timer[timeridx].cval -
51
+ * We don't implement trapped exception handling, so the
115
@@ -XXX,XX +XXX,XX @@ static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
52
+ * trap enable bits are all RAZ/WI (not RES0!)
116
case GTIMER_HYPVIRT:
53
+ */
117
offset = gt_virt_cnt_offset(env);
54
+ val &= ~(FPCR_IDE | FPCR_IXE | FPCR_UFE | FPCR_OFE | FPCR_DZE | FPCR_IOE);
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
+}
55
+
148
+
56
changed = env->vfp.xregs[ARM_VFP_FPSCR];
149
+static void gt_cntpoff_write(CPUARMState *env, const ARMCPRegInfo *ri,
57
env->vfp.xregs[ARM_VFP_FPSCR] = (val & 0xffc8ffff);
150
+ uint64_t value)
58
env->vfp.vec_len = (val >> 16) & 7;
151
+{
152
+ ARMCPU *cpu = env_archcpu(env);
153
+
154
+ trace_arm_gt_cntpoff_write(value);
155
+ raw_write(env, ri, value);
156
+ gt_recalc_timer(cpu, GTIMER_PHYS);
157
+}
158
+
159
+static const ARMCPRegInfo gen_timer_cntpoff_reginfo = {
160
+ .name = "CNTPOFF_EL2", .state = ARM_CP_STATE_AA64,
161
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 0, .opc2 = 6,
162
+ .access = PL2_RW, .type = ARM_CP_IO, .resetvalue = 0,
163
+ .accessfn = gt_cntpoff_access, .writefn = gt_cntpoff_write,
164
+ .nv2_redirect_offset = 0x1a8,
165
+ .fieldoffset = offsetof(CPUARMState, cp15.cntpoff_el2),
166
+};
167
#else
168
169
/*
170
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
171
if (cpu_isar_feature(aa64_ecv_traps, cpu)) {
172
define_arm_cp_regs(cpu, gen_timer_ecv_cp_reginfo);
173
}
174
+#ifndef CONFIG_USER_ONLY
175
+ if (cpu_isar_feature(aa64_ecv, cpu)) {
176
+ define_one_arm_cp_reg(cpu, &gen_timer_cntpoff_reginfo);
177
+ }
178
+#endif
179
if (arm_feature(env, ARM_FEATURE_VAPA)) {
180
ARMCPRegInfo vapa_cp_reginfo[] = {
181
{ .name = "PAR", .cp = 15, .crn = 7, .crm = 4, .opc1 = 0, .opc2 = 0,
182
diff --git a/target/arm/trace-events b/target/arm/trace-events
183
index XXXXXXX..XXXXXXX 100644
184
--- a/target/arm/trace-events
185
+++ b/target/arm/trace-events
186
@@ -XXX,XX +XXX,XX @@ arm_gt_tval_write(int timer, uint64_t value) "gt_tval_write: timer %d value 0x%"
187
arm_gt_ctl_write(int timer, uint64_t value) "gt_ctl_write: timer %d value 0x%" PRIx64
188
arm_gt_imask_toggle(int timer) "gt_ctl_write: timer %d IMASK toggle"
189
arm_gt_cntvoff_write(uint64_t value) "gt_cntvoff_write: value 0x%" PRIx64
190
+arm_gt_cntpoff_write(uint64_t value) "gt_cntpoff_write: value 0x%" PRIx64
191
arm_gt_update_irq(int timer, int irqstate) "gt_update_irq: timer %d irqstate %d"
192
193
# kvm.c
59
--
194
--
60
2.20.1
195
2.34.1
61
62
diff view generated by jsdifflib
1
The arm_boot_info struct has a skip_dtb_autoload flag: if this is
1
Enable all FEAT_ECV features on the 'max' CPU.
2
set to true by the board code then arm_load_kernel() will not
3
load the DTB itself, but will leave this for the board code to
4
do itself later. However, the check for this is done in a
5
code path which is only executed for the case where we load
6
a kernel image file. If we're taking the "boot via firmware"
7
code path then the flag isn't honoured and the DTB is never
8
loaded.
9
10
We didn't notice this because the only real user of "boot
11
via firmware" that cares about the DTB is the virt board
12
(for UEFI boot), and that always wants skip_dtb_autoload
13
anyway. But the SBSA reference board model we're planning to
14
add will want the flag to behave correctly.
15
16
Now we've refactored the arm_load_kernel() function, the
17
fix is simple: drop the early 'return' so we fall into
18
the same "load the DTB" code the boot-direct-kernel path uses.
19
2
20
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>
21
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
22
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
6
Message-id: 20240301183219.2424889-9-peter.maydell@linaro.org
23
Message-id: 20190131112240.8395-6-peter.maydell@linaro.org
24
---
7
---
25
hw/arm/boot.c | 1 -
8
docs/system/arm/emulation.rst | 1 +
26
1 file changed, 1 deletion(-)
9
target/arm/tcg/cpu64.c | 1 +
10
2 files changed, 2 insertions(+)
27
11
28
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
12
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
29
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
30
--- a/hw/arm/boot.c
14
--- a/docs/system/arm/emulation.rst
31
+++ b/hw/arm/boot.c
15
+++ b/docs/system/arm/emulation.rst
32
@@ -XXX,XX +XXX,XX @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
16
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
33
/* Load the kernel. */
17
- FEAT_DotProd (Advanced SIMD dot product instructions)
34
if (!info->kernel_filename || info->firmware_loaded) {
18
- FEAT_DoubleFault (Double Fault Extension)
35
arm_setup_firmware_boot(cpu, info);
19
- FEAT_E0PD (Preventing EL0 access to halves of address maps)
36
- return;
20
+- FEAT_ECV (Enhanced Counter Virtualization)
37
} else {
21
- FEAT_EPAC (Enhanced pointer authentication)
38
arm_setup_direct_kernel_boot(cpu, info);
22
- FEAT_ETS (Enhanced Translation Synchronization)
39
}
23
- FEAT_EVT (Enhanced Virtualization Traps)
24
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
25
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/tcg/cpu64.c
27
+++ b/target/arm/tcg/cpu64.c
28
@@ -XXX,XX +XXX,XX @@ void aarch64_max_tcg_initfn(Object *obj)
29
t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN64_2, 2); /* 64k stage2 supported */
30
t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN4_2, 2); /* 4k stage2 supported */
31
t = FIELD_DP64(t, ID_AA64MMFR0, FGT, 1); /* FEAT_FGT */
32
+ t = FIELD_DP64(t, ID_AA64MMFR0, ECV, 2); /* FEAT_ECV */
33
cpu->isar.id_aa64mmfr0 = t;
34
35
t = cpu->isar.id_aa64mmfr1;
40
--
36
--
41
2.20.1
37
2.34.1
42
38
43
39
diff view generated by jsdifflib
1
Factor out the "direct kernel boot" code path from arm_load_kernel()
1
From: Inès Varhol <ines.varhol@telecom-paris.fr>
2
into its own function; this function is getting long enough that
3
the code flow is a bit confusing.
4
2
5
This commit only moves code around; no semantic changes.
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
6
12
7
We leave the "load the dtb" code in arm_load_kernel() -- this
13
Difference with the real GPIOs :
8
is currently only used by the "direct kernel boot" path, but
14
- Alternate Function and Analog mode aren't implemented :
9
this is a bug which we will fix shortly.
15
pins in AF/Analog behave like pins in input mode
16
- floating pins stay at their last value
17
- register IDR reset values differ from the real one :
18
values are coherent with the other registers reset values
19
and the fact that AF/Analog modes aren't implemented
20
- setting I/O output speed isn't supported
21
- locking port bits isn't supported
22
- ADC function isn't supported
23
- GPIOH has 16 pins instead of 2 pins
24
- writing to registers LCKR, AFRL, AFRH and ASCR is ineffective
10
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
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
14
Message-id: 20190131112240.8395-3-peter.maydell@linaro.org
15
---
32
---
16
hw/arm/boot.c | 150 +++++++++++++++++++++++++++-----------------------
33
MAINTAINERS | 1 +
17
1 file changed, 80 insertions(+), 70 deletions(-)
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
18
43
19
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
44
diff --git a/MAINTAINERS b/MAINTAINERS
20
index XXXXXXX..XXXXXXX 100644
45
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/arm/boot.c
46
--- a/MAINTAINERS
22
+++ b/hw/arm/boot.c
47
+++ b/MAINTAINERS
23
@@ -XXX,XX +XXX,XX @@ static uint64_t load_aarch64_image(const char *filename, hwaddr mem_base,
48
@@ -XXX,XX +XXX,XX @@ F: hw/arm/stm32l4x5_soc.c
24
return size;
49
F: hw/misc/stm32l4x5_exti.c
25
}
50
F: hw/misc/stm32l4x5_syscfg.c
26
51
F: hw/misc/stm32l4x5_rcc.c
27
-void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
52
+F: hw/gpio/stm32l4x5_gpio.c
28
+static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
53
F: include/hw/*/stm32l4x5_*.h
29
+ struct arm_boot_info *info)
54
30
{
55
B-L475E-IOT01A IoT Node
31
+ /* Set up for a direct boot of a kernel image file. */
56
diff --git a/docs/system/arm/b-l475e-iot01a.rst b/docs/system/arm/b-l475e-iot01a.rst
32
CPUState *cs;
57
index XXXXXXX..XXXXXXX 100644
33
+ AddressSpace *as = arm_boot_address_space(cpu, info);
58
--- a/docs/system/arm/b-l475e-iot01a.rst
34
int kernel_size;
59
+++ b/docs/system/arm/b-l475e-iot01a.rst
35
int initrd_size;
60
@@ -XXX,XX +XXX,XX @@ Currently B-L475E-IOT01A machine's only supports the following devices:
36
int is_linux = 0;
61
- STM32L4x5 EXTI (Extended interrupts and events controller)
37
@@ -XXX,XX +XXX,XX @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
62
- STM32L4x5 SYSCFG (System configuration controller)
38
int elf_machine;
63
- STM32L4x5 RCC (Reset and clock control)
39
hwaddr entry;
64
+- STM32L4x5 GPIOs (General-purpose I/Os)
40
static const ARMInsnFixup *primary_loader;
65
41
- AddressSpace *as = arm_boot_address_space(cpu, info);
66
Missing devices
42
-
67
"""""""""""""""
43
- /*
68
@@ -XXX,XX +XXX,XX @@ Missing devices
44
- * CPU objects (unlike devices) are not automatically reset on system
69
The B-L475E-IOT01A does *not* support the following devices:
45
- * reset, so we must always register a handler to do so. If we're
70
46
- * actually loading a kernel, the handler is also responsible for
71
- Serial ports (UART)
47
- * arranging that we start it correctly.
72
-- General-purpose I/Os (GPIO)
48
- */
73
- Analog to Digital Converter (ADC)
49
- for (cs = first_cpu; cs; cs = CPU_NEXT(cs)) {
74
- SPI controller
50
- qemu_register_reset(do_cpu_reset, ARM_CPU(cs));
75
- Timer controller (TIMER)
51
- }
76
diff --git a/include/hw/gpio/stm32l4x5_gpio.h b/include/hw/gpio/stm32l4x5_gpio.h
52
-
77
new file mode 100644
53
- /*
78
index XXXXXXX..XXXXXXX
54
- * The board code is not supposed to set secure_board_setup unless
79
--- /dev/null
55
- * running its code in secure mode is actually possible, and KVM
80
+++ b/include/hw/gpio/stm32l4x5_gpio.h
56
- * doesn't support secure.
81
@@ -XXX,XX +XXX,XX @@
57
- */
82
+/*
58
- assert(!(info->secure_board_setup && kvm_enabled()));
83
+ * STM32L4x5 GPIO (General Purpose Input/Ouput)
59
-
84
+ *
60
- info->dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb");
85
+ * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
61
- info->dtb_limit = 0;
86
+ * Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
62
-
87
+ *
63
- /* Load the kernel. */
88
+ * SPDX-License-Identifier: GPL-2.0-or-later
64
- if (!info->kernel_filename || info->firmware_loaded) {
89
+ *
65
-
90
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
66
- if (have_dtb(info)) {
91
+ * See the COPYING file in the top-level directory.
67
- /*
92
+ */
68
- * If we have a device tree blob, but no kernel to supply it to (or
93
+
69
- * the kernel is supposed to be loaded by the bootloader), copy the
94
+/*
70
- * DTB to the base of RAM for the bootloader to pick up.
95
+ * The reference used is the STMicroElectronics RM0351 Reference manual
71
- */
96
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
72
- info->dtb_start = info->loader_start;
97
+ * https://www.st.com/en/microcontrollers-microprocessors/stm32l4x5/documentation.html
73
- }
98
+ */
74
-
99
+
75
- if (info->kernel_filename) {
100
+#ifndef HW_STM32L4X5_GPIO_H
76
- FWCfgState *fw_cfg;
101
+#define HW_STM32L4X5_GPIO_H
77
- bool try_decompressing_kernel;
102
+
78
-
103
+#include "hw/sysbus.h"
79
- fw_cfg = fw_cfg_find();
104
+#include "qom/object.h"
80
- try_decompressing_kernel = arm_feature(&cpu->env,
105
+
81
- ARM_FEATURE_AARCH64);
106
+#define TYPE_STM32L4X5_GPIO "stm32l4x5-gpio"
82
-
107
+OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5GpioState, STM32L4X5_GPIO)
83
- /*
108
+
84
- * Expose the kernel, the command line, and the initrd in fw_cfg.
109
+#define GPIO_NUM_PINS 16
85
- * We don't process them here at all, it's all left to the
110
+
86
- * firmware.
111
+struct Stm32l4x5GpioState {
87
- */
112
+ SysBusDevice parent_obj;
88
- load_image_to_fw_cfg(fw_cfg,
113
+
89
- FW_CFG_KERNEL_SIZE, FW_CFG_KERNEL_DATA,
114
+ MemoryRegion mmio;
90
- info->kernel_filename,
115
+
91
- try_decompressing_kernel);
116
+ /* GPIO registers */
92
- load_image_to_fw_cfg(fw_cfg,
117
+ uint32_t moder;
93
- FW_CFG_INITRD_SIZE, FW_CFG_INITRD_DATA,
118
+ uint32_t otyper;
94
- info->initrd_filename, false);
119
+ uint32_t ospeedr;
95
-
120
+ uint32_t pupdr;
96
- if (info->kernel_cmdline) {
121
+ uint32_t idr;
97
- fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
122
+ uint32_t odr;
98
- strlen(info->kernel_cmdline) + 1);
123
+ uint32_t lckr;
99
- fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA,
124
+ uint32_t afrl;
100
- info->kernel_cmdline);
125
+ uint32_t afrh;
101
- }
126
+ uint32_t ascr;
102
- }
127
+
103
-
128
+ /* GPIO registers reset values */
104
- /*
129
+ uint32_t moder_reset;
105
- * We will start from address 0 (typically a boot ROM image) in the
130
+ uint32_t ospeedr_reset;
106
- * same way as hardware.
131
+ uint32_t pupdr_reset;
107
- */
108
- return;
109
- }
110
111
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
112
primary_loader = bootloader_aarch64;
113
@@ -XXX,XX +XXX,XX @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
114
for (cs = first_cpu; cs; cs = CPU_NEXT(cs)) {
115
ARM_CPU(cs)->env.boot_info = info;
116
}
117
+}
118
+
119
+void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
120
+{
121
+ CPUState *cs;
122
+ AddressSpace *as = arm_boot_address_space(cpu, info);
123
+
132
+
124
+ /*
133
+ /*
125
+ * CPU objects (unlike devices) are not automatically reset on system
134
+ * External driving of pins.
126
+ * reset, so we must always register a handler to do so. If we're
135
+ * The pins can be set externally through the device
127
+ * actually loading a kernel, the handler is also responsible for
136
+ * anonymous input GPIOs lines under certain conditions.
128
+ * arranging that we start it correctly.
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()`)
129
+ */
142
+ */
130
+ for (cs = first_cpu; cs; cs = CPU_NEXT(cs)) {
143
+ uint16_t disconnected_pins;
131
+ qemu_register_reset(do_cpu_reset, ARM_CPU(cs));
144
+ uint16_t pins_connected_high;
132
+ }
145
+
133
+
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;
134
+ /*
253
+ /*
135
+ * The board code is not supposed to set secure_board_setup unless
254
+ * The pin isn't set if line is configured in output mode
136
+ * running its code in secure mode is actually possible, and KVM
255
+ * except if level is 0 and the output is open-drain.
137
+ * doesn't support secure.
256
+ * This way there will be no short-circuit prone situations.
138
+ */
257
+ */
139
+ assert(!(info->secure_board_setup && kvm_enabled()));
258
+ if (is_output(s, line) && !(is_open_drain(s, line) && (level == 0))) {
140
+
259
+ qemu_log_mask(LOG_GUEST_ERROR, "Line %d can't be driven externally\n",
141
+ info->dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb");
260
+ line);
142
+ info->dtb_limit = 0;
261
+ return;
143
+
262
+ }
144
+ /* Load the kernel. */
263
+
145
+ if (!info->kernel_filename || info->firmware_loaded) {
264
+ s->disconnected_pins &= ~(1 << line);
146
+
265
+ if (level) {
147
+ if (have_dtb(info)) {
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
+ }
148
+ /*
303
+ /*
149
+ * If we have a device tree blob, but no kernel to supply it to (or
304
+ * The only case left is for open-drain ODR 1
150
+ * the kernel is supposed to be loaded by the bootloader), copy the
305
+ * with unactive pin without pull-up or pull-down :
151
+ * DTB to the base of RAM for the bootloader to pick up.
306
+ * the value is floating.
152
+ */
307
+ */
153
+ info->dtb_start = info->loader_start;
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
+ */
154
+ }
335
+ }
155
+
336
+ }
156
+ if (info->kernel_filename) {
337
+
157
+ FWCfgState *fw_cfg;
338
+ s->idr = (old_idr & ~new_idr_mask) | (new_idr & new_idr_mask);
158
+ bool try_decompressing_kernel;
339
+ trace_stm32l4x5_gpio_update_idr(s->name, old_idr, s->idr);
159
+
340
+
160
+ fw_cfg = fw_cfg_find();
341
+ for (int i = 0; i < GPIO_NUM_PINS; i++) {
161
+ try_decompressing_kernel = arm_feature(&cpu->env,
342
+ if (new_idr_mask & (1 << i)) {
162
+ ARM_FEATURE_AARCH64);
343
+ new_pin_state = (new_idr & (1 << i)) > 0;
163
+
344
+ old_pin_state = (old_idr & (1 << i)) > 0;
164
+ /*
345
+ if (new_pin_state > old_pin_state) {
165
+ * Expose the kernel, the command line, and the initrd in fw_cfg.
346
+ qemu_irq_raise(s->pin[i]);
166
+ * We don't process them here at all, it's all left to the
347
+ } else if (new_pin_state < old_pin_state) {
167
+ * firmware.
348
+ qemu_irq_lower(s->pin[i]);
168
+ */
169
+ load_image_to_fw_cfg(fw_cfg,
170
+ FW_CFG_KERNEL_SIZE, FW_CFG_KERNEL_DATA,
171
+ info->kernel_filename,
172
+ try_decompressing_kernel);
173
+ load_image_to_fw_cfg(fw_cfg,
174
+ FW_CFG_INITRD_SIZE, FW_CFG_INITRD_DATA,
175
+ info->initrd_filename, false);
176
+
177
+ if (info->kernel_cmdline) {
178
+ fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
179
+ strlen(info->kernel_cmdline) + 1);
180
+ fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA,
181
+ info->kernel_cmdline);
182
+ }
349
+ }
183
+ }
350
+ }
184
+
351
+ }
185
+ /*
352
+}
186
+ * We will start from address 0 (typically a boot ROM image) in the
353
+
187
+ * same way as hardware.
354
+/*
188
+ */
355
+ * Return mask of pins that are both configured in output
189
+ return;
356
+ * mode and externally driven (except pins in open-drain
190
+ } else {
357
+ * mode externally set to 0).
191
+ arm_setup_direct_kernel_boot(cpu, info);
358
+ */
192
+ }
359
+static uint32_t get_gpio_pinmask_to_disconnect(Stm32l4x5GpioState *s)
193
360
+{
194
if (!info->skip_dtb_autoload && have_dtb(info)) {
361
+ uint32_t pins_to_disconnect = 0;
195
if (arm_load_dtb(info->dtb_start, info, info->dtb_limit, as) < 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"
196
--
671
--
197
2.20.1
672
2.34.1
198
673
199
674
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Inès Varhol <ines.varhol@telecom-paris.fr>
2
2
3
The branch target exception for guarded pages has high priority,
3
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
4
and only 8 instructions are valid for that case. Perform this
4
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
5
check before doing any other decode.
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
6
Acked-by: Alistair Francis <alistair.francis@wdc.com>
7
Clear BTYPE after all insns that neither set BTYPE nor exit via
7
Message-id: 20240305210444.310665-3-ines.varhol@telecom-paris.fr
8
exception (DISAS_NORETURN).
9
10
Not yet handled are insns that exit via DISAS_NORETURN for some
11
other reason, like direct branches.
12
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20190128223118.5255-7-richard.henderson@linaro.org
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
9
---
18
target/arm/internals.h | 6 ++
10
include/hw/arm/stm32l4x5_soc.h | 2 +
19
target/arm/translate.h | 9 ++-
11
include/hw/gpio/stm32l4x5_gpio.h | 1 +
20
target/arm/translate-a64.c | 139 +++++++++++++++++++++++++++++++++++++
12
include/hw/misc/stm32l4x5_syscfg.h | 3 +-
21
3 files changed, 152 insertions(+), 2 deletions(-)
13
hw/arm/stm32l4x5_soc.c | 71 +++++++++++++++++++++++-------
22
14
hw/misc/stm32l4x5_syscfg.c | 1 +
23
diff --git a/target/arm/internals.h b/target/arm/internals.h
15
hw/arm/Kconfig | 3 +-
24
index XXXXXXX..XXXXXXX 100644
16
6 files changed, 63 insertions(+), 18 deletions(-)
25
--- a/target/arm/internals.h
17
26
+++ b/target/arm/internals.h
18
diff --git a/include/hw/arm/stm32l4x5_soc.h b/include/hw/arm/stm32l4x5_soc.h
27
@@ -XXX,XX +XXX,XX @@ enum arm_exception_class {
19
index XXXXXXX..XXXXXXX 100644
28
EC_FPIDTRAP = 0x08,
20
--- a/include/hw/arm/stm32l4x5_soc.h
29
EC_PACTRAP = 0x09,
21
+++ b/include/hw/arm/stm32l4x5_soc.h
30
EC_CP14RRTTRAP = 0x0c,
22
@@ -XXX,XX +XXX,XX @@
31
+ EC_BTITRAP = 0x0d,
23
#include "hw/misc/stm32l4x5_syscfg.h"
32
EC_ILLEGALSTATE = 0x0e,
24
#include "hw/misc/stm32l4x5_exti.h"
33
EC_AA32_SVC = 0x11,
25
#include "hw/misc/stm32l4x5_rcc.h"
34
EC_AA32_HVC = 0x12,
26
+#include "hw/gpio/stm32l4x5_gpio.h"
35
@@ -XXX,XX +XXX,XX @@ static inline uint32_t syn_pactrap(void)
27
#include "qom/object.h"
36
return EC_PACTRAP << ARM_EL_EC_SHIFT;
28
29
#define TYPE_STM32L4X5_SOC "stm32l4x5-soc"
30
@@ -XXX,XX +XXX,XX @@ struct Stm32l4x5SocState {
31
OrIRQState exti_or_gates[NUM_EXTI_OR_GATES];
32
Stm32l4x5SyscfgState syscfg;
33
Stm32l4x5RccState rcc;
34
+ Stm32l4x5GpioState gpio[NUM_GPIOS];
35
36
MemoryRegion sram1;
37
MemoryRegion sram2;
38
diff --git a/include/hw/gpio/stm32l4x5_gpio.h b/include/hw/gpio/stm32l4x5_gpio.h
39
index XXXXXXX..XXXXXXX 100644
40
--- a/include/hw/gpio/stm32l4x5_gpio.h
41
+++ b/include/hw/gpio/stm32l4x5_gpio.h
42
@@ -XXX,XX +XXX,XX @@
43
#define TYPE_STM32L4X5_GPIO "stm32l4x5-gpio"
44
OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5GpioState, STM32L4X5_GPIO)
45
46
+#define NUM_GPIOS 8
47
#define GPIO_NUM_PINS 16
48
49
struct Stm32l4x5GpioState {
50
diff --git a/include/hw/misc/stm32l4x5_syscfg.h b/include/hw/misc/stm32l4x5_syscfg.h
51
index XXXXXXX..XXXXXXX 100644
52
--- a/include/hw/misc/stm32l4x5_syscfg.h
53
+++ b/include/hw/misc/stm32l4x5_syscfg.h
54
@@ -XXX,XX +XXX,XX @@
55
56
#include "hw/sysbus.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 @@
73
#include "sysemu/sysemu.h"
74
#include "hw/or-irq.h"
75
#include "hw/arm/stm32l4x5_soc.h"
76
+#include "hw/gpio/stm32l4x5_gpio.h"
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
+ }
37
}
112
}
38
113
39
+static inline uint32_t syn_btitrap(int btype)
114
static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
40
+{
115
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
41
+ return (EC_BTITRAP << ARM_EL_EC_SHIFT) | btype;
116
Stm32l4x5SocState *s = STM32L4X5_SOC(dev_soc);
42
+}
117
const Stm32l4x5SocClass *sc = STM32L4X5_SOC_GET_CLASS(dev_soc);
43
+
118
MemoryRegion *system_memory = get_system_memory();
44
static inline uint32_t syn_insn_abort(int same_el, int ea, int s1ptw, int fsc)
119
- DeviceState *armv7m;
45
{
120
+ DeviceState *armv7m, *dev;
46
return (EC_INSNABORT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT)
121
SysBusDevice *busdev;
47
diff --git a/target/arm/translate.h b/target/arm/translate.h
122
+ uint32_t pin_index;
48
index XXXXXXX..XXXXXXX 100644
123
49
--- a/target/arm/translate.h
124
if (!memory_region_init_rom(&s->flash, OBJECT(dev_soc), "flash",
50
+++ b/target/arm/translate.h
125
sc->flash_size, errp)) {
51
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
126
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
52
bool pauth_active;
127
return;
53
/* True with v8.5-BTI and SCTLR_ELx.BT* set. */
128
}
54
bool bt;
129
55
- /* A copy of PSTATE.BTYPE, which will be 0 without v8.5-BTI. */
130
+ /* GPIOs */
56
- uint8_t btype;
131
+ for (unsigned i = 0; i < NUM_GPIOS; i++) {
57
+ /*
132
+ g_autofree char *name = g_strdup_printf("%c", 'A' + i);
58
+ * >= 0, a copy of PSTATE.BTYPE, which will be 0 without v8.5-BTI.
133
+ dev = DEVICE(&s->gpio[i]);
59
+ * < 0, set by the current instruction.
134
+ qdev_prop_set_string(dev, "name", name);
60
+ */
135
+ qdev_prop_set_uint32(dev, "mode-reset",
61
+ int8_t btype;
136
+ stm32l4x5_gpio_cfg[i].moder_reset);
62
+ /* True if this page is guarded. */
137
+ qdev_prop_set_uint32(dev, "ospeed-reset",
63
+ bool guarded_page;
138
+ stm32l4x5_gpio_cfg[i].ospeedr_reset);
64
/* Bottom two bits of XScale c15_cpar coprocessor access control reg */
139
+ qdev_prop_set_uint32(dev, "pupd-reset",
65
int c15_cpar;
140
+ stm32l4x5_gpio_cfg[i].pupdr_reset);
66
/* TCG op of the current insn_start. */
141
+ busdev = SYS_BUS_DEVICE(&s->gpio[i]);
67
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
142
+ g_free(name);
68
index XXXXXXX..XXXXXXX 100644
143
+ name = g_strdup_printf("gpio%c-out", 'a' + i);
69
--- a/target/arm/translate-a64.c
144
+ qdev_connect_clock_in(DEVICE(&s->gpio[i]), "clk",
70
+++ b/target/arm/translate-a64.c
145
+ qdev_get_clock_out(DEVICE(&(s->rcc)), name));
71
@@ -XXX,XX +XXX,XX @@ static inline int get_a64_user_mem_index(DisasContext *s)
146
+ if (!sysbus_realize(busdev, errp)) {
72
return arm_to_core_mmu_idx(useridx);
147
+ return;
73
}
148
+ }
74
149
+ sysbus_mmio_map(busdev, 0, stm32l4x5_gpio_cfg[i].addr);
75
+static void reset_btype(DisasContext *s)
76
+{
77
+ if (s->btype != 0) {
78
+ TCGv_i32 zero = tcg_const_i32(0);
79
+ tcg_gen_st_i32(zero, cpu_env, offsetof(CPUARMState, btype));
80
+ tcg_temp_free_i32(zero);
81
+ s->btype = 0;
82
+ }
150
+ }
83
+}
151
+
84
+
152
/* System configuration controller */
85
void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
153
busdev = SYS_BUS_DEVICE(&s->syscfg);
86
fprintf_function cpu_fprintf, int flags)
154
if (!sysbus_realize(busdev, errp)) {
87
{
155
return;
88
@@ -XXX,XX +XXX,XX @@ static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn)
156
}
89
}
157
sysbus_mmio_map(busdev, 0, SYSCFG_ADDR);
90
}
158
- /*
91
159
- * TODO: when the GPIO device is implemented, connect it
92
+/**
160
- * to SYCFG using `qdev_connect_gpio_out`, NUM_GPIOS and
93
+ * is_guarded_page:
161
- * GPIO_NUM_PINS.
94
+ * @env: The cpu environment
162
- */
95
+ * @s: The DisasContext
163
+
96
+ *
164
+ for (unsigned i = 0; i < NUM_GPIOS; i++) {
97
+ * Return true if the page is guarded.
165
+ for (unsigned j = 0; j < GPIO_NUM_PINS; j++) {
98
+ */
166
+ pin_index = GPIO_NUM_PINS * i + j;
99
+static bool is_guarded_page(CPUARMState *env, DisasContext *s)
167
+ qdev_connect_gpio_out(DEVICE(&s->gpio[i]), j,
100
+{
168
+ qdev_get_gpio_in(DEVICE(&s->syscfg),
101
+#ifdef CONFIG_USER_ONLY
169
+ pin_index));
102
+ return false; /* FIXME */
103
+#else
104
+ uint64_t addr = s->base.pc_first;
105
+ int mmu_idx = arm_to_core_mmu_idx(s->mmu_idx);
106
+ unsigned int index = tlb_index(env, mmu_idx, addr);
107
+ CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
108
+
109
+ /*
110
+ * We test this immediately after reading an insn, which means
111
+ * that any normal page must be in the TLB. The only exception
112
+ * would be for executing from flash or device memory, which
113
+ * does not retain the TLB entry.
114
+ *
115
+ * FIXME: Assume false for those, for now. We could use
116
+ * arm_cpu_get_phys_page_attrs_debug to re-read the page
117
+ * table entry even for that case.
118
+ */
119
+ return (tlb_hit(entry->addr_code, addr) &&
120
+ env->iotlb[mmu_idx][index].attrs.target_tlb_bit0);
121
+#endif
122
+}
123
+
124
+/**
125
+ * btype_destination_ok:
126
+ * @insn: The instruction at the branch destination
127
+ * @bt: SCTLR_ELx.BT
128
+ * @btype: PSTATE.BTYPE, and is non-zero
129
+ *
130
+ * On a guarded page, there are a limited number of insns
131
+ * that may be present at the branch target:
132
+ * - branch target identifiers,
133
+ * - paciasp, pacibsp,
134
+ * - BRK insn
135
+ * - HLT insn
136
+ * Anything else causes a Branch Target Exception.
137
+ *
138
+ * Return true if the branch is compatible, false to raise BTITRAP.
139
+ */
140
+static bool btype_destination_ok(uint32_t insn, bool bt, int btype)
141
+{
142
+ if ((insn & 0xfffff01fu) == 0xd503201fu) {
143
+ /* HINT space */
144
+ switch (extract32(insn, 5, 7)) {
145
+ case 0b011001: /* PACIASP */
146
+ case 0b011011: /* PACIBSP */
147
+ /*
148
+ * If SCTLR_ELx.BT, then PACI*SP are not compatible
149
+ * with btype == 3. Otherwise all btype are ok.
150
+ */
151
+ return !bt || btype != 3;
152
+ case 0b100000: /* BTI */
153
+ /* Not compatible with any btype. */
154
+ return false;
155
+ case 0b100010: /* BTI c */
156
+ /* Not compatible with btype == 3 */
157
+ return btype != 3;
158
+ case 0b100100: /* BTI j */
159
+ /* Not compatible with btype == 2 */
160
+ return btype != 2;
161
+ case 0b100110: /* BTI jc */
162
+ /* Compatible with any btype. */
163
+ return true;
164
+ }
165
+ } else {
166
+ switch (insn & 0xffe0001fu) {
167
+ case 0xd4200000u: /* BRK */
168
+ case 0xd4400000u: /* HLT */
169
+ /* Give priority to the breakpoint exception. */
170
+ return true;
171
+ }
170
+ }
172
+ }
171
+ }
173
+ return false;
172
174
+}
173
/* EXTI device */
175
+
174
busdev = SYS_BUS_DEVICE(&s->exti);
176
/* C3.1 A64 instruction index by encoding */
175
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
177
static void disas_a64_insn(CPUARMState *env, DisasContext *s)
176
}
178
{
177
}
179
@@ -XXX,XX +XXX,XX @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s)
178
180
179
- for (unsigned i = 0; i < 16; i++) {
181
s->fp_access_checked = false;
180
+ for (unsigned i = 0; i < GPIO_NUM_PINS; i++) {
182
181
qdev_connect_gpio_out(DEVICE(&s->syscfg), i,
183
+ if (dc_isar_feature(aa64_bti, s)) {
182
qdev_get_gpio_in(DEVICE(&s->exti), i));
184
+ if (s->base.num_insns == 1) {
183
}
185
+ /*
184
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
186
+ * At the first insn of the TB, compute s->guarded_page.
185
/* RESERVED: 0x40024400, 0x7FDBC00 */
187
+ * We delayed computing this until successfully reading
186
188
+ * the first insn of the TB, above. This (mostly) ensures
187
/* AHB2 BUS */
189
+ * that the softmmu tlb entry has been populated, and the
188
- create_unimplemented_device("GPIOA", 0x48000000, 0x400);
190
+ * page table GP bit is available.
189
- create_unimplemented_device("GPIOB", 0x48000400, 0x400);
191
+ *
190
- create_unimplemented_device("GPIOC", 0x48000800, 0x400);
192
+ * Note that we need to compute this even if btype == 0,
191
- create_unimplemented_device("GPIOD", 0x48000C00, 0x400);
193
+ * because this value is used for BR instructions later
192
- create_unimplemented_device("GPIOE", 0x48001000, 0x400);
194
+ * where ENV is not available.
193
- create_unimplemented_device("GPIOF", 0x48001400, 0x400);
195
+ */
194
- create_unimplemented_device("GPIOG", 0x48001800, 0x400);
196
+ s->guarded_page = is_guarded_page(env, s);
195
- create_unimplemented_device("GPIOH", 0x48001C00, 0x400);
197
+
196
/* RESERVED: 0x48002000, 0x7FDBC00 */
198
+ /* First insn can have btype set to non-zero. */
197
create_unimplemented_device("OTG_FS", 0x50000000, 0x40000);
199
+ tcg_debug_assert(s->btype >= 0);
198
create_unimplemented_device("ADC", 0x50040000, 0x400);
200
+
199
diff --git a/hw/misc/stm32l4x5_syscfg.c b/hw/misc/stm32l4x5_syscfg.c
201
+ /*
200
index XXXXXXX..XXXXXXX 100644
202
+ * Note that the Branch Target Exception has fairly high
201
--- a/hw/misc/stm32l4x5_syscfg.c
203
+ * priority -- below debugging exceptions but above most
202
+++ b/hw/misc/stm32l4x5_syscfg.c
204
+ * everything else. This allows us to handle this now
203
@@ -XXX,XX +XXX,XX @@
205
+ * instead of waiting until the insn is otherwise decoded.
204
#include "hw/irq.h"
206
+ */
205
#include "migration/vmstate.h"
207
+ if (s->btype != 0
206
#include "hw/misc/stm32l4x5_syscfg.h"
208
+ && s->guarded_page
207
+#include "hw/gpio/stm32l4x5_gpio.h"
209
+ && !btype_destination_ok(insn, s->bt, s->btype)) {
208
210
+ gen_exception_insn(s, 4, EXCP_UDEF, syn_btitrap(s->btype),
209
#define SYSCFG_MEMRMP 0x00
211
+ default_exception_el(s));
210
#define SYSCFG_CFGR1 0x04
212
+ return;
211
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
213
+ }
212
index XXXXXXX..XXXXXXX 100644
214
+ } else {
213
--- a/hw/arm/Kconfig
215
+ /* Not the first insn: btype must be 0. */
214
+++ b/hw/arm/Kconfig
216
+ tcg_debug_assert(s->btype == 0);
215
@@ -XXX,XX +XXX,XX @@ config STM32L4X5_SOC
217
+ }
216
bool
218
+ }
217
select ARM_V7M
219
+
218
select OR_IRQ
220
switch (extract32(insn, 25, 4)) {
219
- select STM32L4X5_SYSCFG
221
case 0x0: case 0x1: case 0x3: /* UNALLOCATED */
220
select STM32L4X5_EXTI
222
unallocated_encoding(s);
221
+ select STM32L4X5_SYSCFG
223
@@ -XXX,XX +XXX,XX @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s)
222
select STM32L4X5_RCC
224
223
+ select STM32L4X5_GPIO
225
/* if we allocated any temporaries, free them here */
224
226
free_tmp_a64(s);
225
config XLNX_ZYNQMP_ARM
227
+
226
bool
228
+ /*
229
+ * After execution of most insns, btype is reset to 0.
230
+ * Note that we set btype == -1 when the insn sets btype.
231
+ */
232
+ if (s->btype > 0 && s->base.is_jmp != DISAS_NORETURN) {
233
+ reset_btype(s);
234
+ }
235
}
236
237
static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
238
--
227
--
239
2.20.1
228
2.34.1
240
229
241
230
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Inès Varhol <ines.varhol@telecom-paris.fr>
2
2
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
3
The testcase contains :
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
- `test_idr_reset_value()` :
5
Message-id: 20190201195404.30486-3-richard.henderson@linaro.org
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.
24
25
Acked-by: Thomas Huth <thuth@redhat.com>
26
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
27
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
28
Message-id: 20240305210444.310665-4-ines.varhol@telecom-paris.fr
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
29
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
30
---
8
tests/tcg/aarch64/Makefile.target | 6 +++++-
31
tests/qtest/stm32l4x5_gpio-test.c | 551 ++++++++++++++++++++++++++++++
9
tests/tcg/aarch64/pauth-1.c | 23 +++++++++++++++++++++++
32
tests/qtest/meson.build | 3 +-
10
2 files changed, 28 insertions(+), 1 deletion(-)
33
2 files changed, 553 insertions(+), 1 deletion(-)
11
create mode 100644 tests/tcg/aarch64/pauth-1.c
34
create mode 100644 tests/qtest/stm32l4x5_gpio-test.c
12
35
13
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
36
diff --git a/tests/qtest/stm32l4x5_gpio-test.c b/tests/qtest/stm32l4x5_gpio-test.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/tests/tcg/aarch64/Makefile.target
16
+++ b/tests/tcg/aarch64/Makefile.target
17
@@ -XXX,XX +XXX,XX @@ VPATH         += $(AARCH64_SRC)
18
# we don't build any of the ARM tests
19
AARCH64_TESTS=$(filter-out $(ARM_TESTS), $(TESTS))
20
AARCH64_TESTS+=fcvt
21
-TESTS:=$(AARCH64_TESTS)
22
23
fcvt: LDFLAGS+=-lm
24
25
run-fcvt: fcvt
26
    $(call run-test,$<,$(QEMU) $<, "$< on $(TARGET_NAME)")
27
    $(call diff-out,$<,$(AARCH64_SRC)/fcvt.ref)
28
+
29
+AARCH64_TESTS += pauth-1
30
+run-pauth-%: QEMU += -cpu max
31
+
32
+TESTS:=$(AARCH64_TESTS)
33
diff --git a/tests/tcg/aarch64/pauth-1.c b/tests/tcg/aarch64/pauth-1.c
34
new file mode 100644
37
new file mode 100644
35
index XXXXXXX..XXXXXXX
38
index XXXXXXX..XXXXXXX
36
--- /dev/null
39
--- /dev/null
37
+++ b/tests/tcg/aarch64/pauth-1.c
40
+++ b/tests/qtest/stm32l4x5_gpio-test.c
38
@@ -XXX,XX +XXX,XX @@
41
@@ -XXX,XX +XXX,XX @@
39
+#include <assert.h>
42
+/*
40
+#include <sys/prctl.h>
43
+ * QTest testcase for STM32L4x5_GPIO
41
+
44
+ *
42
+asm(".arch armv8.4-a");
45
+ * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
43
+
46
+ * Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
44
+#ifndef PR_PAC_RESET_KEYS
47
+ *
45
+#define PR_PAC_RESET_KEYS 54
48
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
46
+#define PR_PAC_APDAKEY (1 << 2)
49
+ * See the COPYING file in the top-level directory.
47
+#endif
50
+ */
48
+
51
+
49
+int main()
52
+#include "qemu/osdep.h"
50
+{
53
+#include "libqtest-single.h"
51
+ int x;
54
+
52
+ void *p0 = &x, *p1, *p2;
55
+#define GPIO_BASE_ADDR 0x48000000
53
+
56
+#define GPIO_SIZE 0x400
54
+ asm volatile("pacdza %0" : "=r"(p1) : "0"(p0));
57
+#define NUM_GPIOS 8
55
+ prctl(PR_PAC_RESET_KEYS, PR_PAC_APDAKEY, 0, 0, 0);
58
+#define NUM_GPIO_PINS 16
56
+ asm volatile("pacdza %0" : "=r"(p2) : "0"(p0));
59
+
57
+
60
+#define GPIO_A 0x48000000
58
+ assert(p1 != p0);
61
+#define GPIO_B 0x48000400
59
+ assert(p1 != p2);
62
+#define GPIO_C 0x48000800
60
+ return 0;
63
+#define GPIO_D 0x48000C00
61
+}
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
594
index XXXXXXX..XXXXXXX 100644
595
--- a/tests/qtest/meson.build
596
+++ b/tests/qtest/meson.build
597
@@ -XXX,XX +XXX,XX @@ qtests_aspeed = \
598
qtests_stm32l4x5 = \
599
['stm32l4x5_exti-test',
600
'stm32l4x5_syscfg-test',
601
- 'stm32l4x5_rcc-test']
602
+ 'stm32l4x5_rcc-test',
603
+ 'stm32l4x5_gpio-test']
604
605
qtests_arm = \
606
(config_all_devices.has_key('CONFIG_MPS2') ? ['sse-timer-test'] : []) + \
62
--
607
--
63
2.20.1
608
2.34.1
64
609
65
610
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This will allow TBI to be used in user-only mode, as well as
3
While the 8-bit input elements are sequential in the input vector,
4
avoid ping-ponging the softmmu TLB when TBI is in use. It
4
the 32-bit output elements are not sequential in the output matrix.
5
will also enable other armv8 extensions.
5
Do not attempt to compute 2 32-bit outputs at the same time.
6
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Cc: qemu-stable@nongnu.org
8
Fixes: 23a5e3859f5 ("target/arm: Implement SME integer outer product")
9
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2083
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20190204132126.3255-3-richard.henderson@linaro.org
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
12
Message-id: 20240305163931.242795-1-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
14
---
12
target/arm/translate-a64.c | 217 ++++++++++++++++++++-----------------
15
target/arm/tcg/sme_helper.c | 77 ++++++++++++++++++-------------
13
1 file changed, 116 insertions(+), 101 deletions(-)
16
tests/tcg/aarch64/sme-smopa-1.c | 47 +++++++++++++++++++
14
17
tests/tcg/aarch64/sme-smopa-2.c | 54 ++++++++++++++++++++++
15
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
18
tests/tcg/aarch64/Makefile.target | 2 +-
19
4 files changed, 147 insertions(+), 33 deletions(-)
20
create mode 100644 tests/tcg/aarch64/sme-smopa-1.c
21
create mode 100644 tests/tcg/aarch64/sme-smopa-2.c
22
23
diff --git a/target/arm/tcg/sme_helper.c b/target/arm/tcg/sme_helper.c
16
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate-a64.c
25
--- a/target/arm/tcg/sme_helper.c
18
+++ b/target/arm/translate-a64.c
26
+++ b/target/arm/tcg/sme_helper.c
19
@@ -XXX,XX +XXX,XX @@ static void gen_a64_set_pc(DisasContext *s, TCGv_i64 src)
27
@@ -XXX,XX +XXX,XX @@ void HELPER(sme_bfmopa)(void *vza, void *vzn, void *vzm, void *vpn,
20
gen_top_byte_ignore(s, cpu_pc, src, s->tbii);
21
}
22
23
+/*
24
+ * Return a "clean" address for ADDR according to TBID.
25
+ * This is always a fresh temporary, as we need to be able to
26
+ * increment this independently of a dirty write-back address.
27
+ */
28
+static TCGv_i64 clean_data_tbi(DisasContext *s, TCGv_i64 addr)
29
+{
30
+ TCGv_i64 clean = new_tmp_a64(s);
31
+ gen_top_byte_ignore(s, clean, addr, s->tbid);
32
+ return clean;
33
+}
34
+
35
typedef struct DisasCompare64 {
36
TCGCond cond;
37
TCGv_i64 value;
38
@@ -XXX,XX +XXX,XX @@ static void gen_compare_and_swap(DisasContext *s, int rs, int rt,
39
TCGv_i64 tcg_rs = cpu_reg(s, rs);
40
TCGv_i64 tcg_rt = cpu_reg(s, rt);
41
int memidx = get_mem_index(s);
42
- TCGv_i64 addr = cpu_reg_sp(s, rn);
43
+ TCGv_i64 clean_addr;
44
45
if (rn == 31) {
46
gen_check_sp_alignment(s);
47
}
48
- tcg_gen_atomic_cmpxchg_i64(tcg_rs, addr, tcg_rs, tcg_rt, memidx,
49
+ clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
50
+ tcg_gen_atomic_cmpxchg_i64(tcg_rs, clean_addr, tcg_rs, tcg_rt, memidx,
51
size | MO_ALIGN | s->be_data);
52
}
53
54
@@ -XXX,XX +XXX,XX @@ static void gen_compare_and_swap_pair(DisasContext *s, int rs, int rt,
55
TCGv_i64 s2 = cpu_reg(s, rs + 1);
56
TCGv_i64 t1 = cpu_reg(s, rt);
57
TCGv_i64 t2 = cpu_reg(s, rt + 1);
58
- TCGv_i64 addr = cpu_reg_sp(s, rn);
59
+ TCGv_i64 clean_addr;
60
int memidx = get_mem_index(s);
61
62
if (rn == 31) {
63
gen_check_sp_alignment(s);
64
}
65
+ clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
66
67
if (size == 2) {
68
TCGv_i64 cmp = tcg_temp_new_i64();
69
@@ -XXX,XX +XXX,XX @@ static void gen_compare_and_swap_pair(DisasContext *s, int rs, int rt,
70
tcg_gen_concat32_i64(cmp, s2, s1);
71
}
72
73
- tcg_gen_atomic_cmpxchg_i64(cmp, addr, cmp, val, memidx,
74
+ tcg_gen_atomic_cmpxchg_i64(cmp, clean_addr, cmp, val, memidx,
75
MO_64 | MO_ALIGN | s->be_data);
76
tcg_temp_free_i64(val);
77
78
@@ -XXX,XX +XXX,XX @@ static void gen_compare_and_swap_pair(DisasContext *s, int rs, int rt,
79
if (HAVE_CMPXCHG128) {
80
TCGv_i32 tcg_rs = tcg_const_i32(rs);
81
if (s->be_data == MO_LE) {
82
- gen_helper_casp_le_parallel(cpu_env, tcg_rs, addr, t1, t2);
83
+ gen_helper_casp_le_parallel(cpu_env, tcg_rs,
84
+ clean_addr, t1, t2);
85
} else {
86
- gen_helper_casp_be_parallel(cpu_env, tcg_rs, addr, t1, t2);
87
+ gen_helper_casp_be_parallel(cpu_env, tcg_rs,
88
+ clean_addr, t1, t2);
89
}
90
tcg_temp_free_i32(tcg_rs);
91
} else {
92
@@ -XXX,XX +XXX,XX @@ static void gen_compare_and_swap_pair(DisasContext *s, int rs, int rt,
93
TCGv_i64 zero = tcg_const_i64(0);
94
95
/* Load the two words, in memory order. */
96
- tcg_gen_qemu_ld_i64(d1, addr, memidx,
97
+ tcg_gen_qemu_ld_i64(d1, clean_addr, memidx,
98
MO_64 | MO_ALIGN_16 | s->be_data);
99
- tcg_gen_addi_i64(a2, addr, 8);
100
- tcg_gen_qemu_ld_i64(d2, addr, memidx, MO_64 | s->be_data);
101
+ tcg_gen_addi_i64(a2, clean_addr, 8);
102
+ tcg_gen_qemu_ld_i64(d2, clean_addr, memidx, MO_64 | s->be_data);
103
104
/* Compare the two words, also in memory order. */
105
tcg_gen_setcond_i64(TCG_COND_EQ, c1, d1, s1);
106
@@ -XXX,XX +XXX,XX @@ static void gen_compare_and_swap_pair(DisasContext *s, int rs, int rt,
107
/* If compare equal, write back new data, else write back old data. */
108
tcg_gen_movcond_i64(TCG_COND_NE, c1, c2, zero, t1, d1);
109
tcg_gen_movcond_i64(TCG_COND_NE, c2, c2, zero, t2, d2);
110
- tcg_gen_qemu_st_i64(c1, addr, memidx, MO_64 | s->be_data);
111
+ tcg_gen_qemu_st_i64(c1, clean_addr, memidx, MO_64 | s->be_data);
112
tcg_gen_qemu_st_i64(c2, a2, memidx, MO_64 | s->be_data);
113
tcg_temp_free_i64(a2);
114
tcg_temp_free_i64(c1);
115
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn)
116
int is_lasr = extract32(insn, 15, 1);
117
int o2_L_o1_o0 = extract32(insn, 21, 3) * 2 | is_lasr;
118
int size = extract32(insn, 30, 2);
119
- TCGv_i64 tcg_addr;
120
+ TCGv_i64 clean_addr;
121
122
switch (o2_L_o1_o0) {
123
case 0x0: /* STXR */
124
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn)
125
if (is_lasr) {
126
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
127
}
128
- tcg_addr = read_cpu_reg_sp(s, rn, 1);
129
- gen_store_exclusive(s, rs, rt, rt2, tcg_addr, size, false);
130
+ clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
131
+ gen_store_exclusive(s, rs, rt, rt2, clean_addr, size, false);
132
return;
133
134
case 0x4: /* LDXR */
135
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn)
136
if (rn == 31) {
137
gen_check_sp_alignment(s);
138
}
139
- tcg_addr = read_cpu_reg_sp(s, rn, 1);
140
+ clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
141
s->is_ldex = true;
142
- gen_load_exclusive(s, rt, rt2, tcg_addr, size, false);
143
+ gen_load_exclusive(s, rt, rt2, clean_addr, size, false);
144
if (is_lasr) {
145
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
146
}
147
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn)
148
gen_check_sp_alignment(s);
149
}
150
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
151
- tcg_addr = read_cpu_reg_sp(s, rn, 1);
152
- do_gpr_st(s, cpu_reg(s, rt), tcg_addr, size, true, rt,
153
+ clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
154
+ do_gpr_st(s, cpu_reg(s, rt), clean_addr, size, true, rt,
155
disas_ldst_compute_iss_sf(size, false, 0), is_lasr);
156
return;
157
158
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn)
159
if (rn == 31) {
160
gen_check_sp_alignment(s);
161
}
162
- tcg_addr = read_cpu_reg_sp(s, rn, 1);
163
- do_gpr_ld(s, cpu_reg(s, rt), tcg_addr, size, false, false, true, rt,
164
+ clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
165
+ do_gpr_ld(s, cpu_reg(s, rt), clean_addr, size, false, false, true, rt,
166
disas_ldst_compute_iss_sf(size, false, 0), is_lasr);
167
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
168
return;
169
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn)
170
if (is_lasr) {
171
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
172
}
173
- tcg_addr = read_cpu_reg_sp(s, rn, 1);
174
- gen_store_exclusive(s, rs, rt, rt2, tcg_addr, size, true);
175
+ clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
176
+ gen_store_exclusive(s, rs, rt, rt2, clean_addr, size, true);
177
return;
178
}
179
if (rt2 == 31
180
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn)
181
if (rn == 31) {
182
gen_check_sp_alignment(s);
183
}
184
- tcg_addr = read_cpu_reg_sp(s, rn, 1);
185
+ clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
186
s->is_ldex = true;
187
- gen_load_exclusive(s, rt, rt2, tcg_addr, size, true);
188
+ gen_load_exclusive(s, rt, rt2, clean_addr, size, true);
189
if (is_lasr) {
190
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
191
}
192
@@ -XXX,XX +XXX,XX @@ static void disas_ld_lit(DisasContext *s, uint32_t insn)
193
int opc = extract32(insn, 30, 2);
194
bool is_signed = false;
195
int size = 2;
196
- TCGv_i64 tcg_rt, tcg_addr;
197
+ TCGv_i64 tcg_rt, clean_addr;
198
199
if (is_vector) {
200
if (opc == 3) {
201
@@ -XXX,XX +XXX,XX @@ static void disas_ld_lit(DisasContext *s, uint32_t insn)
202
203
tcg_rt = cpu_reg(s, rt);
204
205
- tcg_addr = tcg_const_i64((s->pc - 4) + imm);
206
+ clean_addr = tcg_const_i64((s->pc - 4) + imm);
207
if (is_vector) {
208
- do_fp_ld(s, rt, tcg_addr, size);
209
+ do_fp_ld(s, rt, clean_addr, size);
210
} else {
211
/* Only unsigned 32bit loads target 32bit registers. */
212
bool iss_sf = opc != 0;
213
214
- do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, false,
215
+ do_gpr_ld(s, tcg_rt, clean_addr, size, is_signed, false,
216
true, rt, iss_sf, false);
217
}
218
- tcg_temp_free_i64(tcg_addr);
219
+ tcg_temp_free_i64(clean_addr);
220
}
221
222
/*
223
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_pair(DisasContext *s, uint32_t insn)
224
bool postindex = false;
225
bool wback = false;
226
227
- TCGv_i64 tcg_addr; /* calculated address */
228
+ TCGv_i64 clean_addr, dirty_addr;
229
+
230
int size;
231
232
if (opc == 3) {
233
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_pair(DisasContext *s, uint32_t insn)
234
gen_check_sp_alignment(s);
235
}
236
237
- tcg_addr = read_cpu_reg_sp(s, rn, 1);
238
-
239
+ dirty_addr = read_cpu_reg_sp(s, rn, 1);
240
if (!postindex) {
241
- tcg_gen_addi_i64(tcg_addr, tcg_addr, offset);
242
+ tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
243
}
244
+ clean_addr = clean_data_tbi(s, dirty_addr);
245
246
if (is_vector) {
247
if (is_load) {
248
- do_fp_ld(s, rt, tcg_addr, size);
249
+ do_fp_ld(s, rt, clean_addr, size);
250
} else {
251
- do_fp_st(s, rt, tcg_addr, size);
252
+ do_fp_st(s, rt, clean_addr, size);
253
}
254
- tcg_gen_addi_i64(tcg_addr, tcg_addr, 1 << size);
255
+ tcg_gen_addi_i64(clean_addr, clean_addr, 1 << size);
256
if (is_load) {
257
- do_fp_ld(s, rt2, tcg_addr, size);
258
+ do_fp_ld(s, rt2, clean_addr, size);
259
} else {
260
- do_fp_st(s, rt2, tcg_addr, size);
261
+ do_fp_st(s, rt2, clean_addr, size);
262
}
263
} else {
264
TCGv_i64 tcg_rt = cpu_reg(s, rt);
265
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_pair(DisasContext *s, uint32_t insn)
266
/* Do not modify tcg_rt before recognizing any exception
267
* from the second load.
268
*/
269
- do_gpr_ld(s, tmp, tcg_addr, size, is_signed, false,
270
+ do_gpr_ld(s, tmp, clean_addr, size, is_signed, false,
271
false, 0, false, false);
272
- tcg_gen_addi_i64(tcg_addr, tcg_addr, 1 << size);
273
- do_gpr_ld(s, tcg_rt2, tcg_addr, size, is_signed, false,
274
+ tcg_gen_addi_i64(clean_addr, clean_addr, 1 << size);
275
+ do_gpr_ld(s, tcg_rt2, clean_addr, size, is_signed, false,
276
false, 0, false, false);
277
278
tcg_gen_mov_i64(tcg_rt, tmp);
279
tcg_temp_free_i64(tmp);
280
} else {
281
- do_gpr_st(s, tcg_rt, tcg_addr, size,
282
+ do_gpr_st(s, tcg_rt, clean_addr, size,
283
false, 0, false, false);
284
- tcg_gen_addi_i64(tcg_addr, tcg_addr, 1 << size);
285
- do_gpr_st(s, tcg_rt2, tcg_addr, size,
286
+ tcg_gen_addi_i64(clean_addr, clean_addr, 1 << size);
287
+ do_gpr_st(s, tcg_rt2, clean_addr, size,
288
false, 0, false, false);
289
}
290
}
291
292
if (wback) {
293
if (postindex) {
294
- tcg_gen_addi_i64(tcg_addr, tcg_addr, offset - (1 << size));
295
- } else {
296
- tcg_gen_subi_i64(tcg_addr, tcg_addr, 1 << size);
297
+ tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
298
}
299
- tcg_gen_mov_i64(cpu_reg_sp(s, rn), tcg_addr);
300
+ tcg_gen_mov_i64(cpu_reg_sp(s, rn), dirty_addr);
301
}
28
}
302
}
29
}
303
30
304
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn,
31
-typedef uint64_t IMOPFn(uint64_t, uint64_t, uint64_t, uint8_t, bool);
305
bool post_index;
32
+typedef uint32_t IMOPFn32(uint32_t, uint32_t, uint32_t, uint8_t, bool);
306
bool writeback;
33
+static inline void do_imopa_s(uint32_t *za, uint32_t *zn, uint32_t *zm,
307
34
+ uint8_t *pn, uint8_t *pm,
308
- TCGv_i64 tcg_addr;
35
+ uint32_t desc, IMOPFn32 *fn)
309
+ TCGv_i64 clean_addr, dirty_addr;
36
+{
310
37
+ intptr_t row, col, oprsz = simd_oprsz(desc) / 4;
311
if (is_vector) {
38
+ bool neg = simd_data(desc);
312
size |= (opc & 2) << 1;
39
313
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn,
40
-static inline void do_imopa(uint64_t *za, uint64_t *zn, uint64_t *zm,
314
if (rn == 31) {
41
- uint8_t *pn, uint8_t *pm,
315
gen_check_sp_alignment(s);
42
- uint32_t desc, IMOPFn *fn)
316
}
43
+ for (row = 0; row < oprsz; ++row) {
317
- tcg_addr = read_cpu_reg_sp(s, rn, 1);
44
+ uint8_t pa = (pn[H1(row >> 1)] >> ((row & 1) * 4)) & 0xf;
318
45
+ uint32_t *za_row = &za[tile_vslice_index(row)];
319
+ dirty_addr = read_cpu_reg_sp(s, rn, 1);
46
+ uint32_t n = zn[H4(row)];
320
if (!post_index) {
47
+
321
- tcg_gen_addi_i64(tcg_addr, tcg_addr, imm9);
48
+ for (col = 0; col < oprsz; ++col) {
322
+ tcg_gen_addi_i64(dirty_addr, dirty_addr, imm9);
49
+ uint8_t pb = pm[H1(col >> 1)] >> ((col & 1) * 4);
323
}
50
+ uint32_t *a = &za_row[H4(col)];
324
+ clean_addr = clean_data_tbi(s, dirty_addr);
51
+
325
52
+ *a = fn(n, zm[H4(col)], *a, pa & pb, neg);
326
if (is_vector) {
53
+ }
327
if (is_store) {
54
+ }
328
- do_fp_st(s, rt, tcg_addr, size);
55
+}
329
+ do_fp_st(s, rt, clean_addr, size);
56
+
330
} else {
57
+typedef uint64_t IMOPFn64(uint64_t, uint64_t, uint64_t, uint8_t, bool);
331
- do_fp_ld(s, rt, tcg_addr, size);
58
+static inline void do_imopa_d(uint64_t *za, uint64_t *zn, uint64_t *zm,
332
+ do_fp_ld(s, rt, clean_addr, size);
59
+ uint8_t *pn, uint8_t *pm,
333
}
60
+ uint32_t desc, IMOPFn64 *fn)
334
} else {
61
{
335
TCGv_i64 tcg_rt = cpu_reg(s, rt);
62
intptr_t row, col, oprsz = simd_oprsz(desc) / 8;
336
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn,
63
bool neg = simd_data(desc);
337
bool iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc);
64
@@ -XXX,XX +XXX,XX @@ static inline void do_imopa(uint64_t *za, uint64_t *zn, uint64_t *zm,
338
339
if (is_store) {
340
- do_gpr_st_memidx(s, tcg_rt, tcg_addr, size, memidx,
341
+ do_gpr_st_memidx(s, tcg_rt, clean_addr, size, memidx,
342
iss_valid, rt, iss_sf, false);
343
} else {
344
- do_gpr_ld_memidx(s, tcg_rt, tcg_addr, size,
345
+ do_gpr_ld_memidx(s, tcg_rt, clean_addr, size,
346
is_signed, is_extended, memidx,
347
iss_valid, rt, iss_sf, false);
348
}
349
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn,
350
if (writeback) {
351
TCGv_i64 tcg_rn = cpu_reg_sp(s, rn);
352
if (post_index) {
353
- tcg_gen_addi_i64(tcg_addr, tcg_addr, imm9);
354
+ tcg_gen_addi_i64(dirty_addr, dirty_addr, imm9);
355
}
356
- tcg_gen_mov_i64(tcg_rn, tcg_addr);
357
+ tcg_gen_mov_i64(tcg_rn, dirty_addr);
358
}
359
}
65
}
360
66
361
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn,
67
#define DEF_IMOP_32(NAME, NTYPE, MTYPE) \
362
bool is_store = false;
68
-static uint64_t NAME(uint64_t n, uint64_t m, uint64_t a, uint8_t p, bool neg) \
363
bool is_extended = false;
69
+static uint32_t NAME(uint32_t n, uint32_t m, uint32_t a, uint8_t p, bool neg) \
364
70
{ \
365
- TCGv_i64 tcg_rm;
71
- uint32_t sum0 = 0, sum1 = 0; \
366
- TCGv_i64 tcg_addr;
72
+ uint32_t sum = 0; \
367
+ TCGv_i64 tcg_rm, clean_addr, dirty_addr;
73
/* Apply P to N as a mask, making the inactive elements 0. */ \
368
74
n &= expand_pred_b(p); \
369
if (extract32(opt, 1, 1) == 0) {
75
- sum0 += (NTYPE)(n >> 0) * (MTYPE)(m >> 0); \
370
unallocated_encoding(s);
76
- sum0 += (NTYPE)(n >> 8) * (MTYPE)(m >> 8); \
371
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn,
77
- sum0 += (NTYPE)(n >> 16) * (MTYPE)(m >> 16); \
372
if (rn == 31) {
78
- sum0 += (NTYPE)(n >> 24) * (MTYPE)(m >> 24); \
373
gen_check_sp_alignment(s);
79
- sum1 += (NTYPE)(n >> 32) * (MTYPE)(m >> 32); \
374
}
80
- sum1 += (NTYPE)(n >> 40) * (MTYPE)(m >> 40); \
375
- tcg_addr = read_cpu_reg_sp(s, rn, 1);
81
- sum1 += (NTYPE)(n >> 48) * (MTYPE)(m >> 48); \
376
+ dirty_addr = read_cpu_reg_sp(s, rn, 1);
82
- sum1 += (NTYPE)(n >> 56) * (MTYPE)(m >> 56); \
377
83
- if (neg) { \
378
tcg_rm = read_cpu_reg(s, rm, 1);
84
- sum0 = (uint32_t)a - sum0, sum1 = (uint32_t)(a >> 32) - sum1; \
379
ext_and_shift_reg(tcg_rm, tcg_rm, opt, shift ? size : 0);
85
- } else { \
380
86
- sum0 = (uint32_t)a + sum0, sum1 = (uint32_t)(a >> 32) + sum1; \
381
- tcg_gen_add_i64(tcg_addr, tcg_addr, tcg_rm);
87
- } \
382
+ tcg_gen_add_i64(dirty_addr, dirty_addr, tcg_rm);
88
- return ((uint64_t)sum1 << 32) | sum0; \
383
+ clean_addr = clean_data_tbi(s, dirty_addr);
89
+ sum += (NTYPE)(n >> 0) * (MTYPE)(m >> 0); \
384
90
+ sum += (NTYPE)(n >> 8) * (MTYPE)(m >> 8); \
385
if (is_vector) {
91
+ sum += (NTYPE)(n >> 16) * (MTYPE)(m >> 16); \
386
if (is_store) {
92
+ sum += (NTYPE)(n >> 24) * (MTYPE)(m >> 24); \
387
- do_fp_st(s, rt, tcg_addr, size);
93
+ return neg ? a - sum : a + sum; \
388
+ do_fp_st(s, rt, clean_addr, size);
389
} else {
390
- do_fp_ld(s, rt, tcg_addr, size);
391
+ do_fp_ld(s, rt, clean_addr, size);
392
}
393
} else {
394
TCGv_i64 tcg_rt = cpu_reg(s, rt);
395
bool iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc);
396
if (is_store) {
397
- do_gpr_st(s, tcg_rt, tcg_addr, size,
398
+ do_gpr_st(s, tcg_rt, clean_addr, size,
399
true, rt, iss_sf, false);
400
} else {
401
- do_gpr_ld(s, tcg_rt, tcg_addr, size,
402
+ do_gpr_ld(s, tcg_rt, clean_addr, size,
403
is_signed, is_extended,
404
true, rt, iss_sf, false);
405
}
406
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn,
407
unsigned int imm12 = extract32(insn, 10, 12);
408
unsigned int offset;
409
410
- TCGv_i64 tcg_addr;
411
+ TCGv_i64 clean_addr, dirty_addr;
412
413
bool is_store;
414
bool is_signed = false;
415
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn,
416
if (rn == 31) {
417
gen_check_sp_alignment(s);
418
}
419
- tcg_addr = read_cpu_reg_sp(s, rn, 1);
420
+ dirty_addr = read_cpu_reg_sp(s, rn, 1);
421
offset = imm12 << size;
422
- tcg_gen_addi_i64(tcg_addr, tcg_addr, offset);
423
+ tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
424
+ clean_addr = clean_data_tbi(s, dirty_addr);
425
426
if (is_vector) {
427
if (is_store) {
428
- do_fp_st(s, rt, tcg_addr, size);
429
+ do_fp_st(s, rt, clean_addr, size);
430
} else {
431
- do_fp_ld(s, rt, tcg_addr, size);
432
+ do_fp_ld(s, rt, clean_addr, size);
433
}
434
} else {
435
TCGv_i64 tcg_rt = cpu_reg(s, rt);
436
bool iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc);
437
if (is_store) {
438
- do_gpr_st(s, tcg_rt, tcg_addr, size,
439
+ do_gpr_st(s, tcg_rt, clean_addr, size,
440
true, rt, iss_sf, false);
441
} else {
442
- do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, is_extended,
443
+ do_gpr_ld(s, tcg_rt, clean_addr, size, is_signed, is_extended,
444
true, rt, iss_sf, false);
445
}
446
}
447
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_atomic(DisasContext *s, uint32_t insn,
448
int rs = extract32(insn, 16, 5);
449
int rn = extract32(insn, 5, 5);
450
int o3_opc = extract32(insn, 12, 4);
451
- TCGv_i64 tcg_rn, tcg_rs;
452
+ TCGv_i64 tcg_rs, clean_addr;
453
AtomicThreeOpFn *fn;
454
455
if (is_vector || !dc_isar_feature(aa64_atomics, s)) {
456
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_atomic(DisasContext *s, uint32_t insn,
457
if (rn == 31) {
458
gen_check_sp_alignment(s);
459
}
460
- tcg_rn = cpu_reg_sp(s, rn);
461
+ clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
462
tcg_rs = read_cpu_reg(s, rs, true);
463
464
if (o3_opc == 1) { /* LDCLR */
465
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_atomic(DisasContext *s, uint32_t insn,
466
/* The tcg atomic primitives are all full barriers. Therefore we
467
* can ignore the Acquire and Release bits of this instruction.
468
*/
469
- fn(cpu_reg(s, rt), tcg_rn, tcg_rs, get_mem_index(s),
470
+ fn(cpu_reg(s, rt), clean_addr, tcg_rs, get_mem_index(s),
471
s->be_data | size | MO_ALIGN);
472
}
94
}
473
95
474
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_pac(DisasContext *s, uint32_t insn,
96
#define DEF_IMOP_64(NAME, NTYPE, MTYPE) \
475
bool is_wback = extract32(insn, 11, 1);
97
@@ -XXX,XX +XXX,XX @@ DEF_IMOP_64(umopa_d, uint16_t, uint16_t)
476
bool use_key_a = !extract32(insn, 23, 1);
98
DEF_IMOP_64(sumopa_d, int16_t, uint16_t)
477
int offset;
99
DEF_IMOP_64(usmopa_d, uint16_t, int16_t)
478
- TCGv_i64 tcg_addr, tcg_rt;
100
479
+ TCGv_i64 clean_addr, dirty_addr, tcg_rt;
101
-#define DEF_IMOPH(NAME) \
480
102
- void HELPER(sme_##NAME)(void *vza, void *vzn, void *vzm, void *vpn, \
481
if (size != 3 || is_vector || !dc_isar_feature(aa64_pauth, s)) {
103
- void *vpm, uint32_t desc) \
482
unallocated_encoding(s);
104
- { do_imopa(vza, vzn, vzm, vpn, vpm, desc, NAME); }
483
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_pac(DisasContext *s, uint32_t insn,
105
+#define DEF_IMOPH(NAME, S) \
484
if (rn == 31) {
106
+ void HELPER(sme_##NAME##_##S)(void *vza, void *vzn, void *vzm, \
485
gen_check_sp_alignment(s);
107
+ void *vpn, void *vpm, uint32_t desc) \
486
}
108
+ { do_imopa_##S(vza, vzn, vzm, vpn, vpm, desc, NAME##_##S); }
487
- tcg_addr = read_cpu_reg_sp(s, rn, 1);
109
488
+ dirty_addr = read_cpu_reg_sp(s, rn, 1);
110
-DEF_IMOPH(smopa_s)
489
111
-DEF_IMOPH(umopa_s)
490
if (s->pauth_active) {
112
-DEF_IMOPH(sumopa_s)
491
if (use_key_a) {
113
-DEF_IMOPH(usmopa_s)
492
- gen_helper_autda(tcg_addr, cpu_env, tcg_addr, cpu_X[31]);
114
-DEF_IMOPH(smopa_d)
493
+ gen_helper_autda(dirty_addr, cpu_env, dirty_addr, cpu_X[31]);
115
-DEF_IMOPH(umopa_d)
494
} else {
116
-DEF_IMOPH(sumopa_d)
495
- gen_helper_autdb(tcg_addr, cpu_env, tcg_addr, cpu_X[31]);
117
-DEF_IMOPH(usmopa_d)
496
+ gen_helper_autdb(dirty_addr, cpu_env, dirty_addr, cpu_X[31]);
118
+DEF_IMOPH(smopa, s)
497
}
119
+DEF_IMOPH(umopa, s)
498
}
120
+DEF_IMOPH(sumopa, s)
499
121
+DEF_IMOPH(usmopa, s)
500
/* Form the 10-bit signed, scaled offset. */
122
+
501
offset = (extract32(insn, 22, 1) << 9) | extract32(insn, 12, 9);
123
+DEF_IMOPH(smopa, d)
502
offset = sextract32(offset << size, 0, 10 + size);
124
+DEF_IMOPH(umopa, d)
503
- tcg_gen_addi_i64(tcg_addr, tcg_addr, offset);
125
+DEF_IMOPH(sumopa, d)
504
+ tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
126
+DEF_IMOPH(usmopa, d)
505
+
127
diff --git a/tests/tcg/aarch64/sme-smopa-1.c b/tests/tcg/aarch64/sme-smopa-1.c
506
+ /* Note that "clean" and "dirty" here refer to TBI not PAC. */
128
new file mode 100644
507
+ clean_addr = clean_data_tbi(s, dirty_addr);
129
index XXXXXXX..XXXXXXX
508
130
--- /dev/null
509
tcg_rt = cpu_reg(s, rt);
131
+++ b/tests/tcg/aarch64/sme-smopa-1.c
510
-
132
@@ -XXX,XX +XXX,XX @@
511
- do_gpr_ld(s, tcg_rt, tcg_addr, size, /* is_signed */ false,
133
+#include <stdio.h>
512
+ do_gpr_ld(s, tcg_rt, clean_addr, size, /* is_signed */ false,
134
+#include <string.h>
513
/* extend */ false, /* iss_valid */ !is_wback,
135
+
514
/* iss_srt */ rt, /* iss_sf */ true, /* iss_ar */ false);
136
+int main()
515
137
+{
516
if (is_wback) {
138
+ static const int cmp[4][4] = {
517
- tcg_gen_mov_i64(cpu_reg_sp(s, rn), tcg_addr);
139
+ { 110, 134, 158, 182 },
518
+ tcg_gen_mov_i64(cpu_reg_sp(s, rn), dirty_addr);
140
+ { 390, 478, 566, 654 },
519
}
141
+ { 670, 822, 974, 1126 },
520
}
142
+ { 950, 1166, 1382, 1598 }
521
143
+ };
522
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
144
+ int dst[4][4];
523
bool is_store = !extract32(insn, 22, 1);
145
+ int *tmp = &dst[0][0];
524
bool is_postidx = extract32(insn, 23, 1);
146
+
525
bool is_q = extract32(insn, 30, 1);
147
+ asm volatile(
526
- TCGv_i64 tcg_addr, tcg_rn, tcg_ebytes;
148
+ ".arch armv8-r+sme\n\t"
527
+ TCGv_i64 clean_addr, tcg_rn, tcg_ebytes;
149
+ "smstart\n\t"
528
TCGMemOp endian = s->be_data;
150
+ "index z0.b, #0, #1\n\t"
529
151
+ "movprfx z1, z0\n\t"
530
int ebytes; /* bytes per element */
152
+ "add z1.b, z1.b, #16\n\t"
531
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
153
+ "ptrue p0.b\n\t"
532
elements = (is_q ? 16 : 8) / ebytes;
154
+ "smopa za0.s, p0/m, p0/m, z0.b, z1.b\n\t"
533
155
+ "ptrue p0.s, vl4\n\t"
534
tcg_rn = cpu_reg_sp(s, rn);
156
+ "mov w12, #0\n\t"
535
- tcg_addr = tcg_temp_new_i64();
157
+ "st1w { za0h.s[w12, #0] }, p0, [%0]\n\t"
536
- tcg_gen_mov_i64(tcg_addr, tcg_rn);
158
+ "add %0, %0, #16\n\t"
537
+ clean_addr = clean_data_tbi(s, tcg_rn);
159
+ "st1w { za0h.s[w12, #1] }, p0, [%0]\n\t"
538
tcg_ebytes = tcg_const_i64(ebytes);
160
+ "add %0, %0, #16\n\t"
539
161
+ "st1w { za0h.s[w12, #2] }, p0, [%0]\n\t"
540
for (r = 0; r < rpt; r++) {
162
+ "add %0, %0, #16\n\t"
541
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
163
+ "st1w { za0h.s[w12, #3] }, p0, [%0]\n\t"
542
for (xs = 0; xs < selem; xs++) {
164
+ "smstop"
543
int tt = (rt + r + xs) % 32;
165
+ : "+r"(tmp) : : "memory");
544
if (is_store) {
166
+
545
- do_vec_st(s, tt, e, tcg_addr, size, endian);
167
+ if (memcmp(cmp, dst, sizeof(dst)) == 0) {
546
+ do_vec_st(s, tt, e, clean_addr, size, endian);
168
+ return 0;
547
} else {
169
+ }
548
- do_vec_ld(s, tt, e, tcg_addr, size, endian);
170
+
549
+ do_vec_ld(s, tt, e, clean_addr, size, endian);
171
+ /* See above for correct results. */
550
}
172
+ for (int i = 0; i < 4; ++i) {
551
- tcg_gen_add_i64(tcg_addr, tcg_addr, tcg_ebytes);
173
+ for (int j = 0; j < 4; ++j) {
552
+ tcg_gen_add_i64(clean_addr, clean_addr, tcg_ebytes);
174
+ printf("%6d", dst[i][j]);
553
}
175
+ }
554
}
176
+ printf("\n");
555
}
177
+ }
556
+ tcg_temp_free_i64(tcg_ebytes);
178
+ return 1;
557
179
+}
558
if (!is_store) {
180
diff --git a/tests/tcg/aarch64/sme-smopa-2.c b/tests/tcg/aarch64/sme-smopa-2.c
559
/* For non-quad operations, setting a slice of the low
181
new file mode 100644
560
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
182
index XXXXXXX..XXXXXXX
561
183
--- /dev/null
562
if (is_postidx) {
184
+++ b/tests/tcg/aarch64/sme-smopa-2.c
563
if (rm == 31) {
185
@@ -XXX,XX +XXX,XX @@
564
- tcg_gen_mov_i64(tcg_rn, tcg_addr);
186
+#include <stdio.h>
565
+ tcg_gen_addi_i64(tcg_rn, tcg_rn, rpt * elements * selem * ebytes);
187
+#include <string.h>
566
} else {
188
+
567
tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, rm));
189
+int main()
568
}
190
+{
569
}
191
+ static const long cmp[4][4] = {
570
- tcg_temp_free_i64(tcg_ebytes);
192
+ { 110, 134, 158, 182 },
571
- tcg_temp_free_i64(tcg_addr);
193
+ { 390, 478, 566, 654 },
572
}
194
+ { 670, 822, 974, 1126 },
573
195
+ { 950, 1166, 1382, 1598 }
574
/* AdvSIMD load/store single structure
196
+ };
575
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
197
+ long dst[4][4];
576
bool replicate = false;
198
+ long *tmp = &dst[0][0];
577
int index = is_q << 3 | S << 2 | size;
199
+ long svl;
578
int ebytes, xs;
200
+
579
- TCGv_i64 tcg_addr, tcg_rn, tcg_ebytes;
201
+ /* Validate that we have a wide enough vector for 4 elements. */
580
+ TCGv_i64 clean_addr, tcg_rn, tcg_ebytes;
202
+ asm(".arch armv8-r+sme-i64\n\trdsvl %0, #1" : "=r"(svl));
581
203
+ if (svl < 32) {
582
if (extract32(insn, 31, 1)) {
204
+ return 0;
583
unallocated_encoding(s);
205
+ }
584
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
206
+
585
}
207
+ asm volatile(
586
208
+ "smstart\n\t"
587
tcg_rn = cpu_reg_sp(s, rn);
209
+ "index z0.h, #0, #1\n\t"
588
- tcg_addr = tcg_temp_new_i64();
210
+ "movprfx z1, z0\n\t"
589
- tcg_gen_mov_i64(tcg_addr, tcg_rn);
211
+ "add z1.h, z1.h, #16\n\t"
590
+ clean_addr = clean_data_tbi(s, tcg_rn);
212
+ "ptrue p0.b\n\t"
591
tcg_ebytes = tcg_const_i64(ebytes);
213
+ "smopa za0.d, p0/m, p0/m, z0.h, z1.h\n\t"
592
214
+ "ptrue p0.d, vl4\n\t"
593
for (xs = 0; xs < selem; xs++) {
215
+ "mov w12, #0\n\t"
594
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
216
+ "st1d { za0h.d[w12, #0] }, p0, [%0]\n\t"
595
/* Load and replicate to all elements */
217
+ "add %0, %0, #32\n\t"
596
TCGv_i64 tcg_tmp = tcg_temp_new_i64();
218
+ "st1d { za0h.d[w12, #1] }, p0, [%0]\n\t"
597
219
+ "mov w12, #2\n\t"
598
- tcg_gen_qemu_ld_i64(tcg_tmp, tcg_addr,
220
+ "add %0, %0, #32\n\t"
599
+ tcg_gen_qemu_ld_i64(tcg_tmp, clean_addr,
221
+ "st1d { za0h.d[w12, #0] }, p0, [%0]\n\t"
600
get_mem_index(s), s->be_data + scale);
222
+ "add %0, %0, #32\n\t"
601
tcg_gen_gvec_dup_i64(scale, vec_full_reg_offset(s, rt),
223
+ "st1d { za0h.d[w12, #1] }, p0, [%0]\n\t"
602
(is_q + 1) * 8, vec_full_reg_size(s),
224
+ "smstop"
603
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
225
+ : "+r"(tmp) : : "memory");
604
} else {
226
+
605
/* Load/store one element per register */
227
+ if (memcmp(cmp, dst, sizeof(dst)) == 0) {
606
if (is_load) {
228
+ return 0;
607
- do_vec_ld(s, rt, index, tcg_addr, scale, s->be_data);
229
+ }
608
+ do_vec_ld(s, rt, index, clean_addr, scale, s->be_data);
230
+
609
} else {
231
+ /* See above for correct results. */
610
- do_vec_st(s, rt, index, tcg_addr, scale, s->be_data);
232
+ for (int i = 0; i < 4; ++i) {
611
+ do_vec_st(s, rt, index, clean_addr, scale, s->be_data);
233
+ for (int j = 0; j < 4; ++j) {
612
}
234
+ printf("%6ld", dst[i][j]);
613
}
235
+ }
614
- tcg_gen_add_i64(tcg_addr, tcg_addr, tcg_ebytes);
236
+ printf("\n");
615
+ tcg_gen_add_i64(clean_addr, clean_addr, tcg_ebytes);
237
+ }
616
rt = (rt + 1) % 32;
238
+ return 1;
617
}
239
+}
618
+ tcg_temp_free_i64(tcg_ebytes);
240
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
619
241
index XXXXXXX..XXXXXXX 100644
620
if (is_postidx) {
242
--- a/tests/tcg/aarch64/Makefile.target
621
if (rm == 31) {
243
+++ b/tests/tcg/aarch64/Makefile.target
622
- tcg_gen_mov_i64(tcg_rn, tcg_addr);
244
@@ -XXX,XX +XXX,XX @@ endif
623
+ tcg_gen_addi_i64(tcg_rn, tcg_rn, selem * ebytes);
245
624
} else {
246
# SME Tests
625
tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, rm));
247
ifneq ($(CROSS_AS_HAS_ARMV9_SME),)
626
}
248
-AARCH64_TESTS += sme-outprod1
627
}
249
+AARCH64_TESTS += sme-outprod1 sme-smopa-1 sme-smopa-2
628
- tcg_temp_free_i64(tcg_ebytes);
250
endif
629
- tcg_temp_free_i64(tcg_addr);
251
630
}
252
# System Registers Tests
631
632
/* Loads and stores */
633
--
253
--
634
2.20.1
254
2.34.1
635
255
636
256
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
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
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Relicense the code in the .c and the .h file to GPL-v2-or-later,
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
to make it compatible with the rest of QEMU.
5
Message-id: 20190128223118.5255-9-richard.henderson@linaro.org
7
8
Cc: qemu-stable@nongnu.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Paolo Bonzini (for Red Hat) <pbonzini@redhat.com>
11
Signed-off-by: Artyom Tarasenko <atar4qemu@gmail.com>
12
Signed-off-by: Markus Armbruster <armbru@redhat.com>
13
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
14
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
15
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
16
Acked-by: Alex Bennée <alex.bennee@linaro.org>
17
Message-id: 20240223161300.938542-1-peter.maydell@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
19
---
8
target/arm/translate-a64.c | 37 ++++++++++++++++++++++++++++++++++++-
20
include/hw/rtc/sun4v-rtc.h | 2 +-
9
1 file changed, 36 insertions(+), 1 deletion(-)
21
hw/rtc/sun4v-rtc.c | 2 +-
22
2 files changed, 2 insertions(+), 2 deletions(-)
10
23
11
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
24
diff --git a/include/hw/rtc/sun4v-rtc.h b/include/hw/rtc/sun4v-rtc.h
12
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate-a64.c
26
--- a/include/hw/rtc/sun4v-rtc.h
14
+++ b/target/arm/translate-a64.c
27
+++ b/include/hw/rtc/sun4v-rtc.h
15
@@ -XXX,XX +XXX,XX @@ static void reset_btype(DisasContext *s)
28
@@ -XXX,XX +XXX,XX @@
16
}
29
*
17
}
30
* Copyright (c) 2016 Artyom Tarasenko
18
31
*
19
+static void set_btype(DisasContext *s, int val)
32
- * This code is licensed under the GNU GPL v3 or (at your option) any later
20
+{
33
+ * This code is licensed under the GNU GPL v2 or (at your option) any later
21
+ TCGv_i32 tcg_val;
34
* version.
22
+
35
*/
23
+ /* BTYPE is a 2-bit field, and 0 should be done with reset_btype. */
36
24
+ tcg_debug_assert(val >= 1 && val <= 3);
37
diff --git a/hw/rtc/sun4v-rtc.c b/hw/rtc/sun4v-rtc.c
25
+
38
index XXXXXXX..XXXXXXX 100644
26
+ tcg_val = tcg_const_i32(val);
39
--- a/hw/rtc/sun4v-rtc.c
27
+ tcg_gen_st_i32(tcg_val, cpu_env, offsetof(CPUARMState, btype));
40
+++ b/hw/rtc/sun4v-rtc.c
28
+ tcg_temp_free_i32(tcg_val);
41
@@ -XXX,XX +XXX,XX @@
29
+ s->btype = -1;
42
*
30
+}
43
* Copyright (c) 2016 Artyom Tarasenko
31
+
44
*
32
void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
45
- * This code is licensed under the GNU GPL v3 or (at your option) any later
33
fprintf_function cpu_fprintf, int flags)
46
+ * This code is licensed under the GNU GPL v2 or (at your option) any later
34
{
47
* version.
35
@@ -XXX,XX +XXX,XX @@ static void disas_exc(DisasContext *s, uint32_t insn)
48
*/
36
static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
37
{
38
unsigned int opc, op2, op3, rn, op4;
39
+ unsigned btype_mod = 2; /* 0: BR, 1: BLR, 2: other */
40
TCGv_i64 dst;
41
TCGv_i64 modifier;
42
43
@@ -XXX,XX +XXX,XX @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
44
case 0: /* BR */
45
case 1: /* BLR */
46
case 2: /* RET */
47
+ btype_mod = opc;
48
switch (op3) {
49
case 0:
50
/* BR, BLR, RET */
51
@@ -XXX,XX +XXX,XX @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
52
default:
53
goto do_unallocated;
54
}
55
-
56
gen_a64_set_pc(s, dst);
57
/* BLR also needs to load return address */
58
if (opc == 1) {
59
@@ -XXX,XX +XXX,XX @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
60
if ((op3 & ~1) != 2) {
61
goto do_unallocated;
62
}
63
+ btype_mod = opc & 1;
64
if (s->pauth_active) {
65
dst = new_tmp_a64(s);
66
modifier = cpu_reg_sp(s, op4);
67
@@ -XXX,XX +XXX,XX @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
68
return;
69
}
70
71
+ switch (btype_mod) {
72
+ case 0: /* BR */
73
+ if (dc_isar_feature(aa64_bti, s)) {
74
+ /* BR to {x16,x17} or !guard -> 1, else 3. */
75
+ set_btype(s, rn == 16 || rn == 17 || !s->guarded_page ? 1 : 3);
76
+ }
77
+ break;
78
+
79
+ case 1: /* BLR */
80
+ if (dc_isar_feature(aa64_bti, s)) {
81
+ /* BLR sets BTYPE to 2, regardless of source guarded page. */
82
+ set_btype(s, 2);
83
+ }
84
+ break;
85
+
86
+ default: /* RET or none of the above. */
87
+ /* BTYPE will be set to 0 by normal end-of-insn processing. */
88
+ break;
89
+ }
90
+
91
s->base.is_jmp = DISAS_JUMP;
92
}
93
49
94
--
50
--
95
2.20.1
51
2.34.1
96
52
97
53
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
Place this in its own field within ENV, as that will
3
Move the code to a separate file so that we do not have to compile
4
make it easier to reset from within TCG generated code.
4
it anymore if CONFIG_ARM_V7M is not set.
5
5
6
With the change to pstate_read/write, exception entry
6
Signed-off-by: Thomas Huth <thuth@redhat.com>
7
and return are automatically handled.
7
Message-id: 20240308141051.536599-2-thuth@redhat.com
8
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20190128223118.5255-3-richard.henderson@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
10
---
14
target/arm/cpu.h | 8 ++++++--
11
target/arm/tcg/cpu-v7m.c | 290 +++++++++++++++++++++++++++++++++++++
15
target/arm/translate-a64.c | 3 +++
12
target/arm/tcg/cpu32.c | 261 ---------------------------------
16
2 files changed, 9 insertions(+), 2 deletions(-)
13
target/arm/meson.build | 3 +
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
17
17
18
diff --git a/target/arm/cpu.h b/target/arm/cpu.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
19
index XXXXXXX..XXXXXXX 100644
315
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/cpu.h
316
--- a/target/arm/tcg/cpu32.c
21
+++ b/target/arm/cpu.h
317
+++ b/target/arm/tcg/cpu32.c
22
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
318
@@ -XXX,XX +XXX,XX @@
23
* semantics as for AArch32, as described in the comments on each field)
319
#include "hw/boards.h"
24
* nRW (also known as M[4]) is kept, inverted, in env->aarch64
320
#endif
25
* DAIF (exception masks) are kept in env->daif
321
#include "cpregs.h"
26
+ * BTYPE is kept in env->btype
322
-#if !defined(CONFIG_USER_ONLY) && defined(CONFIG_TCG)
27
* all other bits are stored in their correct places in env->pstate
323
-#include "hw/intc/armv7m_nvic.h"
28
*/
324
-#endif
29
uint32_t pstate;
325
30
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
326
31
uint32_t GE; /* cpsr[19:16] */
327
/* Share AArch32 -cpu max features with AArch64. */
32
uint32_t thumb; /* cpsr[5]. 0 = arm mode, 1 = thumb mode. */
328
@@ -XXX,XX +XXX,XX @@ void aa32_max_features(ARMCPU *cpu)
33
uint32_t condexec_bits; /* IT bits. cpsr[15:10,26:25]. */
329
/* CPU models. These are not needed for the AArch64 linux-user build. */
34
+ uint32_t btype; /* BTI branch type. spsr[11:10]. */
330
#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
35
uint64_t daif; /* exception masks, in the bits they are in PSTATE */
331
36
332
-#if !defined(CONFIG_USER_ONLY)
37
uint64_t elr_el[4]; /* AArch64 exception link regs */
333
-static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
38
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
334
-{
39
#define PSTATE_I (1U << 7)
335
- CPUClass *cc = CPU_GET_CLASS(cs);
40
#define PSTATE_A (1U << 8)
336
- ARMCPU *cpu = ARM_CPU(cs);
41
#define PSTATE_D (1U << 9)
337
- CPUARMState *env = &cpu->env;
42
+#define PSTATE_BTYPE (3U << 10)
338
- bool ret = false;
43
#define PSTATE_IL (1U << 20)
339
-
44
#define PSTATE_SS (1U << 21)
340
- /*
45
#define PSTATE_V (1U << 28)
341
- * ARMv7-M interrupt masking works differently than -A or -R.
46
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
342
- * There is no FIQ/IRQ distinction. Instead of I and F bits
47
#define PSTATE_N (1U << 31)
343
- * masking FIQ and IRQ interrupts, an exception is taken only
48
#define PSTATE_NZCV (PSTATE_N | PSTATE_Z | PSTATE_C | PSTATE_V)
344
- * if it is higher priority than the current execution priority
49
#define PSTATE_DAIF (PSTATE_D | PSTATE_A | PSTATE_I | PSTATE_F)
345
- * (which depends on state like BASEPRI, FAULTMASK and the
50
-#define CACHED_PSTATE_BITS (PSTATE_NZCV | PSTATE_DAIF)
346
- * currently active exception).
51
+#define CACHED_PSTATE_BITS (PSTATE_NZCV | PSTATE_DAIF | PSTATE_BTYPE)
347
- */
52
/* Mode values for AArch64 */
348
- if (interrupt_request & CPU_INTERRUPT_HARD
53
#define PSTATE_MODE_EL3h 13
349
- && (armv7m_nvic_can_take_pending_exception(env->nvic))) {
54
#define PSTATE_MODE_EL3t 12
350
- cs->exception_index = EXCP_IRQ;
55
@@ -XXX,XX +XXX,XX @@ static inline uint32_t pstate_read(CPUARMState *env)
351
- cc->tcg_ops->do_interrupt(cs);
56
ZF = (env->ZF == 0);
352
- ret = true;
57
return (env->NF & 0x80000000) | (ZF << 30)
353
- }
58
| (env->CF << 29) | ((env->VF & 0x80000000) >> 3)
354
- return ret;
59
- | env->pstate | env->daif;
355
-}
60
+ | env->pstate | env->daif | (env->btype << 10);
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);
61
}
363
}
62
364
63
static inline void pstate_write(CPUARMState *env, uint32_t val)
365
-static void cortex_m0_initfn(Object *obj)
64
@@ -XXX,XX +XXX,XX @@ static inline void pstate_write(CPUARMState *env, uint32_t val)
366
-{
65
env->CF = (val >> 29) & 1;
367
- ARMCPU *cpu = ARM_CPU(obj);
66
env->VF = (val << 3) & 0x80000000;
368
- set_feature(&cpu->env, ARM_FEATURE_V6);
67
env->daif = val & PSTATE_DAIF;
369
- set_feature(&cpu->env, ARM_FEATURE_M);
68
+ env->btype = (val >> 10) & 3;
370
-
69
env->pstate = val & ~CACHED_PSTATE_BITS;
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;
70
}
559
}
71
560
72
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
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
73
index XXXXXXX..XXXXXXX 100644
615
index XXXXXXX..XXXXXXX 100644
74
--- a/target/arm/translate-a64.c
616
--- a/target/arm/meson.build
75
+++ b/target/arm/translate-a64.c
617
+++ b/target/arm/meson.build
76
@@ -XXX,XX +XXX,XX @@ void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
618
@@ -XXX,XX +XXX,XX @@ arm_system_ss.add(files(
77
el,
619
'ptw.c',
78
psr & PSTATE_SP ? 'h' : 't');
620
))
79
621
80
+ if (cpu_isar_feature(aa64_bti, cpu)) {
622
+arm_user_ss = ss.source_set()
81
+ cpu_fprintf(f, " BTYPE=%d", (psr & PSTATE_BTYPE) >> 10);
623
+
82
+ }
624
subdir('hvf')
83
if (!(flags & CPU_DUMP_FPU)) {
625
84
cpu_fprintf(f, "\n");
626
if 'CONFIG_TCG' in config_all_accel
85
return;
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
633
index XXXXXXX..XXXXXXX 100644
634
--- a/target/arm/tcg/meson.build
635
+++ b/target/arm/tcg/meson.build
636
@@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
637
arm_system_ss.add(files(
638
'psci.c',
639
))
640
+
641
+arm_system_ss.add(when: 'CONFIG_ARM_V7M', if_true: files('cpu-v7m.c'))
642
+arm_user_ss.add(when: 'TARGET_AARCH64', if_false: files('cpu-v7m.c'))
86
--
643
--
87
2.20.1
644
2.34.1
88
89
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
These bits can be used to cache target-specific data in cputlb
4
read from the page tables.
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20190128223118.5255-5-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
include/exec/memattrs.h | 10 ++++++++++
12
1 file changed, 10 insertions(+)
13
14
diff --git a/include/exec/memattrs.h b/include/exec/memattrs.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/exec/memattrs.h
17
+++ b/include/exec/memattrs.h
18
@@ -XXX,XX +XXX,XX @@ typedef struct MemTxAttrs {
19
unsigned int user:1;
20
/* Requester ID (for MSI for example) */
21
unsigned int requester_id:16;
22
+ /*
23
+ * The following are target-specific page-table bits. These are not
24
+ * related to actual memory transactions at all. However, this structure
25
+ * is part of the tlb_fill interface, cached in the cputlb structure,
26
+ * and has unused bits. These fields will be read by target-specific
27
+ * helpers using env->iotlb[mmu_idx][tlb_index()].attrs.target_tlb_bitN.
28
+ */
29
+ unsigned int target_tlb_bit0 : 1;
30
+ unsigned int target_tlb_bit1 : 1;
31
+ unsigned int target_tlb_bit2 : 1;
32
} MemTxAttrs;
33
34
/* Bus masters which don't specify any attributes will get this,
35
--
36
2.20.1
37
38
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
This is all of the non-exception cases of DISAS_NORETURN.
4
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20190128223118.5255-8-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
target/arm/translate-a64.c | 6 ++++++
11
1 file changed, 6 insertions(+)
12
13
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-a64.c
16
+++ b/target/arm/translate-a64.c
17
@@ -XXX,XX +XXX,XX @@ static void disas_uncond_b_imm(DisasContext *s, uint32_t insn)
18
}
19
20
/* B Branch / BL Branch with link */
21
+ reset_btype(s);
22
gen_goto_tb(s, 0, addr);
23
}
24
25
@@ -XXX,XX +XXX,XX @@ static void disas_comp_b_imm(DisasContext *s, uint32_t insn)
26
tcg_cmp = read_cpu_reg(s, rt, sf);
27
label_match = gen_new_label();
28
29
+ reset_btype(s);
30
tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
31
tcg_cmp, 0, label_match);
32
33
@@ -XXX,XX +XXX,XX @@ static void disas_test_b_imm(DisasContext *s, uint32_t insn)
34
tcg_cmp = tcg_temp_new_i64();
35
tcg_gen_andi_i64(tcg_cmp, cpu_reg(s, rt), (1ULL << bit_pos));
36
label_match = gen_new_label();
37
+
38
+ reset_btype(s);
39
tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
40
tcg_cmp, 0, label_match);
41
tcg_temp_free_i64(tcg_cmp);
42
@@ -XXX,XX +XXX,XX @@ static void disas_cond_b_imm(DisasContext *s, uint32_t insn)
43
addr = s->pc + sextract32(insn, 5, 19) * 4 - 4;
44
cond = extract32(insn, 0, 4);
45
46
+ reset_btype(s);
47
if (cond < 0x0e) {
48
/* genuinely conditional branches */
49
TCGLabel *label_match = gen_new_label();
50
@@ -XXX,XX +XXX,XX @@ static void handle_sync(DisasContext *s, uint32_t insn,
51
* a self-modified code correctly and also to take
52
* any pending interrupts immediately.
53
*/
54
+ reset_btype(s);
55
gen_goto_tb(s, 0, s->pc);
56
return;
57
default:
58
--
59
2.20.1
60
61
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20190128223118.5255-11-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
target/arm/cpu64.c | 4 ++++
9
1 file changed, 4 insertions(+)
10
11
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/cpu64.c
14
+++ b/target/arm/cpu64.c
15
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
16
t = FIELD_DP64(t, ID_AA64PFR0, ADVSIMD, 1);
17
cpu->isar.id_aa64pfr0 = t;
18
19
+ t = cpu->isar.id_aa64pfr1;
20
+ t = FIELD_DP64(t, ID_AA64PFR1, BT, 1);
21
+ cpu->isar.id_aa64pfr1 = t;
22
+
23
t = cpu->isar.id_aa64mmfr1;
24
t = FIELD_DP64(t, ID_AA64MMFR1, HPDS, 1); /* HPD */
25
t = FIELD_DP64(t, ID_AA64MMFR1, LO, 1);
26
--
27
2.20.1
28
29
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20190201195404.30486-2-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
linux-user/aarch64/target_syscall.h | 7 ++++++
9
linux-user/syscall.c | 36 +++++++++++++++++++++++++++++
10
2 files changed, 43 insertions(+)
11
12
diff --git a/linux-user/aarch64/target_syscall.h b/linux-user/aarch64/target_syscall.h
13
index XXXXXXX..XXXXXXX 100644
14
--- a/linux-user/aarch64/target_syscall.h
15
+++ b/linux-user/aarch64/target_syscall.h
16
@@ -XXX,XX +XXX,XX @@ struct target_pt_regs {
17
#define TARGET_PR_SVE_SET_VL 50
18
#define TARGET_PR_SVE_GET_VL 51
19
20
+#define TARGET_PR_PAC_RESET_KEYS 54
21
+# define TARGET_PR_PAC_APIAKEY (1 << 0)
22
+# define TARGET_PR_PAC_APIBKEY (1 << 1)
23
+# define TARGET_PR_PAC_APDAKEY (1 << 2)
24
+# define TARGET_PR_PAC_APDBKEY (1 << 3)
25
+# define TARGET_PR_PAC_APGAKEY (1 << 4)
26
+
27
void arm_init_pauth_key(ARMPACKey *key);
28
29
#endif /* AARCH64_TARGET_SYSCALL_H */
30
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/linux-user/syscall.c
33
+++ b/linux-user/syscall.c
34
@@ -XXX,XX +XXX,XX @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
35
}
36
}
37
return ret;
38
+ case TARGET_PR_PAC_RESET_KEYS:
39
+ {
40
+ CPUARMState *env = cpu_env;
41
+ ARMCPU *cpu = arm_env_get_cpu(env);
42
+
43
+ if (arg3 || arg4 || arg5) {
44
+ return -TARGET_EINVAL;
45
+ }
46
+ if (cpu_isar_feature(aa64_pauth, cpu)) {
47
+ int all = (TARGET_PR_PAC_APIAKEY | TARGET_PR_PAC_APIBKEY |
48
+ TARGET_PR_PAC_APDAKEY | TARGET_PR_PAC_APDBKEY |
49
+ TARGET_PR_PAC_APGAKEY);
50
+ if (arg2 == 0) {
51
+ arg2 = all;
52
+ } else if (arg2 & ~all) {
53
+ return -TARGET_EINVAL;
54
+ }
55
+ if (arg2 & TARGET_PR_PAC_APIAKEY) {
56
+ arm_init_pauth_key(&env->apia_key);
57
+ }
58
+ if (arg2 & TARGET_PR_PAC_APIBKEY) {
59
+ arm_init_pauth_key(&env->apib_key);
60
+ }
61
+ if (arg2 & TARGET_PR_PAC_APDAKEY) {
62
+ arm_init_pauth_key(&env->apda_key);
63
+ }
64
+ if (arg2 & TARGET_PR_PAC_APDBKEY) {
65
+ arm_init_pauth_key(&env->apdb_key);
66
+ }
67
+ if (arg2 & TARGET_PR_PAC_APGAKEY) {
68
+ arm_init_pauth_key(&env->apga_key);
69
+ }
70
+ return 0;
71
+ }
72
+ }
73
+ return -TARGET_EINVAL;
74
#endif /* AARCH64 */
75
case PR_GET_SECCOMP:
76
case PR_SET_SECCOMP:
77
--
78
2.20.1
79
80
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
This has been enabled in the linux kernel since v3.11
4
(commit d50240a5f6cea, 2013-09-03,
5
"arm64: mm: permit use of tagged pointers at EL0").
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20190204132126.3255-5-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/cpu.c | 6 ++++++
13
1 file changed, 6 insertions(+)
14
15
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/cpu.c
18
+++ b/target/arm/cpu.c
19
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
20
env->vfp.zcr_el[1] = cpu->sve_max_vq - 1;
21
env->vfp.zcr_el[2] = env->vfp.zcr_el[1];
22
env->vfp.zcr_el[3] = env->vfp.zcr_el[1];
23
+ /*
24
+ * Enable TBI0 and TBI1. While the real kernel only enables TBI0,
25
+ * turning on both here will produce smaller code and otherwise
26
+ * make no difference to the user-level emulation.
27
+ */
28
+ env->cp15.tcr_el[1].raw_tcr = (3ULL << 37);
29
#else
30
/* Reset into the highest available EL */
31
if (arm_feature(env, ARM_FEATURE_EL3)) {
32
--
33
2.20.1
34
35
diff view generated by jsdifflib
Deleted patch
1
From: Max Filippov <jcmvbkbc@gmail.com>
2
1
3
With multiprocess extensions gdb uses 'vKill' packet instead of 'k' to
4
kill the inferior. Handle 'vKill' the same way 'k' was handled in the
5
presence of single process.
6
7
Fixes: 7cf48f6752e5 ("gdbstub: add multiprocess support to
8
(f|s)ThreadInfo and ThreadExtraInfo")
9
10
Cc: Luc Michel <luc.michel@greensocs.com>
11
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
12
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
13
Reviewed-by: KONRAD Frederic <frederic.konrad@adacore.com>
14
Tested-by: KONRAD Frederic <frederic.konrad@adacore.com>
15
Message-id: 20190130192403.13754-1-jcmvbkbc@gmail.com
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
gdbstub.c | 4 ++++
19
1 file changed, 4 insertions(+)
20
21
diff --git a/gdbstub.c b/gdbstub.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/gdbstub.c
24
+++ b/gdbstub.c
25
@@ -XXX,XX +XXX,XX @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
26
27
put_packet(s, buf);
28
break;
29
+ } else if (strncmp(p, "Kill;", 5) == 0) {
30
+ /* Kill the target */
31
+ error_report("QEMU: Terminated via GDBstub");
32
+ exit(0);
33
} else {
34
goto unknown_command;
35
}
36
--
37
2.20.1
38
39
diff view generated by jsdifflib
Deleted patch
1
Fix the block comment style in arm_load_kernel() to QEMU's
2
current style preferences. This will allow us to do some
3
refactoring of this function without checkpatch complaining
4
about the code-motion patches.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
9
Message-id: 20190131112240.8395-2-peter.maydell@linaro.org
10
---
11
hw/arm/boot.c | 30 ++++++++++++++++++++----------
12
1 file changed, 20 insertions(+), 10 deletions(-)
13
14
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/boot.c
17
+++ b/hw/arm/boot.c
18
@@ -XXX,XX +XXX,XX @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
19
static const ARMInsnFixup *primary_loader;
20
AddressSpace *as = arm_boot_address_space(cpu, info);
21
22
- /* CPU objects (unlike devices) are not automatically reset on system
23
+ /*
24
+ * CPU objects (unlike devices) are not automatically reset on system
25
* reset, so we must always register a handler to do so. If we're
26
* actually loading a kernel, the handler is also responsible for
27
* arranging that we start it correctly.
28
@@ -XXX,XX +XXX,XX @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
29
qemu_register_reset(do_cpu_reset, ARM_CPU(cs));
30
}
31
32
- /* The board code is not supposed to set secure_board_setup unless
33
+ /*
34
+ * The board code is not supposed to set secure_board_setup unless
35
* running its code in secure mode is actually possible, and KVM
36
* doesn't support secure.
37
*/
38
@@ -XXX,XX +XXX,XX @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
39
if (!info->kernel_filename || info->firmware_loaded) {
40
41
if (have_dtb(info)) {
42
- /* If we have a device tree blob, but no kernel to supply it to (or
43
+ /*
44
+ * If we have a device tree blob, but no kernel to supply it to (or
45
* the kernel is supposed to be loaded by the bootloader), copy the
46
* DTB to the base of RAM for the bootloader to pick up.
47
*/
48
@@ -XXX,XX +XXX,XX @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
49
try_decompressing_kernel = arm_feature(&cpu->env,
50
ARM_FEATURE_AARCH64);
51
52
- /* Expose the kernel, the command line, and the initrd in fw_cfg.
53
+ /*
54
+ * Expose the kernel, the command line, and the initrd in fw_cfg.
55
* We don't process them here at all, it's all left to the
56
* firmware.
57
*/
58
@@ -XXX,XX +XXX,XX @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
59
}
60
}
61
62
- /* We will start from address 0 (typically a boot ROM image) in the
63
+ /*
64
+ * We will start from address 0 (typically a boot ROM image) in the
65
* same way as hardware.
66
*/
67
return;
68
@@ -XXX,XX +XXX,XX @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
69
if (info->nb_cpus == 0)
70
info->nb_cpus = 1;
71
72
- /* We want to put the initrd far enough into RAM that when the
73
+ /*
74
+ * We want to put the initrd far enough into RAM that when the
75
* kernel is uncompressed it will not clobber the initrd. However
76
* on boards without much RAM we must ensure that we still leave
77
* enough room for a decent sized initrd, and on boards with large
78
@@ -XXX,XX +XXX,XX @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
79
kernel_size = arm_load_elf(info, &elf_entry, &elf_low_addr,
80
&elf_high_addr, elf_machine, as);
81
if (kernel_size > 0 && have_dtb(info)) {
82
- /* If there is still some room left at the base of RAM, try and put
83
+ /*
84
+ * If there is still some room left at the base of RAM, try and put
85
* the DTB there like we do for images loaded with -bios or -pflash.
86
*/
87
if (elf_low_addr > info->loader_start
88
|| elf_high_addr < info->loader_start) {
89
- /* Set elf_low_addr as address limit for arm_load_dtb if it may be
90
+ /*
91
+ * Set elf_low_addr as address limit for arm_load_dtb if it may be
92
* pointing into RAM, otherwise pass '0' (no limit)
93
*/
94
if (elf_low_addr < info->loader_start) {
95
@@ -XXX,XX +XXX,XX @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
96
fixupcontext[FIXUP_BOARDID] = info->board_id;
97
fixupcontext[FIXUP_BOARD_SETUP] = info->board_setup_addr;
98
99
- /* for device tree boot, we pass the DTB directly in r2. Otherwise
100
+ /*
101
+ * for device tree boot, we pass the DTB directly in r2. Otherwise
102
* we point to the kernel args.
103
*/
104
if (have_dtb(info)) {
105
@@ -XXX,XX +XXX,XX @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
106
info->write_board_setup(cpu, info);
107
}
108
109
- /* Notify devices which need to fake up firmware initialization
110
+ /*
111
+ * Notify devices which need to fake up firmware initialization
112
* that we're doing a direct kernel boot.
113
*/
114
object_child_foreach_recursive(object_get_root(),
115
--
116
2.20.1
117
118
diff view generated by jsdifflib
Deleted patch
1
The code path for booting firmware doesn't set env->boot_info. At
2
first sight this looks odd, so add a comment saying why we don't.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
7
Message-id: 20190131112240.8395-5-peter.maydell@linaro.org
8
---
9
hw/arm/boot.c | 3 ++-
10
1 file changed, 2 insertions(+), 1 deletion(-)
11
12
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/arm/boot.c
15
+++ b/hw/arm/boot.c
16
@@ -XXX,XX +XXX,XX @@ static void arm_setup_firmware_boot(ARMCPU *cpu, struct arm_boot_info *info)
17
18
/*
19
* We will start from address 0 (typically a boot ROM image) in the
20
- * same way as hardware.
21
+ * same way as hardware. Leave env->boot_info NULL, so that
22
+ * do_cpu_reset() knows it does not need to alter the PC on reset.
23
*/
24
}
25
26
--
27
2.20.1
28
29
diff view generated by jsdifflib